Skip to main content
Star OpenZiti on GitHub Star

Router Deployment

Deploy a router as a Linux system service. The router introduction may help to read first.

  1. Creation
  2. Installation
  3. Configuration
  4. Starting Up

Router creation

Create the router in the controller first with the web console or the CLI.

After creating the router, save the enrollment token (JWT) for the configuration step below.

Install the router package

The router package provides a systemd service unit and bootstrapping script.

One-liner install script

curl -sS https://get.openziti.io/install.bash | sudo bash -s openziti-router

Manual package repo setup

Configure the package repository and install openziti-router.

Configure the repository for the Debian family of distributions (Ubuntu, Mint, Pop!_OS)

Install the OpenZiti repository key.

curl -sSLf https://get.openziti.io/tun/package-repos.gpg | sudo gpg --dearmor --output /usr/share/keyrings/openziti.gpg

Ensure the key is readable by all users.

sudo chmod a+r /usr/share/keyrings/openziti.gpg

Create the repository file.

sudo tee /etc/apt/sources.list.d/openziti-release.list >/dev/null <<EOF
deb [signed-by=/usr/share/keyrings/openziti.gpg] https://packages.openziti.org/zitipax-openziti-deb-stable debian main
EOF

Update the package list.

sudo apt update

Finally, install the package: openziti-router

The openziti package provides the ziti CLI and is installed as a dependency.

Configuration

You need a config file and an enrollment with the controller. The easiest way to get both is to run the bootstrap script. You can also migrate from an existing installation or craft a config by hand. The bootstrap script is a convenience — it is not required.

Run the bootstrap script

sudo /opt/openziti/etc/router/bootstrap.bash

The script creates a config file and enrolls the router with the controller. It prompts for any answers it needs. If an answer has already been supplied (through the answer file, environment, or stdin), the script skips that prompt.

The script asks for:

  • Router address — permanent DNS name or IP address (default: localhost)
  • Enrollment token — the JWT from the controller (as a string or file path)

Migrate an existing configuration

This example illustrates copying the configuration and identity files from a previous installation.

Craft a configuration

Create a config file directly with ziti create config router edge --routerName=router. Run ziti create config environment to see the available environment variables. See the router configuration reference for details.

Automation

If you're scripting deployments or using configuration management, you can supply answers ahead of time and run the bootstrap script without prompts. You can also choose which components to bootstrap.

How to supply answers

Answers can come from any combination of:

  • Answer file — write answers in /opt/openziti/etc/router/bootstrap.env
  • Environment — export answers as environment variables and pass them with sudo -E
  • Stdin — pipe answers as KEY=VALUE lines (one per line) into the script

All answers are persisted to bootstrap.env regardless of how they were supplied.

To run without prompts, redirect stdin:

sudo -E /opt/openziti/etc/router/bootstrap.bash < /dev/null

Router answers

  1. ZITI_ENROLL_TOKEN — enrollment token as a string or file path (required)
  2. ZITI_ROUTER_ADVERTISED_ADDRESS — permanent DNS name or IP address (required)
  3. ZITI_ROUTER_PORT — TCP port for routers (default: 3022)

Selective bootstrapping

You don't have to bootstrap everything at once. Each component can be enabled or disabled independently in /opt/openziti/etc/router/service.env:

AnswerDefaultWhat it does
ZITI_BOOTSTRAP_CONFIGtrueGenerate config.yml (set to force to regenerate)
ZITI_BOOTSTRAP_ENROLLMENTtrueEnroll with the controller (set to force to re-enroll)

Starting up

Enable and start the service:

sudo systemctl enable --now ziti-router.service

Further configuration

Customize /var/lib/ziti-router/config.yml as needed and restart the service.

sudo systemctl restart ziti-router.service

Here's a link to the configuration reference.

Learn more about managing routers with the CLI.

Customize the systemd service

Use systemctl edit to override service directives like capabilities or the startup command. Pass -E to sudo so your shell's SYSTEMD_EDITOR (or EDITOR / VISUAL) is used.

sudo -E systemctl edit ziti-router.service
sudo systemctl restart ziti-router.service

