Dockflow

CLI

Every dockflow command, its arguments and its options, as the binary defines them.

This page lists every command of dockflow 1.0.0-alpha.6, with the options its --help prints. Start with the conventions and global options, which apply to every command, then look up a command by name. Every command also accepts -h, --help. Exit codes are on the exit codes page.

Conventions

  • <env> names an environment of dockflow.yml. You can leave it out when the file has a single environment, or shorten it to a unique prefix (prod for production). An ambiguous prefix lists the candidates.
  • <env> in CI. deploy without <env> takes the environment from the tag. 1.2.0 selects the environment whose ci.tag_suffix is empty (production by default); 1.2.0-staging selects the one whose suffix is staging.
  • The project directory is the current directory, or -C <path>.
  • The server of an environment comes from --connection, then the <ENV>_CONNECTION secret, then the environment's server block.
  • What is read. deploy, plan, build, rollback, run, validate, config show and list services read dockflow.yml and the Compose files, so they need every variable these files use. The commands that act on what the server already runs (status, ps, logs, exec, cp, ssh, restart, stop, scale, destroy, cancel, releases, details, diagnose, images, secrets revoke and the server commands) read dockflow.yml alone. On your machine, <ENV>_CONNECTION is enough for them.
  • Prompts. On a terminal, deploy shows its plan and asks for confirmation, and destroy asks before removing anything. With --yes, --json or without a terminal, they never prompt. Declining exits with code 130 (run.declined) and changes nothing.
  • Output. Commands that change a server print events, as JSON Lines with --json. Read commands print a table, or one JSON document with --json. The fields of these documents may change in a minor release, and human output is not stable either. Scripts should rely on the event stream and the exit codes, which are stable for all of 1.x.
  • Masking. Secret values are masked in every output, except the output of exec, run and ssh, which is the command's own.
  • Ctrl+C cancels a command, except while the agent runs on the server. There, the first Ctrl+C asks the agent to stop and roll back; a second one detaches and leaves the run going. dockflow attach follows it again.

Global options

OptionDefaultDescription
--connection stringnoneUse this connection string instead of the environment's secret. @<file> reads it from a file and - from the first line of standard input (not with mcp). Prefer these, or the <ENV>_CONNECTION variable: a string given as is sits on the command line, where other users of the machine can read it, and Dockflow warns about it.
-C, --dir string"."The project directory.
--jsonfalseMachine-readable output.
--no-colorfalseNo colours. The NO_COLOR environment variable has the same effect.
-v, --verbosefalseShow debug events.
-y, --yesfalseNever prompt.
-h, --helpHelp for any command.

init

dockflow init [flags]

Start a project in the current directory (or -C <dir>). It writes:

  • dockflow.yml, with the app's name and a production environment whose DOMAIN is --domain;
  • compose.yml, when the directory has no Compose file: a web service with a route to ${DOMAIN}. The service is built from the Dockerfile, on the port its EXPOSE gives (80 without one), or runs nginx when there is no Dockerfile;
  • .env.dockflow in .gitignore, which is created if needed;
  • with --ci github, .github/workflows/deploy.yml; with --ci gitlab, .gitlab-ci.yml. The workflow builds on every branch, deploys on tags, and backs up production on a schedule (every night on GitHub; on GitLab, when a pipeline schedule runs it). It pins the CLI to the version that wrote it. Workflows for other providers are in Deploying from CI.

On a terminal, it asks for the name, the domain and the CI provider, unless the flags give them. It replaces no file without --force (init.exists, exit code 2). Check the result with dockflow validate.

OptionDefaultDescription
--app stringthe directory's nameThe app's name: lower case letters, digits and hyphens, at most 24 characters.
--domain string<app>.example.comThe domain the app is served at.
--ci stringnoneWrite a CI workflow: github or gitlab.
--forcefalseReplace the files that exist. .gitignore only ever gets the lines it lacks.

validate

dockflow validate [<env>] [flags]

Check everything that can be checked without a server, for one environment: dockflow.yml, the Compose files, the x-dockflow settings and every variable they use. Warnings, such as ignored Compose keys, are printed first. It exits with code 0 when the environment is valid and 3 when it is not.

It does not contact the server, render templates or build images.

No options besides the global ones.

config

config show

dockflow config show [<env>] [flags]

Print the resolved configuration of an environment, with secrets masked: the app, the environment, the version label, releases.keep, on_failure, where each secret comes from, and the services, networks and volumes as Dockflow will deploy them. The output is YAML, or JSON with --json. It does not contact the server.

