Complete production roadmap: vault, peers, swarm, streams, ops
CI / test (push) Successful in 9m54s

Ship remaining roadmap items: encrypted registry vault, peer invite/revoke,
Swarm/plugins behind flags, binary streams, engine create validation, deploy
rollback, schema validation, fleet/access UI, metrics, fuzz/load/soak tests,
systemd packaging, and release tooling. Mark ROADMAP fully complete.
This commit is contained in:
2026-07-10 20:50:55 -04:00
parent 0bb6ba1692
commit 0ee9b67834
56 changed files with 4430 additions and 376 deletions
+108
View File
@@ -0,0 +1,108 @@
# peardock operator guide
## Install (server host)
```bash
git clone <repo> /opt/peardock
cd /opt/peardock
npm ci --omit=dev
# Node.js ≥ 20
```
Create user and systemd unit:
```bash
useradd --system --home /opt/peardock --shell /usr/sbin/nologin peardock
usermod -aG docker peardock
cp deploy/peardock.service /etc/systemd/system/
systemctl daemon-reload
systemctl enable --now peardock
journalctl -u peardock -f
```
Copy the **public key** printed in logs into the Pear client.
## Healthcheck
```bash
node scripts/healthcheck.js
# exit 0 if Docker socket answers ping
```
## Multi-operator setup
1. On first boot, note your clients peer id (handshake returns `peerId`) or the key shown after connect.
2. `.env` example:
```bash
PEARDOCK_DEFAULT_ROLE=viewer
PEARDOCK_ADMIN_KEYS=<64-hex-client-public-key>
PEARDOCK_PEER_ALLOWLIST=1
PEARDOCK_BROWSE_ROOTS=/var/lib/docker/volumes
PEARDOCK_AUDIT=1
```
3. As admin, open **Access** in the UI → **Create invite** → send token to operator.
4. Operator connects with public key; paste invite token when supported, or admin registers their peer id.
5. **Revoke** lost devices from Access.
## Registry vault
Store credentials encrypted (AES-GCM derived from `SERVER_SEED`):
- UI: **Access → Registry vault**
- RPC: `vaultStoreCredential`, `vaultUseCredential`, `listVaultCredentials`
Vault file: `peardock-vault.json` (mode 600). Override path with `PEARDOCK_VAULT_PATH`.
## Feature flags
| Env | Effect |
|-----|--------|
| `ENABLE_SWARM=1` | Swarm / services / secrets / configs RPC |
| `ENABLE_PLUGINS=1` | Plugin install/enable/remove |
| `PEARDOCK_UNRESTRICTED_CLI=1` | Broader `docker` CLI for **admin** |
| `PEARDOCK_BROWSE_OPEN=1` | Legacy open host FS browse (discouraged) |
## Compose stacks
`deployStack` accepts:
- `composeContent` (required)
- `overrideContent` — second compose file
- `envFileContent` — written as `.env` for compose CLI
- `profiles` — array or comma string
- `build: true``docker compose up --build`
## Metrics
RPC `getMetrics` returns process memory, RPC counters, latency percentiles, feature flags.
## Client (Pear)
```bash
npm run dev # development
pear stage . && pear release .
```
## Certification / soak
```bash
npm run soak # 60s Docker health loop
npm run soak:24h # 24h certification (see docs/RELEASE.md)
```
## Releases
See `docs/RELEASE.md` for tarball checksums, GPG signing, and Pear stage/release.
## Backup
Back up atomically:
- `.env` (`SERVER_SEED`)
- `peardock-vault.json`
- `peardock-peers.json`
- `peardock-audit.log` (optional)
Rotating `SERVER_SEED` changes the public key; all clients must reconnect and vault must be re-keyed (re-store credentials).
+68
View File
@@ -0,0 +1,68 @@
# peardock release process
## Server tarball + checksums
```bash
chmod +x scripts/release-checksums.sh
./scripts/release-checksums.sh dist/
# Optional GPG:
GPG_KEY_ID=YOUR_KEY_ID ./scripts/release-checksums.sh dist/
```
Artifacts:
| File | Purpose |
|------|---------|
| `peardock-<ver>-<stamp>.tar.gz` | Source/runtime tree (no node_modules) |
| `*.sha256` | SHA-256 checksum |
| `*.asc` | Detached GPG signature (if keyed) |
Verify:
```bash
cd dist
sha256sum -c peardock-*.sha256
gpg --verify peardock-*.tar.gz.asc peardock-*.tar.gz # if signed
```
## Server install from release
```bash
tar -xzf peardock-*.tar.gz -C /opt/peardock
cd /opt/peardock && npm ci --omit=dev
cp deploy/peardock.service /etc/systemd/system/
systemctl enable --now peardock
```
## Pear desktop app
```bash
npm ci
pear stage .
pear release .
# Distribute pear:// link or channel per Pear docs
```
## Certification soak (24h)
```bash
# Terminal 1
npm run server
# Terminal 2 — 24 hours
SOAK_DURATION_MS=86400000 npm run soak
# or: node scripts/soak.js --hours 24
```
Exit 0 = Docker remained reachable within failure threshold.
## Load / fuzz in CI
Included in `npm test`:
- `test/load.test.js` — concurrent HyperDHT pings
- `test/fuzz.test.js` — schema/role fuzz
## Encoding profile
Handshake returns `schemaVersion` and features. Default encoding remains JSON (`shared/encodings.js`); binary bulk uses `binaryStream*` + `push:binaryChunk`. Hyperschema can replace JSON value encodings without renaming methods.
+37
View File
@@ -0,0 +1,37 @@
# Software bill of materials notes
peardock is a Node.js application. For production releases:
## Generate SBOM
```bash
# CycloneDX (requires @cyclonedx/cyclonedx-npm)
npx @cyclonedx/cyclonedx-npm --output-file peardock-sbom.json
# Or SPDX via syft if installed
# syft dir:. -o spdx-json > peardock-sbom.spdx.json
```
## Runtime dependencies (direct)
See `package.json` / `package-lock.json`. Major surface:
| Package | Role |
|---------|------|
| hyperdht | P2P transport |
| protomux / protomux-rpc | Multiplexed RPC |
| compact-encoding / b4a | Codecs |
| dockerode | Docker Engine API |
| js-yaml | Compose parse |
| dotenv | Config |
| graceful-goodbye | Shutdown |
| hypercore-crypto | Key material |
| pear-electron / pear-bridge | Desktop shell |
## Known-sensitive native deps
- `sodium-native` / `udx-native` (via hyperdht tree) — audit on upgrades
## License
Apache-2.0 (project). Review transitive licenses before redistribution.
+102
View File
@@ -0,0 +1,102 @@
# peardock threat model
**Audience:** operators deploying peardock in multi-operator or semi-trusted environments.
**Scope:** HyperDHT P2P control plane + local Docker Engine socket.
---
## 1. Assets
| Asset | Sensitivity |
|-------|-------------|
| `SERVER_SEED` | Critical — identity + vault key derivation |
| Docker socket access | Critical — full host container control |
| Registry passwords (vault) | High — encrypted at rest |
| Peer invite tokens | Medium — short-lived capability grants |
| Audit log | Medium — forensic integrity |
| Container data / env secrets | High — via inspect, logs, exec, archive |
---
## 2. Trust boundaries
```
[Pear client] --Noise/HyperDHT--> [peardock server] --unix socket--> [dockerd]
|
+-- peardock-vault.json (AES-GCM)
+-- peardock-peers.json
+-- peardock-audit.log
```
- **Anyone with the server public key** can *attempt* a DHT connection.
- **Default role is admin** unless `PEARDOCK_DEFAULT_ROLE` / `PEARDOCK_ADMIN_KEYS` / peer policy tighten it.
- **Swarm / plugins** are off unless `ENABLE_SWARM` / `ENABLE_PLUGINS`.
- **Host FS browse** is **default-deny** unless `PEARDOCK_BROWSE_ROOTS` or `PEARDOCK_BROWSE_OPEN=1`.
---
## 3. Adversaries
1. **Remote internet peer** with public key only — should not get Docker control if allowlist + non-admin default are set.
2. **Stolen invite token** — limited by TTL / max uses; should be rotated after use.
3. **Compromised client machine** — can use any role the peer holds until revoke.
4. **Local host attacker with filesystem** — can steal `SERVER_SEED` and vault if file perms wrong.
5. **Malicious container** — not in scope for peardock; Engine isolation applies.
---
## 4. Controls (implemented)
| Control | Mechanism |
|---------|-----------|
| Transport E2E | HyperDHT Noise |
| Capability ACL | `viewer` / `operator` / `admin` + `MethodRoles` |
| Peer policy | Invite, register, revoke, optional allowlist |
| Audit | Append-only log for privileged methods |
| Rate limit | Per-peer limiter on RPC |
| Registry secrets | AES-256-GCM vault (`registry-vault.js`) |
| Browse FS | Root allowlist / default deny |
| Feature gates | `ENABLE_SWARM`, `ENABLE_PLUGINS`, `PEARDOCK_UNRESTRICTED_CLI` |
---
## 5. Residual risks
- **Default admin** is intentional for single-operator setup — **must** change for multi-tenant.
- Binary image/export streams are size-capped but still large; DoS via memory if many concurrent transfers.
- JSON-over-RPC is not hyperschema-validated end-to-end; malformed args rely on handler validation.
- Swarm secrets/configs once enabled are highly privileged.
---
## 6. Operator hardening checklist
- [ ] Generate unique `SERVER_SEED`; back up offline; never commit `.env`
- [ ] Set `PEARDOCK_DEFAULT_ROLE=viewer` or `operator`
- [ ] Set `PEARDOCK_ADMIN_KEYS=<your client public key hex>`
- [ ] Enable `PEARDOCK_PEER_ALLOWLIST=1` after registering operators
- [ ] Set `PEARDOCK_BROWSE_ROOTS` only if host path pickers are needed
- [ ] Leave `ENABLE_SWARM` / `ENABLE_PLUGINS` off unless required
- [ ] File mode `600` on vault, peer policy, audit, `.env`
- [ ] Run server as non-root in `docker` group (see `deploy/peardock.service`)
- [ ] Review `peardock-audit.log` periodically
- [ ] Revoke lost client keys immediately (`revokePeer` / Access UI)
---
## 7. Pentest focus areas
1. RPC methods missing from `MethodRoles` (should default admin)
2. Invite race / reuse after expiry
3. Path traversal on `browseDirectory` / archive paths
4. Command injection on docker CLI allow-list bypass
5. Role escalation via handshake args (must be ignored)
6. Vault decryption with wrong seed / key rotation story
---
## 8. Explicit non-goals
- Multi-tenant hard isolation between Docker namespaces
- Replacing Docker authorization plugins
- Protecting against root on the Docker host