Skip to content

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-111 'use strict';
e59b7f7cc6archadmin2026-10-112 const fs=require('node:fs');
e59b7f7cc6archadmin2026-10-113 const {URL}=require('node:url');
e59b7f7cc6archadmin2026-10-114 function loadEnv(file=process.env.STATUS_ENV_FILE || '/etc/archforge-status/status.env') {
e59b7f7cc6archadmin2026-10-115  if (!fs.existsSync(file)) return;
e59b7f7cc6archadmin2026-10-116  for(const row of fs.readFileSync(file,'utf8').split(/\r?\n/)){
e59b7f7cc6archadmin2026-10-117  const line=row.trim(); if(!line||line.startsWith('#'))continue;
e59b7f7cc6archadmin2026-10-118  const match=line.match(/^([A-Z][A-Z0-9_]*)=(.*)$/); if(!match)continue;
e59b7f7cc6archadmin2026-10-119  if(process.env[match[1]]===undefined) {
e59b7f7cc6archadmin2026-10-1110  let v=match[2].trim(); if(/^".*"$/.test(v))v=v.slice(1,-1).replace(/\\n/g,'\n');
e59b7f7cc6archadmin2026-10-1111  process.env[match[1]]=v;
e59b7f7cc6archadmin2026-10-1112  }
e59b7f7cc6archadmin2026-10-1113  }
e59b7f7cc6archadmin2026-10-1114 }
e59b7f7cc6archadmin2026-10-1115 function boundedInt(val,def,min,max){let n=Number(val);return Number.isInteger(n)&&n>=min&&n<=max?n:def;}
e59b7f7cc6archadmin2026-10-1116 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-1117 function readConfig(){
e59b7f7cc6archadmin2026-10-1118  loadEnv();
e59b7f7cc6archadmin2026-10-1119  const website=urlValue(process.env.TARGET_WEBSITE,'https://archforge.nl');
e59b7f7cc6archadmin2026-10-1120  const status=urlValue(process.env.STATUS_PUBLIC_URL,'https://status.archforge.nl');
e59b7f7cc6archadmin2026-10-1121  const websiteHost=new URL(website).hostname;
e59b7f7cc6archadmin2026-10-1122  const api=process.env.TARGET_API_URL?urlValue(process.env.TARGET_API_URL):'';
e59b7f7cc6archadmin2026-10-1123  const gitHttp=process.env.TARGET_GIT_HTTP_URL?urlValue(process.env.TARGET_GIT_HTTP_URL):'';
e59b7f7cc6archadmin2026-10-1124  // Disallow off-site targets; prevents DNS rebinding and arbitrary probe destinations via env changes.
e59b7f7cc6archadmin2026-10-1125  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-1126  const key=process.env.STATUS_ENCRYPTION_KEY||'';
e59b7f7cc6archadmin2026-10-1127  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-1128  return {
e59b7f7cc6archadmin2026-10-1129  port:boundedInt(process.env.PORT,3000,1,65535),
e59b7f7cc6archadmin2026-10-1130  host:process.env.STATUS_LISTEN_HOST||'127.0.0.1',
e59b7f7cc6archadmin2026-10-1131  publicUrl:status,website,websiteHost,api,gitHttp,
e59b7f7cc6archadmin2026-10-1132  gitHost:process.env.TARGET_GIT_SSH_HOST||websiteHost,
e59b7f7cc6archadmin2026-10-1133  gitPort:boundedInt(process.env.TARGET_GIT_SSH_PORT,22,1,65535),
e59b7f7cc6archadmin2026-10-1134  interval:boundedInt(process.env.MONITOR_INTERVAL_SECONDS,60,30,3600)*1000,
e59b7f7cc6archadmin2026-10-1135  failures:boundedInt(process.env.MONITOR_FAILURE_THRESHOLD,3,2,20),
e59b7f7cc6archadmin2026-10-1136  recoveries:boundedInt(process.env.MONITOR_RECOVERY_THRESHOLD,2,1,20),
e59b7f7cc6archadmin2026-10-1137  timeout:boundedInt(process.env.MONITOR_TIMEOUT_MS,8000,1000,25000),
e59b7f7cc6archadmin2026-10-1138  discord:process.env.STATUS_DISCORD_WEBHOOK_URL||'',
e59b7f7cc6archadmin2026-10-1139  smtpFrom:process.env.SMTP_FROM||'',
e59b7f7cc6archadmin2026-10-1140  smtpAvailable:!!(process.env.SMTP_HOST&&process.env.SMTP_FROM),
e59b7f7cc6archadmin2026-10-1141  key, dbPath:process.env.STATUS_DB_PATH||'/var/lib/archforge-status/status.db',
e59b7f7cc6archadmin2026-10-1142  test:process.env.NODE_ENV==='test'
e59b7f7cc6archadmin2026-10-1143  };
e59b7f7cc6archadmin2026-10-1144 }
e59b7f7cc6archadmin2026-10-1145 module.exports={loadEnv,readConfig,boundedInt,urlValue};