Approving + managing devices
After enrolment, machines appear in your dashboard's Machines view. This guide covers the admin actions: approve, rename, tag, quarantine, wipe, delete — all via dashboard, CLI, or REST API.
The approval gate
Orgs can enable approval required under Settings → Admin → Security. When enabled:
- Newly enrolled machines go into
pendingstatus - They receive a tailnet IP but ACL evaluation denies all connections
- An admin must explicitly approve before the machine becomes
online - An email + WebSocket notification fires on every new pending machine
Approval gate is off by default. Turn it on for high-sensitivity environments.
Approve
Machines → filter by status: pending
→ select machine
→ click "Approve"
→ (optional) set tags, hostname
→ confirm Rename
name, not new_name.
$ curl https://login.quickztna.com/api/machine-admin \
-H "Authorization: Bearer $QZ_API_KEY" \
-d '{
"action": "rename",
"org_id": "org_9fX2kR",
"machine_id": "m_Pq7r2w",
"name": "laptop-alex-new"
}' The machine's MagicDNS name changes immediately to laptop-alex-new.<org>.zt.net. Old name stops resolving after the next heartbeat (within 60 seconds).
Update tags
Tags are labels used in ACL rules. Change them at any time without restarting the tunnel.
$ ztna set --tags tag:laptop,tag:eng,tag:prod
✓ Tags updated: tag:laptop, tag:eng, tag:prod
✓ Control plane notified Quarantine
Quarantine isolates a device without deleting it. Tailnet IP stays allocated; ACL evaluation denies all traffic. Used for:
- Posture failure (auto-applied)
- Suspicious activity pending investigation
- Offboarding — user has left, device unreturned
$ curl https://login.quickztna.com/api/machine-admin \
-H "Authorization: Bearer $QZ_API_KEY" \
-d '{
"action": "quarantine",
"org_id": "org_9fX2kR",
"machine_id": "m_Pq7r2w",
"reason": "Posture failure: disk encryption disabled"
}' To un-quarantine: re-run approve. Audit log shows who quarantined, when, why, and who approved recovery.
Remote wipe
Delivered via the next heartbeat. If the device is offline, the command queues — it executes when the device comes back online.
$ curl https://login.quickztna.com/api/machine-admin \
-H "Authorization: Bearer $QZ_API_KEY" \
-d '{
"action": "wipe_device",
"org_id": "org_9fX2kR",
"machine_id": "m_Pq7r2w",
"confirm": "WIPE-m_Pq7r2w"
}' The confirm field is a dead-man's switch — it must match the literal string WIPE-<machine_id>. Prevents accidental bulk wipes.
Lock device (reversible)
Temporarily disable a device without wiping it. Tunnel drops; machine cannot reconnect until unlocked.
$ curl https://login.quickztna.com/api/machine-admin \
-H "Authorization: Bearer $QZ_API_KEY" \
-d '{
"action": "lock_device",
"org_id": "org_9fX2kR",
"machine_id": "m_Pq7r2w"
}' Delete
Permanent. Removes the machine from inventory, releases its tailnet IP, invalidates its node_key. Audit log retained per policy.
$ ztna machine-admin delete --name old-server
✓ Machine old-server (100.64.1.88) deleted
Tailnet IP released · node_key invalidated · audit log retained 90d Bulk operations
For fleet-level actions (wipe all offline >30d, quarantine all non-compliant, delete ephemeral runners), use the REST API with a script. CRUD endpoints accept filter criteria:
$ curl https://login.quickztna.com/api/db/machines?action=update \
-X PATCH \
-H "Authorization: Bearer $QZ_API_KEY" \
-d '{
"status": "quarantined",
"_filters": [
{ "column": "org_id", "op": "=", "value": "org_9fX2kR" },
{ "column": "posture_verdict", "op": "=", "value": "non_compliant" }
]
}' Audit trail
Every action (approve, quarantine, rename, wipe, delete) writes to audit_logs with:
- Actor: user ID, email, IP
- Action + target machine ID
- Reason (if provided)
- Before/after state for diffs
- Timestamp (UTC)
Query via ztna audit list --days 7 or export via /api/export (not /api/export-data).
See also
- Posture policies — the auto-quarantine trigger
- ACL policies — tags you set here are referenced there
- API: machine-admin — full reference