A Docker Compose-based reverse proxy solution for hosting multiple web applications across multiple domains, with automatic SSL certificate management via Let's Encrypt.
This project provides a reverse proxy solution using nginx-proxy with automatic SSL certificate generation and renewal through Let's Encrypt. It's perfect for hosting multiple web applications across multiple domains with automatic HTTPS. While primarily designed for Docker containers, it can also be configured to proxy to native services running outside Docker.
AGENTS.md: concise guidance for agentic coding tools operating in this repositoryCHANGELOG.md: historical engineering changes and migration notesdocs/troubleshooting.md: operational troubleshooting runbookdocs/security-checklist.md: periodic security review checklist
- Reverse Proxy: Routes traffic to multiple containers based on hostnames
- Automatic SSL: Let's Encrypt certificates are automatically generated and renewed
- Docker Integration: Seamlessly works with Docker containers via environment variables
- Easy Setup: Simple configuration with Docker Compose
- Security Focused: Comprehensive security measures and monitoring
- Native Service Support: Can be configured to proxy to services running outside Docker (requires manual setup)
- Docker
- Docker Compose
- A domain name pointing to your server
- Ports 80 and 443 available on your host
-
Clone the repository
git clone <repository-url> cd outer-rim
-
Run the secure setup script
./setup.sh
This script will:
- Create necessary directories with proper permissions
- Set up environment file from template
- Validate Docker Compose configuration
- Configure basic firewall rules
- Set up security monitoring
-
Edit environment file
nano .env
IMPORTANT: Update with your actual email for Let's Encrypt notifications:
LETSENCRYPT_EMAIL=your-actual-email@example.com⚠️ Security Note: Never use the default email address. The setup script will validate that you've changed it. -
Start the services
docker-compose up -d
-
Monitor security
# Check service status docker-compose ps # View logs docker-compose logs -f
The .env file contains the following variables:
LETSENCRYPT_EMAIL: Your email address for Let's Encrypt notificationsACME_CA_URI: ACME server URI (staging for testing, production for live)MAX_CERTS_PER_DOMAIN: Maximum certificates per domain (default: 5)CERT_RENEWAL_THRESHOLD: Days before expiration to renew (default: 30)RATE_LIMIT_REQUESTS: Rate limiting requests per window (default: 100)RATE_LIMIT_WINDOW: Rate limiting time window (default: 1m)LOG_LEVEL: Logging level (default: info)
To add your web applications, create additional services in your docker-compose.yml:
services:
your-app:
image: your-app-image
environment:
- VIRTUAL_HOST=your-domain.com
- LETSENCRYPT_HOST=your-domain.com
- LETSENCRYPT_EMAIL=your-email@example.com
networks:
- webFor native services running outside Docker containers:
- Create custom nginx configuration in
nginx/conf.d/your-domain.com.conf - Generate SSL certificate manually or set up automation
- Configure routing to your native service
All services that need to be proxied should be connected to the web network:
networks:
web:
external: false
driver: bridge
driver_opts:
com.docker.network.bridge.name: nginx-proxy
ipam:
config:
- subnet: 172.20.0.0/16SSL certificates are automatically managed by the acme-companion container:
- Automatic Generation: Certificates are created when domains are first accessed
- Automatic Renewal: Certificates are renewed before expiration
- Storage: Certificates are stored in
./nginx/certs/
For troubleshooting or custom certificates:
# Check certificate status
docker-compose logs acme-companion
# Verify certificates are generated
ls -la nginx/certs/
# Test certificate renewal
docker-compose restart acme-companionouter-rim/
├── docker-compose.yml # Main Docker Compose configuration
├── .env # Environment variables (create from env.example)
├── .gitignore # Git ignore rules
├── setup.sh # Secure setup script
├── docs/
│ ├── security-checklist.md # Security audit checklist
│ └── troubleshooting.md # Ops troubleshooting runbook
├── nginx/
│ ├── certs/ # SSL certificates (auto-generated)
│ ├── vhost.d/ # Custom nginx configurations
│ ├── conf.d/ # Additional nginx configurations
│ └── html/ # Static files
├── sites/ # Static site content (nginx.conf files are version controlled)
└── README.md # This file
- Image:
nginxproxy/nginx-proxy:1.8 - Ports: 80, 443
- Purpose: Reverse proxy that automatically routes traffic based on
VIRTUAL_HOSTenvironment variables - Security: Read-only filesystem, resource limits, no new privileges
- Image:
nginxproxy/acme-companion:latest - Purpose: Automatically generates and renews Let's Encrypt SSL certificates
- Dependencies: nginx-proxy
- Security: Resource limits, no new privileges
- Image:
nginx:alpine - Purpose: Example static site configuration
- Domains: xbonell.com, www.xbonell.com
- Custom Configuration: Custom nginx configuration via
./sites/xbonell.com/nginx.conf - Error Handling: Custom 404 error page via
/errorendpoint - Performance: Gzip compression enabled for text-based content
- Security: Read-only filesystem, resource limits
- Image:
nginx:alpine - Purpose: Static site configuration
- Domains: bgespecialitats.com, www.bgespecialitats.com
- Custom Configuration: Custom nginx configuration via
./sites/bgespecialitats.com/nginx.conf - Error Handling: Language-aware 404 error pages (
/ca/404or/es/404) based on URL path or Accept-Language header - Performance: Gzip compression enabled; long-term caching for static assets (CSS, JS, fonts, images) with 1 year expiration
- Security: Read-only filesystem, resource limits
services:
my-webapp:
image: nginx:alpine
environment:
- VIRTUAL_HOST=myapp.example.com
- LETSENCRYPT_HOST=myapp.example.com
- LETSENCRYPT_EMAIL=admin@example.com
networks:
- webservices:
frontend:
image: my-frontend:latest
environment:
- VIRTUAL_HOST=app.example.com
- LETSENCRYPT_HOST=app.example.com
- LETSENCRYPT_EMAIL=admin@example.com
networks:
- web
api:
image: my-api:latest
environment:
- VIRTUAL_HOST=api.example.com
- LETSENCRYPT_HOST=api.example.com
- LETSENCRYPT_EMAIL=admin@example.com
networks:
- webSSL certificates are automatically:
- Generated when a new domain is accessed
- Renewed before expiration
- Stored in
./nginx/certs/
- Ensure your domain points to the server's IP address
- Check that ports 80 and 443 are open
- Verify the email address in your
.envfile - HTTPS not working but HTTP works: Check if
ACME_CA_URIis set to staging. Staging certificates (with_test_prefix) are not trusted by browsers. SetACME_CA_URI=https://acme-v02.api.letsencrypt.org/directoryin your.envfile and recreate the acme-companion container - Certificate generation failures: Check DNS resolution with
dig +short your-domain.com A. Ensure DNS is properly configured before certificate generation
- Make sure all containers are on the
webnetwork - Check that
VIRTUAL_HOSTenvironment variables are set correctly
View logs for troubleshooting:
# nginx-proxy logs
docker-compose logs nginx-proxy
# acme-companion logs
docker-compose logs acme-companion
# All services logs
docker-compose logs -f
# Check service status
docker-compose psThis setup includes comprehensive security measures:
- Read-only root filesystems where possible
- No new privileges security option
- Resource limits to prevent DoS attacks
- Health checks for all services
- Latest image tags for security patches
- Container log rotation to prevent disk bloat
- Compose-enforced resource limits for non-Swarm deployments
- Isolated Docker network with custom subnet
- Rate limiting to prevent abuse
- Security headers (HSTS, CSP, X-Frame-Options, etc.)
- SSL/TLS 1.2+ only with secure cipher suites
- Proper file permissions (600 for sensitive files)
- Hidden file protection in nginx
- Sensitive file blocking (.env, .log, .sql, etc.)
- Docker socket read-only access
- Security checklist for regular audits
- Automated setup script with security validation
- Comprehensive logging for audit trails
- Resource monitoring and limits
- Keep your
.envfile secure and never commit it to version control - Regularly update Docker images for security patches
- Monitor certificate renewal logs
- Use the provided security checklist for regular audits
- Consider using Docker secrets for sensitive environment variables in production
- Run security scans regularly with tools like Trivy
Use the provided security checklist:
# Review docs/security-checklist.md for comprehensive audit guidelines
cat docs/security-checklist.md# Update Docker images
docker-compose pull
# Restart services with new images
docker-compose up -d
# Check for updates
docker-compose images# Check service health
docker-compose ps
# Monitor logs
docker-compose logs -f
# Check resource usage
docker stats- Fork the repository
- Create a feature branch
- Make your changes
- Submit a pull request
This project is licensed under the MIT License - see the LICENSE file for details.
- nginx-proxy - The reverse proxy solution
- acme-companion - Let's Encrypt companion
- Let's Encrypt - Free SSL certificates