Skip to content

Dev-Toolbelt/reverse-proxy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Reverse Proxy

Docker-based reverse proxy setup using nginx-proxy for automatic service discovery and routing. This setup allows you to run multiple services on a single server and route traffic based on domain names.

Overview

This project provides a centralized reverse proxy solution that:

  • Automatically discovers and configures routing for Docker containers
  • Handles HTTP and HTTPS traffic on ports 80 and 443
  • Supports CORS for cross-origin requests
  • Integrates with Cloudflare for SSL/TLS termination (default)
  • Optionally supports Let's Encrypt for direct SSL certificate management

Architecture

The reverse proxy uses jwilder/nginx-proxy which automatically generates nginx configuration by monitoring Docker containers. When a container starts with VIRTUAL_HOST environment variable, the proxy automatically routes traffic to it.

Key Components:

  • reverse-proxy: Main nginx-proxy container that handles routing
  • acme-companion (optional): Let's Encrypt certificate management
  • External network: reverse-proxy network for service communication

Prerequisites

  • Docker and Docker Compose installed
  • Ports 80 and 443 available on the host
  • Domain names configured (DNS pointing to your server)

Quick Start

  1. Create the external Docker network:

    docker network create reverse-proxy
  2. Start the reverse proxy:

    docker compose up -d
  3. Verify it's running:

    docker compose ps
    docker compose logs -f reverse-proxy

Adding Services

To proxy a service through this reverse proxy, configure it in a separate docker-compose file:

services:
  your-app:
    image: your-image:latest
    environment:
      - VIRTUAL_HOST=yourdomain.com
      - VIRTUAL_PORT=8080  # Only if app doesn't use port 80
    networks:
      - reverse-proxy

networks:
  reverse-proxy:
    external: true

The reverse proxy will automatically detect the new container and configure routing.

SSL/HTTPS Configuration

Using Cloudflare (Default)

By default, this setup is designed to work behind Cloudflare:

  1. Configure your domain's DNS in Cloudflare to point to your server
  2. Set SSL/TLS mode to "Full (strict)" in Cloudflare dashboard
  3. Generate an Origin Certificate in Cloudflare (SSL/TLS > Origin Server > Create Certificate)
  4. Save the certificate and key in nginx/certs/ as <domain>.crt and <domain>.key (e.g., app.com.br.crt and app.com.br.key)
  5. Uncomment the ./nginx/certs volume mount in docker-compose.yml
  6. Restart the proxy: docker compose restart reverse-proxy

The nginx-proxy automatically detects certificates matching the VIRTUAL_HOST domain name.

A self-signed fallback certificate (default.crt/default.key) is included in the project to ensure the default HTTPS server block can complete SSL handshakes when no VIRTUAL_HOST is configured, preventing Cloudflare error 525.

Using Let's Encrypt (Optional)

To use Let's Encrypt instead of Cloudflare:

  1. Uncomment the acme-companion service in docker-compose.yml
  2. Uncomment the ./nginx/certs volume mount in the reverse-proxy service
  3. Update DEFAULT_EMAIL with your email address
  4. Restart the reverse proxy: docker compose up -d
  5. Add LETSENCRYPT_HOST environment variable to your services:
    environment:
      - VIRTUAL_HOST=yourdomain.com
      - LETSENCRYPT_HOST=yourdomain.com

Important: When using Let's Encrypt, your server must be directly accessible on ports 80 and 443 (not proxied through Cloudflare).

Certificate Storage: SSL certificates will be stored in nginx/certs/ and ACME challenge files in nginx/acme/. Domain-specific certificates are in .gitignore for security. The fallback default.crt/default.key are versioned.

Directory Structure

reverse-proxy/
├── docker-compose.yml          # Main configuration
├── nginx/
│   ├── conf.d/
│   │   └── 00-proxy.conf       # Global proxy settings + default server blocks
│   ├── vhost.d/
│   │   └── default             # Security headers
│   ├── html/
│   │   └── index.html          # Custom default page
│   ├── certs/
│   │   ├── default.crt         # Self-signed fallback certificate (versioned)
│   │   ├── default.key         # Self-signed fallback private key (versioned)
│   │   └── <domain>.crt/.key   # Domain-specific certificates (gitignored)
│   └── acme/                   # ACME challenge files (when using Let's Encrypt)
└── README.md

Configuration Files

docker-compose.yml

Main reverse proxy configuration with service definitions and network setup.

nginx/conf.d/00-proxy.conf

Global nginx proxy settings applied to all virtual hosts, plus default server blocks.

Security:

  • Server tokens disabled (hides nginx version)
  • Invalid headers ignored

Client Settings:

  • Unlimited body size for large uploads
  • 512KB body buffer size
  • Optimized header buffers

Timeouts:

  • Client timeouts: 20 seconds (body and headers)
  • Proxy timeouts: 120 seconds (connect, send, read)
  • Keepalive: 15 seconds

Performance:

  • Gzip compression enabled for text, JSON, CSS, JavaScript, fonts, and SVG
  • Compression level 6 (balanced between speed and size)
  • Proxy buffering optimized with 8x4KB buffers

