9.3 KiB
Reverse Proxy Configuration Guide for Readur
This guide covers various deployment scenarios for running Readur behind reverse proxies with configurable ports.
Table of Contents
- Port Configuration
- Docker Deployment
- Nginx Configuration
- Traefik Configuration
- Apache Configuration
- Caddy Configuration
- Common Scenarios
- Troubleshooting
Port Configuration
Readur supports flexible port configuration through environment variables:
Server Port Configuration
# Method 1: Full address specification
SERVER_ADDRESS=0.0.0.0:3000
# Method 2: Separate host and port (recommended)
SERVER_HOST=0.0.0.0
SERVER_PORT=3000
Development Port Configuration
For frontend development with Vite:
# Backend API port
BACKEND_PORT=8000
# Frontend dev server port
CLIENT_PORT=5173
Docker Deployment
Basic Docker Run
# Run on custom port 3000
docker run -d \
-e SERVER_PORT=3000 \
-e DATABASE_URL=postgresql://user:pass@host/db \
-e JWT_SECRET=your-secret-key \
-p 3000:3000 \
readur:latest
Docker Compose with Custom Ports
version: '3.8'
services:
readur:
image: readur:latest
environment:
SERVER_PORT: 3000
DATABASE_URL: postgresql://readur:readur@postgres/readur
JWT_SECRET: ${JWT_SECRET}
ports:
- "3000:3000"
Nginx Configuration
Basic Reverse Proxy
server {
listen 80;
server_name readur.example.com;
location / {
proxy_pass http://localhost:3000;
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;
# Large file uploads for documents
client_max_body_size 100M;
# Extended timeouts for OCR processing
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
}
}
SSL Configuration
server {
listen 443 ssl http2;
server_name readur.example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_pass http://localhost:3000;
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 https;
# WebSocket support (future feature)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Subpath Configuration
To serve Readur under a subpath like /readur/:
location /readur/ {
# Remove prefix when passing to backend
rewrite ^/readur/(.*) /$1 break;
proxy_pass http://localhost:3000;
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_set_header X-Forwarded-Prefix /readur;
}
Traefik Configuration
Docker Labels
version: '3.8'
services:
readur:
image: readur:latest
environment:
SERVER_PORT: 3000
labels:
- "traefik.enable=true"
- "traefik.http.routers.readur.rule=Host(`readur.example.com`)"
- "traefik.http.routers.readur.tls=true"
- "traefik.http.routers.readur.tls.certresolver=letsencrypt"
- "traefik.http.services.readur.loadbalancer.server.port=3000"
# Middleware for large uploads
- "traefik.http.middlewares.readur-upload.buffering.maxRequestBodyBytes=104857600"
- "traefik.http.routers.readur.middlewares=readur-upload"
Static Configuration
# traefik.yml
http:
routers:
readur:
rule: "Host(`readur.example.com`)"
service: readur
tls:
certResolver: letsencrypt
middlewares:
- readur-headers
services:
readur:
loadBalancer:
servers:
- url: "http://localhost:3000"
healthCheck:
path: /api/health
interval: 30s
middlewares:
readur-headers:
headers:
customRequestHeaders:
X-Forwarded-Proto: https
Apache Configuration
Basic Reverse Proxy
<VirtualHost *:80>
ServerName readur.example.com
ProxyRequests Off
ProxyPreserveHost On
ProxyPass / http://localhost:3000/
ProxyPassReverse / http://localhost:3000/
# Large file uploads
LimitRequestBody 104857600
# Extended timeouts
ProxyTimeout 300
</VirtualHost>
SSL Configuration
<VirtualHost *:443>
ServerName readur.example.com
SSLEngine on
SSLCertificateFile /path/to/cert.pem
SSLCertificateKeyFile /path/to/key.pem
ProxyRequests Off
ProxyPreserveHost On
ProxyPass / http://localhost:3000/
ProxyPassReverse / http://localhost:3000/
RequestHeader set X-Forwarded-Proto "https"
</VirtualHost>
Caddy Configuration
Caddyfile
readur.example.com {
reverse_proxy localhost:3000 {
header_up X-Real-IP {remote_host}
header_up X-Forwarded-Proto {scheme}
# Health check
health_uri /api/health
health_interval 30s
# Extended timeouts
transport http {
dial_timeout 10s
response_header_timeout 300s
}
}
# Large file uploads
request_body {
max_size 100MB
}
}
Common Scenarios
Multiple Instances with Load Balancing
Nginx
upstream readur_pool {
least_conn;
server readur1:3000 max_fails=3 fail_timeout=30s;
server readur2:3000 max_fails=3 fail_timeout=30s;
server readur3:3000 max_fails=3 fail_timeout=30s;
}
server {
location / {
proxy_pass http://readur_pool;
# ... other proxy settings
}
}
Docker Compose Scale
# Scale to 3 instances
docker compose up -d --scale readur=3
Blue-Green Deployment
# nginx.conf
upstream readur_blue {
server blue:3000;
}
upstream readur_green {
server green:3000;
}
# Switch between blue and green
upstream readur_current {
server blue:3000; # Change to green:3000 for switch
}
server {
location / {
proxy_pass http://readur_current;
}
}
Rate Limiting
# Define rate limit 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;
server {
# Apply to API endpoints
location /api/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://localhost:3000;
}
# Stricter for auth
location /api/auth/ {
limit_req zone=auth burst=5 nodelay;
proxy_pass http://localhost:3000;
}
}
Troubleshooting
Common Issues
-
502 Bad Gateway
- Check if Readur is running on the configured port
- Verify
SERVER_PORTenvironment variable - Check container logs:
docker logs readur
-
Large File Upload Failures
- Increase
client_max_body_sizein nginx - Adjust
MAX_FILE_SIZE_MBin Readur config - Check proxy timeout settings
- Increase
-
WebSocket Connection Issues (future feature)
- Ensure
proxy_http_version 1.1is set - Include Upgrade and Connection headers
- Ensure
-
CORS Errors
- Readur includes CORS middleware
- Ensure
X-Forwarded-Protoheader is set correctly - Check if frontend URL matches expected origin
Health Check Monitoring
# Direct health check
curl http://localhost:3000/api/health
# Through reverse proxy
curl https://readur.example.com/api/health
# Expected response
{"status":"ok"}
Debug Headers
Add these to your reverse proxy for debugging:
add_header X-Proxy-Debug "nginx" always;
add_header X-Upstream-Addr $upstream_addr always;
add_header X-Upstream-Status $upstream_status always;
Security Recommendations
-
Always use HTTPS in production
-
Implement rate limiting to prevent abuse
-
Set 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; -
Restrict access to health check endpoint if needed:
location /api/health { allow 10.0.0.0/8; deny all; proxy_pass http://localhost:3000; } -
Use strong JWT secrets and rotate them regularly
-
Monitor access logs for suspicious activity
Performance Optimization
-
Enable caching for static assets:
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ { proxy_pass http://localhost:3000; expires 1y; add_header Cache-Control "public, immutable"; } -
Use HTTP/2 for better performance
-
Enable gzip compression:
gzip on; gzip_types text/plain text/css application/json application/javascript; gzip_min_length 1000; -
Configure connection pooling for database
-
Use CDN for static assets in production