[{"data":1,"prerenderedAt":193},["ShallowReactive",2],{"docs-\u002Fdocs\u002Farchitecture":3,"docs-nav":186},{"id":4,"title":5,"body":6,"description":177,"extension":178,"meta":179,"navigation":180,"path":181,"section":182,"seo":183,"stem":184,"__hash__":185},"docs\u002Fdocs\u002F01.architecture.md","Architecture",{"type":7,"value":8,"toc":170},"minimark",[9,13,18,26,29,70,73,77,87,90,131,143,147,150,153,157,167],[10,11,12],"p",{},"dummie splits into a control plane you run once and a fleet of hosts that\nactually boot the sandboxes. Everything a user or an SDK talks to is the control\nplane; everything that touches virtualisation happens on a host.",[14,15,17],"h2",{"id":16},"the-control-plane","The control plane",[10,19,20,21,25],{},"A single Go binary, ",[22,23,24],"code",{},"control",". It is the whole deployment: the HTTP API, the web\nconsole, the OpenAPI document and both sets of database migrations are embedded\nin it, so there is no asset directory to ship alongside it and no static files\nto serve from somewhere else.",[10,27,28],{},"It owns:",[30,31,32,43,52,58,64],"ul",{},[33,34,35,39,40],"li",{},[36,37,38],"strong",{},"the API"," every client uses, at ",[22,41,42],{},"\u002Fapi\u002Fv1",[33,44,45,48,49],{},[36,46,47],{},"the console",", the web UI at ",[22,50,51],{},"console.\u003Cyour-domain>",[33,53,54,57],{},[36,55,56],{},"users, tokens and VM records",", in PostgreSQL",[33,59,60,63],{},[36,61,62],{},"event and telemetry history",", in ClickHouse",[33,65,66,69],{},[36,67,68],{},"user artifacts",", in an S3-compatible store",[10,71,72],{},"The control plane never runs a guest itself. It decides what should exist and\nhands that intent to a host.",[14,74,76],{"id":75},"the-hosts","The hosts",[10,78,79,80,83,84,86],{},"Each machine that boots sandboxes runs ",[22,81,82],{},"dclient",", a second binary from the same\nrepository. ",[22,85,82],{}," is the host's agent: it registers with the control plane,\nreceives the work assigned to it, and manages the local services that make a\nsandbox work.",[10,88,89],{},"Those services are:",[30,91,92,104,117,125],{},[33,93,94,99,100,103],{},[36,95,96],{},[22,97,98],{},"proxy"," — terminates the incoming connection for a guest and hands the\nfile descriptor off to ",[22,101,102],{},"dpipe",".",[33,105,106,110,111,113,114,116],{},[36,107,108],{},[22,109,102],{}," — holds that connection open. Because it owns the descriptor\nrather than ",[22,112,98],{},", a ",[22,115,98],{}," restart or crash does not drop a live session.",[33,118,119,124],{},[36,120,121],{},[22,122,123],{},"suricata"," — runs as a container, watching guest network traffic. Egress\npolicy is enforced per run, not per fleet.",[33,126,127,130],{},[36,128,129],{},"CoreDNS"," — resolves names for guests according to that same per-run policy.",[10,132,133,134,136,137,139,140,142],{},"The ",[22,135,98],{},"\u002F",[22,138,102],{}," split is the part worth understanding: connection lifetime is\ndeliberately decoupled from the lifetime of the process that accepted it, so\nshipping a new ",[22,141,98],{}," does not disconnect anybody.",[14,144,146],{"id":145},"the-microvms","The microVMs",[10,148,149],{},"A sandbox is a real microVM with its own kernel, not a container. The kernel is\nbuilt in-tree, stripped to what a short-lived guest needs, which is what makes\ncold boot fast enough to sit in a request path. Guest root filesystems come from\nordinary OCI images, exported to a rootfs at build time.",[10,151,152],{},"Hardware isolation is the whole point: a guest gets a full machine — its own\nkernel, filesystem, and network stack — so code you did not write and cannot\ntrust has nothing to escape into.",[14,154,156],{"id":155},"putting-it-together","Putting it together",[158,159,164],"pre",{"className":160,"code":162,"language":163},[161],"language-text","                        ┌──────────────────────────┐\n  browser \u002F SDK ──────► │  control  (Go binary)    │\n                        │  API + console + spec    │\n                        └────────────┬─────────────┘\n                                     │  assigns work\n                         ┌───────────┴───────────┐\n                         ▼                       ▼\n                 ┌───────────────┐       ┌───────────────┐\n                 │ QEMU host     │       │ QEMU host     │\n                 │  dclient      │       │  dclient      │\n                 │  proxy\u002Fdpipe  │       │  proxy\u002Fdpipe  │\n                 │  suricata     │       │  suricata     │\n                 │  ┌─────────┐  │       │  ┌─────────┐  │\n                 │  │ microVM │  │       │  │ microVM │  │\n                 │  └─────────┘  │       │  └─────────┘  │\n                 └───────────────┘       └───────────────┘\n","text",[22,165,162],{"__ignoreMap":166},"",[10,168,169],{},"The control plane is stateless with respect to guests — it records what should\nexist, and hosts reconcile toward it. A host that goes silent stops being given\nwork; the VMs it was running are reaped by their TTL.",{"title":166,"searchDepth":171,"depth":171,"links":172},2,[173,174,175,176],{"id":16,"depth":171,"text":17},{"id":75,"depth":171,"text":76},{"id":145,"depth":171,"text":146},{"id":155,"depth":171,"text":156},"How the control plane, the QEMU hosts and the microVMs fit together, and which process owns what.","md",{},true,"\u002Fdocs\u002Farchitecture","Concepts",{"title":5,"description":177},"docs\u002F01.architecture","JPeLuodZSmUL1Qzied3_kcBY6LY-WmPZ0jHb6UXhOts",[187,188],{"path":181,"title":5,"section":182,"stem":184},{"path":189,"title":190,"section":191,"stem":192},"\u002Fdocs\u002Fself-hosting","Self-hosting","Getting started","docs\u002F02.self-hosting",1787592506949]