diff --git a/Dockerfile b/Dockerfile index 2933ea1..cc3149b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,6 +13,10 @@ ENV DOMAINNAMES ${DOMAINNAMES} ENV TERM xterm ENV HAPROXY_USER_PARAMS ${HAPROXY_USER_PARAMS} ENV HAPROXY_CONFIG ${HAPROXY_CONFIG:-/etc/haproxy/haproxy.cfg} +ENV HTTP_PORT ${HTTP_PORT:-80} +ENV HTTPS_PORT ${HTTPS_PORT:-443} +ENV HTTPS_FORWARDED_PORT ${HTTPS_FORWARDED_PORT:-%[dst_port]} +ENV NAMESERVER ${NAMESERVER:-127.0.0.11:53} ENV PROXY_LOGLEVEL ${PROXY_LOGLEVEL:-notice} ENV MANAGER_HOST ${MANAGER_HOST:-manager} ENV MANAGER_WEB_PORT ${MANAGER_WEB_PORT:-8080} diff --git a/README.md b/README.md index f9a3552..5128123 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,28 @@ # HAProxy docker image + [![Docker Image](https://github.com/openremote/proxy/actions/workflows/proxy.yml/badge.svg)](https://github.com/openremote/proxy/actions/workflows/proxy.yml) HAProxy docker image with Lets Encrypt SSL auto renewal using certbot with built in support for wildcard certificates using AWS Route53. ## Paths + * `/deployment/letsencrypt` - Certbot config directory where generated certificates are stored * `/etc/haproxy/haproxy.cfg` - Default location of haproxy configuration file * `/etc/haproxy/certs` - Static (non certbot) certificates includes self-signed and any other static certificates should be volume mapped into this folder * `/var/log/*` - Location of log files (all are symlinked to stdout) ## Environment variables + * `DOMAINNAME` - IANA TLD subdomain for which a Lets Encrypt certificate should be requested * `DOMAINNAMES` - Comma separated list of IANA TLD subdomain names for which Lets Encrypt certificates should be requested (this is a multi-value alternative to DOMAINNAME) * `HAPROXY_USER_PARAMS` - Additional arguments that should be passed to the haproxy process during startup * `HAPROXY_CONFIG` - Location of HAProxy config file (default: `/etc/haproxy/haproxy.cfg`) * `PROXY_LOGLEVEL` - Log level for HAProxy (default: `notice`) +* `HTTP_PORT` - The container binds to this port for handling HTTP requests (default: `80`) +* `HTTPS_PORT` - The container binds to this port for handling HTTPS requests (default: `443`) +* `HTTPS_FORWARDED_PORT` - The port set in the `X-Forwarded-Port` header of requests send to the Manager/Keycloak (default: `%[dst_port]` this is the HAProxy port) +* `NAMESERVER` - The nameserver hostname and port used for resolving the Manager/Keycloak hosts (default: `127.0.0.11:53`) * `MANAGER_HOST` - Hostname of OpenRemote Manager (default: `manager`) * `MANAGER_WEB_PORT` - Web server port of OpenRemote Manager (default `8080`) * `MANAGER_MQTT_PORT` - MQTT broker port of OpenRemote Manager (default `1883`) @@ -31,12 +38,22 @@ requested (this is a multi-value alternative to DOMAINNAME) * `MQTT_RATE_LIMIT` - Enable rate limiting for MQTT connections (connections/s) ## Custom certificate format + Any custom certificate volume mapped into `/etc/haproxy/certs` should be in PEM format and must include the full certificate chain and the private key, i.e.: -``` - cat privkey.pem cert.pem chain.pem > ssl-certs.pem +```shell +cat privkey.pem cert.pem chain.pem > ssl-certs.pem ``` See `haproxy` SSL cert [documentation](https://www.haproxy.com/blog/haproxy-ssl-termination/#enabling-ssl-with-haproxy). ## Edge gateway tunnelling using SISH + The built in `haproxy.cfg` has support for forwarding requsts beginning with `gw-` to `https://SISH_HOST:SISH_PORT` just define these environment variables to enable this. + +## Kubernetes + +When running the proxy in Kubernetes make sure to set the `HTTP_PORT` and `HTTPS_PORT` environment variables to a non-privileged port (> 1024). +If you use an Ingress, reconfigure the `HTTPS_FORWARDED_PORT` to the HTTPS port of your Ingress (443). + +You will also need to set the `NAMESERVER` environment variable to the cluster DNS (usually 10.96.0.10:53). +The cluster DNS typically only resolves fully qualified hostnames, so make sure to set these using the `MANAGER_HOST` and `KEYCLOAK_HOST` environment variables (e.g. `manager.default.svc.cluster.local`). diff --git a/haproxy.cfg b/haproxy.cfg index fe5421f..0f14400 100644 --- a/haproxy.cfg +++ b/haproxy.cfg @@ -30,7 +30,7 @@ defaults default-server init-addr none resolvers docker_resolver - nameserver dns 127.0.0.11:53 + nameserver dns "${NAMESERVER}" frontend stats bind *:8404 @@ -40,7 +40,7 @@ frontend stats stats refresh 10s frontend http - bind *:80 + bind *:"${HTTP_PORT}" # Serve certificate validation challenges directly with Lua plugin acl url_acme_http01 path_beg /.well-known/acme-challenge/ @@ -55,7 +55,7 @@ frontend http redirect scheme https code 301 if !url_acme_http01 !url_docker_health frontend https - bind *:443 ssl crt /etc/haproxy/certs crt "${CERT_DIR}" no-tls-tickets + bind *:"${HTTPS_PORT}" ssl crt /etc/haproxy/certs crt "${CERT_DIR}" no-tls-tickets # Optional: redirects for root requests with certain host names to service paths acl is_root path -i / @@ -105,7 +105,7 @@ frontend https option forwardfor http-request add-header X-Forwarded-Proto https http-request set-header X-Forwarded-Host %[req.hdr(Host)] - http-request add-header X-Forwarded-Port %[dst_port] + http-request add-header X-Forwarded-Port "${HTTPS_FORWARDED_PORT}" # Enforce HSTS http-response add-header Strict-Transport-Security max-age=15768000 # Block bot indexing @@ -150,9 +150,6 @@ backend manager_backend backend keycloak_backend server keycloak "${KEYCLOAK_HOST}":"${KEYCLOAK_PORT}" resolvers docker_resolver - .if defined(KEYCLOAK_PATH_PREFIX) - http-request replace-path ^"${KEYCLOAK_PATH_PREFIX}"(/.*)?$ \1 - .endif # Gateway tunnelling config .if defined(SISH_HOST) && defined(SISH_PORT)