From ee1bf618207a897d15a818ad85ed5c659ae7ebbf Mon Sep 17 00:00:00 2001 From: RonaldHensbergen Date: Fri, 28 Aug 2026 18:25:50 +0200 Subject: [PATCH 1/7] New module for traefik --- modules/integration/traefik/module.yaml | 188 ++++++++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 modules/integration/traefik/module.yaml diff --git a/modules/integration/traefik/module.yaml b/modules/integration/traefik/module.yaml new file mode 100644 index 0000000..4c4138c --- /dev/null +++ b/modules/integration/traefik/module.yaml @@ -0,0 +1,188 @@ +# modules/integration/traefik/module.yaml +# yaml-language-server: $schema=../../../cli/resources/module.schema.json +apiVersion: cds/v1alpha1 +kind: Module + +metadata: + name: traefik + category: integration + version: "3.0.0" + displayName: Traefik + description: > + Traefik reverse proxy with TLS 1.2+ enforcement for secure ingress, + service discovery, and centralized certificate management. + +spec: + runtime: + type: container + service: + name: traefik + ports: + - name: http + containerPort: 80 + protocol: TCP + - name: https + containerPort: 443 + protocol: TCP + - name: dashboard + containerPort: 8080 + protocol: TCP + networks: + - default + + configSchema: + type: object + additionalProperties: false + properties: + log: + type: object + default: {} + properties: + level: + type: string + enum: [DEBUG, INFO, WARN, ERROR] + default: INFO + + accessLog: + type: object + default: {} + properties: + enabled: + type: boolean + default: true + + api: + type: object + default: {} + properties: + dashboard: + type: boolean + default: true + debug: + type: boolean + default: false + insecure: + type: boolean + default: false + + entryPoints: + type: object + default: {} + properties: + web: + type: object + properties: + address: + type: string + default: "127.0.0.1:80" + websecure: + type: object + properties: + address: + type: string + default: "127.0.0.1:443" + + tls: + type: object + default: {} + properties: + minVersion: + type: string + default: VersionTLS12 + maxVersion: + type: string + default: VersionTLS13 + preferServerCipherSuites: + type: boolean + default: true + sniStrict: + type: boolean + default: true + + docker: + type: object + default: {} + properties: + enabled: + type: boolean + default: true + exposedByDefault: + type: boolean + default: false + + fileProvider: + type: object + default: {} + properties: + directory: + type: string + default: "/etc/traefik/dynamic" + watch: + type: boolean + default: true + + provides: + - name: reverse-proxy + contract: + kind: reverse-proxy + spec: + host: ${service.host} + port: 443 + protocol: https + connectionUri: "https://${service.host}:443" + + implementation: + kind: docker-compose + compose: + services: + traefik: + image: traefik:v3.0 + user: traefik + init: true + read_only: true + cap_drop: + - ALL + security_opt: + - no-new-privileges:true + pids_limit: 512 + + ports: + - "${config.entryPoints.web.address}:80" + - "${config.entryPoints.websecure.address}:443" + - "127.0.0.1:8080:8080" + + networks: + - default + + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + - ./traefik/traefik.yml:/etc/traefik/traefik.yml:ro + - ./traefik/dynamic:/etc/traefik/dynamic:ro + - ./certs/traefik:/etc/traefik/certs:ro + - ./data:/data:rw + + environment: + TRAEFIK_LOG_LEVEL: "${config.log.level}" + TRAEFIK_LOG_FILEPATH: "/data/traefik.log" + TRAEFIK_ACCESSLOG: "${config.accessLog.enabled}" + TRAEFIK_ACCESSLOG_FILEPATH: "/data/access.log" + TRAEFIK_API_DASHBOARD: "${config.api.dashboard}" + TRAEFIK_API_DEBUG: "${config.api.debug}" + TRAEFIK_API_INSECURE: "${config.api.insecure}" + TRAEFIK_ENTRYPOINTS_WEB_ADDRESS: "${config.entryPoints.web.address}" + TRAEFIK_ENTRYPOINTS_WEBSECURE_ADDRESS: "${config.entryPoints.websecure.address}" + TRAEFIK_ENTRYPOINTS_WEBSECURE_HTTP_TLS_MINVERSION: "${config.tls.minVersion}" + TRAEFIK_ENTRYPOINTS_WEBSECURE_HTTP_TLS_MAXVERSION: "${config.tls.maxVersion}" + TRAEFIK_ENTRYPOINTS_WEBSECURE_HTTP_TLS_SNISTRICT: "${config.tls.sniStrict}" + TRAEFIK_ENTRYPOINTS_WEBSECURE_HTTP_TLS_PREFERSERVERCIPHERSUITES: "${config.tls.preferServerCipherSuites}" + TRAEFIK_PROVIDERS_DOCKER: "${config.docker.enabled}" + TRAEFIK_PROVIDERS_DOCKER_EXPOSEDBYDEFAULT: "${config.docker.exposedByDefault}" + TRAEFIK_PROVIDERS_DOCKER_NETWORK: "default" + TRAEFIK_PROVIDERS_FILE_DIRECTORY: "${config.fileProvider.directory}" + TRAEFIK_PROVIDERS_FILE_WATCH: "${config.fileProvider.watch}" + + healthcheck: + test: ["CMD", "traefik", "healthcheck", "--ping"] + interval: 10s + timeout: 5s + retries: 3 From 68fdacb60de73e36951fe472b61e33d17c5c409c Mon Sep 17 00:00:00 2001 From: Ronald Hensbergen Date: Sat, 29 Aug 2026 07:15:27 +0200 Subject: [PATCH 2/7] Update modules/integration/traefik/module.yaml Co-authored-by: Dane Parin --- modules/integration/traefik/module.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/integration/traefik/module.yaml b/modules/integration/traefik/module.yaml index 4c4138c..3b38aec 100644 --- a/modules/integration/traefik/module.yaml +++ b/modules/integration/traefik/module.yaml @@ -137,7 +137,7 @@ spec: services: traefik: image: traefik:v3.0 - user: traefik + user: "65532:65532" init: true read_only: true cap_drop: From 42d3d4778d21c32651d63ef9fe2f660a7c4c9750 Mon Sep 17 00:00:00 2001 From: Ronald Hensbergen Date: Sat, 29 Aug 2026 07:16:17 +0200 Subject: [PATCH 3/7] Update modules/integration/traefik/module.yaml Co-authored-by: Dane Parin --- modules/integration/traefik/module.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/integration/traefik/module.yaml b/modules/integration/traefik/module.yaml index 3b38aec..8b92c83 100644 --- a/modules/integration/traefik/module.yaml +++ b/modules/integration/traefik/module.yaml @@ -74,7 +74,7 @@ spec: properties: address: type: string - default: "127.0.0.1:80" + default: ":80" websecure: type: object properties: From 1763e819b50d9ed0d3df8241c60e484a81f86d04 Mon Sep 17 00:00:00 2001 From: Ronald Hensbergen Date: Sat, 29 Aug 2026 07:16:30 +0200 Subject: [PATCH 4/7] Update modules/integration/traefik/module.yaml Co-authored-by: Dane Parin --- modules/integration/traefik/module.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/integration/traefik/module.yaml b/modules/integration/traefik/module.yaml index 8b92c83..9005ff3 100644 --- a/modules/integration/traefik/module.yaml +++ b/modules/integration/traefik/module.yaml @@ -80,7 +80,7 @@ spec: properties: address: type: string - default: "127.0.0.1:443" + default: ":443" tls: type: object From 5f623a7bdf4ab6d616e1fa64a4a220f9ed73284f Mon Sep 17 00:00:00 2001 From: Ronald Hensbergen Date: Sat, 29 Aug 2026 07:17:05 +0200 Subject: [PATCH 5/7] Update modules/integration/traefik/module.yaml Co-authored-by: Dane Parin --- modules/integration/traefik/module.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/integration/traefik/module.yaml b/modules/integration/traefik/module.yaml index 9005ff3..88346c0 100644 --- a/modules/integration/traefik/module.yaml +++ b/modules/integration/traefik/module.yaml @@ -156,7 +156,6 @@ spec: volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - - ./traefik/traefik.yml:/etc/traefik/traefik.yml:ro - ./traefik/dynamic:/etc/traefik/dynamic:ro - ./certs/traefik:/etc/traefik/certs:ro - ./data:/data:rw From 4d4346bc3dd037183572c6cbac024f532c006b4d Mon Sep 17 00:00:00 2001 From: Ronald Hensbergen Date: Sat, 29 Aug 2026 07:17:41 +0200 Subject: [PATCH 6/7] Update modules/integration/traefik/module.yaml Co-authored-by: Dane Parin --- modules/integration/traefik/module.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/integration/traefik/module.yaml b/modules/integration/traefik/module.yaml index 88346c0..7813212 100644 --- a/modules/integration/traefik/module.yaml +++ b/modules/integration/traefik/module.yaml @@ -145,6 +145,8 @@ spec: security_opt: - no-new-privileges:true pids_limit: 512 + tmpfs: + - /tmp:rw,noexec,nosuid,nodev ports: - "${config.entryPoints.web.address}:80" From e87ef4cb8e36c184e9d6689a1d7a3577acc29285 Mon Sep 17 00:00:00 2001 From: RonaldHensbergen Date: Sat, 29 Aug 2026 11:41:15 +0200 Subject: [PATCH 7/7] traefik: pin image digest and drop Docker provider by default Addresses remaining review feedback on PR #549: - Pin traefik:v3.0 to its published sha256 digest, matching the pattern used by modules/cache/keydb. - Disable the Docker provider by default and remove the /var/run/docker.sock bind mount from the compose template. Mounting the socket (even read-only) grants root-equivalent host access and undermines the container's cap_drop/no-new-privileges/read_only hardening. fileProvider remains available for dynamic configuration without requiring the socket. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- modules/integration/traefik/module.yaml | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/modules/integration/traefik/module.yaml b/modules/integration/traefik/module.yaml index 7813212..37d91cd 100644 --- a/modules/integration/traefik/module.yaml +++ b/modules/integration/traefik/module.yaml @@ -105,7 +105,16 @@ spec: properties: enabled: type: boolean - default: true + default: false + description: > + Enables Traefik's Docker provider for label-based dynamic + routing. Disabled by default: this module does not mount + /var/run/docker.sock (doing so grants root-equivalent access + to the Docker host, negating the container's cap_drop/ + no-new-privileges/read_only hardening). Enabling this option + alone has no effect unless the profile also supplies the + socket (e.g. via a socket proxy) through a Compose override; + prefer fileProvider for dynamic configuration instead. exposedByDefault: type: boolean default: false @@ -136,7 +145,7 @@ spec: compose: services: traefik: - image: traefik:v3.0 + image: traefik:v3.0@sha256:a208c74fd80a566d4ea376053bff73d31616d7af3f1465a7747b8b89ee34d97e user: "65532:65532" init: true read_only: true @@ -156,8 +165,11 @@ spec: networks: - default + # No /var/run/docker.sock mount: the Docker provider is disabled + # by default (see docker.enabled above), and mounting the socket + # even read-only would grant root-equivalent host access, + # undermining cap_drop/no-new-privileges/read_only hardening. volumes: - - /var/run/docker.sock:/var/run/docker.sock:ro - ./traefik/dynamic:/etc/traefik/dynamic:ro - ./certs/traefik:/etc/traefik/certs:ro - ./data:/data:rw