feat: initial support for deploying multiple instances and VPN#99
Draft
tonsV2 wants to merge 13 commits into
Draft
feat: initial support for deploying multiple instances and VPN#99tonsV2 wants to merge 13 commits into
tonsV2 wants to merge 13 commits into
Conversation
…s on th… (#94) * Reapply "feat: initial support for deploying multiple instances on the same host. WIP" This reverts commit ed9278f. * feat: per-project backup paths * chore: doc updates and list-instances (#96) * chore: doc updates and list-instances * Apply suggestions from code review - remove numbering in reference file Co-authored-by: Philip-Larsen-Donnelly <35666657+Philip-Larsen-Donnelly@users.noreply.github.com> * fix: review comments * fix: add shebang to env-utils.sh to fix shellcheck SC2148 * feat: add delete-instance target to remove instance data and env file * refactor: rename launch-* targets to start-* for consistency with stop-instance * refactor: rename monitoring_net network to monitoring * fix: resolve shellcheck SC1091/SC2119 warnings in generate scripts --------- Co-authored-by: Philip-Larsen-Donnelly <phil@dhis2.org> Co-authored-by: Philip-Larsen-Donnelly <35666657+Philip-Larsen-Donnelly@users.noreply.github.com>
…ble (DEVOPS-665) (#101) * refactor(server-tools): drop systemd and overlay management from ansible (DEVOPS-665) * style(server-tools): unwrap mid-sentence line breaks in README
* feat: initial WireGuard * feat: move Grafana to VPN-only access via grafana.internal Grafana is no longer publicly accessible. It's now only reachable at https://grafana.internal for clients connected to the WireGuard VPN. - Add stacks/traefik/conf.d/internal.yml with VPN-only routes for grafana.internal and glowroot.internal (served with mkcert wildcard cert) - Mount overlays/wireguard/certs/ into stacks/traefik so certs are shared between the wireguard and traefik compose projects - Fix wireguard overlay incompatibilities with multi-instance approach: use bind-mount for certs instead of named volume, change network from `frontend` to `proxy`, remove orphaned traefik service override that referenced the now-deleted single-instance dynamic.yml - Add service definitions to overlays/wireguard/traefik/internal.yml (grafana-internal → monitoring-grafana:3000, glowroot-internal → app:4000) - Remove stacks/traefik/conf.d/monitoring.yml.template and the start-monitoring Makefile step that generated it (public Grafana route) - Remove GRAFANA_HOSTNAME from monitoring .env.template and generate script; hardcode GF_SERVER_ROOT_URL=https://grafana.internal in docker-compose.yml - Gitignore overlays/wireguard/certs/ and config/ (contain private keys) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: proxy VPN traffic to Traefik via socat sidecar Adds wireguard-proxy service that listens on 10.8.0.1:443 (wg0 IP) inside the WireGuard container's network namespace and forwards to traefik:443. Docker DNS resolves 'traefik' per connection, so it handles Traefik container restarts without needing hardcoded IPs or iptables DNAT rules. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: initial WireGuard * chore: get-vpn-ca * docs: vpn updates * fix: restore inventory.ini placeholder host * fix: remove orphan internal.yml from wireguard overlay Unreferenced near-duplicate of stacks/traefik/conf.d/internal.yml, which is the file Traefik actually loads. * chore: gitignore rootCA.pem from get-vpn-ca `make get-vpn-ca` writes the root CA to the working tree so clients can install it; it should not land in commits. * fix: restrict internal.key to mode 600 The mkcert container that writes the key and the Traefik container that reads it both run as root, so the key does not need to be world-readable. * fix: drop unused wildcard domain env from mkcert service The `domain: "*.internal"` env var was never consumed: the compose file overrides the image entrypoint with `command: sh /mkcert.sh`, and the script hardcodes the two host names. The generated cert is already a 2-SAN cert, not a wildcard. * style: replace em dashes with ASCII dashes Sweep em dashes out of files added or modified on this branch. Pre-existing em dashes in master (README intro and footer) are left alone as out of scope. * docs: document mkcert image digest pin The vishnunair/docker-mkcert image only publishes a `latest` tag, so pinning by digest is the only stable reference available. * fix: generate one cert per internal host Previously mkcert.sh produced a single 2-SAN cert (grafana.internal + glowroot.internal) shared by both routes. Switch to one cert per host and list both in Traefik's tls.certificates so SNI selects the right one. Existing deployments must clear the wireguard-certs volume to drop the old internal.crt/internal.key on first run after this change. * feat: build mkcert image locally instead of pulling pre-built Replaces the pinned vishnunair/docker-mkcert digest with a minimal custom Dockerfile that fetches mkcert directly from the upstream release URL, removing the dependency on a third-party image. * feat: align server-tools with VPN deployment * fix: handle IPv6 in wireguard * feat: simplify server deployment * refactor: rename operator_user to docker_user * refactor: split tunnel default * refactor: remove obsolete env template * fix: refactor wireguard env * Update docs/vpn.md Co-authored-by: radnov <radoslav@dhis2.org> * fix: let Buildkit populate TARGETARCH for mkcert build * fix: declare wireguard-certs volume external to avoid project ownership warning * fix: make internal cert keys readable by Traefik * fix: use explicit placeholder IP in example inventory * fix: mount coredns directory to avoid macOS VirtioFS bind-mount failure * docs: note macOS Docker Desktop UDP setting for the VPN server --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Philip-Larsen-Donnelly <phil@dhis2.org> Co-authored-by: Philip-Larsen-Donnelly <35666657+Philip-Larsen-Donnelly@users.noreply.github.com> Co-authored-by: radnov <radoslav@dhis2.org>
Copy config/dhis2 and config/postgresql defaults into instances/<PROJECT_NAME>/ on create-instance and mount the per-instance copies via COMPOSE_PROJECT_NAME so each instance can be tuned independently.
Define the proxy/monitoring networks and the wireguard-certs volume in stacks/base/networks.yml and stacks/base/volumes.yml and create them through $(DOCKER) compose so they land in the same daemon/context as the compose up, fixing the external volume not found error on hosts where docker needs sudo and on Docker Desktop.
Move the per-instance env file from instances/<name>.env to instances/<name>/.env so an instance's env and its dhis2/postgresql config share one folder, letting delete-instance remove everything with a single rm -rf and list-instances enumerate by folder.
# Conflicts: # README.md
radnov
approved these changes
Jul 7, 2026
Contributor
There was a problem hiding this comment.
Tested end-to-end on a fresh Ubuntu 24.04 VM and a MacOS client machine. The multi-instance design seems to work as expected: Ansible provisioning, shared Traefik + monitoring, WireGuard VPN, and two isolated instances all came up without errors. Then I logged into DHIS2 with the generated admin password, changed user profile data and installed an app, all without issues.
I also updated the notes for the MacOS setup, removed some dead config and updated glowroot so it's served on the internal network per instance.
P.S.
The e2e test will be fixed in a separate PR.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR touches almost every file in the project and should be considered the base of version 2.0. The two major features it adds is support for deploying multiples instances on the same server and support for VPN (using WireGuard)