fix(deploy): rework prod artifacts to match the actual Hetzner box
Server recon (read-only SSH) showed the box already runs ~8 apps behind a host-level nginx, with Gitea + an Actions runner. The host-networking design collided with contentra on port 3001. - docker-compose.prod.yml: bridge networking + per-app network, house style; api/web/postgres/redis publish to 127.0.0.1 on verified-free ports (4000/4001/5440/6390); only the generator keeps host networking (no listening port, needs the host namespace for runner-port probing). - Drop the Traefik config; the box uses a host nginx. Add a ready nginx vhost in infra/nginx/buildmymcpserver.conf (listen 80, Cloudflare TLS). - Add .gitea/workflows/deploy.yml mirroring the buildmydiscord pipeline. - Narrow the generated-MCP port range to 4400-4900 (clear of screencraft on 4321). - .env.production.example + DEPLOY.md rewritten for buildmymcpserver.com and the real topology. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
68
infra/nginx/buildmymcpserver.conf
Normal file
68
infra/nginx/buildmymcpserver.conf
Normal file
@@ -0,0 +1,68 @@
|
||||
# nginx vhost for buildmymcpserver.com — install on the host nginx:
|
||||
# scp this to /etc/nginx/sites-available/buildmymcpserver
|
||||
# ln -s /etc/nginx/sites-available/buildmymcpserver /etc/nginx/sites-enabled/
|
||||
# nginx -t && systemctl reload nginx
|
||||
#
|
||||
# TLS is terminated by Cloudflare (proxied DNS records). The origin serves
|
||||
# plain HTTP on :80 — same pattern as the other Cloudflare-fronted apps here.
|
||||
# Set the Cloudflare SSL/TLS mode to "Full" for this zone.
|
||||
|
||||
# --- Web app: buildmymcpserver.com ---
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name buildmymcpserver.com www.buildmymcpserver.com;
|
||||
|
||||
client_max_body_size 12M;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:4001;
|
||||
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 120s;
|
||||
}
|
||||
}
|
||||
|
||||
# --- Control plane API: api.buildmymcpserver.com ---
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name api.buildmymcpserver.com;
|
||||
|
||||
client_max_body_size 12M;
|
||||
|
||||
# Build-log WebSocket stream (/v1/builds/:id/stream) — needs the upgrade
|
||||
# headers and a long read timeout; buffering off so frames are not held.
|
||||
location /v1/builds/ {
|
||||
proxy_pass http://127.0.0.1:4000;
|
||||
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_buffering off;
|
||||
proxy_cache off;
|
||||
proxy_read_timeout 600s;
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:4000;
|
||||
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 120s;
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
# Copy to infra/traefik/.env — used only by docker-compose.traefik.yml.
|
||||
# Email Let's Encrypt uses for expiry notices.
|
||||
ACME_EMAIL=marco.frangiskatos@gmail.com
|
||||
@@ -1,37 +0,0 @@
|
||||
# OPTIONAL reverse proxy — use ONLY if the server has no existing proxy.
|
||||
#
|
||||
# !! DANGER: this binds host ports 80 and 443. If another reverse proxy
|
||||
# !! (nginx / Caddy / another Traefik) is already serving the other live apps
|
||||
# !! on this box, starting this WILL conflict and can take those apps offline.
|
||||
# !! Check first: sudo ss -ltnp '( sport = :80 or sport = :443 )'
|
||||
# !! If something already listens there, DO NOT run this. Instead add a vhost
|
||||
# !! to the existing proxy pointing at 127.0.0.1:3001 (web) and 127.0.0.1:4000
|
||||
# !! (api). See DEPLOY.md.
|
||||
#
|
||||
# Run with:
|
||||
# docker compose --env-file .env -f docker-compose.traefik.yml up -d
|
||||
|
||||
name: buildmymcp-traefik
|
||||
|
||||
services:
|
||||
traefik:
|
||||
image: traefik:v3.2
|
||||
restart: unless-stopped
|
||||
network_mode: host
|
||||
command:
|
||||
- --providers.file.filename=/etc/traefik/dynamic.yml
|
||||
- --providers.file.watch=true
|
||||
- --entrypoints.web.address=:80
|
||||
- --entrypoints.websecure.address=:443
|
||||
- --entrypoints.web.http.redirections.entrypoint.to=websecure
|
||||
- --entrypoints.web.http.redirections.entrypoint.scheme=https
|
||||
- --certificatesresolvers.le.acme.httpchallenge=true
|
||||
- --certificatesresolvers.le.acme.httpchallenge.entrypoint=web
|
||||
- --certificatesresolvers.le.acme.email=${ACME_EMAIL:?set ACME_EMAIL in infra/traefik/.env}
|
||||
- --certificatesresolvers.le.acme.storage=/letsencrypt/acme.json
|
||||
volumes:
|
||||
- ./dynamic.yml:/etc/traefik/dynamic.yml:ro
|
||||
- bmm_letsencrypt:/letsencrypt
|
||||
|
||||
volumes:
|
||||
bmm_letsencrypt:
|
||||
@@ -1,32 +0,0 @@
|
||||
# Traefik file-provider routes. The app stack uses host networking, so it has
|
||||
# no Docker labels for Traefik to discover — routes are declared statically here.
|
||||
# Targets are loopback ports owned by docker-compose.prod.yml.
|
||||
|
||||
http:
|
||||
routers:
|
||||
bmm-web:
|
||||
rule: "Host(`buildmymcp.com`) || Host(`www.buildmymcp.com`)"
|
||||
entryPoints:
|
||||
- websecure
|
||||
service: bmm-web
|
||||
tls:
|
||||
certResolver: le
|
||||
|
||||
bmm-api:
|
||||
rule: "Host(`api.buildmymcp.com`)"
|
||||
entryPoints:
|
||||
- websecure
|
||||
service: bmm-api
|
||||
tls:
|
||||
certResolver: le
|
||||
|
||||
services:
|
||||
bmm-web:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: "http://127.0.0.1:3001"
|
||||
|
||||
bmm-api:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: "http://127.0.0.1:4000"
|
||||
Reference in New Issue
Block a user