# 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: ```yaml 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-vl:/config - /opt/iklimco/swag/dns-conf:/config/dns-conf:ro - /opt/iklimco/swag/proxy-confs:/config/nginx/proxy-confs:ro - /opt/iklimco/swag/site-confs:/config/nginx/site-confs:ro 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: ```yaml cert-reloader: image: docker:27-cli volumes: - swag-vl:/swag-config:ro - /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 sleep 3600 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.txt" docker service update --force iklimco_vault LAST_HASH="$$CURR" echo "[cert-reloader] done" fi fi 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**: ```yaml # 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**: ```yaml # 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 ```yaml # DELETE from apisix-dashboard: ports: - target: 9000 published: 9000 protocol: tcp mode: host ``` ## Step 6 — Remove `rabbitmq` published ports ```yaml # 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 ```yaml # DELETE from prometheus: ports: - target: 9090 published: 9090 protocol: tcp mode: host ``` ## Step 8 — Remove `grafana` published port ```yaml # 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: ```yaml swag-vl: labels: project: co.iklim ``` ## Verification After deploy: ```bash docker service ls --filter label=project=co.iklim ``` Confirm `iklimco_swag` and `iklimco_cert-reloader` appear in the list. ```bash docker service ps iklimco_swag docker service ps iklimco_cert-reloader ``` Both should show `Running`.