// privatae-bastion — a single static binary that turns this machine into a bastion // into your Privatae network. No Docker, no Python, no separate WireGuard install. // // The tunnel runs in userspace (gVisor netstack) for the forward path, so `run` // needs no TUN device and no root. You pair with a short token from your host's // "Set up a bastion" action; the binary generates its OWN keys and pulls only its // cert + routing from your host. Distributed via npm / a plain binary. package main import ( "errors" "fmt" "os" "strings" ) func usage() { fmt.Fprintln(os.Stderr, `privatae-bastion — your bastion into your Privatae network. Usage: privatae-bastion pair enroll this machine with a token from your host's "Set up a bastion". Each pair ADDS a host — one daemon serves them all; pairing an already-paired host is refused (it would rotate its credentials) privatae-bastion pair - the same, with the token as the first line of standard input, so it is not in the process list or your shell history. Every form of pair below takes - in place of as well privatae-bastion pair --replace re-pair an already-paired host: rotates its credentials, keeps its local port, context store, and DCN state privatae-bastion pair --redeem-url unix:///run/privatae-host/enroll.sock pair with a Host on THIS machine that has no platform: the token is redeemed over that socket, the lanes go over the lane socket the Host names, and its CA is pinned for life privatae-bastion pair --redeem-url https://127.0.0.1:8810/v1/local/redeem --host-ca pair with a Host that has no platform and runs in a VM on this machine: the token is redeemed over TLS that trusts that CA alone (name host.cseries.internal), the lanes go to the lane port the Host names, and the CA is pinned for life. No coder runs over this pairing privatae-bastion pair the same pairing from the one code a Cloud Host's card gives: it carries the enroll address and the CA's fingerprint, and the CA is taken from the enroll port only under that fingerprint. On a local machine that already serves a Host, it asks here whether to add this one as well. Exit 3: already paired with this Host, nothing changed privatae-bastion run bring up the tunnel + lanes for EVERY paired host (a loopback control port per host for the verbs below: 127.0.0.1:7878, then 7879, …) privatae-bastion add-folder [--host ] [name] add a folder to your network — your files stay here; Privatae Host keeps only the index; you approve on your Host with your code. --host (a host name or unique prefix) is required when more than one host is paired privatae-bastion stepup-enroll [--host ] [--rotate] [--console-only] enroll a second factor ON THIS MACHINE: from then on your host can only reach a folder or move files here after you approve the request on this machine — the host never handles the code. --console-only: show the secret only on this console and keep it only in the system service's state (an installer's elevated step) privatae-bastion tray Windows, beside the system service: your icon and approvals window, as you; started at every sign-in sudo -H privatae-bastion claim-owner state who owns this machine. Root is required because there is no authority above the box to ask. The name travels to every host this machine serves and shows on its card there. Optional, and it grants nothing anywhere privatae-bastion unpair remove a pairing: tears its tunnel down and deletes the pairing (root on a networked bastion). Your context store and DCN state on this machine are left in place sudo -H privatae-bastion set-mode local (default): one host, non-root is fine, a second pair is refused. networked: a root-owned service serving several hosts, where every pairing after the anchor waits for the anchor host's approval. install.sh --networked sets it for you privatae-bastion service install|uninstall|status macOS and Windows: run this bastion as the system's own service (launchd as root; a Windows service as LocalSystem), so the machine's administrator, not the signed-in user, decides whether it runs. Needs machine authority. install.sh --networked / install.ps1 -Networked do it for you sudo -H privatae-bastion claim-anchor [--owner ] networked mode: redeem a token from YOUR host and make it the anchor — the one host that approves who else may pair here. Needs root; works on a box with no pairing or one pairing sudo -H privatae-bastion claim-anchor --rotate [--owner ] move the anchor to a DIFFERENT host. Needs root AND the current anchor's signed consent (anchor.consent.json), or 14 days without a heartbeat from it sudo -H privatae-bastion release-anchor --host (--host-ca | --force) the anchor host is gone (its data deleted): drop the anchor, unpair it and set its DCN state aside, so a new Host can be paired and anchored. Needs machine authority. --host-ca is the NEW Host's CA, refused when it is the one this box pinned (that Host is not gone); --force skips that check, at a terminal only privatae-bastion approvals-owner --sid [--replace] Windows, beside the system service: the one account whose tray may list and answer approvals. Machine authority; a different SID needs --replace, at an Administrator terminal only sudo -H privatae-bastion claim-anchor --repin same host, new name: re-sign anchor.json from the pairing this box already holds, after the host's own address changed. No token. Cannot move the anchor anywhere. privatae-bastion approvals [--host ] show what your host is asking to do on this machine, in plain words privatae-bastion approve [--host ] approve one request with a code from the authenticator enrolled here privatae-bastion deny [--host ] refuse one request privatae-bastion approvals drop [--host ] take back an approval this machine issued and has not used yet privatae-bastion grants drop [--host ] remove a folder grant held on this machine; the host is told privatae-bastion device-init make THIS machine your approval device: from then on a write a host asks of any machine you govern is approved with a tap here privatae-bastion device-approvals what your machines are asking you to approve, in their words privatae-bastion device-approve |all / device-deny sudo -H privatae-bastion pin-device on a machine you govern: accept approvals signed by your device (the key device-init printed). unpin-device withdraws it privatae-bastion ops [--host ] the ops your host wrote that this machine holds, and the standing op grants; ops drop takes one back sudo -H privatae-bastion root-exec grant [--host ] --for <30d> let the anchor host run commands AS ROOT here, one at a time, with no approval per command, until the time you choose. Asks for the code from the authenticator enrolled here. Every command is recorded here whole privatae-bastion root-exec [--host ] the root-command grant held here, if any; root-exec revoke takes it back privatae-bastion quarantine clear reopen a host's write lanes this machine closed after repeated refusals (5 in 10 minutes) sudo -H privatae-bastion switch on|off switch one capability family off for a host on this machine, or clear that refusal (the console page's switch). Off only removes reach; on grants nothing past the host's signed grant privatae-bastion switch --list every paired host's families, on or off, one per line privatae-bastion coders set [--max N] [--mem MB] [--cpus F] [--engines a,b|all] [--allow-lan h[:p],...] [--image-prefix |default] privatae-bastion coders on | off | drop [--host H] | status [--json] let your hosts run sealed coding runs on this machine (Linux, as root): how many at once, how big each is, which engines. Off by default; each run has no network but a proxy to the internet privatae-bastion git-setup print the git config lines that route git.privatae.ai through this bastion and your host privatae-bastion git-credential git's credential helper — fetches your forge token from your host on every git auth (git-setup resets the helper chain so no other helper caches it) privatae-bastion ui open the local UI in your browser — what this machine is doing, on this machine. Served by the running bastion on 127.0.0.1 and reachable from nowhere else privatae-bastion context choose what your files become on your network. Runs as you, so it shows exactly what you can already open, and asks your host before anything is added privatae-bastion status show every pairing + tunnel status privatae-bastion observe:baseline record what is NORMAL on this machine: every automated program, its user and a digest of the file it runs from. Administrator only. --force replaces an existing baseline privatae-bastion observe:baseline:show print the baseline this machine holds privatae-bastion observe:delta what is running here that the baseline does not hold: new programs, replaced binaries, new standing jobs, with the ordinary ones filtered out. Administrator only. --json for the full record including what was filtered privatae-bastion observe print what this machine would report about agents, automations and scheduled jobs on its next check-in (read-only, JSON) privatae-bastion backup key init | key show | reseal | requests | approve | deny | restore-plan | share | shares | unshare backups: make this bastion's backup key, and hand one backup's key to a host that restores it, when you approve. `+"`privatae-bastion backup`"+` lists the forms privatae-bastion version Your host reaches this machine only through lanes this bastion opens and gates itself. Nothing on this machine drives the host: there is no MCP endpoint here.`) } // takeHostFlag pulls `--host ` out of an argument list wherever it // sits, so `approvals drop --host X ` and `grants drop --host X` both // work — on a machine serving several hosts (most of the fleet) the flag is // not optional, and a parser that only saw it in one position refused the // command on exactly those machines. func takeHostFlag(args []string) (string, []string) { host := "" rest := make([]string, 0, len(args)) for i := 0; i < len(args); i++ { if args[i] == "--host" && i+1 < len(args) { host = args[i+1] i++ continue } rest = append(rest, args[i]) } return host, rest } const pairUsage = "usage: privatae-bastion pair [--replace] [--redeem-url unix:/// | --redeem-url https://:/ --host-ca ] | -\n" + " privatae-bastion pair | -\n" + " - reads the token or pairing code from standard input, so it stays out of the process list and shell history\n" + " exit status: 0 paired, 3 already paired with this Host (nothing changed), anything else a failure" // parsePairArgs reads `pair`'s flags in any order: --replace, --redeem-url // for a Host with no platform (pair_unix.go, pair_tcp.go) and --host-ca for // an https:// one. At most one token: "" when none was given, which pairToken // (pair_stdin.go) refuses with the usage; `-` reads it from standard input. func parsePairArgs(args []string) (token, redeemURL, hostCA string, replace bool, err error) { var rest []string for i := 0; i < len(args); i++ { switch { case args[i] == "--replace": replace = true case args[i] == "--redeem-url" && i+1 < len(args): redeemURL = args[i+1] i++ case strings.HasPrefix(args[i], "--redeem-url="): redeemURL = strings.TrimPrefix(args[i], "--redeem-url=") case args[i] == "--host-ca" && i+1 < len(args): hostCA = args[i+1] i++ case strings.HasPrefix(args[i], "--host-ca="): hostCA = strings.TrimPrefix(args[i], "--host-ca=") case strings.HasPrefix(args[i], "--"): return "", "", "", false, fmt.Errorf("unknown flag %s\n%s", args[i], pairUsage) default: rest = append(rest, args[i]) } } switch len(rest) { case 0: return "", redeemURL, hostCA, replace, nil case 1: return rest[0], redeemURL, hostCA, replace, nil } return "", "", "", false, errors.New(pairUsage) } func main() { // Started by the Windows Service Control Manager: the service runs `run` // itself and never reaches the argument parsing below. if maybeRunAsWindowsService() { auditFlush(auditFlushOnExit) return } if len(os.Args) < 2 { usage() os.Exit(2) } // Before ANY command reads state: on a machine whose bastion is a system // service, an administrator's command acts on the service's state, and an // ordinary account's pair/run/status is refused (sysservice.go). adoptSystemServiceState() if err := guardServiceFork(os.Args[1]); err != nil { fmt.Fprintln(os.Stderr, "error:", err) os.Exit(1) } var err error switch os.Args[1] { case "service": err = cmdService(os.Args[2:]) case "pair": token, redeemURL, hostCA, replace, perr := parsePairArgs(os.Args[2:]) if perr == nil { token, perr = pairToken(token, os.Stdin, stdinIsConsole(), os.Stderr) } if perr != nil { fmt.Fprintln(os.Stderr, perr) os.Exit(2) } err = cmdPair(token, redeemURL, hostCA, replace) // Already paired with this Host, nothing changed: its own exit status, // so the installers (install.ps1 -Pair, install.sh with // PRIVATAE_PAIR_CODE) report "already connected". var already *alreadyPairedError if errors.As(err, &already) { auditFlush(auditFlushOnExit) fmt.Fprintln(os.Stderr, already) os.Exit(pairExitAlreadyPaired) } case "run": err = cmdRun() case "observe:baseline": // The accounting of what is NORMAL here (baseline.go). Root, // and --force is required to replace an existing one: retaking a // baseline silently absorbs whatever has appeared since, which is the // one way this feature can be turned off by accident. args := os.Args[2:] err = cmdObserveBaseline(len(args) > 0 && args[0] == "--force") case "observe:baseline:show": err = cmdObserveBaselineShow() case "observe:delta": // What is running here that the accounting does not hold (delta.go). // Administrator only, for the same reason the accounting // is: a pass that cannot read what the baseline read reports the // difference between two ACCOUNTS rather than a change to the machine. args := os.Args[2:] err = cmdObserveDelta(len(args) > 0 && args[0] == "--json") case "observe": // What this box would report on its next heartbeat about agents, automations and // scheduled jobs — the gate for the detection plane, and the operator's own eyes. // Read-only; prints the same JSON the host receives, nothing else. err = cmdObserve() case "lab-selftest": // Lab box operator tooling: run mode=lab from a spec file without the host relay. if len(os.Args) < 3 { fmt.Fprintln(os.Stderr, "usage: privatae-bastion lab-selftest ") os.Exit(2) } err = cmdLabSelftest(os.Args[2]) case "add-folder": args := os.Args[2:] host := "" if len(args) >= 2 && args[0] == "--host" { host = args[1] args = args[2:] } if len(args) < 1 { fmt.Fprintln(os.Stderr, "usage: privatae-bastion add-folder [--host ] [display name]") os.Exit(2) } name := "" if len(args) > 1 { name = args[1] } err = cmdAddFolder(host, args[0], name) case "git-credential": // git calls: `privatae-bastion git-credential [--host h] ` args := os.Args[2:] host := "" if len(args) >= 2 && args[0] == "--host" { host = args[1] args = args[2:] } action := "get" if len(args) > 0 { action = args[0] } err = cmdGitCredential(host, action) case "backup": // The person's own backups (backupcli.go): their key, opening a // backup, and resealing one backup's key to a host that restores it. err = cmdBackup(os.Args[2:]) case "stepup-enroll": args := os.Args[2:] host, rotate, consoleOnly := "", false, false for len(args) > 0 { switch { case args[0] == "--host" && len(args) >= 2: host = args[1] args = args[2:] case args[0] == "--rotate": rotate = true args = args[1:] case args[0] == "--console-only": consoleOnly = true args = args[1:] default: fmt.Fprintln(os.Stderr, "usage: privatae-bastion stepup-enroll [--host ] [--rotate] [--console-only]") os.Exit(2) } } err = cmdStepupEnroll(host, rotate, consoleOnly) case "approvals", "approve", "deny": // The user confirms (or refuses) what their host asked for, ON this machine, // with the factor enrolled here. The host never handles the code. host, args := takeHostFlag(os.Args[2:]) switch os.Args[1] { case "approvals": // approvals drop : revoke an approval this box issued and has // not yet burned — the console can always take back what it gave. if len(args) >= 2 && args[0] == "drop" { err = cmdStepupDrop(host, args[1]) break } err = cmdStepupApprovals(host) case "approve": if len(args) < 1 { fmt.Fprintln(os.Stderr, "usage: privatae-bastion approve [--host ] ") os.Exit(2) } err = cmdStepupApprove(host, args[0]) case "deny": if len(args) < 1 { fmt.Fprintln(os.Stderr, "usage: privatae-bastion deny [--host ] ") os.Exit(2) } err = cmdStepupDeny(host, args[0]) } case "release-anchor": // An anchor whose Host is gone (anchor_release.go): machine authority // only, the host named, and the new Host's CA to prove it is gone. host, args := takeHostFlag(os.Args[2:]) caFile, force := "", false for len(args) > 0 { switch { case args[0] == "--host-ca" && len(args) >= 2: caFile = args[1] args = args[2:] case args[0] == "--force": force = true args = args[1:] default: host = "" args = nil } } if host == "" { fmt.Fprintln(os.Stderr, "usage: privatae-bastion release-anchor --host (--host-ca | --force) (from an Administrator terminal / with sudo -H)") os.Exit(2) } err = cmdReleaseAnchor(host, caFile, force) case "approvals-owner": // The one account the tray's lane serves (approvals_owner.go). args := os.Args[2:] sid, replace := "", false for len(args) > 0 { switch { case args[0] == "--sid" && len(args) >= 2: sid = args[1] args = args[2:] case args[0] == "--replace": replace = true args = args[1:] default: sid = "" args = nil } } if sid == "" { fmt.Fprintln(os.Stderr, "usage: privatae-bastion approvals-owner --sid [--replace] (from an Administrator terminal)") os.Exit(2) } err = cmdApprovalsOwner(sid, replace) case "tray": // The signed-in person's icon beside a system service // (tray_pipe_windows.go), started at every sign-in. err = cmdTray() case "unpair": // Remove one pairing: file + grant file; context store and DCN state // stay (user data). Root on a networked box, any user on a local one. if len(os.Args) < 3 { fmt.Fprintln(os.Stderr, "usage: privatae-bastion unpair ") os.Exit(2) } err = cmdUnpair(os.Args[2]) case "set-mode": if len(os.Args) < 3 { fmt.Fprintln(os.Stderr, "usage: sudo -H privatae-bastion set-mode ") os.Exit(2) } err = cmdSetMode(os.Args[2]) case "claim-anchor": // Anchoring (anchor.go): root binds this machine to ONE host, which from // then on approves every further pairing here. // // The token is OPTIONAL and usually unwanted. A box you have already // paired holds the answer to "which host" already, so the ordinary flow // is `pair ` → `set-mode networked` → `claim-anchor`, with no // second token to fetch. On a box serving SEVERAL hosts — which is what // networked mode is FOR — `--host ` says which of them holds the // anchor; that is a choice among pairings the box already has, not a // credential. A token is needed only to name a host this box does not // serve at all: a fresh unpaired box, or --rotate. args := os.Args[2:] rotate, repin, owner, host := false, false, "", "" for len(args) > 0 && strings.HasPrefix(args[0], "--") { switch { case args[0] == "--rotate": rotate = true args = args[1:] case args[0] == "--repin": repin = true args = args[1:] case args[0] == "--owner" && len(args) >= 2: owner = args[1] args = args[2:] case args[0] == "--host" && len(args) >= 2: host = args[1] args = args[2:] default: fmt.Fprintln(os.Stderr, "usage: sudo -H privatae-bastion claim-anchor [--host ] [--rotate|--repin] [--owner ] [token]\n"+ " no token: anchor to the host this box is already paired to (the usual case)\n"+ " --host : which pairing holds the anchor, when this box serves several\n"+ " token: name a host this box does not serve yet — a fresh box, or --rotate") os.Exit(2) } } // --repin takes NO token: the new name comes from the pairing this box // already holds, so there is nothing to redeem and nothing to type. if repin { // --owner is refused rather than ignored: --repin deliberately keeps // the existing owner (it is the same host under a new name), so a // caller passing one is asking for something this command does not do. if rotate || owner != "" || host != "" || len(args) > 0 { fmt.Fprintln(os.Stderr, "usage: sudo -H privatae-bastion claim-anchor --repin (no token, no --owner, not with --rotate)") os.Exit(2) } err = cmdRepinAnchor() break } if len(args) > 1 { fmt.Fprintln(os.Stderr, "usage: sudo -H privatae-bastion claim-anchor [--host ] [--rotate|--repin] [--owner ] [token]\n"+ " no token: anchor to the host this box is already paired to (the usual case)\n"+ " --host : which pairing holds the anchor, when this box serves several\n"+ " token: name a host this box does not serve yet — a fresh box, or --rotate") os.Exit(2) } // No token is the ordinary case: cmdClaimAnchor reads "" as "use the // pairing this box already holds", and refuses if that is ambiguous. err = cmdClaimAnchor(strings.Join(args, ""), rotate, owner, host) case "claim-owner": // Machine ownership: root on this box signs an owner claim that travels // on every pairing's heartbeat. Optional, and it grants nothing. if len(os.Args) < 3 { fmt.Fprintln(os.Stderr, "usage: sudo -H privatae-bastion claim-owner ") os.Exit(2) } err = cmdClaimOwner(strings.Join(os.Args[2:], " ")) case "git-setup": err = cmdGitSetup() case "context": // YOUR files, in a process running as YOU (contextui.go). Unlike `ui` this // starts a server of its own and stays in the foreground: it is not a // view of the daemon, it is a separate surface with a different owner. err = cmdContextUI() case "ui": // Opens a browser at the RUNNING daemon's UI (ui.go). It starts no // server of its own: the UI belongs to the process that knows what is // live, and a second one would render a machine nobody is serving. err = cmdUI() case "status": err = cmdStatus() // ── the approval device (device.go) and the write gate's console side ── case "device-init": err = cmdDeviceInit() case "device-approvals": err = cmdDeviceApprovals() case "device-approve", "device-deny": if len(os.Args) < 3 { fmt.Fprintln(os.Stderr, "usage: privatae-bastion "+os.Args[1]+" [--code ]") os.Exit(2) } if os.Args[1] == "device-approve" { code := "" if len(os.Args) >= 5 && os.Args[3] == "--code" { code = os.Args[4] } err = cmdDeviceApproveCode(os.Args[2], code) } else { err = cmdDeviceDeny(os.Args[2]) } case "pin-machine", "unpin-machine": // On the approval device: pin (or drop) a machine's key, as that // machine printed it when this device was pinned there. if (os.Args[1] == "pin-machine" && len(os.Args) < 4) || len(os.Args) < 3 { fmt.Fprintln(os.Stderr, "usage: privatae-bastion pin-machine | unpin-machine ") os.Exit(2) } key := "" if len(os.Args) >= 4 { key = os.Args[3] } err = cmdPinMachine(os.Args[2], key, os.Args[1] == "unpin-machine") case "pin-device", "unpin-device": if len(os.Args) < 3 { fmt.Fprintln(os.Stderr, "usage: sudo -H privatae-bastion "+os.Args[1]+" ") os.Exit(2) } err = cmdPinDevice(os.Args[2], os.Args[1] == "unpin-device") case "grants": // grants drop [--host ]: the person at the machine // removes a held store grant here (localdeny.go's doctrine: the // console can only ever remove reach). The host learns on the next // beat that the store is gone. host, args := takeHostFlag(os.Args[2:]) if len(args) < 2 || args[0] != "drop" { fmt.Fprintln(os.Stderr, "usage: privatae-bastion grants drop [--host ]") os.Exit(2) } err = cmdGrantsDrop(host, args[1]) case opSandboxSubcommand: // The sandbox child (ops_exec_linux.go): never typed by a person; the // daemon re-execs itself this way inside fresh namespaces. if len(os.Args) < 3 { os.Exit(125) } os.Exit(opSandboxChildMain(os.Args[2])) case opSandboxScopeSubcommand: // A root op's scope (ops_taskcap_linux.go): never typed by a person; // systemd-run starts it for the daemon. if len(os.Args) < 3 { os.Exit(125) } os.Exit(opSandboxScopeMain(os.Args[2])) case opActionSubcommand, opActionChildSubcommand, opActionProbeSubcommand: // An action op's unit and its sandbox's pid 1 (ops_action_linux.go): // never typed by a person; the daemon starts them. if len(os.Args) < 3 { os.Exit(125) } if os.Args[1] == opActionSubcommand { os.Exit(opActionOuterMain(os.Args[2])) } if os.Args[1] == opActionProbeSubcommand { os.Exit(opActionProbeMain(os.Args[2])) } os.Exit(opActionChildMain(os.Args[2])) case "ops": // ops [--host ] what ops and op grants this machine holds // ops drop [--host ] take back a held op grant (the host is told) // ops drop --all [--host ] take back every op grant the host holds here host, args := takeHostFlag(os.Args[2:]) if len(args) >= 2 && args[0] == "drop" { err = cmdOpsDrop(host, args[1]) break } err = cmdOpsList(host) case "root-exec": // root-exec [--host ] [grant --for | revoke] (rootexec.go): the // standing grant for the anchor host's root commands, given and taken // back only here. err = cmdRootExec(os.Args[2:]) case "quarantine": // quarantine clear : lift the box's own hold on a pairing's // write lanes (quarantine.go) — the person at the machine, only. if len(os.Args) < 4 || os.Args[2] != "clear" { fmt.Fprintln(os.Stderr, "usage: privatae-bastion quarantine clear ") os.Exit(2) } err = cmdQuarantineClear(os.Args[3]) case "coders": // coders set|on|off|drop|status (coders_cli.go): size this machine // for coder runs. Off by default. err = cmdCoders(os.Args[2:]) case "switch": // switch on|off, switch --list (switch_cli.go): the // local switch without the console page, for a machine nobody sits at. err = cmdSwitch(os.Args[2:]) case "version", "-v", "--version": // clientVersion (run.go) is the load-bearing string: publish.sh stamps it via // -ldflags, the heartbeat reports it, and self-update compares against it. The // old separate `version` var was never stamped (publish stamps clientVersion), // so `version` printed a stale hardcoded default — dropped. fmt.Println("privatae-bastion", clientVersion) default: usage() os.Exit(2) } // The command's audit rows reach the system log before the process ends // (auditlog.go queues them off the op's own path). auditFlush(auditFlushOnExit) if err != nil { fmt.Fprintln(os.Stderr, "error:", err) os.Exit(1) } }