Bootstrap configuration
Environment variables that control runtime settings — data directory, SSH, listening addresses, and GitHub integration.
deeplo has a two-layer configuration model:
| Layer | Source | Controls |
|---|---|---|
| Bootstrap | Environment variables only | All runtime settings |
| Managed | YAML file (local disk or git repo) | Hosts, repos, projects, triggers |
The two layers are strictly separated. Managed config contains only structural deployment config — no paths, credentials, or runtime settings.
All bootstrap env vars use the DEEPLO_ prefix. Defaults prefer .yml, but explicit .yaml paths still work when you set them directly.
Environment variables
Config source
| Variable | Default | Description |
|---|---|---|
DEEPLO_CONFIG_FILE | /etc/deeplo/config.yml | Path to local config file (local mode) |
DEEPLO_CONFIG_WATCH | false | Watch the mounted config file and reload when it changes (local mode) |
DEEPLO_CONFIG_REPO_URL | — | Git clone URL of config repo; switches to git mode when set |
DEEPLO_CONFIG_REPO_BRANCH | main | Branch to track (git mode) |
DEEPLO_CONFIG_REPO_FILE | config.yml | File path within the repo (git mode) |
DEEPLO_CONFIG_REPO_MODE | poll | How config changes are detected: poll, webhook, or hybrid (git mode) |
DEEPLO_CONFIG_REPO_INTERVAL | 60s | How often to check for config changes in poll or hybrid mode |
Data and SSH
| Variable | Default | Description |
|---|---|---|
DEEPLO_DATA_DIR | — | Data/cache root directory. Required. |
DEEPLO_SSH_KEY_FILE | — | SSH private key for deploy hosts and git repo access. Required. |
DEEPLO_SSH_USER | deploy | Default SSH username on deploy hosts. hosts[].user overrides it per host. |
DEEPLO_SSH_PORT | 22 | Default SSH port on deploy hosts. hosts[].port overrides it per host. |
DEEPLO_SSH_KNOWN_HOSTS | DEEPLO_DATA_DIR/known_hosts | known_hosts file for all SSH connections |
DEEPLO_SSH_HOST_KEY_POLICY | accept-new | accept-new (TOFU — accept and remember new keys) or strict (require pre-existing entry) |
HTTP and admin
| Variable | Default | Description |
|---|---|---|
DEEPLO_WEBHOOK_PORT | 8080 | Webhook listener port. |
DEEPLO_ADMIN_SOCKET | /run/deeplo/deeplo.sock | Unix socket path for the admin API (used by deeplo CLI). |
Concurrency
| Variable | Default | Description |
|---|---|---|
DEEPLO_MAX_WORKERS | 0 (= NumCPU) | Maximum concurrent deploys across all hosts. |
DEEPLO_HOST_PARALLEL | 1 | Maximum concurrent deploys per host. |
Logging
| Variable | Default | Description |
|---|---|---|
DEEPLO_LOG_LEVEL | info | Log level: debug, info, warn, error. |
DEEPLO_LOG_FORMAT | text | Log format: text or json. |
DEEPLO_LOGS_PORT | — | Log server port. Enables log serving when set. |
DEEPLO_LOGS_PUBLIC_URL | — | Externally reachable base URL used for GitHub "Details" links. |
DEEPLO_LOG_RETENTION_DAYS | 14 | Log file retention in days (0 = keep forever). |
GitHub integration
| Variable | Default | Description |
|---|---|---|
DEEPLO_GITHUB_WEBHOOK_SECRET_FILE | — | File containing the GitHub webhook HMAC secret |
DEEPLO_GITHUB_TOKEN_FILE | — | File containing a GitHub PAT; enables deployment reporting when set |
DEEPLO_GITHUB_ENVIRONMENT | — | Optional prefix for the GitHub environment name |
DEEPLO_GITHUB_HOST_IN_ENV | false | Set to true to use <host>/<project> as the environment name (default: <project>) |
Local config mode
If DEEPLO_CONFIG_REPO_URL is unset, deeplo reads the managed YAML config from DEEPLO_CONFIG_FILE (default /etc/deeplo/config.yml).
# docker-compose.yml
services:
deeplo:
image: ghcr.io/jancernik/deeplo:latest
environment:
DEEPLO_DATA_DIR: /var/lib/deeplo
DEEPLO_SSH_KEY_FILE: /run/secrets/deploy_key
DEEPLO_GITHUB_WEBHOOK_SECRET_FILE: /run/secrets/github_webhook_secret
volumes:
- ./config.yml:/etc/deeplo/config.yml:ro
- ./data:/var/lib/deeplo
secrets:
- deploy_key
- github_webhook_secretAdvanced: local config file watching (DEEPLO_CONFIG_WATCH)
DEEPLO_CONFIG_WATCH is an advanced convenience feature for local config mode. It tells deeplo to watch the managed config file on disk and reload it when the file changes instead of requiring a daemon restart after config edits.
Set DEEPLO_CONFIG_WATCH=true to enable it.
When a change is detected and the new config is valid:
- The in-memory config is replaced atomically.
- The poller is restarted with the updated repo list and intervals.
- Invalid configs are rejected and logged; the current config remains active.
environment:
DEEPLO_CONFIG_WATCH: "true"This is useful in development or when the config file is managed by a configuration management tool (Ansible, Puppet, etc.) that writes files directly to the host.
It is not the primary deployment path. If you just want a straightforward setup, mount a local config file and restart the daemon when you change it.
Git config mode
When DEEPLO_CONFIG_REPO_URL is set, deeplo fetches the managed config YAML from a git repository on startup. This is useful when you want the deployment config itself to be version-controlled and managed like any other file in a repo.
# docker-compose.yml
services:
deeplo:
image: ghcr.io/jancernik/deeplo:latest
environment:
DEEPLO_CONFIG_REPO_URL: git@github.com:yourorg/deeplo-config.git
DEEPLO_CONFIG_REPO_BRANCH: main
DEEPLO_CONFIG_REPO_FILE: config.yml
DEEPLO_CONFIG_REPO_MODE: hybrid
DEEPLO_DATA_DIR: /var/lib/deeplo
DEEPLO_SSH_KEY_FILE: /run/secrets/deploy_key
DEEPLO_GITHUB_WEBHOOK_SECRET_FILE: /run/secrets/github_webhook_secret
volumes:
- ./data:/var/lib/deeplo
secrets:
- deploy_key
- github_webhook_secretWhat happens on startup (git mode)
ls-remoteis run againstDEEPLO_CONFIG_REPO_URLto get the branch tip SHA.- The config repo is cloned as a bare mirror into
DEEPLO_DATA_DIR/config/repos/(or fetched if already present). - The config file at
DEEPLO_CONFIG_REPO_FILEis read from that exact commit. - The config is parsed and validated.
- If valid, it is written to the last-known-good cache at
DEEPLO_DATA_DIR/config/current.yml.
Automatic reload (git mode)
After startup, a config watcher detects changes to the config repo and reloads automatically. How it detects changes is controlled by DEEPLO_CONFIG_REPO_MODE:
| Mode | Behaviour |
|---|---|
poll (default) | Checks for new commits every DEEPLO_CONFIG_REPO_INTERVAL (default 60s) |
webhook | Reloads immediately when a push to the config repo arrives at /webhooks/github |
hybrid | Both — webhook for instant reload, poll as a safety net |
When a new commit is detected and the updated config is valid:
- The in-memory config is replaced atomically — all subsequent deploys use the new values.
- The poller is restarted so new repos, intervals, and trigger modes take effect immediately.
- The webhook route (
/webhooks/github) always reads the current config, so newly added webhook-mode repos are handled without a daemon restart.
Changing a repo's trigger_mode or poll_interval reloads the runtime trigger behavior only. It does not by itself redeploy all projects. When a repo is switched from webhook-only to poll or hybrid mode, deeplo seeds the current branch tip as the poll baseline so the reload does not create an artificial first-poll deploy storm.
Invalid configs are rejected and logged; the current config remains active.
Required env vars for git mode
| Var | Reason |
|---|---|
DEEPLO_CONFIG_REPO_URL | Where to fetch the config from |
DEEPLO_DATA_DIR | Where to store the local mirror and cache |
DEEPLO_SSH_KEY_FILE | SSH key for fetching the config repo and deploying to target hosts |
DEEPLO_SSH_KNOWN_HOSTS defaults to DEEPLO_DATA_DIR/known_hosts. With DEEPLO_SSH_HOST_KEY_POLICY=accept-new (default), host keys are accepted automatically on first connection and stored there.
Last-known-good cache (git mode)
When DEEPLO_CONFIG_REPO_URL is set, deeplo maintains a last-known-good cache:
DEEPLO_DATA_DIR/config/
current.yml validated managed config from last successful fetch
meta.json source URL, branch, commit SHA, fetch timestamp
repos/ bare git mirror of the config repo| Situation | Result |
|---|---|
| Fetch succeeds, config valid | Cache updated, new config used |
| Fetch fails, valid cache exists | Warning logged, cached config used |
| Fetch succeeds, config invalid | Cache not updated, current config kept |
| Fetch fails, no cache | Startup fails with a clear error |
| Reload: fetch fails | Warning logged, current in-memory config kept |
| Reload: config invalid | Error logged, current in-memory config kept |
Bad config pushes cannot take down a running daemon — the previous valid config remains active until a valid one is pushed.
Shared SSH key
deeplo uses DEEPLO_SSH_KEY_FILE for both:
- fetching the managed config repo in git mode
- fetching watched repos
- deploying to target hosts over SSH
If you need different credentials, that is outside the current product scope. The bootstrap layer keeps the SSH auth story intentionally simple.