No options besides the global ones.

list

list envs

dockflow list envs [flags]

The environments of dockflow.yml, with the CI tags that select each one (x.y.z or x.y.z-<suffix>).

No options besides the global ones.

list services

dockflow list services [<env>] [flags]

The services of an environment, as Dockflow will deploy them: image, replicas, rollout strategy and routes. It does not contact the server.

No options besides the global ones.

list images

dockflow list images [<env>] [flags]

The app's images on the server; with -a, every image of the server.

OptionDefaultDescription
-a, --allfalseEvery image of the server.

build

dockflow build [<env>] [flags]

Build the images of the services that have build, without deploying.

  • Without --push, images are built on this machine for --platform, and the result is discarded. It only checks that they build, and runs no hook.
  • With --push, they are built for the server's architecture and pushed where a deploy would push them. The before_build and after_build hooks run around the build.
  • With build.builder: remote, the build runs on the server, and --push is implied.

A failed build exits with code 7.

OptionDefaultDescription
--only stringsallBuild these services only.
--platform stringlinux/<this machine's architecture>The platform to build for, without --push.
--pushfalseAlso push the images to the registry the environment deploys from.
--skip-hooksfalseDo not run the before_build and after_build hooks.

plan

dockflow plan [<env>] [flags]

Print what a deploy would change, without changing any container. The plan is computed on the server, from what really runs there.

To compare images by content, plan builds and pushes the images first, as a deploy would. With --no-build, built services show as changed. A plan with nothing to do exits with code 0.

OptionDefaultDescription
--markdown stringnoneAlso write the plan to this file as Markdown, for a pull request's comment.
--no-buildfalsePlan without building: built services show as changed.
--only stringsallPlan these services only, as deploy --only would deploy them.
--out stringnoneAlso write the plan to this file, for dockflow deploy --plan. Not with --no-build.
--renderfalseAlso print the service specs that would be sent.

deploy

dockflow deploy [<env>] [flags]

Plan, confirm and apply. The steps, in order:

  1. the before_build hooks, the build and push of images, the after_build hooks, the before_deploy hooks, then the plan. On a terminal, the plan is shown for confirmation, and the agent applies exactly that plan;
  2. on the server, the agent applies the uploads, the jobs, the rollouts, the switch of traffic and the checks;
  3. once the release is live, the after_deploy hooks run.

If the run fails, the previous release is restored and the after_failure hooks run. on_failure or --no-rollback can keep the failed release in place instead. See how it works and releases and rollbacks.

--only web,worker moves only those services to the new version. Every other service stays as the current release has it, even when compose.yml changed it: it is neither updated nor removed. The new release still records the whole app, so a later full deploy updates the services --only left out. Jobs come from the deployed version and run as on a full deploy. A named service that depends on a service the server does not run is refused (plan.only_dependency).

--skip-build builds nothing: each built service uses the image dockflow build --push pushed for the same version. A CI pipeline can then build in one job and deploy in another. The build hooks do not run. A version that was never pushed fails with build.not_pushed (exit code 7). Images built on the server (build.builder: remote) without an external registry are named after their content, so --skip-build cannot find them.

--plan plan.json applies a plan written by dockflow plan --out plan.json, exactly as it was reviewed. It builds nothing (the plan pins the built images) and asks for no confirmation. It is refused with plan.stale (exit code 6) if anything changed since, on the server or in the project, secrets included. The file holds no secret value, and is readable by its owner only.

--detach returns as soon as the run has started on the server, and prints its run ID; dockflow attach <env> <run> follows it. after_deploy and after_failure hooks that run on your machine or over SSH need the CLI until the end, so --detach refuses them. Webhooks are sent by the CLI, so they are not sent for a detached run.

Exit codes: 5 when another run holds the lock, 7 when the build fails, 8 when the run failed and was rolled back, 9 when it failed and was left in place, 11 when a fatal before_* hook failed. See exit codes.

OptionDefaultDescription
--branch stringfrom git or the CIThe git branch recorded in the release and given to hooks as DOCKFLOW_GIT_BRANCH.
--detachfalseReturn once the run started on the server; follow it with dockflow attach.
--forcefalseDeploy despite a manual lock.
--no-rollbackfalseLeave a failed deploy in place instead of rolling back. It applies to failed HTTP checks; a failed rollout always rolls back.
--only stringsallDeploy these services only: the others stay as the current release has them.
--plan stringnoneApply this plan, written by dockflow plan --out, or fail if anything changed since.
--skip-buildfalseUse the images dockflow build --push pushed for this version instead of building.
--version stringthe git commitThe version label of the release. In CI, a tag's version is used.
--wait-lock duration0Wait up to this long for another run's lock instead of failing, like --wait-lock 10m. For CI runs that may overlap.