An example drop-in with commented directives is included at /opt/openziti/etc/router/override.conf.example.

Firewall

The router's generated configuration uses a single TCP port (default: 3022).

Confirm the router is listening:

sudo ss -tlnp | grep ziti
Output
LISTEN 0      4096                          *:3022             *:*    users:(("ziti",pid=2166302,fd=8))

Troubleshooting

Controller address override

The router learns the controller's address from the enrollment token, so you don't normally need to supply it. If you need to override the address in the enrollment token, set these answers in /opt/openziti/etc/router/bootstrap.env or supply them to the bootstrap script:

  • ZITI_CTRL_ADVERTISED_ADDRESS — controller DNS name or IP address
  • ZITI_CTRL_ADVERTISED_PORT — controller port (default: 1280)

For Ziti versions 1.6 and lower, both answers are required.

Verify edge listener

Verify the edge listener is reachable by identities. The edge listener must terminate TLS for identities because they will authenticate with a client certificate for all interactions.

The server certificate must be issued by the controller's edge signer CA (edge.enrollment.signerCert in the controller's config.yml).

Substitute the value of listeners[?binding == 'edge'].options.advertise from /var/lib/ziti-router/config.yml:

openssl s_client -connect {listeners[?binding == 'edge'].options.advertise} -alpn ziti-edge -showcerts <>/dev/null \
|& openssl storeutl -certs -noout -text /dev/stdin \
| grep -E '(Subject|Issuer):'
Output
Issuer: C=US, L=Charlotte, O=NetFoundry, OU=ADV-DEV, CN=NetFoundry Inc. Intermediate CA 42KvRQxn.
Subject: C=US, ST=NC, L=Charlotte, O=NetFoundry, OU=Ziti, CN=BhCjN2Rkx
Issuer: C=US, L=Charlotte, O=NetFoundry, OU=ADV-DEV, CN=NetFoundry Inc. Certificate Authority IpcOEkAR6
Subject: C=US, ST=NC, L=Charlotte, O=NetFoundry, OU=ADV-DEV, CN=NetFoundry Inc. Intermediate CA 42KvRQxn.

At least one router must provide a link listener if you have multiple routers. Verify all link listeners are reachable by all routers. The link listener must terminate TLS for routers because they will authenticate with a client certificate for all interactions.

The server certificate must be issued by the controller's edge signer CA (edge.enrollment.signerCert in the controller's config.yml).

Substitute the value of link.listeners[?binding == 'transport'].advertise after the tls: prefix from /var/lib/ziti-router/config.yml:

openssl s_client -connect {link.listeners[?binding == 'transport'].advertise} -alpn ziti-link -showcerts <>/dev/null \
|& openssl storeutl -certs -noout -text /dev/stdin \
| grep -E '(Subject|Issuer):'
Output
Issuer: C=US, L=Charlotte, O=NetFoundry, OU=ADV-DEV, CN=NetFoundry Inc. Intermediate CA 42KvRQxn.
Subject: C=US, ST=NC, L=Charlotte, O=NetFoundry, OU=Ziti, CN=BhCjN2Rkx
Issuer: C=US, L=Charlotte, O=NetFoundry, OU=ADV-DEV, CN=NetFoundry Inc. Certificate Authority IpcOEkAR6
Subject: C=US, ST=NC, L=Charlotte, O=NetFoundry, OU=ADV-DEV, CN=NetFoundry Inc. Intermediate CA 42KvRQxn.

Logging

View the service's output.

journalctl -u ziti-router.service

Set a different format in the ZITI_ARGS environment variable and restart the service.


ZITI_ARGS='--log-formatter text'


Learn more in the logging reference.

Uninstall

  1. Clean the service state.

    sudo systemctl disable --now ziti-router.service
    sudo systemctl reset-failed ziti-router.service
    sudo systemctl clean --what=state ziti-router.service
  2. Purge the package, including configuration files.

    APT - Debian, Ubuntu, etc.

    sudo apt-get purge openziti-router

    RPM - RedHat, Fedora, etc.

    sudo dnf remove openziti-router
  3. Remove any firewall exceptions you created.