fix: switch from nginx to Traefik for routing and SSL

Server uses Traefik (traefik-public network) with Cloudflare DNS
cert resolver. Nginx not needed. Add Traefik labels to app service,
connect to traefik-public + internal networks, remove nginx/certbot.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Vadym Samoilenko 2026-02-23 14:39:32 +00:00
parent 24b01bcba3
commit d34071f9f8
2 changed files with 28 additions and 68 deletions

View file

@ -11,9 +11,7 @@ PROJECT_DIR="/opt/03-business/Axil"
COMPOSE_FILE="$PROJECT_DIR/docker-compose.prod.yml"
ENV_FILE="$PROJECT_DIR/.env.production"
DEPLOY_CONFIG="$PROJECT_DIR/.deploy-config"
NGINX_SITE="axil-accountants"
NGINX_CONF="/etc/nginx/sites-available/$NGINX_SITE"
NGINX_ENABLED="/etc/nginx/sites-enabled/$NGINX_SITE"
# Routing: Traefik (traefik-public network) — no nginx needed
# ─── Colors ───────────────────────────────────────────────────────────────────
GREEN='\033[0;32m'
@ -273,75 +271,20 @@ run_migrations() {
}
# =============================================================================
# Phase 6 — Nginx setup (first run only)
# Phase 6 — Traefik registration (automatic via Docker labels)
# =============================================================================
setup_nginx() {
header "Phase 6 — Nginx setup"
header "Phase 6 — Traefik routing"
# Load domain from deploy config
if [ ! -f "$DEPLOY_CONFIG" ]; then
warn "Deploy config not found at $DEPLOY_CONFIG — skipping Nginx setup."
return
fi
# shellcheck disable=SC1090
source "$DEPLOY_CONFIG"
if [ -f "$NGINX_CONF" ]; then
log "Nginx config already exists at $NGINX_CONF — skipping creation."
else
log "Writing Nginx config for ${DOMAIN}..."
cat > "$NGINX_CONF" <<NGINX
server {
listen 80;
listen [::]:80;
server_name ${DOMAIN} www.${DOMAIN};
# Allow large file uploads (Payload CMS media)
client_max_body_size 50M;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
proxy_cache_bypass \$http_upgrade;
proxy_read_timeout 60s;
}
}
NGINX
# Enable the site
ln -sf "$NGINX_CONF" "$NGINX_ENABLED"
log "Nginx site enabled."
if [ -f "$DEPLOY_CONFIG" ]; then
# shellcheck disable=SC1090
source "$DEPLOY_CONFIG"
fi
# Start nginx if not running, otherwise reload
nginx -t
if systemctl is-active --quiet nginx; then
systemctl reload nginx
else
systemctl start nginx
fi
log "Nginx is running."
# SSL via Certbot
if certbot certificates 2>/dev/null | grep -q "Domains.*${DOMAIN}"; then
log "SSL certificate for ${DOMAIN} already exists — skipping Certbot."
else
log "Obtaining SSL certificate for ${DOMAIN} (and www.${DOMAIN})..."
certbot --nginx \
-d "${DOMAIN}" \
-d "www.${DOMAIN}" \
--non-interactive \
--agree-tos \
-m "${ADMIN_EMAIL}" \
--redirect
log "SSL certificate obtained. HTTP → HTTPS redirect enabled."
fi
log "Routing handled by Traefik via Docker labels."
log "SSL certificate will be issued automatically via Cloudflare DNS resolver."
info "Route: https://${DOMAIN:-axil.ai-impress.com} → axil-app-1:3000"
}
# =============================================================================

View file

@ -4,8 +4,17 @@ services:
context: .
target: runner
restart: always
ports:
- '127.0.0.1:3000:3000'
networks:
- traefik-public
- internal
labels:
- "traefik.enable=true"
- "traefik.http.routers.axil.entrypoints=websecure"
- "traefik.http.routers.axil.rule=Host(`axil.ai-impress.com`)"
- "traefik.http.routers.axil.tls.certresolver=cloudflare"
- "traefik.http.routers.axil.middlewares=security-headers@file"
- "traefik.http.services.axil.loadbalancer.server.port=3000"
- "traefik.docker.network=traefik-public"
env_file:
- .env.production
depends_on:
@ -15,6 +24,8 @@ services:
db:
image: postgres:17-alpine
restart: always
networks:
- internal
environment:
POSTGRES_USER: ${DB_USER:-axil}
POSTGRES_PASSWORD: ${DB_PASSWORD}
@ -27,5 +38,11 @@ services:
timeout: 5s
retries: 10
networks:
traefik-public:
external: true
internal:
driver: bridge
volumes:
pgdata: