Skip to main content
Version: Developer

OpenZiti quickstart

Overview​

OpenZiti gives Kasm Workspaces a zero trust path to private services without exposing them on the public network. This guide uses kziti, a CLI that wraps OpenZiti behind an opinionated model, to build a small lab on a single Linux VM. You stand up an OpenZiti controller and routers, publish a private nginx service, and configure Kasm to dial that service through OpenZiti egress. The result is a Kasm session that reaches the private service over an authenticated overlay, with no inbound firewall rules and no DNS entry.

Prerequisites​

Before you begin, confirm the following:

  • A Linux VM (x86_64 or aarch64) with:
    • access to root or sudo
    • an internet-accessible IPv4 address
    • a DNS record pointed at the IPv4 address
    • an installation of Docker
  • A Kasm Workspaces deployment whose Manager and Agents can reach the Linux VM on these ports:
    • 1280/tcp - controller edge or client and management API.
    • 6262/tcp - controller fabric port, used by routers.
    • 3022/tcp - public edge router listener.
    • 3023/tcp - private router listener.
  • Administrator access to the Kasm Workspaces deployment, with permission to manage egress providers.

Solution approach​

This guide progresses through the following phases:

  1. Install kziti and deploy the OpenZiti control plane.
  2. Build the network and a private router.
  3. Publish a private service.
  4. Configure OpenZiti egress in Kasm.
  5. Grant access and validate from a Kasm session.

Detailed steps​

Install kziti and deploy the OpenZiti control plane​

Step 1: Install kziti​

  1. Install the kziti CLI on the Linux VM:

    curl -fsSL https://kasmweb-build-artifacts.s3.amazonaws.com/kziti/install.sh | bash
    kziti --version
  2. Confirm the version printout:

    $ kziti --version
    kziti 0.1.0.dev28+dc90047
    commit: dc9004792a40
    built: 2026-05-08T17:18:17Z

Step 2: Deploy the OpenZiti controller and public router​

The deploy command takes two parameters:

  • <your-linux-vm-dns>: the DNS record from the prerequisites.
  • <create-an-admin-password>: a secure alphanumeric password that you generate.
  1. Deploy the controller and public router:

    kziti deploy install \
    --controller-host <your-linux-vm-dns> \
    --router-host <your-linux-vm-dns> \
    --admin-password '<create-an-admin-password>' \
    --yes

    This bootstraps the following components:

    • An OpenZiti Controller on the controller hostname.
    • A Public Router on the router hostname.
    • An admin identity that kziti uses for every subsequent command on this host.

The install runs in a few minutes and lives at /opt/kziti by default. It concludes with Installation complete.

Build the network and a private router​

In the kziti model, a network groups related services. A private router sits next to the resources the network exposes and is the only component that hosts services.

  1. Create the network record on the controller:

    kziti network create demo "Demo"
  2. Provision a private router record for the network. This writes an enrollment JWT:

    kziti router private provision demo demo-router-1 --output-dir /tmp
  3. Run the private router on the same VM in a separate kziti install directory and compose project. Use --router-port 3023 to avoid conflicting with the public router already bound to port 3022:

    kziti deploy install \
    --profile router \
    --install-dir /opt/kziti-demo-router \
    --project kziti-demo-router \
    --router-host <your-linux-vm-dns> \
    --router-port 3023 \
    --enrollment-token "$(cat /tmp/demo-router-1.jwt)" \
    --yes
  4. Confirm the new router shows online:

    kziti router list

Publish a private service​

  1. Run an nginx container attached to the private router's compose network so the router can reach it by container hostname:

    docker run -d \
    --name private-nginx \
    --network kziti-demo-router_ziti \
    nginx:alpine

    If your install used a different --project name, run docker network ls and pick the network whose name starts with the project you chose.

  2. Publish the nginx service:

    kziti service create demo private-nginx private-nginx 80 \
    --alias private-nginx.demo.zt

    The --alias value is the hostname Kasm sessions dial. The Ziti tunnel resolves it, so no DNS entry is needed.

Configure OpenZiti egress in Kasm​

Kasm authenticates to the OpenZiti controller using an admin identity.

  1. Create and auto-enroll an admin identity for Kasm:

    kziti identity create kasm_api --admin --auto-enroll --output-dir .

    This writes ./kasm_api.json, the identity file you paste into Kasm in the next steps.

  2. In the Kasm Workspaces UI, go to Infrastructure > Egress.

  3. Create an egress provider with type OpenZiti.

    OpenZiti Creation
    OpenZiti Creation
  4. Open the provider and go to OpenZiti Configuration.

  5. Open ./kasm_api.json and paste the full JSON as the OpenZiti admin identity.

    OpenZiti Credential
    OpenZiti Credential

    The admin identity JSON uses the following shape:

    {
    "ztAPI": "https://ziti.example.com:1280/edge/client/v1",
    "id": {
    "cert": "pem:-----BEGIN CERTIFICATE-----...",
    "key": "pem:-----BEGIN PRIVATE KEY-----...",
    "ca": "pem:-----BEGIN CERTIFICATE-----..."
    }
    }
  6. Map the provider to target users or workspaces.

    OpenZiti Mapping
    OpenZiti Mapping

Grant access and validate from a Kasm session​

After mapping and reconciliation, Kasm creates identities named like the following:

  • kasm-user-<username>-<user-id-prefix>-<provider-id-prefix>
  • kasm-workspace-<workspace>-<image-id-prefix>-<provider-id-prefix>

You can find the native OpenZiti UI at https://<your-linux-vm-dns>:1280/zac.

OpenZiti Created Identities
OpenZiti Created Identities
  1. List the Kasm-managed identities and pick the one to grant:

    kziti identity list --type workspace
  2. Grant it access to every service in the demo network:

    kziti access grant <kasm-workspace-identity-name> net-demo

    To scope more narrowly, target a service set (svcset-<name>) or individual service (svc-<id>) instead. See Grant access.

  3. Open a browser inside a mapped Kasm workspace session and navigate to http://private-nginx.demo.zt. The default nginx welcome page confirms that egress works.

    OpenZiti Workspace
    OpenZiti Workspace

    If the page does not load, continue with the troubleshooting steps below.

Common troubleshooting steps​

  • The stack or private router is not healthy. Confirm that the OpenZiti stack is healthy and the private router is online:

    kziti status
    kziti router list
  • The service or grant does not resolve. Confirm that the service exists and the grant resolved:

    kziti service list --network demo
    kziti access list <kasm-workspace-identity-name>
  • The session cannot reach the service. Check the Kasm sidecar logs during session startup:

    • /var/log/kasm-sidecar/network_sidecar.log
    • /var/run/kasm-sidecar/$container_namespace/ziti.log
  • The issue persists after these checks. For deeper troubleshooting, see the OpenZiti troubleshooting guide.