Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Configuration reference

This is the single source of truth for everything freshdock reads. Configuration comes from three places:

  • Labels on each container — what to update and when (per-container behaviour).
  • Environment variables — fleet-wide settings, registry credentials, the run flags, and notification secrets. This is the primary way to configure a deployment: nothing to mount.
  • An optional freshdock.toml file — needed only to declare notification targets, and to hold credentials for a registry whose host can’t be spelled as an env-var name. Environment variables override the file, per field.

You usually don’t need a file. Registry credentials, the [settings] defaults, and the run flags all have environment variables — a container deployment never has to mount a freshdock.toml. The one thing env vars can’t do is declare a notification target; that block has to live in the file (its secrets can still come from the environment). See notifications.

Contents


Labels

freshdock is opt-in: a container with no freshdock.enable=true is ignored entirely. All behaviour is driven by these Docker labels (set them in compose under labels: or with docker run --label).

LabelValuesDefaultMeaning
freshdock.enabletrue / falsefalseMaster switch. Without true, the container is invisible to freshdock and every other label is ignored.
freshdock.modelive / nightly / weekly / monthly / watch / offwatch (or [settings] default_mode)How and when this container updates. See scheduling.
freshdock.schedule5-field cronthe mode’s defaultOverride the cron for a calendar mode. Ignored for live / watch / off. See cron syntax.
freshdock.notifytrue / falsefalseEmit notifications for this container’s update events. Requires a configured [notifications.*] target. See notifications.
freshdock.cleanuptrue / false[settings] cleanup (else false)After a healthy update, remove the image the old container ran. Overrides the global [settings] cleanup. See health & cleanup.

Values are case-insensitive and tolerate surrounding whitespace. An invalid value is reported with the offending label named.

When freshdock.enable=true but freshdock.mode is absent, the mode is watch (detect-and-notify, never mutate) — a non-destructive default. Change this fleet-wide fallback with [settings] default_mode (or FRESHDOCK_DEFAULT_MODE); an explicit freshdock.mode label always wins.

Mode vs. schedule. freshdock.schedule only refines the calendar modes (nightly / weekly / monthly). live and watch are polled on the daemon’s run --interval instead and ignore the label. See scheduling.

Health-gate timings. The post-update health timeout and the grace period for containers without a healthcheck are currently hardcoded — not label/config/env-configurable. See health & rollback: timings.

Pinned images. A container whose image is pinned to a digest (repo@sha256:…) has no moving tag to follow. freshdock reports it as pinned (no check) and never updates it.


Environment variables

Environment variables are the primary way to configure freshdock — a container deployment can run entirely from them, no file mounted. They also override the file per field (a lone …_TOKEN replaces the file token while keeping the file username). For registry and notification targets, the <NAME> is the table name, upper-cased, with -_.

VariableSets / overridesNotes
FRESHDOCK_CONFIGconfig file pathThe --config flag wins over it.
FRESHDOCK_REGISTRY_<NAME>_USERNAME[registry.<name>] username<NAME> = alias (DOCKERHUB, GHCR, QUAY, LSCR). Hosts with dots can’t be expressed unambiguously — configure those in the file.
FRESHDOCK_REGISTRY_<NAME>_TOKEN[registry.<name>] tokenA token (with or without a username) is enough to create a registry entry from the environment alone — no file needed.
FRESHDOCK_NOTIFY_<NAME>_BOT_TOKENa Telegram target’s bot_tokenOverrides a secret on a target declared in the file — env can’t create the target itself.
FRESHDOCK_NOTIFY_<NAME>_PASSWORDan SMTP target’s passwordSame: overrides a secret on a file-declared target.
FRESHDOCK_DEFAULT_MODE[settings] default_modeOne of live/nightly/weekly/monthly/watch/off. An invalid value warns and the file value (else watch) applies.
FRESHDOCK_CLEANUP[settings] cleanuptrue/false/1/0, case-insensitive. An invalid value warns and the file value applies.
FRESHDOCK_PRUNE_DANGLING[settings] prune_danglingSame boolean forms as FRESHDOCK_CLEANUP.
FRESHDOCK_INTERVAL, FRESHDOCK_TICK, FRESHDOCK_STOP_TIMEOUTthe run flags of the same nameThe flag wins over the env var. An invalid value is a startup error (it is the flag). See the CLI reference.
NO_COLOR--no-colorAny non-empty value disables colored output.
RUST_LOGlog verbositye.g. info, freshdock=debug, trace. Default info.
DOCKER_HOSTDocker daemon endpointHonoured by the underlying Docker client (bollard).

freshdock --help prints the same override list (after_long_help).


The optional freshdock.toml file

The file is optional — freshdock runs without it. Reach for it only when you need something environment variables can’t express:

  1. Declaring a notification target (a [notifications.<name>] block). Env vars can supply that target’s secret, but the target itself must be declared here.
  2. Registry credentials for a custom host with dots (e.g. registry.example.com), whose name can’t be spelled as an env-var name.

Everything else — the four registry aliases, the [settings] defaults, the run flags — has an environment variable, so most deployments need no file at all.

When present, it is resolved in this order:

  1. --config <path> flag
  2. $FRESHDOCK_CONFIG
  3. ./freshdock.toml in the working directory

