Revamp Swarm example documentation and streamline deployment instructions
- Consolidated and simplified Swarm example README to focus on YAML header comments for documentation. - Removed redundant and extended sections, replacing with concise steps for getting started. - Standardized YAML headers across `easyhaproxy.yml`, `services.yml`, and `portainer.yml` with a clearer and more readable format. - Enhanced user guidance for deployment, setup requirements, verification, and cleanup.
This commit is contained in:
parent
5397f0166e
commit
b9a9bee0b9
29 changed files with 1459 additions and 2861 deletions
|
|
@ -1,590 +1,52 @@
|
|||
# Docker Compose Examples
|
||||
|
||||
This directory contains various Docker Compose examples demonstrating different EasyHAProxy configurations.
|
||||
Self-contained examples for EasyHAProxy. **All documentation is in the docker-compose files as header comments.**
|
||||
|
||||
## Prerequisites: Generate SSL Certificates
|
||||
## Quick Start
|
||||
|
||||
**IMPORTANT:** Before running any examples, you must generate the required SSL certificates and JWT keys:
|
||||
1. Pick an example below
|
||||
2. Open the docker-compose file
|
||||
3. Read the header comments for complete instructions
|
||||
4. Run the commands step-by-step
|
||||
|
||||
```bash
|
||||
# From the repository root
|
||||
./examples/generate-keys.sh
|
||||
```
|
||||
## Basic Examples
|
||||
|
||||
This script automatically generates:
|
||||
- SSL certificates for host1.local and host2.local
|
||||
- JWT keys (jwt_private.pem and jwt_pubkey.pem) for JWT validation examples
|
||||
- All other .pem files needed for testing
|
||||
| File | Description |
|
||||
|----------------------------------------------------------------------------|----------------------------------------------------------------|
|
||||
| [docker-compose.yml](docker-compose.yml) | Basic SSL setup with two virtual hosts and stats interface |
|
||||
| [docker-compose-acme.yml](docker-compose-acme.yml) | Let's Encrypt SSL with automatic certificate generation |
|
||||
| [docker-compose-multi-containers.yml](docker-compose-multi-containers.yml) | Load balancing across multiple container replicas |
|
||||
| [docker-compose-changed-label.yml](docker-compose-changed-label.yml) | Using custom label prefix (for multiple EasyHAProxy instances) |
|
||||
|
||||
**Note:** These are self-signed certificates for testing only. Do not use in production.
|
||||
## Real-World Application Examples
|
||||
|
||||
---
|
||||
|
||||
## Examples Overview
|
||||
|
||||
### 1. Basic Configuration (`docker-compose.yml`)
|
||||
|
||||
**What it demonstrates:**
|
||||
- Basic SSL setup with two virtual hosts
|
||||
- SSL redirect (HTTP → HTTPS)
|
||||
- Custom SSL certificates (embedded and file-based)
|
||||
- HAProxy stats interface
|
||||
|
||||
**Features:**
|
||||
- `host1.local`: SSL certificate embedded as base64 in labels
|
||||
- `host2.local`: SSL certificate loaded from file (`host2.local.pem`)
|
||||
- Automatic HTTP to HTTPS redirect
|
||||
- Stats available at port 1936
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
**Test:**
|
||||
```bash
|
||||
# Test HTTPS
|
||||
curl -k -H "Host: host1.local" https://127.0.0.1/
|
||||
curl -k -H "Host: host2.local" https://127.0.0.1/
|
||||
|
||||
# Test HTTP redirect
|
||||
curl -I -H "Host: host1.local" http://127.0.0.1
|
||||
# Should return: HTTP/1.1 301 Moved Permanently
|
||||
|
||||
# View SSL certificate
|
||||
openssl s_client -showcerts -connect 127.0.0.1:443 -servername host1.local
|
||||
```
|
||||
|
||||
**Access stats:**
|
||||
- URL: http://localhost:1936
|
||||
- Username: `admin`
|
||||
- Password: `password`
|
||||
|
||||
---
|
||||
|
||||
### 2. ACME/Let's Encrypt (`docker-compose-acme.yml`)
|
||||
|
||||
**What it demonstrates:**
|
||||
- Automatic SSL certificate generation using Let's Encrypt
|
||||
- HTTP-01 ACME challenge
|
||||
- Certificate persistence
|
||||
|
||||
**Requirements:**
|
||||
- Public IP address pointing to your machine
|
||||
- Open ports 80 and 443 in firewall
|
||||
- Valid domain name
|
||||
|
||||
**Configuration:**
|
||||
```yaml
|
||||
EASYHAPROXY_CERTBOT_EMAIL: user@example.com # Change this!
|
||||
easyhaproxy.http.certbot: true # Enable certbot
|
||||
```
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
# Edit docker-compose-acme.yml and set:
|
||||
# - EASYHAPROXY_CERTBOT_EMAIL to your email
|
||||
# - easyhaproxy.http.host to your domain
|
||||
|
||||
docker compose -f docker-compose-acme.yml up -d
|
||||
```
|
||||
|
||||
**Certificate storage:**
|
||||
Certificates are persisted in `./certs/certbot/` to avoid re-challenges on restart.
|
||||
|
||||
---
|
||||
|
||||
### 3. Multiple Containers with Load Balancing (`docker-compose-multi-containers.yml`)
|
||||
|
||||
**What it demonstrates:**
|
||||
- Multiple containers behind single domain
|
||||
- Load balancing with round-robin
|
||||
- Domain redirect functionality
|
||||
|
||||
**Features:**
|
||||
- 2 replicas of nginx container
|
||||
- Load balancing across replicas
|
||||
- Domain redirect: `google.helloworld.com` → `www.google.com`
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
docker compose -f docker-compose-multi-containers.yml up -d
|
||||
```
|
||||
|
||||
**Test:**
|
||||
```bash
|
||||
# Test load balancing (hostname changes between containers)
|
||||
curl -H "Host: www.helloworld.com" localhost:19901
|
||||
# Response: f6d8d45b7411
|
||||
curl -H "Host: www.helloworld.com" localhost:19901
|
||||
# Response: 59b213cb8592
|
||||
|
||||
# Test redirect
|
||||
curl -I -H "Host: google.helloworld.com" localhost:19901
|
||||
# Should redirect to: www.google.com/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. Changed Label Prefix (`docker-compose-changed-label.yml`)
|
||||
|
||||
**What it demonstrates:**
|
||||
- Using custom label prefix instead of default `easyhaproxy`
|
||||
- Useful for running multiple EasyHAProxy instances
|
||||
|
||||
**Configuration:**
|
||||
```yaml
|
||||
environment:
|
||||
EASYHAPROXY_LABEL_PREFIX: myproxy
|
||||
```
|
||||
|
||||
**Container labels:**
|
||||
```yaml
|
||||
labels:
|
||||
myproxy.http.host: example.com
|
||||
myproxy.http.port: 80
|
||||
```
|
||||
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
docker compose -f docker-compose-changed-label.yml up -d
|
||||
```
|
||||
|
||||
**Test:**
|
||||
```bash
|
||||
# Test load balancing (hostname changes between containers)
|
||||
curl -H "Host: www.helloworld.com" localhost:19901
|
||||
# Response: f6d8d45b7411
|
||||
curl -H "Host: www.helloworld.com" localhost:19901
|
||||
# Response: 59b213cb8592
|
||||
|
||||
# Test redirect
|
||||
curl -I -H "Host: google.helloworld.com" localhost:19901
|
||||
# Should redirect to: www.google.com/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5. Portainer Integration (`docker-compose-portainer.yml`)
|
||||
|
||||
**What it demonstrates:**
|
||||
- Running Portainer behind EasyHAProxy
|
||||
- Real-world application example
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
docker compose -f docker-compose-portainer.yml up -d
|
||||
```
|
||||
|
||||
**Access Portainer:**
|
||||
- URL: http://portainer.local (add to `/etc/hosts` or use real DNS)
|
||||
- First time: Create admin user
|
||||
|
||||
---
|
||||
|
||||
### 6. Portainer + App Example (`docker-compose-portainer-app-example.yml`)
|
||||
|
||||
**What it demonstrates:**
|
||||
- Multiple applications behind EasyHAProxy
|
||||
- Portainer + custom app setup
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
docker compose -f docker-compose-portainer-app-example.yml up -d
|
||||
```
|
||||
|
||||
---
|
||||
| File | Description |
|
||||
|--------------------------------------------------------------------------------------|-----------------------------------------------------|
|
||||
| [docker-compose-portainer.yml](docker-compose-portainer.yml) | Portainer behind EasyHAProxy with Let's Encrypt |
|
||||
| [docker-compose-portainer-app-example.yml](docker-compose-portainer-app-example.yml) | Additional app alongside Portainer (shared network) |
|
||||
|
||||
## Plugin Examples
|
||||
|
||||
### FastCGI Plugin with PHP-FPM
|
||||
| File | Description |
|
||||
|----------------------------------------------------------------------------|-----------------------------------------------------|
|
||||
| [docker-compose-php-fpm.yml](docker-compose-php-fpm.yml) | FastCGI plugin with PHP-FPM and PATH_INFO routing |
|
||||
| [docker-compose-jwt-validator.yml](docker-compose-jwt-validator.yml) | JWT token validation for API protection |
|
||||
| [docker-compose-ip-whitelist.yml](docker-compose-ip-whitelist.yml) | IP whitelist for admin panels or sensitive services |
|
||||
| [docker-compose-cloudflare.yml](docker-compose-cloudflare.yml) | Restore real client IPs when behind Cloudflare CDN |
|
||||
| [docker-compose-plugins-combined.yml](docker-compose-plugins-combined.yml) | Multiple plugins combined for layered security |
|
||||
|
||||
Run PHP applications with FastCGI protocol support:
|
||||
## Documentation Structure
|
||||
|
||||
**File:** `docker-compose-php-fpm.yml`
|
||||
Each docker-compose file contains:
|
||||
- **WHAT THIS DEMONSTRATES** - Key features and concepts
|
||||
- **REQUIREMENTS** - Idempotent setup commands (safe to run multiple times)
|
||||
- **HOW TO START** - Command to launch the stack
|
||||
- **HOW TO VERIFY IT'S WORKING** - Test commands with expected outputs
|
||||
- **CLEAN UP** - Commands to stop and remove resources
|
||||
|
||||
**What it demonstrates:**
|
||||
- PHP-FPM 8.5 with TCP connection on port 9000
|
||||
- FastCGI protocol support (`proto: fcgi`)
|
||||
- FastCGI plugin for PHP environment configuration
|
||||
- Custom document root and index file
|
||||
- PATH_INFO support for RESTful routing
|
||||
## Additional Documentation
|
||||
|
||||
**Features:**
|
||||
- HAProxy forwards requests to PHP-FPM via TCP (port 9000)
|
||||
- FastCGI plugin generates `fcgi-app` configuration that defines CGI parameters:
|
||||
- `SCRIPT_FILENAME`, `DOCUMENT_ROOT`, `REQUEST_URI`
|
||||
- `QUERY_STRING`, `REQUEST_METHOD`, `CONTENT_TYPE`
|
||||
- `SERVER_NAME`, `SERVER_PORT`, `HTTPS`
|
||||
- `PATH_INFO` (for routing support)
|
||||
- Sample PHP application included in `php-app/` directory
|
||||
|
||||
**Configuration:**
|
||||
```yaml
|
||||
services:
|
||||
haproxy:
|
||||
image: byjg/easy-haproxy:4.6.0
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
environment:
|
||||
EASYHAPROXY_DISCOVER: docker
|
||||
ports:
|
||||
- "80:80/tcp"
|
||||
|
||||
php-fpm:
|
||||
image: byjg/php:8.5-fpm
|
||||
volumes:
|
||||
- ./php-app:/var/www/html:ro
|
||||
labels:
|
||||
easyhaproxy.http.host: phpapp.local
|
||||
easyhaproxy.http.port: 80
|
||||
# PHP-FPM listens on port 9000
|
||||
easyhaproxy.http.localport: 9000
|
||||
easyhaproxy.http.proto: fcgi
|
||||
# Enable FastCGI plugin
|
||||
easyhaproxy.http.plugins: fastcgi
|
||||
easyhaproxy.http.plugin.fastcgi.document_root: /var/www/html
|
||||
easyhaproxy.http.plugin.fastcgi.index_file: index.php
|
||||
easyhaproxy.http.plugin.fastcgi.path_info: "true"
|
||||
```
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
# Add to /etc/hosts
|
||||
echo "127.0.0.1 phpapp.local" | sudo tee -a /etc/hosts
|
||||
|
||||
# Start the stack
|
||||
docker compose -f docker-compose-php-fpm.yml up -d
|
||||
|
||||
# Test PHP application
|
||||
curl http://phpapp.local/
|
||||
curl http://phpapp.local/info.php
|
||||
curl http://phpapp.local/test-path-info.php/users/123
|
||||
```
|
||||
|
||||
**Alternative: Unix Socket Connection**
|
||||
|
||||
For PHP-FPM images that support Unix sockets, you can use socket connection:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
haproxy:
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- php-fpm-socket:/run/php
|
||||
|
||||
php-fpm:
|
||||
image: php:8.2-fpm # Official PHP image supports sockets
|
||||
volumes:
|
||||
- php-fpm-socket:/run/php
|
||||
- ./php-app:/var/www/html:ro
|
||||
labels:
|
||||
easyhaproxy.http.host: phpapp.local
|
||||
easyhaproxy.http.port: 80
|
||||
easyhaproxy.http.socket: /run/php/php-fpm.sock
|
||||
easyhaproxy.http.proto: fcgi
|
||||
easyhaproxy.http.plugins: fastcgi
|
||||
# ... plugin configuration
|
||||
|
||||
volumes:
|
||||
php-fpm-socket:
|
||||
```
|
||||
|
||||
**Sample Application:**
|
||||
|
||||
The `php-app/` directory contains:
|
||||
- `index.php` - Main page showing FastCGI environment
|
||||
- `info.php` - PHP configuration info (phpinfo)
|
||||
- `test-path-info.php` - PATH_INFO routing demonstration
|
||||
|
||||
**What the FastCGI plugin does:**
|
||||
1. Sets `SCRIPT_FILENAME` with proper document root path
|
||||
2. Handles directory requests (appends `index.php`)
|
||||
3. Sets all standard CGI environment variables
|
||||
4. Enables `PATH_INFO` for RESTful URL routing
|
||||
5. Supports custom FastCGI parameters
|
||||
|
||||
---
|
||||
|
||||
### JWT Validator Plugin
|
||||
|
||||
Protect your API with JWT token validation:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
haproxy:
|
||||
image: byjg/easy-haproxy:4.6.0
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ./jwt_pubkey.pem:/etc/haproxy/jwt_keys/api_pubkey.pem:ro
|
||||
environment:
|
||||
EASYHAPROXY_DISCOVER: docker
|
||||
HAPROXY_USERNAME: admin
|
||||
HAPROXY_PASSWORD: password
|
||||
HAPROXY_STATS_PORT: 1936
|
||||
ports:
|
||||
- "80:80/tcp"
|
||||
- "443:443/tcp"
|
||||
- "1936:1936/tcp"
|
||||
|
||||
api:
|
||||
image: my-api:latest
|
||||
labels:
|
||||
easyhaproxy.http.host: api.example.com
|
||||
easyhaproxy.http.port: 80
|
||||
easyhaproxy.http.localport: 8080
|
||||
# Enable JWT validation
|
||||
easyhaproxy.http.plugins: jwt_validator
|
||||
easyhaproxy.http.plugin.jwt_validator.algorithm: RS256
|
||||
easyhaproxy.http.plugin.jwt_validator.issuer: https://auth.example.com/
|
||||
easyhaproxy.http.plugin.jwt_validator.audience: https://api.example.com
|
||||
easyhaproxy.http.plugin.jwt_validator.pubkey_path: /etc/haproxy/jwt_keys/api_pubkey.pem
|
||||
```
|
||||
|
||||
**What it validates:**
|
||||
- Authorization header presence
|
||||
- JWT signing algorithm
|
||||
- JWT issuer and audience
|
||||
- JWT signature using public key
|
||||
- JWT expiration time
|
||||
|
||||
**Test:**
|
||||
```bash
|
||||
# Without token - should fail
|
||||
curl http://api.example.com/endpoint
|
||||
# Response: Missing Authorization HTTP header
|
||||
|
||||
# With valid JWT token
|
||||
curl -H "Authorization: Bearer eyJhbGc..." http://api.example.com/endpoint
|
||||
# Response: Success
|
||||
```
|
||||
|
||||
**Generate test public key:**
|
||||
```bash
|
||||
# Generate private key
|
||||
openssl genrsa -out jwt_private.pem 2048
|
||||
|
||||
# Extract public key
|
||||
openssl rsa -in jwt_private.pem -pubout -out jwt_pubkey.pem
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Cloudflare IP Restoration Plugin
|
||||
|
||||
Restore original visitor IPs when using Cloudflare CDN:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
haproxy:
|
||||
image: byjg/easy-haproxy:4.6.0
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ./cloudflare_ips.lst:/etc/haproxy/cloudflare_ips.lst:ro
|
||||
environment:
|
||||
EASYHAPROXY_DISCOVER: docker
|
||||
ports:
|
||||
- "80:80/tcp"
|
||||
- "443:443/tcp"
|
||||
|
||||
webapp:
|
||||
image: my-webapp:latest
|
||||
labels:
|
||||
easyhaproxy.http.host: myapp.com
|
||||
easyhaproxy.http.port: 80
|
||||
easyhaproxy.http.localport: 3000
|
||||
# Enable Cloudflare plugin
|
||||
easyhaproxy.http.plugins: cloudflare
|
||||
```
|
||||
|
||||
**Setup Cloudflare IP list:**
|
||||
```bash
|
||||
# Download Cloudflare IP ranges
|
||||
curl https://www.cloudflare.com/ips-v4 > cloudflare_ips.lst
|
||||
curl https://www.cloudflare.com/ips-v6 >> cloudflare_ips.lst
|
||||
```
|
||||
|
||||
**What it does:**
|
||||
- Detects requests from Cloudflare IPs
|
||||
- Restores original visitor IP from `CF-Connecting-IP` header
|
||||
- Your application logs show real visitor IPs, not Cloudflare IPs
|
||||
|
||||
---
|
||||
|
||||
### IP Whitelist Plugin
|
||||
|
||||
Restrict access to specific IP addresses:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
haproxy:
|
||||
image: byjg/easy-haproxy:4.6.0
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
environment:
|
||||
EASYHAPROXY_DISCOVER: docker
|
||||
ports:
|
||||
- "80:80/tcp"
|
||||
|
||||
admin_panel:
|
||||
image: admin-panel:latest
|
||||
labels:
|
||||
easyhaproxy.http.host: admin.example.com
|
||||
easyhaproxy.http.port: 80
|
||||
easyhaproxy.http.localport: 8080
|
||||
# Enable IP whitelist
|
||||
easyhaproxy.http.plugins: ip_whitelist
|
||||
easyhaproxy.http.plugin.ip_whitelist.allowed_ips: 192.168.1.0/24,10.0.0.5
|
||||
easyhaproxy.http.plugin.ip_whitelist.status_code: 403
|
||||
```
|
||||
|
||||
**Allowed IP formats:**
|
||||
- Single IP: `10.0.0.5`
|
||||
- CIDR range: `192.168.1.0/24`
|
||||
- Multiple (comma-separated): `192.168.1.0/24,10.0.0.5,172.16.0.100`
|
||||
|
||||
**Test:**
|
||||
```bash
|
||||
# From allowed IP
|
||||
curl http://admin.example.com
|
||||
# Response: Success
|
||||
|
||||
# From blocked IP
|
||||
curl http://admin.example.com
|
||||
# Response: HTTP 403 Forbidden
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Multiple Plugins Combined
|
||||
|
||||
Combine multiple plugins for enhanced security:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
haproxy:
|
||||
image: byjg/easy-haproxy:4.6.0
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ./cloudflare_ips.lst:/etc/haproxy/cloudflare_ips.lst:ro
|
||||
environment:
|
||||
EASYHAPROXY_DISCOVER: docker
|
||||
ports:
|
||||
- "80:80/tcp"
|
||||
- "443:443/tcp"
|
||||
|
||||
webapp:
|
||||
image: webapp:latest
|
||||
labels:
|
||||
easyhaproxy.http.host: myapp.example.com
|
||||
easyhaproxy.http.port: 80
|
||||
easyhaproxy.http.localport: 8080
|
||||
# Enable multiple plugins
|
||||
easyhaproxy.http.plugins: cloudflare,deny_pages
|
||||
# Block specific paths
|
||||
easyhaproxy.http.plugin.deny_pages.paths: /admin,/wp-admin,/wp-login.php,/.env
|
||||
easyhaproxy.http.plugin.deny_pages.status_code: 404
|
||||
|
||||
api:
|
||||
image: api:latest
|
||||
labels:
|
||||
easyhaproxy.http.host: api.example.com
|
||||
easyhaproxy.http.port: 80
|
||||
easyhaproxy.http.localport: 3000
|
||||
# Combine JWT + IP whitelist + path blocking
|
||||
easyhaproxy.http.plugins: jwt_validator,ip_whitelist,deny_pages
|
||||
easyhaproxy.http.plugin.jwt_validator.algorithm: RS256
|
||||
easyhaproxy.http.plugin.jwt_validator.issuer: https://auth.example.com/
|
||||
easyhaproxy.http.plugin.jwt_validator.pubkey_path: /etc/haproxy/jwt_keys/api.pem
|
||||
easyhaproxy.http.plugin.ip_whitelist.allowed_ips: 192.168.0.0/16,10.0.0.0/8
|
||||
easyhaproxy.http.plugin.deny_pages.paths: /internal,/debug
|
||||
```
|
||||
|
||||
**Plugin execution order:**
|
||||
1. IP Whitelist (blocks non-whitelisted IPs)
|
||||
2. Deny Pages (blocks specific paths)
|
||||
3. JWT Validator (validates authentication)
|
||||
|
||||
---
|
||||
|
||||
## Common Configuration Options
|
||||
|
||||
### Environment Variables (HAProxy Container)
|
||||
|
||||
| Variable | Description | Default |
|
||||
|-----------------------------|---------------------------|----------|
|
||||
| `EASYHAPROXY_DISCOVER` | Discovery mode | `docker` |
|
||||
| `EASYHAPROXY_SSL_MODE` | SSL mode (loose/strict) | `strict` |
|
||||
| `EASYHAPROXY_CERTBOT_EMAIL` | Email for Let's Encrypt | - |
|
||||
| `HAPROXY_CUSTOMERRORS` | Enable custom error pages | `false` |
|
||||
| `HAPROXY_USERNAME` | Stats username | - |
|
||||
| `HAPROXY_PASSWORD` | Stats password | - |
|
||||
| `HAPROXY_STATS_PORT` | Stats port | `1936` |
|
||||
|
||||
### Container Labels
|
||||
|
||||
| Label | Description | Example |
|
||||
|---------------------------------|----------------------|---------------|
|
||||
| `easyhaproxy.http.host` | Virtual host domain | `example.com` |
|
||||
| `easyhaproxy.http.port` | External port | `80` |
|
||||
| `easyhaproxy.http.localport` | Container port | `8080` |
|
||||
| `easyhaproxy.http.redirect_ssl` | Force HTTPS redirect | `true` |
|
||||
| `easyhaproxy.http.certbot` | Enable Let's Encrypt | `true` |
|
||||
| `easyhaproxy.https.ssl` | Enable SSL | `true` |
|
||||
| `easyhaproxy.https.sslcert` | Base64 SSL cert | `LS0t...` |
|
||||
|
||||
For complete documentation, see [Container Labels](../../docs/container-labels.md).
|
||||
|
||||
## Tips
|
||||
|
||||
1. **Local Testing with Fake Domains:**
|
||||
Add entries to `/etc/hosts`:
|
||||
```
|
||||
127.0.0.1 host1.local host2.local portainer.local
|
||||
```
|
||||
|
||||
2. **Viewing Logs:**
|
||||
```bash
|
||||
docker compose logs -f haproxy
|
||||
```
|
||||
|
||||
3. **Reloading Configuration:**
|
||||
EasyHAProxy automatically detects changes. Watch logs for reload events.
|
||||
|
||||
4. **Generating Test SSL Certificates:**
|
||||
```bash
|
||||
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
|
||||
-keyout host.key -out host.crt \
|
||||
-subj "/CN=host1.local"
|
||||
cat host.crt host.key > host.pem
|
||||
```
|
||||
|
||||
5. **Base64 Encoding SSL Certificate:**
|
||||
```bash
|
||||
base64 -w 0 host.pem
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Issue:** Container not detected
|
||||
- Check labels are correct (prefix, syntax)
|
||||
- Verify Docker socket is mounted
|
||||
- Check logs: `docker compose logs haproxy`
|
||||
|
||||
**Issue:** SSL not working
|
||||
- Verify certificate format (cert + key in same PEM file)
|
||||
- Check certificate matches domain
|
||||
- Verify SSL mode (`loose` vs `strict`)
|
||||
|
||||
**Issue:** Let's Encrypt fails
|
||||
- Ensure ports 80/443 are publicly accessible
|
||||
- Verify domain DNS points to your IP
|
||||
- Check certbot logs in HAProxy container
|
||||
|
||||
## Further Reading
|
||||
|
||||
- [Docker Configuration Guide](../../docs/docker.md)
|
||||
- [Container Labels Reference](../../docs/container-labels.md)
|
||||
- [ACME/Let's Encrypt Guide](../../docs/acme.md)
|
||||
- [Docker Configuration Guide](../../docs/docker.md)
|
||||
- [Environment Variables](../../docs/environment-variable.md)
|
||||
- [Plugin Documentation](../../docs/plugins/)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,62 @@
|
|||
# This example shows how to setup HTTP-01 ACME CA Challenge
|
||||
# ==============================================================================
|
||||
# EXAMPLE: Let's Encrypt SSL with ACME/Certbot
|
||||
# ==============================================================================
|
||||
#
|
||||
# You need
|
||||
# - public IP pointing your machine
|
||||
# - open ports 80 and 443 in your firewall
|
||||
# WHAT THIS DEMONSTRATES:
|
||||
# - Automatic SSL certificate generation using Let's Encrypt
|
||||
# - HTTP-01 ACME challenge protocol
|
||||
# - Certificate persistence across container restarts
|
||||
# - Auto-renewal of certificates
|
||||
#
|
||||
# REQUIREMENTS (run these first):
|
||||
# ```bash
|
||||
# # You MUST have:
|
||||
# # - A public IP address pointing to your machine
|
||||
# # - Ports 80 and 443 open in your firewall
|
||||
# # - A valid domain name with DNS configured
|
||||
#
|
||||
# # Edit this file and change:
|
||||
# # - Line 21: EASYHAPROXY_CERTBOT_EMAIL to your email
|
||||
# # - Line 36: easyhaproxy.http.host to your real domain
|
||||
#
|
||||
# # Create certs directory
|
||||
# mkdir -p ./certs/certbot
|
||||
# ```
|
||||
#
|
||||
# HOW TO START:
|
||||
# ```bash
|
||||
# docker compose -f docker-compose-acme.yml up -d
|
||||
# ```
|
||||
#
|
||||
# HOW TO VERIFY IT'S WORKING:
|
||||
# ```bash
|
||||
# # Check logs for certificate issuance
|
||||
# docker compose -f docker-compose-acme.yml logs -f haproxy
|
||||
# # Look for: "Successfully received certificate"
|
||||
#
|
||||
# # Test HTTPS with real domain (replace test.xpto.us with your domain)
|
||||
# curl https://test.xpto.us/
|
||||
# # Expected: 200 OK with valid SSL certificate
|
||||
#
|
||||
# # Verify certificate
|
||||
# openssl s_client -showcerts -connect test.xpto.us:443 < /dev/null | grep "Issuer:"
|
||||
# # Expected: Issuer: C = US, O = Let's Encrypt
|
||||
#
|
||||
# # Check certificate files
|
||||
# ls -la ./certs/certbot/
|
||||
# # Expected: Your domain certificate files
|
||||
# ```
|
||||
#
|
||||
# CLEAN UP:
|
||||
# ```bash
|
||||
# docker compose -f docker-compose-acme.yml down
|
||||
# # Keep certificates:
|
||||
# # docker compose -f docker-compose-acme.yml down
|
||||
# # Remove certificates too:
|
||||
# # docker compose -f docker-compose-acme.yml down && rm -rf ./certs/certbot
|
||||
# ```
|
||||
#
|
||||
# ==============================================================================
|
||||
|
||||
services:
|
||||
haproxy:
|
||||
|
|
|
|||
|
|
@ -1,8 +1,40 @@
|
|||
# To test:
|
||||
# curl -k -H "Host: host1.local" https://127.0.0.1/
|
||||
# ==============================================================================
|
||||
# EXAMPLE: Custom Label Prefix
|
||||
# ==============================================================================
|
||||
#
|
||||
# or add to /etc/hosts
|
||||
# 127.0.0.1 host1.local
|
||||
# WHAT THIS DEMONSTRATES:
|
||||
# - Using a custom label prefix instead of default "easyhaproxy"
|
||||
# - Useful for running multiple EasyHAProxy instances
|
||||
# - Custom label configuration (haproxy.* instead of easyhaproxy.*)
|
||||
#
|
||||
# REQUIREMENTS (run these first):
|
||||
# ```bash
|
||||
# # Add to /etc/hosts (idempotent)
|
||||
# grep -q "host1.local" /etc/hosts || echo "127.0.0.1 host1.local" | sudo tee -a /etc/hosts
|
||||
# ```
|
||||
#
|
||||
# HOW TO START:
|
||||
# ```bash
|
||||
# docker compose -f docker-compose-changed-label.yml up -d
|
||||
# ```
|
||||
#
|
||||
# HOW TO VERIFY IT'S WORKING:
|
||||
# ```bash
|
||||
# # Test HTTPS
|
||||
# curl -k -H "Host: host1.local" https://127.0.0.1/
|
||||
# # Expected: 200 OK with hostname in response
|
||||
#
|
||||
# # Verify custom label prefix is working
|
||||
# docker inspect $(docker ps -q -f "ancestor=byjg/static-httpserver") | grep "haproxy.http"
|
||||
# # Expected: Labels starting with "haproxy." instead of "easyhaproxy."
|
||||
# ```
|
||||
#
|
||||
# CLEAN UP:
|
||||
# ```bash
|
||||
# docker compose -f docker-compose-changed-label.yml down
|
||||
# ```
|
||||
#
|
||||
# ==============================================================================
|
||||
|
||||
services:
|
||||
haproxy:
|
||||
|
|
|
|||
|
|
@ -1,28 +1,48 @@
|
|||
# Cloudflare IP Restoration Plugin Example
|
||||
# ==============================================================================
|
||||
# EXAMPLE: Cloudflare IP Restoration Plugin
|
||||
# ==============================================================================
|
||||
#
|
||||
# This example demonstrates restoring original visitor IPs when using Cloudflare CDN
|
||||
# WHAT THIS DEMONSTRATES:
|
||||
# - Restoring original visitor IPs when behind Cloudflare CDN
|
||||
# - Detecting requests from Cloudflare IP ranges
|
||||
# - Using CF-Connecting-IP header for real client IP
|
||||
# - Accurate IP logging for applications behind Cloudflare
|
||||
#
|
||||
# Prerequisites:
|
||||
# 1. Download Cloudflare IP ranges:
|
||||
# curl https://www.cloudflare.com/ips-v4 > cloudflare_ips.lst
|
||||
# curl https://www.cloudflare.com/ips-v6 >> cloudflare_ips.lst
|
||||
# REQUIREMENTS (run these first):
|
||||
# ```bash
|
||||
# # Download Cloudflare IP ranges (idempotent - overwrites if exists)
|
||||
# curl -s https://www.cloudflare.com/ips-v4 > cloudflare_ips.lst
|
||||
# curl -s https://www.cloudflare.com/ips-v6 >> cloudflare_ips.lst
|
||||
#
|
||||
# 2. Add to /etc/hosts:
|
||||
# 127.0.0.1 myapp.local
|
||||
# # Add to /etc/hosts (idempotent)
|
||||
# grep -q "myapp.local" /etc/hosts || echo "127.0.0.1 myapp.local" | sudo tee -a /etc/hosts
|
||||
# ```
|
||||
#
|
||||
# 3. Start the stack:
|
||||
# docker compose -f docker-compose-cloudflare.yml up -d
|
||||
# HOW TO START:
|
||||
# ```bash
|
||||
# docker compose -f docker-compose-cloudflare.yml up -d
|
||||
# ```
|
||||
#
|
||||
# 4. Test (simulating Cloudflare request):
|
||||
# # Without CF-Connecting-IP header:
|
||||
# curl -H "Host: myapp.local" http://127.0.0.1/
|
||||
# HOW TO VERIFY IT'S WORKING:
|
||||
# ```bash
|
||||
# # Test normal request
|
||||
# curl -H "Host: myapp.local" http://127.0.0.1/
|
||||
# # Expected: 200 OK
|
||||
#
|
||||
# # With CF-Connecting-IP header (simulating Cloudflare):
|
||||
# curl -H "Host: myapp.local" -H "CF-Connecting-IP: 203.0.113.50" http://127.0.0.1/
|
||||
# # Test with CF-Connecting-IP header (simulating Cloudflare)
|
||||
# curl -H "Host: myapp.local" -H "CF-Connecting-IP: 203.0.113.50" http://127.0.0.1/
|
||||
# # Expected: 200 OK (backend sees 203.0.113.50 as client IP)
|
||||
#
|
||||
# Note: This plugin is most useful when your site is actually behind Cloudflare.
|
||||
# Without Cloudflare, the request won't come from Cloudflare IPs, so the plugin
|
||||
# won't activate. This example is for demonstration and testing purposes.
|
||||
# # Note: This plugin is most useful when your site is actually behind Cloudflare
|
||||
# # In production, requests come from Cloudflare IPs and the plugin restores real client IPs
|
||||
# ```
|
||||
#
|
||||
# CLEAN UP:
|
||||
# ```bash
|
||||
# docker compose -f docker-compose-cloudflare.yml down
|
||||
# ```
|
||||
#
|
||||
# ==============================================================================
|
||||
|
||||
services:
|
||||
haproxy:
|
||||
|
|
|
|||
|
|
@ -1,23 +1,49 @@
|
|||
# IP Whitelist Plugin Example
|
||||
# ==============================================================================
|
||||
# EXAMPLE: IP Whitelist Plugin
|
||||
# ==============================================================================
|
||||
#
|
||||
# This example demonstrates restricting access to specific IP addresses
|
||||
# WHAT THIS DEMONSTRATES:
|
||||
# - Restricting access to specific IP addresses or CIDR ranges
|
||||
# - Single IP, CIDR notation, and multiple IP support
|
||||
# - Custom HTTP status code for blocked requests
|
||||
# - Admin panel or sensitive application protection
|
||||
#
|
||||
# Prerequisites:
|
||||
# 1. Add to /etc/hosts:
|
||||
# 127.0.0.1 admin.local
|
||||
# REQUIREMENTS (run these first):
|
||||
# ```bash
|
||||
# # Add to /etc/hosts (idempotent)
|
||||
# grep -q "admin.local" /etc/hosts || echo "127.0.0.1 admin.local" | sudo tee -a /etc/hosts
|
||||
#
|
||||
# 2. Start the stack:
|
||||
# docker compose -f docker-compose-ip-whitelist.yml up -d
|
||||
# # IMPORTANT: Update the allowed_ips in this file (line 52) with your actual IPs!
|
||||
# # Default allows localhost and private networks for testing
|
||||
# ```
|
||||
#
|
||||
# 3. Test from localhost (127.0.0.1 is whitelisted):
|
||||
# curl http://admin.local/
|
||||
# # Response: Success (200 OK)
|
||||
# HOW TO START:
|
||||
# ```bash
|
||||
# docker compose -f docker-compose-ip-whitelist.yml up -d
|
||||
# ```
|
||||
#
|
||||
# 4. Test from non-whitelisted IP:
|
||||
# # You'll need to test from another machine or configure the example
|
||||
# # with your actual IP address in the allowed_ips label
|
||||
# HOW TO VERIFY IT'S WORKING:
|
||||
# ```bash
|
||||
# # Test from localhost (127.0.0.1 is whitelisted)
|
||||
# curl http://admin.local/
|
||||
# # Expected: 200 OK - Access granted
|
||||
#
|
||||
# Note: Update the allowed_ips label with your actual IP addresses/networks
|
||||
# # Test from non-whitelisted IP
|
||||
# # You'll need to test from another machine or temporarily remove your IP
|
||||
# # from the allowed_ips list to see the 403 Forbidden response
|
||||
#
|
||||
# # View HAProxy stats to see blocked requests
|
||||
# # URL: http://localhost:1936
|
||||
# # Username: admin
|
||||
# # Password: password
|
||||
# ```
|
||||
#
|
||||
# CLEAN UP:
|
||||
# ```bash
|
||||
# docker compose -f docker-compose-ip-whitelist.yml down
|
||||
# ```
|
||||
#
|
||||
# ==============================================================================
|
||||
|
||||
services:
|
||||
haproxy:
|
||||
|
|
|
|||
|
|
@ -1,31 +1,56 @@
|
|||
# JWT Validator Plugin Example
|
||||
# ==============================================================================
|
||||
# EXAMPLE: JWT Validator Plugin
|
||||
# ==============================================================================
|
||||
#
|
||||
# This example demonstrates JWT token validation for API protection
|
||||
# WHAT THIS DEMONSTRATES:
|
||||
# - JWT token validation for API protection
|
||||
# - RS256 algorithm signature verification
|
||||
# - Issuer and audience validation
|
||||
# - Public key-based JWT verification
|
||||
#
|
||||
# Prerequisites:
|
||||
# 1. Generate RSA key pair:
|
||||
# openssl genrsa -out jwt_private.pem 2048
|
||||
# openssl rsa -in jwt_private.pem -pubout -out jwt_pubkey.pem
|
||||
# REQUIREMENTS (run these first):
|
||||
# ```bash
|
||||
# # Generate RSA key pair (idempotent - skips if exists)
|
||||
# [ -f jwt_private.pem ] || openssl genrsa -out jwt_private.pem 2048
|
||||
# [ -f jwt_pubkey.pem ] || openssl rsa -in jwt_private.pem -pubout -out jwt_pubkey.pem
|
||||
#
|
||||
# 2. Add to /etc/hosts:
|
||||
# 127.0.0.1 api.local
|
||||
# # Add to /etc/hosts (idempotent)
|
||||
# grep -q "api.local" /etc/hosts || echo "127.0.0.1 api.local" | sudo tee -a /etc/hosts
|
||||
# ```
|
||||
#
|
||||
# 3. Start the stack:
|
||||
# docker compose -f docker-compose-jwt-validator.yml up -d
|
||||
# HOW TO START:
|
||||
# ```bash
|
||||
# docker compose -f docker-compose-jwt-validator.yml up -d
|
||||
# ```
|
||||
#
|
||||
# 4. Test without token (should fail):
|
||||
# curl http://api.local/
|
||||
# # Response: Missing Authorization HTTP header
|
||||
# HOW TO VERIFY IT'S WORKING:
|
||||
# ```bash
|
||||
# # Test without token (should fail)
|
||||
# curl http://api.local/
|
||||
# # Expected: HTTP 403 - Missing Authorization HTTP header
|
||||
#
|
||||
# 5. Generate test JWT at https://jwt.io with:
|
||||
# - Algorithm: RS256
|
||||
# - Payload: {"iss":"https://auth.example.com/","aud":"https://api.example.com","exp":9999999999}
|
||||
# - Use your jwt_private.pem for signing
|
||||
# # Generate test JWT at https://jwt.io with:
|
||||
# # - Algorithm: RS256
|
||||
# # - Payload: {"iss":"https://auth.example.com/","aud":"https://api.example.com","exp":9999999999}
|
||||
# # - Paste contents of jwt_private.pem in private key field
|
||||
#
|
||||
# 6. Test with token:
|
||||
# TOKEN="eyJhbGc..."
|
||||
# curl -H "Authorization: Bearer $TOKEN" http://api.local/
|
||||
# # Response: Success
|
||||
# # Test with valid token
|
||||
# TOKEN="eyJhbGc..." # Replace with your generated token
|
||||
# curl -H "Authorization: Bearer $TOKEN" http://api.local/
|
||||
# # Expected: 200 OK with API response
|
||||
#
|
||||
# # View HAProxy stats
|
||||
# # URL: http://localhost:1936
|
||||
# # Username: admin
|
||||
# # Password: password
|
||||
# ```
|
||||
#
|
||||
# CLEAN UP:
|
||||
# ```bash
|
||||
# docker compose -f docker-compose-jwt-validator.yml down
|
||||
# ```
|
||||
#
|
||||
# ==============================================================================
|
||||
|
||||
services:
|
||||
haproxy:
|
||||
|
|
|
|||
|
|
@ -1,11 +1,48 @@
|
|||
# curl -H Host:www.helloworld.com localhost:19901
|
||||
# f6d8d45b7411
|
||||
# 59b213cb8592
|
||||
|
||||
# curl -I -H Host:google.helloworld.com localhost:19901
|
||||
# HTTP/1.1 301 Moved Permanently
|
||||
# content-length: 0
|
||||
# location: www.google.com/
|
||||
# ==============================================================================
|
||||
# EXAMPLE: Load Balancing with Multiple Container Replicas
|
||||
# ==============================================================================
|
||||
#
|
||||
# WHAT THIS DEMONSTRATES:
|
||||
# - Multiple container replicas behind a single domain
|
||||
# - Round-robin load balancing across replicas
|
||||
# - Domain redirect functionality
|
||||
# - Custom port configuration
|
||||
#
|
||||
# REQUIREMENTS (run these first):
|
||||
# ```bash
|
||||
# # No special requirements - this example runs on localhost:19901
|
||||
# ```
|
||||
#
|
||||
# HOW TO START:
|
||||
# ```bash
|
||||
# docker compose -f docker-compose-multi-containers.yml up -d
|
||||
# ```
|
||||
#
|
||||
# HOW TO VERIFY IT'S WORKING:
|
||||
# ```bash
|
||||
# # Test load balancing - hostname should alternate between containers
|
||||
# curl -H "Host: www.helloworld.com" localhost:19901
|
||||
# # Expected: Container ID (e.g., f6d8d45b7411)
|
||||
# curl -H "Host: www.helloworld.com" localhost:19901
|
||||
# # Expected: Different container ID (e.g., 59b213cb8592)
|
||||
#
|
||||
# # Test domain redirect
|
||||
# curl -I -H "Host: google.helloworld.com" localhost:19901
|
||||
# # Expected: HTTP/1.1 301 Moved Permanently, Location: www.google.com/
|
||||
#
|
||||
# # View HAProxy stats
|
||||
# # URL: http://localhost:1936
|
||||
# # Username: admin
|
||||
# # Password: password
|
||||
# # You should see 2 backend servers
|
||||
# ```
|
||||
#
|
||||
# CLEAN UP:
|
||||
# ```bash
|
||||
# docker compose -f docker-compose-multi-containers.yml down
|
||||
# ```
|
||||
#
|
||||
# ==============================================================================
|
||||
|
||||
services:
|
||||
haproxy:
|
||||
|
|
|
|||
|
|
@ -1,25 +1,51 @@
|
|||
# FastCGI Plugin Example with PHP-FPM
|
||||
# ==============================================================================
|
||||
# EXAMPLE: FastCGI Plugin with PHP-FPM
|
||||
# ==============================================================================
|
||||
#
|
||||
# This example demonstrates PHP-FPM configuration with FastCGI protocol support
|
||||
# using HAProxy as a reverse proxy and the FastCGI plugin for PHP environment setup.
|
||||
# WHAT THIS DEMONSTRATES:
|
||||
# - PHP-FPM configuration with FastCGI protocol (proto: fcgi)
|
||||
# - FastCGI plugin for PHP environment variable configuration
|
||||
# - TCP connection to PHP-FPM on port 9000
|
||||
# - PATH_INFO support for RESTful routing
|
||||
# - Custom document root and index file configuration
|
||||
#
|
||||
# Prerequisites:
|
||||
# 1. Add to /etc/hosts:
|
||||
# 127.0.0.1 phpapp.local
|
||||
# REQUIREMENTS (run these first):
|
||||
# ```bash
|
||||
# # Add to /etc/hosts (idempotent)
|
||||
# grep -q "phpapp.local" /etc/hosts || echo "127.0.0.1 phpapp.local" | sudo tee -a /etc/hosts
|
||||
# ```
|
||||
#
|
||||
# 2. Start the stack:
|
||||
# docker compose -f docker-compose-php-fpm.yml up -d
|
||||
# HOW TO START:
|
||||
# ```bash
|
||||
# docker compose -f docker-compose-php-fpm.yml up -d
|
||||
# ```
|
||||
#
|
||||
# 3. Test PHP application:
|
||||
# curl http://phpapp.local/
|
||||
# curl http://phpapp.local/info.php
|
||||
# HOW TO VERIFY IT'S WORKING:
|
||||
# ```bash
|
||||
# # Test main page
|
||||
# curl http://phpapp.local/
|
||||
# # Expected: 200 OK with PHP environment info
|
||||
#
|
||||
# Features:
|
||||
# - PHP-FPM 8.5 with TCP connection on port 9000
|
||||
# - FastCGI protocol support
|
||||
# - Custom document root
|
||||
# - PATH_INFO support for routing
|
||||
# - Custom FastCGI parameters
|
||||
# # Test PHP info page
|
||||
# curl http://phpapp.local/info.php
|
||||
# # Expected: phpinfo() output
|
||||
#
|
||||
# # Test PATH_INFO routing
|
||||
# curl http://phpapp.local/test-path-info.php/users/123
|
||||
# # Expected: PATH_INFO=/users/123
|
||||
#
|
||||
# # View HAProxy stats
|
||||
# # URL: http://localhost:1936
|
||||
# # Username: admin
|
||||
# # Password: password
|
||||
# ```
|
||||
#
|
||||
# CLEAN UP:
|
||||
# ```bash
|
||||
# docker compose -f docker-compose-php-fpm.yml down
|
||||
# ```
|
||||
#
|
||||
# ==============================================================================
|
||||
|
||||
services:
|
||||
haproxy:
|
||||
|
|
|
|||
|
|
@ -1,33 +1,67 @@
|
|||
# Multiple Plugins Combined Example
|
||||
# ==============================================================================
|
||||
# EXAMPLE: Multiple Plugins Combined
|
||||
# ==============================================================================
|
||||
#
|
||||
# This example demonstrates using multiple plugins together for enhanced security
|
||||
# WHAT THIS DEMONSTRATES:
|
||||
# - Using multiple security plugins together
|
||||
# - Different plugin combinations for different services
|
||||
# - Cloudflare + path blocking for public sites
|
||||
# - JWT validation + path blocking for APIs
|
||||
# - IP whitelist for admin panels
|
||||
# - Layered security approach
|
||||
#
|
||||
# Prerequisites:
|
||||
# 1. Generate JWT keys:
|
||||
# openssl genrsa -out jwt_private.pem 2048
|
||||
# openssl rsa -in jwt_private.pem -pubout -out jwt_pubkey.pem
|
||||
# REQUIREMENTS (run these first):
|
||||
# ```bash
|
||||
# # Generate JWT keys (idempotent - skips if exists)
|
||||
# [ -f jwt_private.pem ] || openssl genrsa -out jwt_private.pem 2048
|
||||
# [ -f jwt_pubkey.pem ] || openssl rsa -in jwt_private.pem -pubout -out jwt_pubkey.pem
|
||||
#
|
||||
# 2. Download Cloudflare IPs:
|
||||
# curl https://www.cloudflare.com/ips-v4 > cloudflare_ips.lst
|
||||
# curl https://www.cloudflare.com/ips-v6 >> cloudflare_ips.lst
|
||||
# # Download Cloudflare IPs (idempotent - overwrites if exists)
|
||||
# curl -s https://www.cloudflare.com/ips-v4 > cloudflare_ips.lst
|
||||
# curl -s https://www.cloudflare.com/ips-v6 >> cloudflare_ips.lst
|
||||
#
|
||||
# 3. Add to /etc/hosts:
|
||||
# 127.0.0.1 website.local api.local admin.local
|
||||
# # Add to /etc/hosts (idempotent)
|
||||
# grep -q "website.local" /etc/hosts || echo "127.0.0.1 website.local api.local admin.local" | sudo tee -a /etc/hosts
|
||||
# ```
|
||||
#
|
||||
# 4. Start the stack:
|
||||
# docker compose -f docker-compose-plugins-combined.yml up -d
|
||||
# HOW TO START:
|
||||
# ```bash
|
||||
# docker compose -f docker-compose-plugins-combined.yml up -d
|
||||
# ```
|
||||
#
|
||||
# 5. Test each service:
|
||||
# # Public website (Cloudflare + path blocking)
|
||||
# curl http://website.local/
|
||||
# curl http://website.local/admin # Should be blocked (404)
|
||||
# HOW TO VERIFY IT'S WORKING:
|
||||
# ```bash
|
||||
# # Test public website (Cloudflare + path blocking)
|
||||
# curl http://website.local/
|
||||
# # Expected: 200 OK
|
||||
# curl http://website.local/admin
|
||||
# # Expected: HTTP 404 - Path blocked
|
||||
#
|
||||
# # Protected API (JWT required)
|
||||
# curl http://api.local/ # Should fail - no JWT
|
||||
# curl -H "Authorization: Bearer <token>" http://api.local/ # Success
|
||||
# # Test protected API (JWT required)
|
||||
# curl http://api.local/
|
||||
# # Expected: HTTP 403 - Missing Authorization header
|
||||
# # Generate JWT at https://jwt.io (see jwt-validator example for details)
|
||||
# TOKEN="eyJhbGc..." # Replace with your token
|
||||
# curl -H "Authorization: Bearer $TOKEN" http://api.local/
|
||||
# # Expected: 200 OK
|
||||
#
|
||||
# # Admin panel (IP whitelist only)
|
||||
# curl http://admin.local/ # Success from localhost
|
||||
# # Test admin panel (IP whitelist)
|
||||
# curl http://admin.local/
|
||||
# # Expected: 200 OK from localhost
|
||||
#
|
||||
# # View HAProxy stats
|
||||
# # URL: http://localhost:1936
|
||||
# # Username: admin
|
||||
# # Password: password
|
||||
# # You should see 3 backends with different security configurations
|
||||
# ```
|
||||
#
|
||||
# CLEAN UP:
|
||||
# ```bash
|
||||
# docker compose -f docker-compose-plugins-combined.yml down
|
||||
# ```
|
||||
#
|
||||
# ==============================================================================
|
||||
|
||||
services:
|
||||
haproxy:
|
||||
|
|
|
|||
|
|
@ -1,3 +1,46 @@
|
|||
# ==============================================================================
|
||||
# EXAMPLE: Additional Application with Portainer
|
||||
# ==============================================================================
|
||||
#
|
||||
# WHAT THIS DEMONSTRATES:
|
||||
# - Adding more applications to an existing EasyHAProxy setup
|
||||
# - Using the shared "easyhaproxy" network
|
||||
# - Multiple applications behind the same HAProxy instance
|
||||
#
|
||||
# REQUIREMENTS (run these first):
|
||||
# ```bash
|
||||
# # 1. First start the Portainer stack (creates network and HAProxy)
|
||||
# docker compose -f docker-compose-portainer.yml up -d
|
||||
#
|
||||
# # 2. Edit this file and change:
|
||||
# # - Line 6: easyhaproxy.http.host to your real domain
|
||||
# ```
|
||||
#
|
||||
# HOW TO START:
|
||||
# ```bash
|
||||
# docker compose -f docker-compose-portainer-app-example.yml up -d
|
||||
# ```
|
||||
#
|
||||
# HOW TO VERIFY IT'S WORKING:
|
||||
# ```bash
|
||||
# # Check container is running
|
||||
# docker compose -f docker-compose-portainer-app-example.yml ps
|
||||
#
|
||||
# # Test the application
|
||||
# curl http://test.xpto.us
|
||||
# # OR with /etc/hosts: echo "127.0.0.1 test.xpto.us" | sudo tee -a /etc/hosts
|
||||
#
|
||||
# # Verify both apps in HAProxy stats (port 1936)
|
||||
# # You should see backends for both portainer.xpto.us and test.xpto.us
|
||||
# ```
|
||||
#
|
||||
# CLEAN UP:
|
||||
# ```bash
|
||||
# docker compose -f docker-compose-portainer-app-example.yml down
|
||||
# ```
|
||||
#
|
||||
# ==============================================================================
|
||||
|
||||
services:
|
||||
container:
|
||||
image: byjg/static-httpserver
|
||||
|
|
|
|||
|
|
@ -1,7 +1,60 @@
|
|||
# ==============================================================================
|
||||
# EXAMPLE: Portainer Behind EasyHAProxy
|
||||
# ==============================================================================
|
||||
#
|
||||
# WHAT THIS DEMONSTRATES:
|
||||
# - Running Portainer (Docker management UI) behind EasyHAProxy
|
||||
# - Using external volumes and networks for shared infrastructure
|
||||
# - Real-world application example with Let's Encrypt
|
||||
# - HTTP to HTTPS redirect with Certbot
|
||||
#
|
||||
# REQUIREMENTS (run these first):
|
||||
# ```bash
|
||||
# # Create required volumes (idempotent)
|
||||
# docker volume create certs_certbot
|
||||
# docker volume create certs_haproxy
|
||||
# docker volume create portainer_data
|
||||
#
|
||||
# # Create shared network (idempotent)
|
||||
# docker network create easyhaproxy
|
||||
#
|
||||
# # Edit this file and change:
|
||||
# # - Line 18: EASYHAPROXY_CERTBOT_EMAIL to your email
|
||||
# # - Line 38: easyhaproxy.http.host to your real domain
|
||||
# ```
|
||||
#
|
||||
# HOW TO START:
|
||||
# ```bash
|
||||
# docker compose -f docker-compose-portainer.yml up -d
|
||||
# ```
|
||||
#
|
||||
# HOW TO VERIFY IT'S WORKING:
|
||||
# ```bash
|
||||
# # Check containers are running
|
||||
# docker compose -f docker-compose-portainer.yml ps
|
||||
# # Expected: Both easyhaproxy and portainer containers running
|
||||
#
|
||||
# # Access Portainer (replace with your domain or use /etc/hosts)
|
||||
# # First time: Create admin user
|
||||
# curl http://portainer.xpto.us
|
||||
# # OR with /etc/hosts: echo "127.0.0.1 portainer.xpto.us" | sudo tee -a /etc/hosts
|
||||
#
|
||||
# # View HAProxy stats
|
||||
# # URL: http://localhost:1936
|
||||
# # Username: admin
|
||||
# # Password: password
|
||||
# ```
|
||||
#
|
||||
# CLEAN UP:
|
||||
# ```bash
|
||||
# docker compose -f docker-compose-portainer.yml down
|
||||
# # To also remove volumes:
|
||||
# # docker compose -f docker-compose-portainer.yml down -v
|
||||
# # docker volume rm certs_certbot certs_haproxy portainer_data
|
||||
# # docker network rm easyhaproxy
|
||||
# ```
|
||||
#
|
||||
# ==============================================================================
|
||||
|
||||
|
||||
services:
|
||||
|
|
|
|||
|
|
@ -1,19 +1,53 @@
|
|||
# To test:
|
||||
# ==============================================================================
|
||||
# EXAMPLE: Basic SSL Setup with Two Virtual Hosts
|
||||
# ==============================================================================
|
||||
#
|
||||
# WHAT THIS DEMONSTRATES:
|
||||
# - Basic SSL setup with custom certificates (embedded base64 and file-based)
|
||||
# - Automatic HTTP to HTTPS redirect
|
||||
# - Two virtual hosts (host1.local and host2.local)
|
||||
# - HAProxy stats interface
|
||||
#
|
||||
# REQUIREMENTS (run these first):
|
||||
# ```bash
|
||||
# # Add to /etc/hosts (idempotent)
|
||||
# grep -q "host1.local" /etc/hosts || echo "127.0.0.1 host1.local host2.local" | sudo tee -a /etc/hosts
|
||||
#
|
||||
# # Generate SSL certificates
|
||||
# cd ../.. && ./examples/generate-keys.sh && cd examples/docker
|
||||
# ```
|
||||
#
|
||||
# HOW TO START:
|
||||
# ```bash
|
||||
# docker compose up -d
|
||||
# ```
|
||||
#
|
||||
# HOW TO VERIFY IT'S WORKING:
|
||||
# ```bash
|
||||
# # Test HTTPS
|
||||
# curl -k -H "Host: host1.local" https://127.0.0.1/
|
||||
# curl -k -H "Host: host2.local" https://127.0.0.1/
|
||||
#
|
||||
# curl -I -H Host:host1.local http://127.0.0.1
|
||||
# HTTP/1.1 301 Moved Permanently
|
||||
# content-length: 0
|
||||
# location: https://host1.local/
|
||||
# # Expected: 200 OK with hostname in response
|
||||
#
|
||||
# curl -I -H Host:host2.local http://127.0.0.1
|
||||
# HTTP/1.1 301 Moved Permanently
|
||||
# content-length: 0
|
||||
# location: https://host1.local/
|
||||
# # Test HTTP redirect
|
||||
# curl -I -H "Host: host1.local" http://127.0.0.1
|
||||
# # Expected: HTTP/1.1 301 Moved Permanently, Location: https://host1.local/
|
||||
#
|
||||
# Test SSL:
|
||||
# openssl s_client -showcerts -connect 127.0.0.1:443 -servername host1.local
|
||||
# # View SSL certificate
|
||||
# openssl s_client -showcerts -connect 127.0.0.1:443 -servername host1.local < /dev/null
|
||||
#
|
||||
# # Access stats interface
|
||||
# # URL: http://localhost:1936
|
||||
# # Username: admin
|
||||
# # Password: password
|
||||
# ```
|
||||
#
|
||||
# CLEAN UP:
|
||||
# ```bash
|
||||
# docker compose down
|
||||
# ```
|
||||
#
|
||||
# ==============================================================================
|
||||
|
||||
services:
|
||||
haproxy:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue