Remove Traefik from deploy package (use existing nginx)
Build and Push Docker Image / build (push) Successful in 1m52s Details

- 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 <noreply@anthropic.com>
This commit is contained in:
Matt 2026-01-26 11:18:55 +01:00
parent 3187f5babb
commit 8cabe7d362
3 changed files with 129 additions and 119 deletions

View File

@ -14,9 +14,6 @@
# Your domain name (without https://) # Your domain name (without https://)
DOMAIN=portal.monacousa.org DOMAIN=portal.monacousa.org
# Email for Let's Encrypt SSL certificates
ACME_EMAIL=admin@monacousa.org
# ============================================ # ============================================
# DATABASE CONFIGURATION # DATABASE CONFIGURATION
# ============================================ # ============================================
@ -97,17 +94,6 @@ ADDITIONAL_REDIRECT_URLS=
# Database schemas exposed via REST API # Database schemas exposed via REST API
PGRST_DB_SCHEMAS=public,storage,graphql_public 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 # NOTES

View File

@ -7,8 +7,8 @@ This is a standalone deployment package for the Monaco USA Portal. No source cod
- Linux server (Ubuntu 22.04+ recommended) - Linux server (Ubuntu 22.04+ recommended)
- Docker Engine 24.0+ - Docker Engine 24.0+
- Docker Compose v2.20+ - Docker Compose v2.20+
- Nginx installed and configured for SSL
- Domain name with DNS pointing to your server - Domain name with DNS pointing to your server
- Ports 80 and 443 open
## Quick Start ## Quick Start
@ -21,7 +21,7 @@ mkdir -p /opt/monacousa
cd /opt/monacousa cd /opt/monacousa
# Download files from your deployment source # Download files from your deployment source
# Example: scp, git clone, or direct download # Example: copy from Gitea, scp, etc.
``` ```
You need these files: You need these files:
@ -43,7 +43,6 @@ nano .env
At minimum, configure: At minimum, configure:
- `DOMAIN` - Your domain name (e.g., `portal.monacousa.org`) - `DOMAIN` - Your domain name (e.g., `portal.monacousa.org`)
- `ACME_EMAIL` - Email for SSL certificates
- SMTP settings (optional but recommended for emails) - SMTP settings (optional but recommended for emails)
### 3. Run setup script ### 3. Run setup script
@ -67,7 +66,85 @@ The setup script will:
docker compose up -d 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 ```bash
# Check all containers are running # Check all containers are running
@ -80,24 +157,24 @@ docker compose logs db
docker compose logs -f 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 ## Architecture
``` ```
Internet Internet
├─► :80/:443 ──► Traefik (SSL/Reverse Proxy) └─► Nginx (SSL/Reverse Proxy)
│ │
│ ├─► portal.domain.com ──► Portal (SvelteKit) ├─► portal.domain.com:443 ──► localhost:3000 ──► Portal (SvelteKit)
│ ├─► api.domain.com ──► Kong ──► Auth/REST/Storage ├─► api.domain.com:443 ──► localhost:8000 ──► Kong ──► Auth/REST/Storage
│ └─► studio.domain.com ──► Studio (Dashboard) └─► studio.domain.com:443 ──► localhost:3001 ──► Studio (Dashboard)
Internal Docker Network
Internal Network ├─► Kong API Gateway (port 8000)
├─► Kong API Gateway
│ ├─► Auth (GoTrue) │ ├─► Auth (GoTrue)
│ ├─► REST (PostgREST) │ ├─► REST (PostgREST)
│ ├─► Storage API │ ├─► Storage API
@ -106,6 +183,16 @@ Internal Network
└─► PostgreSQL Database └─► 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 ## Files Description
| File | Purpose | | File | Purpose |
@ -193,17 +280,7 @@ docker compose up -d
docker compose logs docker compose logs
# Check if ports are in use # Check if ports are in use
netstat -tlnp | grep -E ':(80|443)' netstat -tlnp | grep -E ':(3000|3001|8000)'
```
### SSL certificate issues
```bash
# Check Traefik logs
docker compose logs traefik
# Verify DNS is pointing to server
dig +short your-domain.com
``` ```
### Database connection errors ### 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" 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 ## Security Recommendations
1. **Secure your .env file** 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 chmod 600 .env
``` ```
2. **Enable dashboard authentication** 2. **Protect Supabase Studio with auth**
```bash ```bash
# Generate password hash # Generate password file for nginx
htpasswd -nB admin htpasswd -c /etc/nginx/.htpasswd admin
# Add to .env as STUDIO_AUTH and TRAEFIK_DASHBOARD_AUTH
``` ```
3. **Set up firewall** 3. **Regular updates**
```bash
ufw allow 80/tcp
ufw allow 443/tcp
ufw allow 22/tcp
ufw enable
```
4. **Regular updates**
- Keep Docker and host OS updated - Keep Docker and host OS updated
- Regularly pull latest portal images - Regularly pull latest portal images
5. **Monitor logs** 4. **Monitor logs**
- Set up log rotation (configured in docker-compose.yml) - Set up log rotation (configured in docker-compose.yml)
- Consider centralized logging (ELK, Loki, etc.) - Consider centralized logging
## Support ## Support
For issues and questions: For issues and questions:
- Check logs: `docker compose logs -f` - Check logs: `docker compose logs -f`
- GitHub issues: [Project Repository] - GitHub/Gitea issues
- Email: support@monacousa.org - Email: support@monacousa.org

View File

@ -8,51 +8,14 @@
# 2. Copy .env.example to .env and configure # 2. Copy .env.example to .env and configure
# 3. Run ./setup.sh to generate secrets and kong.yml # 3. Run ./setup.sh to generate secrets and kong.yml
# 4. Run: docker compose up -d # 4. Run: docker compose up -d
# 5. Configure your nginx to proxy to the exposed ports
# #
# Prerequisites: # Exposed Ports (configure nginx to proxy to these):
# - Docker and Docker Compose installed # - Portal: localhost:3000
# - Domain DNS pointing to server IP # - Kong API: localhost:8000
# - Ports 80 and 443 open # - Studio: localhost:3001 (optional)
services: 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 # PostgreSQL Database
# ============================================ # ============================================
@ -95,6 +58,8 @@ services:
image: supabase/studio:20241202-71e5240 image: supabase/studio:20241202-71e5240
container_name: monacousa-studio container_name: monacousa-studio
restart: unless-stopped restart: unless-stopped
ports:
- "127.0.0.1:3001:3000"
environment: environment:
STUDIO_PG_META_URL: http://meta:8080 STUDIO_PG_META_URL: http://meta:8080
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
@ -109,14 +74,6 @@ services:
condition: service_healthy condition: service_healthy
networks: networks:
- monacousa-network - 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: logging:
driver: "json-file" driver: "json-file"
options: options:
@ -130,6 +87,8 @@ services:
image: kong:2.8.1 image: kong:2.8.1
container_name: monacousa-kong container_name: monacousa-kong
restart: unless-stopped restart: unless-stopped
ports:
- "127.0.0.1:8000:8000"
environment: environment:
KONG_DATABASE: "off" KONG_DATABASE: "off"
KONG_DECLARATIVE_CONFIG: /var/lib/kong/kong.yml KONG_DECLARATIVE_CONFIG: /var/lib/kong/kong.yml
@ -144,12 +103,6 @@ services:
condition: service_healthy condition: service_healthy
networks: networks:
- monacousa-network - 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: logging:
driver: "json-file" driver: "json-file"
options: options:
@ -385,6 +338,8 @@ services:
image: ${PORTAL_IMAGE:-code.letsbe.solutions/letsbe/monacousa-portal:latest} image: ${PORTAL_IMAGE:-code.letsbe.solutions/letsbe/monacousa-portal:latest}
container_name: monacousa-portal container_name: monacousa-portal
restart: unless-stopped restart: unless-stopped
ports:
- "127.0.0.1:3000:3000"
environment: environment:
PUBLIC_SUPABASE_URL: https://api.${DOMAIN} PUBLIC_SUPABASE_URL: https://api.${DOMAIN}
PUBLIC_SUPABASE_ANON_KEY: ${ANON_KEY} PUBLIC_SUPABASE_ANON_KEY: ${ANON_KEY}
@ -400,12 +355,6 @@ services:
condition: service_healthy condition: service_healthy
networks: networks:
- monacousa-network - 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: deploy:
resources: resources:
limits: limits:
@ -433,5 +382,3 @@ volumes:
driver: local driver: local
storage-data: storage-data:
driver: local driver: local
traefik-certs:
driver: local