Default Server Blocks:

  • HTTPS (port 443): Uses the self-signed fallback certificate (default.crt/default.key) and serves the default HTML page. This ensures SSL handshakes succeed even when no VIRTUAL_HOST is configured, preventing Cloudflare error 525.
  • HTTP (port 80): Serves the default HTML page for unmatched hosts.
  • Both blocks deny access to hidden files (.env, .git, etc.).

nginx/vhost.d/default

Security headers and CORS configuration applied to all virtual hosts:

Security Headers:

  • X-Frame-Options: SAMEORIGIN - Prevents clickjacking attacks
  • X-Content-Type-Options: nosniff - Prevents MIME type sniffing
  • X-XSS-Protection: 1; mode=block - Enables XSS filter
  • Referrer-Policy: strict-origin-when-cross-origin - Controls referrer information
  • HSTS available (commented by default, enable if using Let's Encrypt)

Additional Protection:

  • Rate limiting: 10 requests/second per IP (burst of 20 allowed)
  • Hidden files blocked (.env, .git, .htaccess, etc.)

nginx/html/index.html

Custom default page displayed when accessing the server without a configured service. Features:

  • Professional, responsive design
  • Clear instructions for configuration
  • Neutral color scheme with gradient background
  • Mobile-friendly layout

nginx/certs/

SSL certificate directory. Contains:

  • default.crt and default.key: Self-signed fallback certificate (10-year validity, versioned in git). Used by the default HTTPS server block.
  • Domain-specific certificates (e.g., app.com.br.crt and app.com.br.key): Cloudflare Origin Certificates or Let's Encrypt certificates. These are gitignored for security.

nginx/acme/ (when using Let's Encrypt)

Directory for ACME challenge files and acme.sh configuration. This directory is ignored by git.

Common Commands

# Start the reverse proxy
docker compose up -d

# Stop the reverse proxy
docker compose down

# View logs
docker compose logs -f reverse-proxy

# Restart after configuration changes
docker compose restart reverse-proxy

# Check status
docker compose ps

Troubleshooting

Seeing the default "Reverse Proxy Configured" page:

  • This means the reverse proxy is working but no service is configured for this domain
  • Verify the container has VIRTUAL_HOST environment variable set
  • Confirm the container is connected to the reverse-proxy network
  • Check that the domain in VIRTUAL_HOST matches the URL you're accessing

Service not accessible:

  • Verify the container is connected to the reverse-proxy network
  • Check that VIRTUAL_HOST is set correctly
  • Review logs: docker compose logs reverse-proxy

SSL issues (Cloudflare error 525 - SSL handshake failed):

  • Verify domain-specific certificates exist in nginx/certs/ (e.g., app.com.br.crt and app.com.br.key)
  • Ensure the ./nginx/certs volume mount is uncommented in docker-compose.yml
  • Confirm Cloudflare SSL mode is set to "Full (strict)"
  • Check that at least the default.crt/default.key fallback certificate is present
  • If using Let's Encrypt, verify ports 80/443 are publicly accessible
  • Check that DNS is properly configured
  • Review logs: docker compose logs reverse-proxy

Security Features

This reverse proxy includes multiple security layers:

DDoS Protection

  • Rate limiting: 10 requests/second per IP with burst capacity of 20
  • Automatic HTTP 429 response when limits are exceeded
  • Connection limiting per IP address

Security Headers

Modern security headers are automatically applied to all responses to protect against common web vulnerabilities:

  • Clickjacking protection: X-Frame-Options prevents your site from being embedded in iframes
  • MIME sniffing prevention: X-Content-Type-Options prevents browsers from MIME-sniffing
  • XSS protection: X-XSS-Protection enables browser XSS filters
  • Referrer control: Strict referrer policy to protect user privacy

Access Control

  • Hidden files (.env, .git, etc.) automatically blocked
  • Invalid HTTP headers rejected
  • Server version information hidden from responses

Performance Optimization

  • Gzip compression reduces bandwidth by 60-80% for text content
  • Optimized buffer sizes for handling large requests
  • Efficient proxy buffering for backend communication
  • Keepalive connections reduce latency

Customization

Adjusting Upload Limits

Edit nginx/conf.d/00-proxy.conf and modify:

client_max_body_size 100M;  # Change to your desired limit

Modifying Rate Limiting

Edit nginx/vhost.d/default to adjust rate limits:

limit_req zone=general burst=20 nodelay;  # Adjust burst value

Or edit nginx/conf.d/00-proxy.conf to change the base rate:

limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;  # Adjust rate

Enabling HSTS (for Let's Encrypt)

If using Let's Encrypt instead of Cloudflare, uncomment in nginx/vhost.d/default:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

CORS Customization

To restrict CORS to specific origins instead of allowing all, edit nginx/vhost.d/default:

# Replace "$http_origin" with your specific domain
add_header 'Access-Control-Allow-Origin' "https://yourdomain.com" always;

License

This is a configuration repository for open-source components. The nginx-proxy and acme-companion images are subject to their respective licenses.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages