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:
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 readur: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¶
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_PORT
environment variable -
Check container logs:
docker logs readur
-
Large File Upload Failures
- Increase
client_max_body_size
in nginx - Adjust
MAX_FILE_SIZE_MB
in Readur config -
Check proxy timeout settings
-
WebSocket Connection Issues (future feature)
- Ensure
proxy_http_version 1.1
is set -
Include Upgrade and Connection headers
-
CORS Errors
- Readur includes CORS middleware
- Ensure
X-Forwarded-Proto
header 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:
-
Restrict access to health check endpoint if needed:
-
Use strong JWT secrets and rotate them regularly
- Monitor access logs for suspicious activity
Performance Optimization¶
-
Enable caching for static assets:
-
Use HTTP/2 for better performance
-
Enable gzip compression:
-
Configure connection pooling for database
- Use CDN for static assets in production