rollback

dockflow rollback [<env>] [flags]

Re-apply a recorded release, by default the previous one. The rollback becomes a new release in the history, applied with the same rollouts and checks as a deploy. Jobs and hooks do not run. It takes the environment's lock.

OptionDefaultDescription
--service stringallRestore this service only, as the release has it; the other services stay as they are. The new release keeps the current version label.
--to stringthe previous releaseThe release to restore: its number (see dockflow releases), or a version label such as 1.4.0, for the newest release of that version that went live.

attach

dockflow attach [<env>] [<run-id>] [flags]

Follow a run in progress, or replay a finished one. Without <run-id>, the environment's last run. It exits with the run's exit code.

No options besides the global ones.

cancel

dockflow cancel [<env>] [flags]

Ask the running agent to stop and roll back, and follow it until it finishes. It fails with code 2 when no run of the environment is in progress.

No options besides the global ones.

status

dockflow status [<env>] [flags]

The current release (number, version, date, author), the services with their running and desired containers, the release each one serves from, its strategy and routes, a degraded flag, the manual lock, and the watchdog's latest restarts. Without <env>, every environment of dockflow.yml.

No options besides the global ones.

releases

dockflow releases [<env>] [flags]

The release history of an environment: number, version, status, date and author, with the current release marked. Rollbacks, restarts, stops and scales appear as releases too.

OptionDefaultDescription
-n, --count int0, all kept releasesShow the n most recent releases.
--statsfalseAdd durations and the success rate.

version

dockflow version [<env>] [flags]

The deployed version of an environment; without <env>, the CLI's own version. An environment that was never deployed exits with code 6.

No options besides the global ones.

ps

dockflow ps [<env>] [flags]

The app's containers: name, service, release, state and health.

OptionDefaultDescription
-a, --allfalseInclude stopped containers and one-off ones.

details

dockflow details [<env>] [flags]

Every service of the current release: strategy, replicas, image, routes, ports, networks, mounts, resources and restart policy, and the names of its environment variables (never their values, with --json too, where each reads KEY=***: they may hold secrets).

No options besides the global ones.

diagnose

dockflow diagnose [<env>] [flags]

Why containers don't run: containers that exited, crash loops, failed health checks with their last output, OOM kills, ports in use, services missing containers, and low disk space. It exits with code 9 when it finds a problem, 0 otherwise.

No options besides the global ones.

logs

dockflow logs [<env>] [<service>] [flags]

The logs of the app's serving containers, or of one service, with secrets masked. Each line is prefixed with its container when several are shown.

OptionDefaultDescription
--allfalseInclude the previous release's and stopped containers.
-f, --followfalseKeep following the logs.
-n, --lines string100, 20 with -fLines per container from the end, or all.
--no-prefixfalseNo container prefix on each line.
--pickfalseChoose one container.
--since stringnoneOnly logs since a timestamp (2026-10-26T14:00:00Z) or a duration (10m).
--timestampsfalseShow timestamps.

exec

dockflow exec [<env>] <service> [-- <command>…] [flags]

Run a command in a running container of a service; without a command, a shell (bash when the image has it, sh otherwise). It uses the first running container unless --pick is given. It exits with the command's own exit code.

OptionDefaultDescription
-e, --env stringArraynoneSet an environment variable, K=V. Repeatable.
-T, --no-ttyfalseNo terminal, for scripts.
--pickfalseChoose the container, when the service has several.
--shfalseOpen sh, not bash.
-u, --user stringthe container's userRun as this user.
-w, --workdir stringthe container's directoryRun in this directory.

run

dockflow run [<env>] <service> [-e K=V]… -- <command>… [flags]

Start a one-off container with the service's spec and the image it currently runs, for a console or a script, and remove it when the command ends. It publishes no ports, has no network aliases, and is never restarted. It exits with the command's own exit code.

OptionDefaultDescription
-e, --env stringArraynoneSet an environment variable, K=V. Repeatable.

cp

dockflow cp [<env>] <src> <dest> [flags]

Copy files or directories between this machine and a container, either way. The container side is written service:/path; the other side is a local path.

dockflow cp production web:/app/storage/logs ./logs
dockflow cp production ./seed.sql postgres:/tmp/

