Corrects six documentation files to match the actual deployed pipeline behavior and align test/prod approaches where they share the same code. prod-env/02-godaddy-credentials.md - Step 1: correct secret file from .env.secrets.shared to .env.secrets.swag; add clarifying note that .env.secrets.shared holds AppRole/DB secrets and must not be used for GoDaddy credentials. - Step 4: document that GoDaddy A records are now managed automatically by the pipeline's 'Update DNS Records' step via the GoDaddy API; reference the Gitea variable PROD_FLOATING_IP that must be set once. prod-env/08-deploy-pipeline-update.md - Add Step 2 documenting the new 'Update DNS Records' pipeline step (GoDaddy API, idempotent check-before-update, requires jq and vars.PROD_FLOATING_IP). - Renumber subsequent steps 3-8 to accommodate the new step. - Fix DB hostnames in Step 7 (Run Database Init Scripts) from iklimco_postgresql/iklimco_mongodb to postgresql/mongodb, matching how Swarm overlay DNS resolves service names inside iklimco-net. - Update context block: correct DB hostname description, replace outdated storagebox path note with env-var approach, list new steps. - Update final step order to 24 steps including the DNS step and Release Deploy Lock; mark Wait for etcd as NEW. prod-env/09-verify.md - Insert check #2 for the precipitation image directory (/mnt/storagebox/precipitation/images) and iklimco_image-data volume bind mount, mirroring the equivalent check in test-env/08-verify.md. - Renumber all subsequent checks (3-12) to maintain sequential ordering. test-env/03-infra-stack-changes.md - Update SWAG service volume snippet: replace hardcoded paths (swag-vl:/config, /opt/iklimco/swag/dns-conf, /opt/iklimco/swag/site-confs) with env-var forms (${SWAG_CONFIG_DIR:-swag-vl}, ${SWAG_DNS_CONF_DIR:-...}, ${SWAG_SITE_CONFS_DIR:-...}) to match docker-stack-infra.yml. - Update cert-reloader volume snippet: replace swag-vl and /opt/iklimco/ssl with ${SWAG_CONFIG_DIR:-swag-vl} and ${SWAG_CERT_DIR:-/opt/iklimco/ssl}, enabling StorageBox override in prod without changing the base file. test-env/04-swag-nginx-configs.md - Replace RESTRICTED_IP_1/RESTRICTED_IP_2 individual env vars with RESTRICTED_IPS (comma-separated CIDR list) in the required-vars section, matching env-test/.env and the actual pipeline. - Update all three IP-restricted template examples (apigw, rabbitmq, grafana) from allow ${RESTRICTED_IP_1}; allow ${RESTRICTED_IP_2}; to ${RESTRICTED_IPS_BLOCK}, matching the actual .conf.tpl files in the repo. - Rewrite the deploy step section to match the real pipeline: docker run alpine for file writing, RESTRICTED_IPS_BLOCK generation via sed, and envsubst with explicit SWAG_VARS filter to protect nginx $upstream_* vars. test-env/07-deploy-pipeline-update.md - Step 2 (Prepare SWAG Directories): replace sudo-tee approach with the actual docker-run-alpine method used in deploy-test.yml; add nginx reload block; update notes to reflect RESTRICTED_IPS_BLOCK generation. - Step 4 (Re-order): correct step numbering to match actual pipeline (21 steps); mark 'Wait for etcd' as already present in pipeline rather than a new addition; add Bootstrap Vault TLS Placeholder which was missing from the documented order.
174 lines
7.3 KiB
Markdown
174 lines
7.3 KiB
Markdown
# 07 — Deploy Pipeline Update (Test)
|
||
|
||
## Context
|
||
- **File:** `.gitea/workflows/deploy-test.yml`
|
||
- Changes:
|
||
1. Remove manual `scp STAR.iklim.co.full.crt` steps (SWAG now owns cert lifecycle).
|
||
2. Add SWAG host directories preparation (dns-conf, nginx site-confs).
|
||
3. Add cert bootstrap step: on first deploy, wait for SWAG to obtain cert, then copy
|
||
to `/opt/iklimco/ssl/` so Vault can start.
|
||
4. Ensure `GODADDY_KEY` and `GODADDY_SECRET` are available from `.env.secrets.swag`.
|
||
|
||
## Step 1 — Update `Initialize Servers` step
|
||
|
||
**Remove** the two `scp` lines that copy the TLS cert files:
|
||
|
||
```yaml
|
||
# DELETE these two lines from the "Initialize Servers" step:
|
||
scp -P 23 ${{ vars.STORAGEBOX_USER }}@${{ vars.STORAGEBOX_USER }}.your-storagebox.de:test/app/iklim.co/ssl/STAR.iklim.co.full.crt ./STAR.iklim.co.full.crt
|
||
scp -P 23 ${{ vars.STORAGEBOX_USER }}@${{ vars.STORAGEBOX_USER }}.your-storagebox.de:test/app/iklim.co/ssl/STAR.iklim.co_key.pem ./STAR.iklim.co_key.pem
|
||
```
|
||
|
||
Also remove any references to `STAR.iklim.co.full.crt` and `STAR.iklim.co_key.pem` in
|
||
the `Prepare Init Files` step's `sudo cp` commands:
|
||
|
||
```yaml
|
||
# DELETE or make conditional:
|
||
sudo cp STAR.iklim.co.full.crt STAR.iklim.co_key.pem /opt/iklimco/ssl/ 2>/dev/null || true
|
||
```
|
||
|
||
## Step 2 — Add `Prepare SWAG Directories` step
|
||
|
||
Insert this step **before** `Deploy Swarm Stack`:
|
||
|
||
```yaml
|
||
- name: Prepare SWAG Directories
|
||
run: |
|
||
set -a; . ./.env; . ./.env.secrets.swag; set +a
|
||
|
||
docker run --rm -v /opt/iklimco/swag:/output alpine \
|
||
mkdir -p /output/dns-conf /output/site-confs
|
||
|
||
envsubst < swag/dns-conf/godaddy.ini.tpl | docker run --rm -i \
|
||
-v /opt/iklimco/swag/dns-conf:/output \
|
||
alpine sh -c "cat > /output/godaddy.ini && chmod 600 /output/godaddy.ini"
|
||
echo "✅ godaddy.ini written"
|
||
|
||
# RESTRICTED_IPS → multi-line allow block (indented 8 spaces per nginx style)
|
||
export RESTRICTED_IPS_BLOCK="$(echo "$RESTRICTED_IPS" | tr ',' '\n' | sed 's|.*| allow &;|')"
|
||
|
||
# Explicit var list prevents nginx $upstream_* from being substituted by envsubst
|
||
SWAG_VARS='${API_SUBDOMAIN}${APIGW_SUBDOMAIN}${GRAFANA_SUBDOMAIN}${RABBITMQ_SUBDOMAIN}${RESTRICTED_IPS_BLOCK}'
|
||
for tpl in swag/site-confs/*.conf.tpl; do
|
||
fname=$(basename "${tpl%.tpl}")
|
||
envsubst "$SWAG_VARS" < "$tpl" | docker run --rm -i \
|
||
-v /opt/iklimco/swag/site-confs:/output \
|
||
alpine sh -c "cat > /output/${fname}"
|
||
echo "✅ ${fname}"
|
||
done
|
||
|
||
cat swag/site-confs/default.conf | docker run --rm -i \
|
||
-v /opt/iklimco/swag/site-confs:/output \
|
||
alpine sh -c "cat > /output/default.conf"
|
||
|
||
echo "✅ SWAG directories ready"
|
||
|
||
SWAG_CTR=$(docker ps -q -f name=iklimco_swag 2>/dev/null | head -1)
|
||
if [ -n "$SWAG_CTR" ]; then
|
||
docker exec "$SWAG_CTR" nginx -t && docker exec "$SWAG_CTR" nginx -s reload
|
||
echo "✅ SWAG nginx reloaded"
|
||
fi
|
||
working-directory: /workspace/iklim.co
|
||
```
|
||
|
||
> `GODADDY_KEY` ve `GODADDY_SECRET` `.env.secrets.swag` içinde olmalı (bkz. step 02).
|
||
> `API_SUBDOMAIN`, `APIGW_SUBDOMAIN` vb. `.env` içinde olmalı (bkz. step 04).
|
||
> Dosyalar `docker run alpine` ile yazılır — host'a `sudo` erişimi gerekmez.
|
||
> `RESTRICTED_IPS` comma-separated CIDR listesinden (`env-test/.env`) her satıra `allow` direktifi üretilir.
|
||
|
||
## Step 3 — Add `Bootstrap SWAG Certificate` step
|
||
|
||
Insert this step **after** `Deploy Swarm Stack` and **before** any step that depends on
|
||
Vault being accessible (e.g., `Provision Vault AppRole IDs`):
|
||
|
||
```yaml
|
||
- name: Bootstrap SWAG Certificate
|
||
run: |
|
||
echo "Waiting for SWAG container to start..."
|
||
SWAG_CTR=""
|
||
for i in $(seq 1 24); do
|
||
SWAG_CTR=$(docker ps -q -f name=iklimco_swag 2>/dev/null | head -1)
|
||
[ -n "$SWAG_CTR" ] && break
|
||
sleep 10
|
||
done
|
||
|
||
if [ -z "$SWAG_CTR" ]; then
|
||
echo "❌ SWAG container did not start in time"
|
||
exit 1
|
||
fi
|
||
|
||
CERT_PATH="/config/etc/letsencrypt/live/iklim.co/fullchain.pem"
|
||
echo "Waiting for SWAG to obtain Let's Encrypt cert (up to 10 min)..."
|
||
for i in $(seq 1 20); do
|
||
if docker exec "$SWAG_CTR" test -f "$CERT_PATH" 2>/dev/null; then
|
||
echo "✅ Cert obtained by SWAG"
|
||
break
|
||
fi
|
||
echo " attempt $i/20 — waiting 30s..."
|
||
sleep 30
|
||
done
|
||
|
||
if ! docker exec "$SWAG_CTR" test -f "$CERT_PATH" 2>/dev/null; then
|
||
echo "❌ SWAG did not obtain cert in time. Check logs:"
|
||
docker service logs iklimco_swag --tail 50
|
||
exit 1
|
||
fi
|
||
|
||
# Copy cert to host for Vault bootstrap
|
||
sudo mkdir -p /opt/iklimco/ssl
|
||
docker exec "$SWAG_CTR" cat "$CERT_PATH" | \
|
||
sudo tee /opt/iklimco/ssl/STAR.iklim.co.full.crt > /dev/null
|
||
docker exec "$SWAG_CTR" cat "/config/etc/letsencrypt/live/iklim.co/privkey.pem" | \
|
||
sudo tee /opt/iklimco/ssl/STAR.iklim.co_key.pem > /dev/null
|
||
echo "✅ Cert bootstrapped to /opt/iklimco/ssl/"
|
||
working-directory: /workspace/iklim.co
|
||
```
|
||
|
||
> **First deploy only:** SWAG contacts Let's Encrypt via GoDaddy DNS challenge.
|
||
> This step waits up to 10 minutes. On subsequent deploys the cert is already in
|
||
> `swag-vl` (persisted volume) and SWAG starts immediately — wait loop exits fast.
|
||
|
||
## Step 4 — Re-order steps
|
||
|
||
Final step order in the pipeline:
|
||
|
||
1. Checkout Branch
|
||
2. Prepare Folders
|
||
3. Set up SSH Key
|
||
4. Update Apt / Install Tools
|
||
5. Fetch Service Secret Files
|
||
6. Initialize Docker Swarm
|
||
7. Initialize Servers
|
||
8. Upload Updated Secrets to Storagebox
|
||
9. Provision Vault AppRole IDs and Docker Secrets
|
||
10. Upload Updated Env to Storagebox
|
||
11. Prepare Init Files ← `sudo cp STAR.iklim.co.*.crt` lines removed
|
||
12. Stop Docker Compose Services
|
||
13. Docker Login to Harbor
|
||
14. **Prepare SWAG Directories** ← NEW
|
||
15. Bootstrap Vault TLS Placeholder
|
||
16. Deploy Swarm Stack
|
||
17. **Wait for etcd** ← zaten pipeline'da mevcut; etcd health endpoint'i kontrol eder
|
||
18. **Run APISIX Init** ← NEW (`SPRING_PROFILES_ACTIVE=test`)
|
||
19. **Bootstrap SWAG Certificate** ← NEW
|
||
20. **Run Database Init Scripts** ← NEW
|
||
21. Review Environment
|
||
|
||
> Steps 8 (Provision Vault) runs before SWAG because it creates Docker secrets and
|
||
> AppRole IDs — Vault must be reachable for this. On re-deploys, Vault is already
|
||
> running with the previous cert. On first deploy, step 16 handles the cert wait before
|
||
> any further Vault interaction is needed post-deploy.
|
||
>
|
||
> If Vault provisioning (step 8) fails on first deploy because Vault has no cert yet,
|
||
> move step 16 before step 8. Adjust based on observed behavior.
|
||
|
||
## Notes
|
||
- `.env` must contain the subdomain env vars added in step 04. Add them to storagebox
|
||
`test/secrets/iklim.co/.env` before the first deploy.
|
||
- `RESTRICTED_IP_1` and `RESTRICTED_IP_2` are hardcoded in the pipeline step above.
|
||
Move to `.env` if they change often.
|
||
- Precipitation service expects its image-data bind mount at
|
||
`/mnt/storagebox/precipitation/images`. This directory is provisioned by the
|
||
test Ansible bootstrap through `storagebox_managed_directories`; do not rely on
|
||
the deploy pipeline to create it.
|