Migrate configuration paths to /etc/easyhaproxy and improve health check support in E2E tests
- Refactored HAProxy configuration files, templates, and paths to use `/etc/easyhaproxy` instead of `/etc/haproxy`. - Updated Dockerfile to generate DH params and placeholder certificates in the new configuration directory. - Added health check support with timeout to `DockerComposeFixture` in E2E test utilities. - Adjusted tests, templates, and plugins to use the new `Consts`-based configuration paths. - Introduced pytest fixtures for environment isolation and temporary directory management.
This commit is contained in:
parent
3e963228f3
commit
045dd3817e
73 changed files with 600 additions and 287 deletions
|
|
@ -28,7 +28,7 @@ Prevents disk space issues by automatically cleaning up temporary files created
|
|||
### Static YAML Configuration
|
||||
|
||||
```yaml
|
||||
# /etc/haproxy/static/config.yaml
|
||||
# /etc/easyhaproxy/static/config.yaml
|
||||
plugins:
|
||||
enabled: [cleanup]
|
||||
config:
|
||||
|
|
@ -53,7 +53,7 @@ Configure the Cleanup plugin globally:
|
|||
### Custom Idle Time (1 hour)
|
||||
|
||||
```yaml
|
||||
# /etc/haproxy/static/config.yaml
|
||||
# /etc/easyhaproxy/static/config.yaml
|
||||
plugins:
|
||||
enabled: [cleanup]
|
||||
config:
|
||||
|
|
|
|||
|
|
@ -17,11 +17,11 @@ Cloudflare replaces the visitor's IP with its own. This plugin restores the orig
|
|||
|
||||
## Configuration Options
|
||||
|
||||
| Option | Description | Default |
|
||||
|-------------------|------------------------------------------|-----------------------------------|
|
||||
| `enabled` | Enable/disable plugin | `true` |
|
||||
| `use_builtin_ips` | Use built-in Cloudflare IP ranges | `true` |
|
||||
| `ip_list_path` | Path to Cloudflare IP list | `/etc/haproxy/cloudflare_ips.lst` |
|
||||
| Option | Description | Default |
|
||||
|-------------------|------------------------------------------|---------------------------------------|
|
||||
| `enabled` | Enable/disable plugin | `true` |
|
||||
| `use_builtin_ips` | Use built-in Cloudflare IP ranges | `true` |
|
||||
| `ip_list_path` | Path to Cloudflare IP list | `/etc/easyhaproxy/cloudflare_ips.lst` |
|
||||
|
||||
## Configuration Examples
|
||||
|
||||
|
|
@ -55,7 +55,7 @@ kind: Ingress
|
|||
metadata:
|
||||
annotations:
|
||||
easyhaproxy.plugins: "cloudflare"
|
||||
easyhaproxy.plugin.cloudflare.ip_list_path: "/etc/haproxy/cloudflare_ips.lst"
|
||||
easyhaproxy.plugin.cloudflare.ip_list_path: "/etc/easyhaproxy/cloudflare_ips.lst"
|
||||
spec:
|
||||
rules:
|
||||
- host: example.com
|
||||
|
|
@ -72,7 +72,7 @@ spec:
|
|||
### Static YAML Configuration
|
||||
|
||||
```yaml
|
||||
# /etc/haproxy/static/config.yaml
|
||||
# /etc/easyhaproxy/static/config.yaml
|
||||
plugins:
|
||||
config:
|
||||
cloudflare:
|
||||
|
|
@ -84,11 +84,11 @@ plugins:
|
|||
|
||||
Configure Cloudflare plugin defaults for all domains:
|
||||
|
||||
| Environment Variable | Config Key | Type | Default | Description |
|
||||
|-------------------------------------------------|-------------------|----------|-----------------------------------|---------------------------------------|
|
||||
| `EASYHAPROXY_PLUGIN_CLOUDFLARE_ENABLED` | `enabled` | boolean | `true` | Enable/disable plugin for all domains |
|
||||
| `EASYHAPROXY_PLUGIN_CLOUDFLARE_USE_BUILTIN_IPS` | `use_builtin_ips` | boolean | `true` | Use built-in Cloudflare IP ranges |
|
||||
| `EASYHAPROXY_PLUGIN_CLOUDFLARE_IP_LIST_PATH` | `ip_list_path` | string | `/etc/haproxy/cloudflare_ips.lst` | Path to Cloudflare IP list file |
|
||||
| Environment Variable | Config Key | Type | Default | Description |
|
||||
|-------------------------------------------------|-------------------|----------|---------------------------------------|---------------------------------------|
|
||||
| `EASYHAPROXY_PLUGIN_CLOUDFLARE_ENABLED` | `enabled` | boolean | `true` | Enable/disable plugin for all domains |
|
||||
| `EASYHAPROXY_PLUGIN_CLOUDFLARE_USE_BUILTIN_IPS` | `use_builtin_ips` | boolean | `true` | Use built-in Cloudflare IP ranges |
|
||||
| `EASYHAPROXY_PLUGIN_CLOUDFLARE_IP_LIST_PATH` | `ip_list_path` | string | `/etc/easyhaproxy/cloudflare_ips.lst` | Path to Cloudflare IP list file |
|
||||
|
||||
**Note:** Environment variables set defaults for ALL domains. To enable/disable per-domain, use container labels or Kubernetes annotations.
|
||||
|
||||
|
|
@ -96,7 +96,7 @@ Configure Cloudflare plugin defaults for all domains:
|
|||
|
||||
```haproxy
|
||||
# Cloudflare - Restore original visitor IP
|
||||
acl from_cloudflare src -f /etc/haproxy/cloudflare_ips.lst
|
||||
acl from_cloudflare src -f /etc/easyhaproxy/cloudflare_ips.lst
|
||||
http-request set-header X-Forwarded-For %[req.hdr(CF-Connecting-IP)] if from_cloudflare
|
||||
```
|
||||
|
||||
|
|
@ -114,7 +114,7 @@ The plugin includes the current Cloudflare IP ranges (22 ranges total):
|
|||
- 2400:cb00::/32, 2606:4700::/32, 2803:f800::/32, 2405:b500::/32
|
||||
- 2405:8100::/32, 2a06:98c0::/29, 2c0f:f248::/32
|
||||
|
||||
These ranges are automatically written to `/etc/haproxy/cloudflare_ips.lst` during each discovery cycle.
|
||||
These ranges are automatically written to `/etc/easyhaproxy/cloudflare_ips.lst` during each discovery cycle.
|
||||
|
||||
## Important Notes
|
||||
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ spec:
|
|||
### Static YAML Configuration
|
||||
|
||||
```yaml
|
||||
# /etc/haproxy/static/config.yaml
|
||||
# /etc/easyhaproxy/static/config.yaml
|
||||
containers:
|
||||
"example.com:80":
|
||||
ip: ["webapp:80"]
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ Automatically generates HAProxy `fcgi-app` configuration that defines required C
|
|||
| Option | Description | Default |
|
||||
|-------------------|-----------------------------------------|------------------------------------|
|
||||
| `enabled` | Enable/disable plugin | `true` |
|
||||
| `document_root` | Document root path | `/var/www/html` |
|
||||
| `document_root` | Document root path | `/etc/easyhaproxy/www` |
|
||||
| `script_filename` | Custom pattern for SCRIPT_FILENAME | `%[path]` (uses HAProxy's default) |
|
||||
| `index_file` | Default index file | `index.php` |
|
||||
| `path_info` | Enable PATH_INFO support | `true` |
|
||||
|
|
@ -40,10 +40,10 @@ services:
|
|||
easyhaproxy.http.localport: 9000
|
||||
easyhaproxy.http.proto: fcgi
|
||||
easyhaproxy.http.plugins: fastcgi
|
||||
easyhaproxy.http.plugin.fastcgi.document_root: /var/www/html
|
||||
easyhaproxy.http.plugin.fastcgi.document_root: /etc/easyhaproxy/www
|
||||
easyhaproxy.http.plugin.fastcgi.index_file: index.php
|
||||
volumes:
|
||||
- ./app:/var/www/html
|
||||
- ./app:/etc/easyhaproxy/www
|
||||
```
|
||||
|
||||
### Docker/Docker Compose (Unix socket)
|
||||
|
|
@ -57,10 +57,10 @@ services:
|
|||
easyhaproxy.http.socket: /run/php/php-fpm.sock
|
||||
easyhaproxy.http.proto: fcgi
|
||||
easyhaproxy.http.plugins: fastcgi
|
||||
easyhaproxy.http.plugin.fastcgi.document_root: /var/www/html
|
||||
easyhaproxy.http.plugin.fastcgi.document_root: /etc/easyhaproxy/www
|
||||
easyhaproxy.http.plugin.fastcgi.index_file: index.php
|
||||
volumes:
|
||||
- ./app:/var/www/html
|
||||
- ./app:/etc/easyhaproxy/www
|
||||
- /run/php:/run/php
|
||||
```
|
||||
|
||||
|
|
@ -82,7 +82,7 @@ kind: Ingress
|
|||
metadata:
|
||||
annotations:
|
||||
easyhaproxy.plugins: "fastcgi"
|
||||
easyhaproxy.plugin.fastcgi.document_root: "/var/www/html"
|
||||
easyhaproxy.plugin.fastcgi.document_root: "/etc/easyhaproxy/www"
|
||||
easyhaproxy.plugin.fastcgi.index_file: "index.php"
|
||||
spec:
|
||||
rules:
|
||||
|
|
@ -100,7 +100,7 @@ spec:
|
|||
### Static YAML Configuration
|
||||
|
||||
```yaml
|
||||
# /etc/haproxy/static/config.yaml
|
||||
# /etc/easyhaproxy/static/config.yaml
|
||||
easymapping:
|
||||
- host: phpapp.local
|
||||
port: 80
|
||||
|
|
@ -110,7 +110,7 @@ easymapping:
|
|||
- fastcgi
|
||||
plugin_config:
|
||||
fastcgi:
|
||||
document_root: /var/www/html
|
||||
document_root: /etc/easyhaproxy/www
|
||||
index_file: index.php
|
||||
path_info: true
|
||||
```
|
||||
|
|
@ -122,7 +122,7 @@ Configure FastCGI plugin defaults for all domains:
|
|||
| Environment Variable | Config Key | Type | Default | Description |
|
||||
|----------------------------------------------|-------------------|----------|-----------------|---------------------------------------|
|
||||
| `EASYHAPROXY_PLUGIN_FASTCGI_ENABLED` | `enabled` | boolean | `true` | Enable/disable plugin for all domains |
|
||||
| `EASYHAPROXY_PLUGIN_FASTCGI_DOCUMENT_ROOT` | `document_root` | string | `/var/www/html` | Document root path |
|
||||
| `EASYHAPROXY_PLUGIN_FASTCGI_DOCUMENT_ROOT` | `document_root` | string | `/etc/easyhaproxy/www` | Document root path |
|
||||
| `EASYHAPROXY_PLUGIN_FASTCGI_SCRIPT_FILENAME` | `script_filename` | string | `%[path]` | Custom pattern for SCRIPT_FILENAME |
|
||||
| `EASYHAPROXY_PLUGIN_FASTCGI_INDEX_FILE` | `index_file` | string | `index.php` | Default index file |
|
||||
| `EASYHAPROXY_PLUGIN_FASTCGI_PATH_INFO` | `path_info` | boolean | `true` | Enable PATH_INFO support |
|
||||
|
|
@ -136,7 +136,7 @@ The plugin generates a top-level `fcgi-app` section and a `use-fcgi-app` directi
|
|||
```haproxy
|
||||
# Top-level fcgi-app definition (added after defaults, before frontends/backends)
|
||||
fcgi-app fcgi_phpapp_local
|
||||
docroot /var/www/html
|
||||
docroot /etc/easyhaproxy/www
|
||||
index index.php
|
||||
path-info ^(/.+\.php)(/.*)?$
|
||||
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ spec:
|
|||
### Static YAML Configuration
|
||||
|
||||
```yaml
|
||||
# /etc/haproxy/static/config.yaml
|
||||
# /etc/easyhaproxy/static/config.yaml
|
||||
easymapping:
|
||||
- host: admin.example.com
|
||||
port: 443
|
||||
|
|
|
|||
|
|
@ -77,9 +77,9 @@ services:
|
|||
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
|
||||
easyhaproxy.http.plugin.jwt_validator.pubkey_path: /etc/easyhaproxy/jwt_keys/api_pubkey.pem
|
||||
volumes:
|
||||
- ./pubkey.pem:/etc/haproxy/jwt_keys/api_pubkey.pem:ro
|
||||
- ./pubkey.pem:/etc/easyhaproxy/jwt_keys/api_pubkey.pem:ro
|
||||
```
|
||||
|
||||
### Protect Specific Paths Only
|
||||
|
|
@ -87,7 +87,7 @@ services:
|
|||
```yaml
|
||||
labels:
|
||||
easyhaproxy.http.plugins: jwt_validator
|
||||
easyhaproxy.http.plugin.jwt_validator.pubkey_path: /etc/haproxy/jwt_keys/api_pubkey.pem
|
||||
easyhaproxy.http.plugin.jwt_validator.pubkey_path: /etc/easyhaproxy/jwt_keys/api_pubkey.pem
|
||||
easyhaproxy.http.plugin.jwt_validator.paths: /api/admin,/api/sensitive
|
||||
easyhaproxy.http.plugin.jwt_validator.only_paths: false
|
||||
# /api/health, /api/docs, etc. remain publicly accessible
|
||||
|
|
@ -98,7 +98,7 @@ labels:
|
|||
```yaml
|
||||
labels:
|
||||
easyhaproxy.http.plugins: jwt_validator
|
||||
easyhaproxy.http.plugin.jwt_validator.pubkey_path: /etc/haproxy/jwt_keys/api_pubkey.pem
|
||||
easyhaproxy.http.plugin.jwt_validator.pubkey_path: /etc/easyhaproxy/jwt_keys/api_pubkey.pem
|
||||
easyhaproxy.http.plugin.jwt_validator.paths: /api/public,/api/v1
|
||||
easyhaproxy.http.plugin.jwt_validator.only_paths: true
|
||||
# All paths except /api/public and /api/v1 are denied
|
||||
|
|
@ -110,7 +110,7 @@ labels:
|
|||
labels:
|
||||
easyhaproxy.http.plugin.jwt_validator.issuer: none
|
||||
easyhaproxy.http.plugin.jwt_validator.audience: none
|
||||
easyhaproxy.http.plugin.jwt_validator.pubkey_path: /etc/haproxy/jwt_keys/api_pubkey.pem
|
||||
easyhaproxy.http.plugin.jwt_validator.pubkey_path: /etc/easyhaproxy/jwt_keys/api_pubkey.pem
|
||||
```
|
||||
|
||||
### Allow Anonymous Access (Optional JWT)
|
||||
|
|
@ -121,10 +121,10 @@ services:
|
|||
labels:
|
||||
easyhaproxy.http.host: api.example.com
|
||||
easyhaproxy.http.plugins: jwt_validator
|
||||
easyhaproxy.http.plugin.jwt_validator.pubkey_path: /etc/haproxy/jwt_keys/api_pubkey.pem
|
||||
easyhaproxy.http.plugin.jwt_validator.pubkey_path: /etc/easyhaproxy/jwt_keys/api_pubkey.pem
|
||||
easyhaproxy.http.plugin.jwt_validator.allow_anonymous: true
|
||||
volumes:
|
||||
- ./pubkey.pem:/etc/haproxy/jwt_keys/api_pubkey.pem:ro
|
||||
- ./pubkey.pem:/etc/easyhaproxy/jwt_keys/api_pubkey.pem:ro
|
||||
# Requests without Authorization header are allowed
|
||||
# Requests with Authorization header are validated
|
||||
# Invalid JWTs are rejected
|
||||
|
|
@ -204,7 +204,7 @@ metadata:
|
|||
easyhaproxy.plugin.jwt_validator.algorithm: "RS256"
|
||||
easyhaproxy.plugin.jwt_validator.issuer: "https://auth.example.com/"
|
||||
easyhaproxy.plugin.jwt_validator.audience: "https://api.example.com"
|
||||
easyhaproxy.plugin.jwt_validator.pubkey_path: "/etc/haproxy/jwt_keys/api_pubkey.pem"
|
||||
easyhaproxy.plugin.jwt_validator.pubkey_path: "/etc/easyhaproxy/jwt_keys/api_pubkey.pem"
|
||||
easyhaproxy.plugin.jwt_validator.paths: "/api/admin,/api/users"
|
||||
easyhaproxy.plugin.jwt_validator.only_paths: "false"
|
||||
spec:
|
||||
|
|
@ -227,7 +227,7 @@ spec:
|
|||
### Static YAML Configuration
|
||||
|
||||
```yaml
|
||||
# /etc/haproxy/static/config.yaml
|
||||
# /etc/easyhaproxy/static/config.yaml
|
||||
containers:
|
||||
"api.example.com:443":
|
||||
ip: ["api-service:8080"]
|
||||
|
|
@ -238,7 +238,7 @@ containers:
|
|||
algorithm: RS256
|
||||
issuer: https://auth.example.com/
|
||||
audience: https://api.example.com
|
||||
pubkey_path: /etc/haproxy/jwt_keys/api_pubkey.pem
|
||||
pubkey_path: /etc/easyhaproxy/jwt_keys/api_pubkey.pem
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
|
|
@ -277,7 +277,7 @@ http-request set-var(txn.exp) http_auth_bearer,jwt_payload_query('$.exp','int')
|
|||
http-request deny content-type 'text/html' string 'Unsupported JWT signing algorithm' unless { var(txn.alg) -m str RS256 }
|
||||
http-request deny content-type 'text/html' string 'Invalid JWT issuer' unless { var(txn.iss) -m str https://auth.example.com/ }
|
||||
http-request deny content-type 'text/html' string 'Invalid JWT audience' unless { var(txn.aud) -m str https://api.example.com }
|
||||
http-request deny content-type 'text/html' string 'Invalid JWT signature' unless { http_auth_bearer,jwt_verify(txn.alg,"/etc/haproxy/jwt_keys/api_pubkey.pem") -m int 1 }
|
||||
http-request deny content-type 'text/html' string 'Invalid JWT signature' unless { http_auth_bearer,jwt_verify(txn.alg,"/etc/easyhaproxy/jwt_keys/api_pubkey.pem") -m int 1 }
|
||||
|
||||
# Validate expiration
|
||||
http-request set-var(txn.now) date()
|
||||
|
|
@ -303,7 +303,7 @@ http-request set-var(txn.exp) http_auth_bearer,jwt_payload_query('$.exp','int')
|
|||
|
||||
# Validate JWT (only on protected paths)
|
||||
http-request deny content-type 'text/html' string 'Unsupported JWT signing algorithm' unless { var(txn.alg) -m str RS256 } if jwt_protected_path
|
||||
http-request deny content-type 'text/html' string 'Invalid JWT signature' unless { http_auth_bearer,jwt_verify(txn.alg,"/etc/haproxy/jwt_keys/api_pubkey.pem") -m int 1 } if jwt_protected_path
|
||||
http-request deny content-type 'text/html' string 'Invalid JWT signature' unless { http_auth_bearer,jwt_verify(txn.alg,"/etc/easyhaproxy/jwt_keys/api_pubkey.pem") -m int 1 } if jwt_protected_path
|
||||
|
||||
# Validate expiration
|
||||
http-request set-var(txn.now) date() if jwt_protected_path
|
||||
|
|
@ -332,7 +332,7 @@ http-request set-var(txn.exp) http_auth_bearer,jwt_payload_query('$.exp','int')
|
|||
|
||||
# Validate JWT (all requests at this point are on allowed paths)
|
||||
http-request deny content-type 'text/html' string 'Unsupported JWT signing algorithm' unless { var(txn.alg) -m str RS256 }
|
||||
http-request deny content-type 'text/html' string 'Invalid JWT signature' unless { http_auth_bearer,jwt_verify(txn.alg,"/etc/haproxy/jwt_keys/api_pubkey.pem") -m int 1 }
|
||||
http-request deny content-type 'text/html' string 'Invalid JWT signature' unless { http_auth_bearer,jwt_verify(txn.alg,"/etc/easyhaproxy/jwt_keys/api_pubkey.pem") -m int 1 }
|
||||
|
||||
# Validate expiration
|
||||
http-request set-var(txn.now) date()
|
||||
|
|
@ -356,7 +356,7 @@ http-request set-var(txn.exp) http_auth_bearer,jwt_payload_query('$.exp','int')
|
|||
http-request deny content-type 'text/html' string 'Unsupported JWT signing algorithm' unless { var(txn.alg) -m str RS256 } if { req.hdr(authorization) -m found }
|
||||
http-request deny content-type 'text/html' string 'Invalid JWT issuer' unless { var(txn.iss) -m str https://auth.example.com/ } if { req.hdr(authorization) -m found }
|
||||
http-request deny content-type 'text/html' string 'Invalid JWT audience' unless { var(txn.aud) -m str https://api.example.com } if { req.hdr(authorization) -m found }
|
||||
http-request deny content-type 'text/html' string 'Invalid JWT signature' unless { http_auth_bearer,jwt_verify(txn.alg,"/etc/haproxy/jwt_keys/api_pubkey.pem") -m int 1 } if { req.hdr(authorization) -m found }
|
||||
http-request deny content-type 'text/html' string 'Invalid JWT signature' unless { http_auth_bearer,jwt_verify(txn.alg,"/etc/easyhaproxy/jwt_keys/api_pubkey.pem") -m int 1 } if { req.hdr(authorization) -m found }
|
||||
|
||||
# Validate expiration (only if Authorization header is present)
|
||||
http-request set-var(txn.now) date() if { req.hdr(authorization) -m found }
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ At a high level, ACME with Easy HAProxy works in two stages:
|
|||
- Manually setting `EASYHAPROXY_CERTBOT_SERVER` (and `EASYHAPROXY_CERTBOT_EAB_KID` / `EASYHAPROXY_CERTBOT_EAB_HMAC_KEY` when your CA requires EAB).
|
||||
- Always set your contact email via `EASYHAPROXY_CERTBOT_EMAIL`.
|
||||
- Ensure ports 80 and 443 are publicly reachable on the EasyHAProxy host.
|
||||
- Persist the folder `/certs/certbot` on a durable volume so issued/renewed certificates survive container restarts and avoid hitting CA rate limits.
|
||||
- Persist the folder `/etc/easyhaproxy/certs/certbot` on a durable volume so issued/renewed certificates survive container restarts and avoid hitting CA rate limits.
|
||||
- Challenge method is HTTP-01 only; EasyHAProxy configures a standalone Certbot responder internally.
|
||||
|
||||
2. Enable ACME per domain (per service/app)
|
||||
|
|
@ -44,7 +44,7 @@ At a high level, ACME with Easy HAProxy works in two stages:
|
|||
What happens under the hood
|
||||
- When a labeled domain is detected and a certificate is needed, EasyHAProxy runs Certbot with `--preferred-challenges http` and a standalone responder bound to internal port 2080.
|
||||
- HAProxy temporarily routes `/.well-known/acme-challenge/` for that domain to the Certbot responder, allowing the CA to validate via HTTP-01.
|
||||
- On success, EasyHAProxy merges the issued cert and key and stores them under `/certs/certbot` (one PEM per domain), then reloads HAProxy to serve HTTPS for that domain.
|
||||
- On success, EasyHAProxy merges the issued cert and key and stores them under `/etc/easyhaproxy/certs/certbot` (one PEM per domain), then reloads HAProxy to serve HTTPS for that domain.
|
||||
- Certificates are monitored and renewed automatically before expiry.
|
||||
|
||||
Tips
|
||||
|
|
@ -105,7 +105,7 @@ docker run \
|
|||
-e EASYHAPROXY_CERTBOT_EMAIL=john@doe.com \
|
||||
-p 80:80 \
|
||||
-p 443:443 \
|
||||
-v /path/to/guest/certbot/certs:/certs/certbot \
|
||||
-v /path/to/guest/certbot/certs:/etc/easyhaproxy/certs/certbot \
|
||||
... \
|
||||
byjg/easy-haproxy
|
||||
```
|
||||
|
|
@ -118,7 +118,7 @@ docker run \
|
|||
|
||||
:::danger Important: Persist Certbot Certificates
|
||||
To avoid hitting rate limits and certificate issuing problems:
|
||||
- **You must persist** the container folder `/certs/certbot` outside the container
|
||||
- **You must persist** the container folder `/etc/easyhaproxy/certs/certbot` outside the container
|
||||
- **Never delete or modify** its contents manually
|
||||
- If you don't persist this folder, or if you delete/modify its contents, certificate issuing may not work properly and you may hit rate limits
|
||||
:::
|
||||
|
|
|
|||
|
|
@ -4,20 +4,21 @@ sidebar_position: 12
|
|||
|
||||
# Docker environment variables
|
||||
|
||||
| Environment Variable | Description | Default |
|
||||
|--------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|
|
||||
| EASYHAPROXY_DISCOVER | How the services will be discovered to create `haproxy.cfg`: `static`, `docker`, `swarm` or `kubernetes` | **required** |
|
||||
| EASYHAPROXY_LABEL_PREFIX | (Optional) The key will search for matching resources. | `easyhaproxy` |
|
||||
| EASYHAPROXY_CERTBOT_* | (Optional) Enable Let's Encrypt or any other ACME certificate. See more: [acme](acme.md) | *empty* |
|
||||
| EASYHAPROXY_SSL_MODE | (Optional) `strict` supports only the most recent TLS version; `default` good SSL integration with recent browsers; `loose` supports all old SSL protocols for old browsers (not recommended). | `default` |
|
||||
| EASYHAPROXY_REFRESH_CONF | (Optional) Check for new containers/services every N seconds. | 10 |
|
||||
| EASYHAPROXY_LOG_LEVEL | (Optional) The log level for EasyHAproxy messages. Available: TRACE,DEBUG,INFO,WARN,ERROR,FATAL | DEBUG |
|
||||
| CERTBOT_LOG_LEVEL | (Optional) The log level for Certbot messages. Available: TRACE,DEBUG,INFO,WARN,ERROR,FATAL | DEBUG |
|
||||
| HAPROXY_LOG_LEVEL | (Optional) The log level for HAProxy messages. Available: TRACE,DEBUG,INFO,WARN,ERROR,FATAL | INFO |
|
||||
| HAPROXY_USERNAME | (Optional) The HAProxy username for the statistics endpoint (used only when `HAPROXY_PASSWORD` is set). | `admin` |
|
||||
| HAPROXY_PASSWORD | (Optional) The HAProxy password to the statistics endpoint. Stats are **disabled** unless this is defined. | *empty* |
|
||||
| HAPROXY_STATS_PORT | (Optional) The HAProxy port to the statistics. If set to `false`, disable statistics. Only applies when `HAPROXY_PASSWORD` is defined. | `1936` |
|
||||
| HAPROXY_CUSTOMERRORS | (Optional) If HAProxy will use custom HTML errors. true/false. | `false` |
|
||||
| Environment Variable | Description | Default |
|
||||
|--------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------|
|
||||
| EASYHAPROXY_DISCOVER | How the services will be discovered to create `haproxy.cfg`: `static`, `docker`, `swarm` or `kubernetes` | **required** |
|
||||
| EASYHAPROXY_LABEL_PREFIX | (Optional) The key will search for matching resources. | `easyhaproxy` |
|
||||
| EASYHAPROXY_BASE_PATH | (Optional) Base directory for all EasyHAProxy files. All paths (config, certs, plugins, www) are constructed relative to this base. | `/etc/easyhaproxy` |
|
||||
| EASYHAPROXY_CERTBOT_* | (Optional) Enable Let's Encrypt or any other ACME certificate. See more: [acme](acme.md) | *empty* |
|
||||
| EASYHAPROXY_SSL_MODE | (Optional) `strict` supports only the most recent TLS version; `default` good SSL integration with recent browsers; `loose` supports all old SSL protocols for old browsers (not recommended). | `default` |
|
||||
| EASYHAPROXY_REFRESH_CONF | (Optional) Check for new containers/services every N seconds. | 10 |
|
||||
| EASYHAPROXY_LOG_LEVEL | (Optional) The log level for EasyHAproxy messages. Available: TRACE,DEBUG,INFO,WARN,ERROR,FATAL | DEBUG |
|
||||
| CERTBOT_LOG_LEVEL | (Optional) The log level for Certbot messages. Available: TRACE,DEBUG,INFO,WARN,ERROR,FATAL | DEBUG |
|
||||
| HAPROXY_LOG_LEVEL | (Optional) The log level for HAProxy messages. Available: TRACE,DEBUG,INFO,WARN,ERROR,FATAL | INFO |
|
||||
| HAPROXY_USERNAME | (Optional) The HAProxy username for the statistics endpoint (used only when `HAPROXY_PASSWORD` is set). | `admin` |
|
||||
| HAPROXY_PASSWORD | (Optional) The HAProxy password to the statistics endpoint. Stats are **disabled** unless this is defined. | *empty* |
|
||||
| HAPROXY_STATS_PORT | (Optional) The HAProxy port to the statistics. If set to `false`, disable statistics. Only applies when `HAPROXY_PASSWORD` is defined. | `1936` |
|
||||
| HAPROXY_CUSTOMERRORS | (Optional) If HAProxy will use custom HTML errors. true/false. | `false` |
|
||||
|
||||
:::tip HAProxy Stats
|
||||
Statistics are only configured when `HAPROXY_PASSWORD` is set. Without a password, the stats section is not generated.
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ metadata:
|
|||
easyhaproxy.plugin.jwt_validator.algorithm: "RS256"
|
||||
easyhaproxy.plugin.jwt_validator.issuer: "https://auth.example.com/"
|
||||
easyhaproxy.plugin.jwt_validator.audience: "https://api.example.com"
|
||||
easyhaproxy.plugin.jwt_validator.pubkey_path: "/etc/haproxy/jwt_keys/api_pubkey.pem"
|
||||
easyhaproxy.plugin.jwt_validator.pubkey_path: "/etc/easyhaproxy/jwt_keys/api_pubkey.pem"
|
||||
spec:
|
||||
ingressClassName: easyhaproxy
|
||||
```
|
||||
|
|
|
|||
|
|
@ -36,18 +36,18 @@ docker run \
|
|||
|
||||
## Mapping custom .cfg files
|
||||
|
||||
You can concatenate valid HAProxy `.cfg` files to the dynamically generated `haproxy.cfg` by mapping the folder `/etc/haproxy/conf.d`.
|
||||
You can concatenate valid HAProxy `.cfg` files to the dynamically generated `haproxy.cfg` by mapping the folder `/etc/easyhaproxy/haproxy/conf.d`.
|
||||
|
||||
```bash title="Mount custom config directory"
|
||||
docker run \
|
||||
/* other parameters */
|
||||
-v /your/local/conf.d:/etc/haproxy/conf.d \
|
||||
-v /your/local/conf.d:/etc/easyhaproxy/haproxy/conf.d \
|
||||
-d byjg/easy-haproxy
|
||||
```
|
||||
|
||||
## Setting Custom Errors
|
||||
|
||||
If enabled, map the volume : `/etc/haproxy/errors-custom/` to your container and put a file named `ERROR_NUMBER.http`
|
||||
If enabled, map the volume : `/etc/easyhaproxy/haproxy/errors-custom/` to your container and put a file named `ERROR_NUMBER.http`
|
||||
where ERROR_NUMBER is the HTTP error code (e.g., `503.http`)
|
||||
|
||||
----
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ Execute **once per discovered domain/host**.
|
|||
### Plugin Loading Order
|
||||
|
||||
1. **Builtin plugins** - Loaded from `/src/plugins/builtin/`
|
||||
2. **External plugins** - Loaded from `/etc/haproxy/plugins/`
|
||||
2. **External plugins** - Loaded from `/etc/easyhaproxy/plugins/`
|
||||
|
||||
Plugins are discovered automatically by filename (`*.py` excluding `__*.py`).
|
||||
|
||||
|
|
@ -160,10 +160,10 @@ HAProxy Reload
|
|||
|
||||
### Step 1: Create Plugin File
|
||||
|
||||
Create a new Python file in `/etc/haproxy/plugins/` (or builtin location for core plugins):
|
||||
Create a new Python file in `/etc/easyhaproxy/plugins/` (or builtin location for core plugins):
|
||||
|
||||
```python
|
||||
# /etc/haproxy/plugins/my_plugin.py
|
||||
# /etc/easyhaproxy/plugins/my_plugin.py
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
|
@ -248,7 +248,7 @@ services:
|
|||
**Via YAML configuration:**
|
||||
|
||||
```yaml
|
||||
# /etc/haproxy/static/config.yaml
|
||||
# /etc/easyhaproxy/static/config.yaml
|
||||
plugins:
|
||||
enabled: [my_plugin]
|
||||
config:
|
||||
|
|
@ -521,13 +521,13 @@ return PluginResult(
|
|||
return PluginResult(
|
||||
haproxy_config="use-fcgi-app fcgi_example_com",
|
||||
global_configs=[
|
||||
"fcgi-app fcgi_example_com\n docroot /var/www/html"
|
||||
"fcgi-app fcgi_example_com\n docroot /etc/easyhaproxy/www"
|
||||
]
|
||||
)
|
||||
|
||||
# With defaults-level config (new in v2.0)
|
||||
return PluginResult(
|
||||
haproxy_config="acl from_cloudflare src -f /etc/haproxy/cloudflare_ips.lst",
|
||||
haproxy_config="acl from_cloudflare src -f /etc/easyhaproxy/cloudflare_ips.lst",
|
||||
defaults_configs=[
|
||||
'log-format "%{+Q}[var(txn.real_ip)]:-/%ci:%cp [%tr] %ft %b/%s"'
|
||||
]
|
||||
|
|
@ -551,7 +551,7 @@ class PluginManager:
|
|||
|
||||
Args:
|
||||
plugins_dir: Directory containing plugin files (defaults to
|
||||
EASYHAPROXY_PLUGINS_DIR env var or /etc/haproxy/plugins)
|
||||
EASYHAPROXY_PLUGINS_DIR env var or /etc/easyhaproxy/plugins)
|
||||
abort_on_error: If True, abort on plugin errors; if False, log and continue
|
||||
"""
|
||||
|
||||
|
|
@ -573,7 +573,7 @@ class PluginManager:
|
|||
|
||||
**Environment Variables:**
|
||||
|
||||
- `EASYHAPROXY_PLUGINS_DIR` - Override plugin directory (default: `/etc/haproxy/plugins`)
|
||||
- `EASYHAPROXY_PLUGINS_DIR` - Override plugin directory (default: `/etc/easyhaproxy/plugins`)
|
||||
|
||||
**Note:** You typically don't interact with PluginManager directly when writing plugins. It's used by EasyHAProxy core.
|
||||
|
||||
|
|
@ -712,7 +712,7 @@ The plugin creates:
|
|||
|
||||
Configuration:
|
||||
- enabled: Enable/disable the plugin (default: true)
|
||||
- document_root: Document root path (default: /var/www/html)
|
||||
- document_root: Document root path (default: /etc/easyhaproxy/www)
|
||||
- script_filename: Pattern for SCRIPT_FILENAME (default: %[path])
|
||||
- index_file: Default index file (default: index.php)
|
||||
- path_info: Enable PATH_INFO support (default: true)
|
||||
|
|
@ -722,7 +722,7 @@ Example YAML config:
|
|||
plugins:
|
||||
fastcgi:
|
||||
enabled: true
|
||||
document_root: /var/www/html
|
||||
document_root: /etc/easyhaproxy/www
|
||||
index_file: index.php
|
||||
path_info: true
|
||||
|
||||
|
|
@ -748,7 +748,7 @@ class FastcgiPlugin(PluginInterface):
|
|||
|
||||
def __init__(self):
|
||||
self.enabled = True
|
||||
self.document_root = "/var/www/html"
|
||||
self.document_root = "/etc/easyhaproxy/www"
|
||||
self.script_filename = "%[path]"
|
||||
self.index_file = "index.php"
|
||||
self.path_info = True
|
||||
|
|
@ -885,7 +885,7 @@ Example YAML config:
|
|||
algorithm: RS256
|
||||
issuer: https://myaccount.auth0.com/
|
||||
audience: https://api.mywebsite.com
|
||||
pubkey_path: /etc/haproxy/jwt_keys/pubkey.pem
|
||||
pubkey_path: /etc/easyhaproxy/jwt_keys/pubkey.pem
|
||||
paths:
|
||||
- /api/admin
|
||||
- /api/sensitive
|
||||
|
|
@ -896,7 +896,7 @@ Example Container Label:
|
|||
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
|
||||
easyhaproxy.http.plugin.jwt_validator.pubkey_path: /etc/easyhaproxy/jwt_keys/api_pubkey.pem
|
||||
easyhaproxy.http.plugin.jwt_validator.paths: /api/admin,/api/sensitive
|
||||
easyhaproxy.http.plugin.jwt_validator.only_paths: true
|
||||
"""
|
||||
|
|
@ -1267,7 +1267,7 @@ class CleanupPlugin(PluginInterface):
|
|||
|
||||
### Core Environment Variables
|
||||
|
||||
- `EASYHAPROXY_PLUGINS_DIR` - Override plugin directory (default: `/etc/haproxy/plugins`)
|
||||
- `EASYHAPROXY_PLUGINS_DIR` - Override plugin directory (default: `/etc/easyhaproxy/plugins`)
|
||||
- `EASYHAPROXY_PLUGINS_ENABLED` - Comma-separated list of enabled plugins
|
||||
- `EASYHAPROXY_PLUGINS_ABORT_ON_ERROR` - Abort on plugin errors (default: `false`)
|
||||
|
||||
|
|
@ -1685,7 +1685,7 @@ services:
|
|||
- "443:443"
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ./my_plugin.py:/etc/haproxy/plugins/my_plugin.py
|
||||
- ./my_plugin.py:/etc/easyhaproxy/plugins/my_plugin.py
|
||||
environment:
|
||||
- EASYHAPROXY_DISCOVER=docker
|
||||
```
|
||||
|
|
@ -1707,7 +1707,7 @@ Expected output:
|
|||
**Verify generated configuration:**
|
||||
|
||||
```bash
|
||||
docker-compose exec haproxy cat /etc/haproxy/haproxy.cfg | grep -A 5 "My Plugin"
|
||||
docker-compose exec haproxy cat /etc/easyhaproxy/haproxy/haproxy.cfg | grep -A 5 "My Plugin"
|
||||
```
|
||||
|
||||
---
|
||||
|
|
@ -1722,13 +1722,13 @@ docker-compose exec haproxy cat /etc/haproxy/haproxy.cfg | grep -A 5 "My Plugin"
|
|||
|
||||
1. **File not in plugins directory**
|
||||
```bash
|
||||
ls -la /etc/haproxy/plugins/
|
||||
ls -la /etc/easyhaproxy/plugins/
|
||||
# Ensure my_plugin.py exists
|
||||
```
|
||||
|
||||
2. **Invalid Python syntax**
|
||||
```bash
|
||||
python3 -m py_compile /etc/haproxy/plugins/my_plugin.py
|
||||
python3 -m py_compile /etc/easyhaproxy/plugins/my_plugin.py
|
||||
# Check for syntax errors
|
||||
```
|
||||
|
||||
|
|
@ -1814,7 +1814,7 @@ docker-compose exec haproxy cat /etc/haproxy/haproxy.cfg | grep -A 5 "My Plugin"
|
|||
1. **Invalid HAProxy syntax in generated config**
|
||||
```bash
|
||||
# Test configuration manually:
|
||||
haproxy -c -f /etc/haproxy/haproxy.cfg
|
||||
haproxy -c -f /etc/easyhaproxy/haproxy/haproxy.cfg
|
||||
```
|
||||
|
||||
2. **Missing quotes or escaping**
|
||||
|
|
@ -1907,7 +1907,7 @@ Share your plugin as a single `.py` file:
|
|||
|
||||
```bash
|
||||
# Users copy the file to their plugins directory:
|
||||
cp my_plugin.py /etc/haproxy/plugins/
|
||||
cp my_plugin.py /etc/easyhaproxy/plugins/
|
||||
```
|
||||
|
||||
**Advantages:**
|
||||
|
|
@ -1935,7 +1935,7 @@ my-easyhaproxy-plugin/
|
|||
**Installation:**
|
||||
```bash
|
||||
# Users download and install:
|
||||
wget https://raw.githubusercontent.com/user/my-plugin/main/my_plugin.py -O /etc/haproxy/plugins/my_plugin.py
|
||||
wget https://raw.githubusercontent.com/user/my-plugin/main/my_plugin.py -O /etc/easyhaproxy/plugins/my_plugin.py
|
||||
```
|
||||
|
||||
#### Option 3: Docker Image with Plugin
|
||||
|
|
@ -1949,7 +1949,7 @@ FROM byjg/easy-haproxy:latest
|
|||
COPY my_plugin.py /app/src/plugins/builtin/
|
||||
|
||||
# Optional: Add default configuration
|
||||
COPY plugin_config.yaml /etc/haproxy/static/config.yaml
|
||||
COPY plugin_config.yaml /etc/easyhaproxy/static/config.yaml
|
||||
```
|
||||
|
||||
**Build and distribute:**
|
||||
|
|
@ -1977,7 +1977,7 @@ Brief description of what your plugin does.
|
|||
|
||||
### Docker
|
||||
\`\`\`bash
|
||||
wget https://example.com/my_plugin.py -O /etc/haproxy/plugins/my_plugin.py
|
||||
wget https://example.com/my_plugin.py -O /etc/easyhaproxy/plugins/my_plugin.py
|
||||
\`\`\`
|
||||
|
||||
### Kubernetes
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ metadata:
|
|||
easyhaproxy.plugin.jwt_validator.algorithm: "RS256"
|
||||
easyhaproxy.plugin.jwt_validator.issuer: "https://auth.example.com/"
|
||||
easyhaproxy.plugin.jwt_validator.audience: "https://api.example.com"
|
||||
easyhaproxy.plugin.jwt_validator.pubkey_path: "/etc/haproxy/jwt_keys/api_pubkey.pem"
|
||||
easyhaproxy.plugin.jwt_validator.pubkey_path: "/etc/easyhaproxy/jwt_keys/api_pubkey.pem"
|
||||
easyhaproxy.plugin.jwt_validator.paths: "/api/admin,/api/users"
|
||||
easyhaproxy.plugin.jwt_validator.only_paths: "false"
|
||||
# Configure deny_pages plugin
|
||||
|
|
@ -124,7 +124,7 @@ services:
|
|||
|
||||
### 3. Static YAML Configuration
|
||||
|
||||
Configure plugins in `/etc/haproxy/static/config.yaml`:
|
||||
Configure plugins in `/etc/easyhaproxy/static/config.yaml`:
|
||||
|
||||
```yaml
|
||||
plugins:
|
||||
|
|
@ -200,9 +200,9 @@ services:
|
|||
easyhaproxy.http.plugins: jwt_validator
|
||||
easyhaproxy.http.plugin.jwt_validator.issuer: https://auth0.myapp.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
|
||||
easyhaproxy.http.plugin.jwt_validator.pubkey_path: /etc/easyhaproxy/jwt_keys/api_pubkey.pem
|
||||
volumes:
|
||||
- ./auth_pubkey.pem:/etc/haproxy/jwt_keys/api_pubkey.pem:ro
|
||||
- ./auth_pubkey.pem:/etc/easyhaproxy/jwt_keys/api_pubkey.pem:ro
|
||||
```
|
||||
|
||||
**Protect only admin/sensitive endpoints:**
|
||||
|
|
@ -213,11 +213,11 @@ services:
|
|||
labels:
|
||||
easyhaproxy.http.host: api.example.com
|
||||
easyhaproxy.http.plugins: jwt_validator
|
||||
easyhaproxy.http.plugin.jwt_validator.pubkey_path: /etc/haproxy/jwt_keys/api_pubkey.pem
|
||||
easyhaproxy.http.plugin.jwt_validator.pubkey_path: /etc/easyhaproxy/jwt_keys/api_pubkey.pem
|
||||
easyhaproxy.http.plugin.jwt_validator.paths: /api/admin,/api/users,/api/billing
|
||||
easyhaproxy.http.plugin.jwt_validator.only_paths: false
|
||||
volumes:
|
||||
- ./auth_pubkey.pem:/etc/haproxy/jwt_keys/api_pubkey.pem:ro
|
||||
- ./auth_pubkey.pem:/etc/easyhaproxy/jwt_keys/api_pubkey.pem:ro
|
||||
# /api/health, /api/docs, etc. remain publicly accessible
|
||||
```
|
||||
|
||||
|
|
@ -229,11 +229,11 @@ services:
|
|||
labels:
|
||||
easyhaproxy.http.host: api.example.com
|
||||
easyhaproxy.http.plugins: jwt_validator
|
||||
easyhaproxy.http.plugin.jwt_validator.pubkey_path: /etc/haproxy/jwt_keys/api_pubkey.pem
|
||||
easyhaproxy.http.plugin.jwt_validator.pubkey_path: /etc/easyhaproxy/jwt_keys/api_pubkey.pem
|
||||
easyhaproxy.http.plugin.jwt_validator.paths: /api/v1,/api/v2
|
||||
easyhaproxy.http.plugin.jwt_validator.only_paths: true
|
||||
volumes:
|
||||
- ./auth_pubkey.pem:/etc/haproxy/jwt_keys/api_pubkey.pem:ro
|
||||
- ./auth_pubkey.pem:/etc/easyhaproxy/jwt_keys/api_pubkey.pem:ro
|
||||
# All paths except /api/v1 and /api/v2 are denied
|
||||
```
|
||||
|
||||
|
|
@ -287,7 +287,7 @@ labels:
|
|||
Keep your system clean with automatic temp file removal:
|
||||
|
||||
```yaml
|
||||
# /etc/haproxy/static/config.yaml
|
||||
# /etc/easyhaproxy/static/config.yaml
|
||||
plugins:
|
||||
enabled: [cleanup]
|
||||
config:
|
||||
|
|
@ -346,13 +346,13 @@ EASYHAPROXY_LOG_LEVEL=DEBUG
|
|||
INFO: Loaded builtin plugin: cloudflare (domain)
|
||||
INFO: Loaded builtin plugin: cleanup (global)
|
||||
DEBUG: Executing domain plugin: cloudflare for domain: example.com
|
||||
DEBUG: Plugin cloudflare metadata: {'domain': 'example.com', 'ip_list_path': '/etc/haproxy/cloudflare_ips.lst'}
|
||||
DEBUG: Plugin cloudflare metadata: {'domain': 'example.com', 'ip_list_path': '/etc/easyhaproxy/cloudflare_ips.lst'}
|
||||
```
|
||||
|
||||
### Plugin Not Loading
|
||||
|
||||
**Check:**
|
||||
1. Plugin file exists in `/etc/haproxy/plugins/` or builtin directory
|
||||
1. Plugin file exists in `/etc/easyhaproxy/plugins/` or builtin directory
|
||||
2. Python syntax is valid
|
||||
3. Plugin class inherits from `PluginInterface`
|
||||
4. Check logs for load errors
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ Add the Base64 string you generated before to the label `easyhaproxy.[definition
|
|||
|
||||
## Map the certificate as a docker volume
|
||||
|
||||
EasyHAProxy stores the certificates inside the container folder `/certs/haproxy`.
|
||||
EasyHAProxy stores the certificates inside the container folder `/etc/easyhaproxy/certs/haproxy`.
|
||||
|
||||
1. Run EasyHAProxy with the volume for the certificates:
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ docker volume create certs_haproxy
|
|||
|
||||
docker run \
|
||||
/* other parameters */
|
||||
-v certs_haproxy:/certs/haproxy \
|
||||
-v certs_haproxy:/etc/easyhaproxy/certs/haproxy \
|
||||
-d byjg/easy-haproxy
|
||||
```
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ MIIEojCCA4qgAwIBAgIUegW2BimwuL4RzRZ2WYkHA6U5nkAwDQYJKoZIhvcNAQEL
|
|||
3. Copy this certificate to EasyHAProxy volume:
|
||||
|
||||
```bash title="Copy certificate to container"
|
||||
docker cp single.pem easyhaproxy:/certs/haproxy
|
||||
docker cp single.pem easyhaproxy:/etc/easyhaproxy/certs/haproxy
|
||||
```
|
||||
|
||||
----
|
||||
|
|
|
|||
|
|
@ -66,12 +66,12 @@ The `containers` format simplifies static configuration:
|
|||
- **Clearer mapping**: Format mirrors internal Docker label structure
|
||||
:::
|
||||
|
||||
Then map this file to `/etc/haproxy/static/config.yml` in your EasyHAProxy container:
|
||||
Then map this file to `/etc/easyhaproxy/static/config.yml` in your EasyHAProxy container:
|
||||
|
||||
```bash title="Run EasyHAProxy with static configuration"
|
||||
docker run -d \
|
||||
--name easy-haproxy-container \
|
||||
-v /my/static/:/etc/haproxy/static/ \
|
||||
-v /my/static/:/etc/easyhaproxy/static/ \
|
||||
-e EASYHAPROXY_DISCOVER="static" \
|
||||
# + Environment Variables \
|
||||
-p 80:80 \
|
||||
|
|
|
|||
194
docs/volumes.md
194
docs/volumes.md
|
|
@ -8,15 +8,193 @@ sidebar_position: 13
|
|||
These volumes allow you to persist certificates, provide custom configurations, and extend EasyHAProxy functionality.
|
||||
:::
|
||||
|
||||
You can map the following volumes:
|
||||
## Directory Structure
|
||||
|
||||
| Volume | Description |
|
||||
|-----------------------------|-------------------------------------------------------------------------------------------------------------------------------|
|
||||
| /etc/haproxy/static/ | The folder that will contain the [config.yml](static.md) file for static configuration |
|
||||
| /certs/haproxy/ | The folder that will contain the certificates (`PEM`) for the [SSL](ssl.md) |
|
||||
| /certs/certbot/ | The folder that will contain the certificates (`PEM`) processed by Certbot (e.g. Let's Encrypt). More info: [acme](acme.md). |
|
||||
| /etc/haproxy/conf.d/ | The folder that will contain the [custom configuration](other.md) files. |
|
||||
| /etc/haproxy/errors-custom/ | The folder that will contain the [custom error](other.md) html files. |
|
||||
:::info Base Path
|
||||
All EasyHAProxy files are organized under `/etc/easyhaproxy/`. This can be customized using the `EASYHAPROXY_BASE_PATH` environment variable.
|
||||
:::
|
||||
|
||||
```plaintext title="/etc/easyhaproxy/ Directory Tree"
|
||||
/etc/easyhaproxy/
|
||||
├── static/ # 🔧 Runtime (static mode only)
|
||||
│ └── config.yml # Static service configuration
|
||||
│
|
||||
├── haproxy/
|
||||
│ ├── haproxy.cfg # 🔧 Runtime - Generated HAProxy config
|
||||
│ ├── conf.d/ # 📦 Base image
|
||||
│ │ ├── README.md
|
||||
│ │ └── *.cfg # User-provided custom configs
|
||||
│ ├── dhparam # 📦 Base image - DH params 2048-bit
|
||||
│ ├── dhparam-1024 # 📦 Base image - DH params 1024-bit
|
||||
│ └── errors-custom/ # 📦 Base image
|
||||
│ ├── 400.http # Bad Request
|
||||
│ ├── 403.http # Forbidden
|
||||
│ ├── 408.http # Request Timeout
|
||||
│ ├── 500.http # Internal Server Error
|
||||
│ ├── 502.http # Bad Gateway
|
||||
│ ├── 503.http # Service Unavailable
|
||||
│ └── 504.http # Gateway Timeout
|
||||
│
|
||||
├── certs/
|
||||
│ ├── live/ # 🔧 Runtime (Certbot)
|
||||
│ │ └── {domain}/
|
||||
│ │ ├── cert.pem # Certificate only
|
||||
│ │ ├── chain.pem # Certificate chain
|
||||
│ │ ├── fullchain.pem # cert.pem + chain.pem
|
||||
│ │ ├── privkey.pem # Private key
|
||||
│ │ └── README
|
||||
│ ├── archive/ # 🔧 Runtime (Certbot)
|
||||
│ │ └── {domain}/
|
||||
│ │ ├── cert1.pem, cert2.pem... # Versioned certificates
|
||||
│ │ └── privkey1.pem... # Versioned keys
|
||||
│ ├── work/ # 🔧 Runtime (Certbot working dir)
|
||||
│ ├── logs/ # 🔧 Runtime (Certbot logs)
|
||||
│ │ └── letsencrypt.log
|
||||
│ ├── certbot/ # 📦 Base image
|
||||
│ │ ├── {domain}.pem # 🔧 Runtime - Merged cert+key
|
||||
│ │ └── placeholder.pem # 📦 Base image - Placeholder cert
|
||||
│ └── haproxy/ # 📦 Base image
|
||||
│ ├── {domain}.pem # User-provided cert+key (PEM format)
|
||||
│ └── placeholder.pem # 📦 Base image - Placeholder cert
|
||||
│
|
||||
├── plugins/ # Optional - Custom plugins
|
||||
│ └── *.py # Python plugin files
|
||||
│
|
||||
├── jwt_keys/ # Optional - JWT validation
|
||||
│ └── *.pem # RSA public keys
|
||||
│
|
||||
├── cloudflare_ips.lst # Optional - Cloudflare plugin
|
||||
│
|
||||
└── www/ # Optional - FastCGI document root
|
||||
└── index.php
|
||||
```
|
||||
|
||||
:::tip Legend
|
||||
- **📦 Base image** - Included in the Docker image
|
||||
- **🔧 Runtime** - Created/generated when EasyHAProxy runs
|
||||
- **Optional** - Created only when specific features are used
|
||||
:::
|
||||
|
||||
## Common Volume Mappings
|
||||
|
||||
The most commonly mapped volumes for persistence and customization:
|
||||
|
||||
| Volume | Purpose | Required |
|
||||
|-------------------------------------------|-------------------------------------------------------------------------------------------------------|----------|
|
||||
| `/etc/easyhaproxy/static/` | [Static configuration](static.md) - mount your `config.yml` here | Optional |
|
||||
| `/etc/easyhaproxy/certs/haproxy/` | [SSL certificates](ssl.md) - user-provided certificates in PEM format | Optional |
|
||||
| `/etc/easyhaproxy/certs/certbot/` | [ACME/Certbot certificates](acme.md) - auto-generated Let's Encrypt certificates | Optional |
|
||||
| `/etc/easyhaproxy/certs/live/` | Certbot live certificates - persist across container restarts | Optional |
|
||||
| `/etc/easyhaproxy/haproxy/conf.d/` | [Custom HAProxy config](other.md) - additional `.cfg` files to include | Optional |
|
||||
| `/etc/easyhaproxy/haproxy/errors-custom/` | [Custom error pages](other.md) - custom HTTP error pages (400, 403, 500, etc.) | Optional |
|
||||
| `/etc/easyhaproxy/plugins/` | [Custom plugins](plugins.md) - Python plugin files | Optional |
|
||||
| `/etc/easyhaproxy/jwt_keys/` | [JWT public keys](Plugins/jwt-validator.md) - RSA public keys for JWT validation | Optional |
|
||||
| `/etc/easyhaproxy/www/` | [FastCGI document root](Plugins/fastcgi.md) - PHP/FastCGI application files | Optional |
|
||||
|
||||
## Directory Details
|
||||
|
||||
### Configuration Files
|
||||
|
||||
#### Static Configuration
|
||||
```bash
|
||||
/etc/easyhaproxy/static/config.yml
|
||||
```
|
||||
Static service configuration when not using service discovery (Docker/Kubernetes).
|
||||
|
||||
:::note
|
||||
This directory only exists when `EASYHAPROXY_DISCOVER=static` is set.
|
||||
:::
|
||||
|
||||
#### HAProxy Configuration
|
||||
```bash
|
||||
/etc/easyhaproxy/haproxy/haproxy.cfg
|
||||
```
|
||||
Auto-generated HAProxy configuration file.
|
||||
|
||||
:::warning Do Not Edit
|
||||
This file is automatically generated by EasyHAProxy. Any manual changes will be overwritten.
|
||||
:::
|
||||
|
||||
#### Custom Configuration Snippets
|
||||
```bash
|
||||
/etc/easyhaproxy/haproxy/conf.d/*.cfg
|
||||
```
|
||||
Place custom HAProxy configuration snippets here. These files are automatically included in the main configuration.
|
||||
|
||||
:::tip Example
|
||||
```bash
|
||||
# Mount your custom config
|
||||
docker run -v ./my-custom.cfg:/etc/easyhaproxy/haproxy/conf.d/my-custom.cfg byjg/easy-haproxy
|
||||
```
|
||||
:::
|
||||
|
||||
### SSL/TLS Certificates
|
||||
|
||||
#### User-Provided Certificates
|
||||
```bash
|
||||
/etc/easyhaproxy/certs/haproxy/{domain}.pem
|
||||
```
|
||||
Place your SSL certificates here in PEM format (certificate + private key combined).
|
||||
|
||||
:::info PEM Format
|
||||
```bash
|
||||
cat domain.crt domain.key > /etc/easyhaproxy/certs/haproxy/domain.com.pem
|
||||
```
|
||||
:::
|
||||
|
||||
#### ACME/Let's Encrypt Certificates
|
||||
```bash
|
||||
/etc/easyhaproxy/certs/certbot/{domain}.pem # Merged cert+key for HAProxy
|
||||
/etc/easyhaproxy/certs/live/{domain}/ # Certbot live certificates (symlinks)
|
||||
/etc/easyhaproxy/certs/archive/{domain}/ # Versioned certificate archive
|
||||
```
|
||||
|
||||
EasyHAProxy automatically merges Certbot certificates from `/etc/easyhaproxy/certs/live/` into `/etc/easyhaproxy/certs/certbot/` for HAProxy consumption.
|
||||
|
||||
:::tip Persist Certbot Certificates
|
||||
```yaml
|
||||
volumes:
|
||||
- certbot-certs:/etc/easyhaproxy/certs/live
|
||||
- certbot-archive:/etc/easyhaproxy/certs/archive
|
||||
```
|
||||
:::
|
||||
|
||||
### Plugins & Extensions
|
||||
|
||||
#### Custom Plugins
|
||||
```bash
|
||||
/etc/easyhaproxy/plugins/*.py
|
||||
```
|
||||
Add custom Python plugins to extend EasyHAProxy functionality.
|
||||
|
||||
See [Plugin Development](plugin-development.md) for details.
|
||||
|
||||
#### JWT Public Keys
|
||||
```bash
|
||||
/etc/easyhaproxy/jwt_keys/*.pem
|
||||
```
|
||||
RSA public keys for [JWT token validation](Plugins/jwt-validator.md).
|
||||
|
||||
#### Cloudflare IP Ranges
|
||||
```bash
|
||||
/etc/easyhaproxy/cloudflare_ips.lst
|
||||
```
|
||||
Cloudflare IP ranges for the [Cloudflare plugin](Plugins/cloudflare.md) to restore real client IPs.
|
||||
|
||||
### Error Pages
|
||||
|
||||
```bash
|
||||
/etc/easyhaproxy/haproxy/errors-custom/{code}.http
|
||||
```
|
||||
|
||||
Custom HTTP error pages (400, 403, 408, 500, 502, 503, 504). Default error pages are included in the base image.
|
||||
|
||||
:::tip Customize Error Pages
|
||||
```bash
|
||||
# Mount your custom 503 error page
|
||||
docker run -v ./custom-503.http:/etc/easyhaproxy/haproxy/errors-custom/503.http byjg/easy-haproxy
|
||||
```
|
||||
:::
|
||||
|
||||
----
|
||||
[Open source ByJG](http://opensource.byjg.com)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue