Skip to content

Ansible deployment

The Ansible role at deploy/ansible/ is the canonical provisioning tool. It handles everything: system packages, Python environment, config files, systemd services, nginx, rclone mount, backups, and optional features.

Prerequisites

  • Debian 13+ or Ubuntu target host (the role's own support target; the standalone deploy/install.sh path only warns below Debian 12)
  • Nextcloud instance with app password
  • Ansible 2.14+ with community.general and ansible.posix collections

Example playbook

- hosts: your-server
  become: yes
  roles:
    - role: istota
      vars:
        istota_nextcloud_url: "https://nextcloud.example.com"
        istota_nextcloud_app_password: "{{ vault_istota_nc_password }}"
        istota_rclone_password_obscured: "{{ vault_rclone_password }}"
        istota_admin_users:
          - alice
        istota_users:
          alice:
            display_name: "Alice"
            email_addresses: ["alice@example.com"]
            timezone: "America/New_York"

Using the role

Point roles_path at deploy/ansible/:

# ansible.cfg
[defaults]
roles_path = /path/to/istota/deploy/ansible

Or symlink into your roles directory:

ln -s /path/to/istota/deploy/ansible /path/to/roles/istota

Feature flags

Feature Variable Default
Email istota_email_enabled false
Browser container istota_browser_enabled false
Memory search istota_memory_search_enabled true
Sleep cycle istota_sleep_cycle_enabled true
Channel sleep cycle istota_channel_sleep_cycle_enabled true
Whisper transcription istota_whisper_enabled false
Static web root at / (nginx) istota_web_root_enabled true
Node.js istota_nodejs_enabled false
Developer/GitLab istota_developer_enabled false
Database backups istota_backup_enabled true
Bubblewrap sandbox istota_security_sandbox_enabled true
Web interface istota_web_enabled true
GPS location istota_location_enabled false

Variables

All variables with defaults are in deploy/ansible/defaults/main.yml. Key groups:

  • Core: istota_namespace, istota_home, istota_repo_url
  • Nextcloud: istota_nextcloud_url, istota_nextcloud_username, istota_nextcloud_app_password
  • Security: istota_security_sandbox_enabled, istota_use_environment_file
  • Users: istota_users (dict), istota_admin_users (list)
  • Scheduler: istota_scheduler_* (poll intervals, worker limits, timeouts)
  • Web: istota_web_enabled, istota_web_port, istota_web_chat_max_attachment_mb, istota_web_graceful_shutdown_seconds, istota_web_stop_timeout_seconds

Two web variables are worth knowing about before changing them:

istota_web_chat_max_attachment_mb (default 100, against an application default of 25) feeds two consumers — the [web.chat] max_attachment_mb setting in config.toml and nginx's client_max_body_size. Do not split them: if nginx's ceiling is the lower of the two it rejects the upload with its own HTML error page, which the browser client cannot parse into a message.

istota_web_graceful_shutdown_seconds bounds uvicorn's wait for open connections. It matters because the web chat room stream is a session-lived SSE connection whose generator exits only on client disconnect — which a server shutdown does not trigger — so without the flag a restart with any browser tab open sat out the full TimeoutStopSec and was eventually SIGKILLed. Note the unit template is skipped in web-only mode, so a changed value lands on the next full or istota_update_only run.

Inlined dependencies

External role dependencies are inlined as tasks:

  • Docker: apt-get install docker.io docker-compose-plugin (when browser enabled)
  • rclone: install + config (when rclone configured)
  • rclone mount: systemd unit for FUSE mount (when mount enabled)
  • nginx: install + config (when location or web enabled)
  • Node.js: NodeSource 20.x (when Node.js enabled)

Update mode

Skip full installation for config changes or code updates:

ansible-playbook playbook.yml -e "istota_update_only=true"

Post-install

Claude auth is provisioned during install from the istota_claude_code_oauth_token variable (generate the token with claude setup-token; the wizard prompts for it and the role writes the credentials file). No separate login is needed.

Only if you deployed without the token (and aren't using ANTHROPIC_API_KEY), authenticate manually:

sudo -u istota HOME=/srv/app/istota claude login

Adding config fields

When adding new fields to the config system:

  1. Add the field to the dataclass in config.py
  2. Update config/config.example.toml
  3. Update deploy/ansible/defaults/main.yml
  4. Update deploy/ansible/templates/config.toml.j2