Podman / Docker Deployment
Mezite ships container images and Podman Compose files for deploying the full stack with Podman (preferred) or Docker.
Building the Container Image
The repository's build/Containerfile produces an Alpine image with
all four binaries (mezhub, mezd,
msh, mezctl) and exposes the four standard
ports. The image's ENTRYPOINT is mezhub.
podman build -t mezite:latest -f build/Containerfile . Compose Deployment
The repository's podman-compose.yml is the source of truth for
the full E2E stack (PostgreSQL, mezhub, agents, mock providers, S3, etc.). For
a minimal production-style deployment, a much shorter Compose file is sufficient.
The example below pairs mezhub with PostgreSQL; pass
MEZITE_DB_DRIVER=sqlite (and drop the postgres service) for a zero-dependency
setup.
services:
postgres:
image: docker.io/library/postgres:16-alpine
environment:
POSTGRES_USER: mezite
POSTGRES_PASSWORD: mezite
POSTGRES_DB: mezite
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U mezite"]
interval: 2s
retries: 10
mezhub:
image: mezite:latest
depends_on:
postgres:
condition: service_healthy
environment:
MEZITE_CLUSTER_NAME: my-cluster
MEZITE_DB_DRIVER: postgres
MEZITE_DB_HOST: postgres
MEZITE_DB_PORT: "5432"
MEZITE_DB_USER: mezite
MEZITE_DB_PASSWORD: mezite
MEZITE_DB_NAME: mezite
MEZITE_DB_SSLMODE: disable
MEZITE_LOG_LEVEL: info
MEZITE_PROXY_PUBLIC_ADDR: mezite.example.com:3080
MEZITE_CA_KEY_PASSPHRASE: change-me-in-production
ports:
- "3025:3025" # Auth gRPC
- "3080:3080" # Proxy HTTPS / Web UI
- "3023:3023" # SSH proxy
- "3024:3024" # Agent reverse tunnel
healthcheck:
test: ["CMD-SHELL", "/usr/local/bin/mezhub healthcheck"]
interval: 2s
retries: 15
volumes:
pgdata: podman-compose -f compose.yml up -d Running with podman run
podman run -d --name mezhub \
-e MEZITE_CLUSTER_NAME=my-cluster \
-e MEZITE_DB_DRIVER=postgres \
-e MEZITE_DB_HOST=host -e MEZITE_DB_PORT=5432 \
-e MEZITE_DB_USER=mezite -e MEZITE_DB_PASSWORD=mezite \
-e MEZITE_DB_NAME=mezite -e MEZITE_DB_SSLMODE=disable \
-e MEZITE_CA_KEY_PASSPHRASE=change-me \
-p 3025:3025 -p 3080:3080 -p 3023:3023 -p 3024:3024 \
mezite:latest Environment Variables
The mezhub server reads configuration in this order of precedence (highest
wins): explicit environment variables, then the YAML config file (--config), then built-in defaults. The variables below are the env-var bindings
that exist today; for keys without an env binding, use the YAML file. See Configuration
for the full reference.
| Variable | Description | Default |
|---|---|---|
MEZITE_CLUSTER_NAME | Cluster identifier (also used as the trust domain) | mezite |
MEZITE_DB_DRIVER | Database backend: sqlite or postgres | sqlite |
MEZITE_DB_URL | Connection string (overrides the host/port/user/password fields) | — |
MEZITE_DB_HOST | PostgreSQL host | localhost |
MEZITE_DB_PORT | PostgreSQL port | 5432 |
MEZITE_DB_USER | PostgreSQL user | mezite |
MEZITE_DB_PASSWORD | PostgreSQL password | (empty) |
MEZITE_DB_NAME | PostgreSQL database name | mezite |
MEZITE_DB_SSLMODE | PostgreSQL SSL mode | require |
MEZITE_LOG_LEVEL | Log level (debug, info, warn, error) | info |
MEZITE_LOG_FORMAT | Log format (json or console) | json |
MEZITE_PROXY_PUBLIC_ADDR | Public address clients reach the proxy at (used for WebAuthn RPID and host/SSH cert principals) | (empty) |
MEZITE_OIDC_ISSUER_URL | OIDC issuer URL advertised at /.well-known/openid-configuration. Explicit — never inferred from the Host header or
public_addr. | (empty) |
MEZITE_CA_KEY_PASSPHRASE | Passphrase for the software-encrypted CA signing keys | (empty — required for production) |
MEZITE_SINGLE_PORT | Multiplex all protocols on the proxy HTTPS port via ALPN | false |
MEZITE_GRPC_ALLOW_HTTP | Enable h2c on the gRPC auth port (for reverse-proxy deployments) | false |
MEZITE_AUTH_H2C | Disable TLS on the gRPC auth port entirely (LB terminates TLS) | (unset) |
Listen addresses (auth.listen_addr,
proxy.listen_addr, proxy.ssh_listen_addr,
proxy.tunnel_listen_addr) are configured via the YAML file —
they do not have env-var bindings and default to 0.0.0.0 on ports
3025/3080/3023/3024 respectively.
Health Checks
The proxy serves a liveness endpoint at /healthz and a readiness
endpoint at /readyz on the HTTPS port. The
mezhub healthcheck subcommand wraps the same check and is what
the bundled podman-compose.yml uses.
healthcheck:
test: ["CMD-SHELL", "/usr/local/bin/mezhub healthcheck"]
interval: 10s
timeout: 5s
retries: 3