diff --git a/.gitea/workflows/prod-deploy.yaml b/.gitea/workflows/prod-deploy.yaml index e851e5f..874f8c1 100644 --- a/.gitea/workflows/prod-deploy.yaml +++ b/.gitea/workflows/prod-deploy.yaml @@ -141,6 +141,7 @@ jobs: # PROD_PGBACKREST_ARCHIVE_MODE=on activates it (deploy/README.md, arming). PGBACKREST_ARCHIVE_MODE: ${{ vars.PROD_PGBACKREST_ARCHIVE_MODE }} PGBACKREST_S3_ENDPOINT: ${{ vars.PROD_PGBACKREST_S3_ENDPOINT }} + PGBACKREST_S3_PORT: ${{ vars.PROD_PGBACKREST_S3_PORT }} PGBACKREST_S3_BUCKET: ${{ vars.PROD_PGBACKREST_S3_BUCKET }} PGBACKREST_S3_REGION: ${{ vars.PROD_PGBACKREST_S3_REGION }} PGBACKREST_S3_KEY: ${{ secrets.PROD_PGBACKREST_S3_KEY }} diff --git a/.gitea/workflows/prod-rollback.yaml b/.gitea/workflows/prod-rollback.yaml index d846b7e..19ca854 100644 --- a/.gitea/workflows/prod-rollback.yaml +++ b/.gitea/workflows/prod-rollback.yaml @@ -81,6 +81,7 @@ jobs: # silently disarm WAL archiving (PGBACKREST_ARCHIVE_MODE would fall back to off). PGBACKREST_ARCHIVE_MODE: ${{ vars.PROD_PGBACKREST_ARCHIVE_MODE }} PGBACKREST_S3_ENDPOINT: ${{ vars.PROD_PGBACKREST_S3_ENDPOINT }} + PGBACKREST_S3_PORT: ${{ vars.PROD_PGBACKREST_S3_PORT }} PGBACKREST_S3_BUCKET: ${{ vars.PROD_PGBACKREST_S3_BUCKET }} PGBACKREST_S3_REGION: ${{ vars.PROD_PGBACKREST_S3_REGION }} PGBACKREST_S3_KEY: ${{ secrets.PROD_PGBACKREST_S3_KEY }} diff --git a/deploy/.env.example b/deploy/.env.example index c757459..96ccd77 100644 --- a/deploy/.env.example +++ b/deploy/.env.example @@ -21,7 +21,8 @@ POSTGRES_PASSWORD=change-me # required # recovery). Gitea: PROD_PGBACKREST_* — endpoint/bucket/region/archive-mode are variables, # the two S3 keys + the cipher passphrase are secrets. PGBACKREST_ARCHIVE_MODE=off # on = archiving active (arm only after the stanza exists) -PGBACKREST_S3_ENDPOINT= # e.g. s3.ru-1.storage.selcloud.ru (Selectel S3, path-style addressing) +PGBACKREST_S3_ENDPOINT= # S3 HOST ONLY — no https://, no port, no bucket (e.g. s3.ru-1.storage.selcloud.ru); path-style addressing +PGBACKREST_S3_PORT= # optional; default 443 — set only if the provider uses a non-standard S3 port PGBACKREST_S3_BUCKET= # bucket name; lowercase, no dots/underscores PGBACKREST_S3_REGION= # e.g. ru-1 PGBACKREST_S3_KEY= # secret: S3 access key id diff --git a/deploy/README.md b/deploy/README.md index 93e4733..f1dc886 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -267,9 +267,12 @@ is a ~10 MB, sub-second job on the 2 vCPU host. Revisit both if traffic grows ~1 1. **Owner (Selectel + Gitea):** create an S3 bucket (name **lowercase, no dots/underscores**) and an S3 access key/secret; pick a repository **cipher passphrase** and store it **apart from the S3 keys** (losing it makes the archive unrecoverable). Set the Gitea `PROD_` set — - variables `PROD_PGBACKREST_S3_ENDPOINT` / `_S3_BUCKET` / `_S3_REGION` and - `PROD_PGBACKREST_ARCHIVE_MODE=on`; secrets `PROD_PGBACKREST_S3_KEY` / `_S3_KEY_SECRET` / - `_CIPHER_PASS`. + variables `PROD_PGBACKREST_S3_ENDPOINT` (the S3 **host only** — no `https://`, no port, no + bucket) / `_S3_BUCKET` / `_S3_REGION`, an optional `_S3_PORT` (default 443, set only for a + non-standard provider port), and `PROD_PGBACKREST_ARCHIVE_MODE=on`; secrets + `PROD_PGBACKREST_S3_KEY` (the S3 **access key**) / `_S3_KEY_SECRET` (its paired **secret + key**, shown once at creation) / `_CIPHER_PASS` (a fresh repository passphrase, e.g. + `openssl rand -base64 48`). 2. Promote `development → master`, tag, and run **prod-deploy**. The roll recreates postgres with `archive_mode=on` behind the maintenance page. (Archive pushes fail harmlessly for the minute until step 3 creates the repository — the WAL is retained, not lost.) @@ -331,8 +334,8 @@ variables: TELEGRAM_GAME_CHANNEL_ID, TELEGRAM_CHAT_ID, TELEGRAM_SUPPORT_CHAT_ID, TELEGRAM_BOT_USERNAME, VITE_TELEGRAM_BOT_ID, VITE_TELEGRAM_LINK, VITE_TELEGRAM_GAME_CHANNEL_NAME, SMTP_RELAY_FROM, PUBLIC_BASE_URL, SMTP_RELAY_ADMIN_FROM, ADMIN_EMAIL, SMTP_RELAY_SERVICE_FROM, SERVICE_EMAIL, -GF_SMTP_ENABLED, PGBACKREST_S3_ENDPOINT, PGBACKREST_S3_BUCKET, PGBACKREST_S3_REGION, -PGBACKREST_ARCHIVE_MODE}`. The test contour uses the same names under `TEST_`, minus the +GF_SMTP_ENABLED, PGBACKREST_S3_ENDPOINT, PGBACKREST_S3_PORT, PGBACKREST_S3_BUCKET, +PGBACKREST_S3_REGION, PGBACKREST_ARCHIVE_MODE}`. The test contour uses the same names under `TEST_`, minus the prod-only infra (`MAIN_HOST`/`TG_HOST`/`REGISTRY_*`/`SSH_*`/`BOTLINK_*` and the `PGBACKREST_*` PITR set, which is prod-only — the test contour never archives) and plus `TEST_AWG_CONF` (the bot's VPN egress). diff --git a/deploy/docker-compose.prod.yml b/deploy/docker-compose.prod.yml index 2aa393e..9cc94c2 100644 --- a/deploy/docker-compose.prod.yml +++ b/deploy/docker-compose.prod.yml @@ -61,6 +61,7 @@ services: PGBACKREST_REPO1_PATH: /pgbackrest PGBACKREST_REPO1_S3_URI_STYLE: path PGBACKREST_REPO1_S3_ENDPOINT: ${PGBACKREST_S3_ENDPOINT:-} + PGBACKREST_REPO1_S3_PORT: ${PGBACKREST_S3_PORT:-443} PGBACKREST_REPO1_S3_BUCKET: ${PGBACKREST_S3_BUCKET:-} PGBACKREST_REPO1_S3_REGION: ${PGBACKREST_S3_REGION:-} PGBACKREST_REPO1_S3_KEY: ${PGBACKREST_S3_KEY:-} diff --git a/deploy/write-prod-env.sh b/deploy/write-prod-env.sh index 5ce91cf..6899efb 100755 --- a/deploy/write-prod-env.sh +++ b/deploy/write-prod-env.sh @@ -79,6 +79,7 @@ export GATEWAY_ABUSE_BAN_ENABLED='true' # on (deploy/README.md). Empty repository values are harmless while the mode is off. export PGBACKREST_ARCHIVE_MODE='${PGBACKREST_ARCHIVE_MODE:-off}' export PGBACKREST_S3_ENDPOINT='$PGBACKREST_S3_ENDPOINT' +export PGBACKREST_S3_PORT='${PGBACKREST_S3_PORT:-443}' export PGBACKREST_S3_BUCKET='$PGBACKREST_S3_BUCKET' export PGBACKREST_S3_REGION='$PGBACKREST_S3_REGION' export PGBACKREST_S3_KEY='$PGBACKREST_S3_KEY'