There is no registry for this: the image is built from the Dockerfile in the checkout. `docker compose up -d` reuses whatever image already exists, so after a git pull it starts the old code and reports success - an update that silently did not happen, on the program whose job is to notice things. `--build` on both commands that need an image. `exec` does not.
108 lines
4.7 KiB
YAML
108 lines
4.7 KiB
YAML
# The guard, as one service.
|
|
#
|
|
# AN EXAMPLE, not a compose file. Copy it to docker-compose.yml, edit it there,
|
|
# and start that - the copy is gitignored so your host and your URLs do not end
|
|
# up in a commit.
|
|
#
|
|
# Do not use it as an override. `docker compose up` reads docker-compose.yml
|
|
# and docker-compose.override.yml together and merges them, so an override
|
|
# leaves these example values in play rather than replacing them.
|
|
#
|
|
# As written it will not start: the host below is a placeholder the guard
|
|
# refuses, so this can never become a live config by being copied and
|
|
# forgotten.
|
|
services:
|
|
dejima-guard:
|
|
# Built here, not pulled: there is no registry for this. Which makes
|
|
# `--build` part of every command that starts it - `docker compose up -d`
|
|
# alone reuses the image it already has, so after a `git pull` it would run
|
|
# the old code and look like it had worked.
|
|
build: .
|
|
# image: gitbox.example.invalid/dejima/dejima-guard:latest
|
|
container_name: dejima-guard
|
|
restart: unless-stopped
|
|
|
|
environment:
|
|
# --- the machine being WATCHED, not the one this runs on ------------
|
|
#
|
|
# The devbox's hostname or address, as this container reaches it.
|
|
# Replace the placeholder: the guard refuses to start on CHANGE-ME.
|
|
DEJIMA_GUARD_DEVBOX_HOST: CHANGE-ME.example.invalid
|
|
|
|
# The account ON THE DEVBOX to log in as. Not root, and there is no
|
|
# default: the devbox runbook builds a machine with no root password
|
|
# and expects sudo from an ordinary account. The guard connects as that
|
|
# account and elevates for the two commands it runs.
|
|
DEJIMA_GUARD_DEVBOX_USER: your-devbox-account
|
|
|
|
# The private key, inside this container, to connect with. Mounted as a
|
|
# secret below rather than baked into the image.
|
|
DEJIMA_GUARD_SSH_KEY: /run/secrets/guard_key
|
|
|
|
# Where the devbox's host key is remembered. On the state volume,
|
|
# because a container filesystem is new every run - and without it,
|
|
# every collection fails host-key verification and reports the devbox
|
|
# unreachable. Already set in the image; here so it is visible.
|
|
DEJIMA_GUARD_SSH_KNOWN_HOSTS: /var/lib/dejima-guard/known_hosts
|
|
|
|
# --- where alerts go -----------------------------------------------
|
|
#
|
|
# Its OWN ntfy topic, not the one dejima pushes to. That URL lives on
|
|
# the devbox, so root there can publish to it: a compromised box could
|
|
# drown the topic or forge an all-clear. The token for this one goes in
|
|
# the mounted config, not here.
|
|
DEJIMA_GUARD_NTFY_URL: https://ntfy.example.invalid/devbox-alerts
|
|
|
|
# --- the dead-man's switch ------------------------------------------
|
|
#
|
|
# GET after a cycle that completed clean - an Uptime Kuma push monitor
|
|
# is the documented shape. Without it, a guard that dies looks exactly
|
|
# like a guard with nothing to report.
|
|
DEJIMA_GUARD_HEARTBEAT_URL: https://kuma.example.invalid/api/push/abcdef
|
|
|
|
# --- this container --------------------------------------------------
|
|
#
|
|
# Seconds between collections. Sets the dead-man's switch granularity
|
|
# and how long an intruder has to notice the monitoring and scrub.
|
|
DEJIMA_GUARD_INTERVAL: "900"
|
|
# Anything secret goes in the config file rather than here. Everything
|
|
# above is visible in `docker inspect` and to anything that can read
|
|
# /proc; a mounted secret is not. The guard reads the environment first
|
|
# and the file second, so this is the value that overrides.
|
|
DEJIMA_GUARD_CONF: /run/secrets/guard_config
|
|
|
|
# Mounted at /run/secrets/<name>, which is why CONF points there rather
|
|
# than at /etc. A `target:` naming an absolute path is a swarm feature and
|
|
# does not do what it looks like it does under plain `docker compose`.
|
|
secrets:
|
|
- guard_key
|
|
- guard_config
|
|
|
|
volumes:
|
|
# The baseline, the last report, and known_hosts. Losing this is not a
|
|
# clean slate: it is a guard that compares clean against everything and
|
|
# cannot verify the host it connects to.
|
|
- guard-state:/var/lib/dejima-guard
|
|
|
|
# It opens two outbound connections and writes one directory. Nothing here
|
|
# is a hardship, and this container holds an SSH key to a machine whose
|
|
# threat model says it may be owned.
|
|
read_only: true
|
|
tmpfs:
|
|
- /tmp
|
|
cap_drop: [ALL]
|
|
security_opt:
|
|
- no-new-privileges:true
|
|
|
|
# NO PORTS. Not "none needed today" - the reason a container is an
|
|
# acceptable home for this is that nothing can connect to it.
|
|
|
|
volumes:
|
|
guard-state:
|
|
|
|
secrets:
|
|
guard_key:
|
|
file: ./secrets/guard_key # mode 0600, the private key
|
|
guard_config:
|
|
file: ./secrets/config # ntfy_token, and anything else secret
|