Copying from a container writes inside the local destination only. Symlinks whose target is absolute or leaves the destination are not created, and are reported as warnings (cp.symlink_outside). A file never writes through a symlink in its place: it replaces it.

OptionDefaultDescription
--pickfalseChoose the container, when the service has several.

ssh

dockflow ssh [<env>] [-- <command>…] [flags]

Open a shell on the server, or run a command there, with the environment's connection. It exits with the command's own exit code.

No options besides the global ones.

restart

dockflow restart [<env>] [<service>…] [flags]

Restart services with their rollout strategy, so routed services restart without downtime. Without a service, it restarts every service except jobs.

It restarts the current release as recorded, and does not read your Compose files. It takes the environment's lock. The first argument is taken as the environment only when it is an environment's exact name.

No options besides the global ones.

stop

dockflow stop [<env>] [<service>…] [flags]

Stop services until the next deploy or restart. Without a service, it stops every service except jobs. It takes the environment's lock. The first argument is taken as the environment only when it is an environment's exact name.

No options besides the global ones.

scale

dockflow scale [<env>] <service> <replicas> [flags]

Change a service's number of containers until the next deploy, which restores the count of the Compose file. <replicas> is at least 1; to stop a service, use dockflow stop. A stateful service, or one with container_name, cannot run more than once. It takes the environment's lock.

No options besides the global ones.

destroy

dockflow destroy [<env>] [flags]

Remove an environment from the server: its containers, routes, networks and state. Volumes are kept unless --volumes is given. It asks for confirmation on a terminal.

With --only, it removes these services only. A remaining service that depends on one of them is an error.

OptionDefaultDescription
--only stringsnoneDestroy these services only.
--volumesfalseAlso delete the environment's volumes and their data. Only with the whole environment. On a terminal, you type the environment's name to confirm; without a terminal, it needs --yes.

dockflow destroy --volumes deletes the data of every volume of the environment. There is no undo.

prune

dockflow prune [<env>] [flags]

Remove what the server no longer needs. Without a kind option, it removes stopped containers, untagged images and networks that Dockflow does not manage, and runs the registry's garbage collection.

Images of the releases in retention and app volumes are always kept; --volumes removes unused anonymous volumes only. See the cleanup guide.

OptionDefaultDescription
-a, --allfalseEvery unused image, not only untagged ones.
--containersfalseStopped containers.
--imagesfalseUntagged images.
--networksfalseUnused networks.
--registryfalseThe layers of the server's registry that no kept release uses; run it outside deploys.
--volumesfalseUnused anonymous volumes.

backup

backup run

dockflow backup run [<env>] [<service>] [--server] [--wait-lock <duration>]

Back up the services of the current release that declare x-dockflow.backup, or the one named, to the environment's restic repository. It then applies each service's retention and checks a sample of the repository.

It takes the environment's lock; --wait-lock 10m waits for a deploy to finish. When a service's backup fails, the other services are still backed up, and the command exits with code 12.

--server backs up the server's state instead: /var/lib/dockflow without the backups' passwords, with no lock. See backups and the server's state.

OptionDefaultDescription
--serverfalseBack up the server's state, /var/lib/dockflow, to the environment's repository.
--wait-lock duration0Wait up to this long for a deploy or another run to release the lock, like --wait-lock 10m.

backup list

dockflow backup list [<env>] [<service>] [--server]

The environment's snapshots, or one service's, oldest first: id, time, service, release and size. --server lists the snapshots of the server's state. --json prints them as one document.

OptionDefaultDescription
--serverfalseList the snapshots of the server's state.

backup restore

dockflow backup restore [<env>] <service> [--snapshot <id|latest|date>] [--from <env>] [--wait-lock <duration>]

Restore a snapshot of the service into the current release, under the environment's lock. A dump is restored with pg_restore --single-transaction --exit-on-error (or the restore command); volumes are restored with the service stopped. It asks for confirmation on a terminal, and needs --yes without one. A failed restore exits with code 12. See restoring.

OptionDefaultDescription
--snapshot stringlatestA snapshot id or its beginning, latest, or a date (2026-10-27) or time (RFC 3339) for the newest snapshot taken by then.
--from stringthis environmentRestore a snapshot of another environment, read from its repository.
--wait-lock duration0Wait up to this long for the environment's lock.

backup prune

dockflow backup prune [<env>] [<service>] [--server] [--keep-last n] [--keep-hourly n] [--keep-daily n] [--keep-weekly n] [--keep-monthly n]

