// Node 22+, local WireGuard tools. Never sends the private key to JMPKit. import fs from 'node:fs/promises'; import path from 'node:path'; import {execFileSync} from 'node:child_process'; process.umask(0o077); const [name='device', directory='./private-wg'] = process.argv.slice(2); const base = new URL(process.env.JMPKIT_APP_URL || 'https://SET-YOUR-APP.jmpkit.app'); const key = process.env.JMPKIT_APP_KEY; if (!key || base.protocol !== 'https:' || base.username || base.password) throw Error('Set trusted HTTPS JMPKIT_APP_URL and private JMPKIT_APP_KEY'); base.pathname='/api/wg10';base.search='';base.hash=''; async function api(suffix,method='GET',body) { const r=await fetch(base.href+suffix,{method,redirect:'error',signal:AbortSignal.timeout(20000), headers:{authorization:'Bearer '+key,'content-type':'application/json'}, ...(body===undefined?{}:{body:JSON.stringify(body)})}); const value=await r.json();if(!r.ok)throw Error('WG HTTP '+r.status+': '+(value.error || 'request failed'));return value; } // Refuse an existing folder; never overwrite a key/config from another join. await fs.mkdir(directory,{mode:0o700}); const privateKey=execFileSync('wg',['genkey'],{encoding:'utf8'}).trim(); const publicKey=execFileSync('wg',['pubkey'],{input:privateKey+'\n',encoding:'utf8'}).trim(); await fs.writeFile(path.join(directory,'private.key'),privateKey+'\n',{mode:0o600,flag:'wx'}); await fs.writeFile(path.join(directory,'public.key'),publicKey+'\n',{mode:0o600,flag:'wx'}); try { await api('','PUT',{}); const peer=await api('/peers','POST',{name,publicKey}); await fs.writeFile(path.join(directory,'peer.json'),JSON.stringify(peer,null,2)+'\n',{mode:0o600}); const result=await api('/peers/'+peer.id+'/config'); if(!result.config.includes(''))throw Error('Unexpected configuration template'); await fs.writeFile(path.join(directory,'jmpkit.conf'),result.config.replace('',privateKey),{mode:0o600,flag:'wx'}); console.log(JSON.stringify({peerId:peer.id,ipv4:peer.ipv4,ipv6:peer.ipv6,config:path.resolve(directory,'jmpkit.conf')},null,2)); }catch(e){ console.error('Join did not finish. Your local key was retained. Inspect the peer list for public.key before retrying.'); throw e; }