dev-deploy: production mirror + full observability behind the /_gm gate #88
@@ -148,6 +148,31 @@ jobs:
|
|||||||
-v "${{ gitea.workspace }}/pkg/geoip/test-data/test-data:/src:ro" \
|
-v "${{ gitea.workspace }}/pkg/geoip/test-data/test-data:/src:ro" \
|
||||||
alpine sh -c 'cp /src/GeoIP2-Country-Test.mmdb /dst/geoip.mmdb'
|
alpine sh -c 'cp /src/GeoIP2-Country-Test.mmdb /dst/geoip.mmdb'
|
||||||
|
|
||||||
|
- name: Seed mailpit relay config
|
||||||
|
env:
|
||||||
|
GALAXY_DEV_MAIL_RELAY_USERNAME: ${{ secrets.GALAXY_DEV_MAIL_RELAY_USERNAME }}
|
||||||
|
GALAXY_DEV_MAIL_RELAY_PASSWORD: ${{ secrets.GALAXY_DEV_MAIL_RELAY_PASSWORD }}
|
||||||
|
run: |
|
||||||
|
# Render the Mailpit relay upstream config from the template,
|
||||||
|
# substituting the Gmail App Password from a Gitea secret, then
|
||||||
|
# seed it into a named volume (same rationale as the geoip seed:
|
||||||
|
# a workspace bind-mount would vanish with the runner workspace).
|
||||||
|
# The secret never lands in git or a committed file; it is
|
||||||
|
# rendered to a tmpfile outside the repo and removed after. Gmail
|
||||||
|
# App Passwords are [a-z]{16}, so the `|` sed delimiter is safe.
|
||||||
|
# When the secret is unset the creds render empty and the compose
|
||||||
|
# default relay-match is non-routable, so the stack only captures.
|
||||||
|
rendered="$(mktemp)"
|
||||||
|
sed -e "s|\${GALAXY_DEV_MAIL_RELAY_USERNAME}|${GALAXY_DEV_MAIL_RELAY_USERNAME}|g" \
|
||||||
|
-e "s|\${GALAXY_DEV_MAIL_RELAY_PASSWORD}|${GALAXY_DEV_MAIL_RELAY_PASSWORD}|g" \
|
||||||
|
"${{ gitea.workspace }}/tools/dev-deploy/mailpit/relay.conf.tmpl" > "$rendered"
|
||||||
|
docker volume create galaxy-dev-mailpit-config >/dev/null
|
||||||
|
docker run --rm \
|
||||||
|
-v galaxy-dev-mailpit-config:/dst \
|
||||||
|
-v "$rendered:/src/relay.conf:ro" \
|
||||||
|
alpine sh -c 'cp /src/relay.conf /dst/relay.conf && chmod 600 /dst/relay.conf'
|
||||||
|
rm -f "$rendered"
|
||||||
|
|
||||||
- name: Recycle engine containers on image drift
|
- name: Recycle engine containers on image drift
|
||||||
run: |
|
run: |
|
||||||
# Compare the freshly-built `galaxy-engine:dev` SHA against
|
# Compare the freshly-built `galaxy-engine:dev` SHA against
|
||||||
@@ -231,6 +256,11 @@ jobs:
|
|||||||
|
|
||||||
- name: Bring up the stack
|
- name: Bring up the stack
|
||||||
working-directory: tools/dev-deploy
|
working-directory: tools/dev-deploy
|
||||||
|
env:
|
||||||
|
# Recipient regex Mailpit auto-relays to the owner's Gmail.
|
||||||
|
# Unset/empty → the compose default (non-routable) keeps the
|
||||||
|
# stack capture-only.
|
||||||
|
GALAXY_DEV_MAIL_RELAY_MATCH: ${{ vars.GALAXY_DEV_MAIL_RELAY_MATCH }}
|
||||||
run: |
|
run: |
|
||||||
# Resolve in the shell, not in YAML expressions — `env.HOME`
|
# Resolve in the shell, not in YAML expressions — `env.HOME`
|
||||||
# is empty at the workflow-evaluation stage.
|
# is empty at the workflow-evaluation stage.
|
||||||
|
|||||||
@@ -117,13 +117,37 @@ and the dev-deploy compose ships with it enabled by default:
|
|||||||
1. Enter your email address in the login form.
|
1. Enter your email address in the login form.
|
||||||
2. Submit `123456` as the code — the docker-compose default for
|
2. Submit `123456` as the code — the docker-compose default for
|
||||||
`BACKEND_AUTH_DEV_FIXED_CODE` is `123456`, so the bcrypt-hashed
|
`BACKEND_AUTH_DEV_FIXED_CODE` is `123456`, so the bcrypt-hashed
|
||||||
email code stays a fallback. To force real Mailpit codes (e.g. for
|
email code stays a fallback. To force the real email code (which
|
||||||
mail-flow QA), set `BACKEND_AUTH_DEV_FIXED_CODE=` (empty) in a
|
Mailpit then relays to your Gmail — see **Mail** below), set
|
||||||
local `.env` and `make rebuild`.
|
`BACKEND_AUTH_DEV_FIXED_CODE=` (empty) and redeploy.
|
||||||
|
|
||||||
The fixed-code override is rejected by production env loaders, so it
|
The fixed-code override is rejected by production env loaders, so it
|
||||||
cannot leak into the prod environment.
|
cannot leak into the prod environment.
|
||||||
|
|
||||||
|
## Mail
|
||||||
|
|
||||||
|
The backend always submits mail to **Mailpit** (`galaxy-mailpit:1025`),
|
||||||
|
exactly as it would to a production SMTP server. Mailpit captures every
|
||||||
|
message in its UI (internal `:8025`) and, when configured, **relays**
|
||||||
|
the ones whose recipient matches `GALAXY_DEV_MAIL_RELAY_MATCH` up to a
|
||||||
|
real Gmail account — so an OTP addressed to you lands in your real inbox
|
||||||
|
while everything else stays captured-only.
|
||||||
|
|
||||||
|
Configure the relay through Gitea Actions secrets/vars (never
|
||||||
|
committed); the `dev-deploy.yaml` workflow renders Mailpit's
|
||||||
|
`relay.conf` (from `tools/dev-deploy/mailpit/relay.conf.tmpl`) and seeds
|
||||||
|
it into the `galaxy-dev-mailpit-config` volume:
|
||||||
|
|
||||||
|
| Name | Kind | Purpose |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `GALAXY_DEV_MAIL_RELAY_USERNAME` | secret | Gmail address used as the relay login + From. |
|
||||||
|
| `GALAXY_DEV_MAIL_RELAY_PASSWORD` | secret | Gmail **App Password** (requires 2FA; not the account password). |
|
||||||
|
| `GALAXY_DEV_MAIL_RELAY_MATCH` | var | Recipient regex to auto-relay (e.g. your Gmail address). Unset → capture-only. |
|
||||||
|
|
||||||
|
With none set the stack only captures mail (the compose relay-match
|
||||||
|
defaults to a non-routable address), so it can never email third
|
||||||
|
parties.
|
||||||
|
|
||||||
## Networking
|
## Networking
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -66,10 +66,20 @@ services:
|
|||||||
image: axllent/mailpit:v1.21
|
image: axllent/mailpit:v1.21
|
||||||
container_name: galaxy-dev-mailpit
|
container_name: galaxy-dev-mailpit
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
# Mailpit is both the SMTP submission point and a relay: it captures
|
||||||
|
# every message in its UI and auto-relays the ones whose recipient
|
||||||
|
# matches GALAXY_DEV_MAIL_RELAY_MATCH to the Gmail account in the
|
||||||
|
# secret-rendered relay config. The default match is non-routable, so
|
||||||
|
# a stack brought up without the relay secret only captures, never sends.
|
||||||
|
command:
|
||||||
|
- "--smtp-relay-config=/etc/mailpit/relay.conf"
|
||||||
|
- "--smtp-relay-matching=${GALAXY_DEV_MAIL_RELAY_MATCH:-nobody@invalid.example}"
|
||||||
labels:
|
labels:
|
||||||
galaxy.stack: dev-deploy
|
galaxy.stack: dev-deploy
|
||||||
networks:
|
networks:
|
||||||
- galaxy-internal
|
- galaxy-internal
|
||||||
|
volumes:
|
||||||
|
- galaxy-dev-mailpit-config:/etc/mailpit:ro
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "wget", "-q", "-O-", "http://localhost:8025/livez"]
|
test: ["CMD", "wget", "-q", "-O-", "http://localhost:8025/livez"]
|
||||||
interval: 3s
|
interval: 3s
|
||||||
@@ -283,3 +293,5 @@ volumes:
|
|||||||
name: galaxy-dev-site-dist
|
name: galaxy-dev-site-dist
|
||||||
galaxy-dev-geoip-data:
|
galaxy-dev-geoip-data:
|
||||||
name: galaxy-dev-geoip-data
|
name: galaxy-dev-geoip-data
|
||||||
|
galaxy-dev-mailpit-config:
|
||||||
|
name: galaxy-dev-mailpit-config
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Mailpit SMTP relay upstream — RENDERED AT DEPLOY TIME by
|
||||||
|
# .gitea/workflows/dev-deploy.yaml from Gitea Actions secrets, then
|
||||||
|
# seeded into the `galaxy-dev-mailpit-config` volume. The Gmail App
|
||||||
|
# Password is a secret and MUST NOT be committed: this template only
|
||||||
|
# carries ${PLACEHOLDER}s that the workflow substitutes. See
|
||||||
|
# tools/dev-deploy/README.md ("Mail").
|
||||||
|
#
|
||||||
|
# Mailpit captures every message; the `--smtp-relay-matching` flag (set
|
||||||
|
# from GALAXY_DEV_MAIL_RELAY_MATCH in the compose) decides which
|
||||||
|
# recipients are actually relayed up to this Gmail account.
|
||||||
|
host: smtp.gmail.com
|
||||||
|
port: 587
|
||||||
|
starttls: true
|
||||||
|
allow-insecure: false
|
||||||
|
auth: login
|
||||||
|
username: ${GALAXY_DEV_MAIL_RELAY_USERNAME}
|
||||||
|
password: ${GALAXY_DEV_MAIL_RELAY_PASSWORD}
|
||||||
|
return-path: ${GALAXY_DEV_MAIL_RELAY_USERNAME}
|
||||||
Reference in New Issue
Block a user