diff --git a/ct/patchmon.sh b/ct/patchmon.sh index ebd28b546..1022d0bff 100644 --- a/ct/patchmon.sh +++ b/ct/patchmon.sh @@ -43,22 +43,40 @@ function update_script() { CLEAN_INSTALL=1 fetch_and_deploy_gh_release "PatchMon" "PatchMon/PatchMon" "tarball" "latest" "/opt/patchmon" msg_info "Updating PatchMon" - cd /opt/patchmon + VERSION=$(get_latest_github_release "PatchMon/PatchMon") + PROTO="$(sed -n '/SERVER_PROTOCOL/s/[^=]*=//p' /opt/backend.env)" + HOST="$(sed -n '/SERVER_HOST/s/[^=]*=//p' /opt/backend.env)" + [[ "${PROTO:-http}" == "http" ]] && PORT=":3001" + sed -i 's/PORT=3399/PORT=3001/' /opt/backend.env + sed -i -e "s/VERSION=.*/VERSION=$VERSION/" \ + -e "\|VITE_API_URL=|s|http.*|${PROTO:-http}://${HOST:-$LOCAL_IP}${PORT:-}/api/v1|" /opt/frontend.env export NODE_ENV=production - $STD npm install --no-audit --no-fund --no-save --ignore-scripts - cd /opt/patchmon/backend + cd /opt/patchmon $STD npm install --no-audit --no-fund --no-save --ignore-scripts cd /opt/patchmon/frontend - $STD npm install --include=dev --no-audit --no-fund --no-save --ignore-scripts + mv /opt/frontend.env /opt/patchmon/frontend/.env + $STD npm install --no-audit --no-fund --no-save --ignore-scripts --include=dev $STD npm run build cd /opt/patchmon/backend mv /opt/backend.env /opt/patchmon/backend/.env - mv /opt/frontend.env /opt/patchmon/frontend/.env + $STD npm run db:generate $STD npx prisma migrate deploy - $STD npx prisma generate + cp /opt/patchmon/docker/nginx.conf.template /etc/nginx/sites-available/patchmon.conf + sed -i -e 's|proxy_pass .*|proxy_pass http://127.0.0.1:3001;|' \ + -e '\|try_files |i\ root /opt/patchmon/frontend/dist;' \ + -e 's|alias.*|alias /opt/patchmon/frontend/dist/assets;|' \ + -e '\|expires 1y|i\ root /opt/patchmon/frontend/dist;' /etc/nginx/sites-available/patchmon.conf + ln -sf /etc/nginx/sites-available/patchmon.conf /etc/nginx/sites-enabled/ + rm -f /etc/nginx/sites-enabled/default + $STD nginx -t + systemctl restart nginx msg_ok "Updated PatchMon" msg_info "Starting Service" + if grep -q '/usr/bin/node' /etc/systemd/system/patchmon-server.service; then + sed -i 's|ExecStart=.*|ExecStart=/usr/bin/npm run start|' /etc/systemd/system/patchmon-server.service + systemctl daemon-reload + fi systemctl start patchmon-server msg_ok "Started Service" msg_ok "Updated successfully!" @@ -73,4 +91,4 @@ description msg_ok "Completed successfully!\n" echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" echo -e "${INFO}${YW} Access it using the following URL:${CL}" -echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}" +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3000${CL}" diff --git a/frontend/public/json/patchmon.json b/frontend/public/json/patchmon.json index 3fc347a0d..4cb919fa8 100644 --- a/frontend/public/json/patchmon.json +++ b/frontend/public/json/patchmon.json @@ -8,7 +8,7 @@ "type": "ct", "updateable": true, "privileged": false, - "interface_port": 3399, + "interface_port": 3000, "documentation": "https://docs.patchmon.net", "website": "https://patchmon.net", "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/patchmon.webp", diff --git a/install/patchmon-install.sh b/install/patchmon-install.sh index 99ef333af..9dc7d2666 100644 --- a/install/patchmon-install.sh +++ b/install/patchmon-install.sh @@ -27,162 +27,42 @@ PG_DB_NAME="patchmon_db" PG_DB_USER="patchmon_usr" setup_postgresql_db fetch_and_deploy_gh_release "PatchMon" "PatchMon/PatchMon" "tarball" "latest" "/opt/patchmon" msg_info "Configuring PatchMon" -cd /opt/patchmon +VERSION=$(get_latest_github_release "PatchMon/PatchMon") export NODE_ENV=production +cd /opt/patchmon $STD npm install --no-audit --no-fund --no-save --ignore-scripts -cd /opt/patchmon/backend -$STD npm install --no-audit --no-fund --no-save --ignore-scripts + cd /opt/patchmon/frontend -$STD npm install --include=dev --no-audit --no-fund --no-save --ignore-scripts -$STD npm run build -JWT_SECRET="$(openssl rand -base64 64 | tr -d "=+/" | cut -c1-50)" -cat </opt/patchmon/backend/.env -# Database Configuration -DATABASE_URL="postgresql://$PG_DB_USER:$PG_DB_PASS@localhost:5432/$PG_DB_NAME" -PY_THRESHOLD=3M_DB_CONN_MAX_ATTEMPTS=30 -PM_DB_CONN_WAIT_INTERVAL=2 - -# JWT Configuration -JWT_SECRET="$JWT_SECRET" -JWT_EXPIRES_IN=1h -JWT_REFRESH_EXPIRES_IN=7d - -# Server Configuration -PORT=3399 -NODE_ENV=production - -# API Configuration -API_VERSION=v1 - -# CORS Configuration -CORS_ORIGIN="http://$LOCAL_IP" - -# Session Configuration -SESSION_INACTIVITY_TIMEOUT_MINUTES=30 - -# User Configuration -DEFAULT_USER_ROLE=user - -# Rate Limiting (times in milliseconds) -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 Configuration -REDIS_HOST=localhost -REDIS_PORT=6379 - -# Logging -LOG_LEVEL=info -ENABLE_LOGGING=true - -# TFA Configuration -TFA_REMEMBER_ME_EXPIRES_IN=30d -TFA_MAX_REMEMBER_SESSIONS=5 -TFA_SUSPICIOUS_ACTIVITY_THRESHOLD=3 -EOF - -cat </opt/patchmon/frontend/.env -VITE_API_URL=http://$LOCAL_IP/api/v1 +cat <./.env +VITE_API_URL=http://${LOCAL_IP}:3001/api/v1 VITE_APP_NAME=PatchMon -VITE_APP_VERSION=1.3.0 +VITE_APP_VERSION=${VERSION} EOF +$STD npm install --no-audit --no-fund --no-save --ignore-scripts --include=dev +$STD npm run build + +JWT_SECRET="$(openssl rand -hex 64)" +mv /opt/patchmon/backend/env.example /opt/patchmon/backend/.env +sed -i -e "s|DATABASE_URL=.*|DATABASE_URL=\"postgresql://$PG_DB_USER:$PG_DB_PASS@localhost:5432/$PG_DB_NAME\"|" \ + -e "/JWT_SECRET/s/[=$].*/=$JWT_SECRET/" \ + -e "\|CORS_ORIGIN|s|localhost|$LOCAL_IP|" \ + -e "/PORT=3001/aSERVER_PROTOCOL=http \\ + SERVER_HOST=$LOCAL_IP \\ + SERVER_PORT=3000" \ + -e '/_ENV=production/aTRUST_PROXY=1' \ + -e '/REDIS_USER=.*/,+1d' /opt/patchmon/backend/.env cd /opt/patchmon/backend +$STD npm run db:generate $STD npx prisma migrate deploy -$STD npx prisma generate msg_ok "Configured PatchMon" msg_info "Configuring Nginx" -cat </etc/nginx/sites-available/patchmon.conf -map \$http_x_forwarded_proto \$proxy_corrected_scheme { - default \$scheme; # Fallback to Nginx's actual connection scheme if no X-Forwarded-Proto header was set - https https; # If X-Forwarded-Proto is 'https', use 'https' - http http; # If X-Forwarded-Proto is 'http', use 'http' -} - -server { - # Listen on both IPv4 and IPv6 (with all hostnames) - listen 80; - listen [::]:80; - - # Security headers - add_header X-Frame-Options DENY always; - add_header X-Content-Type-Options nosniff always; - add_header X-XSS-Protection "1; mode=block" always; - add_header Referrer-Policy "strict-origin-when-cross-origin" always; - - # Frontend - location / { - root /opt/patchmon/frontend/dist; - try_files \$uri \$uri/ /index.html; - } - - # Bull Board proxy - location /bullboard { - proxy_pass http://127.0.0.1:3399; - proxy_http_version 1.1; - proxy_set_header Upgrade \$http_upgrade; - proxy_set_header Connection 'upgrade'; - proxy_set_header Host \$host; - proxy_set_header X-Real-IP \$remote_addr; - proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto \$proxy_corrected_scheme; - proxy_set_header X-Forwarded-Host \$host; - proxy_set_header Cookie \$http_cookie; - proxy_cache_bypass \$http_upgrade; - proxy_read_timeout 300s; - proxy_connect_timeout 75s; - - # Enable cookie passthrough - proxy_pass_header Set-Cookie; - proxy_cookie_path / /; - - # Preserve original client IP - proxy_set_header X-Original-Forwarded-For \$http_x_forwarded_for; - if (\$request_method = 'OPTIONS') { - return 204; - } - } - - # API proxy - location /api/ { - proxy_pass http://127.0.0.1:3399; - proxy_http_version 1.1; - proxy_set_header Upgrade \$http_upgrade; - proxy_set_header Connection 'upgrade'; - proxy_set_header Host \$host; - proxy_set_header X-Real-IP \$remote_addr; - proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto \$proxy_corrected_scheme; - proxy_cache_bypass \$http_upgrade; - proxy_read_timeout 300s; - proxy_connect_timeout 75s; - - # Preserve original client IP - proxy_set_header X-Original-Forwarded-For \$http_x_forwarded_for; - if (\$request_method = 'OPTIONS') { - return 204; - } - } - - # Static assets caching (exclude Bull Board assets) - location ~* ^/(?!bullboard).*\.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { - root /opt/patchmon/frontend/dist; - expires 1y; - add_header Cache-Control "public, immutable"; - } - - # Health check endpoint - location /health { - proxy_pass http://127.0.0.1:3399/health; - access_log off; - } -} -EOF +cp /opt/patchmon/docker/nginx.conf.template /etc/nginx/sites-available/patchmon.conf +sed -i -e 's|proxy_pass .*|proxy_pass http://127.0.0.1:3001;|' \ + -e '\|try_files |i\ root /opt/patchmon/frontend/dist;' \ + -e 's|alias.*|alias /opt/patchmon/frontend/dist/assets;|' \ + -e '\|expires 1y|i\ root /opt/patchmon/frontend/dist;' /etc/nginx/sites-available/patchmon.conf ln -sf /etc/nginx/sites-available/patchmon.conf /etc/nginx/sites-enabled/ rm -f /etc/nginx/sites-enabled/default $STD nginx -t @@ -198,7 +78,7 @@ After=network.target postgresql.service [Service] Type=simple WorkingDirectory=/opt/patchmon/backend -ExecStart=/usr/bin/node src/server.js +ExecStart=/usr/bin/npm run start Restart=always RestartSec=10 Environment=NODE_ENV=production @@ -215,57 +95,6 @@ EOF systemctl enable -q --now patchmon-server msg_ok "Created and started service" -msg_info "Updating settings" -cat </opt/patchmon/backend/update-settings.js -const { PrismaClient } = require('@prisma/client'); -const { v4: uuidv4 } = require('uuid'); -const prisma = new PrismaClient(); - -async function updateSettings() { - try { - const existingSettings = await prisma.settings.findFirst(); - - const settingsData = { - id: uuidv4(), - server_url: 'http://$LOCAL_IP', - server_protocol: 'http', - server_host: '$LOCAL_IP', - server_port: 3399, - update_interval: 60, - auto_update: true, - signup_enabled: false, - ignore_ssl_self_signed: false, - updated_at: new Date() - }; - - if (existingSettings) { - // Update existing settings - await prisma.settings.update({ - where: { id: existingSettings.id }, - data: settingsData - }); - } else { - // Create new settings record - await prisma.settings.create({ - data: settingsData - }); - } - - console.log('✅ Database settings updated successfully'); - } catch (error) { - console.error('❌ Error updating settings:', error.message); - process.exit(1); - } finally { - await prisma.\$disconnect(); - } -} - -updateSettings(); -EOF -cd /opt/patchmon/backend -$STD node update-settings.js -msg_ok "Settings updated successfully" - motd_ssh customize cleanup_lxc