Alpine Router with an API Client written in GO
  • Go 75.4%
  • Python 8.1%
  • Svelte 7.9%
  • JavaScript 3.5%
  • TypeScript 2.6%
  • Other 2.3%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Alex 95faa5189e Document that required secrets refuse empty strings
Refs #137

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-12 10:15:39 +00:00
.forgejo/workflows build: drop mandatory third-party license review from the release pipeline 2026-11-06 19:29:39 +00:00
cmd Install the configured agent logger as the slog default 2026-11-12 07:23:36 +00:00
configs WIP: expand complete TOML provisioning and native validation 2026-10-28 19:20:42 +00:00
deployments Read TOML directly at first boot, without router-assigned ids 2026-11-07 06:23:32 +00:00
docs Reject empty strings for required secrets 2026-11-12 10:15:39 +00:00
internal Reject empty strings for required secrets 2026-11-12 10:15:39 +00:00
iso Rework RAUC A/B updates with independent OS and kernel slots 2026-10-14 20:30:46 +02:00
make build: drop mandatory third-party license review from the release pipeline 2026-11-06 19:29:39 +00:00
pkg Reject empty strings for required secrets 2026-11-12 10:15:39 +00:00
rauc feat(build): independent build signing identities, source release and faster test pipeline 2026-11-06 18:37:02 +00:00
scripts Fail Go packages whose test binary cannot list its tests 2026-11-12 09:34:54 +00:00
tests Update hurl interface and PPPoE tests to the draft flow 2026-11-12 06:51:21 +00:00
ui Preview restore removals for the complete port mapping 2026-11-12 10:09:32 +00:00
.dockerignore feat(build): independent build signing identities, source release and faster test pipeline 2026-11-06 18:37:02 +00:00
.env.example build: drop mandatory third-party license review from the release pipeline 2026-11-06 19:29:39 +00:00
.gitignore Merge remote-tracking branch 'origin/main' into issue-71-independent-build-signing 2026-11-06 18:37:02 +00:00
build-images.md Fix make tidy, bundle staging and ownership cleanup 2026-11-09 14:13:49 +00:00
Dockerfile.build Optimize production builds and validate exact release inputs 2026-10-24 13:15:40 +00:00
example-router.toml Add switch to turn return routing off globally and per gateway 2026-11-11 16:48:21 +00:00
go.mod Fix make tidy, bundle staging and ownership cleanup 2026-11-09 14:13:49 +00:00
go.sum Fix make tidy, bundle staging and ownership cleanup 2026-11-09 14:13:49 +00:00
LICENSE rename: vyrex-router → kaido-core 2026-04-20 13:13:24 +00:00
Makefile Fix Linux E2E scripts for the current agent 2026-11-09 14:43:00 +00:00
NOTICE feat(build): independent build signing identities, source release and faster test pipeline 2026-11-06 18:37:02 +00:00
openapi.yaml Document that required secrets refuse empty strings 2026-11-12 10:15:39 +00:00
package-lock.json rename: vyrex-router → kaido-core 2026-04-20 13:13:24 +00:00
README.md Document deploy.sh Node.js requirement in the README 2026-11-12 09:34:15 +00:00
roadmap-idea.md Record faster historic reads and TOML IDs as roadmap ideas 2026-11-07 08:43:06 +00:00
router-dashboard.md Update docs for removed recovery units 2026-11-06 20:47:55 +00:00

kaido-core

kaido-core is a Linux-based router and firewall built on Alpine Linux. It brings network configuration, firewall policy, routing, and system updates together in a router with a web dashboard and an API.

It can run on physical hardware or as a virtual machine.

Why kaido-core exists

I started kaido-core because I was unhappy with the router options available to me. VyOS lacked the web interface I wanted, I felt pfSense placed more emphasis on its commercial edition, and I could not find an Alpine-based router that suited my needs. I wanted an Alpine-based router with a web interface.

Dashboard

The screenshots show an example configuration. In the diagonal comparisons, dark mode is on the left and light mode is on the right.

Dashboard overview in dark and light mode

Firewall rules in dark and light mode

Interfaces in light mode

Gateway groups in dark and light mode

Static routes in dark mode

Firewall and routing

kaido-core uses Linux networking and nftables to apply firewall and NAT rules. Administrators can configure interfaces, addresses, routes, and routing policies alongside the firewall. Firewall rules can select a gateway group for matching traffic, allowing different traffic to use different connections.

Gateway groups combine gateways into priority tiers. The lowest available tier is active, and a group can require a minimum number of healthy gateways in a tier. Gateways in the same tier can share traffic using configured weights. When a tier no longer meets the group's health requirement, traffic can fail over to an eligible lower-priority tier. Configurable ICMP, TCP, and HTTP health checks monitor individual gateways. This supports deployments with multiple internet connections, including a backup connection for failover.

Other highlights

kaido-core supports WireGuard and IPsec VPNs, VLAN and VRF interfaces, and BGP and OSPF routing through FRRouting. It also provides DHCP and DNS services and traffic shaping.

Its API-first management supports access through an HTTPS API. A dedicated MCP server connects AI assistants and other MCP clients to the router API using standard input and output.

