{"id":31048966,"url":"https://github.com/kaczmar2/nginx-reverse-proxy","last_synced_at":"2026-05-08T19:32:58.525Z","repository":{"id":309847211,"uuid":"1037683397","full_name":"kaczmar2/nginx-reverse-proxy","owner":"kaczmar2","description":"Opinionated nginx reverse proxy Docker image for homelab environments with SSL termination and security headers","archived":false,"fork":false,"pushed_at":"2026-03-23T02:29:34.000Z","size":43,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-23T22:30:03.839Z","etag":null,"topics":["alpine","container","docker","docker-image","homelab","nginx","nginx-proxy","proxy","reverse-proxy","ssl"],"latest_commit_sha":null,"homepage":"","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kaczmar2.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-08-14T00:50:47.000Z","updated_at":"2026-03-23T02:20:53.000Z","dependencies_parsed_at":"2025-08-14T06:12:59.325Z","dependency_job_id":"0e192414-0990-4c53-87b6-e59dea24e571","html_url":"https://github.com/kaczmar2/nginx-reverse-proxy","commit_stats":null,"previous_names":["kaczmar2/nginx-reverse-proxy"],"tags_count":33,"template":false,"template_full_name":null,"purl":"pkg:github/kaczmar2/nginx-reverse-proxy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kaczmar2%2Fnginx-reverse-proxy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kaczmar2%2Fnginx-reverse-proxy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kaczmar2%2Fnginx-reverse-proxy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kaczmar2%2Fnginx-reverse-proxy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kaczmar2","download_url":"https://codeload.github.com/kaczmar2/nginx-reverse-proxy/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kaczmar2%2Fnginx-reverse-proxy/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32794673,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-08T08:22:46.396Z","status":"ssl_error","status_checked_at":"2026-05-08T08:22:45.650Z","response_time":54,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["alpine","container","docker","docker-image","homelab","nginx","nginx-proxy","proxy","reverse-proxy","ssl"],"created_at":"2025-09-14T21:25:18.151Z","updated_at":"2026-05-08T19:32:58.519Z","avatar_url":"https://github.com/kaczmar2.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# nginx-reverse-proxy\n\n[![Docker Build, Test and Publish](https://github.com/kaczmar2/nginx-reverse-proxy/actions/workflows/docker-build.yml/badge.svg)](https://github.com/kaczmar2/nginx-reverse-proxy/actions/workflows/docker-build.yml) [![Base Image Update Check](https://github.com/kaczmar2/nginx-reverse-proxy/actions/workflows/base-image-update.yml/badge.svg)](https://github.com/kaczmar2/nginx-reverse-proxy/actions/workflows/base-image-update.yml)\n\nAn opinionated nginx reverse proxy Docker image designed for easy configuration management in homelab environments. This image provides a battle-tested nginx configuration with modern security settings, requiring users to only manage their site-specific reverse proxy configurations.\n\n## Features\n\n- **Based on `nginx:alpine`** for minimal size and security\n- **Opinionated configuration** with proven nginx.conf, SSL settings, and security headers\n- **Modular includes** for SSL, proxy headers, WebSocket support, and HSTS\n- **Example configurations** for common homelab services (UniFi, Pi-hole, Home Assistant, etc.)\n- **Custom landing page** showing the proxy is running\n- **SSL-ready** with organized certificate structure\n\n## Quick Start\n\n```bash\n# Run with default configuration (serves landing page)\ndocker run -d \\\n  --name nginx-proxy \\\n  -p 80:80 \\\n  -p 443:443 \\\n  kaczmar2/nginx-reverse-proxy\n\n# Visit http://localhost to see the landing page\n```\n\n## Getting Started Guide\n\nThis guide walks you through setting up nginx-reverse-proxy from scratch to a working reverse proxy with SSL.\n\n### Prerequisites\n\n- Docker and Docker Compose installed\n- A domain name pointing to your server\n- Basic understanding of nginx configuration\n\n### Step 1: Initial Setup\n\n```bash\n# Create a new directory for your proxy\nmkdir nginx-reverse-proxy \u0026\u0026 cd nginx-reverse-proxy\n\n# Create the required directory structure\nmkdir -p sites ssl\n\n# Download the example docker-compose.yml\nwget https://raw.githubusercontent.com/kaczmar2/nginx-reverse-proxy/main/docker-compose.yml\n```\n\n### Step 2: Start the Container and Explore Examples\n\n```bash\n# Start the container to access example configurations\ndocker-compose up -d\n\n# Verify it's working - you should see the landing page\ncurl http://localhost\n\n# List available example configurations\ndocker exec nginx-proxy ls -la /etc/nginx/sites.template/\n\n# Copy an example that matches your service type\n# For a web service (like a NAS):\ndocker cp nginx-proxy:/etc/nginx/sites.template/01-nas.mydomain.com.conf ./sites/my-service.conf\n\n# For a service needing WebSocket support (like Home Assistant):\ndocker cp nginx-proxy:/etc/nginx/sites.template/04-ha.mydomain.com.conf ./sites/my-ha.conf\n```\n\n### Step 3: Configure Your Service\n\nEdit your copied configuration file:\n\n```bash\nnano sites/my-service.conf\n```\n\n**Replace these values:**\n- `nas.mydomain.com` → your actual domain (e.g., `jellyfin.homelab.local`)\n- `10.10.10.30:5000` → your service's IP:port (e.g., `192.168.1.100:8096`)\n- SSL certificate paths → match your domain name\n\n**Example modification:**\n```nginx\n# Change from:\nserver_name nas.mydomain.com;\nproxy_pass http://10.10.10.30:5000;\nssl_certificate /etc/nginx/ssl/nas.mydomain.com/fullchain.pem;\n\n# To:\nserver_name jellyfin.homelab.local;\nproxy_pass http://192.168.1.100:8096;\nssl_certificate /etc/nginx/ssl/jellyfin.homelab.local/fullchain.pem;\n```\n\n### Step 4: Generate SSL Certificates\n\nWe'll use acme.sh for SSL certificate generation. Install it first if you haven't already:\n\n```bash\n# Install acme.sh\ncurl https://get.acme.sh | sh\nsource ~/.bashrc\n```\n\nGenerate and install certificates for your domain:\n\n```bash\n# Set up your DNS provider credentials (example uses Cloudflare)\nexport CF_Email=\"your-email@example.com\"\nexport CF_Key=\"your-cloudflare-global-api-key\"\n\n# Issue the certificate using DNS challenge\nacme.sh --issue --dns dns_cf -d your-domain.com --server letsencrypt\n\n# Create the SSL directory for your domain\nmkdir -p ssl/your-domain.com\n\n# Install the certificate\nacme.sh --install-cert -d your-domain.com \\\n  --key-file $(pwd)/ssl/your-domain.com/privkey.pem \\\n  --fullchain-file $(pwd)/ssl/your-domain.com/fullchain.pem \\\n  --reloadcmd \"docker exec nginx-proxy nginx -s reload\"\n```\n\nFor other DNS providers or challenge methods, see the [acme.sh documentation](https://github.com/acmesh-official/acme.sh).\n\n### Step 5: Test and Deploy\n\n```bash\n# Start the reverse proxy\ndocker-compose up -d\n\n# Test the configuration\ndocker exec nginx-proxy nginx -t\n\n# Check the logs for any errors\ndocker-compose logs nginx-proxy\n\n# Test your service (replace with your domain)\ncurl -k https://your-domain.com/health\n\n# If using a browser, navigate to https://your-domain.com\n```\n\n### Step 6: Add More Services\n\nFor additional services, repeat steps 2-5:\n\n```bash\n# Copy another example\ndocker cp nginx-proxy:/etc/nginx/sites.template/00-unifi.mydomain.com.conf ./sites/unifi.conf\n\n# Edit the configuration\nnano sites/unifi.conf\n\n# Generate SSL certificate for the new domain\nacme.sh --issue -d unifi.your-domain.com --standalone\n\n# Restart to reload configuration\ndocker-compose restart nginx-proxy\n```\n\n### Common Issues and Solutions\n\n**Issue: Certificate errors**\n```bash\n# Check certificate files exist and have correct permissions\nls -la ssl/your-domain.com/\n# Should show: fullchain.pem (644) and privkey.pem (600)\n```\n\n**Issue: Service not accessible**\n```bash\n# Verify your backend service is reachable from the container\ndocker exec nginx-proxy ping 192.168.1.100\ndocker exec nginx-proxy curl http://192.168.1.100:8080\n```\n\n**Issue: nginx won't start**\n```bash\n# Check configuration syntax\ndocker exec nginx-proxy nginx -t\n\n# Review the logs\ndocker-compose logs nginx-proxy\n```\n\n**Issue: WebSocket connections fail**\n```bash\n# Ensure your configuration includes WebSocket settings\ngrep -r \"websocket_settings\" sites/\n# Should show: include /etc/nginx/includes/websocket_settings.conf;\n```\n\n### Testing Your Configuration\n\n```bash\n# Test SSL certificate\nopenssl s_client -connect your-domain.com:443 -servername your-domain.com\n\n# Test HTTP to HTTPS redirect\ncurl -I http://your-domain.com\n\n# Test health endpoint\ncurl https://your-domain.com/health\n\n# Check response headers for security\ncurl -I https://your-domain.com\n# Should include: Strict-Transport-Security header\n```\n\n### Automated Certificate Renewal\n\nacme.sh automatically installs a cron job for certificate renewal, but let's verify it's configured correctly:\n\n```bash\n# Check if acme.sh cron job is installed\ncrontab -l | grep acme.sh\n\n# List all certificates managed by acme.sh\nacme.sh --list\n\n# Test renewal (dry run) - doesn't actually renew\nacme.sh --renew -d your-domain.com --dry-run\n\n# Force renewal for testing (only use during testing)\nacme.sh --renew -d your-domain.com --force\n\n# Check renewal logs\ntail -f ~/.acme.sh/acme.sh.log\n```\n\n**The automatic renewal will:**\n1. Renew certificates before they expire (typically 60 days before expiration)\n2. Automatically install renewed certificates to your ssl directory\n3. Execute the reload command to restart your nginx container\n4. Send email notifications if renewal fails (if configured)\n\n**Manual renewal** (if needed):\n```bash\n# Renew a specific certificate\nacme.sh --renew -d your-domain.com\n\n# Renew all certificates\nacme.sh --renew-all\n```\n\n### Production Considerations\n\n1. **Backup your certificates and configurations**\n2. **Monitor certificate expiration dates**\n3. **Use strong SSL ciphers** (already configured in the image)\n4. **Keep the Docker image updated**\n5. **Monitor nginx logs** for suspicious activity\n6. **Consider using fail2ban** for additional security\n\n### Next Steps\n\n- Set up monitoring for your services\n- Configure log rotation\n- Add additional security headers if needed\n- Consider implementing rate limiting for public-facing services\n\n## Getting Started\n\n### 1. Set up your directory structure\n\n```bash\n# Create directories for your configurations\nmkdir -p sites ssl\n\n# Your directory structure should look like:\n# ./sites/          # Your reverse proxy site configs\n# ./ssl/             # SSL certificates organized by domain\n```\n\n### 2. Copy example configurations\n\n```bash\n# Start the container to access examples\ndocker run -d --name nginx-proxy-temp kaczmar2/nginx-reverse-proxy\n\n# Copy an example configuration\ndocker cp nginx-proxy-temp:/etc/nginx/sites.template/01-nas.mydomain.com.conf ./sites/my-service.conf\n\n# Clean up\ndocker stop nginx-proxy-temp \u0026\u0026 docker rm nginx-proxy-temp\n```\n\n### 3. Edit your configuration\n\n```bash\n# Edit the copied config file\nnano sites/my-service.conf\n\n# Replace:\n# - 'nas.mydomain.com' with your actual domain\n# - '10.10.10.30:5000' with your service IP:port\n# - SSL certificate paths if needed\n```\n\n### 4. Generate SSL certificates (recommended)\n\n```bash\n# Using acme.sh (recommended method)\n# Install acme.sh first: https://github.com/acmesh-official/acme.sh\n\n# Generate certificate for your domain\nacme.sh --issue -d your-domain.com --standalone\n\n# Copy certificates to your ssl directory\nmkdir -p ssl/your-domain.com\ncp ~/.acme.sh/your-domain.com/fullchain.cer ssl/your-domain.com/fullchain.pem\ncp ~/.acme.sh/your-domain.com/your-domain.com.key ssl/your-domain.com/privkey.pem\n```\n\n### 5. Run with Docker Compose (recommended)\n\n```yaml\n# docker-compose.yml\nversion: '3.8'\n\nservices:\n  nginx-proxy:\n    image: kaczmar2/nginx-reverse-proxy:latest\n    container_name: nginx-proxy\n    restart: unless-stopped\n    ports:\n      - \"80:80\"\n      - \"443:443\"\n    volumes:\n      - ./sites:/etc/nginx/sites\n      - ./ssl:/etc/nginx/ssl\n    environment:\n      - TZ=America/Denver\n```\n\n```bash\n# Start the proxy\ndocker-compose up -d\n```\n\n## Configuration Structure\n\nThis image uses an opinionated structure where most configuration is built-in:\n\n```\nBuilt into image (opinionated):\n├── nginx.conf              # Main nginx config with WebSocket support\n├── conf.d/default.conf     # Serves the landing page\n└── includes/               # Reusable configuration snippets\n    ├── ssl_settings.conf   # Modern TLS configuration\n    ├── proxy_settings.conf # Standard proxy headers\n    ├── hsts_settings.conf  # HTTP Strict Transport Security\n    ├── websocket_settings.conf # WebSocket proxy support\n    └── keepalive_settings.conf # Keep-alive for embedded devices\n\nUser manages:\n├── sites/                  # Your reverse proxy configurations\n└── ssl/                    # SSL certificates organized by domain\n    ├── example.com/\n    │   ├── fullchain.pem\n    │   └── privkey.pem\n    └── another.com/\n        ├── fullchain.pem\n        └── privkey.pem\n```\n\n**Site Naming Convention:** Use numbered prefixes (e.g., `00-`, `01-`, `02-`) for your site configs to control the load order.\n\n## Example Site Configurations\n\nExample configurations are included for common homelab services:\n\n- **`00-unifi.mydomain.com.conf`** - UniFi Network Application (UDM-Pro, CloudKey, etc.)\n  - HTTPS proxy with WebSocket support for real-time updates\n  - Handles self-signed backend certificates\n  \n- **`01-nas.mydomain.com.conf`** - Synology NAS web interface (DSM)\n  - Standard HTTPS proxy for NAS management\n  \n- **`02-pihole.mydomain.com.conf`** - Pi-hole DNS management interface\n  - Simple HTTP-to-HTTPS reverse proxy\n  \n- **`03-print.mydomain.com.conf`** - HP Printer web interface\n  - Includes keep-alive settings for embedded web servers\n  \n- **`04-ha.mydomain.com.conf`** - Home Assistant with Z-Wave JS UI sub-path\n  - Main service on `/` with WebSocket support\n  - Z-Wave JS UI accessible at `/zwave/` subdirectory\n  - Demonstrates complex URL rewriting and multiple backend services\n\nEach example includes:\n- HTTP to HTTPS redirect\n- SSL certificate configuration\n- Security headers (HSTS)\n- Service-specific optimizations\n\n## Volume Mounts\n\nThe simplified approach only requires mounting what you customize:\n\n```bash\ndocker run -d \\\n  --name nginx-proxy \\\n  -p 80:80 -p 443:443 \\\n  -v ./sites:/etc/nginx/sites \\\n  -v ./ssl:/etc/nginx/ssl \\\n  kaczmar2/nginx-reverse-proxy\n```\n\nOptional mounts:\n```bash\n# Override the landing page\n-v ./custom-html:/usr/share/nginx/html\n```\n\n## SSL Certificate Management\n\n### Using acme.sh\n\nInstall acme.sh and generate certificates:\n\n```bash\n# Install acme.sh\ncurl https://get.acme.sh | sh\nsource ~/.bashrc\n\n# Set up DNS provider credentials (example uses Cloudflare)\nexport CF_Email=\"your-email@example.com\"\nexport CF_Key=\"your-cloudflare-global-api-key\"\n\n# Issue certificate\nacme.sh --issue --dns dns_cf -d your-domain.com --server letsencrypt\n\n# Install certificate\nmkdir -p ssl/your-domain.com\nacme.sh --install-cert -d your-domain.com \\\n  --key-file ssl/your-domain.com/privkey.pem \\\n  --fullchain-file ssl/your-domain.com/fullchain.pem \\\n  --reloadcmd \"docker exec nginx-proxy nginx -s reload\"\n```\n\nFor other DNS providers or challenge methods, see the [acme.sh documentation](https://github.com/acmesh-official/acme.sh).\n\n## Building from Source\n\n```bash\ngit clone https://github.com/kaczmar2/nginx-reverse-proxy.git\ncd nginx-reverse-proxy\ndocker build -t nginx-reverse-proxy .\n```\n\n## Available Images\n\n- **Docker Hub**: `docker pull kaczmar2/nginx-reverse-proxy`\n- **GitHub Container Registry**: `docker pull ghcr.io/kaczmar2/nginx-reverse-proxy`\n\n## License\n\nMIT License - see [LICENSE](LICENSE) file for details.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkaczmar2%2Fnginx-reverse-proxy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkaczmar2%2Fnginx-reverse-proxy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkaczmar2%2Fnginx-reverse-proxy/lists"}