Apply the retention of the services, or of the one given, and reclaim the space of the forgotten snapshots. --server applies it to the snapshots of the server's state.

With any --keep-* option, the options given replace the whole retention for this run: a rule not given keeps nothing.

OptionDefaultDescription
--keep-last intthe service's retentionKeep the n most recent snapshots.
--keep-hourly intthe service's retentionKeep the most recent snapshot of the n last hours that have one.
--keep-daily intthe service's retentionKeep the most recent snapshot of the n last days that have one.
--keep-weekly intthe service's retentionKeep the most recent snapshot of the n last weeks that have one.
--keep-monthly intthe service's retentionKeep the most recent snapshot of the n last months that have one.
--serverfalsePrune the snapshots of the server's state.

lock

dockflow lock status|acquire|release [<env>] [flags]

Hold an environment's lock by hand, for a maintenance window.

  • acquire sets a manual lock, which never expires. Until release, every command that takes the lock (deploy, rollback, restart, stop, scale, destroy) is refused with exit code 5, except deploy --force. acquire fails with code 5 when a manual lock is already set, unless --force is given.
  • release removes the manual lock. Releasing a lock someone else set needs --force.
  • status shows the manual lock: who set it, when and why.
OptionDefaultDescription
--forcefalseTake over (acquire) or release (release) someone else's manual lock.
-m, --message stringnoneWhy the environment is locked.

maintenance

dockflow maintenance on|off [<env>] [flags]

Answer every route of an environment with a maintenance page, without stopping anything.

  • on makes the switch answer the environment's domains with 503 Service Unavailable and a maintenance page. The services keep running, and a deploy, rollback or restart keeps the page up. Running on again replaces the page and the allowed addresses.
  • off sends the traffic back to the services at once, without a deploy.
  • dockflow status shows the maintenance mode, since when and who turned it on.

It changes the switch's configuration, which is reloaded, and takes the server's lock rather than the environment's, so it works while a deploy hangs. The other apps of the server are not affected. An environment without routes cannot be put under maintenance.

OptionDefaultDescription
--page fileDockflow's pageAn HTML file to show instead, up to 256 KiB. Its assets must be inline or hosted elsewhere: every request of the environment's domains gets the page.
--allow addressnoneAn address or CIDR range that still reaches the app, like 203.0.113.7 or 10.0.0.0/8. Repeatable. Behind Cloudflare or an external proxy, it is the client's address the edge vouches for.

mcp

dockflow mcp [--allow-apply]

An MCP server over stdio, for AI assistants: the tools validate, status, releases, logs and plan, each running the command of the same name with --json. See AI agents.

OptionDefaultDescription
--allow-applyfalseAlso offer deploy, which applies a plan the plan tool computed, by its fingerprint, and rollback, which takes a release number.

plugins

plugins list

dockflow plugins list [--json]

The built-in plugins, and the plugins of the project that dockflow.yml uses, each with its source, description and inputs: type, whether it is required, its default. It needs no server. See plugins.

secrets

secrets list

dockflow secrets list [<env>]

Every secret key the environment sees, with its source: CI (the process environment and DOCKFLOW_SECRETS), .env.dockflow, or the SOPS file. Never the values. It needs no server, and lists the keys even when a Compose file uses one that is missing.

secrets set

echo -n "$VALUE" | dockflow secrets set [<env>] <KEY> [--age <recipient>…]

Sets KEY in the environment's SOPS file (secrets_file, default secrets/<env>.sops.yaml), and encrypts the file again for the same recipients. The value is read from stdin; on a terminal, it is asked without echo. A file that does not exist yet is created for the --age recipients, or those .sops.yaml's creation_rules give its path. Commit the file: it is encrypted.

OptionDefaultDescription
--age strings.sops.yaml's creation_rulesFor a new file: the age recipients to encrypt for. Ignored when the file exists.

secrets edit

dockflow secrets edit [<env>] [--age <recipient>…]

Opens the environment's secrets, decrypted, as KEY: value lines in $VISUAL or $EDITOR (default vi), from a temporary file readable by you only and deleted afterwards, then encrypts the result. Comments of the file are not kept.

OptionDefaultDescription
--age strings.sops.yaml's creation_rulesFor a new file: the age recipients to encrypt for. Ignored when the file exists.

secrets revoke

dockflow secrets revoke [<env>] <name>

Deletes from the server every file of the Compose secret <name> that the current release does not use: the old values of a leaked secret leave the server at once. Releases that used them can no longer be rolled back to: their rollback fails with secret.missing.