An explicit path (flag or env) that doesn’t exist is an error; a missing default ./freshdock.toml is fine (you get an empty config). Secrets in the file are redacted in all log output, even at RUST_LOG=trace, and can be supplied via environment variables instead.

The file has three top-level tables, all optional: [settings], [registry.*], and [notifications.*].

[settings]

Fleet-wide defaults. Every key is optional — and each has an environment variable (shown below) that overrides it.

[settings]
default_mode   = "watch"   # fallback mode for an enabled container with no
                           # freshdock.mode label. Invalid → warn + fall back to watch.
cleanup        = false     # remove the replaced image after a healthy update;
                           # overridable per container with freshdock.cleanup.
prune_dangling = false     # additionally run a daemon-wide dangling-image prune
                           # after each successful update (no per-container override).
KeyEnv varTypeDefaultNotes
default_modeFRESHDOCK_DEFAULT_MODEstring (a mode name)unset → watchApplied to enabled containers without a freshdock.mode label. A freshdock.mode label always overrides it.
cleanupFRESHDOCK_CLEANUPboolfalseDefault for freshdock.cleanup. Best-effort; a shared image in use elsewhere is kept, and a cleanup failure never fails the update.
prune_danglingFRESHDOCK_PRUNE_DANGLINGboolfalseDaemon-wide; prunes untagged images after a success. Best-effort.

[registry.<name>]

One table per registry. <name> may be a friendly alias (dockerhub, ghcr, quay, lscr) or a literal host ("registry.example.com"); both fold onto the same registry as the matching image reference. For the four aliases you can skip the file entirely and set FRESHDOCK_REGISTRY_<NAME>_TOKEN (and optionally _USERNAME) instead.

[registry.ghcr]
username = "octocat"          # any non-empty value works for a GHCR PAT
token    = "ghp_xxx"          # personal access token (read:packages for GHCR)

[registry.dockerhub]
username = "myuser"           # required for Docker Hub
token    = "dckr_pat_xxx"

[registry."registry.example.com"]
token    = "…"                # username optional
KeyTypeRequiredNotes
usernamestringdepends on registryDocker Hub needs the real account name; GHCR and most others accept any non-empty value with a PAT.
tokenstring (secret)yesPassword or personal access token. Redacted in logs.

For per-registry guidance (PAT scopes, the alias list, a smoke test, and what’s out of scope), see registry-auth.md.

[notifications.<name>]

One table per target, selected by type. This is the one thing that requires the file — env vars can supply a target’s secret but can’t declare the target. Every target may set an optional triggers list to subscribe to a subset of events; omit it (or use []) to receive all three (available, succeeded, failed). Payload formats and the event/mode matrix are documented in notifications.md.

[notifications.ops-webhook]
type = "webhook"
url  = "https://example.com/hooks/freshdock"
# triggers omitted → all of available, succeeded, failed

[notifications.discord]
type        = "discord"
webhook_url = "https://discord.com/api/webhooks/123/abc"
triggers    = ["succeeded", "failed"]

[notifications.tg]
type      = "telegram"
bot_token = "123456:ABC-DEF"          # or FRESHDOCK_NOTIFY_TG_BOT_TOKEN
chat_id   = "987654321"
triggers  = ["failed"]

[notifications.email]
type     = "smtp"
host     = "smtp.example.com"
port     = 587                        # default 587
username = "freshdock@example.com"    # username + password together, or neither
password = "s3cr3t"                   # or FRESHDOCK_NOTIFY_EMAIL_PASSWORD
from     = "freshdock@example.com"
to       = ["admin@example.com"]      # non-empty list
starttls = true                       # default true; false → implicit TLS (465)
triggers = ["succeeded", "failed"]

Per-type keys:

typeKeysNotes
webhookurl (secret)Generic JSON POST.
discordwebhook_url (secret)Posts a coloured embed.
telegrambot_token (secret), chat_idPlain-text message via the Bot API.
smtphost, port (=587), username?, password? (secret), from, to (list), starttls (=true)username+password must be set together or both omitted (anonymous relay).

All targets also accept triggers = ["available", "succeeded", "failed"] (subset allowed).


A complete example

File-free (environment only)

A deployment with a private GHCR image, cleanup on, and no notifications needs no file at all — just environment:

FRESHDOCK_DEFAULT_MODE=nightly
FRESHDOCK_CLEANUP=true
FRESHDOCK_REGISTRY_GHCR_USERNAME=octocat
FRESHDOCK_REGISTRY_GHCR_TOKEN=ghp_xxx

(Set these under environment: in compose, Environment= in a systemd unit, or export in a shell.)

With a file (for notifications)

Once you want notifications, declare the target in a freshdock.toml and keep the secret in the environment:

# freshdock.toml
[settings]
default_mode   = "watch"
cleanup        = true
prune_dangling = false

[registry.ghcr]
username = "octocat"
token    = "ghp_xxx"

[notifications.discord]
type        = "discord"
webhook_url = "https://discord.com/api/webhooks/123/abc"
triggers    = ["succeeded", "failed"]

A copy-paste starting point with every section commented out lives at freshdock.toml.example in the repository root. Runnable compose stacks live in examples/compose/.