Systemd Deployment

For bare-metal or VM deployments, run mezhub and mezd under systemd. The release tarball ships binaries only, so create the unit files below on the host.

mezhub.service

The main server unit runs the combined auth + proxy services. The server is configured from a YAML file (--config), not from environment variables — see Configuration for the full reference.

/etc/systemd/system/mezhub.service (SQLite — the default) ini
[Unit]
Description=Mezite Server (Auth + Proxy)
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
ExecStart=/usr/local/bin/mezhub --config=/etc/mezite/mezite.yaml
Restart=always
RestartSec=5
LimitNOFILE=65535

NoNewPrivileges=yes
ProtectSystem=strict
ReadWritePaths=/var/lib/mezite
PrivateTmp=yes

[Install]
WantedBy=multi-user.target

The default database backend is SQLite (zero external dependencies), so the unit above does not order against any database service. If you are running PostgreSQL on the same host, add postgresql.service to the After= line so mezhub waits for the database to be up:

PostgreSQL-on-same-host variant — just the [Unit] section ini
[Unit]
Description=Mezite Server (Auth + Proxy)
After=network-online.target postgresql.service
Wants=network-online.target postgresql.service

mezd.service

The agent unit runs on each SSH node. mezd is configured entirely via environment variables — there is no agent config file. Set the variables in an EnvironmentFile consumed by systemd.

/etc/systemd/system/mezd.service ini
[Unit]
Description=Mezite Agent
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
ExecStart=/usr/local/bin/mezd start
Restart=always
RestartSec=5
LimitNOFILE=65535
EnvironmentFile=-/etc/mezite/agent.env

# Note: NoNewPrivileges and ProtectSystem=strict are intentionally omitted.
# The agent needs root privilege transitions for host user provisioning
# (useradd/userdel) and must write to /etc/passwd, /etc/shadow, /etc/group,
# /home/, and /etc/sudoers.d/.
PrivateTmp=yes

[Install]
WantedBy=multi-user.target

Environment File for mezd

Place the agent's environment file at /etc/mezite/agent.env. Required keys: MEZITE_AUTH_ADDR, MEZITE_PROXY_ADDR, and MEZITE_JOIN_TOKEN (only on first start — once the agent has joined and persisted its identity to MEZITE_DATA_DIR, the token is no longer required for reconnects). Keep the agent's data dir separate from the server's (/var/lib/mezd vs /var/lib/mezite) when both run on the same host.

/etc/mezite/agent.env bash
MEZITE_AUTH_ADDR=mezite.example.com:3025
MEZITE_PROXY_ADDR=mezite.example.com:3024
MEZITE_JOIN_TOKEN=<join-token>
MEZITE_DATA_DIR=/var/lib/mezd
MEZITE_NODE_NAME=web-server-01
MEZITE_NODE_LABELS=env=production,role=web

mezd start takes no command-line flags — every knob is an environment variable, so the EnvironmentFile is the only place you configure the agent.

Combined Mode: Agent Plus Identity

One mezd process can serve both node SSH access and agent identity, sharing a single gRPC connection to the auth server. Add these to the same agent.env — there is no separate unit to install, and again no flags:

/etc/mezite/agent.env — combined mode additions bash
MEZITE_IDENTITY_DIR=/var/lib/mezite/identity
MEZITE_IDENTITY_TOKEN=<agent-identity-token>

# Optional: SPIFFE Workload API socket for workloads on this node
MEZITE_WORKLOAD_SOCKET=/run/mezite/workload.sock

# Optional: certificate TTL and renewal cadence (defaults shown)
MEZITE_IDENTITY_TTL=1h
MEZITE_IDENTITY_RENEWAL_INTERVAL=20m

Keep agent.env at mode 0600 — it holds the join token and the identity token. To run the identity daemon on a host that is not a Mezite node, install mezd-identity.service instead and drive it with mezd identity start.

mezite.yaml — minimal mezhub config

A minimal SQLite-backed config that listens on the default ports. See Configuration for every option, and Reverse Proxy for the LB posture.

/etc/mezite/mezite.yaml yaml
cluster_name: my-cluster
data_dir: /var/lib/mezite

database:
  driver: sqlite               # or: postgres
  url: /var/lib/mezite/mezhub.db

auth:
  enabled: true
  listen_addr: 0.0.0.0:3025

proxy:
  enabled: true
  listen_addr: 0.0.0.0:3080
  ssh_listen_addr: 0.0.0.0:3023
  tunnel_listen_addr: 0.0.0.0:3024
  public_addr: mezite.example.com:3080

log:
  level: info
  format: json

Installation

Install and enable services bash
# Download and unpack the release tarball (linux-amd64 shown;
# use linux-arm64 on ARM). The archive is flat and contains
# mezhub, mezd, msh, mezctl, LICENSE and README.md.
curl -fsSL -o mezite.tar.gz \
  https://github.com/leonardaustin/mezite/releases/latest/download/mezite-linux-amd64.tar.gz
tar -xzf mezite.tar.gz

# Install only the binaries this host needs
sudo install -m 0755 mezhub /usr/local/bin/mezhub   # server host
sudo install -m 0755 mezd   /usr/local/bin/mezd     # SSH node

# Write the unit files above to /etc/systemd/system/

# Create config + data directories
sudo mkdir -p /etc/mezite /var/lib/mezite /var/lib/mezd

# Drop your mezite.yaml and agent.env into /etc/mezite/, then enable
sudo systemctl daemon-reload
sudo systemctl enable --now mezhub
sudo systemctl enable --now mezd

Log Management

View logs with journalctl:

Viewing logs bash
# Follow mezhub logs
journalctl -u mezhub -f

# View agent logs from the last hour
journalctl -u mezd --since "1 hour ago"

# Filter by priority
journalctl -u mezhub -p err