From defde8c94e56b4c3cf125da929a13d2d03f9c8ef Mon Sep 17 00:00:00 2001 From: Mike McFetridge <91107715+mmcfetridge1969@users.noreply.github.com> Date: Mon, 20 Jul 2026 14:08:47 -0400 Subject: [PATCH] . --- .gitea/workflows/deploy-patchmon.yml | 35 ++++++ Patchmon/.env | 169 +++++++++++++++++++++++++++ Patchmon/docker-compose.yml | 114 ++++++++++++++++++ 3 files changed, 318 insertions(+) create mode 100644 .gitea/workflows/deploy-patchmon.yml create mode 100644 Patchmon/.env create mode 100644 Patchmon/docker-compose.yml diff --git a/.gitea/workflows/deploy-patchmon.yml b/.gitea/workflows/deploy-patchmon.yml new file mode 100644 index 0000000..033a577 --- /dev/null +++ b/.gitea/workflows/deploy-patchmon.yml @@ -0,0 +1,35 @@ +name: Deploy Patchmon + +on: + push: + branches: + - main + paths: + - 'Patchmon/**' + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v4 + + - name: Sync Patchmon to Host + uses: appleboy/scp-action@master + with: + host: "192.168.2.14" + username: "miker" + key: ${{ secrets.SSH_PRIVATE_KEY }} + source: "Patchmon/*" + target: "/opt/Docker-Deployments/Patchmon" + strip_components: 1 + + - name: Deploy Patchmon Stack + uses: appleboy/ssh-action@master + with: + host: "192.168.2.14" + username: "miker" + key: ${{ secrets.SSH_PRIVATE_KEY }} + script: | + cd /opt/Docker-Deployments/Patchmon + docker compose up -d --remove-orphans diff --git a/Patchmon/.env b/Patchmon/.env new file mode 100644 index 0000000..d71b128 --- /dev/null +++ b/Patchmon/.env @@ -0,0 +1,169 @@ +# Documentation: https://patchmon.net/docs/patchmon-operator-guide#patchmon-environment-variables-reference + +# ============================================================================== +# Run the script ./setup-env.sh for easy first time filling of variables +# Or Manually perform the tasks below +# ============================================================================== +# [ ] Enter in your frontend URLs you will use to access PatchMon in CORS_ORIGIN +# [ ] Run "openssl rand -hex 64" and put that value in the JWT_SECRET= +# [ ] Run "openssl rand -hex 64" and put that value in the AI_ENCRYPTION_KEY= +# [ ] Run "openssl rand -hex 64" and put that value in the SESSION_SECRET== +# [ ] Run "openssl rand -hex 32" and put that password in where it says POSTGRES_PASSWORD= for the postgresql database +# [ ] Run "openssl rand -hex 32" and put that password in where it says REDIS_PASSWORD= for the redis db + +# ============================================================================== +# SERVER +# ============================================================================== +# CORS_ORIGIN must match your frontend URL. Comma-separated for multiple origins. +# Example: +#CORS_ORIGIN=https://patchmon.domain.tld,http://patchmon.local:3000 + +CORS_ORIGIN=https://patch.mikemcfetridge.com,http://192.168.2.3:3000,http://localhost:3000 +JWT_SECRET=b552dcd09a958144ee3e436acd09767574fba73d2f4237496c97e6d2d59d2b6d4575d0148a3869276130d505492e73c023d40c090c42780fb611d0be9c29f4dc + +# ============================================================================== +# DATABASE (Postgresql) +# ============================================================================== +# It's optional to change the patchmon_user and patchmon_db +# POSTGRES_HOST is "database" because that's the name of the docker container. +# If you are using an external DB or localhost then you may change this accordingly + +POSTGRES_HOST=database +POSTGRES_PASSWORD=0200334338be290e45a13737783fc4e3c873bf63fd4817bf6f254e23f4db38c6 +POSTGRES_USER=patchmon_user +POSTGRES_DB=patchmon_db +DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:5432/${POSTGRES_DB} + +# ============================================================================== +# REDIS +# ============================================================================== +## REDIS_HOST is "redis" because that's the name of the docker container. +# If you are using an external redis server then you may change this accordingly + +REDIS_HOST=redis +REDIS_PORT=6379 +REDIS_PASSWORD=0200334338be290e45a13737783fc4e3c873bf63fd4817bf6f254e23f4db38c6 +REDIS_DB=0 + +# ============================================================================== +# SESSION ENCRYPTION SECRETS +# ============================================================================== +# Used in various encryptions (keep these safe) + +SESSION_SECRET=b552dcd09a958144ee3e436acd09767574fba73d2f4237496c97e6d2d59d2b6d4575d0148a3869276130d505492e73c023d40c090c42780fb611d0be9c29f4dc +AI_ENCRYPTION_KEY=b552dcd09a958144ee3e436acd09767574fba73d2f4237496c97e6d2d59d2b6d4575d0148a3869276130d505492e73c023d40c090c42780fb611d0be9c29f4dc + +# ============================================================================== +# GUACAMOLE (Windows RDP - Beta) +# ============================================================================== +# RDP: connect to guacd sidecar (server image has no guacd binary) + +GUACD_ADDRESS=guacd:4822 + + +# ============================================================================== +# OPTIONAL - CAN BE CONFIGURED VIA APP SETTINGS UI +# ============================================================================== +### Setting them here overrides the configured settings from the app or defaults coded in + +## Server +## TRUST_PROXY is to be set to true if you are using another proxy in front of the app like nginx / caddy etc +# ENABLE_HSTS=false +TRUST_PROXY=true + +## Timezone (TZ or TIMEZONE) Set in full as an example : TZ=Europe/London +# TZ=UTC + +## Logging +## LOG_LEVEL can be info/warn/debug/error +# ENABLE_LOGGING=true +# LOG_LEVEL=info + +## Authentication / Lockout +# MAX_LOGIN_ATTEMPTS=5 +# LOCKOUT_DURATION_MINUTES=15 +# SESSION_INACTIVITY_TIMEOUT_MINUTES=30 +# TFA_MAX_REMEMBER_SESSIONS=5 + +## Auth / JWT / TFA +# When true, auth cookies are browser session cookies (cleared when the browser session ends; not persisted across browser restarts). +# AUTH_BROWSER_SESSION_COOKIES=true +# JWT_EXPIRES_IN=1h +# MAX_TFA_ATTEMPTS=5 +# TFA_LOCKOUT_DURATION_MINUTES=30 +# TFA_REMEMBER_ME_EXPIRES_IN=30d + +## Password policy +# PASSWORD_MIN_LENGTH=8 +# PASSWORD_REQUIRE_UPPERCASE=true +# PASSWORD_REQUIRE_LOWERCASE=true +# PASSWORD_REQUIRE_NUMBER=true +# PASSWORD_REQUIRE_SPECIAL=true + +## Body limits (e.g. 5mb, 10mb, 2mb) +# JSON_BODY_LIMIT=5mb +# AGENT_UPDATE_BODY_LIMIT=2mb + +## Env file path (default: .env) +# ENV_FILE=.env + +## Database connection / pool (startup only) +# PM_DB_CONN_MAX_ATTEMPTS=30 +# PM_DB_CONN_WAIT_INTERVAL=2 +# DB_CONNECTION_LIMIT=30 +# DB_CONNECT_TIMEOUT=10 +# DB_TRANSACTION_LONG_TIMEOUT=60000 + +## Server - Port 3000 is the frontend port, which is proxying backend queries to the backend. This is handled by the server itself. If you change this port, you change the port that is used to access PatchMon and therefore will also need to ammend the "ports" values in your docker-compose.yml +# PORT=3000 +# APP_ENV=production + +## Rate limits (env-only) +# 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 +# PASSWORD_RATE_LIMIT_WINDOW_MS=900000 +# PASSWORD_RATE_LIMIT_MAX=5 + +## User default - Can be changed in settings +# DEFAULT_USER_ROLE=user + +## Redis +# REDIS_TLS=false +# REDIS_TLS_VERIFY=false +# REDIS_TLS_CA=/path/to/ca.pem +# REDIS_CONNECT_TIMEOUT_MS=60000 +# REDIS_COMMAND_TIMEOUT_MS=60000 + +## OIDC / SSO (when OIDC_ENABLED=true, issuer/client/secret/redirect required) +# OIDC_ENABLED=false +# OIDC_ISSUER_URL= +# OIDC_CLIENT_ID= +# OIDC_CLIENT_SECRET= +# OIDC_REDIRECT_URI= +# OIDC_SCOPES=openid email profile groups +# OIDC_AUTO_CREATE_USERS=false +# OIDC_DEFAULT_ROLE=user +# OIDC_DISABLE_LOCAL_AUTH=false +# OIDC_BUTTON_TEXT=Login with SSO +# OIDC_SESSION_TTL=600 +# OIDC_POST_LOGOUT_URI= +# OIDC_SYNC_ROLES=false +# OIDC_ADMIN_GROUP= +# OIDC_SUPERADMIN_GROUP= +# OIDC_HOST_MANAGER_GROUP= +# OIDC_READONLY_GROUP= +# OIDC_USER_GROUP= +# OIDC_ENFORCE_HTTPS=true +# FRONTEND_URL= # Fallback for OIDC_POST_LOGOUT_URI + +## Agent binaries +# AGENTS_DIR=agents +# AGENT_BINARIES_DIR # + +## RDP (in-browser RDP for Windows hosts via guacd) +# GUACD_PATH= # Path to guacd binary, or empty to use PATH +# GUACD_ADDRESS=127.0.0.1:4822 diff --git a/Patchmon/docker-compose.yml b/Patchmon/docker-compose.yml new file mode 100644 index 0000000..fa41c16 --- /dev/null +++ b/Patchmon/docker-compose.yml @@ -0,0 +1,114 @@ +# ============================================================================= +# PatchMon Docker Compose - Production +# ============================================================================= +# To set up your environment, run the setup script: +# +# bash -c "$(curl -fsSL https://raw.githubusercontent.com/PatchMon/PatchMon/refs/heads/main/docker/setup-env.sh)" +# +# This will download env.example, generate secrets, and create your .env file. +# Alternatively, copy env.example to .env and fill in the values manually. +# +# Then start PatchMon: +# +# docker compose up -d +# +# See the PatchMon documentation for full configuration details. +# ============================================================================= + +name: patchmon + +services: + + server: + image: ghcr.io/patchmon/patchmon-server:latest + restart: unless-stopped + env_file: .env + ports: + - "3000:3000" + networks: + - patchmon-internal + depends_on: + database: + condition: service_healthy + redis: + condition: service_healthy + guacd: + condition: service_healthy + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + + database: + image: postgres:17-alpine + restart: unless-stopped + env_file: .env + volumes: + - postgres_data:/var/lib/postgresql/data + networks: + - patchmon-internal + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] + interval: 3s + timeout: 5s + retries: 7 + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + + redis: + image: redis:7-alpine + restart: unless-stopped + env_file: .env + command: redis-server --requirepass ${REDIS_PASSWORD} + volumes: + - redis_data:/data + networks: + - patchmon-internal + healthcheck: + test: ["CMD", "redis-cli", "--no-auth-warning", "-a", "${REDIS_PASSWORD}", "ping"] + interval: 3s + timeout: 5s + retries: 7 + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + + guacd: + image: guacamole/guacd:latest + restart: unless-stopped + read_only: true + tmpfs: + - /tmp:size=64m + security_opt: + - no-new-privileges:true + cap_drop: + - ALL + mem_limit: 512m + cpus: '1.0' + networks: + - patchmon-internal + healthcheck: + test: ["CMD-SHELL", "nc -z localhost 4822 || exit 1"] + interval: 10s + timeout: 5s + retries: 3 + start_period: 10s + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + +volumes: + postgres_data: + redis_data: + +networks: + patchmon-internal: + driver: bridge