SpolettaDocs

Installing

With Podman

Run Spoletta on one machine with Podman: MySQL, the webapp and the worker that runs agents and scripts, each in a container built from Spoletta's source. Podman runs them without a daemon, and without root.

What you need

  • Podman 4 or later and podman-compose: podman compose version prints a version. On macOS and Windows, Podman runs containers in a virtual machine; start it once with podman machine init and then podman machine start.
  • git, openssl, and access to the Spoletta repository.
  • An API key for at least one model provider, such as Anthropic or OpenAI.
  • About 4 GB of memory free for the three containers.

Install

  1. Get the source

    sh
    git clone https://github.com/Nucc/spoletta.git
    cd spoletta
  2. Choose the models

    The worker runs agents with pi, and offers the models your pi config names: ~/.pi/agent/settings.json and models.json. If you use pi already, keep yours. Otherwise make both; these offer one OpenAI model:

    sh
    mkdir -p ~/.pi/agent
    [ -f ~/.pi/agent/models.json ] || echo '{}' > ~/.pi/agent/models.json
    [ -f ~/.pi/agent/settings.json ] || cat > ~/.pi/agent/settings.json <<'EOF'
    {
      "defaultProvider": "openai",
      "defaultModel": "gpt-5.5",
      "enabledModels": ["openai/gpt-5.5"]
    }
    EOF

    enabledModels lists every model agents may pick, as provider/model; models.json adds providers pi doesn't know, such as a gateway of your own.

  3. Write the settings

    Settings go in a .env file next to compose.yaml. Make one with passwords for MySQL and the secret key that seals the model keys and tokens kept in the database:

    sh
    cat > .env <<EOF
    MYSQL_ROOT_PASSWORD=$(openssl rand -hex 16)
    MYSQL_PASSWORD=$(openssl rand -hex 16)
    SECRET_KEY=$(openssl rand -base64 32)
    EOF
    chmod 600 .env

    MySQL takes its passwords the first time it starts, so set them before then. Copy SECRET_KEY to wherever you keep your backups: the webapp won't start without the key that sealed its secrets. See Sealing secrets.

  4. Give the worker your model keys

    Export them in the shell you start compose from, which passes them on to the worker:

    sh
    export OPENAI_API_KEY=...

    Not in .env: podman-compose reads that file only to fill in compose.yaml, and the worker takes its model keys from the shell. The same goes for the Sentry and Jira settings scripts read.

    Or skip this, and once Spoletta runs, paste them in Settings, Model keys, where they are kept sealed and survive restarts. See Model keys.

  5. Start it

    sh
    podman compose up --build -d

    The first build takes a few minutes. podman compose ps shows the three containers, and podman compose logs -f webapp worker what they are doing.

  6. Open it

    Go to http://localhost:8080, and build your first flow.

More settings

All go in .env, and take effect with podman compose up -d. The comments in compose.yaml list every one.

SettingWhat it is for
GIT_TOKEN, GIT_USERNAMECloning the repositories of flows that have them over https, such as a GitHub token with contents:read. See Workspaces and git.
SENTRY_AUTH_TOKEN, SENTRY_URLSentry processes, with a token that has event:read. The URL only for a self-hosted Sentry.
OIDC_ISSUER, GOOGLE_CLIENT_ID and the restSigning in. See Sign-in and secrets.
MYSQL_PUBLISHWhere MySQL is published. If another MySQL already listens on 127.0.0.1:3306, set it to [::1]:3306.

Scripts and agents can read GIT_TOKEN and the Sentry and Jira settings too, since they run on the worker with them. With Podman, the worker takes the Sentry and Jira settings from the shell, as it does model keys, and only the webapp, for Sentry processes, from .env.

Day to day

ToRun
Update to the latest Spolettagit pull && podman compose up --build -d
Pick up a changed pi configpodman compose restart worker
Stop it, keeping everythingpodman compose down
Back up the databasepodman compose exec mysql sh -c 'mysqldump -uroot -p"$MYSQL_ROOT_PASSWORD" --single-transaction app' > spoletta.sql
Spoletta · spoletta.comBusiness processes, drawn and run.