server

server init

dockflow server init <admin>@<host>[:port] [flags]
sudo dockflow server init [flags]          # on the server, outside a project
dockflow server init [<env>] [flags]

Prepare a server, or update one. The command has three forms, described below.

With <admin>@<host>, it prepares a server from an administrator's account (root, or a user with passwordless sudo), then prints the connection string for your CI. The steps:

  1. installs Docker from Docker's repository when it is missing (Debian and Ubuntu; elsewhere, install Docker Engine 27 or later first, or pass --skip-docker-install to be told so);
  2. creates the deploy user (dockflow), adds it to the docker group, and installs a key generated on this machine, with restrict,port-forwarding,pty, and from= with --from;
  3. with --harden-ssh, hardens SSH: a drop-in, read before the providers' ones, that refuses passwords and lets root in by key only. Passwords stay allowed while the administrator's account has no key, and nothing is written when that account is root without a key, so you are never locked out. It then checks the values sshd uses, and warns about each one that did not take effect. Without it, SSH is left alone, as is the rest of the server's administration (fail2ban, automatic updates, time synchronisation): see Security model;
  4. with --nginx, installs nginx, which refuses the host names no vhost serves, with the sudo rules of the nginx plugin;
  5. installs the boot units of the port filter and of Cloudflare's ranges;
  6. reconnects as the deploy user and installs the switch, the server-local registry and the watchdog.

On a terminal, without --edge or --nginx, it asks how traffic reaches the server's apps. Enter keeps the server's choice, or builtin for a new server. With --yes or --json, it never asks.

The server's host key must be known: in your ~/.ssh/known_hosts, or given with --host-key. Every step can be run again; a new run adds a new key. <host> may be a Host alias of your ~/.ssh/config. Its HostName, Port, User and IdentityFile apply where the target sets none, and the connection string gets the real address.

Without an argument, in a directory without dockflow.yml, it prepares the server it runs on, which must be Linux, as root. The steps are the same, with the key generated in memory and never written to disk. The connection string gives:

  • the server's public address: the source address of its route to the internet. A private address is refused; give --host instead;
  • the SSH port of sshd_config, following its Include lines (22 when it sets none);
  • the fingerprint of /etc/ssh/ssh_host_ed25519_key.pub (ecdsa, then rsa, when there is no ed25519 key).

The deploy user is then checked through the SSH server on 127.0.0.1, as the CI will reach it.

With an environment, it installs or updates the switch and the registry on the server of that environment, reached as for a deploy.

Running it again updates the server, and the switch keeps every app's routes. An option you don't give keeps what the server has. For example, sudo dockflow server init alone, after a new Dockflow is installed, upgrades the watchdog and keeps the edge, its address, the registry and the filter as they were. Give an option to change it. --no-registry=false, --no-port-filter=false and --no-watchdog=false install again what an earlier run left out. See the switch and edges.

EdgeEffect
builtinThe switch listens on ports 80 and 443 and obtains certificates.
cloudflareAs builtin, with ports 80 and 443 open to Cloudflare's ranges only, and the client's address from CF-Connecting-IP. See the cloudflare edge.
externalThe switch listens on --switch-listen (127.0.0.1:8080) in plain HTTP, behind your own proxy, which terminates TLS. See behind nginx.
noneNo switch. Apps publish their own ports; routes are refused.
OptionDefaultDescription
--edge stringthe server's, or builtinHow traffic reaches the switch: builtin, cloudflare, external or none.
--acme-email stringthe server's, or noneThe address Let's Encrypt writes to about the switch's certificates (expiry, revocation). --acme-email "" removes it.
--acme-ca stringthe server's, or Let's Encrypt then ZeroSSLThe ACME directory the switch gets its certificates from, such as Let's Encrypt's staging, https://acme-staging-v02.api.letsencrypt.org/directory, for a test server. --acme-ca "" goes back to the default.
--no-registryfalseNo server-local registry: every built image goes to registry.url.
--registry-image stringthe registry:3.x.y this version pins, by digestThe image of the server-local registry.
--switch-image stringthe caddy:2.x.y this version pins, by digestThe Caddy image of the switch.
--no-watchdogfalseNo watchdog: unhealthy containers are not restarted, and apps with Compose secrets wait for a deploy after a reboot.
--no-port-filterfalseNo port filter: every port Docker publishes on a public address is open.
--switch-listen string127.0.0.1:8080With --edge external: the address the switch listens on.
--trusted-proxy stringsprivate rangesWith --edge external: CIDRs whose X-Forwarded-For is trusted.
-k, --key stringssh-agent, ~/.sshWith <admin>@<host>: the administrator's private key.
--password-file stringnoneWith <admin>@<host>: a file holding the administrator's password.
--host-key stringknown_hostsWith <admin>@<host>: the server's host key fingerprint (SHA256:…).
--user stringdockflowWhen preparing a server: the deploy user to create.
--deploy-key stringa new keyWhen preparing a server: a private key to use for the deploy user instead of generating one.
--name stringmainWhen preparing a server: its name in the connection string.
--skip-docker-installfalseWhen preparing a server: refuse one without Docker instead of installing it.
--harden-sshfalseWhen preparing a server: write an SSH drop-in that refuses passwords and lets root in by key only, once the administrator has a key.
--nginxfalseWhen preparing a server: install nginx in front of the switch (--edge external unless given), refusing unknown host names, with the sudo rules of the nginx plugin.
--from stringsnoneWhen preparing a server: the addresses or CIDRs the deploy key is accepted from (from= of authorized_keys). Keep it off with hosted CI runners, whose addresses change.
--host stringits public addressOn the server itself: the address or domain name the CI reaches it at.
--port intPort of sshd_config, or 22On the server itself: the SSH port the CI uses.
dockflow server init [email protected] --edge external

