Stop silently dropping failed capabilities (which forced viewer), log handshake role/auth, and show each AutoPass invite with its linked capability on one Access card.
peardock
Decentralized Docker management on the modern Holepunch stack.
Share a public key. Manage containers, stacks, Swarm, logs, terminals, and tunnels over encrypted peer-to-peer connections. No central control plane, no VPN required, and no need to open inbound ports for Docker or the control UI.
| Layer | Technology |
|---|---|
| Transport | HyperDHT (Noise-encrypted P2P) |
| RPC | protomux-rpc + compact-encoding JSON |
| Server | Bare standalone binary or Node.js (dockerode) |
| Client | Electron desktop (preferred) or Pear dev shell |
| Port tunnels | Holesail (hs://, separate data plane) |
| License | AGPL-3.0 (same family as Holesail) |
Site and docs: peardock.boats · Source: git.ssh.surf/snxraven/peardock · Rolling binaries: releases
Quick start
One-line installer (recommended)
Interactive installer detects OS/arch, installs a Linux systemd server and/or a desktop client, and pulls artifacts from the rolling release:
curl -fsSL https://install.peardock.boats | bash
Non-interactive:
# Server (Linux → /opt/peardock + peardock.service + docker group)
curl -fsSL https://install.peardock.boats | bash -s -- --server --yes
# Desktop client (Linux or macOS)
curl -fsSL https://install.peardock.boats | bash -s -- --client --yes
# Both
curl -fsSL https://install.peardock.boats | bash -s -- --both --yes
After the server starts, copy the public key from the journal:
sudo journalctl -u peardock -n 80 --no-pager | grep -i 'public key'
# or: sudo systemctl status peardock
Open the desktop client → Add peer:
| Paste | Access |
|---|---|
| Public key only (64 hex) | Viewer (read-only) |
| Public key + SERVER_SEED | Admin (HMAC proof; seed never stored on disk) |
| AutoPass invite (from Access → Create invite) | Role granted by the invite — no seed sharing |
Clients use a stable DHT identity and auto-reconnect if the link drops.
More detail: docs/OPERATOR.md · peardock.boats/download · peardock.boats/docs/quickstart
Install from source
git clone https://git.ssh.surf/snxraven/peardock.git
cd peardock
npm install # Node.js ≥ 20
npm run server # control plane (needs Docker socket)
npm run start:client # Electron GUI (builds electron/app.bundle.cjs then launches)
You should see:
peardock server ready
Public key (viewer / read-only by default):
<64 hex characters>
Admin: paste public key + SERVER_SEED in the client.
Operators: create an AutoPass invite from Access (never share SERVER_SEED).
Identity is stored in .env (or /opt/peardock/.env for package installs):
| Variable | Meaning |
|---|---|
SERVER_SEED |
Secret 32-byte seed (admin only — never share with operators) |
SERVER_PUBLIC_KEY |
Derived public key (safe to share; alone = read-only) |
SERVER_KEY |
Legacy alias for the seed (still accepted) |
PEARDOCK_INSECURE_OPEN_ADMIN |
Set 1 only for single-operator dev (everyone is admin) |
Pear development shell (optional)
# macOS: ensure pear is on PATH
export PATH="$HOME/Library/Application Support/pear/bin:$PATH"
npm run dev
# or: pear run -d .
Pear may print DEPRECATED: pear run is deprecated (platform-wide). For day-to-day operators, prefer the Electron client from the rolling release or npm run start:client.
What you get
- Full Engine surface over P2P: containers, images, volumes, networks, compose stacks, logs, stats, terminals, prune, schedules, registry vault
- Docker Swarm UI and RPC (services, nodes, tasks, secrets, configs, scale). On by default; set
ENABLE_SWARM=0to disable - Holesail tunnels for published ports without firewall holes. On by default; set
ENABLE_HOLESAIL=0to disable. See docs/HOLESAIL.md - Roles:
viewer/operator/admin(default viewer; admin via seed proof or AutoPass invite) - Multi-peer fleet in one desktop client with reconnect and job tray
- Standalone binaries for six 64-bit hosts (server Bare + client Electron)
Architecture
shared/ Protocol constants + encodings (client + server)
server/
server.js Entry: HyperDHT listen
core/ Keys, peer registry, audit
rpc/ PeerSession (protomux-rpc), handler registration
handlers/ Domain methods (containers, swarm, tunnels, vault, …)
services/ Docker client, stats, metrics, event stream
utils/ Validation, rate limit, logging, compose
client/
connection.js Single HyperDHT + protomux-rpc link
manager.js Multi-server connections + persistence
api.js Typed RPC helpers
holesailLocal.js Local Holesail client (data plane)
electron/ Electron main / packaged desktop shell
ui/ + app.js + libs/ Desktop UI
assets/ Logos + favicons
peardock-branding/ Master brand package
deploy/ systemd unit
scripts/ install.sh, make, rolling release, healthcheck
Two planes (do not conflate)
| Plane | Technology | Purpose |
|---|---|---|
| Control | HyperDHT + protomux-rpc | Docker ops, ACL, logs, deploy, stats |
| Data / tunnels | Holesail | L4 proxy of host:port via hs:// |
RPC model
Client → server (examples): handshake, ping, listContainers, deployContainer, deployStack, startTerminal, scaleService, createTunnel, …
Server → client pushes: push:containers, push:allStats, push:logs, push:pullProgress, push:buildProgress, push:dockerEvent, push:terminalOutput, …
Defined in shared/protocol.js (PROTOCOL_VERSION negotiated on connect).
Deployment
- Host with Docker socket access for the service user (
peardockin groupdocker). - Process: installer Bare binary + systemd, or
node server/server.jsunder systemd/pm2. - Network: HyperDHT hole punching (UDP when possible). No need to expose Docker TCP or a public control port.
- Secrets: back up
SERVER_SEED. Rotating it changes the public key; clients must reconnect. - Client: rolling Electron package, or
npm run start:clientfrom source. - Security: Noise E2E, rate limits, roles, optional audit and peer allowlist. See docs/THREAT_MODEL.md.
- Feature flags (defaults): Swarm and Holesail on; plugins off. Opt out with
ENABLE_SWARM=0/ENABLE_HOLESAIL=0.
Canonical systemd unit: deploy/peardock.service (matches what install.sh writes).
[Unit]
Description=peardock HyperDHT Docker control plane
After=network-online.target
Wants=network-online.target
Wants=docker.service
[Service]
Type=simple
WorkingDirectory=/opt/peardock
ExecStart=/opt/peardock/peardock-server
Restart=on-failure
User=peardock
Group=docker
SupplementaryGroups=docker
Environment=NODE_ENV=production
EnvironmentFile=-/opt/peardock/.env
ReadWritePaths=/opt/peardock
[Install]
WantedBy=multi-user.target
Source-install alternative: ExecStart=/usr/bin/node /opt/peardock/server/server.js.
Standalone binaries
64-bit only: linux-x64, linux-arm64, darwin-x64, darwin-arm64, win32-x64, win32-arm64.
npm run make # all server + client hosts (same as CI)
npm run make:server:linux-x64
npm run make:client:darwin-arm64
# → out/peardock-server-<host>/ and out/peardock-<platform>-<arch>/
Gitea CI publishes tag rolling on every main build (secret RELEASE_TOKEN). See docs/RELEASE.md.
Asset patterns:
peardock-server-VERSION-HOST.tar.gz(+.sha256)peardock-client-VERSION-HOST.tar.gz(+.sha256; macOS includes a.app)
macOS clients from Linux CI are ad-hoc signed. If Gatekeeper blocks: right-click → Open, or xattr -cr ~/Applications/peardock.app. Re-sign: npm run sign:macos -- out/peardock-darwin-arm64/peardock.app.
Scripts
| Command | Description |
|---|---|
npm run server |
HyperDHT Docker control plane (Node) |
npm run start:client |
Build client bundle + Electron GUI |
npm run dev |
Pear desktop shell (dev) |
npm test |
Unit + integration tests (brittle) |
npm run healthcheck |
Docker socket health probe |
npm run soak / soak:24h |
Certification soak against Docker |
npm run make |
Cross-build all server + client hosts |
npm run make:server / make:client |
Server-only or client-only builds |
npm run sign:macos |
Ad-hoc / identity re-sign for .app |
npm run release:checksums |
Tarball + SHA-256 (+ optional GPG) |
npm run release:rolling |
Local dry-run helper for rolling publish |
Documentation
Full technical docs live under docs/ (architecture diagrams, protocol, codebase map, server/client deep dives).
| Doc | Contents |
|---|---|
| docs/README.md | Documentation hub + system overview |
| docs/ARCHITECTURE.md | Design, two planes, session lifecycle, mermaid charts |
| docs/CODEBASE-MAP.md | Directory and module map |
| docs/PROTOCOL.md | RPC methods, roles, pushes |
| docs/SERVER.md | Server internals |
| docs/CLIENT-UI.md | Client stack and desktop UI |
| docs/FEATURES.md | Feature catalog |
| docs/OPERATOR.md | Install, systemd, roles, vault, flags, logging, backup |
| docs/HOLESAIL.md | Control vs data plane, tunnel RPC, security |
| docs/THREAT_MODEL.md | Assets, trust boundaries, hardening checklist |
| docs/RELEASE.md | Host matrix, bare/Electron builds, rolling CI |
| docs/SBOM.md | SBOM generation, license notes |
| ROADMAP.md | Feature tracks and status |
| peardock.boats/docs | Public operator docs mirror |
Configuration (common env)
| Variable | Default / notes |
|---|---|
SERVER_SEED |
Generated on first start if missing |
PEARDOCK_DEFAULT_ROLE |
viewer (secure default; elevate via seed/AutoPass) |
PEARDOCK_ADMIN_KEYS |
Comma-separated client public keys treated as admin |
PEARDOCK_INSECURE_OPEN_ADMIN |
1 only for single-operator dev (everyone admin) |
PEARDOCK_PEER_ALLOWLIST |
1 to require registered peers |
PEARDOCK_AUDIT |
1 to append privileged actions to audit log |
PEARDOCK_BROWSE_ROOTS |
Allowed host paths for file browse |
ENABLE_SWARM |
On (1); set 0 to disable Swarm RPC |
ENABLE_HOLESAIL |
On (1); set 0 to disable tunnels |
ENABLE_PLUGINS |
Off unless 1 |
PEARDOCK_MAX_TUNNELS |
20 |
LOG_LEVEL / LOG_FORMAT |
info / json recommended under journald |
Full tables: docs/OPERATOR.md.
Breaking changes from v1
| v1 (legacy) | v2 (current) |
|---|---|
Hyperswarm topic = SERVER_KEY |
HyperDHT listen on keypair from seed |
| Share topic hex with clients | Share public key with clients |
| Raw JSON on duplex streams | protomux-rpc methods + push channels |
Monolithic server.js switch |
Modular handlers under server/handlers/ |
Clients and servers are not wire-compatible across major versions.
License
GNU Affero General Public License v3.0 (AGPL-3.0).
PearDock matches Holesail (also AGPL-3.0). If you modify PearDock and let others interact with it over a network, review AGPL source-offer obligations (AGPL §13). See docs/SBOM.md and peardock.boats/legal/license.
Owned and engineered by HoneyPeer, LLC (DeKalb County, Georgia, USA). Legal: [email protected].
