Environment_Infrastructure/roadmap/test-env/03-infra-stack-changes.md
Murat ÖZDEMİR fd6a0b4f46 docs: fix roadmap inconsistencies between test-env and prod-env
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.
2026-05-16 16:52:48 +03:00

6.1 KiB

03 — docker-stack-infra.yml Changes (Test)

Context

  • File: docker-stack-infra.yml (repo root)
  • Goal: Add SWAG as TLS-terminating reverse proxy; remove all published ports from internal services (they become reachable only via SWAG through the iklimco-net overlay network); remove Vault's external port entirely.

Changes Summary

Service Before After
swag does not exist add: ports 80+443, manager-pinned
cert-reloader does not exist add: manager-pinned, Docker socket
vault publishes 8200 no published port
apisix publishes 8080, 8443, 9180 no published ports
rabbitmq publishes 5672, 15672, 61613, 15674 no published ports
prometheus publishes 9090 no published port
grafana publishes 3000 no published port
apisix-dashboard publishes 9000 no published port

RabbitMQ STOMP note: Ports 61613 (STOMP) and 15674 (WebSocket STOMP) are removed because APISIX already proxies WebSocket STOMP to RabbitMQ via the overlay network. Verify that APISIX has a stream/WebSocket route for STOMP before removing these if external clients connect to STOMP directly (not via APISIX).

Step 1 — Add swag service

Add after the apisix-dashboard service block:

  swag:
    image: lscr.io/linuxserver/swag:latest
    cap_add:
      - NET_ADMIN
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Europe/Istanbul
      - URL=iklim.co
      - SUBDOMAINS=wildcard
      - VALIDATION=dns
      - DNSPLUGIN=godaddy
      - ONLY_SUBDOMAINS=false
      - EMAIL=muratozdemir@tarla.io
      - DNSPROPAGATION=90
    volumes:
      - ${SWAG_CONFIG_DIR:-swag-vl}:/config
      - ${SWAG_DNS_CONF_DIR:-/opt/iklimco/swag/dns-conf}:/config/dns-conf
      - ${SWAG_SITE_CONFS_DIR:-/opt/iklimco/swag/site-confs}:/config/nginx/site-confs
    ports:
      - target: 80
        published: 80
        protocol: tcp
        mode: host
      - target: 443
        published: 443
        protocol: tcp
        mode: host
    deploy:
      mode: replicated
      replicas: 1
      placement:
        constraints:
          - node.role == manager
      restart_policy:
        condition: on-failure
        delay: 5s
    labels:
      project: co.iklim

Step 2 — Add cert-reloader service

Add after the swag service block:

  cert-reloader:
    image: docker:27-cli
    volumes:
      - ${SWAG_CONFIG_DIR:-swag-vl}:/swag-config:ro
      - ${SWAG_CERT_DIR:-/opt/iklimco/ssl}:/host-ssl
      - /var/run/docker.sock:/var/run/docker.sock
    entrypoint: ["/bin/sh", "-c"]
    command:
      - |
        CERT_DIR=/swag-config/etc/letsencrypt/live/iklim.co
        HOST_DIR=/host-ssl
        LAST_HASH=""
        echo "[cert-reloader] started"
        while true; do
          if [ -f "$$CERT_DIR/fullchain.pem" ]; then
            CURR=$$(md5sum "$$CERT_DIR/fullchain.pem" | cut -d' ' -f1)
            if [ "$$CURR" != "$$LAST_HASH" ]; then
              echo "[cert-reloader] cert changed — copying and reloading Vault"
              cp "$$CERT_DIR/fullchain.pem" "$$HOST_DIR/STAR.iklim.co.full.crt"
              cp "$$CERT_DIR/privkey.pem"   "$$HOST_DIR/STAR.iklim.co_key.pem"
              docker service update --force iklimco_vault
              LAST_HASH="$$CURR"
              echo "[cert-reloader] done"
            fi
          fi
          sleep 3600
        done
    deploy:
      mode: replicated
      replicas: 1
      placement:
        constraints:
          - node.role == manager
      restart_policy:
        condition: on-failure
        delay: 10s
    labels:
      project: co.iklim

$$ is required in Docker Swarm YAML to escape $ and prevent host-side variable expansion.

Step 3 — Remove vault published port

Find the vault service ports: block and delete it entirely:

# DELETE this entire block from vault service:
    ports:
      - target: 8200
        published: 8200
        protocol: tcp
        mode: host

Vault remains reachable within iklimco-net via the overlay alias vault.iklim.co:8200. The VAULT_LOCAL_CONFIG api_addr and networks.default.aliases entries stay unchanged.

Step 4 — Remove apisix published ports

Find the apisix service ports: block and delete it entirely:

# DELETE this entire block from apisix service:
    ports:
      - target: 9080
        published: 8080
        protocol: tcp
        mode: host
      - target: 9443
        published: 8443
        protocol: tcp
        mode: host
      - target: 9180
        published: 9180
        protocol: tcp
        mode: host

APISIX admin API (9180) access: use docker exec or SSH tunnel. APISIX is reachable from SWAG via http://apisix:9080 on the overlay network.

Step 5 — Remove apisix-dashboard published port

# DELETE from apisix-dashboard:
    ports:
      - target: 9000
        published: 9000
        protocol: tcp
        mode: host

Step 6 — Remove rabbitmq published ports

# DELETE from rabbitmq:
    ports:
      - target: 5672
        published: 5672
        protocol: tcp
        mode: host
      - target: 15672
        published: 15672
        protocol: tcp
        mode: host
      - target: 61613
        published: 61613
        protocol: tcp
        mode: host
      - target: 15674
        published: 15674
        protocol: tcp
        mode: host

Step 7 — Remove prometheus published port

# DELETE from prometheus:
    ports:
      - target: 9090
        published: 9090
        protocol: tcp
        mode: host

Step 8 — Remove grafana published port

# DELETE from grafana:
    ports:
      - target: 3000
        published: 3000
        protocol: tcp
        mode: host

Step 9 — Add swag-vl volume

In the volumes: section at the bottom of the file, add:

  swag-vl:
    labels:
      project: co.iklim

Verification

After deploy:

docker service ls --filter label=project=co.iklim

Confirm iklimco_swag and iklimco_cert-reloader appear in the list.

docker service ps iklimco_swag
docker service ps iklimco_cert-reloader

Both should show Running.