Concepts
What PowerCloud is and the ideas every other page builds on - trusted and untrusted nodes, the cluster and its storage locations, the passphrase and recovery key, the cluster CA, nodes, pcctl, the mesh and apps - with a glossary.
PowerCloud is an operating system for running your own cloud on machines you own, rented servers and VMs on any public cloud, all at once. Data is encrypted before it leaves a machine you trust, so storage providers and plain cloud VMs only ever hold ciphertext, and it is spread over several providers so that no single one can read it, change it unnoticed, or take it away. This page explains the parts of a PowerCloud cluster and the words the rest of the documentation uses.
What PowerCloud is
PowerCloud OS is a minimal, hardened Linux kernel with a userland written entirely in Go, for x86-64 (amd64) and arm64 machines.
- No shell, no SSH, no login. The userland is a handful of static Go binaries:
pcinit(PID 1, which starts and supervises services) andpcd(the node daemon). There is no package manager and no way to log in. - Managed only through an API. Everything is done with the
pcctlcommand-line tool on your own computer, which talks to nodes over mutually authenticated TLS. - One image file. The kernel, its initramfs and a fixed kernel command line are a single EFI application that UEFI firmware boots directly, with no boot loader. Nobody at the console or at the cloud provider can change the command line, and one signature covers the whole OS for Secure Boot.
- Hardened kernel. Loadable modules are disabled entirely and kernel lockdown is forced to confidentiality mode.
PowerCloud has two halves that you can use separately: an encrypted, replicated object store you drive from pcctl alone, and nodes that run the OS, join a mesh, hold storage and run apps.
Trusted and untrusted
Every place your data touches is either trusted or untrusted.
| Examples | What it may do | |
|---|---|---|
| Trusted node | Your own hardware (home server, colo machine), or a confidential VM (AMD SEV-SNP) that passed attestation | Holds keys, decrypts data, runs apps |
| Untrusted location or node | An S3 bucket, a plain cloud VM | Stores and relays ciphertext only |
The reason is the threat model: on someone else's ordinary VM, the host can read the VM's memory, and with it any key the VM holds. Only a confidential VM, whose memory the CPU encrypts, closes that gap; PowerCloud verifies AMD SEV-SNP attestation before it gives such a VM a key (Intel TDX and Arm CCA are not supported yet). See Security model for the full threat model and Unlocking nodes after a reboot for attested unlock.
The cluster
A cluster is one set of keys, one store and the nodes enrolled in it.
Storage locations: the repository
The cluster's data lives in an encrypted store spread over storage locations. Together they are called the repository, given to pcctl with --repo as a comma-separated list:
pcctl --repo '/srv/pc,s3://my-bucket/pc?region=us-east-2,node://home-1' ls
A location is a local directory, an S3-compatible bucket (AWS S3, Cloudflare R2, Backblaze B2, Wasabi, MinIO and others), the encrypted disk of one of your nodes (node://NAME), or an erasure-coded set of several of these (ec:K:LOC;LOC;...). You can mix them freely. Instead of typing --repo every time, you can set the POWERCLOUD_REPO environment variable to the same list.
- Everything is encrypted on your machine first. Files are split into 4 MiB chunks, each sealed with XChaCha20-Poly1305. Names, sizes and chunk lists are in encrypted manifests, so a provider sees neither file names nor contents.
- Each write goes to several locations. A write must reach a quorum of locations (by default a majority) to succeed. Reads fall back to any location that has the data, so losing one provider loses nothing.
pcctl check,repairandgccompare the locations, bring one that was down (or newly added) up to date, and reclaim chunks nothing uses any more.
Storage covers locations, quorum, erasure coding and repair in detail.
The passphrase and the recovery key
The cluster has one random 256-bit root key, which is never stored in plaintext. It is wrapped, in the style of LUKS keyslots, in a small key header stored at every location:
- a passphrase slot (at least 12 characters; stretched with Argon2id), which you choose at
pcctl init - a recovery key slot:
pcctl initprints a 160-bit recovery key once. Write it down and store it offline. It opens the cluster on its own, if the passphrase is forgotten.
Every other key is derived from the root key for its purpose: the store's encryption keys, the cluster CA, the keys for each node's disk. So whoever has the passphrase or the recovery key, plus a copy of the header from any location, holds the whole cluster. If either leaks, pcctl rotate replaces the root key and re-encrypts the store (see Admins, keys and revocation).
There is no backdoor. If every passphrase and the recovery key are lost, the data cannot be recovered by anyone.
pcctl reads the passphrase from the terminal, or from POWERCLOUD_PASSPHRASE for scripts. To unlock with the recovery key instead, set POWERCLOUD_RECOVERY_KEY.
The cluster CA
Nodes and admins prove who they are with certificates from the cluster CA. Its Ed25519 key is derived from the root key and is never stored anywhere, so anyone who can unlock the cluster can issue certificates, and nobody else can, including a provider holding every blob.
The CA signs everything nodes accept from admins: node and admin certificates, the membership list, the revocation list, releases, cluster apps and the consensus founding document. Nodes check the CA's signature, so these documents can be passed from node to node safely.
Nodes and pcd
A node is a machine (physical or virtual) running PowerCloud OS. Its daemon, pcd, holds the node's identity and serves the node API on TCP port 7443.
- Identity. On first start,
pcdgenerates an Ed25519 key. The node ID is a hash of that key (shown as 16 hex digits, such asfa8adc53910a6a79). - Enrollment. A new node prints a one-time enrollment code on its console.
pcctl node enrolluses it to check it is talking to that exact node and to prove you read the console, then gives the node a certificate from the cluster CA. Alternatively, a node can be issued its identity ahead of time as a join bundle and join with nobody at its console. See Enroll a node. - After enrollment the node accepts only clients with a certificate from its cluster CA, and checks each certificate's role:
admin(you) ornode(its peers). Node certificates last a year and are renewed withpcctl node renew. - Encrypted state volume. A node keeps its identity and state on an encrypted partition of its disk (dm-crypt, with an HMAC-SHA256 tag on every sector, so a disk changed while the node is off reads as an error rather than as altered data). The key for it can only be derived by someone who can unlock the cluster. After a reboot, the node stays locked until an admin runs
pcctl node unlock, unless TPM unlock or peer unlock is on; see Unlocking nodes after a reboot. - The registry. Every enrolled node is recorded in the cluster's encrypted store, so every admin of the cluster sees the same nodes, their addresses and their disk volume IDs.
See Managing nodes for managing nodes day to day.
pcctl and admin certificates
pcctl is the only management tool. It runs on Linux and macOS (amd64 and arm64); there is no Windows build.
Commands come in two kinds:
- Commands that need the cluster keys take
--repo(or--via NODE, below) and ask for the passphrase:init,put,get,node enroll,node unlock,node rm,rotateand others. - Day-to-day commands need only your admin certificate:
pcctl status,pcctl node info NAME,pcctl node reboot NAME,pcctl app ...,pcctl console.
An admin certificate lasts 30 days. pcctl --repo ... login issues one, and any command that unlocks the cluster renews it by itself when a week or less is left. It is kept, with the CA certificate and the list of nodes this machine knows (nodes.json), in the configuration directory: $POWERCLOUD_CONFIG if set, otherwise ~/.config/powercloud on Linux or ~/Library/Application Support/powercloud on macOS. pcctl revoke-admins revokes every admin certificate at once, for example after losing a laptop.
Once a node serves the storage (pcctl node storage), --via NODE can replace --repo: the node holds the storage locations and their credentials and relays encrypted blobs, so your laptop needs only the passphrase and its admin certificate. The node never gets the keys. init, check, repair, gc and rotate still need --repo.
pcctl command reference is the full command reference.
The mesh
Enrolled nodes connect to each other over an encrypted mesh of kernel WireGuard tunnels, on UDP port 51820.
- Addresses come from identity. Each node's mesh address is a private IPv6 address made from the cluster ID and the node ID, so there is nothing to allocate.
- Peers are distributed automatically. A membership list, signed by the cluster CA, names every node with its WireGuard key and endpoint (the public
IP:PORTwhere peers can reach it).pcctlpublishes a new list whenever a node is added or removed, and nodes pass newer lists on to each other, so a node that was offline catches up from any peer. - NAT traversal. Nodes behind NAT find each other's public address through a node both can reach and connect directly. When their NATs prevent that (symmetric NAT), they connect through a relay: a public node that forwards their WireGuard packets, which it cannot read.
- Authenticated twice. Inside the tunnel, nodes still call each other's API with their node certificates.
pcctl node info NAME shows each peer's handshake age and whether its API answers over the mesh.
Apps
Nodes run services you deploy, called apps: static Linux binaries or container images from a registry.
- Apps on one node (
pcctl app deploy NODE NAME ...): each runs in a sandbox (chrooted on the node's encrypted disk, as its own user, in its own namespaces and cgroup with memory, CPU and process limits, under a seccomp filter, with its own network reached only through ports it publishes), and is restarted when it exits. With--vm, an app runs in a microVM with a kernel of its own. See Apps on a node. - Cluster apps (
pcctl --repo ... cluster app deploy ...): you publish the app for the whole cluster, and the nodes decide among themselves where it runs, starting it elsewhere when a node goes away. See Cluster apps.
Consensus
For state the nodes must agree on themselves, such as which node runs an exclusive app or the marks that detect a provider rolling back an object, the nodes form a Raft group: pcctl --repo ... consensus init, once. It keeps working while a majority of its voters are up. See Cluster apps and Storage.
Glossary
| Term | Meaning |
|---|---|
| Admin certificate | A 30-day client certificate from the cluster CA, kept in pcctl's configuration directory, that lets you manage nodes without the passphrase. |
| Attestation | A report signed by the CPU (AMD SEV-SNP) proving a VM's memory is encrypted; pcctl checks it before giving such a node its disk key. |
| Cluster | One root key, the store it encrypts, and the nodes enrolled with its CA. |
| Cluster app | An app published for the whole cluster, which the nodes place and move among themselves. |
| Cluster CA | The certificate authority whose key is derived from the root key; it signs node and admin certificates and every document nodes accept. |
| Consensus | The nodes' Raft group, which keeps a key-value state they agree on while a majority is up. |
| Endpoint | Where peers reach a node's WireGuard port, as IP:PORT or HOST:PORT. |
| Enrollment code | The one-time code a new node shows on its console: a fingerprint of its key plus a secret, used by pcctl node enroll. |
| Join bundle | A file from pcctl node provision holding a node's whole identity, given to a machine as cloud user data or a QEMU fw_cfg file so it joins unattended. |
| Key header | The one unencrypted blob at each location: the keyslots that wrap the root key, holding no plaintext key. |
| Location | One place the store is kept: a directory, an S3-compatible bucket, a node's disk (node://NAME) or an erasure-coded set (ec:K:...). |
| Membership list | The CA-signed list of nodes with their WireGuard keys and endpoints, passed between nodes. |
| Mesh | The WireGuard network between a cluster's nodes, with addresses derived from node identity. |
| MicroVM | A small virtual machine with its own kernel that an app can run in (--vm), for a stronger boundary than the shared-kernel sandbox. |
| Node | A machine running PowerCloud OS, enrolled in a cluster. |
| Node API | The mutual-TLS API pcd serves on TCP 7443, used by pcctl and by peers. |
| pcctl | The command-line tool that manages a cluster from your own computer. |
| pcd | The node daemon: identity, enrollment, unlock, mesh, storage and apps. |
| Quorum | How many locations must accept a write for it to succeed; by default a majority (--quorum N overrides it). |
| Recovery key | A 160-bit key printed once at pcctl init (and at pcctl rotate) that unlocks the cluster without the passphrase. |
| Registry | The cluster's record of its nodes, kept in the encrypted store. |
| Relay | A public node that forwards WireGuard packets between two nodes whose NATs block a direct connection; it sees only ciphertext. |
| Release | A CA-signed set of node images that nodes roll out themselves, one at a time; a PowerCloud release is also the set of downloadable files named vYYYY.MM.DD. See Upgrades and releases. |
| Repository | All of a cluster's storage locations together, given with --repo or POWERCLOUD_REPO. |
| Revocation list | The CA-signed list of removed nodes and revoked admin certificates, enforced by every node. |
| Root key | The cluster's 256-bit master key, from which every other key is derived; never stored in plaintext. |
| State volume | The encrypted, integrity-checked partition where a node keeps its identity and state; locked after each reboot until unlocked. |
| Trusted node | A node that may hold keys and run apps: your own hardware or an attested confidential VM. |
| Unlock code | The code a locked node shows on its console after a reboot, used by pcctl node unlock. |
| Untrusted | A bucket or plain VM that may only store or relay ciphertext. |