The project uses embedded DoltLite for versioned configuration. Each author has a draft branch. Selected changes are reviewed and activated as a candidate; confirmation advances the confirmed configuration. Commits record authors and support history and diffs. Snapshot tags identify saved versions that can be restored as new validated changes.

Configuration and management

The router agent manages the system and exposes its configuration through the web dashboard and API. Configuration changes are prepared as drafts and activated through a central commit flow. Changes can be confirmed or rolled back, including automatic rollback when a pending change is not confirmed. This helps recover access after a configuration change disrupts management connectivity.

A new router can start from a TOML file, for example one exported from a running router and passed in by Terraform through cloud-init. The router reads this file only at first boot; a running router accepts no TOML. To restore a router, load a backup. The router assigns its own ids for firewall rules and other resources, so the file contains none. Rules apply in the order they appear in the file, or by an optional order number on every rule of a list.

RAUC and A/B system updates

kaido-core uses RAUC for signed operating system updates. A router has two root partitions, A and B. A full update writes a complete system into the inactive slot while the current slot continues running. Each slot contains its own kernel, initramfs, and matching kernel modules.

After a reboot, the router starts the updated slot. The agent confirms it after successful startup. If the new slot is not confirmed, the bootloader can return to the previously confirmed slot on a later boot. A new installation starts with slot A populated and slot B empty, so the first update provides the second bootable system.

Router configuration, identity, credentials, and state are kept on the shared /data partition across OS updates. The shared bootloader and data partition remain outside the root slots. A/B rollback does not protect against failure of the shared disk or bootloader.

Verify downloads

The repository contains no signing keys. Each release publishes three separate public identities: APK-PUBLIC-KEY.pem, RAUC-CERT.pem, and RELEASE-PUBLIC-KEY.pem. Their private keys are not published. Independent builds use their own selected identities.

The official fingerprints will be listed here when the official identities are active.

Compare the fingerprints with an independently trusted source before trusting downloaded keys. A fingerprint obtained only from the same untrusted download as its key cannot establish its authenticity. In the complete release directory, inspect the release key fingerprint first. If it matches the independently confirmed value, verify the signature and every listed file:

openssl pkey -pubin -in RELEASE-PUBLIC-KEY.pem -outform DER | sha256sum
openssl dgst -sha256 -verify RELEASE-PUBLIC-KEY.pem -signature SHA256SUMS.sig SHA256SUMS
sha256sum --check SHA256SUMS

Check the other public identities before trusting their signatures:

openssl pkey -pubin -in APK-PUBLIC-KEY.pem -outform DER | sha256sum
openssl x509 -in RAUC-CERT.pem -noout -fingerprint -sha256
rauc info --keyring=RAUC-CERT.pem /path/to/bundle.raucb

The signed checksum list covers the release artifacts, including images, binaries, public verification material and version-matched source and component inventory. A successful checksum alone does not authenticate the publisher.

Build it yourself

Build on a Linux amd64 host with Git, GNU Make, Python 3, and access to Docker. The build container provides the remaining build tools. Building the VM image requires a privileged container and available host loop devices. Building the Kea and Knot packages uses the selected local APK signing identity.

Install the host tools and allow your user to access Docker, then log in again:

# Arch/CachyOS
sudo pacman -S --needed git make python docker

# Debian/Ubuntu
sudo apt install git make python3 docker.io

# Both
sudo systemctl enable --now docker
sudo usermod -aG docker "$USER"

Then build:

git clone https://git.knoll-systems.de/Alex/kaido-core.git
cd kaido-core
make image-amd64 VERSION=dev FAMILY=vm
make iso-amd64 VERSION=dev FAMILY=hardware

The VM image is dist/images/kaido-core-dev-amd64-vm-lts.qcow2. The hardware installer is dist/images/kaido-core-dev-amd64-hardware-lts.iso. Start a VM with the QCOW2 image or boot the ISO to install on hardware. Both use the RAUC A/B layout.

To build a signed VM update bundle, run make bundle-amd64 VERSION=dev FAMILY=vm. Use FAMILY=hardware for hardware. Local builds generate persistent signing identities in the Git-ignored .kaido-signing/ directory. The image trusts its selected RAUC identity. Back up the private keys securely; losing or rotating a key affects updates to installations that trust it. CI must provide stable identities and does not generate them.

Run the tests

make test runs on the host and needs more tools than the image build:

# Arch/CachyOS
sudo pacman -S --needed go gcc zlib zlib-static nodejs-lts-krypton npm rauc openssl squashfs-tools nftables

# Debian/Ubuntu
sudo apt install golang-go gcc zlib1g-dev nodejs npm rauc openssl squashfs-tools nftables

The project needs Go 1.26 or newer and Node.js 24 LTS, and distributions can package older versions. Check go version and node --version.

Tests skip when a tool is missing, and the run still reports ok. Add -v to go test to see skipped tests and the missing tool. A few tests also look for busybox, grub-editenv, rsyslogd or softflowd.

Update a running router

scripts/deploy/deploy.sh <host> builds the agent with the host tools above and installs it on a running router. It needs a patched Node.js: 22.23.4+, 24.22.1+ or 26.12.1+. Run it as your own user, not with sudo, because sudo can find an older Node.js.

License

Kaido Core is licensed under AGPL-3.0-only. See NOTICE for the project license declaration and third-party materials.