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 versionprints a version. On macOS and Windows, Podman runs containers in a virtual machine; start it once withpodman machine initand thenpodman 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
Get the source
sh git clone https://github.com/Nucc/spoletta.git cd spolettaChoose the models
The worker runs agents with pi, and offers the models your pi config names:
~/.pi/agent/settings.jsonandmodels.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"] } EOFenabledModelslists every model agents may pick, asprovider/model;models.jsonadds providers pi doesn't know, such as a gateway of your own.Write the settings
Settings go in a
.envfile next tocompose.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 .envMySQL takes its passwords the first time it starts, so set them before then. Copy
SECRET_KEYto wherever you keep your backups: the webapp won't start without the key that sealed its secrets. See Sealing secrets.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 incompose.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.
Start it
sh podman compose up --build -dThe first build takes a few minutes.
podman compose psshows the three containers, andpodman compose logs -f webapp workerwhat they are doing.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.
| Setting | What it is for |
|---|---|
GIT_TOKEN, GIT_USERNAME | Cloning 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_URL | Sentry processes, with a token that has event:read. The URL only for a self-hosted Sentry. |
OIDC_ISSUER, GOOGLE_CLIENT_ID and the rest | Signing in. See Sign-in and secrets. |
MYSQL_PUBLISH | Where 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
| To | Run |
|---|---|
| Update to the latest Spoletta | git pull && podman compose up --build -d |
| Pick up a changed pi config | podman compose restart worker |
| Stop it, keeping everything | podman compose down |
| Back up the database | podman compose exec mysql sh -c 'mysqldump -uroot -p"$MYSQL_ROOT_PASSWORD" --single-transaction app' > spoletta.sql |