Skip to main content

Release process

routerd uses date-based release versions. The executable version, release tag, and release archive name use yyyymmdd.N format, such as 20260509.0.

Automated release

Push a release tag to start the GitHub Actions workflow:

git tag 20260509.0
git push origin 20260509.0

The Release workflow builds these targets:

  • linux-amd64
  • freebsd-amd64

Each target archive is named routerd-<tag>-<os>-<arch>.tar.gz. The archive contains:

  • bin/: routerd, routerctl, and the managed daemon binaries
  • install.sh: POSIX sh installer
  • uninstall.sh: POSIX sh uninstaller
  • etc/routerd/router.yaml.sample: sanitized sample configuration
  • systemd/ or rc.d/: service templates for the target OS
  • share/doc/: README, VERSION, and LICENSE notice

The workflow uploads each .tar.gz archive and its .sha256 file to the GitHub Release page.

Responsibility split

Installation logic lives in install.sh. The Makefile is only for development tasks such as building, testing, schema checks, example validation, website builds, and release archive generation. The release archive does not include the Makefile. This keeps end-user installation and upgrade behavior in one script.

Development tests use Makefile targets:

make test
make check-schema
make validate-example
make dist ROUTERD_OS=linux GOARCH=amd64 VERSION=20260509.0

Deployment smoke checks use install.sh. After installation, install.sh calls routerctl status when the routerd control socket exists. The GitHub release workflow also extracts each archive and runs install.sh with a temporary non-system prefix. That smoke test verifies that the archive can install and uninstall without using a Makefile. The CI smoke test passes --no-install-deps because dependency installation belongs to the target router host.

Install a release archive on the router host:

tar -xzf routerd-20260509.0-linux-amd64.tar.gz
sudo ./install.sh

install.sh copies binaries to /usr/local/sbin, installs service templates, and writes router.yaml.sample. At the start of the run, it detects the OS package manager and installs known runtime packages unless --no-install-deps is passed. It does not overwrite an existing /usr/local/etc/routerd/router.yaml. When an existing /usr/local/sbin/routerd is found, the installer switches to upgrade mode automatically. It prints the old and new routerd --version output, replaces binaries and service templates, preserves configuration and state, and restarts routerd.service or the FreeBSD routerd rc.d service if it was already running. Replaced files are copied to *.backup.YYYYMMDDHHMMSS before replacement. Pass --no-restart to replace files without restarting the service. Pass --dry-run to print planned file and service-manager changes. Pass --verbose for shell tracing. Pass --no-config-update to leave router.yaml.sample unchanged. Pass --no-install-deps to skip OS package installation. Pass --list-deps to print the package and command list without changing the host. Pass --deps-only to install packages and then exit before copying routerd files. Pass --with-tailscale to include the optional Tailscale package and command check. Pass --enable-service or --start-service when you want a fresh install to call the host service manager. After installation, the script runs routerctl status when the routerd control socket exists.

The installer never modifies these runtime or state locations:

  • /usr/local/etc/routerd/router.yaml
  • /var/lib/routerd
  • /var/db/routerd
  • /run/routerd
  • /var/run/routerd
  • /var/log/otelcol

Runtime dependencies

install.sh keeps dependency installation in the same end-user path as binary installation. This avoids a separate Makefile install path.

On Debian and Ubuntu, the installer uses apt-get and installs:

ca-certificates curl dnsmasq nftables wireguard-tools chrony bind9-dnsutils tcpdump cron jq ppp pppoe conntrack iproute2 iputils-ping iputils-tracepath net-tools kmod radvd strongswan-swanctl iptables

On Fedora-like systems, the installer uses dnf and installs:

ca-certificates curl dnsmasq nftables wireguard-tools chrony bind-utils tcpdump cronie jq ppp rp-pppoe conntrack-tools iproute iputils traceroute kmod radvd strongswan iptables

On Arch-like systems, the installer uses pacman and installs:

ca-certificates curl dnsmasq nftables wireguard-tools chrony bind tcpdump cronie jq ppp rp-pppoe conntrack-tools iproute2 iputils traceroute kmod radvd strongswan iptables

On FreeBSD, the installer uses pkg and installs:

ca_root_nss curl dnsmasq wireguard-tools mpd5 bind-tools tcpdump jq chrony strongswan

FreeBSD pf, ifconfig, route, service, sysrc, and cron are base-system tools and are checked as commands rather than installed as packages.

On NixOS, the installer prints a warning instead of calling nix-env. Declare packages in the NixOS configuration or in routerd Package resources.

After dependency installation, the script checks that the expected commands exist. Missing commands are warnings, not fatal errors, because package names vary between distributions. Use this command to inspect the dependency set:

./install.sh --list-deps

Uninstall

Use uninstall.sh when you want to remove installed files separately from state:

sudo ./uninstall.sh --yes

The default uninstall stops and disables the service, removes routerd binaries, removes the service template, and removes runtime files. It keeps /usr/local/etc/routerd, /var/lib/routerd, /var/db/routerd, and /var/log/otelcol.

Purge options are explicit:

sudo ./uninstall.sh --yes --purge-config
sudo ./uninstall.sh --yes --purge-state
sudo ./uninstall.sh --yes --all

Use --dry-run to preview removal without changing the host.

Manual dispatch

If a tag already exists, the workflow can also be started from GitHub Actions with the workflow_dispatch input:

tag = 20260509.0

The workflow checks out that tag before building.

Fallback

If GitHub Actions is unavailable, build the same archives locally:

make dist ROUTERD_OS=linux GOARCH=amd64 VERSION=20260509.0
make dist ROUTERD_OS=freebsd GOARCH=amd64 VERSION=20260509.0

Then create a release with the GitHub CLI:

gh release create 20260509.0 \
dist/linux-amd64/routerd-20260509.0-linux-amd64.tar.gz \
dist/linux-amd64/routerd-20260509.0-linux-amd64.tar.gz.sha256 \
dist/freebsd-amd64/routerd-20260509.0-freebsd-amd64.tar.gz \
dist/freebsd-amd64/routerd-20260509.0-freebsd-amd64.tar.gz.sha256 \
--title "routerd 20260509.0" \
--generate-notes \
--verify-tag