Complete roadmap optionals: Holesail, Swarm UI, GitOps, virtualization.
CI / test (push) Successful in 9m58s

Add tunnel persistence and container one-click tunnels with local
Holesail client bind, Swarm services/nodes/tasks view, GitOps stack
sync from git, deploy wizard step chrome, virtualized container lists,
and structure regression tests. Mark Tracks A–D and optional future done.
This commit is contained in:
2026-07-10 22:53:30 -04:00
parent 573298b836
commit 02f25e0981
26 changed files with 2458 additions and 121 deletions
+84
View File
@@ -0,0 +1,84 @@
# Holesail integration
[Holesail](https://github.com/holesail/holesail) is a peer-to-peer **TCP/UDP reverse proxy** on HyperDHT. peardock uses HyperDHT + protomux-rpc for the **Docker control plane**; Holesail is integrated **beside** that path so operators can share **published ports / local services** via `hs://` keys without opening firewall ports.
## Architecture (do not conflate the two planes)
| Plane | Technology | Purpose |
|-------|------------|---------|
| **Control** | HyperDHT + protomux-rpc | peardock RPC: containers, deploy, logs, ACL |
| **Data / tunnels** | Holesail (`holesail` package) | L4 proxy of `host:port` ↔ remote peer via `hs://` |
```
[Pear client] --protomux-rpc / HyperDHT--> [peardock server] --dockerode--> dockerd
|
+-- HolesailServer instances (per tunnel)
|
pipes to 127.0.0.1:<published-port>
|
[remote user] --holesail client--> local bind --P2P--> that tunnel
```
**Why not replace peardock RPC with Holesail?**
Holesail is not an RPC framework. It tunnels bytes between TCP/UDP sockets. peardock needs structured methods, roles, audit, and pushes (stats, logs). Keep both.
## Enable
```bash
# on the peardock server host
export ENABLE_HOLESAIL=1
npm run server
```
Optional env:
| Variable | Default | Meaning |
|----------|---------|---------|
| `ENABLE_HOLESAIL` | off | Must be `1` / `true` |
| `PEARDOCK_MAX_TUNNELS` | `20` | Concurrent tunnel cap |
| `PEARDOCK_TUNNEL_HOSTS` | `127.0.0.1,localhost,::1,0.0.0.0` | Allowed tunnel targets (SSRF guard) |
## RPC
| Method | Role | Description |
|--------|------|-------------|
| `getHolesailStatus` | viewer | Feature flag + availability |
| `listTunnels` | viewer | Active tunnels (+ `hs://` URLs) |
| `getTunnel` | viewer | One tunnel by id |
| `createTunnel` | operator | Start tunnel (`host`/`port` or `containerId`+`containerPort`) |
| `closeTunnel` | operator | Stop tunnel |
`createTunnel` always uses **secure** mode by default (`secure: true`) so the DHT capability is not the raw listen key.
## UI
Sidebar → **Tunnels**: create by host/port, list active tunnels, copy `hs://` URL, close.
Remote connect (outside peardock):
```bash
npx holesail 'hs://s000…'
# then open http://127.0.0.1:<bound-port>
```
## License note
`holesail` is **AGPL-3.0**. peardock remains Apache-2.0; enabling Holesail adds an AGPL dependency for servers that set `ENABLE_HOLESAIL=1`. Operators distributing a combined binary should review AGPL obligations. See `docs/SBOM.md`.
## Security
- Treat `hs://` URLs as **secrets** (capability to reach the service).
- Default targets are loopback / published Docker binds only.
- Create/close are audited when `PEARDOCK_AUDIT` is on.
- Max tunnel count limits resource exhaustion.
- Do **not** reuse peardocks `SERVER_SEED` for tunnel keypairs — each tunnel gets its own Holesail seed.
## Implemented extensions
1. **Container UI action** — “Tunnel this port” on container details port table.
2. **Client-side HolesailClient** — Pear binds a local port and opens the browser (`client/holesailLocal.js`, Tunnels → plug icon).
3. **Persist tunnel definitions**`peardock-tunnels.json` (mode 600); restored on server boot with the same `hs://` keys when possible.
## Optional later
- QR codes in the Tunnels view for mobile Holesail Go.
+3
View File
@@ -61,6 +61,9 @@ Vault file: `peardock-vault.json` (mode 600). Override path with `PEARDOCK_VAULT
|-----|--------|
| `ENABLE_SWARM=1` | Swarm / services / secrets / configs RPC |
| `ENABLE_PLUGINS=1` | Plugin install/enable/remove |
| `ENABLE_HOLESAIL=1` | Holesail P2P port tunnels (`hs://` keys) — see [HOLESAIL.md](./HOLESAIL.md) |
| `PEARDOCK_MAX_TUNNELS` | Max concurrent Holesail tunnels (default 20) |
| `PEARDOCK_TUNNEL_HOSTS` | Extra allowed tunnel target hosts (comma-separated) |
| `PEARDOCK_UNRESTRICTED_CLI=1` | Broader `docker` CLI for **admin** |
| `PEARDOCK_BROWSE_OPEN=1` | Legacy open host FS browse (discouraged) |
+2 -1
View File
@@ -27,6 +27,7 @@ See `package.json` / `package-lock.json`. Major surface:
| graceful-goodbye | Shutdown |
| hypercore-crypto | Key material |
| pear-electron / pear-bridge | Desktop shell |
| holesail | Optional P2P TCP/UDP tunnels (`ENABLE_HOLESAIL=1`) — **AGPL-3.0** |
## Known-sensitive native deps
@@ -34,4 +35,4 @@ See `package.json` / `package-lock.json`. Major surface:
## License
Apache-2.0 (project). Review transitive licenses before redistribution.
Apache-2.0 (project). Optional Holesail integration pulls **AGPL-3.0** (`holesail` / `holesail-server` / `holesail-client`). Review transitive licenses before redistribution; servers that enable tunnels should document AGPL obligations.
+3 -1
View File
@@ -31,6 +31,7 @@
- **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`.
- **Holesail tunnels** are off unless `ENABLE_HOLESAIL=1` — each `hs://` URL is a capability to the target port.
- **Host FS browse** is **default-deny** unless `PEARDOCK_BROWSE_ROOTS` or `PEARDOCK_BROWSE_OPEN=1`.
---
@@ -56,7 +57,8 @@
| 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` |
| Feature gates | `ENABLE_SWARM`, `ENABLE_PLUGINS`, `ENABLE_HOLESAIL`, `PEARDOCK_UNRESTRICTED_CLI` |
| Tunnel targets | Loopback / allowlisted hosts only (`PEARDOCK_TUNNEL_HOSTS`) |
---