Agent Identity (mezd identity)
Status: Available — The mezd identity daemon
is implemented and working. Agent Identity CRUD, one-time bootstrap tokens,
automatic certificate renewal, generation rotation, and agent identity locking
are all functional.
mezd identity provides agent identities for CI/CD pipelines,
monitoring systems, and automated services that need SSH access to Mezite-managed
nodes. It authenticates with a one-time bootstrap token, receives short-lived
SSH certificates from the User CA, and automatically renews them without human
interaction. This eliminates long-lived SSH keys and shared service accounts.
What mezd identity Does
mezd identity is a lightweight daemon that manages automated
certificate renewal for non-human identities. It:
- Authenticates to the Mezite auth service using a one-time join token.
- Receives a short-lived SSH certificate signed by the cluster's User CA.
- Writes the certificate and private key to a local directory.
- Automatically renews the certificate before it expires.
- Makes certificates available for other tools (SSH, SCP, Ansible, etc.) to use.
Use Cases
CI/CD Pipelines
Deploy code to production servers via SSH without storing static keys in CI secrets. Each pipeline run bootstraps a fresh certificate that expires after the job completes.
Monitoring and Observability
Monitoring agents that need SSH access to collect metrics or run health
checks can use
mezd identity for continuously renewed certificates.
Automated Deploys
Deployment orchestrators (Ansible, Chef, Puppet) that SSH into managed
nodes can authenticate via mezd identity certificates instead
of static SSH keys distributed across the fleet.
Configuration
mezd identity is configured via command-line flags or a configuration
file. The key parameters are:
| Parameter | Description |
|---|---|
auth-server | Address of the Mezite auth service (gRPC, port 3025; or :443 in single-port ALPN mode) |
token-file | Path to a file holding the one-time bootstrap token (mode 0600).
Prefer this, or the MEZITE_IDENTITY_TOKEN environment
variable, over the deprecated --token flag — a token
on the command line is visible in ps output and the
journal. |
destination-dir | Directory where certificates are written |
cert-ttl | Requested certificate TTL (default 1h) |
renewal-interval | How often to renew certificates (default 20m; must
be shorter than cert TTL) |
# Put the token in a root-owned file first — never on the command line.
install -m 0600 /dev/null /etc/mezite/identity-token
printf '%s' "$AGENT_IDENTITY_TOKEN" > /etc/mezite/identity-token
# Start the agent identity daemon for continuous cert renewal
mezd identity start \
--auth-server=mezite.example.com:3025 \
--token-file=/etc/mezite/identity-token \
--destination-dir=/var/lib/mezite/identity/certs \
--renewal-interval=30m # Bootstrap once and exit (for short-lived CI jobs). Pass the token
# through the environment so it never appears in the process list.
export MEZITE_IDENTITY_TOKEN="$AGENT_IDENTITY_TOKEN"
mezd identity start \
--auth-server=mezite.example.com:3025 \
--destination-dir=/tmp/mezite-certs \
--one-shot
Tokens are 64-character hex strings (32 random bytes) — no structured
prefix. Pass them via --token-file or
MEZITE_IDENTITY_TOKEN, never via --token: that
flag is deprecated precisely because the value leaks into ps
output and the systemd journal. Never log the token.
Output Files
After bootstrapping, mezd identity writes the following files
to the destination directory:
ssh_key— SSH private key (Ed25519)-
ssh_cert— SSH certificate signed by the User CA -
x509_cert.pem— X.509 certificate signed by the User CA -
x509_key.pem— X.509 private key (ECDSA P-256) -
cert_serial— Serial number of the issued SSH certificate -
ssh_known_hosts— Host CA public key for verifying node host certificates
# Use the agent identity-issued SSH cert with the OpenSSH client. The cert and key
# pair is what counts; ssh_known_hosts gives the OpenSSH client the
# Mezite host CA so it can verify node host certs.
ssh -i /var/lib/mezite/identity/certs/ssh_key \
-o CertificateFile=/var/lib/mezite/identity/certs/ssh_cert \
-o UserKnownHostsFile=/var/lib/mezite/identity/certs/ssh_known_hosts \
deploy@web-server-01 How It Differs from Human Auth
mezd identity is designed for non-interactive, long-running use.
The key differences from human authentication (msh login)
are:
| Aspect | Human (msh login) | Agent Identity (mezd identity) |
|---|---|---|
| Authentication | Password, SSO, or MFA | One-time join token |
| Lifetime | Single session (hours) | Long-lived daemon (days/months) |
| Renewal | Manual re-login | Automatic, continuous |
| Certificate TTL | Matches session TTL | Short (30m-1h), renewed frequently |
| Interactive | Yes (browser, terminal) | No (headless, unattended) |
| RBAC | User roles | Agent identity-specific roles (least privilege) |
Admin Setup
Step 1: Create an Agent Identity Role
Define a role scoped to exactly the nodes and logins the agent identity needs. Follow the principle of least privilege.
{
"metadata": {
"name": "ci-deployer",
"description": "CI/CD deploy pipeline SSH access"
},
"spec": {
"options": { "max_session_ttl": "1h" },
"allow": {
"node_labels": { "env": ["staging", "production"] },
"logins": ["deploy"]
},
"deny": {
"logins": ["root"]
}
}
} Step 2: Create the Agent Identity
# Create an agent identity with mezctl
mezctl agent-identities add --name=github-deploy --roles=ci-deployer --token-ttl=1h
# Output:
# Agent identity "github-deploy" created.
# Roles: [ci-deployer]
# Token: 8f3a2b1c9d4e5f607182930445566778899aabbccddeeff0011223344556677
#
# Start the agent identity daemon with:
# mezd identity start --auth-server=<fqdn>:443 --token-file=<path> --destination-dir=/var/lib/mezite/identity
#
# This token can only be used once. Step 3: Run in Your Pipeline
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Mezite tools
run: |
# Pin the version in automation so a new release cannot change
# what this pipeline installs.
curl -fsSL https://github.com/leonardaustin/mezite/releases/download/v0.2.24/mezite-linux-amd64.tar.gz \
| tar -xz -C /usr/local/bin/ mezd msh
- name: Bootstrap certificates
env:
# Passed through the environment, not as a flag — a --token
# argument is visible in the runner's process list.
MEZITE_IDENTITY_TOKEN: ${{ secrets.MEZITE_AGENT_IDENTITY_TOKEN }}
run: |
mezd identity start \
--auth-server=mezite.example.com:3025 \
--destination-dir=/tmp/mezite-certs \
--one-shot
- name: Deploy via SSH
run: |
ssh -i /tmp/mezite-certs/ssh_key \
-o CertificateFile=/tmp/mezite-certs/ssh_cert \
-o UserKnownHostsFile=/tmp/mezite-certs/ssh_known_hosts \
deploy@web-server-01 ./deploy.sh Managing Agent Identities
# List all agent identities
mezctl agent-identities ls
# View agent identity details (status, roles, generation, last seen)
mezctl agent-identities status github-deploy
# Remove an agent identity
mezctl agent-identities rm github-deploy
# To rotate credentials, delete the agent identity and re-add it — the previous
# token (or any renewal-state) becomes invalid the moment the agent identity is
# deleted, and the new `agent-identities add` invocation prints a fresh one-time
# token. Next Steps
- RBAC Configuration — Define least-privilege roles for agent identities.
- SSH Access — Understand the SSH connection flow that agent identities use.
- Audit Logging — Monitor agent identity activity in audit logs.