From b2c3869e3d94b8a4d46fc61f154acc199bfcda0f Mon Sep 17 00:00:00 2001 From: merge-check <140916359+agentHits@users.noreply.github.com> Date: Wed, 28 Oct 2026 14:21:17 -0400 Subject: [PATCH] fix(traefik): pin 3.7.16 and audit the Traefik, Postgres and Redis images MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Что: - Закреплённая версия Traefik 3.7.14 → 3.7.16: PINNED_VERSIONS, TRAEFIK_IMAGE в install-agenthits.sh, docs/server-components-update.md, docs/server-hardening.md, docs/agenthits-install.md. TRAEFIK_VERSION в traefik-setup.ts берётся из PINNED_VERSIONS. - image-audit.yml каждый понедельник сканирует не только образ панели, но и закреплённые traefik, postgres и redis, каждый отдельной задачей. component-versions-sync.test.ts сверяет их теги с PINNED_VERSIONS. - В .trivyignore.yaml добавлена CVE-2026-116587 для usr/local/bin/traefik, срок до 2026-11-27. - Для postgres:18.6 до 2026-11-27 пропускается usr/local/bin/gosu. В нём 26 исправимых находок Go stdlib (gosu 1.19 на Go 1.24.6), а файл игнорирования требует запись на каждую. gosu нужен только при старте контейнера, gosu 1.20 вышел 2026-10-25. - CLAUDE.md и docs/server-components-update.md упоминают аудит этих образов. Зачем: - Traefik — единственный компонент серверов, открытый в интернет (порт 443). Trivy нашёл в traefik:v3.7.14 6 исправимых high: go-jose, golang.org/x/net, Go stdlib. В 3.7.16 остаётся одна: go-jose 4.1.5, исправление в 4.1.6, новее релиза нет. - Образы Traefik, Postgres и Redis до сих пор не проверялись. Риски: - С 3.7.15 Traefik отклоняет CONNECT и по HTTP/2 и HTTP/3, с ответом 501. По HTTP/1 он отклонял его и раньше, с 3.7.9. Прямой прокси через HTTP-роутер Traefik так работать не будет, его нужно вести через TCP-роутер. Изменения Gateway API к Swarm не относятся. - На серверы новая версия попадает только через Components → Update. Это короткий перезапуск Traefik: порт 443 недоступен, пока стартует новый контейнер. - Аудит упадёт 2026-11-27, если к этому времени не выйдут исправленные релизы. Так задумано. Проверки: - Команды и результаты: Trivy 0.76.1 (remote) — traefik:v3.7.14 6 high, v3.7.16 1 high, postgres:18.6 1 C + 25 H только в gosu, redis:8.10.2 без исправимых. Шаг сканирования из image-audit.yml, запущенный локально, — traefik, postgres и redis exit 0; postgres с прошедшей датой exit 1. vitest по 55 файлам, связанным с Traefik и закреплёнными версиями, — 1164 из 1164. biome — без замечаний. actionlint — без замечаний. bash -n install-agenthits.sh — ок. - Ограничения: обновление Traefik кнопкой Components → Update на живом сервере не проверялось. What: - The pinned Traefik goes 3.7.14 → 3.7.16: PINNED_VERSIONS, TRAEFIK_IMAGE in install-agenthits.sh, docs/server-components-update.md, docs/server-hardening.md, docs/agenthits-install.md. TRAEFIK_VERSION in traefik-setup.ts comes from PINNED_VERSIONS. - image-audit.yml now scans, every Monday, the pinned traefik, postgres and redis images as well as the panel image, each in its own job. component-versions-sync.test.ts checks their tags against PINNED_VERSIONS. - .trivyignore.yaml gets CVE-2026-116587 for usr/local/bin/traefik, expiring 2026-11-27. - For postgres:18.6, usr/local/bin/gosu is skipped until 2026-11-27. It carries 26 fixable Go stdlib findings (gosu 1.19 on Go 1.24.6), and the ignore file needs an entry for each. gosu only runs when the container starts; gosu 1.20 came out on 2026-10-25. - CLAUDE.md and docs/server-components-update.md mention the audit of these images. Why: - Traefik is the only server component exposed to the internet (port 443). Trivy found 6 fixable high in traefik:v3.7.14: go-jose, golang.org/x/net, Go stdlib. One remains in 3.7.16: go-jose 4.1.5, fixed in 4.1.6, with no newer release. - The Traefik, Postgres and Redis images were not checked before. Risks: - Since 3.7.15 Traefik rejects CONNECT over HTTP/2 and HTTP/3 as well, with 501. Over HTTP/1 it already did since 3.7.9. A forward proxy behind a Traefik HTTP router will not work this way; it has to go through a TCP router. The Gateway API changes do not apply to Swarm. - Servers get the new version only through Components → Update. That briefly restarts Traefik: port 443 is unavailable while the new container starts. - The audit fails on 2026-11-27 if no fixed releases have come out by then. That is intended. Checks: - Commands and results: Trivy 0.76.1 (remote) — traefik:v3.7.14 6 high, v3.7.16 1 high, postgres:18.6 1 C + 25 H only in gosu, redis:8.10.2 no fixable. The scan step of image-audit.yml run locally — traefik, postgres and redis exit 0; postgres with a past date exit 1. vitest on the 55 files about Traefik and pinned versions — 1164 of 1164. biome — clean. actionlint — clean. bash -n install-agenthits.sh — ok. - Limitations: the Traefik update through Components → Update was not tried on a live server. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/image-audit.yml | 49 +++++++++++++++---- .trivyignore.yaml | 8 ++- CLAUDE.md | 2 +- .../server/component-versions-sync.test.ts | 16 ++++++ docs/agenthits-install.md | 2 +- docs/server-components-update.md | 5 +- docs/server-hardening.md | 2 +- install-agenthits.sh | 2 +- .../server/src/setup/component-versions.ts | 2 +- 9 files changed, 70 insertions(+), 18 deletions(-) diff --git a/.github/workflows/image-audit.yml b/.github/workflows/image-audit.yml index 9fe2bde227..8b43c30fe8 100644 --- a/.github/workflows/image-audit.yml +++ b/.github/workflows/image-audit.yml @@ -2,17 +2,18 @@ name: Image audit # bun audit sees only the npm dependencies. This scan reads the published panel # image: its Debian packages, the Go binaries of the bundled tools (Docker CLI, -# rclone, Railpack, pack) and the npm packages inside it. It fails on critical -# and high findings that already have a fix; .trivyignore.yaml lists the ones -# still waiting for a tool release. GitHub notifies the person who last changed -# the cron line when a scheduled run fails. +# rclone, Railpack, pack) and the npm packages inside it. It also reads the +# pinned Traefik, Postgres and Redis images that run next to the panel and on +# servers. It fails on critical and high findings that already have a fix; +# .trivyignore.yaml lists the ones still waiting for a release. GitHub notifies +# the person who last changed the cron line when a scheduled run fails. on: schedule: - cron: "53 5 * * 1" workflow_dispatch: inputs: image: - description: Image to scan + description: Panel image to scan type: string default: ghcr.io/agenthits/dokploy:agenthits-dev @@ -27,18 +28,46 @@ env: jobs: scan: - name: image audit + name: image audit (${{ matrix.name }}) runs-on: ubuntu-24.04 timeout-minutes: 20 + strategy: + fail-fast: false + matrix: + # component-versions-sync.test.ts keeps the Traefik, Postgres and Redis + # tags equal to PINNED_VERSIONS. + include: + - name: panel + image: ghcr.io/agenthits/dokploy:agenthits-dev + - name: traefik + image: traefik:v3.7.16 + - name: postgres + image: postgres:18.6 + # gosu only switches to the postgres user when the container + # starts. postgres:18.6 still ships gosu 1.19, built with Go 1.24.6; + # its 26 Go stdlib advisories would each need an entry in + # .trivyignore.yaml. gosu 1.20 came out on 2026-10-25, so the skip + # ends with the date below and the scan reports gosu again. + skip-files: usr/local/bin/gosu + skip-until: "2026-11-27" + - name: redis + image: redis:8.10.2 steps: - uses: actions/checkout@v7 with: persist-credentials: false - name: Scan image env: - IMAGE: ${{ inputs.image || 'ghcr.io/agenthits/dokploy:agenthits-dev' }} + IMAGE: ${{ matrix.name == 'panel' && inputs.image || matrix.image }} + SKIP_FILES: ${{ matrix.skip-files }} + SKIP_UNTIL: ${{ matrix.skip-until }} run: | + skip=() + if [ -n "$SKIP_FILES" ] && [[ "$(date -u +%F)" < "$SKIP_UNTIL" ]]; then + skip=(--skip-files "$SKIP_FILES") + fi docker run --rm -v "$PWD:/src:ro" -w /src "$TRIVY_IMAGE" image \ - --image-src remote --scanners vuln --severity CRITICAL,HIGH \ - --ignore-unfixed --ignorefile .trivyignore.yaml --exit-code 1 \ - --no-progress "$IMAGE" + --image-src remote --platform linux/amd64 --scanners vuln \ + --severity CRITICAL,HIGH --ignore-unfixed \ + --ignorefile .trivyignore.yaml --exit-code 1 --no-progress \ + "${skip[@]}" "$IMAGE" diff --git a/.trivyignore.yaml b/.trivyignore.yaml index f38e7226d8..177b4f864a 100644 --- a/.trivyignore.yaml +++ b/.trivyignore.yaml @@ -1,4 +1,5 @@ -# Fixable findings in bundled tools whose latest release still carries them. +# Fixable findings in bundled tools and pinned images whose latest release +# still carries them. # Each entry expires, so the image audit fails again and the tool gets checked # for a new release. vulnerabilities: @@ -19,3 +20,8 @@ vulnerabilities: - usr/libexec/docker/cli-plugins/docker-buildx statement: buildx 0.38.1, the latest release, uses moby/go-archive 0.2.0. expired_at: 2026-11-27 + - id: CVE-2026-116587 + paths: + - usr/local/bin/traefik + statement: Traefik 3.7.16, the latest release, uses go-jose 4.1.5; the fix is in 4.1.6. + expired_at: 2026-11-27 diff --git a/CLAUDE.md b/CLAUDE.md index 87744d8a95..99cad9b28e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -27,4 +27,4 @@ One GitHub release `agenthits-vX.Y.Z` covers a batch of work, not a single PR (o - The one-day age is `minimumReleaseAge` in `bunfig.toml` and `MIN_RELEASE_AGE` in the workflow; change both together. - A commit pushed to the branch of the open PR stops its daily rebuild until the PR is merged or closed. - `.github/workflows/dependency-audit.yml` runs `bun audit` every Monday for advisories published between updates. -- `bun audit` does not see the image. Trivy scans the published `agenthits-dev` image every Monday (`.github/workflows/image-audit.yml`) and the image a PR builds (`bun-migration-docker-check.yml`). Both fail on critical and high findings that have a fix in Debian packages, in the Go binaries of the bundled tools (Docker CLI, rclone, Railpack, pack) or in npm packages inside the image. `.trivyignore.yaml` holds findings whose latest tool release still carries them; each entry expires, so the audit fails again and the tool gets rechecked. Trivy is pinned by digest in both workflows; move them together. +- `bun audit` does not see the image. Trivy scans the published `agenthits-dev` image and the pinned Traefik, Postgres and Redis images every Monday (`.github/workflows/image-audit.yml`), and the image a PR builds (`bun-migration-docker-check.yml`). Both fail on critical and high findings that have a fix in Debian packages, in the Go binaries of the bundled tools (Docker CLI, rclone, Railpack, pack) or in npm packages inside the image. `.trivyignore.yaml` holds findings whose latest tool release still carries them; each entry expires, so the audit fails again and the tool gets rechecked. Trivy is pinned by digest in both workflows; move them together. diff --git a/apps/dokploy/__test__/server/component-versions-sync.test.ts b/apps/dokploy/__test__/server/component-versions-sync.test.ts index d1148c7a5b..ca0997a107 100644 --- a/apps/dokploy/__test__/server/component-versions-sync.test.ts +++ b/apps/dokploy/__test__/server/component-versions-sync.test.ts @@ -121,6 +121,22 @@ describe("CI workflow", () => { }); }); +describe("image audit workflow", () => { + const audit = read(".github/workflows/image-audit.yml"); + + it("scans the pinned Traefik", () => { + expect(pinIn(audit, /image: traefik:v(\S+)/)).toBe(PINNED_VERSIONS.traefik); + }); + it("scans the pinned Postgres", () => { + expect(pinIn(audit, /image: postgres:(\S+)/)).toBe( + PINNED_VERSIONS.postgres, + ); + }); + it("scans the pinned Redis", () => { + expect(pinIn(audit, /image: redis:(\S+)/)).toBe(PINNED_VERSIONS.redis); + }); +}); + describe("application Railpack picker", () => { const picker = read( "apps/dokploy/components/dashboard/application/build/show.tsx", diff --git a/docs/agenthits-install.md b/docs/agenthits-install.md index 113e2f906e..b5abb0f381 100644 --- a/docs/agenthits-install.md +++ b/docs/agenthits-install.md @@ -48,7 +48,7 @@ Installer сам определяет систему: ```text Dokploy: ghcr.io/agenthits/dokploy:agenthits-dev -Traefik: traefik:v3.7.14 +Traefik: traefik:v3.7.16 Postgres: postgres:18.6 Redis: redis:8.10.2 ``` diff --git a/docs/server-components-update.md b/docs/server-components-update.md index 4aa4201e50..3a66769282 100644 --- a/docs/server-components-update.md +++ b/docs/server-components-update.md @@ -6,6 +6,7 @@ - установщик панели `install-agenthits.sh` (значения по умолчанию, плюс Nixpacks, Railpack, pack и RClone на хосте панели); - образ панели `Dockerfile` (Docker, RClone, Railpack, pack); - CI `.github/workflows/pull-request.yml` (Nixpacks, Railpack); +- еженедельный аудит образов `.github/workflows/image-audit.yml` (Traefik, Postgres, Redis); - список версий Railpack в форме приложения (значение по умолчанию и список). Тест `apps/dokploy/__test__/server/component-versions-sync.test.ts` сверяет каждый из этих файлов с `PINNED_VERSIONS` и падает при расхождении. @@ -16,7 +17,7 @@ |---|---|---| | Node.js (базовый образ панели и CI) | 26.12.1 | `node:26.12.1-bookworm-slim`, последний релиз; ветка 26 — LTS с 2026-10-28 | | Docker Engine | 29.9.2 | docker-ce для noble и resolute, amd64 и arm64; в образе панели только docker-ce-cli для bookworm | -| Traefik | 3.7.14 | последний стабильный релиз (GitHub), образ `traefik:v3.7.14` | +| Traefik | 3.7.16 | последний стабильный релиз (GitHub), образ `traefik:v3.7.16` | | Postgres (база панели) | 18.6 | `postgres:18.6`, более новых тегов 18.x нет | | Redis (база панели) | 8.10.2 | `redis:8.10.2`, более новых тегов 8.10.x нет | | Nixpacks | 1.41.0 | последний релиз | @@ -39,7 +40,7 @@ Postgres и Redis относятся к базе панели. На сервер ## Как поменять версию 1. Поменять значение в `PINNED_VERSIONS` (`component-versions.ts`). Для Traefik также можно переопределить переменной окружения `TRAEFIK_VERSION`, но для одинаковой установки этого делать не стоит. -2. Поменять то же значение в `install-agenthits.sh` (значения по умолчанию), `Dockerfile` (ARG) и `.github/workflows/pull-request.yml`. Если тест не проходит, какой-то файл остался со старым значением. +2. Поменять то же значение в `install-agenthits.sh` (значения по умолчанию), `Dockerfile` (ARG), `.github/workflows/pull-request.yml` и `.github/workflows/image-audit.yml`. Если тест не проходит, какой-то файл остался со старым значением. 3. Выпустить панель обычным путём: PR, merge, образ. 4. На каждом сервере нажать Components → Update. diff --git a/docs/server-hardening.md b/docs/server-hardening.md index 21254213fb..366de31a2a 100644 --- a/docs/server-hardening.md +++ b/docs/server-hardening.md @@ -12,7 +12,7 @@ | `--harden` | все три | Все три флага сразу. | | — | `DOKPLOY_SERVER_HARDENING=ssh,ufw,fail2ban` | То же самое панель применяет к новым серверам в «Setup Server». Если задан флаг установки, переменная выставляется автоматически. | -Версия Traefik для серверов берётся из установщика: `TRAEFIK_IMAGE`, сейчас `traefik:v3.7.14`. Тест `apps/dokploy/__test__/server/component-versions-sync.test.ts` падает, если версия по умолчанию в панели расходится с установщиком. +Версия Traefik для серверов берётся из установщика: `TRAEFIK_IMAGE`, сейчас `traefik:v3.7.16`. Тест `apps/dokploy/__test__/server/component-versions-sync.test.ts` падает, если версия по умолчанию в панели расходится с установщиком. Флаги усиления принимают только `install` и `harden`. `install-agenthits.sh update` обновляет панель и её стек, но не меняет SSH, UFW и Fail2Ban. diff --git a/install-agenthits.sh b/install-agenthits.sh index fc38f9427e..a460a9d900 100755 --- a/install-agenthits.sh +++ b/install-agenthits.sh @@ -4,7 +4,7 @@ set -euo pipefail DOKPLOY_IMAGE="${DOKPLOY_IMAGE:-ghcr.io/agenthits/dokploy:agenthits-dev}" DOKPLOY_RELEASE_TAG="${DOKPLOY_RELEASE_TAG:-agenthits-dev}" DOKPLOY_OFFICIAL_VERSION="${DOKPLOY_OFFICIAL_VERSION:-v0.29.8}" -TRAEFIK_IMAGE="${TRAEFIK_IMAGE:-traefik:v3.7.14}" +TRAEFIK_IMAGE="${TRAEFIK_IMAGE:-traefik:v3.7.16}" POSTGRES_IMAGE="${POSTGRES_IMAGE:-postgres:18.6}" REDIS_IMAGE="${REDIS_IMAGE:-redis:8.10.2}" POSTGRES_DATA_TARGET="${POSTGRES_DATA_TARGET:-}" diff --git a/packages/server/src/setup/component-versions.ts b/packages/server/src/setup/component-versions.ts index 5830f4cc99..c74e6b9f7a 100644 --- a/packages/server/src/setup/component-versions.ts +++ b/packages/server/src/setup/component-versions.ts @@ -5,7 +5,7 @@ export const PINNED_VERSIONS = { node: "26.12.1", docker: "29.9.2", - traefik: "3.7.14", + traefik: "3.7.16", postgres: "18.6", redis: "8.10.2", nixpacks: "1.41.0",