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:
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:
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):
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:
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.
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:
# 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:
# 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.
# 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:
- 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).
- 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. - 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.
- 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.
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.