Skip to content

Restructure Docker Compose Setup With Modular Extensions#6

Merged
danielesser merged 12 commits into
mainfrom
advanced-example
Jul 17, 2026
Merged

Restructure Docker Compose Setup With Modular Extensions#6
danielesser merged 12 commits into
mainfrom
advanced-example

Conversation

@danielesser

Copy link
Copy Markdown
Member

What and why

Configuration should be changeable in one place, and optional features (HTTPS, backups, auto-updates, a management UI) shouldn't force everyone to carry their weight. This PR keeps docker-compose.yml as a zero-edit quick start, moves all secrets/settings to ${VAR:-default} interpolation so they're overridable from a single .env file, and splits optional functionality into independent extensions/ overlays that can be mixed and matched with -f instead of bundled into one fixed setup.

Summary

  • docker-compose.yml still runs out of the box with zero edits, but secrets/settings now have working defaults baked in via ${VAR:-default} instead of being hardcoded — change one in a .env file (see .env.example) instead of hunting it down across the compose file.
  • Optional add-ons live in extensions/, one self-contained Compose overlay per feature, layered on with -f:
    • extensions/nginx — HTTPS reverse proxy with automatic Let's Encrypt certificates
    • extensions/watchtower — automatic container updates (nickfedor/watchtower, since containrrr/watchtower is deprecated)
    • extensions/backup — daily database + workflow-data backups, local by default, optional S3 upload
    • extensions/portainer — web UI for managing the Docker stack without the CLI
  • CI (.github/workflows/validate.yml) validates every Compose file combination on push/PR/manual dispatch.
  • Vagrant bumped from debian/buster64 (EOL) to debian/bookworm64, with forwarded ports for the new extensions.
  • README promotes Extensions to a top-level section instead of a collapsed "Advanced Topics" block.

