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:
@@ -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 client’s 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).
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user