From 8cabe7d362978e8c46a92869fb9edd4818ff3a3f Mon Sep 17 00:00:00 2001 From: Matt Date: Mon, 26 Jan 2026 11:18:55 +0100 Subject: [PATCH] Remove Traefik from deploy package (use existing nginx) - Remove Traefik service and related labels - Expose ports to localhost only (3000, 8000, 3001) - Update README with nginx proxy configuration examples - Remove ACME_EMAIL and Traefik auth from .env.example Co-Authored-By: Claude Opus 4.5 --- deploy/.env.example | 14 ---- deploy/README.md | 159 ++++++++++++++++++++++++++++---------- deploy/docker-compose.yml | 75 +++--------------- 3 files changed, 129 insertions(+), 119 deletions(-) diff --git a/deploy/.env.example b/deploy/.env.example index 9a73e96..69dde4f 100644 --- a/deploy/.env.example +++ b/deploy/.env.example @@ -14,9 +14,6 @@ # Your domain name (without https://) DOMAIN=portal.monacousa.org -# Email for Let's Encrypt SSL certificates -ACME_EMAIL=admin@monacousa.org - # ============================================ # DATABASE CONFIGURATION # ============================================ @@ -97,17 +94,6 @@ ADDITIONAL_REDIRECT_URLS= # Database schemas exposed via REST API PGRST_DB_SCHEMAS=public,storage,graphql_public -# ============================================ -# SECURITY - DASHBOARD ACCESS (Optional) -# ============================================ -# Basic auth for Traefik dashboard (format: user:password-hash) -# Generate with: htpasswd -nB admin -# Example: admin:$apr1$xyz... -TRAEFIK_DASHBOARD_AUTH= - -# Basic auth for Supabase Studio (format: user:password-hash) -# Generate with: htpasswd -nB admin -STUDIO_AUTH= # ============================================ # NOTES diff --git a/deploy/README.md b/deploy/README.md index 3d86ac6..d7f95fa 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -7,8 +7,8 @@ This is a standalone deployment package for the Monaco USA Portal. No source cod - Linux server (Ubuntu 22.04+ recommended) - Docker Engine 24.0+ - Docker Compose v2.20+ +- Nginx installed and configured for SSL - Domain name with DNS pointing to your server -- Ports 80 and 443 open ## Quick Start @@ -21,7 +21,7 @@ mkdir -p /opt/monacousa cd /opt/monacousa # Download files from your deployment source -# Example: scp, git clone, or direct download +# Example: copy from Gitea, scp, etc. ``` You need these files: @@ -43,7 +43,6 @@ nano .env At minimum, configure: - `DOMAIN` - Your domain name (e.g., `portal.monacousa.org`) -- `ACME_EMAIL` - Email for SSL certificates - SMTP settings (optional but recommended for emails) ### 3. Run setup script @@ -67,7 +66,85 @@ The setup script will: docker compose up -d ``` -### 5. Verify deployment +### 5. Configure Nginx + +Add proxy configuration for your domain. Example: + +```nginx +# Portal - main site +server { + listen 443 ssl http2; + server_name portal.monacousa.org; + + ssl_certificate /path/to/cert.pem; + ssl_certificate_key /path/to/key.pem; + + 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; + } +} + +# API - Supabase services +server { + listen 443 ssl http2; + server_name api.portal.monacousa.org; + + ssl_certificate /path/to/cert.pem; + ssl_certificate_key /path/to/key.pem; + + location / { + proxy_pass http://127.0.0.1:8000; + 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; + } +} + +# Studio - Supabase dashboard (optional) +server { + listen 443 ssl http2; + server_name studio.portal.monacousa.org; + + ssl_certificate /path/to/cert.pem; + ssl_certificate_key /path/to/key.pem; + + # Add basic auth for security + auth_basic "Supabase Studio"; + auth_basic_user_file /etc/nginx/.htpasswd; + + location / { + proxy_pass http://127.0.0.1:3001; + 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; + } +} +``` + +Reload nginx: +```bash +nginx -t && systemctl reload nginx +``` + +### 6. Verify deployment ```bash # Check all containers are running @@ -80,24 +157,24 @@ docker compose logs db docker compose logs -f ``` -### 6. Access the portal +### 7. Access the portal -Open `https://your-domain.com` in your browser. On first visit, you'll be redirected to `/setup` to create the initial admin account. +Open `https://portal.monacousa.org` in your browser. On first visit, you'll be redirected to `/setup` to create the initial admin account. ## Architecture ``` Internet │ - ├─► :80/:443 ──► Traefik (SSL/Reverse Proxy) - │ │ - │ ├─► portal.domain.com ──► Portal (SvelteKit) - │ ├─► api.domain.com ──► Kong ──► Auth/REST/Storage - │ └─► studio.domain.com ──► Studio (Dashboard) + └─► Nginx (SSL/Reverse Proxy) + │ + ├─► portal.domain.com:443 ──► localhost:3000 ──► Portal (SvelteKit) + ├─► api.domain.com:443 ──► localhost:8000 ──► Kong ──► Auth/REST/Storage + └─► studio.domain.com:443 ──► localhost:3001 ──► Studio (Dashboard) + +Internal Docker Network │ -Internal Network - │ - ├─► Kong API Gateway + ├─► Kong API Gateway (port 8000) │ ├─► Auth (GoTrue) │ ├─► REST (PostgREST) │ ├─► Storage API @@ -106,6 +183,16 @@ Internal Network └─► PostgreSQL Database ``` +## Exposed Ports + +| Service | Port | Purpose | +|---------|------|---------| +| Portal | 127.0.0.1:3000 | Main web application | +| Kong | 127.0.0.1:8000 | Supabase API gateway | +| Studio | 127.0.0.1:3001 | Supabase dashboard (optional) | + +All ports are bound to localhost only for security. Use nginx to expose them. + ## Files Description | File | Purpose | @@ -193,17 +280,7 @@ docker compose up -d docker compose logs # Check if ports are in use -netstat -tlnp | grep -E ':(80|443)' -``` - -### SSL certificate issues - -```bash -# Check Traefik logs -docker compose logs traefik - -# Verify DNS is pointing to server -dig +short your-domain.com +netstat -tlnp | grep -E ':(3000|3001|8000)' ``` ### Database connection errors @@ -238,6 +315,15 @@ docker compose logs portal docker compose exec portal wget -qO- http://kong:8000/rest/v1/ || echo "Kong not reachable" ``` +### Nginx 502 Bad Gateway + +Check if the Docker containers are running: +```bash +docker compose ps +curl http://127.0.0.1:3000 # Should return HTML +curl http://127.0.0.1:8000 # Should return JSON +``` + ## Security Recommendations 1. **Secure your .env file** @@ -245,32 +331,23 @@ docker compose exec portal wget -qO- http://kong:8000/rest/v1/ || echo "Kong not chmod 600 .env ``` -2. **Enable dashboard authentication** +2. **Protect Supabase Studio with auth** ```bash - # Generate password hash - htpasswd -nB admin - # Add to .env as STUDIO_AUTH and TRAEFIK_DASHBOARD_AUTH + # Generate password file for nginx + htpasswd -c /etc/nginx/.htpasswd admin ``` -3. **Set up firewall** - ```bash - ufw allow 80/tcp - ufw allow 443/tcp - ufw allow 22/tcp - ufw enable - ``` - -4. **Regular updates** +3. **Regular updates** - Keep Docker and host OS updated - Regularly pull latest portal images -5. **Monitor logs** +4. **Monitor logs** - Set up log rotation (configured in docker-compose.yml) - - Consider centralized logging (ELK, Loki, etc.) + - Consider centralized logging ## Support For issues and questions: - Check logs: `docker compose logs -f` -- GitHub issues: [Project Repository] +- GitHub/Gitea issues - Email: support@monacousa.org diff --git a/deploy/docker-compose.yml b/deploy/docker-compose.yml index 9fdde11..9811bff 100644 --- a/deploy/docker-compose.yml +++ b/deploy/docker-compose.yml @@ -8,51 +8,14 @@ # 2. Copy .env.example to .env and configure # 3. Run ./setup.sh to generate secrets and kong.yml # 4. Run: docker compose up -d +# 5. Configure your nginx to proxy to the exposed ports # -# Prerequisites: -# - Docker and Docker Compose installed -# - Domain DNS pointing to server IP -# - Ports 80 and 443 open +# Exposed Ports (configure nginx to proxy to these): +# - Portal: localhost:3000 +# - Kong API: localhost:8000 +# - Studio: localhost:3001 (optional) services: - # ============================================ - # Traefik Reverse Proxy (SSL/HTTPS) - # ============================================ - traefik: - image: traefik:v3.0 - container_name: monacousa-traefik - restart: unless-stopped - command: - - "--api.dashboard=true" - - "--providers.docker=true" - - "--providers.docker.exposedbydefault=false" - - "--entrypoints.web.address=:80" - - "--entrypoints.websecure.address=:443" - - "--entrypoints.web.http.redirections.entryPoint.to=websecure" - - "--entrypoints.web.http.redirections.entryPoint.scheme=https" - - "--certificatesresolvers.letsencrypt.acme.httpchallenge=true" - - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web" - - "--certificatesresolvers.letsencrypt.acme.email=${ACME_EMAIL}" - - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json" - - "--log.level=INFO" - ports: - - "80:80" - - "443:443" - volumes: - - /var/run/docker.sock:/var/run/docker.sock:ro - - traefik-certs:/letsencrypt - networks: - - monacousa-network - labels: - # Traefik dashboard (optional - remove in production if not needed) - - "traefik.enable=true" - - "traefik.http.routers.traefik.rule=Host(`traefik.${DOMAIN}`)" - - "traefik.http.routers.traefik.entrypoints=websecure" - - "traefik.http.routers.traefik.tls.certresolver=letsencrypt" - - "traefik.http.routers.traefik.service=api@internal" - - "traefik.http.routers.traefik.middlewares=traefik-auth" - - "traefik.http.middlewares.traefik-auth.basicauth.users=${TRAEFIK_DASHBOARD_AUTH:-}" - # ============================================ # PostgreSQL Database # ============================================ @@ -95,6 +58,8 @@ services: image: supabase/studio:20241202-71e5240 container_name: monacousa-studio restart: unless-stopped + ports: + - "127.0.0.1:3001:3000" environment: STUDIO_PG_META_URL: http://meta:8080 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} @@ -109,14 +74,6 @@ services: condition: service_healthy networks: - monacousa-network - labels: - - "traefik.enable=true" - - "traefik.http.routers.studio.rule=Host(`studio.${DOMAIN}`)" - - "traefik.http.routers.studio.entrypoints=websecure" - - "traefik.http.routers.studio.tls.certresolver=letsencrypt" - - "traefik.http.services.studio.loadbalancer.server.port=3000" - - "traefik.http.routers.studio.middlewares=studio-auth" - - "traefik.http.middlewares.studio-auth.basicauth.users=${STUDIO_AUTH:-}" logging: driver: "json-file" options: @@ -130,6 +87,8 @@ services: image: kong:2.8.1 container_name: monacousa-kong restart: unless-stopped + ports: + - "127.0.0.1:8000:8000" environment: KONG_DATABASE: "off" KONG_DECLARATIVE_CONFIG: /var/lib/kong/kong.yml @@ -144,12 +103,6 @@ services: condition: service_healthy networks: - monacousa-network - labels: - - "traefik.enable=true" - - "traefik.http.routers.kong.rule=Host(`api.${DOMAIN}`)" - - "traefik.http.routers.kong.entrypoints=websecure" - - "traefik.http.routers.kong.tls.certresolver=letsencrypt" - - "traefik.http.services.kong.loadbalancer.server.port=8000" logging: driver: "json-file" options: @@ -385,6 +338,8 @@ services: image: ${PORTAL_IMAGE:-code.letsbe.solutions/letsbe/monacousa-portal:latest} container_name: monacousa-portal restart: unless-stopped + ports: + - "127.0.0.1:3000:3000" environment: PUBLIC_SUPABASE_URL: https://api.${DOMAIN} PUBLIC_SUPABASE_ANON_KEY: ${ANON_KEY} @@ -400,12 +355,6 @@ services: condition: service_healthy networks: - monacousa-network - labels: - - "traefik.enable=true" - - "traefik.http.routers.portal.rule=Host(`${DOMAIN}`)" - - "traefik.http.routers.portal.entrypoints=websecure" - - "traefik.http.routers.portal.tls.certresolver=letsencrypt" - - "traefik.http.services.portal.loadbalancer.server.port=3000" deploy: resources: limits: @@ -433,5 +382,3 @@ volumes: driver: local storage-data: driver: local - traefik-certs: - driver: local