96 lines
4.3 KiB
YAML
96 lines
4.3 KiB
YAML
|
|
# ===========================================================================
|
||
|
|
# docker-mailserver management bastion (broker mode)
|
||
|
|
# ===========================================================================
|
||
|
|
# A single bastion that lets a sidecar app (e.g. a Nuxt "mail manager") run a
|
||
|
|
# WHITELIST of docker-mailserver `setup` sub-commands — and nothing else.
|
||
|
|
#
|
||
|
|
# The app talks to the bastion over the internal docker network via SSH:
|
||
|
|
# ssh agent@bastion-mail "email add jane@example.com <password>"
|
||
|
|
# The bastion validates the request against ALLOWED_COMMANDS, and on a match
|
||
|
|
# runs docker exec -i mailserver setup email add jane@example.com <password>
|
||
|
|
# against the host docker socket. No match → refused, nothing runs.
|
||
|
|
#
|
||
|
|
# Drop this `bastion-mail` service into the same compose project as your
|
||
|
|
# `mailserver` container (or any compose project on the same external
|
||
|
|
# network), then `docker compose up -d bastion-mail`.
|
||
|
|
# ===========================================================================
|
||
|
|
|
||
|
|
services:
|
||
|
|
bastion-mail:
|
||
|
|
image: blaxsoftware/bastion:latest
|
||
|
|
restart: unless-stopped
|
||
|
|
|
||
|
|
environment:
|
||
|
|
# ----------------------------------------------------------------
|
||
|
|
# COMMAND_PREFIX — trusted, operator-set. Prepended to every
|
||
|
|
# validated request so clients send clean `email add …` commands
|
||
|
|
# and never see the docker plumbing. `setup` is docker-mailserver's
|
||
|
|
# in-container admin CLI; `-i` (not `-it`) because the caller has no
|
||
|
|
# TTY over a scripted SSH/HTTP call.
|
||
|
|
# ----------------------------------------------------------------
|
||
|
|
COMMAND_PREFIX: "docker exec -i mailserver setup"
|
||
|
|
|
||
|
|
# ----------------------------------------------------------------
|
||
|
|
# ALLOWED_COMMANDS — the whitelist. A YAML block scalar (`|`) reads
|
||
|
|
# like a string array: one extended-regex (ERE) rule per line. A
|
||
|
|
# request is permitted only if it matches a rule WHOLE-LINE.
|
||
|
|
#
|
||
|
|
# Matched commands run WITHOUT a shell (; | & $() are literal args),
|
||
|
|
# so the regex is the entire authorization boundary — keep argument
|
||
|
|
# classes tight ([^ ]+ rather than .*). Values that must arrive
|
||
|
|
# intact can't contain spaces; generate passwords space-free.
|
||
|
|
#
|
||
|
|
# Prefer the mounted file (see volumes) if you'd rather edit rules
|
||
|
|
# without redeploying — the two sources are additive.
|
||
|
|
# ----------------------------------------------------------------
|
||
|
|
ALLOWED_COMMANDS: |
|
||
|
|
email add [^ ]+@[^ ]+ [^ ]+
|
||
|
|
email update [^ ]+@[^ ]+ [^ ]+
|
||
|
|
email del [^ ]+@[^ ]+
|
||
|
|
email list
|
||
|
|
alias add [^ ]+@[^ ]+ [^ ]+
|
||
|
|
alias del [^ ]+@[^ ]+ [^ ]+
|
||
|
|
alias list
|
||
|
|
quota set [^ ]+@[^ ]+ [0-9]+[KMGT]?
|
||
|
|
quota del [^ ]+@[^ ]+
|
||
|
|
|
||
|
|
volumes:
|
||
|
|
# REQUIRED — the host docker socket, so `docker exec` can reach the
|
||
|
|
# mailserver container. This is host-root-equivalent; the allowlist
|
||
|
|
# is what keeps it scoped.
|
||
|
|
- /var/run/docker.sock:/var/run/docker.sock
|
||
|
|
|
||
|
|
# Authorized clients — drop one pubkey per identity. The mail-manager
|
||
|
|
# app's key goes here; read live, no restart to add/revoke.
|
||
|
|
- ./docker-data/bastion/users.d:/etc/bastion/users.d
|
||
|
|
|
||
|
|
# Persist the bastion's SSH host identity across rebuilds (bind mount,
|
||
|
|
# never a named volume — `down -v` would wipe it and clients would see
|
||
|
|
# a changed host key).
|
||
|
|
- ./docker-data/bastion/keys:/etc/ssh/keys
|
||
|
|
|
||
|
|
# OPTIONAL — live-editable allowlist (additive with ALLOWED_COMMANDS
|
||
|
|
# above). Edit the file and the next request picks it up; no restart.
|
||
|
|
# - ./allowed-commands.list:/etc/bastion/allowed-commands.list:ro
|
||
|
|
|
||
|
|
# No host port published: the mail-manager reaches the bastion by
|
||
|
|
# service name on the shared network (ssh agent@bastion-mail). Uncomment
|
||
|
|
# to also expose SSH on the host for debugging — bind to localhost.
|
||
|
|
# ports:
|
||
|
|
# - "127.0.0.1:2222:22"
|
||
|
|
|
||
|
|
networks: [web]
|
||
|
|
|
||
|
|
# Your docker-mailserver container — referenced by name in COMMAND_PREFIX.
|
||
|
|
# Shown here for context; usually it already lives in its own compose file.
|
||
|
|
# mailserver:
|
||
|
|
# image: ghcr.io/docker-mailserver/docker-mailserver:latest
|
||
|
|
# container_name: mailserver
|
||
|
|
# hostname: mail.example.com
|
||
|
|
# networks: [web]
|
||
|
|
# # …ports/volumes/env per the docker-mailserver docs…
|
||
|
|
|
||
|
|
networks:
|
||
|
|
web:
|
||
|
|
external: true
|