-
Notifications
You must be signed in to change notification settings - Fork 2
appliance
Pre-Alpha. This page describes behavior that may change.
Ze ships a bootable x86_64 VM appliance image: a minimal Linux system built with gokrazy that runs Ze as its only application. No package manager, no shell (except an emergency serial console), atomic A/B updates, automatic process supervision. The result is a 2 GB disk image suitable for N100-class mini PCs, Proxmox VMs, or QEMU testing.
If you just want to run Ze on an existing Linux host, use the binary or container builds from the install page instead. The appliance is for when you want a locked-down, single-purpose networking box.
| Component | Purpose |
|---|---|
| Linux kernel (x86_64) | Boot and hardware drivers. |
| Gokrazy init | Process supervisor, DHCP client, NTP, web status UI. |
| Ze | BGP daemon with all internal plugins compiled in. |
| serial-busybox | Emergency shell on the serial console (not started by default). |
The root filesystem is a read-only SquashFS. Persistent data lives on a separate ext4 partition mounted at /perm.
Install once on the build machine. macOS:
brew install e2fsprogs # ext4 filesystem tools
brew install qemu # VM runtime (testing only)The gok build tool is vendored in the repo at gokrazy/tools/vendor/ and built automatically by Make. No separate install is needed.
After cloning the repo, download gokrazy system packages (Linux kernel, init, serial console) into the Go module cache. This is a one-time ~42 MB download. The exact versions are pinned in gokrazy/ze/builddir/*/go.mod (tracked in git, verified by go.sum):
make ze-gokrazy-depsAfter this, subsequent builds work offline.
The first build creates SSH credentials and a TLS certificate for the web UI:
make ze-gokrazy USER=admin PASS=secretSubsequent rebuilds reuse the existing database (same credentials, same TLS cert):
make ze-gokrazyTo use a database from a running instance or from another machine:
make ze-gokrazy ZEFS=/path/to/database.zefsThe first build does six things:
- Builds
bin/zefor the host. - Runs
ze initwith the supplied credentials and generates a self-signed TLS certificate (the--web-certflag wires this up). - Cross-compiles Ze for
linux/amd64. - Builds a 2 GB disk image.
- Formats the persistent
/permpartition. - Injects
database.zefs(credentials plus TLS cert) into/perm/ze/.
The database is kept at tmp/gokrazy/init/database.zefs between builds, so browsers that trust the certificate on first use will not prompt again after image rebuilds. The final image lands at tmp/gokrazy/ze.img.
make ze-gokrazy-runThis boots the image with the ports you care about forwarded to localhost:
| Host port | Guest service | How to use it |
|---|---|---|
| 18080 | Gokrazy web UI (port 80) | http://localhost:18080/ |
| 28080 | Ze web UI (port 8080) | http://localhost:28080/ |
| 2222 | Ze SSH CLI (port 22) | ssh -p 2222 admin@localhost |
Quit QEMU with Ctrl-A X.
The gokrazy web UI (:18080) shows process status, stdout/stderr ring buffers, and resource usage. Default credentials for it live in gokrazy/ze/config.json under Update.HTTPPassword.
Write the image to a USB drive or internal disk on your target machine:
# Linux
sudo dd if=tmp/gokrazy/ze.img of=/dev/sdX bs=4M status=progress
# macOS
sudo dd if=tmp/gokrazy/ze.img of=/dev/rdiskN bs=4mOr import into Proxmox:
qm importdisk <vmid> tmp/gokrazy/ze.img <storage>The machine boots to a serial console (115200 baud). Ze starts automatically, gets a DHCP address, and begins listening for BGP connections according to the baked-in /etc/ze/ze.conf.
The initial Ze config is embedded in the read-only root filesystem at /etc/ze/ze.conf. It is baked in at build time from the ExtraFileContents field of gokrazy/ze/config.json. The shipped seed enables the web UI on :8080 and SSH on :22, with logging at info level:
environment {
log {
level info
}
web {
enabled true
server default {
ip 0.0.0.0
port 8080
}
}
ssh {
enabled true
server default {
ip 0.0.0.0
port 22
}
}
}
To change the seed config, edit ExtraFileContents in gokrazy/ze/config.json and rebuild.
Once booted, use ze config edit over SSH to modify the running configuration. Changes are stored in /perm/ze/database.zefs and persist across reboots and image updates.
Ze's environment is set in gokrazy/ze/config.json under PackageConfig:
| Variable | Value | Purpose |
|---|---|---|
ze.config.dir |
/perm/ze |
Persistent storage for database.zefs. |
ze.bgp.api.socketpath |
/tmp/ze.socket |
Unix socket for the local API. |
ze.bgp.daemon.drop |
false |
No privilege dropping (no zeuser on gokrazy). |
ze.log |
info |
Log level. |
ze.log.backend |
stderr |
Logs land in the gokrazy ring buffer. |
Gokrazy supports atomic A/B partition updates over the network. Build a new image and push it to the running instance:
GOARCH=amd64 bin/gok --parent_dir gokrazy -i ze updateThis rebuilds and pushes the new root filesystem without touching /perm. The machine reboots into the new version. If the update fails mid-flight, the previous root partition is still intact — you cannot brick the box with a bad update.
For full image rebuilds (when you also want to update the kernel or partition layout), use make ze-gokrazy USER=admin PASS=secret again and re-flash.
Gokrazy has no shell and no PATH. Ze's external plugin mechanism uses /bin/sh -c to fork processes, so it does not work here. Instead, every Ze plugin (bgp-rib, bgp-gr, bgp-adj-rib-in, …) is compiled into the ze binary as an internal plugin and runs as a goroutine. This is the default build and covers all standard BGP functionality. If you need an external plugin, the gokrazy appliance is the wrong target.
Gokrazy's init restarts Ze if it exits with a non-zero status, except exit code 125 which means "don't restart". Ze handles SIGTERM for graceful shutdown. Logs (stdout/stderr) are captured in ring buffers visible through the gokrazy web UI.
The /perm partition (ext4) survives image updates. Ze stores its database (database.zefs), TLS certificates, and config state there. The pointer is ze.config.dir=/perm/ze.
gokrazy/
.gitignore # excludes *.img
tools/
tools.go # blank import pinning the gok version
go.mod, go.sum # gok dependency pins
vendor/ # vendored gok source (~16 MB, committed)
ze/
config.json # gokrazy instance config (what to build, how to start)
builddir/
codeberg.org/thomas-mangin/ze/
go.mod # ze dependency pins + relative replace directive
go.sum
github.com/rtr7/kernel/
go.mod, go.sum # Linux kernel version pin
github.com/gokrazy/gokrazy/
go.mod, go.sum # gokrazy init version pin
cmd/dhcp/ # DHCP client
cmd/ntp/ # NTP client
cmd/heartbeat/ # watchdog heartbeat
cmd/randomd/ # entropy seeder
github.com/gokrazy/serial-busybox/
go.mod, go.sum # emergency serial shell
The tools/vendor/ directory holds the gok tool source, committed to git. The builddir/ files are small text (go.mod + go.sum, ~27 KB). System packages (kernel, init) live in the Go module cache after make ze-gokrazy-deps.
The ze appliance command provides a structured workflow for managing appliance fleets from a bastion host:
| Command | Purpose |
|---|---|
ze appliance init <name> |
Interactive wizard: set target IP, SSH user, passphrase. Creates encrypted appliance directory at ~/.config/ze/appliances/<name>/. |
ze appliance build <name> |
Build a full disk image for the named appliance. |
ze appliance run <name> |
Boot the image in QEMU for local testing. |
ze appliance push <name> |
OTA update to the running appliance (A/B partition swap). |
ze appliance config-push <name> |
Push config to a running device. The device auto-reverts after 30s if BGP does not stabilize. |
ze appliance config-push --all --parallel 4 |
Push config to all appliances in parallel. |
ze appliance list |
List all configured appliances. |
ze appliance show <name> |
Show appliance details. |
ze appliance export <name> |
Export encrypted archive for disaster recovery. |
ze appliance import <archive> |
Restore appliance from encrypted archive. |
Appliance secrets are encrypted at rest using Argon2id + XChaCha20-Poly1305 when a passphrase is set.
When config is pushed to a device (config-push), the device:
- Validates the new config against YANG schemas.
- Applies the config atomically.
- Waits 30 seconds for BGP sessions to stabilize.
- If BGP does not stabilize, automatically reverts to the previous config.
This prevents a bad config push from leaving a device unreachable.
- Install for non-appliance builds (binary, container, from source).
- Building for host builds and toolchain setup.
- CLI for editing the running config over SSH.
- Web UI for the browser interface reachable on port 8080 of the appliance.
Adapted from main/docs/guide/appliance.md.
Unreviewed draft. This wiki was authored in bulk and has not been reviewed. File corrections on the issue tracker.
- Overview
- YANG Model
- Editor Workflow
- Archive and Rollback
- System
- Interfaces
- VRRP
- BFD
- FIB
- OSPF
- IS-IS
- MPLS / LDP / RSVP-TE
- RSVP-TE
- SRv6
- Static Routes
- Policy Routing
- Firewall
- Traffic Control
- Class of Service
- L2TP/PPP
- PPPoE
- VPP Data Plane
- RPKI
- IPsec VPN
- TACACS+ AAA
- RADIUS AAA
- AS112 DNS
- Authorization
- Fleet
- BGP
- Starting and Stopping
- Show Commands
- Monitoring
- Flow Export
- DDoS Mitigation
- Anomaly Detection
- Health Checks
- Audit Trail
- Production Diagnostics
- Logging
- Operational Reports
- Healthcheck
- Self-Update
- Zero-Touch Provisioning
- MRT Analysis
- Upgrade and Restart
- Storage
- Policy
- Core
- Resilience
- Validation
- Capabilities
- Address Families
- Protocol
- Subsystems
- Infrastructure
- Route Server at an IXP
- Transit Edge with RPKI
- Public Looking Glass
- ExaBGP Migration Walkthrough
- FlowSpec Injection
- Chaos-Tested Peering
- AS Path Topology