Router Deployment
Deploy a router as a Linux system service. The router introduction may help to read first.
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
Use the install script to configure the package repo and install the ziti CLI (if not already done):
curl -sS https://get.openziti.io/install.bash | sudo bash -s openziti
Then install openziti-router in a terminal session so the bootstrap can prompt you.
sudo apt-get install openziti-router # Debian, Ubuntu
sudo dnf install openziti-router # RedHat, Fedora
For non-interactive installs, see Automation.
Manual package repo setup
Configure the package repository and install openziti-router.
- Debian
- RedHat
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
Configure the repository for the RedHat family (Fedora, Rocky, Alma)
Create the repository file.
sudo tee /etc/yum.repos.d/openziti-release.repo >/dev/null <<\EOF
[OpenZitiRelease]
name=OpenZiti Release
baseurl=https://packages.openziti.org/zitipax-openziti-rpm-stable/redhat/$basearch
enabled=1
gpgcheck=0
gpgkey=https://packages.openziti.org/zitipax-openziti-rpm-stable/redhat/$basearch/repodata/repomd.xml.key
repo_gpgcheck=1
EOF
Update the package list.
sudo dnf 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 answers interactively. When run non-interactively (e.g., with an answer file), it uses the provided values without prompting.
On success, the script enables and starts the service.
The script asks for:
- Permanent external address — DNS name or IP of this router (required, no default)
- Port — TCP port (default: 3022)
- 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 — copy /opt/openziti/etc/router/bootstrap.env as a template, fill in the values, and pass it as the first argument. The bootstrap script reads the file but never modifies it.
- Environment — export answers as environment variables and pass them with
sudo -E
Precedence (highest to lowest): environment variables → answer file → service.env defaults.
Answers are written to a temporary file during bootstrap and deleted automatically on success. If bootstrap fails, the temporary file is preserved and a re-run command is printed.
cp /opt/openziti/etc/router/bootstrap.env /tmp/my-answers.env
# edit /tmp/my-answers.env with your values
sudo -E /opt/openziti/etc/router/bootstrap.bash /tmp/my-answers.env
Router answers
ZITI_ROUTER_ADVERTISED_ADDRESS— permanent external address of this router (required)ZITI_ROUTER_PORT— TCP port (default: 3022)ZITI_ENROLL_TOKEN— enrollment token as a string or file path (required)
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:
| Answer | Default | What it does |
|---|---|---|
ZITI_BOOTSTRAP_CONFIG | true | Generate config.yml (set to force to regenerate) |
ZITI_BOOTSTRAP_ENROLLMENT | true | Enroll with the controller (set to force to re-enroll) |
Starting up
The bootstrap script automatically enables and starts the service on success. If you need to start it manually (for example, after crafting a configuration by hand):
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
The package includes a drop-in file with commented example directives at /etc/systemd/system/ziti-router.service.d/override.conf. Your edits to this file are preserved across package upgrades.
Firewall
The router's generated configuration uses a single TCP port (default: 3022).
Confirm the router is listening:
sudo ss -tlnp | grep ziti
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, supply these answers via the answer file or environment variables:
ZITI_CTRL_ADVERTISED_ADDRESS— controller DNS name or IP addressZITI_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):'
Verify link listener
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):'
Logging
View the service's output.
journalctl -u ziti-router.service
- Log Formats
- Log Levels
Set a different format in the ZITI_ARGS environment variable and restart the service.
ZITI_ARGS='--log-formatter text'
Enable DEBUG log level with the --verbose flag in the ZITI_ARGS environment variable and restart the service.
ZITI_ARGS='--verbose'
Learn more in the logging reference.
Uninstall
-
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 -
Purge the package, including configuration files.
APT - Debian, Ubuntu, etc.
sudo apt-get purge openziti-routerRPM - RedHat, Fedora, etc.
sudo dnf remove openziti-router -
Remove any firewall exceptions you created.