Files
peardock-website/docs/architecture.html
T
Raven Scott 28314838f7 Update site for .env keys and pd1 connection invites.
Quick start, operator, security, FAQ, download, home, and learn pages now
point operators at /opt/peardock/.env for public key and seed, and document
viewer / admin / pd1. invite roles.
2026-07-14 22:43:41 -04:00

260 lines
11 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="keywords" content="PearDock architecture, HyperDHT, protomux-rpc, Holesail" />
<meta name="author" content="HoneyPeer, LLC" />
<meta name="robots" content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1" />
<meta name="googlebot" content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1" />
<meta name="theme-color" content="#2dd4bf" />
<meta name="color-scheme" content="dark light" />
<meta name="application-name" content="PearDock" />
<meta name="apple-mobile-web-app-title" content="PearDock" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="mobile-web-app-capable" content="yes" />
<meta name="msapplication-TileColor" content="#2dd4bf" />
<meta name="msapplication-config" content="/assets/favicons/browserconfig.xml" />
<meta name="format-detection" content="telephone=no" />
<link rel="canonical" href="https://peardock.boats/docs/architecture" />
<link rel="alternate" hreflang="en" href="https://peardock.boats/docs/architecture" />
<link rel="alternate" hreflang="x-default" href="https://peardock.boats/docs/architecture" />
<!-- Open Graph -->
<meta property="og:type" content="article" />
<meta property="og:site_name" content="PearDock" />
<meta property="og:locale" content="en_US" />
<meta property="og:url" content="https://peardock.boats/docs/architecture" />
<meta property="og:title" content="Architecture · PearDock Docs" />
<meta property="og:description" content="PearDock architecture: HyperDHT, protomux-rpc, handlers, Holesail data plane." />
<meta property="og:image" content="https://peardock.boats/assets/brand/og-image.png" />
<meta property="og:image:secure_url" content="https://peardock.boats/assets/brand/og-image.png" />
<meta property="og:image:type" content="image/png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:image:alt" content="PearDock: decentralized Docker management on HyperDHT" />
<!-- Twitter / X -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="Architecture · PearDock Docs" />
<meta name="twitter:description" content="PearDock architecture: HyperDHT, protomux-rpc, handlers, Holesail data plane." />
<meta name="twitter:image" content="https://peardock.boats/assets/brand/twitter-card.png" />
<meta name="twitter:image:alt" content="PearDock: decentralized Docker management" />
<!-- Icons & PWA -->
<link rel="icon" href="/assets/favicons/favicon.ico" sizes="any" />
<link rel="icon" type="image/png" sizes="32x32" href="/assets/favicons/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/assets/favicons/favicon-16x16.png" />
<link rel="icon" type="image/png" sizes="48x48" href="/assets/favicons/favicon-48x48.png" />
<link rel="apple-touch-icon" sizes="180x180" href="/assets/favicons/apple-touch-icon.png" />
<link rel="manifest" href="/assets/favicons/site.webmanifest" />
<link rel="mask-icon" href="/assets/logo/peardock-wordmark.svg" color="#2dd4bf" />
<!-- Article -->
<meta property="article:section" content="Documentation" />
<meta property="article:author" content="HoneyPeer, LLC" />
<meta property="article:publisher" content="HoneyPeer, LLC" />
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": [
"WebPage",
"TechArticle"
],
"name": "Architecture \u00b7 PearDock Docs",
"description": "PearDock architecture: HyperDHT, protomux-rpc, handlers, Holesail data plane.",
"url": "https://peardock.boats/docs/architecture",
"isPartOf": {
"@type": "WebSite",
"name": "PearDock",
"url": "https://peardock.boats"
},
"publisher": {
"@type": "Organization",
"name": "HoneyPeer, LLC",
"url": "https://peardock.boats"
},
"inLanguage": "en-US",
"primaryImageOfPage": {
"@type": "ImageObject",
"url": "https://peardock.boats/assets/brand/og-image.png",
"width": 1200,
"height": 630
},
"headline": "Architecture \u00b7 PearDock Docs"
}
</script>
<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 (default) / operator / admin + method ACL</li>
<li>Elevate via <code>SERVER_SEED</code> proof or self-contained <code>pd1.</code> invites</li>
<li>Optional peer allowlist + revoke</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 &amp; 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>