Secure connections with AutoPass invites, HMAC capabilities, and viewer default.
Release rolling / release (push) Successful in 12m24s
Release rolling / release (push) Successful in 12m24s
Default peers are read-only; admin requires seed proof and operators redeem AutoPass packages with signed grants. ACL UI and docs match the new trust model.
This commit is contained in:
+24
-3
@@ -8,6 +8,7 @@ import DHT from 'hyperdht'
|
||||
import b4a from 'b4a'
|
||||
import gracefulGoodbye from 'graceful-goodbye'
|
||||
import { loadOrCreateKeyPair } from './core/keys.js'
|
||||
import { initAuthKeys } from './core/auth-keys.js'
|
||||
import { peers } from './core/peer-registry.js'
|
||||
import { PeerSession } from './rpc/session.js'
|
||||
import { registerAllHandlers, cleanupSession } from './rpc/register.js'
|
||||
@@ -15,6 +16,8 @@ import { startDockerEventStream, stopDockerEventStream } from './services/events
|
||||
import { startStatsBroadcast, stopStatsBroadcast } from './services/stats.js'
|
||||
import { isPeerRevoked } from './core/peer-policy.js'
|
||||
import { recordPeerConnect, recordPeerDisconnect } from './services/metrics.js'
|
||||
import { isInsecureOpenAdmin } from '../shared/crypto-auth.js'
|
||||
import { closeAutopassVault } from './core/autopass-vault.js'
|
||||
import {
|
||||
closeAllTunnels,
|
||||
isHolesailEnabled,
|
||||
@@ -30,16 +33,24 @@ import { isPluginsEnabled } from './handlers/plugins.js'
|
||||
const bootStarted = Date.now()
|
||||
const log = logger.child('server')
|
||||
|
||||
/** @type {{ keyPair: any, publicKeyHex: string }} */
|
||||
/** @type {{ keyPair: any, publicKeyHex: string, seedHex: string }} */
|
||||
let keyPair
|
||||
let publicKeyHex
|
||||
let seedHex
|
||||
try {
|
||||
;({ keyPair, publicKeyHex } = loadOrCreateKeyPair())
|
||||
;({ keyPair, publicKeyHex, seedHex } = loadOrCreateKeyPair())
|
||||
initAuthKeys({ seedHex, publicKeyHex })
|
||||
} catch (err) {
|
||||
log.error('Failed to load server keypair', { error: err.message })
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
if (isInsecureOpenAdmin()) {
|
||||
log.warn(
|
||||
'PEARDOCK_INSECURE_OPEN_ADMIN=1 — every peer is admin. Disable for production multi-operator use.'
|
||||
)
|
||||
}
|
||||
|
||||
const dht = new DHT()
|
||||
const server = dht.createServer()
|
||||
|
||||
@@ -112,9 +123,12 @@ const bootMs = Date.now() - bootStarted
|
||||
logger.banner([
|
||||
'peardock server ready',
|
||||
'',
|
||||
'Public key (paste into the Pear client):',
|
||||
'Public key (viewer / read-only by default):',
|
||||
publicKeyHex,
|
||||
'',
|
||||
'Admin: paste public key + SERVER_SEED in the client.',
|
||||
'Operators: create an AutoPass invite from Access (never share SERVER_SEED).',
|
||||
'',
|
||||
`Docker: ${dockerStatus.ok ? `ok · API ${dockerStatus.apiVersion || '?'} · ${dockerStatus.os || '?'}` : `unavailable · ${dockerStatus.error || 'socket error'}`}`,
|
||||
`Holesail: ${
|
||||
!isHolesailEnabled()
|
||||
@@ -123,6 +137,7 @@ logger.banner([
|
||||
? `on · max ${hs.max} tunnels`
|
||||
: `on but package missing${hs?.loadError ? ` · ${String(hs.loadError).slice(0, 80)}` : ''}`
|
||||
}`,
|
||||
`Auth: HMAC capabilities · default role viewer${isInsecureOpenAdmin() ? ' · INSECURE OPEN ADMIN' : ''}`,
|
||||
`Swarm RPC: ${isSwarmEnabled() ? 'on' : 'off'} · Plugins: ${isPluginsEnabled() ? 'on' : 'off'}`,
|
||||
`Log: ${logger.format} · level ${['error', 'warn', 'info', 'debug'][logger.level] || 'info'}`,
|
||||
`Boot ${bootMs}ms · pid ${process.pid} · Node ${process.version}`,
|
||||
@@ -180,6 +195,12 @@ async function shutdown(signal = 'shutdown') {
|
||||
|
||||
peers.clear()
|
||||
|
||||
try {
|
||||
await closeAutopassVault()
|
||||
} catch (err) {
|
||||
log.debug('autopass.close', { error: err.message })
|
||||
}
|
||||
|
||||
try {
|
||||
await server.close()
|
||||
} catch (err) {
|
||||
|
||||
Reference in New Issue
Block a user