Remove Traefik from deploy package (use existing nginx)
Build and Push Docker Image / build (push) Successful in 1m52s
Details
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:
parent
3187f5babb
commit
8cabe7d362
|
|
@ -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
|
||||||
|
|
|
||||||
159
deploy/README.md
159
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)
|
- 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
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue