265 lines
11 KiB
HTML
265 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 + encodings + schema + crypto-auth (both sides)
|
|
server/
|
|
server.js Entry: HyperDHT listen
|
|
core/ Keys, peer registry, ACL, audit, vault
|
|
rpc/ PeerSession, handler registration
|
|
handlers/ Domain methods (containers, images, registry, vault, stacks, …)
|
|
services/ Docker, stats, events, Holesail, schedules, image-updates, registry-client
|
|
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
|
|
jobs.js Job tray + hybrid pull progress helpers
|
|
templateResolve.js Portainer template / stack resolve
|
|
app.js + libs/ Desktop UI (deploy, registry, add-container, …)
|
|
electron/ Electron shell + OTA + GUI bundle
|
|
assets/ Logos + favicons
|
|
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>checkImageUpdates</code>, <code>deployContainer</code>, <code>recreateContainer</code></li>
|
|
<li><code>pullImage</code> / <code>pushImage</code> (optional vault credential), <code>pruneImages</code></li>
|
|
<li><code>deployStack</code>, registry catalog/tags/manifest, vault CRUD, Swarm, tunnels, schedules…</li>
|
|
<li><code>startTerminal</code>, <code>getContainerLogs</code></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:pushProgress</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 (currently <strong>3</strong> for HMAC auth).
|
|
Full catalog: <a href="/docs/api">RPC & API</a>.
|
|
</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) + remote Registry HTTP API V2 browser</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>
|