# ============================================================================== # EXAMPLE: Multiple Plugins Combined (Swarm) # ============================================================================== # # WHAT THIS DEMONSTRATES: # - Using multiple plugins together for layered security # - Three different security profiles for different service types: # * Public website: Cloudflare IP restoration + path blocking # * Protected API: JWT authentication + path blocking # * Admin panel: Strict IP whitelist # - Complex production-ready security configuration # # REQUIREMENTS (run these first): # ```bash # # Initialize Docker Swarm (if not already initialized) # docker swarm init # # # Create overlay network (idempotent) # docker network ls | grep -q easyhaproxy || docker network create --driver overlay --attachable easyhaproxy # # # Ensure EasyHAProxy is deployed # docker stack deploy -c easyhaproxy.yml easyhaproxy # # # Generate JWT key pair (RS256 algorithm) # openssl genrsa -out jwt_private.pem 2048 # openssl rsa -in jwt_private.pem -pubout -out jwt_pubkey.pem # docker config create jwt_api_pubkey jwt_pubkey.pem # # # Download Cloudflare IP ranges and create Docker config # curl https://www.cloudflare.com/ips-v4 > cloudflare_ips.lst # echo "" >> cloudflare_ips.lst # curl https://www.cloudflare.com/ips-v6 >> cloudflare_ips.lst # docker config create cloudflare_ips cloudflare_ips.lst # rm cloudflare_ips.lst jwt_private.pem jwt_pubkey.pem # # # Add to /etc/hosts for local testing (idempotent) # grep -q "website.example.com" /etc/hosts || echo "127.0.0.1 website.example.com api.example.com admin.example.com" | sudo tee -a /etc/hosts # # # IMPORTANT: Edit this file (plugins-combined.yml) line 124 to add your actual IP! # ``` # # HOW TO START: # ```bash # docker stack deploy -c plugins-combined.yml production # ``` # # HOW TO VERIFY IT'S WORKING: # ```bash # # Check stack is deployed # docker stack ls | grep production # # Expected: production stack listed # # # Check all services are running # docker service ls | grep production # # Expected: 3 services (website, api, admin) with all replicas running # # # Test public website (Cloudflare + deny_pages) # curl -H "Host: website.example.com" http://localhost/ # # Expected: 200 OK with "Public Website" # curl -H "Host: website.example.com" http://localhost/admin # # Expected: HTTP 404 (blocked by deny_pages) # # # Test protected API (JWT + deny_pages) # curl -H "Host: api.example.com" http://localhost/ # # Expected: HTTP 401 with "Missing Authorization HTTP header" # # # Generate JWT at https://jwt.io (see jwt-validator.yml for details) # TOKEN="eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." # curl -H "Host: api.example.com" -H "Authorization: Bearer $TOKEN" http://localhost/ # # Expected: 200 OK with "Protected API" # curl -H "Host: api.example.com" -H "Authorization: Bearer $TOKEN" http://localhost/internal # # Expected: HTTP 403 (blocked by deny_pages) # # # Test admin panel (IP whitelist) # curl -H "Host: admin.example.com" http://localhost/ # # Expected: 200 OK if your IP is whitelisted, 403 otherwise # # # View HAProxy stats to see all plugin configurations # # URL: http://localhost:1936 # # Username: admin # # Password: password # ``` # # CLEAN UP: # ```bash # docker stack rm production # # To also remove Docker configs: # # docker config rm cloudflare_ips jwt_api_pubkey # ``` # # ============================================================================== version: "3.7" services: haproxy: image: byjg/easy-haproxy:5.0.0 volumes: - /var/run/docker.sock:/var/run/docker.sock configs: - source: cloudflare_ips target: /etc/haproxy/cloudflare_ips.lst - source: jwt_api_pubkey target: /etc/haproxy/jwt_keys/api_pubkey.pem deploy: replicas: 1 placement: constraints: - node.role == manager environment: EASYHAPROXY_DISCOVER: swarm EASYHAPROXY_SSL_MODE: "loose" HAPROXY_CUSTOMERRORS: "true" HAPROXY_USERNAME: admin HAPROXY_PASSWORD: password HAPROXY_STATS_PORT: 1936 ports: - "80:80/tcp" - "443:443/tcp" - "1936:1936/tcp" networks: - easyhaproxy # Public website with Cloudflare + path blocking website: image: byjg/static-httpserver environment: TITLE: "Public Website" deploy: replicas: 4 labels: easyhaproxy.http.host: "website.example.com" easyhaproxy.http.port: "80" easyhaproxy.http.localport: "8080" # Cloudflare IP restoration + block sensitive paths easyhaproxy.http.plugins: "cloudflare,deny_pages" easyhaproxy.http.plugin.deny_pages.paths: "/admin,/wp-admin,/wp-login.php,/.env,/config" easyhaproxy.http.plugin.deny_pages.status_code: "404" networks: - easyhaproxy # Protected API with JWT + path blocking api: image: byjg/static-httpserver environment: TITLE: "Protected API" deploy: replicas: 6 labels: easyhaproxy.http.host: "api.example.com" easyhaproxy.http.port: "80" easyhaproxy.http.localport: "8080" # JWT validation + block internal endpoints easyhaproxy.http.plugins: "jwt_validator,deny_pages" # JWT configuration 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" # Block internal/debug paths easyhaproxy.http.plugin.deny_pages.paths: "/internal,/debug,/metrics" easyhaproxy.http.plugin.deny_pages.status_code: "403" networks: - easyhaproxy # Admin panel with strict IP whitelist admin: image: byjg/static-httpserver environment: TITLE: "Admin Panel" deploy: replicas: 2 labels: easyhaproxy.http.host: "admin.example.com" easyhaproxy.http.port: "80" easyhaproxy.http.localport: "8080" # IP whitelist only (strictest security) easyhaproxy.http.plugins: "ip_whitelist" # Only allow office network # UPDATE with your actual office/VPN IPs! easyhaproxy.http.plugin.ip_whitelist.allowed_ips: "203.0.113.0/24,10.0.0.0/8" easyhaproxy.http.plugin.ip_whitelist.status_code: "403" networks: - easyhaproxy networks: easyhaproxy: external: true configs: cloudflare_ips: external: true jwt_api_pubkey: external: true