Installing PatchMon Server on Docker
Installing PatchMon Server on Docker
Overview
PatchMon isruns as a containerised application thatmade monitors system patches and updates. The application consistsup of four main services:
- Database
:- PostgreSQL 17 - Redis
:- Redis 7 (used for BullMQ job queues andcachingcaching) - Backend
:- Node.js API server - Frontend
:- React application served via NGINX
Container Images
- Backend: ghcr.io/patchmon/patchmon-backend
- Frontend: ghcr.io/patchmon/patchmon-frontend
Available Tags
-
Tag Description latest:The latestLatest stable release ofPatchMonx.y.z:FullExact version tagspin (e.g.1.2.3)-Usethis for exact version pinning.x.y:MinorLatest versionpatchtagsin a minor series (e.g.1.2)-UsethisxtoLatest getminorthe latestand patchreleasein aminormajorversion series.x: Major version tagsseries (e.g.1)-Usethis to get the latest minor and patch release in a major version series.edge:The latestLatest development build withinthemainmostbranchrecent features and fixes. This tag- mayoftenbeunstable and is intended onlyunstable, for testingandonlydevelopmentpurposes. - Download the
Docker Compose file Set a database password in the file where it says:filesenvironment:curlPOSTGRES_PASSWORD:-fsSL#-oCREATEdocker-compose.ymlA STRONG PASSWORD AND PUT IT HEREhttps://raw.githubusercontent.com/PatchMon/PatchMon/refs/heads/main/docker/docker-compose.ymlUpdate the correspondingDATABASE_URLwith your password in the backend service where it says:environment:curlDATABASE_URL:-fsSLpostgresql:-o env.example https://patchmon_user:REPLACE_YOUR_POSTGRES_PASSWORD_HERE@database:5432/patchmon_dbraw.githubusercontent.com/PatchMon/PatchMon/refs/heads/main/docker/env.exampleSetCreateayourRedis.envpasswordfileinCopy the
Redisexampleservicefilecommandandwheregenerateitthesays:three required secrets:command:cpredis-serverenv.example--requirepass.envyour-redis-password-here#Note: The Redis service uses a hardcoded password in the command line for better reliabilityGenerate andto avoid environment variable parsing issues.Update the correspondingREDIS_PASSWORDin the backend service where it says:environment: REDIS_PASSWORD: your-redis-password-hereGenerate ainsert strongJWTsecretssecret.sedYou-ican do this like so:"s/^POSTGRES_PASSWORD=$/POSTGRES_PASSWORD=$(openssl rand -hex6432)/" .env sed -i "s/^REDIS_PASSWORD=$/REDIS_PASSWORD=$(openssl rand -hex 32)/" .env sed -i "s/^JWT_SECRET=$/JWT_SECRET=$(openssl rand -hex 64)/" .env- open
.envand configure your server access settings:# SetatheseJWTtosecretthe URL you will use to access PatchMon. # SERVER_PROTOCOL, SERVER_HOST and SERVER_PORT are used by agents to connect back to PatchMon. # CORS_ORIGIN should match the full URL you access PatchMon from intheyourbackendbrowser.serviceSERVER_PROTOCOL=httpwhereSERVER_HOST=localhostitSERVER_PORT=3000says:environment: JWT_SECRET: # CREATE A STRONG SECRET AND PUT IT HERECORS_ORIGIN=http://localhost:3000 ConfigureTip: If you are deploying PatchMon behind a reverse proxy with a domain name, set
SERVER_PROTOCOL=https,SERVER_HOST=patchmon.example.com,SERVER_PORT=443, andCORS_ORIGIN=https://patchmon.example.com.Starttheapplication:Environment Variables page.3. Start PatchMon
docker compose up -dAccessallthecontainersapplicationare healthy, open your browser athttp://localhost:3000
These tags are available for bothBoth backend and frontend images asshare theythe aresame versionedversion together.tags.
Quick Start
Production1. Deployment
2.
Then
That's it. The docker-compose.yml uses env_file: .env to pass all your configuration straight into the containers. You do not need to edit the compose file itself.
For a full list of optional environment variables (rate limiting, logging, database pool tuning, session timeouts, etc.), see Configuration section)
Once
Updating PatchMon
By default,default the compose file uses the latest tagtag. forTo both backend and frontend images.
This means you can update PatchMon to the latest version as easily as:update:
docker compose pull
docker compose up -d
--pull
This command will:
Pullpulls the latestimagesimages,fromrecreatesthecontainers,registryand Recreatekeepscontainers with updated imagesMaintainall your dataand configuration
Version-Specific Updates
If you'd like to pin your Docker deployment of PatchMonPinning to a specific version,version
If you can do this in the compose file.
When you do this, updatingprefer to apin newversions, version requires manually updating the image tags in the compose file yourself:
Updateupdate the image tags indocker-compose.yml. For example::services: backend: image: ghcr.io/patchmon/patchmon-backend:1.2.3 # Update version here ...4.0 frontend: image: ghcr.io/patchmon/patchmon-frontend:1.2.3 # Update version here ...4.0Then
run the update command:run:docker compose pull docker compose up -d--pull
[!TIP]Check the releases page for version-specific changes and migration notes.
ConfigurationVolumes
Environment
The Variablescompose
Databasefile Service
creates the following Docker volumes:
|
directory |
|
|
directory |
|
|
Redis Service
|
[!NOTE] The Redis service uses a hardcoded password in the command line (redis-server --requirepass your-password) instead of environment variables or configuration files. This approach eliminates parsing issues and provides better reliability. The password must be set in both the Redis command and the backend service environment variables.
Backend Service
Database Configuration
| ||
|
| favicons) |
| |
Redis Configuration
| | |
| | |
| ||
| 1.4.0 |
Authentication & Security
| | |
| | |
| | |
| | |
| |
Server & Network Configuration
| | |
| | |
| | |
| | |
| | |
| | |
| |
You SERVER_PROTOCOL, SEVER_HOST & SERVER_PORT is used by the agent scripts to communicate to the server which goes via the frontend.
Generally this is the same as CORS_ORIGIN but in some cases it's different.
Rate Limiting
| | |
| | |
| | |
| | |
| | |
| |
Logging
| | |
| |
Frontend Service
| | |
| |
Volumes
The compose file creates three Docker volumes:
postgres_data: PostgreSQL's data directory.redis_data: Redis's data directory.agent_files: PatchMon's agent files.
If you wish tocan bind eitherany ifof their respective container pathsthese to a host path ratherinstead thanof a Docker volume,volume youby can do so inediting the Docker Composecompose file.
[!TIP]Note: The backend container runs as user&and group ID 1000. If youplanrebind theagent_filesorbranding_assetsvolumes tore-bindathehostagentpath,filesmakedirectory, ensuresure thatthe same user and/oruser/groupIDhaspermission towriteto the host path to which it's bound.permissions.
Docker Swarm Deployment
This section covers deploying PatchMon to a Docker Swarm cluster. For standard single-host deployments, use the production guide above.
Network Configuration
This section covers deploying PatchMon to a Docker Swarm cluster. For standard single-host deployments, use the production guide above.
The default compose file uses an internal bridge network (patchmon-internal) for service-to-service communication. All services connect to this network and discover each other by service name.
If you are using an external reverse proxy network (e.g. Traefik):
- Keep all PatchMon services on
patchmon-internalfor internal communication - Optionally add the frontend service to the reverse proxy network
- Make sure service name resolution works within the same network
Example: Traefik integration
services:
frontend:
image: ghcr.io/patchmon/patchmon-frontend:latest
networks:
- patchmon-internal
deploy:
replicas: 1
labels:
- "traefik.enable=true"
- "traefik.http.routers.patchmon.rule=Host(`patchmon.example.com`)"
The frontend reaches the backend via patchmon-internal using the hostname backend, while Traefik routes external traffic to the frontend.
Troubleshooting: host not found in upstream "backend"
This usually means the frontend and backend are on different networks, or services haven't fully started. Check:
- All services are on the same internal network
- Service health status with
docker psordocker service ps - Network connectivity with
docker exec <container> ping backend
Development Setup
This section is for developers who want to contribute to PatchMon or run it locally in development mode.
Development
Getting
For development with live reload and source code mounting:
startedClone the repository:git clone https://github.com/PatchMon/PatchMon.git cdpatchmon.netPatchMonStart development environment:docker compose -f docker/docker-compose.dev.yml up --watch --buildSeeDevelopment Commandsfor more options.Access the application:Frontend:http://localhost:3000Backend API:http://localhost:3001Database:localhost:5432Redis:localhost:6379
Development Docker Compose
The development compose file (docker/docker-compose.dev.yml):file:
- Builds images locally from source
using development targets - Enables hot reload
withvia Docker Compose watchfunctionality - Exposes
databasealland backendservice ports fortesting and developmentdebugging - Mounts source code directly into containers
for live development Supports debugging with enhanced logging
BuildingDevelopment Imagesports
Locally
| Service | Port | URL |
|---|---|---|
| Frontend | 3000 | http://localhost:3000 |
| Backend API | 3001 | http://localhost:3001 |
| PostgreSQL | 5432 | localhost:5432 |
| Redis | 6379 | localhost:6379 |
Common commands
# BuildStart developmentwith hot reload (attached)
docker compose -f docker/docker-compose.dev.yml up --watch
# Start detached
docker compose -f docker/docker-compose.dev.yml up -d
# Rebuild a specific service
docker compose -f docker/docker-compose.dev.yml up -d --build backend
# View logs
docker compose -f docker/docker-compose.dev.yml logs -f
How hot reload works
- Frontend/backend source changes are synced automatically in watch mode
- package.json changes trigger an automatic service rebuild
- Prisma schema changes cause the backend to restart automatically
Building images locally
# Development images
docker build -f docker/backend.Dockerfile --target development -t patchmon-backend:dev .
docker build -f docker/frontend.Dockerfile --target development -t patchmon-frontend:dev .
# Build productionProduction images (default target)
docker build -f docker/backend.Dockerfile -t patchmon-backend:latest .
docker build -f docker/frontend.Dockerfile -t patchmon-frontend:latest .
Development Commands
Hot Reload Development
# Attached, live log output, services stopped on Ctrl+C
docker compose -f docker/docker-compose.dev.yml up
# Attached with Docker Compose watch for hot reload
docker compose -f docker/docker-compose.dev.yml up --watch
# Detached
docker compose -f docker/docker-compose.dev.yml up -d
# Quiet, no log output, with Docker Compose watch for hot reload
docker compose -f docker/docker-compose.dev.yml watch
Rebuild Services
# Rebuild specific service
docker compose -f docker/docker-compose.dev.yml up -d --build backend
# Rebuild all services
docker compose -f docker/docker-compose.dev.yml up -d --build
Development Ports
The development setup exposes additional ports for debugging:
Database:5432- Direct PostgreSQL accessRedis:6379- Direct Redis accessBackend:3001- API server with development featuresFrontend:3000- React development server with hot reload
Development Workflow
Initial Setup: Clone repository and start development environmentgit clone https://github.com/PatchMon/PatchMon.git cd patchmon.net docker compose -f docker/docker-compose.dev.yml up -d --buildHot Reload Development: Use Docker Compose watch for automatic reloaddocker compose -f docker/docker-compose.dev.yml up --watch --buildCode Changes:Frontend/Backend Source: Files are synced automatically with watch modePackage.json Changes: Triggers automatic service rebuildPrisma Schema Changes: Backend service restarts automatically
Database Access: Connect database client directly tolocalhost:5432Redis Access: Connect Redis client directly tolocalhost:6379Debug: If started withdocker compose [...] up -dordocker compose [...] watch, check logs manually:docker compose -f docker/docker-compose.dev.yml logs -fOtherwise logs are shown automatically in attached modes (up,up --watch).
Features in Development Mode
Hot Reload: Automatic code synchronization and service restartsEnhanced Logging: Detailed logs for debuggingDirect Access: Exposed ports for database, Redis, and API debuggingHealth Checks: Built-in health monitoring for servicesVolume Persistence: Development data persists between restarts