Environment_Infrastructure/roadmap/test-env/04-swag-nginx-configs.md
Murat ÖZDEMİR f23835a30a docs(config): Update template file paths to use 'template/' subdirectory
Reflects a clearer organization for SWAG configuration templates across all roadmap and setup documentation. This standardizes references to template files by explicitly including the `template/` subdirectory, improving clarity and distinction from generated configuration files.
2026-05-23 14:43:04 +03:00

5.8 KiB

04 — SWAG Nginx Proxy Configs (Test)

Context

SWAG nginx auto-includes only site-confs/*.conf. All proxy config templates live in template/swag/site-confs/ in the repo and are rendered to /opt/iklimco/swag/site-confs/ on the host at deploy time.

Templates use ${VAR} placeholders processed with envsubst at deploy time.

Required env vars (in .env on storagebox test/secrets/iklim.co/.env)

API_SUBDOMAIN=api-test.iklim.co
APIGW_SUBDOMAIN=apigw-test.iklim.co
RABBITMQ_SUBDOMAIN=rabbitmq-test.iklim.co
GRAFANA_SUBDOMAIN=grafana-test.iklim.co
# Comma-separated list of allowed CIDRs for IP-restricted subdomains
RESTRICTED_IPS="78.187.87.109/32,95.70.151.248/32"

Files to create

template/swag/site-confs/default.conf

Default catch-all: HTTP→HTTPS redirect + 444 for unknown HTTPS hosts.

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2 default_server;
    listen [::]:443 ssl http2 default_server;
    server_name _;
    include /config/nginx/ssl.conf;
    return 444;
}

template/swag/site-confs/api.conf.tpl

Public API gateway — no IP restriction.

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name ${API_SUBDOMAIN};

    include /config/nginx/ssl.conf;
    include /config/nginx/resolver.conf;

    client_max_body_size 50m;

    location / {
        include /config/nginx/proxy.conf;
        include /config/nginx/resolver.conf;
        set $upstream_app apisix;
        set $upstream_port 9080;
        set $upstream_proto http;
        proxy_pass $upstream_proto://$upstream_app:$upstream_port;
    }
}

template/swag/site-confs/apigw.conf.tpl

APISIX Dashboard — IP restricted.

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name ${APIGW_SUBDOMAIN};

    include /config/nginx/ssl.conf;
    include /config/nginx/resolver.conf;

    client_max_body_size 0;

    location / {
${RESTRICTED_IPS_BLOCK}
        deny all;

        include /config/nginx/proxy.conf;
        include /config/nginx/resolver.conf;
        set $upstream_app apisix-dashboard;
        set $upstream_port 9000;
        set $upstream_proto http;
        proxy_pass $upstream_proto://$upstream_app:$upstream_port;
    }
}

${RESTRICTED_IPS_BLOCK} is generated at deploy time from RESTRICTED_IPS (comma-separated CIDRs) as multi-line allow directives with /32 suffix. See 07-deploy-pipeline-update.md for the pipeline step.

template/swag/site-confs/rabbitmq.conf.tpl

RabbitMQ Management UI — IP restricted.

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name ${RABBITMQ_SUBDOMAIN};

    include /config/nginx/ssl.conf;
    include /config/nginx/resolver.conf;

    client_max_body_size 0;

    location / {
${RESTRICTED_IPS_BLOCK}
        deny all;

        include /config/nginx/proxy.conf;
        include /config/nginx/resolver.conf;
        set $upstream_app rabbitmq;
        set $upstream_port 15672;
        set $upstream_proto http;
        proxy_pass $upstream_proto://$upstream_app:$upstream_port;
    }
}

template/swag/site-confs/grafana.conf.tpl

Grafana — IP restricted.

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name ${GRAFANA_SUBDOMAIN};

    include /config/nginx/ssl.conf;
    include /config/nginx/resolver.conf;

    client_max_body_size 0;

    location / {
${RESTRICTED_IPS_BLOCK}
        deny all;

        include /config/nginx/proxy.conf;
        include /config/nginx/resolver.conf;
        set $upstream_app grafana;
        set $upstream_port 3000;
        set $upstream_proto http;
        proxy_pass $upstream_proto://$upstream_app:$upstream_port;
    }
}

Deploy step (handled by pipeline — see 07-deploy-pipeline-update.md)

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 < template/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"

# 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 template/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 template/swag/site-confs/default.conf | docker run --rm -i \
  -v /opt/iklimco/swag/site-confs:/output \
  alpine sh -c "cat > /output/default.conf"

Verification

After deploy, check SWAG nginx config is valid:

docker exec $(docker ps -q -f name=iklimco_swag) nginx -t

Check subdomains resolve (from outside the server):

curl -sk https://api-test.iklim.co/health    # expects APISIX response
curl -sk https://grafana-test.iklim.co       # expects 403 Forbidden (wrong IP)

Notes

  • include /config/nginx/resolver.conf enables dynamic upstream resolution via Docker DNS — required for overlay service names like apisix, grafana, etc.
  • SWAG's proxy.conf already sets X-Real-IP, X-Forwarded-For, X-Forwarded-Proto and WebSocket upgrade headers. No manual addition needed.
  • *.iklim.co cert covers both api.iklim.co and api-test.iklim.co subdomains — both test and prod servers can independently obtain and use it.