Add Docker deployment setup with health check endpoint

- Add multi-stage Dockerfile with standalone Next.js output
- Add docker-compose.yml with Caddy reverse proxy
- Add nginx configs for local and SSL setups
- Add Caddyfile for automatic HTTPS
- Add docker-entrypoint.sh for runtime config
- Add .env.example and .dockerignore
- Add comprehensive Docker README
- Add /api/health endpoint for container health checks
- Configure next.config.ts for standalone output
This commit is contained in:
Christomatt
2026-01-31 03:53:19 +01:00
parent 50355b740a
commit df5b61f42a
12 changed files with 1090 additions and 1 deletions
+96
View File
@@ -0,0 +1,96 @@
# Dependencies
node_modules
npm-debug.log*
yarn-debug.log*
yarn-error.log*
package-lock.json
yarn.lock
pnpm-lock.yaml
# Build outputs
.next
out
dist
build
*.tsbuildinfo
# Environment files (these are passed via docker-compose)
.env
.env.local
.env.*.local
.env.dev
.env.test
.env.production
# Version control
.git
.gitignore
.gitattributes
# IDE and editor files
.vscode
.idea
*.swp
*.swo
*~
.DS_Store
Thumbs.db
# Testing
coverage
.nyc_output
*.test.ts
*.test.tsx
*.spec.ts
*.spec.tsx
tests
test
__tests__
# Documentation (not needed in production image)
*.md
!README.md
LICENSE
CHANGELOG.md
CONTRIBUTING.md
# Docker files (avoid recursive copy)
docker
docker-compose*.yml
Dockerfile*
.dockerignore
# CI/CD
.github
.gitlab-ci.yml
.travis.yml
azure-pipelines.yml
Jenkinsfile
# Logs
logs
*.log
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Misc
.cache
temp
tmp
.tmp
uploads/*
!uploads/.gitkeep
# Large binary files
*.mp4
*.mov
*.avi
*.mkv
*.pdf
*.zip
*.tar.gz
*.rar
+54
View File
@@ -0,0 +1,54 @@
# ===========================================
# Synapsis Docker Environment Configuration
# ===========================================
# Copy this file to .env and configure your values
# ===========================================
# Required Settings
# ===========================================
# Domain Configuration
# Replace with your actual domain
DOMAIN=your-domain.com
# Database Credentials
# Change these to secure values!
DB_USER=synapsis
DB_PASSWORD=your-secure-password-here
DB_NAME=synapsis
# Authentication Secret
# Generate with: openssl rand -hex 32
AUTH_SECRET=your-secret-key-here-minimum-32-characters
# Admin Users
# Comma-separated list of email addresses with admin access
ADMIN_EMAILS=admin@your-domain.com
# ===========================================
# S3-Compatible Storage (Required for uploads)
# ===========================================
# You can use AWS S3, MinIO, Wasabi, Backblaze B2, etc.
STORAGE_ENDPOINT=https://s3.your-provider.com
STORAGE_REGION=us-east-1
STORAGE_BUCKET=synapsis-uploads
STORAGE_ACCESS_KEY=your-access-key
STORAGE_SECRET_KEY=your-secret-key
STORAGE_PUBLIC_BASE_URL=https://cdn.your-domain.com
# ===========================================
# Optional Settings
# ===========================================
# Maximum bots per user (default: 5)
# BOT_MAX_PER_USER=5
# Redis configuration (if using external Redis)
# REDIS_URL=redis://redis:6379
# ===========================================
# Docker Compose Settings
# ===========================================
# COMPOSE_PROJECT_NAME=synapsis
+40
View File
@@ -0,0 +1,40 @@
# Caddyfile for Synapsis
# Automatic HTTPS via Let's Encrypt
{$DOMAIN} {
# Reverse proxy to Synapsis app
reverse_proxy app:3000
# Enable compression
encode gzip
# Security headers
header {
# Enable HSTS
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
# Prevent clickjacking
X-Frame-Options "SAMEORIGIN"
# Prevent MIME type sniffing
X-Content-Type-Options "nosniff"
# XSS protection
X-XSS-Protection "1; mode=block"
# Referrer policy
Referrer-Policy "strict-origin-when-cross-origin"
}
# Logging
log {
output file /data/access.log
format json
}
# Increase max body size for uploads (20MB)
request_body {
max_size 20MB
}
}
# Health check endpoint for Docker
:8080 {
respond /health "healthy" 200
}
+90
View File
@@ -0,0 +1,90 @@
# Synapsis - Multi-stage Production Dockerfile
# This Dockerfile creates a production-ready image that:
# - Keeps source files immutable (prevents accidental modifications)
# - Optimizes build size with multi-stage approach
# - Runs as non-root user for security
# ============================================
# Stage 1: Dependencies
# ============================================
FROM node:22-alpine AS deps
RUN apk add --no-cache libc6-compat openssl
WORKDIR /app
# Copy package files for efficient layer caching
COPY package.json package-lock.json* ./
# Install production dependencies only (using ci for reproducible builds)
RUN npm ci --only=production --ignore-scripts && npm cache clean --force
# ============================================
# Stage 2: Builder
# ============================================
FROM node:22-alpine AS builder
RUN apk add --no-cache libc6-compat openssl
WORKDIR /app
# Copy dependencies from deps stage
COPY --from=deps /app/node_modules ./node_modules
# Copy all source files
COPY . .
# Set environment variables for build
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
# Build the Next.js application
RUN npm run build
# ============================================
# Stage 3: Production Runner
# ============================================
FROM node:22-alpine AS runner
RUN apk add --no-cache libc6-compat openssl
WORKDIR /app
# Create non-root user for security
RUN addgroup --system --gid 1001 nodejs && \
adduser --system --uid 1001 nextjs
# Set production environment
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"
# Copy public assets
COPY --from=builder /app/public ./public
# Copy Next.js build output
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
# Copy drizzle migrations for runtime database updates
COPY --from=builder --chown=nextjs:nodejs /app/drizzle ./drizzle
COPY --from=builder --chown=nextjs:nodejs /app/drizzle.config.ts ./
COPY --from=builder --chown=nextjs:nodejs /app/package.json ./
# Copy entrypoint script
COPY --from=builder --chown=nextjs:nodejs /app/docker/docker-entrypoint.sh ./
RUN chmod +x ./docker-entrypoint.sh
# Switch to non-root user
USER nextjs
# Expose the application port
EXPOSE 3000
# Health check to ensure container is running properly
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD node -e "require('http').get('http://localhost:3000/api/health', (r) => r.statusCode === 200 ? process.exit(0) : process.exit(1))"
# Set the entrypoint
ENTRYPOINT ["./docker-entrypoint.sh"]
# Default command (can be overridden)
CMD ["node", "server.js"]
+325
View File
@@ -0,0 +1,325 @@
# Synapsis Docker Production Deployment
One-command Docker deployment for Synapsis that solves the "user modifies file and breaks git sync" problem.
## 🚀 Quick Start
```bash
cd /var/www/Synapsis/docker
# 1. Copy and edit environment variables
cp .env.example .env
nano .env # Edit all required values
# 2. Start the stack
docker-compose up -d
# 3. Check logs
docker-compose logs -f
```
Your Synapsis instance will be available at `http://localhost` (or your configured domain).
---
## 📋 Server Requirements
| Resource | Minimum | Recommended |
|----------|---------|-------------|
| RAM | 2 GB | 4 GB |
| CPU | 2 cores | 4 cores |
| Disk | 20 GB SSD | 50 GB SSD |
| OS | Ubuntu 22.04/24.04, Debian 12, or compatible |
### Required Software
- Docker 24.0+
- Docker Compose 2.20+
### Installation (Ubuntu/Debian)
```bash
# Install Docker
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
newgrp docker
# Verify
docker --version
docker-compose --version
```
---
## 🔧 Configuration
### 1. Environment Variables
Copy `.env.example` to `.env` and configure:
```bash
cd /var/www/Synapsis/docker
cp .env.example .env
```
**Required settings:**
- `DOMAIN` - Your domain name (e.g., `synapsis.example.com`)
- `DB_PASSWORD` - Strong database password
- `AUTH_SECRET` - Generate with `openssl rand -hex 32`
- `ADMIN_EMAILS` - Admin user email(s)
- `STORAGE_*` - S3-compatible storage credentials
### 2. SSL/HTTPS Setup
#### Option A: Let's Encrypt (Recommended)
1. Start with HTTP first:
```bash
docker-compose up -d
```
2. Obtain SSL certificates:
```bash
docker run -it --rm \
-v ./certbot_data:/etc/letsencrypt \
-v ./certbot_www:/var/www/certbot \
-p 80:80 \
certbot/certbot certonly \
--standalone \
-d your-domain.com
```
3. Enable SSL configuration:
```bash
cd nginx/conf.d
mv default.conf default.conf.http
mv default.conf.ssl default.conf
# Edit default.conf and replace ${DOMAIN} with your actual domain
docker-compose restart nginx
```
4. Uncomment the certbot service in docker-compose.yml for auto-renewal.
#### Option B: Custom SSL Certificates
Place your certificates in `./certbot_data/live/your-domain.com/`:
- `fullchain.pem`
- `privkey.pem`
---
## 🔄 Updates
### Standard Update Process
```bash
cd /var/www/Synapsis/docker
# 1. Pull latest changes
git pull origin main
# 2. Rebuild and restart
docker-compose down
docker-compose pull # If using pre-built images
docker-compose up -d --build
# 3. Run migrations (if needed)
docker-compose exec app npx drizzle-kit push
# 4. Verify
docker-compose ps
docker-compose logs -f app
```
### One-Command Update Script
Create `update.sh`:
```bash
#!/bin/bash
cd /var/www/Synapsis/docker
git pull origin main
docker-compose down
docker-compose up -d --build
docker-compose exec -T app npx drizzle-kit push || true
echo "✅ Update complete!"
```
---
## 📁 Directory Structure
```
/var/www/Synapsis/docker/
├── docker-compose.yml # Main orchestration file
├── Dockerfile # Multi-stage build
├── docker-entrypoint.sh # Startup script
├── .env # Your environment variables
├── .env.example # Template
├── .dockerignore # Build exclusions
├── nginx/
│ ├── nginx.conf # Main Nginx config
│ └── conf.d/
│ ├── default.conf # HTTP config
│ └── default.conf.ssl # HTTPS config
└── README.md # This file
```
---
## 🛠️ Management Commands
### View Logs
```bash
docker-compose logs -f app # Application logs
docker-compose logs -f nginx # Nginx logs
docker-compose logs -f postgres # Database logs
docker-compose logs -f # All logs
```
### Database Operations
```bash
# Access database shell
docker-compose exec postgres psql -U synapsis -d synapsis
# Backup database
docker-compose exec postgres pg_dump -U synapsis synapsis > backup.sql
# Restore database
docker-compose exec -T postgres psql -U synapsis -d synapsis < backup.sql
# Run migrations manually
docker-compose exec app npx drizzle-kit push
```
### Container Management
```bash
# Restart services
docker-compose restart app
docker-compose restart nginx
# Stop everything
docker-compose down
# Stop and remove volumes (⚠️ destroys data!)
docker-compose down -v
# View running containers
docker-compose ps
# Enter container shell
docker-compose exec app sh
docker-compose exec postgres sh
```
---
## 🔒 Security Features
This Docker setup includes:
- **Immutable source code** - Application runs from image, not bind-mounted files
- **Non-root execution** - App runs as unprivileged user
- **Network isolation** - Services communicate via internal Docker network
- **Rate limiting** - Nginx protects against brute force attacks
- **Security headers** - X-Frame-Options, X-Content-Type-Options, etc.
- **Resource limits** - Memory constraints on all containers
- **Health checks** - Automatic container health monitoring
---
## 🔍 Troubleshooting
### Container won't start
```bash
# Check for configuration errors
docker-compose config
# View detailed logs
docker-compose logs app --tail=100
```
### Database connection failed
```bash
# Check database is healthy
docker-compose ps
# Verify environment variables
docker-compose exec app env | grep DATABASE
```
### SSL certificate issues
```bash
# Test SSL configuration
docker-compose exec nginx nginx -t
# Check certificate files
ls -la certbot_data/live/
```
### Port already in use
```bash
# Find process using port 80/443
sudo netstat -tlnp | grep :80
# Change ports in docker-compose.yml if needed
```
---
## 📊 Monitoring
### Health Checks
- App: `http://your-domain/api/health`
- Nginx: `http://your-domain/nginx-health`
### Resource Usage
```bash
# Container stats
docker stats
# Disk usage
docker system df
```
---
## 💾 Backup Strategy
### Automated Backup Script
Create `/var/www/Synapsis/docker/backup.sh`:
```bash
#!/bin/bash
BACKUP_DIR="/var/backups/synapsis"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR
# Database backup
docker-compose exec -T postgres pg_dump -U synapsis synapsis > "$BACKUP_DIR/db_$DATE.sql"
# Uploads backup
tar -czf "$BACKUP_DIR/uploads_$DATE.tar.gz" -C /var/lib/docker/volumes/synapsis_uploads_data/_data .
# Keep only last 7 days
find $BACKUP_DIR -type f -mtime +7 -delete
echo "✅ Backup complete: $DATE"
```
Add to crontab:
```bash
0 2 * * * /var/www/Synapsis/docker/backup.sh >> /var/log/synapsis-backup.log 2>&1
```
---
## 📞 Support
For issues or questions:
1. Check logs: `docker-compose logs -f`
2. Review configuration: `docker-compose config`
3. Consult the main Synapsis documentation
---
## 📝 License
This Docker configuration follows the same license as Synapsis (Apache 2.0).
+139
View File
@@ -0,0 +1,139 @@
# Synapsis - Docker Compose
# One-command deployment: docker-compose up -d
#
# Services:
# - Synapsis Next.js application
# - PostgreSQL database (persistent storage)
# - Caddy reverse proxy with automatic SSL
#
# All state is stored in Docker volumes - source code is immutable in the image
version: "3.8"
services:
# ============================================
# PostgreSQL Database
# ============================================
postgres:
image: postgres:16-alpine
container_name: synapsis-db
restart: unless-stopped
environment:
POSTGRES_USER: ${DB_USER:-synapsis}
POSTGRES_PASSWORD: ${DB_PASSWORD:-changeme}
POSTGRES_DB: ${DB_NAME:-synapsis}
PGDATA: /var/lib/postgresql/data/pgdata
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- synapsis-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-synapsis} -d ${DB_NAME:-synapsis}"]
interval: 10s
timeout: 5s
retries: 5
deploy:
resources:
limits:
memory: 1G
reservations:
memory: 256M
# ============================================
# Synapsis Application
# ============================================
app:
build:
context: ..
dockerfile: docker/Dockerfile
image: synapsis:latest
container_name: synapsis-app
restart: unless-stopped
environment:
# Database connection
DATABASE_URL: postgresql://${DB_USER:-synapsis}:${DB_PASSWORD:-changeme}@postgres:5432/${DB_NAME:-synapsis}
# Authentication
AUTH_SECRET: ${AUTH_SECRET}
# Domain configuration
NEXT_PUBLIC_NODE_DOMAIN: ${DOMAIN:-localhost}
# Admin emails
ADMIN_EMAILS: ${ADMIN_EMAILS}
# S3 Storage configuration
STORAGE_ENDPOINT: ${STORAGE_ENDPOINT}
STORAGE_REGION: ${STORAGE_REGION:-us-east-1}
STORAGE_BUCKET: ${STORAGE_BUCKET}
STORAGE_ACCESS_KEY: ${STORAGE_ACCESS_KEY}
STORAGE_SECRET_KEY: ${STORAGE_SECRET_KEY}
STORAGE_PUBLIC_BASE_URL: ${STORAGE_PUBLIC_BASE_URL}
# Optional settings
BOT_MAX_PER_USER: ${BOT_MAX_PER_USER:-5}
# Node environment
NODE_ENV: production
volumes:
# Uploads directory (if using local file storage)
- uploads_data:/app/uploads
networks:
- synapsis-network
depends_on:
postgres:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://localhost:3000/api/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
deploy:
resources:
limits:
memory: 1G
reservations:
memory: 256M
# ============================================
# Caddy Reverse Proxy (Automatic SSL)
# ============================================
caddy:
image: caddy:2-alpine
container_name: synapsis-caddy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
networks:
- synapsis-network
depends_on:
app:
condition: service_healthy
environment:
- DOMAIN=${DOMAIN:-localhost}
# ============================================
# Persistent Volumes
# ============================================
volumes:
postgres_data:
driver: local
uploads_data:
driver: local
caddy_data:
driver: local
caddy_config:
driver: local
# ============================================
# Networks
# ============================================
networks:
synapsis-network:
driver: bridge
+101
View File
@@ -0,0 +1,101 @@
#!/bin/sh
# Synapsis Docker Entrypoint Script
# Handles database migrations, seeding, and application startup
set -e
echo "========================================"
echo " Synapsis - Starting Application"
echo "========================================"
# Function to wait for database
wait_for_db() {
echo "⏳ Waiting for PostgreSQL..."
# Extract connection details from DATABASE_URL
# Format: postgresql://user:password@host:port/database
DB_HOST=$(echo "$DATABASE_URL" | sed -n 's/.*@\([^:]*\):.*/\1/p')
DB_PORT=$(echo "$DATABASE_URL" | sed -n 's/.*:\([0-9]*\)\/.*/\1/p')
# Default values
DB_HOST=${DB_HOST:-postgres}
DB_PORT=${DB_PORT:-5432}
max_retries=30
retry_count=0
while ! nc -z "$DB_HOST" "$DB_PORT"; do
retry_count=$((retry_count + 1))
if [ $retry_count -ge $max_retries ]; then
echo "❌ Failed to connect to database after $max_retries attempts"
exit 1
fi
echo " Attempt $retry_count/$max_retries - waiting for $DB_HOST:$DB_PORT..."
sleep 2
done
echo "✅ Database is ready!"
}
# Function to run database migrations
run_migrations() {
echo ""
echo "🔄 Running database migrations..."
# Check if drizzle-kit is available (in dev dependencies)
if command -v drizzle-kit >/dev/null 2>&1; then
echo " Using drizzle-kit for migrations..."
drizzle-kit push --force || {
echo "⚠️ Migration push failed - database may already be up to date"
}
else
echo " ⚠️ drizzle-kit not found in production image"
echo " Migrations should be run manually during deployment:"
echo " docker-compose exec app npx drizzle-kit push"
fi
echo "✅ Migration check complete"
}
# Function to check/create initial admin user
check_admin_setup() {
echo ""
echo "👤 Checking admin setup..."
# This is a placeholder - you can add logic here to ensure
# at least one admin user exists on first run
# For now, we rely on the application to handle this
echo "✅ Admin check complete (handled by application)"
}
# Install netcat for database connectivity check if not present
if ! command -v nc >/dev/null 2>&1; then
echo "📦 Installing netcat for database checks..."
# Note: In Alpine, nc is typically included in busybox
# If not, we'll proceed anyway and let the app handle connection
echo " (Skipping - using application-level retry logic)"
fi
# Wait for database to be ready
wait_for_db
# Run migrations
run_migrations
# Check admin setup
check_admin_setup
# Display startup info
echo ""
echo "========================================"
echo " 🚀 Starting Synapsis Server"
echo "========================================"
echo " Environment: $NODE_ENV"
echo " Port: $PORT"
echo " Database: Connected"
echo "========================================"
echo ""
# Execute the main command (passed as arguments)
exec "$@"
+63
View File
@@ -0,0 +1,63 @@
# HTTP to HTTPS redirect (run this first without SSL)
# After SSL certificates are obtained, use the SSL version below
server {
listen 80;
server_name _; # Accept any server name (change to your domain for production)
# Health check endpoint for Docker
location /nginx-health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
# Proxy all requests to the Next.js app
location / {
proxy_pass http://app: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 86400;
}
# Static files caching
location /_next/static {
proxy_pass http://app:3000;
proxy_cache_valid 200 365d;
add_header Cache-Control "public, immutable";
}
# API rate limiting
location /api/ {
limit_req zone=api burst=20 nodelay;
limit_conn addr 10;
proxy_pass http://app: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;
}
# Auth endpoints - stricter rate limiting
location /api/auth/ {
limit_req zone=auth burst=5 nodelay;
limit_conn addr 5;
proxy_pass http://app:3000;
proxy_http_version 1.1;
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;
}
}
+91
View File
@@ -0,0 +1,91 @@
# SSL Configuration (use this after obtaining certificates)
# Rename to default.conf after SSL setup
server {
listen 80;
server_name ${DOMAIN};
# Certbot challenge
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
# Redirect all HTTP to HTTPS
location / {
return 301 https://$server_name$request_uri;
}
}
server {
listen 443 ssl http2;
server_name ${DOMAIN};
# SSL certificates (mounted from certbot)
ssl_certificate /etc/letsencrypt/live/${DOMAIN}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${DOMAIN}/privkey.pem;
# SSL configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# HSTS (enable after confirming HTTPS works)
# add_header Strict-Transport-Security "max-age=63072000" always;
# Health check
location /nginx-health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
# Proxy all requests to the Next.js app
location / {
proxy_pass http://app: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 86400;
}
# Static files caching
location /_next/static {
proxy_pass http://app:3000;
proxy_cache_valid 200 365d;
add_header Cache-Control "public, immutable";
}
# API rate limiting
location /api/ {
limit_req zone=api burst=20 nodelay;
limit_conn addr 10;
proxy_pass http://app:3000;
proxy_http_version 1.1;
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;
}
# Auth endpoints - stricter rate limiting
location /api/auth/ {
limit_req zone=auth burst=5 nodelay;
limit_conn addr 5;
proxy_pass http://app:3000;
proxy_http_version 1.1;
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;
}
}
+70
View File
@@ -0,0 +1,70 @@
# Nginx configuration for Synapsis
# This configuration includes:
# - Gzip compression
# - Security headers
# - Rate limiting
# - Proper handling of Next.js static files
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
use epoll;
multi_accept on;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Logging format
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
# Performance
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
client_max_body_size 50M;
# Gzip compression
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml+rss
application/rss+xml
font/truetype
font/opentype
application/vnd.ms-fontobject
image/svg+xml;
# Rate limiting zones
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=auth:10m rate=5r/m;
limit_conn_zone $binary_remote_addr zone=addr:10m;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Include server configurations
include /etc/nginx/conf.d/*.conf;
}
+5 -1
View File
@@ -1,7 +1,11 @@
import type { NextConfig } from "next"; import type { NextConfig } from "next";
const nextConfig: NextConfig = { const nextConfig: NextConfig = {
// Empty turbopack config to silence the warning // Enable standalone output for Docker deployment
// This creates a minimal server.js that doesn't require full node_modules
output: 'standalone',
// Turbopack configuration
turbopack: {}, turbopack: {},
}; };
+16
View File
@@ -0,0 +1,16 @@
import { NextResponse } from 'next/server';
/**
* Health check endpoint for Docker and monitoring
* Returns 200 OK when the application is running properly
*/
export async function GET() {
return NextResponse.json(
{
status: 'healthy',
timestamp: new Date().toISOString(),
service: 'synapsis',
},
{ status: 200 }
);
}