Quickstart

This guide walks you through a complete Mezite deployment on a single machine — from installing the server to SSH-ing into your first node. It should take about five minutes.

By the end you will have a running Mezite auth/proxy server, an enrolled agent node, an admin user, and a working SSH connection through the Mezite proxy.

This guide uses a local, single-node setup suitable for development and evaluation. TLS verification is disabled for simplicity. For production deployments, see the Architecture and Systemd guides.

Prerequisites

  • Linux or macOS host
  • Podman or Docker (only needed if using PostgreSQL — SQLite requires no external services)
  • Mezite binaries installed (see Installation)

Step 1: Install Mezite

If you have not already installed the Mezite binaries, grab them now. The quickest method on Linux:

Install binaries bash
curl -fsSL https://releases.mezite.com/latest/mezite-linux-amd64.tar.gz \
  | tar -xz -C /usr/local/bin/

# Confirm installation
mezhub version

Step 2: Choose a Database

Mezite stores all cluster state — users, roles, certificate authorities, audit events — in a database. You can use SQLite (zero dependencies, great for getting started) or PostgreSQL (recommended for production).

Option A: SQLite (default, simplest)

No external services needed. SQLite is the default — Mezite creates the database file automatically:

Start mezhub with SQLite (default) bash
MEZITE_CLUSTER_NAME=my-cluster \
MEZITE_ADMIN_PASSWORD='S3cureP@ssw0rd' \
MEZITE_AUTH_H2C=true \
mezhub

That's it — no database to install. The SQLite file is created at /var/lib/mezite/mezhub.db. Skip to Step 3.

Option B: PostgreSQL

Start a local PostgreSQL instance with Podman (or Docker):

Start PostgreSQL 16 bash
podman run -d --name mezite-postgres \
  -e POSTGRES_USER=mezite \
  -e POSTGRES_PASSWORD=mezite \
  -e POSTGRES_DB=mezite \
  -p 5432:5432 \
  postgres:16

# Wait a few seconds for PostgreSQL to become ready
podman logs -f mezite-postgres 2>&1 | grep -m1 "ready to accept connections"

Then start mezhub with PostgreSQL configuration:

Start mezhub with PostgreSQL bash
MEZITE_CLUSTER_NAME=my-cluster \
MEZITE_DB_DRIVER=postgres \
MEZITE_DB_HOST=localhost \
MEZITE_DB_PORT=5432 \
MEZITE_DB_USER=mezite \
MEZITE_DB_PASSWORD=mezite \
MEZITE_DB_NAME=mezite \
MEZITE_DB_SSLMODE=disable \
MEZITE_ADMIN_PASSWORD='S3cureP@ssw0rd' \
MEZITE_AUTH_H2C=true \
mezhub

# You should see output like:
# {"level":"info","msg":"starting mezhub","cluster":"my-cluster"}
# {"level":"info","msg":"database connected"}
# {"level":"info","msg":"migrations applied"}
# {"level":"info","msg":"certificate authorities initialized"}
# {"level":"info","msg":"default admin user created"}
# {"level":"info","msg":"gRPC auth server listening","addr":"0.0.0.0:3025"}
# {"level":"info","msg":"HTTPS proxy listener started","addr":"0.0.0.0:3080"}
# {"level":"info","msg":"SSH proxy listener started","addr":"0.0.0.0:3023"}
# {"level":"info","msg":"tunnel listener started","addr":"0.0.0.0:3024"}

Leave this terminal running (or add & to background the process). Open a new terminal for the remaining steps.

You can also use a config file: mezhub --config=mezite.yaml. See the Configuration Reference for details.

Step 3: Log In with msh

The msh client authenticates against the proxy, receives a short-lived SSH certificate, and stores it locally. The --insecure flag skips TLS verification for local development.

Client login bash
msh login --proxy=localhost:3080 --user=admin --password='S3cureP@ssw0rd' --insecure

# Output:
# Logged in as admin
# Roles:       admin
# Valid until: 2026-03-31T04:00:00Z