danielesser and others added 9 commits July 16, 2026 08:55
The single-file quick start still works with zero edits, but secrets and
settings now have working defaults baked in via ${VAR:-default} instead of
being hardcoded. To change one, place a .env file next to docker-compose.yml
and set the variable there — see .env.example — rather than hunting down
every place it appears in the compose file. Also adds restart: unless-stopped
to all services and bumps mongo to the latest 7.0.x patch release.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds nginx-proxy plus acme-companion for automatic Let's Encrypt certificate
issuance, layered on with -f as an opt-in overlay rather than a separate
combined compose file. Requires DOMAIN and LETSENCRYPT_EMAIL in .env,
enforced by Compose's ${VAR:?message} syntax so it fails fast with a clear
message instead of starting misconfigured.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Uses the nickfedor/watchtower fork rather than containrrr/watchtower, which
is deprecated. Labels api, web, and executor with
com.centurylinklabs.watchtower.enable so only Runner's own containers are
targeted, not the extension containers or anything else on the host.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Runs mongodump inside the mongodb container via docker-volume-backup's
archive-pre/archive-post hooks, so the dump is consistent even while Runner
is running, then archives it alongside the api-data volume (uploaded
workflows and environments). executor-data is excluded — it's the
executor's working/cache directory, not source-of-truth data. Backups land
locally by default with zero configuration; shipping them to an
S3-compatible bucket is opt-in via .env.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Zero-config, matching the watchtower extension's pattern — no secrets or
.env vars needed. The admin account is claimed via Portainer's own
one-time setup token on first visit instead of a baked-in default password.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Advanced Topics subsections were H2, same level as their H2 parent instead
of nested under it. Also replaces the misleading MongoDB password example
in "Changing secrets and settings" — MONGO_ROOT_PASSWORD in .env only takes
effect on first initialization, not on a running installation — with the
shared API key, and points to the docs for the actual rotation procedure.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
debian/buster64 (Debian 10) is past its LTS window; bookworm64 is the
current stable release with actively maintained Vagrant Cloud box builds
(trixie64 boxes aren't reliably published yet). Also forwards 80/443/9000
so extensions/nginx and extensions/portainer are reachable from the host
when running inside the box, matching the existing 8080 forward for the
base stack.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds a GitHub Container Registry pulls badge and a documentation badge
alongside the existing Product/Changelog/License badges. Wraps onto a
second line via <br/> within a single <p> rather than two separate <p>
tags, to avoid stacking paragraph margins between the two badge rows.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Runs docker compose config against the base file, each extension
individually, and all extensions combined, as a matrix job so failures
show up per-combination in the checks list rather than one long job. This
is exactly the class of bug (required-var errors, broken -f combos,
interpolation typos) that surfaced only through manual testing while
building these files.

Also triggers on pull_request (so fork PRs get checked, since push alone
only fires for pushes to this repo) and workflow_dispatch (manual runs).
Sets explicit least-privilege permissions, cancels superseded runs via
concurrency, and pins actions/checkout to a commit SHA rather than a
mutable tag.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@danielesser
danielesser requested a review from qqilihq July 16, 2026 07:47
@qqilihq

qqilihq commented Jul 16, 2026

Copy link
Copy Markdown
Member

LGTM! Go for it!

@qqilihq
qqilihq requested a review from Copilot July 16, 2026 19:21

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR restructures the local/self-hosted Docker Compose setup to be configurable from a single .env file and to support optional features via modular extensions/ Compose overlays, while also adding CI validation for supported file combinations.

Changes:

  • Refactors docker-compose.yml to use ${VAR:-default} interpolation so configuration can be overridden centrally via .env (with .env.example added).
  • Adds modular Compose overlays under extensions/ (nginx/HTTPS, watchtower updates, backups, portainer UI).
  • Adds a GitHub Actions workflow to validate Compose configurations and updates Vagrant defaults/forwarded ports.

Reviewed changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
Vagrantfile Updates Debian base box and forwards ports needed by optional extensions.
README.md Documents extensions usage and .env-based configuration workflow.
docker-compose.yml Moves key settings/secrets to .env-overridable defaults; adds restart policies and bumps Mongo image.
.gitignore Ignores local .env and extension-generated/host-archive paths.
.github/workflows/validate.yml CI matrix validates docker compose ... config for base + extension combinations.
.env.example Provides a single place to override compose defaults and extension settings.
extensions/watchtower/docker-compose.yml Adds Watchtower overlay and labels to opt-in containers.
extensions/portainer/docker-compose.yml Adds Portainer overlay for stack management UI.
extensions/nginx/docker-compose.yml Adds nginx-proxy + acme-companion overlay for HTTPS termination.
extensions/nginx/conf.d/client_max_body_size.conf Adds nginx config to remove upload size limit.
extensions/backup/docker-compose.yml Adds backup overlay using docker-volume-backup with optional S3 shipping.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Vagrantfile Outdated
Comment thread extensions/nginx/conf.d/client_max_body_size.conf
Comment thread docker-compose.yml
Comment thread docker-compose.yml Outdated
Comment thread extensions/portainer/docker-compose.yml Outdated
danielesser and others added 3 commits July 17, 2026 07:54
Forwarding ports 80/443/8080/9000 unconditionally could make `vagrant up`
fail outright if any of those are already taken on the host, which is
common on developer machines. auto_correct: true falls back to a
different free host port instead of failing when the requested one is in
use.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
API_KEY and the MongoDB credentials default to fixed, repo-known values.
Fine for local evaluation, but easy to accidentally deploy without
overriding them in .env. Adds a one-line warning at each default so it's
visible at the exact point someone might copy the value, rather than only
in the top-of-file comment. Also drops a comment that only restated what
the DB_URL value already shows, and tightens another to fit one line.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Portainer has the Docker socket mounted, so anyone who can log in has
root-equivalent access to the host. That warrants network-level isolation
by default, not just Portainer's own login screen — publish on localhost
only and document the SSH tunnel needed to reach it on a remote host.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@danielesser
danielesser merged commit ca13ef2 into main Jul 17, 2026
12 checks passed
@danielesser
danielesser deleted the advanced-example branch July 17, 2026 06:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants