Configuration Reference
The slipp.yaml file configures a project for slipp operations.
File Location
Section titled “File Location”Directoryyour-project/
- slipp.yaml
Directoryinventory/
- …
- playbook.yml
Created automatically by slipp launch or slipp deploy --name.
Full Example
Section titled “Full Example”# Project identityname: myapp
# Ansible pathsinventory: inventory/hostsplaybook: playbook.ymlroles_path: - rolesgalaxy_path: roles/galaxy
# Secretsvault: inventory/host_vars/myserver/vault.yml
# Runtime (auto-detected if omitted)runtime: docker
# Routing: service -> domain/path (seeded by slipp launch, hand-editable)expose: frontend: domain: app.example.com backend: domain: app.example.com path: /api
# Managed roles (for filtering in slipp ps)managed_roles: - myapp - myapp-worker
# Tag presets for deploymentstag_presets: install: "--tags install-all" setup: "--tags setup-all --skip-tags start" restart: "--tags restart" update: "--tags update-app"
# Run profiles for local developmentruns: dev: cmd: npm run dev tunnels: out: [5173:app.example.com@myserver] vaults: [myapp] dev-staging: extends: dev env: - VITE_ENV=stagingFields
Section titled “Fields”Required. Project identifier used in:
- Global registry
- Service filtering with
slipp ps -p - Cross-project vault access
name: myappinventory
Section titled “inventory”Path to Ansible inventory file, relative to project root.
inventory: inventory/hostsDefault: inventory.yml (or inventory-{env}.yml for non-production environments).
Optional — projects that only use run profiles (no deploy target) don’t need an inventory.
playbook
Section titled “playbook”Path to main Ansible playbook.
playbook: playbook.ymlDefault: playbook.yml
roles_path
Section titled “roles_path”List of directories to search for Ansible roles. Passed to Ansible via ANSIBLE_ROLES_PATH.
roles_path: - roles - ../shared-rolesDefault: [] (Ansible default)
galaxy_path
Section titled “galaxy_path”Install directory for external roles from requirements.yml. Automatically added to roles_path at runtime.
galaxy_path: roles/galaxyDefault: roles/galaxy (used automatically if not set — no need to configure this
unless you want a different path).
slipp launch generates a requirements.yml listing the Ansible collections your
project needs (e.g. community.docker or containers.podman, depending on your
container runtime). When requirements.yml exists, slipp deploy installs both
roles and collections from it automatically before running the playbook.
Path to Ansible vault file for secrets.
vault: inventory/host_vars/myserver/vault.ymlUsed by:
slipp secretscommandsslipp run --vaultfor environment injection
runtime
Section titled “runtime”How the app runs on the server: systemd, docker, or podman.
runtime: dockerdocker and podman generate container-based deployments (Dockerfile, compose,
container-specific Ansible collections). systemd generates a native app deployment
(direct process management, no containers).
Auto-detected from playbook if omitted (container runtimes only — systemd must be
set explicitly).
runtime: systemd works for both Node and Python projects. For a Python
project it renders a distinct systemd role (a uv-managed venv, uv sync --frozen) rather than the Node role. Two slipp launch flags only apply
to Python systemd deploys:
slipp launch --name myapp --python-extra prod --exec-args "--workers 4"| Flag | Purpose |
|---|---|
--python-extra | Optional dependency group passed as uv sync --extra <group> |
--exec-args | Extra arguments appended to the systemd unit’s ExecStart |
expose
Section titled “expose”Routes services to public domains/paths. Each key is a detected service name; the value is where it’s served.
expose: frontend: domain: app.example.com # path defaults to "/" backend: domain: app.example.com path: /api worker: domain: worker.app.example.com host: secondary-host # deploy target other than the primary host port: 8081 # override only to resolve a same-host port collision internal: true # force wg-manage --internal-tls, no public domain/DNS needed| Field | Description |
|---|---|
domain | Required. FQDN serving this service |
path | Path prefix on the domain. Default: / |
host | Inventory host name to deploy this service to. Default: the project’s primary host |
port | Override the service’s container/host port — only needed to resolve a same-host port collision between two services |
internal | Force wg-manage --internal-tls for this service regardless of the project’s --public launch flag (--proxy wg-manage only) |
Seeding. slipp launch seeds this block automatically if it doesn’t
exist yet, following one convention: a single service gets the bare
domain at /; a frontend+backend pair puts the frontend at / and the
backend at /api on the same domain; every other service gets its own
{name}.{domain} subdomain.
Editing. A hand-edited block always wins — slipp launch never
overwrites an existing expose: block, only fills one in when there
isn’t one yet. To change routing, edit the entries directly and redeploy.
To remove a service from public exposure, delete its entry — that’s the
supported opt-out, not an oversight.
Domain changes. If the project’s app_domain changes but the
expose: block still points at the old domain, slipp launch only
warns (expose: block doesn't reference <domain>) — it never rewrites
your routing for you. Delete the block to have it re-seed against the
new domain.
managed_roles
Section titled “managed_roles”List of Ansible role names this project manages. Used to filter slipp ps output.
managed_roles: - myapp - myapp-worker - myapp-schedulerServices from these roles appear in slipp ps without --all.
tag_presets
Section titled “tag_presets”Named shortcuts for Ansible tag combinations.
tag_presets: install: "--tags install-all" setup: "--tags setup-all --skip-tags start" restart: "--tags restart"Use with:
slipp deploy installslipp deploy setupRun profiles for local development. Each key is a profile name. See
Local Development for concepts and
slipp run for CLI usage.
runs: dev: cmd: npm run dev vaults: [myapp] env: - NODE_ENV=development tunnels: out: [5173:app.example.com@myserver] in: [postgres:5432@myserver] auth: "user:<bcrypt-hash>" proxy: - from: app.example.com/api to: localhost:8080/api host: myserver dev-staging: extends: dev env: - VITE_ENV=stagingA profile can inherit from another with extends — the child’s fields replace
the parent’s (no merging). Personal overrides go in the untracked
.slipp/runs.local.yaml (same name shadows the tracked profile entirely).
Inventory Format
Section titled “Inventory Format”The inventory file uses standard Ansible YAML format:
all: hosts: myserver: ansible_host: 192.168.1.100 ansible_user: slipp ansible_port: 22Multiple hosts
Section titled “Multiple hosts”An inventory can have more than one host for the same project and
environment — e.g. a frontend on one VPS and a worker service on
another. Exactly one host is the primary (is_primary: true,
auto-managed — slipp launch fails loud if the inventory ever ends up
with zero or more than one). It owns the project’s public identity
(app_domain, DNS, primary Caddy/wg-manage routing); every other host is
secondary.
The interactive slipp launch prompt only ever creates the primary
host. Add secondary hosts with the CLI, not by hand-editing the
inventory file:
slipp hosts add worker --host 203.0.113.9 --runtime dockerslipp hosts listslipp hosts remove workerAssigning a service to a secondary host is a separate step: set
expose: <service>: host: <name> in slipp.yaml, then run slipp launch --reconfigure to regenerate the deployment. See
expose: and slipp hosts.
IP-reuse rules. Adding a host whose IP is already used by another
host within this same project’s inventory is a hard error — no
legitimate reason for one project to deploy two names to the same box.
An IP already used by a different registered project is allowed
(that’s real, deliberate host sharing, e.g. two projects on one VPS) —
slipp hosts add/slipp projects add print an informational notice
naming the other project(s), but never block it. On a shared host,
unqualified slipp logs/exec/ssh/status <service> commands become
ambiguous and must be qualified as project:service — see
Service lookup grammar.
Host variables
Section titled “Host variables”Per-host configuration in host_vars/:
Directoryinventory/
- hosts
Directoryhost_vars/
Directorymyserver/
- vars.yml
- vault.yml
domain: app.example.comapp_port: 3000database_host: localhostdatabase_password: "{{ vault_database_password }}"Global Registry
Section titled “Global Registry”Projects are tracked globally at ~/.config/slipp/projects.json:
{ "projects": [ { "name": "myapp", "project_path": "/home/user/projects/myapp", "registered_at": "2024-01-15T10:30:00Z" } ]}View with:
slipp projects listEnvironment-Specific Config
Section titled “Environment-Specific Config”For multiple environments, use separate inventory files:
Directoryinventory/
- production
- staging
- development
Deploy to specific environment:
slipp deploy stagingOr configure in slipp.yaml per environment (not yet supported - use CLI flags).
Migration from Older Formats
Section titled “Migration from Older Formats”If upgrading from an older slipp version:
- Rename
ansictl.yamltoslipp.yaml - The format is identical - no content changes needed