feat(deploy): wire the SMTP relay through every contour
Add the backend confirm-code relay env to compose (BACKEND_SMTP_HOST/PORT/ USERNAME/PASSWORD/FROM + BACKEND_PUBLIC_BASE_URL), sourced from SMTP_RELAY_* / SMTP_RELAY_FROM / PUBLIC_BASE_URL. An empty host keeps the backend on the log mailer so a contour without relay credentials still boots. Port defaults to 465 (implicit TLS). Map the TEST_ set in ci.yaml and the PROD_ set in prod-deploy.yaml (both the deploy-main env and the env.sh heredoc). Document the six variables in .env.example and the deploy README (secrets: user/pass; variables: host/port/from + the per-contour PUBLIC_BASE_URL, required whenever the relay host is set).
This commit is contained in:
@@ -332,6 +332,16 @@ jobs:
|
|||||||
GATEWAY_VK_APP_SECRET: ${{ secrets.TEST_GATEWAY_VK_APP_SECRET }}
|
GATEWAY_VK_APP_SECRET: ${{ secrets.TEST_GATEWAY_VK_APP_SECRET }}
|
||||||
# Signs the finished-game export download URLs (backend + compose interpolation).
|
# Signs the finished-game export download URLs (backend + compose interpolation).
|
||||||
EXPORT_SIGN_KEY: ${{ secrets.TEST_EXPORT_SIGN_KEY }}
|
EXPORT_SIGN_KEY: ${{ secrets.TEST_EXPORT_SIGN_KEY }}
|
||||||
|
# Transactional email via the shared Selectel relay. Empty host leaves the
|
||||||
|
# backend on the log mailer (email disabled) but the contour still boots.
|
||||||
|
SMTP_RELAY_USER: ${{ secrets.TEST_SMTP_RELAY_USER }}
|
||||||
|
SMTP_RELAY_PASS: ${{ secrets.TEST_SMTP_RELAY_PASS }}
|
||||||
|
SMTP_RELAY_HOST: ${{ vars.TEST_SMTP_RELAY_HOST }}
|
||||||
|
SMTP_RELAY_PORT: ${{ vars.TEST_SMTP_RELAY_PORT }}
|
||||||
|
SMTP_RELAY_FROM: ${{ vars.TEST_SMTP_RELAY_FROM }}
|
||||||
|
# Canonical public origin for links in the email (this contour's URL);
|
||||||
|
# required by the backend whenever SMTP_RELAY_HOST is set.
|
||||||
|
PUBLIC_BASE_URL: ${{ vars.TEST_PUBLIC_BASE_URL }}
|
||||||
GM_BASICAUTH_USER: ${{ vars.TEST_GM_BASICAUTH_USER }}
|
GM_BASICAUTH_USER: ${{ vars.TEST_GM_BASICAUTH_USER }}
|
||||||
GRAFANA_ROOT_URL: ${{ vars.TEST_GRAFANA_ROOT_URL }}
|
GRAFANA_ROOT_URL: ${{ vars.TEST_GRAFANA_ROOT_URL }}
|
||||||
CADDY_SITE_ADDRESS: ${{ vars.TEST_CADDY_SITE_ADDRESS }}
|
CADDY_SITE_ADDRESS: ${{ vars.TEST_CADDY_SITE_ADDRESS }}
|
||||||
|
|||||||
@@ -86,6 +86,13 @@ jobs:
|
|||||||
GATEWAY_VK_APP_SECRET: ${{ secrets.PROD_GATEWAY_VK_APP_SECRET }}
|
GATEWAY_VK_APP_SECRET: ${{ secrets.PROD_GATEWAY_VK_APP_SECRET }}
|
||||||
# Signs the finished-game export download URLs (backend BACKEND_EXPORT_SIGN_KEY).
|
# Signs the finished-game export download URLs (backend BACKEND_EXPORT_SIGN_KEY).
|
||||||
EXPORT_SIGN_KEY: ${{ secrets.PROD_EXPORT_SIGN_KEY }}
|
EXPORT_SIGN_KEY: ${{ secrets.PROD_EXPORT_SIGN_KEY }}
|
||||||
|
# Transactional email via the shared Selectel relay (confirm-codes).
|
||||||
|
SMTP_RELAY_USER: ${{ secrets.PROD_SMTP_RELAY_USER }}
|
||||||
|
SMTP_RELAY_PASS: ${{ secrets.PROD_SMTP_RELAY_PASS }}
|
||||||
|
SMTP_RELAY_HOST: ${{ vars.PROD_SMTP_RELAY_HOST }}
|
||||||
|
SMTP_RELAY_PORT: ${{ vars.PROD_SMTP_RELAY_PORT }}
|
||||||
|
SMTP_RELAY_FROM: ${{ vars.PROD_SMTP_RELAY_FROM }}
|
||||||
|
PUBLIC_BASE_URL: ${{ vars.PROD_PUBLIC_BASE_URL }}
|
||||||
PROD_BOTLINK_CA: ${{ secrets.PROD_BOTLINK_CA }}
|
PROD_BOTLINK_CA: ${{ secrets.PROD_BOTLINK_CA }}
|
||||||
PROD_BOTLINK_GATEWAY_CERT: ${{ secrets.PROD_BOTLINK_GATEWAY_CERT }}
|
PROD_BOTLINK_GATEWAY_CERT: ${{ secrets.PROD_BOTLINK_GATEWAY_CERT }}
|
||||||
PROD_BOTLINK_GATEWAY_KEY: ${{ secrets.PROD_BOTLINK_GATEWAY_KEY }}
|
PROD_BOTLINK_GATEWAY_KEY: ${{ secrets.PROD_BOTLINK_GATEWAY_KEY }}
|
||||||
@@ -142,6 +149,12 @@ jobs:
|
|||||||
export TELEGRAM_MINIAPP_URL='$TELEGRAM_MINIAPP_URL'
|
export TELEGRAM_MINIAPP_URL='$TELEGRAM_MINIAPP_URL'
|
||||||
export GATEWAY_VK_APP_SECRET='$GATEWAY_VK_APP_SECRET'
|
export GATEWAY_VK_APP_SECRET='$GATEWAY_VK_APP_SECRET'
|
||||||
export EXPORT_SIGN_KEY='$EXPORT_SIGN_KEY'
|
export EXPORT_SIGN_KEY='$EXPORT_SIGN_KEY'
|
||||||
|
export SMTP_RELAY_HOST='$SMTP_RELAY_HOST'
|
||||||
|
export SMTP_RELAY_PORT='$SMTP_RELAY_PORT'
|
||||||
|
export SMTP_RELAY_USER='$SMTP_RELAY_USER'
|
||||||
|
export SMTP_RELAY_PASS='$SMTP_RELAY_PASS'
|
||||||
|
export SMTP_RELAY_FROM='$SMTP_RELAY_FROM'
|
||||||
|
export PUBLIC_BASE_URL='$PUBLIC_BASE_URL'
|
||||||
export GATEWAY_ABUSE_BAN_ENABLED='true'
|
export GATEWAY_ABUSE_BAN_ENABLED='true'
|
||||||
EOF
|
EOF
|
||||||
printf '%s\n' "$PROD_BOTLINK_CA" > stage/certs-main/ca.crt
|
printf '%s\n' "$PROD_BOTLINK_CA" > stage/certs-main/ca.crt
|
||||||
|
|||||||
@@ -26,6 +26,21 @@ LOG_LEVEL=info
|
|||||||
# real contour value with `openssl rand -base64 32` (Gitea TEST_/PROD_EXPORT_SIGN_KEY).
|
# real contour value with `openssl rand -base64 32` (Gitea TEST_/PROD_EXPORT_SIGN_KEY).
|
||||||
EXPORT_SIGN_KEY=dev-export-sign-key
|
EXPORT_SIGN_KEY=dev-export-sign-key
|
||||||
|
|
||||||
|
# --- Transactional email (Selectel relay) -----------------------------------
|
||||||
|
# Confirm-code email via the shared Selectel relay (one relay for every contour;
|
||||||
|
# limit 100 msgs / 5 min). Empty SMTP_RELAY_HOST makes the backend log codes instead
|
||||||
|
# of sending (dev). Port 465 = implicit TLS, else STARTTLS; no client cert is needed.
|
||||||
|
# FROM must use the prod domain (Selectel only accepts the verified sender domain), so
|
||||||
|
# it is the same on every contour. PUBLIC_BASE_URL is the canonical https origin for
|
||||||
|
# links in the email — the contour's own public URL. Gitea TEST_/PROD_SMTP_RELAY_* +
|
||||||
|
# TEST_/PROD_PUBLIC_BASE_URL.
|
||||||
|
SMTP_RELAY_HOST=
|
||||||
|
SMTP_RELAY_PORT=465
|
||||||
|
SMTP_RELAY_USER= # secret
|
||||||
|
SMTP_RELAY_PASS= # secret
|
||||||
|
SMTP_RELAY_FROM=no-reply@erudit-game.ru
|
||||||
|
PUBLIC_BASE_URL= # required when SMTP_RELAY_HOST is set (e.g. https://erudit-game.ru)
|
||||||
|
|
||||||
# --- Edge / caddy -----------------------------------------------------------
|
# --- Edge / caddy -----------------------------------------------------------
|
||||||
# Test: ":80" (the host caddy terminates TLS and forwards to scrabble:80 on the
|
# Test: ":80" (the host caddy terminates TLS and forwards to scrabble:80 on the
|
||||||
# external `edge` network). Prod: a domain so caddy does its own ACME.
|
# external `edge` network). Prod: a domain so caddy does its own ACME.
|
||||||
|
|||||||
+10
-2
@@ -96,6 +96,12 @@ without it Docker's resolver handles `otelcol`, `gateway` and `api.telegram.org`
|
|||||||
| `VITE_TELEGRAM_GAME_CHANNEL_NAME` | variable | _(empty)_ | UI build-arg: the landing "Play in Telegram" link, the bot's game channel (e.g. `https://t.me/Erudit_Game`). |
|
| `VITE_TELEGRAM_GAME_CHANNEL_NAME` | variable | _(empty)_ | UI build-arg: the landing "Play in Telegram" link, the bot's game channel (e.g. `https://t.me/Erudit_Game`). |
|
||||||
| `VITE_VK_APP_LINK` | variable | _(empty)_ | UI build-arg: the landing "Play on VK" link, the VK Mini App (full URL, `https://vk.com/app<id>`). |
|
| `VITE_VK_APP_LINK` | variable | _(empty)_ | UI build-arg: the landing "Play on VK" link, the VK Mini App (full URL, `https://vk.com/app<id>`). |
|
||||||
| `VITE_GATEWAY_URL` | variable | _(empty)_ | UI build-arg: gateway origin; empty = same-origin (the usual single-origin deploy). |
|
| `VITE_GATEWAY_URL` | variable | _(empty)_ | UI build-arg: gateway origin; empty = same-origin (the usual single-origin deploy). |
|
||||||
|
| `SMTP_RELAY_HOST` | variable | _(empty)_ | Selectel SMTP relay host for confirm-code email. Empty leaves the backend on the log mailer (email disabled) — the contour still boots. One relay for every contour (limit 100 msgs / 5 min). |
|
||||||
|
| `SMTP_RELAY_PORT` | variable | `465` | Relay port. `465` selects implicit TLS; any other port uses STARTTLS. No client certificate is needed (the server cert is validated against the system roots). |
|
||||||
|
| `SMTP_RELAY_USER` | secret | _(empty)_ | Relay SMTP AUTH username. |
|
||||||
|
| `SMTP_RELAY_PASS` | secret | _(empty)_ | Relay SMTP AUTH password. |
|
||||||
|
| `SMTP_RELAY_FROM` | variable | `no-reply@localhost` | Sender address. **Must use the prod domain** (`no-reply@erudit-game.ru`) — Selectel only accepts the verified sender domain — so it is the same on every contour. |
|
||||||
|
| `PUBLIC_BASE_URL` | variable | _(empty)_ | Canonical public https origin for links in the email (the contour's own URL, e.g. `https://erudit-game.ru`). **Required by the backend whenever `SMTP_RELAY_HOST` is set** — it is never derived from a request Host header (anti-injection). |
|
||||||
|
|
||||||
The six `VITE_*` are **build-args** baked into the gateway and landing images at
|
The six `VITE_*` are **build-args** baked into the gateway and landing images at
|
||||||
build time (both targets share one UI build stage — keep the args identical so it is
|
build time (both targets share one UI build stage — keep the args identical so it is
|
||||||
@@ -198,11 +204,13 @@ players arrive.
|
|||||||
**`PROD_` Gitea set** (mirrors `TEST_`, mapped onto the unprefixed names above) — secrets:
|
**`PROD_` Gitea set** (mirrors `TEST_`, mapped onto the unprefixed names above) — secrets:
|
||||||
`PROD_{POSTGRES_PASSWORD, GM_BASICAUTH_HASH, GRAFANA_ADMIN_PASSWORD, TELEGRAM_BOT_TOKEN,
|
`PROD_{POSTGRES_PASSWORD, GM_BASICAUTH_HASH, GRAFANA_ADMIN_PASSWORD, TELEGRAM_BOT_TOKEN,
|
||||||
TELEGRAM_PROMO_BOT_TOKEN, EXPORT_SIGN_KEY, REGISTRY_PASSWORD, SSH_KEY, SSH_KNOWN_HOSTS, BOTLINK_CA,
|
TELEGRAM_PROMO_BOT_TOKEN, EXPORT_SIGN_KEY, REGISTRY_PASSWORD, SSH_KEY, SSH_KNOWN_HOSTS, BOTLINK_CA,
|
||||||
BOTLINK_GATEWAY_CERT, BOTLINK_GATEWAY_KEY, BOTLINK_BOT_CERT, BOTLINK_BOT_KEY}`; variables:
|
BOTLINK_GATEWAY_CERT, BOTLINK_GATEWAY_KEY, BOTLINK_BOT_CERT, BOTLINK_BOT_KEY,
|
||||||
|
SMTP_RELAY_USER, SMTP_RELAY_PASS}`; variables:
|
||||||
`PROD_{REGISTRY_USER, MAIN_HOST, TG_HOST, CADDY_SITE_ADDRESS, GM_BASICAUTH_USER,
|
`PROD_{REGISTRY_USER, MAIN_HOST, TG_HOST, CADDY_SITE_ADDRESS, GM_BASICAUTH_USER,
|
||||||
GRAFANA_ROOT_URL, LOG_LEVEL, DICT_VERSION, TELEGRAM_MINIAPP_URL, TELEGRAM_GAME_CHANNEL_ID,
|
GRAFANA_ROOT_URL, LOG_LEVEL, DICT_VERSION, TELEGRAM_MINIAPP_URL, TELEGRAM_GAME_CHANNEL_ID,
|
||||||
TELEGRAM_CHAT_ID, TELEGRAM_BOT_USERNAME, VITE_TELEGRAM_BOT_ID, VITE_TELEGRAM_LINK,
|
TELEGRAM_CHAT_ID, TELEGRAM_BOT_USERNAME, VITE_TELEGRAM_BOT_ID, VITE_TELEGRAM_LINK,
|
||||||
VITE_TELEGRAM_GAME_CHANNEL_NAME, VITE_VK_APP_LINK}`.
|
VITE_TELEGRAM_GAME_CHANNEL_NAME, VITE_VK_APP_LINK,
|
||||||
|
SMTP_RELAY_HOST, SMTP_RELAY_PORT, SMTP_RELAY_FROM, PUBLIC_BASE_URL}`.
|
||||||
|
|
||||||
## Host-side setup (outside this repo)
|
## Host-side setup (outside this repo)
|
||||||
|
|
||||||
|
|||||||
@@ -136,6 +136,18 @@ services:
|
|||||||
# GOMAXPROCS matches the CPU limit below so the Go scheduler aligns with the
|
# GOMAXPROCS matches the CPU limit below so the Go scheduler aligns with the
|
||||||
# cgroup quota (the runtime otherwise sees all of the host's cores).
|
# cgroup quota (the runtime otherwise sees all of the host's cores).
|
||||||
GOMAXPROCS: "2"
|
GOMAXPROCS: "2"
|
||||||
|
# Transactional email (confirm-codes) via the shared Selectel relay. An empty
|
||||||
|
# host makes the backend log codes instead of sending them (dev default). Port
|
||||||
|
# 465 selects implicit TLS; any other port uses STARTTLS. The From uses the prod
|
||||||
|
# domain (Selectel only accepts the verified sender domain), so it is the same on
|
||||||
|
# every contour. PUBLIC_BASE_URL is the canonical origin for links in the email
|
||||||
|
# (never a request Host header) — required whenever the relay host is set.
|
||||||
|
BACKEND_SMTP_HOST: ${SMTP_RELAY_HOST:-}
|
||||||
|
BACKEND_SMTP_PORT: ${SMTP_RELAY_PORT:-465}
|
||||||
|
BACKEND_SMTP_USERNAME: ${SMTP_RELAY_USER:-}
|
||||||
|
BACKEND_SMTP_PASSWORD: ${SMTP_RELAY_PASS:-}
|
||||||
|
BACKEND_SMTP_FROM: ${SMTP_RELAY_FROM:-no-reply@localhost}
|
||||||
|
BACKEND_PUBLIC_BASE_URL: ${PUBLIC_BASE_URL:-}
|
||||||
# The dictionary lives on a named volume seeded from the image on first boot
|
# The dictionary lives on a named volume seeded from the image on first boot
|
||||||
# (the image's /opt/dawg is owned by the nonroot UID, which the fresh volume
|
# (the image's /opt/dawg is owned by the nonroot UID, which the fresh volume
|
||||||
# inherits). The admin console writes new version subdirectories here, and the
|
# inherits). The admin console writes new version subdirectories here, and the
|
||||||
|
|||||||
Reference in New Issue
Block a user