Step 4: Add a Node

To enroll a remote machine, install the mezd binary on it and join it to the cluster. First, generate a join token from the server using mezctl.

mezctl needs an auth token. Log in first, then export the token:

Authenticate mezctl and create a join token bash
# Log in and save the session token
export MEZITE_AUTH_TOKEN=$(mezctl --insecure login --username=admin --password='S3cureP@ssw0rd')

# Create a join token for the node agent
mezctl --insecure tokens create --type=static --roles=node --ttl=1h

# Output:
# Token: d4f8a2e1-7b3c-4d9e-a5f6-1234567890ab
# Valid for: 1h
# Use this token to join a node to the cluster.

On the target node, install mezd and start it with the token:

Start the agent on the target node bash
# Install mezd on the target node
curl -fsSL https://releases.mezite.com/latest/mezite-linux-amd64.tar.gz \
  | tar -xz -C /usr/local/bin/ mezd

# Start the agent, pointing it at your proxy's tunnel address.
MEZITE_JOIN_TOKEN=d4f8a2e1-7b3c-4d9e-a5f6-1234567890ab \
MEZITE_AUTH_ADDR=your-server:3025 \
MEZITE_PROXY_ADDR=your-server:3024 \
mezd start

# Output:
# {"level":"info","msg":"joined cluster","cluster":"my-cluster","node":"webserver-01"}
# {"level":"info","msg":"reverse tunnel established","proxy":"your-server:3024"}

Step 5: SSH to the Node

With the agent running and connected, you can now SSH through the Mezite proxy.

SSH through Mezite bash
# List available nodes
msh ls --insecure

# Output:
# Node Name      Address          Labels
# -------------- ---------------- ----------------
# localhost       127.0.0.1        env=local
# webserver-01   192.168.1.50     env=staging

# SSH to a node
msh ssh --login=root webserver-01

# You are now connected through the Mezite proxy.
# This session is being recorded for audit.
webserver-01 $

What Just Happened?

Here is the full certificate flow you just exercised:

  1. mezhub started with both Auth and Proxy services. On first boot it ran database migrations and generated a User CA and Host CA keypair (Ed25519), storing them encrypted in the database (SQLite or PostgreSQL).
  2. msh login authenticated against the Auth service via the Proxy, received a short-lived SSH certificate signed by the User CA, and saved it to ~/.msh/keys. The certificate encodes the user's identity, roles, and allowed principals.
  3. mezd used its join token to register with the Auth service, received a host certificate signed by the Host CA, and established a reverse tunnel to the Proxy on port 3024.
  4. msh ssh opened an SSH connection to the Proxy on port 3023. The Proxy verified the user's certificate against the User CA, resolved the target node, and forwarded the connection through the agent's reverse tunnel. The agent verified the user's certificate and started the SSH session. The session was recorded and an audit event was written to the database.
Certificate trust chain text
User CA (Ed25519)                    Host CA (Ed25519)
    │                                       │
    ▼                                       ▼
User Cert                              Host Cert
  identity: admin                        host: webserver-01
  roles: [admin]                         cluster: my-cluster
  principals: [root, admin]              valid: 24h
  valid: 12h                                │
    │                                       │
    │  presented to ──▶ Agent           presented to ──▶ msh
    │  (agent trusts User CA)           (msh trusts Host CA)
    ▼                                       ▼
Mutual verification: both sides reject expired, revoked, or unknown certs

Next Steps

  • SSH Access Guide — Deep dive into SSH certificate authentication, session recording, and advanced SSH features.
  • RBAC Guide — Create roles with fine-grained label-based permissions and deny rules.
  • SSO Guide — Configure OIDC, SAML, LDAP, or GitHub OAuth for enterprise authentication.
  • Audit & Recording — Query audit logs and replay SSH sessions.
  • Configuration Reference — Tune session TTLs, logging, TLS, and more.
  • Systemd Deployment — Run Mezite as a system service in production.