65 |
PATH_INFO Test
66 |
67 |
68 |
69 | Success! PATH_INFO is working correctly.
70 |
71 |
72 |
PATH_INFO Value
73 |
74 |
75 |
Parsed Path Segments
76 |
80 |
81 |
82 |
83 | Note: PATH_INFO is not set. Try accessing this page with additional path segments.
84 |
85 |
86 |
87 |
Request Information
88 |
94 |
95 |
Example Usage
96 |
PATH_INFO enables RESTful URL routing. Try these URLs:
97 |
102 |
103 |
← Back to Home
104 |
105 |
106 |
107 |
--------------------------------------------------------------------------------
/examples/swarm/ip-whitelist.yml:
--------------------------------------------------------------------------------
1 | # ==============================================================================
2 | # EXAMPLE: IP Whitelist Plugin (Swarm)
3 | # ==============================================================================
4 | #
5 | # WHAT THIS DEMONSTRATES:
6 | # - Restricting access to specific IP addresses/networks
7 | # - IP-based access control for admin panels or sensitive services
8 | # - Returning custom status codes for blocked IPs
9 | # - Service discovery in Swarm mode with plugins
10 | #
11 | # REQUIREMENTS (run these first):
12 | # ```bash
13 | # # Initialize Docker Swarm (if not already initialized)
14 | # docker swarm init
15 | #
16 | # # Create overlay network (idempotent)
17 | # docker network ls | grep -q easyhaproxy || docker network create --driver overlay --attachable easyhaproxy
18 | #
19 | # # Ensure EasyHAProxy is deployed
20 | # docker stack deploy -c easyhaproxy.yml easyhaproxy
21 | #
22 | # # Add to /etc/hosts for local testing (idempotent)
23 | # grep -q "admin.example.com" /etc/hosts || echo "127.0.0.1 admin.example.com" | sudo tee -a /etc/hosts
24 | #
25 | # # IMPORTANT: Edit this file (ip-whitelist.yml) line 64 to add your actual IP addresses!
26 | # # Get your current IP: curl ifconfig.me
27 | # ```
28 | #
29 | # HOW TO START:
30 | # ```bash
31 | # docker stack deploy -c ip-whitelist.yml admin
32 | # ```
33 | #
34 | # HOW TO VERIFY IT'S WORKING:
35 | # ```bash
36 | # # Check stack is deployed
37 | # docker stack ls | grep admin
38 | # # Expected: admin stack listed
39 | #
40 | # # Check service is running
41 | # docker service ls | grep admin_admin
42 | # # Expected: admin_admin with 3/3 replicas
43 | #
44 | # # Test from allowed IP (assumes 127.0.0.1 or your IP is in the whitelist)
45 | # curl -H "Host: admin.example.com" http://localhost/
46 | # # Expected: 200 OK with "Admin Panel - IP Restricted"
47 | #
48 | # # Test from blocked IP (using a different IP via proxy or VPN)
49 | # # Expected: HTTP 403 Forbidden
50 | #
51 | # # View HAProxy stats to see IP whitelist rules
52 | # # URL: http://localhost:1936
53 | # # Username: admin
54 | # # Password: password
55 | # ```
56 | #
57 | # CLEAN UP:
58 | # ```bash
59 | # docker stack rm admin
60 | # ```
61 | #
62 | # ==============================================================================
63 |
64 | version: "3.7"
65 |
66 | services:
67 | haproxy:
68 | image: byjg/easy-haproxy:5.0.0
69 | volumes:
70 | - /var/run/docker.sock:/var/run/docker.sock
71 | deploy:
72 | replicas: 1
73 | placement:
74 | constraints:
75 | - node.role == manager
76 | environment:
77 | EASYHAPROXY_DISCOVER: swarm
78 | HAPROXY_USERNAME: admin
79 | HAPROXY_PASSWORD: password
80 | HAPROXY_STATS_PORT: 1936
81 | ports:
82 | - "80:80/tcp"
83 | - "1936:1936/tcp"
84 | networks:
85 | - easyhaproxy
86 |
87 | # Admin panel with IP restrictions
88 | admin:
89 | image: byjg/static-httpserver
90 | environment:
91 | TITLE: "Admin Panel - IP Restricted"
92 | deploy:
93 | replicas: 3
94 | labels:
95 | easyhaproxy.http.host: "admin.example.com"
96 | easyhaproxy.http.port: "80"
97 | easyhaproxy.http.localport: "8080"
98 |
99 | # Enable IP whitelist plugin
100 | easyhaproxy.http.plugins: "ip_whitelist"
101 |
102 | # Allow specific IPs and networks
103 | # UPDATE THIS with your actual office/VPN IPs!
104 | easyhaproxy.http.plugin.ip_whitelist.allowed_ips: "203.0.113.0/24,198.51.100.0/24,10.0.0.0/8"
105 |
106 | # Status code to return for blocked IPs
107 | easyhaproxy.http.plugin.ip_whitelist.status_code: "403"
108 | networks:
109 | - easyhaproxy
110 |
111 | networks:
112 | easyhaproxy:
113 | external: true
114 |
--------------------------------------------------------------------------------
/docs/environment-variable.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 12
3 | ---
4 |
5 | # Docker environment variables
6 |
7 | | Environment Variable | Description | Default |
8 | |--------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|
9 | | EASYHAPROXY_DISCOVER | How the services will be discovered to create `haproxy.cfg`: `static`, `docker`, `swarm` or `kubernetes` | **required** |
10 | | EASYHAPROXY_LABEL_PREFIX | (Optional) The key will search for matching resources. | `easyhaproxy` |
11 | | EASYHAPROXY_CERTBOT_* | (Optional) Enable Let's Encrypt or any other ACME certificate. See more: [acme](acme.md) | *empty* |
12 | | 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` |
13 | | EASYHAPROXY_REFRESH_CONF | (Optional) Check for new containers/services every N seconds. | 10 |
14 | | EASYHAPROXY_LOG_LEVEL | (Optional) The log level for EasyHAproxy messages. Available: TRACE,DEBUG,INFO,WARN,ERROR,FATAL | DEBUG |
15 | | CERTBOT_LOG_LEVEL | (Optional) The log level for Certbot messages. Available: TRACE,DEBUG,INFO,WARN,ERROR,FATAL | DEBUG |
16 | | HAPROXY_LOG_LEVEL | (Optional) The log level for HAProxy messages. Available: TRACE,DEBUG,INFO,WARN,ERROR,FATAL | INFO |
17 | | HAPROXY_USERNAME | (Optional) The HAProxy username for the statistics endpoint (used only when `HAPROXY_PASSWORD` is set). | `admin` |
18 | | HAPROXY_PASSWORD | (Optional) The HAProxy password to the statistics endpoint. Stats are **disabled** unless this is defined. | *empty* |
19 | | HAPROXY_STATS_PORT | (Optional) The HAProxy port to the statistics. If set to `false`, disable statistics. Only applies when `HAPROXY_PASSWORD` is defined. | `1936` |
20 | | HAPROXY_CUSTOMERRORS | (Optional) If HAProxy will use custom HTML errors. true/false. | `false` |
21 |
22 | :::tip HAProxy Stats
23 | Statistics are only configured when `HAPROXY_PASSWORD` is set. Without a password, the stats section is not generated.
24 | :::
25 |
26 | :::note ACME/Certbot Environment Variables
27 | For ACME/Certbot configuration (Let's Encrypt, ZeroSSL, etc.), see the [ACME documentation](acme.md#environment-variables) for the complete list of `EASYHAPROXY_CERTBOT_*` variables.
28 | :::
29 |
30 | ----
31 | [Open source ByJG](http://opensource.byjg.com)
32 |
--------------------------------------------------------------------------------
/docs/swarm.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 2
3 | ---
4 |
5 | # Swarm
6 |
7 | ## Setup Docker EasyHAProxy
8 |
9 | This method involves using a Docker Swarm installation to discover containers and configure HAProxy.
10 |
11 | EasyHAProxy inspects Docker containers within the Swarm and retrieves labels to configure HAProxy. Once it identifies a container with at least the label 'easyhaproxy.http.host,' it configures HAProxy to redirect traffic to that container. To accomplish this, EasyHAProxy may need to attach the same network to its container.
12 |
13 | :::tip Docker Swarm Advantages
14 | - **Container Discovery**: Docker Swarm facilitates the discovery of containers within the cluster, streamlining the process of identifying services for HAProxy configuration.
15 | - **Remote Node Management**: Docker Swarm allows for the management of containers across multiple nodes, providing flexibility and scalability in deploying services while ensuring seamless HAProxy configuration across the cluster.
16 | :::
17 |
18 | It's recommended to create a network external to EasyHAProxy.
19 |
20 | :::warning Limitations
21 | - You cannot mix Docker containers with Swarm containers.
22 | - This method does not work with containers that use the `--network=host` option. See [limitations](limitations.md) for details.
23 | :::
24 |
25 | For example:
26 |
27 | ```bash title="Create overlay network"
28 | docker network create -d overlay --attachable easyhaproxy
29 | ```
30 |
31 | And then deploy the EasyHAProxy stack:
32 |
33 | ```yaml
34 | services:
35 | haproxy:
36 | image: byjg/easy-haproxy:5.0.0
37 | volumes:
38 | - /var/run/docker.sock:/var/run/docker.sock
39 | deploy:
40 | replicas: 1
41 | environment:
42 | EASYHAPROXY_DISCOVER: swarm
43 | EASYHAPROXY_SSL_MODE: "loose"
44 | HAPROXY_CUSTOMERRORS: "true"
45 | HAPROXY_USERNAME: admin
46 | HAPROXY_PASSWORD: password
47 | HAPROXY_STATS_PORT: 1936
48 | ports:
49 | - "80:80/tcp"
50 | - "443:443/tcp"
51 | - "1936:1936/tcp"
52 | networks:
53 | - easyhaproxy
54 |
55 | networks:
56 | easyhaproxy:
57 | external: true
58 | ```
59 |
60 | Deploy the stack:
61 |
62 | ```bash title="Deploy EasyHAProxy stack"
63 | docker stack deploy --compose-file docker-compose.yml easyhaproxy
64 | ```
65 |
66 | Mapping to `/var/run/docker.sock` is necessary to discover the docker containers and get the labels;
67 |
68 | :::danger Single Replica Only
69 | **Do not** add more than one replica for EasyHAProxy. To understand why, see the [limitations](limitations.md) page.
70 | :::
71 |
72 | ## Running containers
73 |
74 | To make your containers "discoverable" by EasyHAProxy, that is the minimum configuration you need:
75 |
76 | ```yaml
77 | services:
78 | container:
79 | image: my/image:tag
80 | deploy:
81 | replicas: 1
82 | labels:
83 | easyhaproxy.http.host: host1.local
84 | easyhaproxy.http.port: 80
85 | easyhaproxy.http.localport: 8080
86 | networks:
87 | - easyhaproxy
88 |
89 | networks:
90 | easyhaproxy:
91 | external: true
92 | ```
93 |
94 | Once the container is running, EasyHAProxy will detect automatically and start to redirect all traffic from `example.org:80` to your container.
95 |
96 | You don't need to expose any port in your container.
97 |
98 | Please follow the [docker label configuration](container-labels.md) to see other configurations available.
99 |
100 | ## Setup the EasyHAProxy container
101 |
102 | You can configure the behavior of the EasyHAProxy by setup specific environment variables. To get a list of the variables, please follow the [environment variable guide](environment-variable.md)
103 |
104 | ## More information
105 |
106 | You can refer to the [Docker Documentation](docker.md) to get other detailed instructions.
107 |
108 | ----
109 | [Open source ByJG](http://opensource.byjg.com)
110 |
--------------------------------------------------------------------------------
/src/plugins/builtin/ip_whitelist.py:
--------------------------------------------------------------------------------
1 | """
2 | IP Whitelist Plugin for EasyHAProxy
3 |
4 | This plugin restricts access to a domain to only specific IP addresses or CIDR ranges.
5 | It runs as a DOMAIN plugin (once per domain).
6 |
7 | Configuration:
8 | - enabled: Enable/disable the plugin (default: true)
9 | - allowed_ips: Comma-separated list of IPs/CIDR ranges to allow
10 | - status_code: HTTP status code to return for blocked IPs (default: 403)
11 |
12 | Example YAML config:
13 | plugins:
14 | ip_whitelist:
15 | enabled: true
16 | allowed_ips: "192.168.1.0/24,10.0.0.1,172.16.0.0/16"
17 | status_code: 403
18 |
19 | Example Container Label:
20 | easyhaproxy.http.plugins: "ip_whitelist"
21 | easyhaproxy.http.plugin.ip_whitelist.allowed_ips: "192.168.1.0/24,10.0.0.1"
22 | easyhaproxy.http.plugin.ip_whitelist.status_code: 403
23 |
24 | HAProxy Config Generated:
25 | # IP Whitelist - Only allow specific IPs
26 | acl whitelisted_ip src 192.168.1.0/24 10.0.0.1
27 | http-request deny deny_status 403 if !whitelisted_ip
28 | """
29 |
30 | import os
31 | import sys
32 |
33 | # Add parent directory to path for imports
34 | sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
35 |
36 | from plugins import PluginInterface, PluginType, PluginContext, PluginResult
37 |
38 |
39 | class IpWhitelistPlugin(PluginInterface):
40 | """Plugin to restrict access to specific IP addresses"""
41 |
42 | def __init__(self):
43 | self.enabled = True
44 | self.allowed_ips = []
45 | self.status_code = 403
46 |
47 | @property
48 | def name(self) -> str:
49 | return "ip_whitelist"
50 |
51 | @property
52 | def plugin_type(self) -> PluginType:
53 | return PluginType.DOMAIN
54 |
55 | def configure(self, config: dict) -> None:
56 | """
57 | Configure the plugin
58 |
59 | Args:
60 | config: Dictionary with configuration options
61 | - enabled: Whether plugin is enabled
62 | - allowed_ips: Comma-separated list of IPs/CIDR ranges
63 | - status_code: HTTP status code to return for denied requests
64 | """
65 | if "enabled" in config:
66 | self.enabled = str(config["enabled"]).lower() in ["true", "1", "yes"]
67 |
68 | if "allowed_ips" in config:
69 | ips_str = str(config["allowed_ips"])
70 | self.allowed_ips = [ip.strip() for ip in ips_str.split(",") if ip.strip()]
71 |
72 | if "status_code" in config:
73 | try:
74 | self.status_code = int(config["status_code"])
75 | except ValueError:
76 | self.status_code = 403
77 |
78 | def process(self, context: PluginContext) -> PluginResult:
79 | """
80 | Generate HAProxy config to whitelist specific IPs
81 |
82 | Args:
83 | context: Plugin execution context with domain information
84 |
85 | Returns:
86 | PluginResult with HAProxy configuration snippet
87 | """
88 | if not self.enabled or not self.allowed_ips:
89 | return PluginResult()
90 |
91 | # Create space-separated list of IPs for ACL
92 | ips_str = " ".join(self.allowed_ips)
93 |
94 | # Generate HAProxy config snippet
95 | haproxy_config = f"""# IP Whitelist - Only allow specific IPs
96 | acl whitelisted_ip src {ips_str}
97 | http-request deny deny_status {self.status_code} if !whitelisted_ip"""
98 |
99 | return PluginResult(
100 | haproxy_config=haproxy_config,
101 | modified_easymapping=None,
102 | metadata={
103 | "domain": context.domain,
104 | "allowed_ips": self.allowed_ips,
105 | "status_code": self.status_code
106 | }
107 | )
108 |
--------------------------------------------------------------------------------
/examples/kubernetes/service.yml:
--------------------------------------------------------------------------------
1 | # ==============================================================================
2 | # EXAMPLE: Basic Kubernetes Ingress
3 | # ==============================================================================
4 | #
5 | # WHAT THIS DEMONSTRATES:
6 | # - Basic ingress configuration with EasyHAProxy
7 | # - Multiple domains pointing to the same service
8 | # - Complete deployment + service + ingress setup
9 | # - HTTP ingress without TLS
10 | #
11 | # REQUIREMENTS (run these first):
12 | # ```bash
13 | # # 1. Ensure EasyHAProxy is installed in your cluster
14 | # kubectl create namespace easyhaproxy
15 | # kubectl apply -f https://raw.githubusercontent.com/byjg/docker-easy-haproxy/5.0.0/deploy/kubernetes/easyhaproxy-daemonset.yml
16 | #
17 | # # 2. Label the node where EasyHAProxy will run
18 | # kubectl label nodes