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