server status

dockflow server status [<env>]

The server as a whole:

  • its settings: edge, port filter, the Dockflow version that last ran server init;
  • the Docker version;
  • the switch, the registry and the watchdog, with their state and image;
  • every app environment on the server, with its current release and how many of its containers run;
  • the free disk space.

--json prints it as one document. Without <env>, it shows the server of the only environment of dockflow.yml, or of --connection.

server check

dockflow server check [<env>]

Checks what Dockflow needs on the server, each check ok, a warning or a failure, with what to do:

  • Docker 27 or newer;
  • /run/dockflow on a tmpfs, for Compose secrets;
  • /var/lib/dockflow readable by root only;
  • the free disk space;
  • whether server init ran, and the switch, the registry and the watchdog are running;
  • the port filter, applied or off;
  • ports 80 and 443, when the edge needs them and the switch is not running: free, or held by another program.

It exits with code 0 when no check failed, and 9 (check.failed) when one did. Warnings do not change the exit code.

server edge

dockflow server edge [<env>] builtin|cloudflare|external|none [--switch-listen <addr:port>] [--trusted-proxy <cidr>…]

Changes how traffic reaches the server's switch, and keeps every other setting. It is the same as server init <env> --edge <mode>. The switch container is replaced, which interrupts traffic for a moment, and every app's routes are loaded into the new one. none is refused while routes go through the switch. See the switch and edges.

OptionDefaultDescription
--switch-listen stringthe server's, or 127.0.0.1:8080With external: the address the switch listens on.
--trusted-proxy stringsthe server'sWith external: CIDRs whose X-Forwarded-For is trusted.

server upgrade

dockflow server upgrade [<env>]

Moves the switch and the registry to the images this version of Dockflow pins, and replaces their containers when the image changed. Each release of Dockflow pins one release of Caddy and of the registry, by digest, so every server upgraded with the same version runs the same images; dockflow server upgrade --help names them. An image you chose with --switch-image or --registry-image, from another repository, is pulled again by its tag instead. The watchdog runs this CLI's agent. Every setting stays.

When the server cannot pull an image, it keeps the one it has and warns (upgrade.pull). Run it after installing a new Dockflow: Caddy's fixes come with Dockflow's releases.

server uninstall

dockflow server uninstall [<env>] [--volumes]

Removes Dockflow from the server:

  • every app environment: their containers, networks, Compose secrets and releases, and with --volumes, their volumes and data;
  • the switch with its certificates, the registry with its images, and the watchdog;
  • the shared networks, the port filter's rules, the finished agents and /var/lib/dockflow.

The backups stay, with their passwords in /var/lib/dockflow/backups/, unless --volumes is given. The deploy user, Docker, the containers Dockflow did not create and Docker's volume plugins always stay.

On a terminal, it asks you to type the server's name. Without a terminal, it needs --yes. Running server init afterwards installs Dockflow again, on an empty server.

OptionDefaultDescription
--volumesfalseAlso delete the volumes of the app environments, with their data, and the backups on the server.

server cloud-init

dockflow server cloud-init --host <address> [flags] > user-data.yml

