In einer Zeit, in der IT-Sicherheit und Patch-Management immer wichtiger werden, stehen viele Administratoren vor der Herausforderung, ihre Server-Landschaft systematisch zu überwachen und aktuell zu halten. PatchMon bietet hier eine leistungsstarke Open-Source-Lösung, die speziell für kleine bis mittelständische Unternehmen entwickelt wurde.
PatchMon ist ein modernes Patch-Management-System, das entwickelt wurde, um die Verwaltung von System-Updates über mehrere Server hinweg zu vereinfachen. Es richtet sich an Systemadministratoren, IT-Dienstleister und DevOps-Teams, die eine zentrale Übersicht über den Patch-Status ihrer Infrastruktur benötigen.
Die Stärken von PatchMon liegen in der einfachen Einrichtung und der übersichtlichen Web-Oberfläche. Das System unterstützt Linux-basierte Systeme und bietet automatische Agent-Erkennung, zentralisierte Update-Verwaltung und detaillierte Reporting-Funktionen. Durch die aktive Entwicklung und moderne Architektur bleibt PatchMon stets auf dem neuesten Stand der Technik.
| Datum | Änderungen |
|---|---|
| 04.12.2025 | Anleitung erstellt |
1. Grundvoraussetzung
Diese Anleitung wurde getestet mit Traefik v3.6.1 und Docker v29.0.0 auf Debian Trixxie sollte aber auch auf Ubuntu funktionieren. Alle Befehle werden als Root-Benutzer ausgeführt.
- Docker & Docker Compose v2 (Debian / Ubuntu)
- Traefik V3 Installation, Konfiguration und CrowdSec-Security
- Root oder Sudo-Zugriff
2. Verzeichnisse anlegen und Berechtigungen anlegen
mkdir -p /opt/containers/patchmon/{agent_files,postgres_data,redis_data}
chown -R 1000:1000 /opt/containers/patchmon/agent_files # oder 1001:1001, je nach Container UID
chmod -R 755 /opt/containers/patchmon/agent_files
cd /opt/containers/patchmon/
3. Dateien erstellen
Nun legen wir uns die Docker Compose Datei und die Umgebungsvariablen an:
touch .env docker-compose.yml
Inhalt der /opt/containers/docker-compose.yml:
services:
database:
image: postgres:17-alpine
restart: unless-stopped
environment:
POSTGRES_DB: patchmon_db
POSTGRES_USER: patchmon_user
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- ./postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U patchmon_user -d patchmon_db"]
interval: 3s
timeout: 5s
retries: 7
networks:
- default
redis:
image: redis:7-alpine
restart: unless-stopped
command: redis-server --requirepass ${REDIS_PASSWORD}
volumes:
- ./redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "--no-auth-warning", "-a", "${REDIS_PASSWORD}", "ping"]
interval: 3s
timeout: 5s
retries: 7
networks:
- default
backend:
image: ghcr.io/patchmon/patchmon-backend:latest
restart: unless-stopped
environment:
LOG_LEVEL: info
DATABASE_URL: ${DATABASE_URL}
JWT_SECRET: ${JWT_SECRET}
SERVER_PROTOCOL: https
SERVER_HOST: 0.0.0.0
SERVER_PORT: 3001
CORS_ORIGIN: ${CORS_ORIGIN}
DB_CONNECTION_LIMIT: 30
DB_POOL_TIMEOUT: 20
DB_CONNECT_TIMEOUT: 10
DB_IDLE_TIMEOUT: 300
DB_MAX_LIFETIME: 1800
RATE_LIMIT_WINDOW_MS: 900000
RATE_LIMIT_MAX: 5000
AUTH_RATE_LIMIT_WINDOW_MS: 600000
AUTH_RATE_LIMIT_MAX: 500
AGENT_RATE_LIMIT_WINDOW_MS: 60000
AGENT_RATE_LIMIT_MAX: 1000
REDIS_HOST: redis
REDIS_PORT: 6379
REDIS_PASSWORD: ${REDIS_PASSWORD}
REDIS_DB: 0
volumes:
- ./agent_files:/app/agents
depends_on:
database:
condition: service_healthy
redis:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3001/health"]
interval: 10s
timeout: 5s
retries: 3
labels:
- "traefik.enable=true"
- "traefik.http.routers.patchmon-backend.entrypoints=websecure"
- "traefik.http.routers.patchmon-backend.rule=Host(`${PATCHMON_DOMAIN}`) && PathPrefix(`/api`)"
- "traefik.http.routers.patchmon-backend.service=patchmon-backend"
- "traefik.http.services.patchmon-backend.loadbalancer.server.port=3001"
- "traefik.http.routers.patchmon-backend.tls=true"
- "traefik.http.routers.patchmon-backend.tls.certresolver=http_resolver"
- "traefik.docker.network=proxy"
- "traefik.http.routers.patchmon-backend.middlewares=default@file"
networks:
- default
- proxy
frontend:
image: ghcr.io/patchmon/patchmon-frontend:latest
restart: unless-stopped
environment:
VITE_API_URL: https://${PATCHMON_DOMAIN}/api
depends_on:
backend:
condition: service_healthy
labels:
- "traefik.enable=true"
- "traefik.http.routers.patchmon.entrypoints=websecure"
- "traefik.http.routers.patchmon.rule=Host(`${PATCHMON_DOMAIN}`)"
- "traefik.http.routers.patchmon.service=patchmon"
- "traefik.http.services.patchmon.loadbalancer.server.port=3000"
- "traefik.http.routers.patchmon.tls=true"
- "traefik.http.routers.patchmon.tls.certresolver=http_resolver"
- "traefik.docker.network=proxy"
- "traefik.http.routers.patchmon.middlewares=default@file"
networks:
- default
- proxy
networks:
default:
driver: bridge
proxy:
external: true
name: proxy
volumes:
postgres_data:
redis_data:
Inhalt der /opt/containers/patchmon/.env :
# Patchmon - Sensitive Values Only # Kopiere diese Datei als ".env" in das gleiche Verzeichnis wie docker-compose.yml # ======================== # PostgreSQL # ======================== POSTGRES_PASSWORD=TEste1234 # ======================== # Redis # ======================== REDIS_PASSWORD=test123 # ======================== # Backend # ======================== JWT_SECRET=Token-XYZ231234 #bitte ein Token setzen. DATABASE_URL=postgresql://patchmon_user:TEste1234@database:5432/patchmon_db CORS_ORIGIN=https://patchmon.euredomain.de # ======================== # Domain # ======================== PATCHMON_DOMAIN=patchmon.euredomain.de
Passe die die Domain an. Wichtig beide Domains müssen gleich sein und bei CORS_ORIGIN= muss das https:// davor stehen bleiben.
4. PatchMon starten
cd /opt/containers/patchmon docker compose up -d
⏱️ Warte 2-3 Minuten – Der erste Start dauert etwas länger.

