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 |
|---|---|
| 10.12.2025 | Docker-Compose.yml angepasst. @Curiosity |
| 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
SERVER_PROTOCOL: https
SERVER_HOST: ${PATCHMON_DOMAIN}
SERVER_PORT: 443
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.


Hallo, gerade erst am Wochende Zuhause im lokalen Netzwerk Patchmon mal probeweise installiert gehabt und für klasse befunden. Leider halt nur lokal. Heute morgen dann hier bei go-neuland diese Installationsanleitung entdeckt und auch gleich auf meinem Hetzner Server installiert. Der Container startet auch einwandfrei, kann mich einloggen und den Admin anlegen. Soweit so gut, jetzt wollte ich mal einen Host hinzufügen doch das klappt nicht. Wenn ich mir den Link kopiere und auf dem zu überwachenden Host ausführen will, passiert nichts. Bekomme auch keine Fehlermeldung. Die 0.0.0.0 natürlich auch gegen die echte IP ausgetauscht und entsprechend in der Firewall für meine IP freigeschaltet. Kann mir da vielleicht jemand einen Tipp geben, wo es klemmt?
Glückwunsch zur 2. Anleitung (:
Super geschrieben und direkt ausprobiert 🙂