1
0
Fork 0

Compare commits

..

No commits in common. "e7a0f7b9306777c1aa9a69c4dbaf0bbd498e19a5" and "e4b62a3925fec255253ac8fd2adf5d4c9ec73dbd" have entirely different histories.

29 changed files with 409 additions and 1435 deletions

View file

@ -34,7 +34,7 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v7 uses: actions/checkout@v4
- name: Install uv - name: Install uv
run: curl -LsSf https://astral.sh/uv/install.sh | sh run: curl -LsSf https://astral.sh/uv/install.sh | sh
@ -58,7 +58,7 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v7 uses: actions/checkout@v4
- name: Install uv - name: Install uv
run: curl -LsSf https://astral.sh/uv/install.sh | sh run: curl -LsSf https://astral.sh/uv/install.sh | sh
@ -82,7 +82,7 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v7 uses: actions/checkout@v4
- name: Install uv - name: Install uv
run: curl -LsSf https://astral.sh/uv/install.sh | sh run: curl -LsSf https://astral.sh/uv/install.sh | sh
@ -106,7 +106,7 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v7 uses: actions/checkout@v4
- name: Install uv - name: Install uv
run: curl -LsSf https://astral.sh/uv/install.sh | sh run: curl -LsSf https://astral.sh/uv/install.sh | sh
@ -138,7 +138,7 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v7 uses: actions/checkout@v4
- name: Install uv - name: Install uv
run: curl -LsSf https://astral.sh/uv/install.sh | sh run: curl -LsSf https://astral.sh/uv/install.sh | sh
@ -170,17 +170,17 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v7 uses: actions/checkout@v4
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v4 uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4 uses: docker/setup-buildx-action@v3
- name: Log into registry - name: Log into registry
if: github.event_name == 'push' || github.event.inputs.push == 'true' if: github.event_name == 'push' || github.event.inputs.push == 'true'
uses: docker/login-action@v4 uses: docker/login-action@v3
with: with:
registry: ${{ secrets.DOCKER_REGISTRY }} registry: ${{ secrets.DOCKER_REGISTRY }}
username: ${{ secrets.DOCKER_REGISTRY_USER }} username: ${{ secrets.DOCKER_REGISTRY_USER }}
@ -190,11 +190,11 @@ jobs:
# https://github.com/docker/metadata-action # https://github.com/docker/metadata-action
- name: Extract Docker metadata - name: Extract Docker metadata
id: meta id: meta
uses: docker/metadata-action@v6 uses: docker/metadata-action@v5
with: with:
images: ${{ secrets.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }} images: ${{ secrets.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}
- uses: actions/github-script@v9 - uses: actions/github-script@v6
id: tags id: tags
with: with:
script: | script: |
@ -215,7 +215,7 @@ jobs:
run: | run: |
echo "${{ steps.tags.outputs.result }}" echo "${{ steps.tags.outputs.result }}"
- uses: actions/github-script@v9 - uses: actions/github-script@v6
id: normalized id: normalized
with: with:
script: | script: |
@ -239,7 +239,7 @@ jobs:
# Build and push Docker image with Buildx (don't push on PR) # Build and push Docker image with Buildx (don't push on PR)
# https://github.com/docker/build-push-action # https://github.com/docker/build-push-action
- name: Build and push Docker image - name: Build and push Docker image
uses: docker/build-push-action@v7 uses: docker/build-push-action@v5
with: with:
context: . context: .
file: deploy/docker/Dockerfile file: deploy/docker/Dockerfile
@ -271,7 +271,7 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v7 uses: actions/checkout@v4
- name: Install uv - name: Install uv
run: curl -LsSf https://astral.sh/uv/install.sh | sh run: curl -LsSf https://astral.sh/uv/install.sh | sh
@ -291,12 +291,12 @@ jobs:
env: env:
DOC_GITHUB_TOKEN: '${{ secrets.DOC_TOKEN }}' DOC_GITHUB_TOKEN: '${{ secrets.DOC_TOKEN }}'
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v4
if: startsWith(github.ref, 'refs/tags/') if: startsWith(github.ref, 'refs/tags/')
with: with:
ref: master ref: master
- uses: actions/checkout@v7 - uses: actions/checkout@v4
if: github.ref == 'refs/heads/master' if: github.ref == 'refs/heads/master'
- name: Get result - name: Get result

View file

@ -54,7 +54,7 @@ EasyHAProxy follows [Semantic Versioning](https://semver.org/):
- **MINOR**: New features, plugin additions, backward-compatible changes - **MINOR**: New features, plugin additions, backward-compatible changes
- **PATCH**: Bug fixes, documentation updates, minor improvements - **PATCH**: Bug fixes, documentation updates, minor improvements
**Current Version:** `6.1.1` (as of Chart.yaml) **Current Version:** `6.0.1` (as of Chart.yaml)
## Automated Release (Recommended) ## Automated Release (Recommended)
@ -329,8 +329,6 @@ helm show chart byjg/easyhaproxy
| Version | Release Date | Type | Highlights | | Version | Release Date | Type | Highlights |
|---------|--------------|-------|---------------------------------------------------------------------------------------------------------------------------------------| |---------|--------------|-------|---------------------------------------------------------------------------------------------------------------------------------------|
| 6.1.1 | 2026-06-25 | Patch | Add pass_headers support to FastCGI plugin, fix flaky ACME e2e test timeout |
| 6.1.0 | 2026-06-24 | Minor | FastCGI protocol support, certbot sidecar plugin, dependency updates |
| 6.0.1 | 2026-02-23 | Patch | HAProxy dashboard, real-time monitoring dashboard with live traffic charts, ACME e2e test fixes | | 6.0.1 | 2026-02-23 | Patch | HAProxy dashboard, real-time monitoring dashboard with live traffic charts, ACME e2e test fixes |
| 6.0.0 | 2026-XX-XX | Major | Python module refactoring (one-class-per-file), IngressClassName support (spec.ingressClassName + deprecated annotation fallback), modernized build system (uv/pyproject.toml), improved version management and release tooling, GitHub Actions workflow_dispatch push control | | 6.0.0 | 2026-XX-XX | Major | Python module refactoring (one-class-per-file), IngressClassName support (spec.ingressClassName + deprecated annotation fallback), modernized build system (uv/pyproject.toml), improved version management and release tooling, GitHub Actions workflow_dispatch push control |
| 5.0.0 | 2025-12-04 | Major | Plugin framework (builtin plugins: JWT, FastCGI, Cloudflare, IP whitelist, deny pages, cleanup), docs restructure, examples refreshed | | 5.0.0 | 2025-12-04 | Major | Plugin framework (builtin plugins: JWT, FastCGI, Cloudflare, IP whitelist, deny pages, cleanup), docs restructure, examples refreshed |

View file

@ -1,6 +1,6 @@
services: services:
easyhaproxy: easyhaproxy:
image: byjg/easy-haproxy:6.1.1 image: byjg/easy-haproxy:6.0.1
volumes: volumes:
- /var/run/docker.sock:/var/run/docker.sock - /var/run/docker.sock:/var/run/docker.sock
- certs_certbot:/etc/easyhaproxy/certs/certbot - certs_certbot:/etc/easyhaproxy/certs/certbot

View file

@ -6,10 +6,10 @@ metadata:
name: ingress-easyhaproxy name: ingress-easyhaproxy
namespace: easyhaproxy namespace: easyhaproxy
labels: labels:
helm.sh/chart: easyhaproxy-2.0.4 helm.sh/chart: easyhaproxy-2.0.2
app.kubernetes.io/name: easyhaproxy app.kubernetes.io/name: easyhaproxy
app.kubernetes.io/instance: ingress app.kubernetes.io/instance: ingress
app.kubernetes.io/version: "6.1.1" app.kubernetes.io/version: "6.0.1"
app.kubernetes.io/managed-by: Helm app.kubernetes.io/managed-by: Helm
--- ---
# Source: easyhaproxy/templates/clusterrole.yaml # Source: easyhaproxy/templates/clusterrole.yaml
@ -19,10 +19,10 @@ metadata:
name: ingress-easyhaproxy name: ingress-easyhaproxy
namespace: easyhaproxy namespace: easyhaproxy
labels: labels:
helm.sh/chart: easyhaproxy-2.0.4 helm.sh/chart: easyhaproxy-2.0.2
app.kubernetes.io/name: easyhaproxy app.kubernetes.io/name: easyhaproxy
app.kubernetes.io/instance: ingress app.kubernetes.io/instance: ingress
app.kubernetes.io/version: "6.1.1" app.kubernetes.io/version: "6.0.1"
app.kubernetes.io/managed-by: Helm app.kubernetes.io/managed-by: Helm
rules: rules:
- apiGroups: - apiGroups:
@ -83,10 +83,10 @@ metadata:
name: ingress-easyhaproxy name: ingress-easyhaproxy
namespace: easyhaproxy namespace: easyhaproxy
labels: labels:
helm.sh/chart: easyhaproxy-2.0.4 helm.sh/chart: easyhaproxy-2.0.2
app.kubernetes.io/name: easyhaproxy app.kubernetes.io/name: easyhaproxy
app.kubernetes.io/instance: ingress app.kubernetes.io/instance: ingress
app.kubernetes.io/version: "6.1.1" app.kubernetes.io/version: "6.0.1"
app.kubernetes.io/managed-by: Helm app.kubernetes.io/managed-by: Helm
roleRef: roleRef:
apiGroup: rbac.authorization.k8s.io apiGroup: rbac.authorization.k8s.io
@ -105,10 +105,10 @@ metadata:
name: ingress-easyhaproxy name: ingress-easyhaproxy
namespace: easyhaproxy namespace: easyhaproxy
labels: labels:
helm.sh/chart: easyhaproxy-2.0.4 helm.sh/chart: easyhaproxy-2.0.2
app.kubernetes.io/name: easyhaproxy app.kubernetes.io/name: easyhaproxy
app.kubernetes.io/instance: ingress app.kubernetes.io/instance: ingress
app.kubernetes.io/version: "6.1.1" app.kubernetes.io/version: "6.0.1"
app.kubernetes.io/managed-by: Helm app.kubernetes.io/managed-by: Helm
annotations: annotations:
{} {}
@ -140,10 +140,10 @@ metadata:
name: ingress-easyhaproxy name: ingress-easyhaproxy
namespace: easyhaproxy namespace: easyhaproxy
labels: labels:
helm.sh/chart: easyhaproxy-2.0.4 helm.sh/chart: easyhaproxy-2.0.2
app.kubernetes.io/name: easyhaproxy app.kubernetes.io/name: easyhaproxy
app.kubernetes.io/instance: ingress app.kubernetes.io/instance: ingress
app.kubernetes.io/version: "6.1.1" app.kubernetes.io/version: "6.0.1"
app.kubernetes.io/managed-by: Helm app.kubernetes.io/managed-by: Helm
spec: spec:
replicas: 1 replicas: 1
@ -164,7 +164,7 @@ spec:
- name: easyhaproxy - name: easyhaproxy
securityContext: securityContext:
{} {}
image: "byjg/easy-haproxy:6.1.1" image: "byjg/easy-haproxy:6.0.1"
imagePullPolicy: Always imagePullPolicy: Always
ports: ports:
- name: http - name: http
@ -217,10 +217,10 @@ kind: IngressClass
metadata: metadata:
name: easyhaproxy name: easyhaproxy
labels: labels:
helm.sh/chart: easyhaproxy-2.0.4 helm.sh/chart: easyhaproxy-2.0.2
app.kubernetes.io/name: easyhaproxy app.kubernetes.io/name: easyhaproxy
app.kubernetes.io/instance: ingress app.kubernetes.io/instance: ingress
app.kubernetes.io/version: "6.1.1" app.kubernetes.io/version: "6.0.1"
app.kubernetes.io/managed-by: Helm app.kubernetes.io/managed-by: Helm
spec: spec:
controller: byjg.com/easyhaproxy controller: byjg.com/easyhaproxy

View file

@ -6,10 +6,10 @@ metadata:
name: ingress-easyhaproxy name: ingress-easyhaproxy
namespace: easyhaproxy namespace: easyhaproxy
labels: labels:
helm.sh/chart: easyhaproxy-2.0.4 helm.sh/chart: easyhaproxy-2.0.2
app.kubernetes.io/name: easyhaproxy app.kubernetes.io/name: easyhaproxy
app.kubernetes.io/instance: ingress app.kubernetes.io/instance: ingress
app.kubernetes.io/version: "6.1.1" app.kubernetes.io/version: "6.0.1"
app.kubernetes.io/managed-by: Helm app.kubernetes.io/managed-by: Helm
--- ---
# Source: easyhaproxy/templates/clusterrole.yaml # Source: easyhaproxy/templates/clusterrole.yaml
@ -19,10 +19,10 @@ metadata:
name: ingress-easyhaproxy name: ingress-easyhaproxy
namespace: easyhaproxy namespace: easyhaproxy
labels: labels:
helm.sh/chart: easyhaproxy-2.0.4 helm.sh/chart: easyhaproxy-2.0.2
app.kubernetes.io/name: easyhaproxy app.kubernetes.io/name: easyhaproxy
app.kubernetes.io/instance: ingress app.kubernetes.io/instance: ingress
app.kubernetes.io/version: "6.1.1" app.kubernetes.io/version: "6.0.1"
app.kubernetes.io/managed-by: Helm app.kubernetes.io/managed-by: Helm
rules: rules:
- apiGroups: - apiGroups:
@ -83,10 +83,10 @@ metadata:
name: ingress-easyhaproxy name: ingress-easyhaproxy
namespace: easyhaproxy namespace: easyhaproxy
labels: labels:
helm.sh/chart: easyhaproxy-2.0.4 helm.sh/chart: easyhaproxy-2.0.2
app.kubernetes.io/name: easyhaproxy app.kubernetes.io/name: easyhaproxy
app.kubernetes.io/instance: ingress app.kubernetes.io/instance: ingress
app.kubernetes.io/version: "6.1.1" app.kubernetes.io/version: "6.0.1"
app.kubernetes.io/managed-by: Helm app.kubernetes.io/managed-by: Helm
roleRef: roleRef:
apiGroup: rbac.authorization.k8s.io apiGroup: rbac.authorization.k8s.io
@ -104,10 +104,10 @@ metadata:
name: ingress-easyhaproxy name: ingress-easyhaproxy
namespace: easyhaproxy namespace: easyhaproxy
labels: labels:
helm.sh/chart: easyhaproxy-2.0.4 helm.sh/chart: easyhaproxy-2.0.2
app.kubernetes.io/name: easyhaproxy app.kubernetes.io/name: easyhaproxy
app.kubernetes.io/instance: ingress app.kubernetes.io/instance: ingress
app.kubernetes.io/version: "6.1.1" app.kubernetes.io/version: "6.0.1"
app.kubernetes.io/managed-by: Helm app.kubernetes.io/managed-by: Helm
spec: spec:
selector: selector:
@ -136,7 +136,7 @@ spec:
- name: easyhaproxy - name: easyhaproxy
securityContext: securityContext:
{} {}
image: "byjg/easy-haproxy:6.1.1" image: "byjg/easy-haproxy:6.0.1"
imagePullPolicy: Always imagePullPolicy: Always
ports: ports:
- name: http - name: http
@ -189,10 +189,10 @@ kind: IngressClass
metadata: metadata:
name: easyhaproxy name: easyhaproxy
labels: labels:
helm.sh/chart: easyhaproxy-2.0.4 helm.sh/chart: easyhaproxy-2.0.2
app.kubernetes.io/name: easyhaproxy app.kubernetes.io/name: easyhaproxy
app.kubernetes.io/instance: ingress app.kubernetes.io/instance: ingress
app.kubernetes.io/version: "6.1.1" app.kubernetes.io/version: "6.0.1"
app.kubernetes.io/managed-by: Helm app.kubernetes.io/managed-by: Helm
spec: spec:
controller: byjg.com/easyhaproxy controller: byjg.com/easyhaproxy

View file

@ -6,10 +6,10 @@ metadata:
name: ingress-easyhaproxy name: ingress-easyhaproxy
namespace: easyhaproxy namespace: easyhaproxy
labels: labels:
helm.sh/chart: easyhaproxy-2.0.4 helm.sh/chart: easyhaproxy-2.0.2
app.kubernetes.io/name: easyhaproxy app.kubernetes.io/name: easyhaproxy
app.kubernetes.io/instance: ingress app.kubernetes.io/instance: ingress
app.kubernetes.io/version: "6.1.1" app.kubernetes.io/version: "6.0.1"
app.kubernetes.io/managed-by: Helm app.kubernetes.io/managed-by: Helm
--- ---
# Source: easyhaproxy/templates/clusterrole.yaml # Source: easyhaproxy/templates/clusterrole.yaml
@ -19,10 +19,10 @@ metadata:
name: ingress-easyhaproxy name: ingress-easyhaproxy
namespace: easyhaproxy namespace: easyhaproxy
labels: labels:
helm.sh/chart: easyhaproxy-2.0.4 helm.sh/chart: easyhaproxy-2.0.2
app.kubernetes.io/name: easyhaproxy app.kubernetes.io/name: easyhaproxy
app.kubernetes.io/instance: ingress app.kubernetes.io/instance: ingress
app.kubernetes.io/version: "6.1.1" app.kubernetes.io/version: "6.0.1"
app.kubernetes.io/managed-by: Helm app.kubernetes.io/managed-by: Helm
rules: rules:
- apiGroups: - apiGroups:
@ -83,10 +83,10 @@ metadata:
name: ingress-easyhaproxy name: ingress-easyhaproxy
namespace: easyhaproxy namespace: easyhaproxy
labels: labels:
helm.sh/chart: easyhaproxy-2.0.4 helm.sh/chart: easyhaproxy-2.0.2
app.kubernetes.io/name: easyhaproxy app.kubernetes.io/name: easyhaproxy
app.kubernetes.io/instance: ingress app.kubernetes.io/instance: ingress
app.kubernetes.io/version: "6.1.1" app.kubernetes.io/version: "6.0.1"
app.kubernetes.io/managed-by: Helm app.kubernetes.io/managed-by: Helm
roleRef: roleRef:
apiGroup: rbac.authorization.k8s.io apiGroup: rbac.authorization.k8s.io
@ -105,10 +105,10 @@ metadata:
name: ingress-easyhaproxy name: ingress-easyhaproxy
namespace: easyhaproxy namespace: easyhaproxy
labels: labels:
helm.sh/chart: easyhaproxy-2.0.4 helm.sh/chart: easyhaproxy-2.0.2
app.kubernetes.io/name: easyhaproxy app.kubernetes.io/name: easyhaproxy
app.kubernetes.io/instance: ingress app.kubernetes.io/instance: ingress
app.kubernetes.io/version: "6.1.1" app.kubernetes.io/version: "6.0.1"
app.kubernetes.io/managed-by: Helm app.kubernetes.io/managed-by: Helm
annotations: annotations:
{} {}
@ -140,10 +140,10 @@ metadata:
name: ingress-easyhaproxy name: ingress-easyhaproxy
namespace: easyhaproxy namespace: easyhaproxy
labels: labels:
helm.sh/chart: easyhaproxy-2.0.4 helm.sh/chart: easyhaproxy-2.0.2
app.kubernetes.io/name: easyhaproxy app.kubernetes.io/name: easyhaproxy
app.kubernetes.io/instance: ingress app.kubernetes.io/instance: ingress
app.kubernetes.io/version: "6.1.1" app.kubernetes.io/version: "6.0.1"
app.kubernetes.io/managed-by: Helm app.kubernetes.io/managed-by: Helm
spec: spec:
replicas: 1 replicas: 1
@ -164,7 +164,7 @@ spec:
- name: easyhaproxy - name: easyhaproxy
securityContext: securityContext:
{} {}
image: "byjg/easy-haproxy:6.1.1" image: "byjg/easy-haproxy:6.0.1"
imagePullPolicy: Always imagePullPolicy: Always
ports: ports:
- name: http - name: http
@ -217,10 +217,10 @@ kind: IngressClass
metadata: metadata:
name: easyhaproxy name: easyhaproxy
labels: labels:
helm.sh/chart: easyhaproxy-2.0.4 helm.sh/chart: easyhaproxy-2.0.2
app.kubernetes.io/name: easyhaproxy app.kubernetes.io/name: easyhaproxy
app.kubernetes.io/instance: ingress app.kubernetes.io/instance: ingress
app.kubernetes.io/version: "6.1.1" app.kubernetes.io/version: "6.0.1"
app.kubernetes.io/managed-by: Helm app.kubernetes.io/managed-by: Helm
spec: spec:
controller: byjg.com/easyhaproxy controller: byjg.com/easyhaproxy

View file

@ -41,7 +41,7 @@ Exposes HAProxy on NodePort `31080` (HTTP), `31443` (HTTPS), and `31936` (stats)
```bash ```bash
kubectl apply -f \ kubectl apply -f \
https://raw.githubusercontent.com/byjg/docker-easy-haproxy/6.1.1/deploy/kubernetes/easyhaproxy-nodeport.yml https://raw.githubusercontent.com/byjg/docker-easy-haproxy/6.0.1/deploy/kubernetes/easyhaproxy-nodeport.yml
``` ```
### ClusterIP (behind a LoadBalancer) ### ClusterIP (behind a LoadBalancer)
@ -50,7 +50,7 @@ Cluster-internal only. Pair with an external cloud LoadBalancer or `kubectl port
```bash ```bash
kubectl apply -f \ kubectl apply -f \
https://raw.githubusercontent.com/byjg/docker-easy-haproxy/6.1.1/deploy/kubernetes/easyhaproxy-clusterip.yml https://raw.githubusercontent.com/byjg/docker-easy-haproxy/6.0.1/deploy/kubernetes/easyhaproxy-clusterip.yml
``` ```
### DaemonSet (special cases — requires node label) ### DaemonSet (special cases — requires node label)
@ -64,7 +64,7 @@ The node label must be reapplied after any node replacement. Failing to do so wi
kubectl label nodes node-01 "easyhaproxy/node=master" kubectl label nodes node-01 "easyhaproxy/node=master"
kubectl apply -f \ kubectl apply -f \
https://raw.githubusercontent.com/byjg/docker-easy-haproxy/6.1.1/deploy/kubernetes/easyhaproxy-daemonset.yml https://raw.githubusercontent.com/byjg/docker-easy-haproxy/6.0.1/deploy/kubernetes/easyhaproxy-daemonset.yml
``` ```
If you need to configure environment variables (log levels, stats password, etc.), see the [environment variable reference](../reference/environment-variables.md). If you need to configure environment variables (log levels, stats password, etc.), see the [environment variable reference](../reference/environment-variables.md).

View file

@ -28,7 +28,7 @@ docker network create -d overlay --attachable easyhaproxy
```yaml ```yaml
services: services:
haproxy: haproxy:
image: byjg/easy-haproxy:6.1.1 image: byjg/easy-haproxy:6.0.1
volumes: volumes:
- /var/run/docker.sock:/var/run/docker.sock - /var/run/docker.sock:/var/run/docker.sock
deploy: deploy:

View file

@ -157,7 +157,7 @@ Here's a complete `docker-compose.yml` showing proper ACME configuration:
```yaml ```yaml
services: services:
easyhaproxy: easyhaproxy:
image: byjg/easy-haproxy:6.1.1 image: byjg/easy-haproxy:6.0.1
volumes: volumes:
- /var/run/docker.sock:/var/run/docker.sock - /var/run/docker.sock:/var/run/docker.sock
# REQUIRED: Persist Certbot certificates (ACME) # REQUIRED: Persist Certbot certificates (ACME)

View file

@ -83,7 +83,7 @@ docker cp single.pem easyhaproxy:/etc/easyhaproxy/certs/haproxy/example.com.pem
```yaml ```yaml
services: services:
easyhaproxy: easyhaproxy:
image: byjg/easy-haproxy:6.1.1 image: byjg/easy-haproxy:6.0.1
volumes: volumes:
- /var/run/docker.sock:/var/run/docker.sock - /var/run/docker.sock:/var/run/docker.sock
- certs_haproxy:/etc/easyhaproxy/certs/haproxy - certs_haproxy:/etc/easyhaproxy/certs/haproxy

View file

@ -19,56 +19,13 @@ Automatically generates HAProxy `fcgi-app` configuration that defines required C
## Configuration Options ## Configuration Options
| Option | Description | Default | | Option | Description | Default |
|-------------------|--------------------------------------------|--------------------------------------| |-------------------|-----------------------------------------|------------------------------------|
| `enabled` | Enable/disable plugin | `true` | | `enabled` | Enable/disable plugin | `true` |
| `document_root` | Document root path | `/var/www/html` | | `document_root` | Document root path | `/var/www/html` |
| `script_filename` | Custom pattern for SCRIPT_FILENAME | `%[path]` (uses HAProxy's default) | | `script_filename` | Custom pattern for SCRIPT_FILENAME | `%[path]` (uses HAProxy's default) |
| `index_file` | Default index file | `index.php` | | `index_file` | Default index file | `index.php` |
| `path_info` | PATH_INFO preset or custom regex | `php` | | `path_info` | Enable PATH_INFO support | `true` |
| `log_stderr` | Forward FastCGI stderr to HAProxy logs | `false` |
| `keep_conn` | Reuse FastCGI connections between requests | `true` |
| `custom_params` | Dictionary of custom FastCGI parameters | (optional) | | `custom_params` | Dictionary of custom FastCGI parameters | (optional) |
| `pass_headers` | HTTP headers to forward to the FastCGI app | (optional) |
### `path_info` — PATH_INFO Presets
The `path_info` option accepts a preset name or a custom regex. Built-in presets:
| Preset | Language | Regex |
|----------|----------------|---------------------------------|
| `php` | PHP (default) | `^(/.+\.php)(/.*)?$` |
| `python` | Python FastCGI | `^(/.+\.py)(/.*)?$` |
| `perl` | Perl/CGI | `^(/.+\.(pl\|cgi))(/.*)?$` |
| `ruby` | Ruby FastCGI | `^(/.+\.rb)(/.*)?$` |
| `any` | Generic | `^(.+?)(/.*)?$` |
Pass `false` to disable PATH_INFO entirely, or any other string to use it as a custom regex directly.
Setting `path_info: true` maps to `php` for backward compatibility.
### `pass_headers` — Forwarding HTTP Headers
:::important
HAProxy strips `Authorization`, `Proxy-Authorization`, and all hop-by-hop headers before forwarding requests to the FastCGI backend. Applications that rely on these headers (e.g. APIs using Bearer tokens, Basic auth, or JWT) will fail silently without this option.
:::
`pass_headers` accepts a comma-separated string or a list of strings/dicts:
```yaml
# Simple — single header
pass_headers: "Authorization"
# Multiple — comma-separated
pass_headers: "Authorization, Proxy-Authorization"
# With ACL condition — list of dicts
pass_headers:
- Authorization
- name: X-Custom-Header
condition: "if { ssl_fc }"
```
> **Note:** `Content-Type` and `Content-Length` cannot be passed here — they are automatically converted to the CGI parameters `CONTENT_TYPE` and `CONTENT_LENGTH`.
## Configuration Examples ## Configuration Examples
@ -121,7 +78,6 @@ metadata:
easyhaproxy.plugin.fastcgi.document_root: "/var/www/html" easyhaproxy.plugin.fastcgi.document_root: "/var/www/html"
easyhaproxy.plugin.fastcgi.index_file: "index.php" easyhaproxy.plugin.fastcgi.index_file: "index.php"
easyhaproxy.plugin.fastcgi.script_filename: "/var/www/html/index.php" easyhaproxy.plugin.fastcgi.script_filename: "/var/www/html/index.php"
easyhaproxy.plugin.fastcgi.pass_headers: "Authorization, Proxy-Authorization"
spec: spec:
ingressClassName: easyhaproxy ingressClassName: easyhaproxy
rules: rules:
@ -158,7 +114,7 @@ easymapping:
### Environment Variables ### Environment Variables
| Environment Variable | Config Key | Type | Default | Description | | Environment Variable | Config Key | Type | Default | Description |
|----------------------------------------------|-------------------|----------|-------------------------|---------------------------------------| |----------------------------------------------|-------------------|----------|------------------------|---------------------------------------|
| `EASYHAPROXY_PLUGIN_FASTCGI_ENABLED` | `enabled` | boolean | `true` | Enable/disable plugin for all domains | | `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 | `/var/www/html` | Document root path |
| `EASYHAPROXY_PLUGIN_FASTCGI_SCRIPT_FILENAME` | `script_filename` | string | `%[path]` | Custom pattern for SCRIPT_FILENAME | | `EASYHAPROXY_PLUGIN_FASTCGI_SCRIPT_FILENAME` | `script_filename` | string | `%[path]` | Custom pattern for SCRIPT_FILENAME |
@ -172,10 +128,7 @@ easymapping:
fcgi-app fcgi_phpapp_local fcgi-app fcgi_phpapp_local
docroot /var/www/html docroot /var/www/html
index index.php index index.php
option keep-conn
path-info ^(/.+\.php)(/.*)?$ path-info ^(/.+\.php)(/.*)?$
pass-header Authorization
pass-header Proxy-Authorization
# Backend configuration (added to the backend section) # Backend configuration (added to the backend section)
backend srv_phpapp_local_80 backend srv_phpapp_local_80

View file

@ -15,12 +15,12 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes # This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version. # to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/) # Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 2.0.4 version: 2.0.2
# This is the version number of the application being deployed. This version number should be # This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to # incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using. # follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes. # It is recommended to use it with quotes.
appVersion: "6.1.1" appVersion: "6.0.1"
icon: https://opensource.byjg.com/img/easy_haproxy_logo.png icon: https://opensource.byjg.com/img/easy_haproxy_logo.png

View file

@ -99,6 +99,3 @@ spec:
{{- end }} {{- end }}
- name: EASYHAPROXY_STATUS_UPDATE_INTERVAL - name: EASYHAPROXY_STATUS_UPDATE_INTERVAL
value: {{ .Values.ingressStatus.updateInterval | quote }} value: {{ .Values.ingressStatus.updateInterval | quote }}
{{- with .Values.extraEnv }}
{{- toYaml . | nindent 12 }}
{{- end }}

View file

@ -98,15 +98,3 @@ masterNode:
label: easyhaproxy/node label: easyhaproxy/node
values: values:
- master - master
# Extra environment variables to inject into the container
# Supports all Kubernetes env var forms: value, valueFrom (secretKeyRef, configMapKeyRef, fieldRef)
# extraEnv:
# - name: MY_VAR
# value: "my-value"
# - name: SECRET_VAR
# valueFrom:
# secretKeyRef:
# name: my-secret
# key: my-key
extraEnv: []

View file

@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project] [project]
name = "easyhaproxy" name = "easyhaproxy"
version = "6.1.1" version = "6.0.1"
description = "HAProxy label based routing with service discovery for Docker, Swarm, and Kubernetes" description = "HAProxy label based routing with service discovery for Docker, Swarm, and Kubernetes"
readme = "README.md" readme = "README.md"
license = {file = "LICENSE"} license = {file = "LICENSE"}

View file

@ -15,8 +15,6 @@ Configuration:
- index_file: Default index file (default: index.php) - index_file: Default index file (default: index.php)
- path_info: Enable PATH_INFO support (default: true) - path_info: Enable PATH_INFO support (default: true)
- custom_params: Dictionary of custom FastCGI parameters (optional) - custom_params: Dictionary of custom FastCGI parameters (optional)
- pass_headers: Headers to forward to the FastCGI app (optional).
Comma-separated string or list of strings/dicts with optional condition.
Example YAML config: Example YAML config:
plugins: plugins:
@ -36,7 +34,6 @@ Example Kubernetes Annotation:
easyhaproxy.plugins: "fastcgi" easyhaproxy.plugins: "fastcgi"
easyhaproxy.plugin.fastcgi.document_root: /var/www/myapp easyhaproxy.plugin.fastcgi.document_root: /var/www/myapp
easyhaproxy.plugin.fastcgi.index_file: index.php easyhaproxy.plugin.fastcgi.index_file: index.php
easyhaproxy.plugin.fastcgi.pass_headers: "Authorization, Proxy-Authorization"
""" """
import os import os
@ -51,25 +48,13 @@ from plugins import PluginContext, PluginInterface, PluginResult, PluginType
class FastcgiPlugin(PluginInterface): class FastcgiPlugin(PluginInterface):
"""Plugin to configure FastCGI parameters for PHP-FPM""" """Plugin to configure FastCGI parameters for PHP-FPM"""
# Built-in path-info regex presets
PATH_INFO_PRESETS = {
"php": r"^(/.+\.php)(/.*)?$",
"python": r"^(/.+\.py)(/.*)?$",
"perl": r"^(/.+\.(?:pl|cgi))(/.*)?$",
"ruby": r"^(/.+\.rb)(/.*)?$",
"any": r"^(.+?)(/.*)?$",
}
def __init__(self): def __init__(self):
self.enabled = True self.enabled = True
self.document_root = "/var/www/html" self.document_root = "/var/www/html"
self.script_filename = "%[path]" self.script_filename = "%[path]"
self.index_file = "index.php" self.index_file = "index.php"
self.path_info = "php" # False | preset name | custom regex string self.path_info = True
self.log_stderr = False
self.keep_conn = True
self.custom_params = {} self.custom_params = {}
self.pass_headers = [] # list of {"name": str, "condition": str|None}
@property @property
def name(self) -> str: def name(self) -> str:
@ -91,29 +76,6 @@ class FastcgiPlugin(PluginInterface):
- index_file: Default index file - index_file: Default index file
- path_info: Enable PATH_INFO support - path_info: Enable PATH_INFO support
- custom_params: Dictionary of custom FastCGI parameters - custom_params: Dictionary of custom FastCGI parameters
- path_info: Enable PATH_INFO splitting. Accepts:
- False / "false" / "no" / "0": disabled
- "php" (default): ^(/.+[.]php)(/.*)?$
- "python": ^(/.+[.]py)(/.*)?$
- "perl": ^(/.+[.](pl|cgi))(/.*)?$
- "ruby": ^(/.+[.]rb)(/.*)?$
- "any": ^(.+?)(/.*)?$
- any other string: used as-is as the regex
- log_stderr: Forward FastCGI app's stderr to HAProxy logs (default: false)
- keep_conn: Reuse FastCGI connections between requests (default: true)
- pass_headers: Headers to forward to the FastCGI application.
HAProxy omits Authorization, Proxy-Authorization, and hop-by-hop headers
by default this directive is required to pass them through.
Note: Content-Type and Content-Length are never passable here; they are
already converted to CGI parameters (CONTENT_TYPE, CONTENT_LENGTH).
Accepts a comma-separated string or a list of strings/dicts:
Simple: "Authorization"
Multiple: "Authorization, Proxy-Authorization"
With ACL: [{"name": "Authorization", "condition": "if { ssl_fc }"}]
HAProxy syntax: pass-header <name> [ { if | unless } <condition> ]
Ref: https://docs.haproxy.org/dev/configuration.html
""" """
if "enabled" in config: if "enabled" in config:
self.enabled = str(config["enabled"]).lower() in ["true", "1", "yes"] self.enabled = str(config["enabled"]).lower() in ["true", "1", "yes"]
@ -128,40 +90,11 @@ class FastcgiPlugin(PluginInterface):
self.index_file = config["index_file"] self.index_file = config["index_file"]
if "path_info" in config: if "path_info" in config:
val = str(config["path_info"]).lower() self.path_info = str(config["path_info"]).lower() in ["true", "1", "yes"]
if val in ["false", "0", "no"]:
self.path_info = False
elif val in ["true", "1", "yes"]:
self.path_info = "php" # backward-compatible: true → php preset
else:
self.path_info = str(config["path_info"]) # preset name or custom regex
if "log_stderr" in config:
self.log_stderr = str(config["log_stderr"]).lower() in ["true", "1", "yes"]
if "keep_conn" in config:
self.keep_conn = str(config["keep_conn"]).lower() in ["true", "1", "yes"]
if "custom_params" in config: if "custom_params" in config:
self.custom_params = config["custom_params"] self.custom_params = config["custom_params"]
if "pass_headers" in config:
val = config["pass_headers"]
if isinstance(val, str):
self.pass_headers = [{"name": h.strip(), "condition": None}
for h in val.split(",") if h.strip()]
elif isinstance(val, list):
result = []
for item in val:
if isinstance(item, str):
result.append({"name": item.strip(), "condition": None})
elif isinstance(item, dict):
result.append({
"name": item["name"],
"condition": item.get("condition")
})
self.pass_headers = result
def process(self, context: PluginContext) -> PluginResult: def process(self, context: PluginContext) -> PluginResult:
""" """
Process the plugin and generate FastCGI configuration Process the plugin and generate FastCGI configuration
@ -188,16 +121,9 @@ class FastcgiPlugin(PluginInterface):
fcgi_app_lines.append(f" docroot {self.document_root}") fcgi_app_lines.append(f" docroot {self.document_root}")
fcgi_app_lines.append(f" index {self.index_file}") fcgi_app_lines.append(f" index {self.index_file}")
if self.log_stderr:
fcgi_app_lines.append(" log-stderr")
if self.keep_conn:
fcgi_app_lines.append(" option keep-conn")
# PATH_INFO support # PATH_INFO support
if self.path_info: if self.path_info:
regex = self.PATH_INFO_PRESETS.get(self.path_info, self.path_info) fcgi_app_lines.append(" path-info ^(/.+\\.php)(/.*)?$")
fcgi_app_lines.append(f" path-info {regex}")
# Set SCRIPT_FILENAME if customized # Set SCRIPT_FILENAME if customized
if self.script_filename and self.script_filename != "%[path]": if self.script_filename and self.script_filename != "%[path]":
@ -208,13 +134,6 @@ class FastcgiPlugin(PluginInterface):
for param_name, param_value in self.custom_params.items(): for param_name, param_value in self.custom_params.items():
fcgi_app_lines.append(f" set-param {param_name.upper()} {param_value}") fcgi_app_lines.append(f" set-param {param_name.upper()} {param_value}")
# Pass headers
for header in self.pass_headers:
line = f" pass-header {header['name']}"
if header.get("condition"):
line += f" {header['condition']}"
fcgi_app_lines.append(line)
fcgi_app_definition = "\n".join(fcgi_app_lines) fcgi_app_definition = "\n".join(fcgi_app_lines)
# Build metadata # Build metadata
@ -224,10 +143,7 @@ class FastcgiPlugin(PluginInterface):
"document_root": self.document_root, "document_root": self.document_root,
"index_file": self.index_file, "index_file": self.index_file,
"path_info": self.path_info, "path_info": self.path_info,
"log_stderr": self.log_stderr, "custom_params_count": len(self.custom_params)
"keep_conn": self.keep_conn,
"custom_params_count": len(self.custom_params),
"pass_headers_count": len(self.pass_headers)
} }
return PluginResult( return PluginResult(

View file

@ -26,9 +26,6 @@ class Docker(ProcessorInterface):
self.parsed_object = {} self.parsed_object = {}
for container in self.client.containers.list(): for container in self.client.containers.list():
if not any(self.label in key for key in container.labels):
continue
# Issue 32 - Docker container cannot connect to containers in different network. # Issue 32 - Docker container cannot connect to containers in different network.
if ha_proxy_network_name not in container.attrs["NetworkSettings"]["Networks"].keys(): if ha_proxy_network_name not in container.attrs["NetworkSettings"]["Networks"].keys():
ha_proxy_network.connect(container.name) ha_proxy_network.connect(container.name)

View file

@ -105,53 +105,4 @@ def test_processor_docker():
container2.stop() container2.stop()
def test_processor_docker_ignores_unlabeled():
try:
client = docker.from_env()
except docker.errors.DockerException:
pytest.skip("There is no docker environment")
if len(client.containers.list()) > 0:
pytest.skip("I cannot run this test with other containers running.")
network = client.networks.create("test_processor_docker_network", driver="bridge")
# The most recent container is inspected first, so the labeled one defines the network to use.
unlabeled = client.containers.run("byjg/static-httpserver",
name="test_processor_docker_unlabeled",
detach=True,
auto_remove=True,
remove=True)
time.sleep(1)
container = client.containers.run("byjg/static-httpserver",
name="test_processor_docker_labeled",
detach=True,
auto_remove=True,
remove=True,
network=network.name,
labels={
"easyhaproxy.labeled.port": "80",
"easyhaproxy.labeled.localport": "8080",
"easyhaproxy.labeled.host": "labeled.local",
})
try:
time.sleep(1)
static = ProcessorInterface.factory(ProcessorInterface.DOCKER)
# The labeled container is served through the network it already belongs to.
labeled_ip = client.containers.get(container.name).attrs["NetworkSettings"]["Networks"][network.name][
"IPAddress"]
assert _get_ip_host(static.get_parsed_object(), "easyhaproxy.labeled") == labeled_ip
# The container without any label is neither inspected nor connected to the network.
unlabeled_networks = client.containers.get(unlabeled.name).attrs["NetworkSettings"]["Networks"]
assert list(unlabeled_networks.keys()) == ["bridge"]
assert unlabeled_networks["bridge"]["IPAddress"] not in static.get_parsed_object()
finally:
container.stop()
unlabeled.stop()
time.sleep(1)
network.remove()
# test_processor_docker() # test_processor_docker()

View file

@ -950,11 +950,8 @@ class TestFastcgiPlugin:
assert plugin.enabled is True assert plugin.enabled is True
assert plugin.document_root == "/var/www/html" assert plugin.document_root == "/var/www/html"
assert plugin.index_file == "index.php" assert plugin.index_file == "index.php"
assert plugin.path_info == "php" assert plugin.path_info is True
assert plugin.log_stderr is False
assert plugin.keep_conn is True
assert plugin.custom_params == {} assert plugin.custom_params == {}
assert plugin.pass_headers == []
def test_fastcgi_plugin_configuration(self): def test_fastcgi_plugin_configuration(self):
"""Test plugin configuration""" """Test plugin configuration"""
@ -1049,128 +1046,6 @@ class TestFastcgiPlugin:
assert result.haproxy_config is None or result.haproxy_config == "" assert result.haproxy_config is None or result.haproxy_config == ""
def test_fastcgi_plugin_pass_headers_string(self):
"""Test pass_headers parsed from comma-separated string"""
plugin = FastcgiPlugin()
plugin.configure({"pass_headers": "Authorization, Proxy-Authorization"})
assert plugin.pass_headers == [
{"name": "Authorization", "condition": None},
{"name": "Proxy-Authorization", "condition": None},
]
context = PluginContext(
parsed_object={}, easymapping=[], container_env={},
domain="phpapp.local", port="80", host_config={}
)
result = plugin.process(context)
fcgi_app_def = result.global_configs[0]
assert "pass-header Authorization" in fcgi_app_def
assert "pass-header Proxy-Authorization" in fcgi_app_def
assert result.metadata["pass_headers_count"] == 2
def test_fastcgi_plugin_pass_headers_list(self):
"""Test pass_headers parsed from list of strings and dicts with condition"""
plugin = FastcgiPlugin()
plugin.configure({
"pass_headers": [
"Authorization",
{"name": "X-Custom-Header", "condition": "if { ssl_fc }"},
]
})
assert plugin.pass_headers == [
{"name": "Authorization", "condition": None},
{"name": "X-Custom-Header", "condition": "if { ssl_fc }"},
]
context = PluginContext(
parsed_object={}, easymapping=[], container_env={},
domain="phpapp.local", port="80", host_config={}
)
result = plugin.process(context)
fcgi_app_def = result.global_configs[0]
assert "pass-header Authorization" in fcgi_app_def
assert "pass-header X-Custom-Header if { ssl_fc }" in fcgi_app_def
assert result.metadata["pass_headers_count"] == 2
def test_fastcgi_plugin_log_stderr(self):
"""Test log-stderr directive is emitted when enabled"""
plugin = FastcgiPlugin()
plugin.configure({"log_stderr": "true"})
assert plugin.log_stderr is True
context = PluginContext(
parsed_object={}, easymapping=[], container_env={},
domain="phpapp.local", port="80", host_config={}
)
result = plugin.process(context)
assert "log-stderr" in result.global_configs[0]
assert result.metadata["log_stderr"] is True
def test_fastcgi_plugin_keep_conn_disabled(self):
"""Test option keep-conn is omitted when disabled"""
plugin = FastcgiPlugin()
plugin.configure({"keep_conn": "false"})
assert plugin.keep_conn is False
context = PluginContext(
parsed_object={}, easymapping=[], container_env={},
domain="phpapp.local", port="80", host_config={}
)
result = plugin.process(context)
assert "option keep-conn" not in result.global_configs[0]
assert result.metadata["keep_conn"] is False
def test_fastcgi_plugin_path_info_presets(self):
"""Test path_info presets resolve to correct regexes"""
presets = {
"php": r"^(/.+\.php)(/.*)?$",
"python": r"^(/.+\.py)(/.*)?$",
"perl": r"^(/.+\.(?:pl|cgi))(/.*)?$",
"ruby": r"^(/.+\.rb)(/.*)?$",
"any": r"^(.+?)(/.*)?$",
}
context = PluginContext(
parsed_object={}, easymapping=[], container_env={},
domain="phpapp.local", port="80", host_config={}
)
for preset, expected_regex in presets.items():
plugin = FastcgiPlugin()
plugin.configure({"path_info": preset})
assert plugin.path_info == preset
result = plugin.process(context)
assert f"path-info {expected_regex}" in result.global_configs[0], \
f"Preset '{preset}' did not emit expected regex"
def test_fastcgi_plugin_path_info_custom_regex(self):
"""Test path_info accepts a custom regex"""
plugin = FastcgiPlugin()
plugin.configure({"path_info": r"^(/.+\.fcgi)(/.*)?$"})
assert plugin.path_info == r"^(/.+\.fcgi)(/.*)?$"
context = PluginContext(
parsed_object={}, easymapping=[], container_env={},
domain="phpapp.local", port="80", host_config={}
)
result = plugin.process(context)
assert r"path-info ^(/.+\.fcgi)(/.*)?$" in result.global_configs[0]
def test_fastcgi_plugin_path_info_backward_compat(self):
"""Test path_info: true maps to php preset (backward compatibility)"""
plugin = FastcgiPlugin()
plugin.configure({"path_info": "true"})
assert plugin.path_info == "php"
context = PluginContext(
parsed_object={}, easymapping=[], container_env={},
domain="phpapp.local", port="80", host_config={}
)
result = plugin.process(context)
assert r"path-info ^(/.+\.php)(/.*)?$" in result.global_configs[0]
class TestPluginManager: class TestPluginManager:
"""Test cases for PluginManager""" """Test cases for PluginManager"""

View file

@ -60,7 +60,7 @@
services: services:
haproxy: haproxy:
image: byjg/easy-haproxy:6.1.1 image: byjg/easy-haproxy:6.0.1
volumes: volumes:
- /var/run/docker.sock:/var/run/docker.sock - /var/run/docker.sock:/var/run/docker.sock
# Persist the CERTBOT to avoid re-challenge when the server restarts # Persist the CERTBOT to avoid re-challenge when the server restarts

View file

@ -59,7 +59,7 @@
services: services:
easyhaproxy: easyhaproxy:
image: byjg/easy-haproxy:6.1.1 image: byjg/easy-haproxy:6.0.1
volumes: volumes:
- /var/run/docker.sock:/var/run/docker.sock - /var/run/docker.sock:/var/run/docker.sock
- certs_certbot:/etc/easyhaproxy/certs/certbot - certs_certbot:/etc/easyhaproxy/certs/certbot

View file

@ -12,7 +12,7 @@
# ```bash # ```bash
# # 1. Ensure EasyHAProxy is installed in your cluster # # 1. Ensure EasyHAProxy is installed in your cluster
# kubectl create namespace easyhaproxy # kubectl create namespace easyhaproxy
# kubectl apply -f https://raw.githubusercontent.com/byjg/docker-easy-haproxy/6.1.1/deploy/kubernetes/easyhaproxy-daemonset.yml # kubectl apply -f https://raw.githubusercontent.com/byjg/docker-easy-haproxy/6.0.1/deploy/kubernetes/easyhaproxy-daemonset.yml
# #
# # 2. Download Cloudflare IP ranges # # 2. Download Cloudflare IP ranges
# curl -s https://www.cloudflare.com/ips-v4 > cloudflare_ips.lst # curl -s https://www.cloudflare.com/ips-v4 > cloudflare_ips.lst

View file

@ -12,7 +12,7 @@
# ```bash # ```bash
# # 1. Ensure EasyHAProxy is installed in your cluster # # 1. Ensure EasyHAProxy is installed in your cluster
# kubectl create namespace easyhaproxy # kubectl create namespace easyhaproxy
# kubectl apply -f https://raw.githubusercontent.com/byjg/docker-easy-haproxy/6.1.1/deploy/kubernetes/easyhaproxy-daemonset.yml # kubectl apply -f https://raw.githubusercontent.com/byjg/docker-easy-haproxy/6.0.1/deploy/kubernetes/easyhaproxy-daemonset.yml
# #
# # 2. IMPORTANT: Edit this file (line 80) and update allowed_ips # # 2. IMPORTANT: Edit this file (line 80) and update allowed_ips
# # with your actual office/VPN IP addresses or networks # # with your actual office/VPN IP addresses or networks

View file

@ -30,7 +30,7 @@
# ```bash # ```bash
# # 1. Ensure EasyHAProxy is installed in your cluster # # 1. Ensure EasyHAProxy is installed in your cluster
# kubectl create namespace easyhaproxy # kubectl create namespace easyhaproxy
# kubectl apply -f https://raw.githubusercontent.com/byjg/docker-easy-haproxy/6.1.1/deploy/kubernetes/easyhaproxy-daemonset.yml # kubectl apply -f https://raw.githubusercontent.com/byjg/docker-easy-haproxy/6.0.1/deploy/kubernetes/easyhaproxy-daemonset.yml
# #
# # 2. Generate RSA key pair (idempotent - skips if exists) # # 2. Generate RSA key pair (idempotent - skips if exists)
# [ -f jwt_private.pem ] || openssl genrsa -out jwt_private.pem 2048 # [ -f jwt_private.pem ] || openssl genrsa -out jwt_private.pem 2048

View file

@ -15,7 +15,7 @@
# ```bash # ```bash
# # 1. Ensure EasyHAProxy is installed in your cluster # # 1. Ensure EasyHAProxy is installed in your cluster
# kubectl create namespace easyhaproxy # kubectl create namespace easyhaproxy
# kubectl apply -f https://raw.githubusercontent.com/byjg/docker-easy-haproxy/6.1.1/deploy/kubernetes/easyhaproxy-daemonset.yml # kubectl apply -f https://raw.githubusercontent.com/byjg/docker-easy-haproxy/6.0.1/deploy/kubernetes/easyhaproxy-daemonset.yml
# #
# # 2. Generate JWT keys (idempotent - skips if exists) # # 2. Generate JWT keys (idempotent - skips if exists)
# [ -f jwt_private.pem ] || openssl genrsa -out jwt_private.pem 2048 # [ -f jwt_private.pem ] || openssl genrsa -out jwt_private.pem 2048

View file

@ -12,7 +12,7 @@
# ```bash # ```bash
# # 1. Ensure EasyHAProxy is installed in your cluster # # 1. Ensure EasyHAProxy is installed in your cluster
# kubectl create namespace easyhaproxy # kubectl create namespace easyhaproxy
# kubectl apply -f https://raw.githubusercontent.com/byjg/docker-easy-haproxy/6.1.1/deploy/kubernetes/easyhaproxy-daemonset.yml # kubectl apply -f https://raw.githubusercontent.com/byjg/docker-easy-haproxy/6.0.1/deploy/kubernetes/easyhaproxy-daemonset.yml
# #
# # 2. Label the node where EasyHAProxy will run # # 2. Label the node where EasyHAProxy will run
# kubectl label nodes <node-name> "easyhaproxy/node=master" # kubectl label nodes <node-name> "easyhaproxy/node=master"

View file

@ -12,7 +12,7 @@
# ```bash # ```bash
# # 1. Ensure EasyHAProxy is installed in your cluster # # 1. Ensure EasyHAProxy is installed in your cluster
# kubectl create namespace easyhaproxy # kubectl create namespace easyhaproxy
# kubectl apply -f https://raw.githubusercontent.com/byjg/docker-easy-haproxy/6.1.1/deploy/kubernetes/easyhaproxy-daemonset.yml # kubectl apply -f https://raw.githubusercontent.com/byjg/docker-easy-haproxy/6.0.1/deploy/kubernetes/easyhaproxy-daemonset.yml
# #
# # 2. Label the node where EasyHAProxy will run # # 2. Label the node where EasyHAProxy will run
# kubectl label nodes <node-name> "easyhaproxy/node=master" # kubectl label nodes <node-name> "easyhaproxy/node=master"

View file

@ -920,7 +920,7 @@ class TestACME:
"""Test that Pebble successfully issues a certificate""" """Test that Pebble successfully issues a certificate"""
# Wait for certificate issuance (Certbot runs in background loop) # Wait for certificate issuance (Certbot runs in background loop)
# Typical time: 10-15 seconds from container start # Typical time: 10-15 seconds from container start
max_retries = 60 max_retries = 30
check_interval = 1 check_interval = 1
has_success = False has_success = False

1331
uv.lock generated

File diff suppressed because it is too large Load diff