Prints the cloud-init user-data of a new server, to give your provider (DigitalOcean, Hetzner, Scaleway, AWS) when you create it. On its first boot, the server does what server init does before reconnecting: Docker, the deploy user and its key, --harden-ssh, --nginx. The command then prints the connection string on the standard error.

  • The deploy key is generated here; only its public part is in the user-data.
  • The server's SSH host key is generated here too, and is in the user-data: the connection string pins it before the server exists. Keep the user-data as you would the server's disk, or write it with -o user-data.yml (mode 600).
  • --host is required: the address the CI will reach the server at, a reserved IP or a domain name.

The first boot takes a few minutes, mostly to install Docker. cloud-init status --wait on the server returns when it is done; before that, the deploy user does not exist yet. Once it has finished, install the switch, the registry and the watchdog with dockflow server init <env>.

OptionDefaultDescription
--host stringrequiredThe address or domain name the CI reaches the server at.
--port int22The SSH port the CI uses.
--user stringdockflowThe deploy user to create.
--deploy-key stringa new keyA private key to use for the deploy user instead of generating one.
--name stringmainThe server's name in the connection string.
--from stringsnoneThe source addresses or CIDRs the deploy key accepts.
--nginxfalseInstall nginx, with the sudo rules of the nginx plugin.
--harden-sshfalseWrite an SSH drop-in that refuses passwords and lets root in by key only, once root has a key.
--no-port-filterfalseDo not install the published-port filter's boot unit.
--skip-docker-installfalseFor an image that has Docker: refuse to install it.
-o, --output stringthe standard outputWrite the user-data to this file, mode 600.

server network

dockflow server network create|list|remove [<env>] [<name>]

Manage networks shared between the apps of a server, which their Compose files join as external networks. create makes a bridge network owned by the server. remove refuses while containers use it. list shows each one with its containers. See several apps on one server.

server plugin

dockflow server plugin install [<env>] <plugin> [--alias <name>] [<key>=<value>…]
dockflow server plugin list|remove [<env>] [<plugin>]

Manage Docker volume plugins, which Compose volumes use with driver. install pulls the plugin, grants the privileges it asks for and prints them, applies its settings and enables it; --alias is its name on the server. remove refuses while volumes use it. Setting values are masked, and list shows only their names. See several apps on one server.

OptionDefaultDescription
--alias stringthe pluginWith install: the plugin's name on the server, which Compose volumes give as their driver.

server connection

dockflow server connection [<user@host[:port]>] [flags]

Connects to the server, verifying its host key against --host-key or known_hosts, and checks that the user can use Docker. It then prints the connection string: the server, its host key and the private key. Store it in the <ENV>_CONNECTION secret of your CI.

The target's user defaults to dockflow and its port to 22. Without a target, it uses the server of --env, as a deploy would.

dockflow server connection [email protected] -k ~/.ssh/dockflow_ed25519
OptionDefaultDescription
--env stringnoneWithout a target: the environment whose server to use.
--host-key stringnoneThe server's host key fingerprint (SHA256:…), when known_hosts does not have it.
-k, --key stringDOCKFLOW_SSH_KEYThe private key file the connection string holds.
--name stringmainThe server's name.

The connection string holds the private key. Store it as a CI secret, never in the repository.

completion

dockflow completion [command]

Generate the autocompletion script of dockflow for a shell: bash, fish, powershell or zsh. Each subcommand prints how to load the script in its --help.

completion bash

dockflow completion bash

Requires the bash-completion package. Load it in the current shell with source <(dockflow completion bash).

OptionDefaultDescription
--no-descriptionsfalseDisable completion descriptions.

completion fish

dockflow completion fish [flags]

Load it in the current shell with dockflow completion fish | source.

OptionDefaultDescription
--no-descriptionsfalseDisable completion descriptions.

completion powershell

dockflow completion powershell [flags]

Load it in the current shell with dockflow completion powershell | Out-String | Invoke-Expression.

OptionDefaultDescription
--no-descriptionsfalseDisable completion descriptions.

completion zsh

dockflow completion zsh [flags]

Load it in the current shell with source <(dockflow completion zsh). Completion must be enabled in zsh (autoload -U compinit; compinit).

OptionDefaultDescription
--no-descriptionsfalseDisable completion descriptions.

help

dockflow help [command] [flags]

Help about any command, the same as dockflow <command> --help.

Not available yet

This version has no ui command. A local web UI may come after 1.0.0. See the roadmap.

Edit on GitHub

On this page