178 lines
6.9 KiB
HTML
178 lines
6.9 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
|
<title>Architecture · PearDock Docs</title>
|
|
<meta name="description" content="PearDock architecture: HyperDHT, protomux-rpc, handlers, Holesail data plane." />
|
|
<meta name="theme-color" content="#2dd4bf" />
|
|
<link rel="icon" href="/assets/favicons/favicon.ico" sizes="any" />
|
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
|
|
<link rel="stylesheet" href="/src/styles/global.css" />
|
|
<link rel="stylesheet" href="/src/styles/docs.css" />
|
|
</head>
|
|
<body>
|
|
<div class="bg-mesh" aria-hidden="true"></div>
|
|
<div data-nav data-prefix="../"></div>
|
|
|
|
<div class="docs-layout">
|
|
<aside class="docs-sidebar" data-docs-nav data-prefix="../"></aside>
|
|
<button type="button" class="docs-sidebar-toggle" aria-label="Docs menu">☰</button>
|
|
|
|
<article class="docs-main">
|
|
<h1>Architecture</h1>
|
|
<p class="docs-lead">How PearDock is structured: control plane, data plane, repository layout, and RPC model. All peer-to-peer, with no open ports required for remote Docker ops.</p>
|
|
|
|
<h2>High-level</h2>
|
|
<p>Control plane (Docker RPC) and optional data plane (Holesail port tunnels) stay separate:</p>
|
|
<pre class="mermaid">
|
|
flowchart LR
|
|
subgraph Client["Desktop client"]
|
|
UI[PearDock UI]
|
|
end
|
|
subgraph Server["peardock server"]
|
|
RPC[protomux-rpc handlers]
|
|
HS[HolesailServer tunnels]
|
|
D[dockerode]
|
|
end
|
|
UI -- "HyperDHT · Noise · protomux-rpc" --> RPC
|
|
RPC --> D
|
|
D --> DE[dockerd]
|
|
HS -. "hs:// per published port" .-> Port["127.0.0.1:hostPort"]
|
|
Remote[Remote user / peer] -- "Holesail client" --> HS
|
|
</pre>
|
|
|
|
<h3>Planes</h3>
|
|
<pre class="mermaid">
|
|
flowchart TB
|
|
subgraph Control["Control plane"]
|
|
C1[HyperDHT keypair]
|
|
C2[protomux-rpc methods]
|
|
C3[ACL · audit · stats pushes]
|
|
end
|
|
subgraph Data["Data plane · optional"]
|
|
D1[Holesail L4 proxy]
|
|
D2["hs:// capability URLs"]
|
|
end
|
|
Control --> Docker[Docker Engine API]
|
|
Data --> Ports[Host published ports]
|
|
</pre>
|
|
|
|
<div class="table-wrap">
|
|
<table>
|
|
<thead>
|
|
<tr><th>Plane</th><th>Technology</th><th>Purpose</th></tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td><strong>Control</strong></td>
|
|
<td>HyperDHT + protomux-rpc</td>
|
|
<td>Docker RPC: containers, deploy, logs, ACL, stats pushes</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Data / tunnels</strong></td>
|
|
<td>Holesail</td>
|
|
<td>L4 proxy of host:port ↔ remote peer via hs://</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="callout info">
|
|
<div class="callout-icon">i</div>
|
|
<div class="callout-body">
|
|
<strong>Why not replace RPC with Holesail?</strong>
|
|
Holesail tunnels bytes between sockets. PearDock needs structured methods, roles, audit, and pushes (stats, logs, terminal). Keep both.
|
|
</div>
|
|
</div>
|
|
|
|
<h2>Repository layout</h2>
|
|
<pre><code>shared/ Protocol constants + encodings (both sides)
|
|
server/
|
|
server.js Entry: HyperDHT listen
|
|
core/ Keys, peer registry, ACL, audit, vault
|
|
rpc/ PeerSession, handler registration
|
|
handlers/ Domain methods (containers, images, volumes, …)
|
|
services/ Docker client, stats, events, Holesail, schedules
|
|
utils/ Validation, rate limit, logging, compose, GitOps
|
|
client/
|
|
connection.js Single HyperDHT + protomux-rpc link
|
|
manager.js Multi-server connections + persistence
|
|
api.js Typed RPC helpers
|
|
app.js + libs/ Desktop UI
|
|
electron/ Electron shell + OTA + GUI bundle
|
|
assets/ Logos + favicons
|
|
build/icon.* Package icons
|
|
peardock-branding/ Master brand package</code></pre>
|
|
|
|
<h2>RPC model</h2>
|
|
<pre class="mermaid">
|
|
sequenceDiagram
|
|
participant C as Client
|
|
participant S as Server
|
|
participant D as dockerd
|
|
C->>S: handshake / ping
|
|
S-->>C: role · protocol version
|
|
C->>S: listContainers / deploy / …
|
|
S->>D: dockerode API
|
|
D-->>S: result
|
|
S-->>C: response
|
|
S-->>C: push:containers / push:allStats / …
|
|
</pre>
|
|
<p><strong>Client → server</strong> methods (examples):</p>
|
|
<ul>
|
|
<li><code>handshake</code>, <code>ping</code></li>
|
|
<li><code>listContainers</code>, <code>killContainer</code>, <code>containerTop</code>, <code>deployContainer</code>, <code>recreateContainer</code></li>
|
|
<li><code>pruneImages</code>, <code>getSystemDf</code>, <code>systemPrune</code></li>
|
|
<li><code>startTerminal</code>, <code>getContainerLogs</code></li>
|
|
<li><code>deployStack</code>, Swarm methods, vault, tunnels, schedules…</li>
|
|
</ul>
|
|
<p><strong>Server → client</strong> pushes:</p>
|
|
<ul>
|
|
<li><code>push:containers</code>, <code>push:allStats</code>, <code>push:logs</code></li>
|
|
<li><code>push:pullProgress</code>, <code>push:buildProgress</code></li>
|
|
<li><code>push:dockerEvent</code>, <code>push:terminalOutput</code></li>
|
|
</ul>
|
|
<p>Defined in <code>shared/protocol.js</code>. <code>PROTOCOL_VERSION</code> is negotiated on connect.</p>
|
|
|
|
<h2>Security surfaces</h2>
|
|
<ul>
|
|
<li>Noise transport (HyperDHT)</li>
|
|
<li>Roles: viewer / operator / admin + method ACL</li>
|
|
<li>Optional peer allowlist + invites</li>
|
|
<li>Rate limits per peer</li>
|
|
<li>Audit log for privileged methods</li>
|
|
<li>Registry vault AES-GCM (keyed from seed)</li>
|
|
<li>Browse roots default-deny</li>
|
|
</ul>
|
|
<p>See <a href="/docs/security">Security & threat model</a>.</p>
|
|
|
|
<h2>Breaking changes from v1</h2>
|
|
<div class="table-wrap">
|
|
<table>
|
|
<thead>
|
|
<tr><th>v1 (legacy)</th><th>v2 (current)</th></tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr><td>Hyperswarm topic = SERVER_KEY</td><td>HyperDHT listen on keypair from seed</td></tr>
|
|
<tr><td>Share topic hex with clients</td><td>Share <strong>public key</strong> with clients</td></tr>
|
|
<tr><td>Raw JSON on duplex streams</td><td>protomux-rpc methods + push channels</td></tr>
|
|
<tr><td>Monolithic server.js switch</td><td>Modular handlers under server/handlers/</td></tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="docs-pager">
|
|
<a href="/docs/quickstart"><span>Previous</span><strong>← Quick start</strong></a>
|
|
<a class="next" href="/docs/operator"><span>Next</span><strong>Operator guide →</strong></a>
|
|
</div>
|
|
</article>
|
|
</div>
|
|
|
|
<div data-footer data-prefix="../"></div>
|
|
<script type="module" src="/src/js/site.js"></script>
|
|
</body>
|
|
</html>
|