Skip to content
Docs · Kubyl Server: install and pairing

Kubyl Server

Kubyl Server: install and pairing

Run Kubyl Server in a container, pair the mobile app and configure it with flags and environment variables.

Kubyl Server runs on a machine you control, holds your kubeconfigs and credentials, and serves them over gRPC to Kubyl Mobile. The phone never gets a kubeconfig, an exec plugin or a cluster token: it pairs with the server and the server talks to your clusters. The desktop app does not need it.

Kubyl Server is a subscription (no free tier, no trial). The container image is private: your subscription comes with an OCI pull token for harbor.tyrola.dev/kubyl/server, which stops working when the subscription ends. The mobile app is free in the stores.

What you need

  • A Linux host (or any Docker or Podman host) that can reach your clusters' API servers.
  • A kubeconfig for each cluster, readable by the server.
  • A way for your phone to reach the server: the same network or, recommended, a private network such as Tailscale or WireGuard. The server is not meant to face the public internet. See Server operations.
  • A subscription, which you activate with a code from your customer portal at kubyl.dev. See Server license.

Install with a container

docker login harbor.tyrola.dev          # the pull token from your portal
docker run --rm -it \
  -p 8443:8443 \
  -v kubyl-config:/config \
  -v "$HOME/.kube:/kube:ro" \
  -e KUBYL_SERVER_PUBLIC_URL=https://kubyl.example.net:8443 \
  harbor.tyrola.dev/kubyl/server:latest
  • `-it` gives you the console, a full-screen terminal UI. Without a terminal (plain docker run -d, Kubernetes, systemd) the server writes logs to stdout instead, prints the pairing QR code at startup and offers everything through the web UI.
  • /config is the server's state: settings, the TLS certificate, paired devices, the encrypted credential store and its key, and the license. Keep it on a volume and back it up. See Server license.
  • KUBYL_SERVER_PUBLIC_URL is the address your phone reaches the server at. It goes into the pairing link and into the self-signed certificate's names. Without it the server guesses its default route's address.
  • The container runs as UID 65532. Mount kubeconfigs readable by that user.

Tell the server where the kubeconfigs are in /config/settings.json. Create it before the first start, or edit it after and restart.

settings.json
{
  "kubernetes": {
    "load_default_kubeconfig": false,
    "load_kubeconfig_env": false,
    "kubeconfigs": ["/kube/config"]
  }
}

Without a kubernetes section the server reads $KUBECONFIG and ~/.kube/config of its user.

Command line and environment

FlagEnvironmentMeaning
--config-dirKUBYL_SERVER_CONFIG_DIRState directory. Default ~/.config/kubyl-server, mode 0700. The server refuses a directory others can read.
--listenKUBYL_SERVER_LISTENListen address. Default 0.0.0.0:8443; the image sets it.
--public-urlKUBYL_SERVER_PUBLIC_URLThe URL clients use.
--tls-cert, --tls-keyKUBYL_SERVER_TLS_CERT, KUBYL_SERVER_TLS_KEYYour own PEM certificate and key instead of the self-signed one.
--no-consoleNever open the console, even in a terminal.
--activation-codeKUBYL_SERVER_ACTIVATION_CODEActivate at startup. Prefer the variable. See Server license.
KUBYL_SERVER_KEYThe credential store's key (base64, 32 bytes) instead of a key file.

settings.json also takes "server": {"listen": …, "public_url": …}, "license": {"online": true, "service_url": …} and "push": {"relay_url": …}. Changes need a restart.

First start and pairing

  1. Start the container with -it. The first thing the console shows is the web UI admin token, once. Copy it somewhere safe.
  2. On the Overview tab you see the pairing QR code, its link and how long it works. A code is good for one device and 10 minutes; R makes a new one. The QR code is 45x23 characters: in a small window press F to show it full screen, or use the link or the web UI's Pair page.
  3. In Kubyl Mobile, add a server and scan the code, or paste the link. The app pins the server's certificate (its public key hash is in the link), so there is no certificate authority to trust and nothing to type.
  4. A server without a license is Unlicensed: the phone can pair and shows the license screen, nothing else works. Activate it next.

Paired devices appear on the Devices tab, where X revokes one: its sessions end at once and its streams close. A phone can also remove itself, and any paired phone can list and revoke devices, because there is one user per server. Failed pairing attempts are limited per address (5 in 10 minutes).

Something missing or wrong? Open an issue on GitHub.