Repository files, collaboration, releases and project activity.
ARCHFORGE HISTORY
Blame · src/config.js
Branch main · the Commit author is not necessarily a verified ArchForge account.
e59b7f7cc6archadmin2026-10-11
1 'use strict';e59b7f7cc6archadmin2026-10-11
2 const fs=require('node:fs');e59b7f7cc6archadmin2026-10-11
3 const {URL}=require('node:url');e59b7f7cc6archadmin2026-10-11
4 function loadEnv(file=process.env.STATUS_ENV_FILE || '/etc/archforge-status/status.env') {e59b7f7cc6archadmin2026-10-11
5 if (!fs.existsSync(file)) return;e59b7f7cc6archadmin2026-10-11
6 for(const row of fs.readFileSync(file,'utf8').split(/\r?\n/)){e59b7f7cc6archadmin2026-10-11
7 const line=row.trim(); if(!line||line.startsWith('#'))continue;e59b7f7cc6archadmin2026-10-11
8 const match=line.match(/^([A-Z][A-Z0-9_]*)=(.*)$/); if(!match)continue;e59b7f7cc6archadmin2026-10-11
9 if(process.env[match[1]]===undefined) {e59b7f7cc6archadmin2026-10-11
10 let v=match[2].trim(); if(/^".*"$/.test(v))v=v.slice(1,-1).replace(/\\n/g,'\n');e59b7f7cc6archadmin2026-10-11
11 process.env[match[1]]=v;e59b7f7cc6archadmin2026-10-11
12 }e59b7f7cc6archadmin2026-10-11
13 }e59b7f7cc6archadmin2026-10-11
14 }e59b7f7cc6archadmin2026-10-11
15 function boundedInt(val,def,min,max){let n=Number(val);return Number.isInteger(n)&&n>=min&&n<=max?n:def;}e59b7f7cc6archadmin2026-10-11
16 function urlValue(value,def){try{const u=new URL(value||def);if(u.protocol!=='https:'||u.username||u.password||u.hash)throw Error('invalid');return u.toString();}catch{throw new Error('URL must use HTTPS: '+(value||def));}}e59b7f7cc6archadmin2026-10-11
17 function readConfig(){e59b7f7cc6archadmin2026-10-11
18 loadEnv();e59b7f7cc6archadmin2026-10-11
19 const website=urlValue(process.env.TARGET_WEBSITE,'https://archforge.nl');e59b7f7cc6archadmin2026-10-11
20 const status=urlValue(process.env.STATUS_PUBLIC_URL,'https://status.archforge.nl');e59b7f7cc6archadmin2026-10-11
21 const websiteHost=new URL(website).hostname;e59b7f7cc6archadmin2026-10-11
22 const api=process.env.TARGET_API_URL?urlValue(process.env.TARGET_API_URL):'';e59b7f7cc6archadmin2026-10-11
23 const gitHttp=process.env.TARGET_GIT_HTTP_URL?urlValue(process.env.TARGET_GIT_HTTP_URL):'';e59b7f7cc6archadmin2026-10-11
24 // Disallow off-site targets; prevents DNS rebinding and arbitrary probe destinations via env changes.e59b7f7cc6archadmin2026-10-11
25 for(const u of [api,gitHttp].filter(Boolean))if(new URL(u).hostname!==websiteHost)throw Error('Probe hostname must equal TARGET_WEBSITE host');e59b7f7cc6archadmin2026-10-11
26 const key=process.env.STATUS_ENCRYPTION_KEY||'';e59b7f7cc6archadmin2026-10-11
27 if(!/^[a-f0-9]{64}$/i.test(key) && process.env.NODE_ENV==='production')throw Error('STATUS_ENCRYPTION_KEY must be 32 random bytes in hex');e59b7f7cc6archadmin2026-10-11
28 return {e59b7f7cc6archadmin2026-10-11
29 port:boundedInt(process.env.PORT,3000,1,65535),e59b7f7cc6archadmin2026-10-11
30 host:process.env.STATUS_LISTEN_HOST||'127.0.0.1',e59b7f7cc6archadmin2026-10-11
31 publicUrl:status,website,websiteHost,api,gitHttp,e59b7f7cc6archadmin2026-10-11
32 gitHost:process.env.TARGET_GIT_SSH_HOST||websiteHost,e59b7f7cc6archadmin2026-10-11
33 gitPort:boundedInt(process.env.TARGET_GIT_SSH_PORT,22,1,65535),e59b7f7cc6archadmin2026-10-11
34 interval:boundedInt(process.env.MONITOR_INTERVAL_SECONDS,60,30,3600)*1000,e59b7f7cc6archadmin2026-10-11
35 failures:boundedInt(process.env.MONITOR_FAILURE_THRESHOLD,3,2,20),e59b7f7cc6archadmin2026-10-11
36 recoveries:boundedInt(process.env.MONITOR_RECOVERY_THRESHOLD,2,1,20),e59b7f7cc6archadmin2026-10-11
37 timeout:boundedInt(process.env.MONITOR_TIMEOUT_MS,8000,1000,25000),e59b7f7cc6archadmin2026-10-11
38 discord:process.env.STATUS_DISCORD_WEBHOOK_URL||'',e59b7f7cc6archadmin2026-10-11
39 smtpFrom:process.env.SMTP_FROM||'',e59b7f7cc6archadmin2026-10-11
40 smtpAvailable:!!(process.env.SMTP_HOST&&process.env.SMTP_FROM),e59b7f7cc6archadmin2026-10-11
41 key, dbPath:process.env.STATUS_DB_PATH||'/var/lib/archforge-status/status.db',e59b7f7cc6archadmin2026-10-11
42 test:process.env.NODE_ENV==='test'e59b7f7cc6archadmin2026-10-11
43 };e59b7f7cc6archadmin2026-10-11
44 }e59b7f7cc6archadmin2026-10-11
45 module.exports={loadEnv,readConfig,boundedInt,urlValue};