Skip to content

Servers API

Servers and agents.

37 operations. Every call needs a session cookie or an Authorization: Bearer nct_… token unless marked Public. Conventions, errors and scopes

GET/geo/maxmind

Whether the team has a MaxMind GeoLite2 account on file

The licence key is write-only. serversUsing counts the team's servers that currently use the MaxMind source.

Response 200 · OK · application/json
GeoCredentialsStatus
  • accountIdstringrequired
    MaxMind account ID; empty when none is stored
  • configuredbooleanrequired
  • serversUsinginteger (int64)required
  • updatedAtstring (date-time) | nullrequired
Errors
  • 401Unauthorized
  • 403Forbidden
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

PUT/geo/maxmind

Store the team's MaxMind account ID and licence key

The key is sealed with the instance secret key. Servers on the MaxMind source receive it with their next reconcile (sent immediately to online agents, never persisted in a command).

Request body · application/json · required
SetGeoCredentialsInputBody
  • accountIdstringrequired
    Numeric MaxMind account ID
  • licenseKeystringrequired
    MaxMind licence key; stored encrypted, never returned
Response 200 · OK · application/json
GeoCredentialsStatus
  • accountIdstringrequired
    MaxMind account ID; empty when none is stored
  • configuredbooleanrequired
  • serversUsinginteger (int64)required
  • updatedAtstring (date-time) | nullrequired
Errors
  • 401Unauthorized
  • 403Forbidden
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

DELETE/geo/maxmind

Remove the team's MaxMind account

Refused with 409 maxmind_in_use while a server still uses the MaxMind source.

Response 200 · OK · application/json
GeoCredentialsStatus
  • accountIdstringrequired
    MaxMind account ID; empty when none is stored
  • configuredbooleanrequired
  • serversUsinginteger (int64)required
  • updatedAtstring (date-time) | nullrequired
Errors
  • 401Unauthorized
  • 403Forbidden
  • 409Conflictmaxmind_in_use
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

GET/instance/upgrade

Control-plane version, agent version skew per server and the pre-upgrade backup

The version the control plane runs, whether agents behind it upgrade themselves when they connect, the outcome of the backup the control plane took before its last upgrade, and for every server how its agent's version compares (behind, current, ahead, unknown), whether it can be upgraded now (and if not, why) and the state of its latest upgrade.

Response 200 · OK · application/json
InstanceUpgradeView
  • agentAutoUpgradebooleanrequired
    Upgrade an agent that is behind the control plane as soon as it connects. Default on.
  • behindinteger (int64)required
    Servers whose agent is behind the control plane.
  • controlPlaneVersionstringrequired
  • PreUpgradeBackupView
  • ServerUpgradeView[] | nullrequired
  • upgradableinteger (int64)required
    Servers whose agent can be upgraded now.
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

PATCH/instance/upgrade

Switch the automatic agent upgrade

Needs the servers:write scope and the instance admin (the first account). Audited.

Request body · application/json · required
PatchInputBody
  • agentAutoUpgradeboolean
    Upgrade an agent that is behind the control plane when it connects.
Response 200 · OK · application/json
InstanceUpgradeView
  • agentAutoUpgradebooleanrequired
    Upgrade an agent that is behind the control plane as soon as it connects. Default on.
  • behindinteger (int64)required
    Servers whose agent is behind the control plane.
  • controlPlaneVersionstringrequired
  • PreUpgradeBackupView
  • ServerUpgradeView[] | nullrequired
  • upgradableinteger (int64)required
    Servers whose agent can be upgraded now.
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

GET/servers

List servers

ParameterInTypeDescription
cursorquerystringOpaque cursor from a previous page's nextCursor
limitqueryinteger (int64)Page size (default 50, max 200)
Response 200 · OK · application/json
PageServer
  • Server[] | nullrequired
  • nextCursorstring
    Present when more items exist
Errors
  • 401Unauthorized
  • 403Forbidden
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

GET/servers/{serverId}

Get a server

ParameterInTypeDescription
serverIdrequiredpathstring
Response 200 · OK · application/json
Server
  • acceptWorkloadsbooleanrequired
    Whether services may be scheduled on this server. Turning it off keeps what already runs here and refuses new placements and moves.
  • acmeEmailstring | nullrequired
  • agentVersionstring | nullrequired
  • baseDomainstring | nullrequired
  • buildAllowEmulationbooleanrequired
    Allow building for another CPU architecture through emulation (slow); needs the agent to report emulation for the platform
  • buildAllowPreviewsbooleanrequired
    Allow pull request previews (untrusted code) to build here; off by default
  • buildEnabledbooleanrequired
    The server builds images for other servers and pushes them to a registry (the Builds or Both role). Independent of acceptWorkloads.
  • buildMaxConcurrentinteger (int64)required
    Builds that run at the same time; more queue on the control plane
  • composeVersionstringrequired
    Docker Compose plugin version the agent reported, empty when it has none
  • controlPlanebooleanrequired
    The host the installer put the control plane on; its proxy serves the dashboard
  • createdAtstring (date-time)required
  • diskAlertbooleanrequired
    True while the root filesystem is at or above the threshold
  • diskAlertThresholdPercentinteger (int64)required
    Root filesystem usage that raises the disk alert (50-99)
  • drainMessagestringrequired
    Why the last drain failed or was canceled, empty otherwise
  • drainStartedAtstring (date-time) | nullrequired
  • drainStateenum: none | draining | drained | failedrequired
    Evacuation state; draining and drained servers accept no new services
  • Factsrequired
  • geoEnabledbooleanrequired
    Count where requests come from (country, and city at the city level) from the client IP; IPs are never stored
  • geoLevelenum: country | cityrequired
    country needs a ~8 MB database on the server, city ~130 MB
  • geoRefreshDaysinteger (int64)required
    Check for a newer database every N days (1-90)
  • geoSourceenum: dbip | maxmindrequired
    dbip = DB-IP Lite (CC BY 4.0, no key); maxmind = MaxMind GeoLite2 with the team's account
  • idstringrequired
  • lastSeenAtstring (date-time) | nullrequired
  • Latestrequired
  • metricsRetentionDaysinteger (int64)required
    How long resource metric history is kept (1-90)
  • namestringrequired
  • ServerPatchSummaryrequired
  • protocolVersioninteger (int32) | nullrequired
  • Proxyrequired
  • publicIpstring | nullrequired
  • serviceCountinteger (int64)required
  • statusenum: pending | online | offline | revokedrequired
  • trafficAnalyticsEnabledbooleanrequired
    Aggregate Traefik access logs into traffic analytics
  • trafficDailyRetentionDaysinteger (int64)required
    Daily traffic history (7-365 days)
  • trafficHourlyRetentionDaysinteger (int64)required
    Hourly traffic history (2-90 days)
  • ServerTunnelSummaryrequired
  • unrestrictedbooleanrequired
    An instance admin made this server unrestricted: stacks and services on it may use privileged mode, host networking, devices, GPUs, a runtime, the host PID namespace, unconfined seccomp or AppArmor, NET_ADMIN, SYS_ADMIN, the Docker socket and host bind mounts
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

PATCH/servers/{serverId}

Update a server's name, host settings, retention or alert settings

ParameterInTypeDescription
serverIdrequiredpathstring
Request body · application/json · required
UpdateServerInputBody
  • acceptWorkloadsboolean
    false stops new services being scheduled on this server (what already runs here keeps running); default true
  • acmeEmailstring
    Empty string clears
  • baseDomainstring
    Empty string clears
  • buildAllowEmulationboolean
    Allow cross-architecture builds through emulation (default off)
  • buildAllowPreviewsboolean
    Let pull request previews build on this server (default off: previews build on their own server)
  • buildEnabledboolean
    Make the server a build server: it builds git sources for other servers and pushes the images to a registry. Combine with acceptWorkloads: Deployments (true/false), Builds (false/true) or Both (true/true).
  • buildMaxConcurrentinteger (int64)
    Parallel builds on this server (default 2); more queue on the control plane
  • diskAlertThresholdPercentinteger (int64)
    Disk usage percent that raises the disk alert (default 80)
  • geoEnabledboolean
    Count where requests come from (default on); needs traffic analytics
  • geoLevelenum: country | city
    country (default, ~8 MB database) or city (~130 MB)
  • geoRefreshDaysinteger (int64)
    Check for a newer database every N days (default 7)
  • geoSourceenum: dbip | maxmind
    dbip = DB-IP Lite (default, no key); maxmind = MaxMind GeoLite2 (needs the team's account, see PUT /geo/maxmind)
  • metricsRetentionDaysinteger (int64)
    Days of resource metric history (default 7)
  • namestring
  • publicIpstring
    Empty string clears
  • trafficAnalyticsEnabledboolean
    Turns Traefik access-log analytics on or off (default on)
  • trafficDailyRetentionDaysinteger (int64)
    Days of daily traffic history (default 90)
  • trafficHourlyRetentionDaysinteger (int64)
    Days of hourly traffic history (default 7)
Response 200 · OK · application/json
Server
  • acceptWorkloadsbooleanrequired
    Whether services may be scheduled on this server. Turning it off keeps what already runs here and refuses new placements and moves.
  • acmeEmailstring | nullrequired
  • agentVersionstring | nullrequired
  • baseDomainstring | nullrequired
  • buildAllowEmulationbooleanrequired
    Allow building for another CPU architecture through emulation (slow); needs the agent to report emulation for the platform
  • buildAllowPreviewsbooleanrequired
    Allow pull request previews (untrusted code) to build here; off by default
  • buildEnabledbooleanrequired
    The server builds images for other servers and pushes them to a registry (the Builds or Both role). Independent of acceptWorkloads.
  • buildMaxConcurrentinteger (int64)required
    Builds that run at the same time; more queue on the control plane
  • composeVersionstringrequired
    Docker Compose plugin version the agent reported, empty when it has none
  • controlPlanebooleanrequired
    The host the installer put the control plane on; its proxy serves the dashboard
  • createdAtstring (date-time)required
  • diskAlertbooleanrequired
    True while the root filesystem is at or above the threshold
  • diskAlertThresholdPercentinteger (int64)required
    Root filesystem usage that raises the disk alert (50-99)
  • drainMessagestringrequired
    Why the last drain failed or was canceled, empty otherwise
  • drainStartedAtstring (date-time) | nullrequired
  • drainStateenum: none | draining | drained | failedrequired
    Evacuation state; draining and drained servers accept no new services
  • Factsrequired
  • geoEnabledbooleanrequired
    Count where requests come from (country, and city at the city level) from the client IP; IPs are never stored
  • geoLevelenum: country | cityrequired
    country needs a ~8 MB database on the server, city ~130 MB
  • geoRefreshDaysinteger (int64)required
    Check for a newer database every N days (1-90)
  • geoSourceenum: dbip | maxmindrequired
    dbip = DB-IP Lite (CC BY 4.0, no key); maxmind = MaxMind GeoLite2 with the team's account
  • idstringrequired
  • lastSeenAtstring (date-time) | nullrequired
  • Latestrequired
  • metricsRetentionDaysinteger (int64)required
    How long resource metric history is kept (1-90)
  • namestringrequired
  • ServerPatchSummaryrequired
  • protocolVersioninteger (int32) | nullrequired
  • Proxyrequired
  • publicIpstring | nullrequired
  • serviceCountinteger (int64)required
  • statusenum: pending | online | offline | revokedrequired
  • trafficAnalyticsEnabledbooleanrequired
    Aggregate Traefik access logs into traffic analytics
  • trafficDailyRetentionDaysinteger (int64)required
    Daily traffic history (7-365 days)
  • trafficHourlyRetentionDaysinteger (int64)required
    Hourly traffic history (2-90 days)
  • ServerTunnelSummaryrequired
  • unrestrictedbooleanrequired
    An instance admin made this server unrestricted: stacks and services on it may use privileged mode, host networking, devices, GPUs, a runtime, the host PID namespace, unconfined seccomp or AppArmor, NET_ADMIN, SYS_ADMIN, the Docker socket and host bind mounts
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

POST/servers/{serverId}/agent-upgrade

Upgrade one server's agent to the control plane's version

The agent downloads the binary from this control plane, checks its SHA-256 against the one in the command, replaces itself, restarts when its running work is done and rolls back if the new binary does not start. Needs the Owner or Admin role; audited. 409 server_offline, agent_current, agent_newer or upgrade_in_progress; 422 agent_predates_upgrade (re-run the agent installer once) or no_agent_binary.

ParameterInTypeDescription
Idempotency-KeyheaderstringClient-chosen key (<=255 chars). A retry with the same key replays the original response for 24 hours.
serverIdrequiredpathstring
Request body · application/json · required
ServerInputBody
  • forceboolean
    Install a version this agent rolled back before.
Response 202 · Accepted · application/json
ServerUpgradeView
  • agentVersionstring
  • canSelfUpgradebooleanrequired
  • finishedAtstring (date-time)
  • messagestring
  • namestringrequired
  • reasonstring
    Why the agent cannot be upgraded now.
  • requestedAtstring (date-time)
  • serverIdstringrequired
  • skewenum: current | behind | ahead | unknownrequired
    The agent against the control plane: behind (older), ahead (newer), current, or unknown when a version is not a release version.
  • stateenum: queued | restarting | succeeded | failed
  • statusstringrequired
    pending, online, offline or revoked.
  • targetVersionstring
  • triggerenum: auto | manual
  • upgradablebooleanrequired
    The agent can be upgraded now.
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 409Conflictserver_offline
  • 422Unprocessable Entityagent_predates_upgrade
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

GET/servers/{serverId}/cleanup

Docker cleanup settings and history of a server

Whether the scheduled cleanup is on, when it runs next and the most recent runs with what each prune step removed. A cleanup removes dangling images, unused images older than unusedImageMinAgeHours (default 72), build cache older than buildCacheMinAgeDays (default 7) and unused NebulaCtrl networks, and optionally stopped containers NebulaCtrl does not manage. It never removes the current or a rollback-eligible release's image, a pinned infrastructure image, or any volume.

ParameterInTypeDescription
serverIdrequiredpathstring
Response 200 · OK · application/json
CleanupView
  • agentSupportedbooleanrequired
    The server's agent can run a cleanup
  • buildCacheMinAgeDaysinteger (int64)required
    Build cache older than this many days is pruned (default 7)
  • cronstringrequired
    The schedule as a 5-field cron expression, evaluated in UTC (default 0 4 * * *)
  • diskAlertbooleanrequired
    The disk alert is active now
  • diskAlertThresholdPercentinteger (int64)required
    The server's disk alert threshold, which starts the emergency cleanup when diskTriggerPercent is null
  • diskTriggerPercentinteger (int64) | nullrequired
    Disk usage (50-99) that starts an emergency cleanup; null follows the server's disk alert threshold
  • enabledbooleanrequired
    Scheduled and emergency cleanups run (default true)
  • nextRunAtstring (date-time) | nullrequired
    The next scheduled cleanup; null when cleanup is off
  • removeStoppedUnmanagedbooleanrequired
    Also remove stopped containers NebulaCtrl does not manage (default false)
  • runningbooleanrequired
    A cleanup is waiting for the agent or running
  • CleanupRun[]required
    The most recent runs, newest first
  • schedulestringrequired
    The schedule in words
  • unusedImageMinAgeHoursinteger (int64)required
    Unused images older than this are removed unless a release or the infrastructure needs them (default 72)
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

PUT/servers/{serverId}/cleanup

Change the Docker cleanup settings of a server

Needs the servers:write scope. cron sets the schedule (UTC), unusedImageMinAgeHours and buildCacheMinAgeDays the age limits and diskTriggerPercent the disk usage that starts an emergency run (omitted or 0: the server's disk alert threshold); omitted or 0 keeps each default. Turning the schedule off also turns off the emergency run; "Run cleanup now" still works. 422 validation_failed for a bad cron expression (or one that fires more often than every 15 minutes) or an out-of-range value.

ParameterInTypeDescription
serverIdrequiredpathstring
Request body · application/json · required
UpdateCleanupInputBody
  • buildCacheMinAgeDaysinteger (int64)
    Prune build cache older than this many days (1-365). 0 or omitted keeps the default, 7.
  • cronstring
    The schedule: a 5-field cron expression (or @daily, @weekly, ...) evaluated in UTC. Runs must be at least 15 minutes apart. Empty keeps the default, 0 4 * * *.
  • diskTriggerPercentinteger (int64)
    Start an emergency cleanup when disk usage reaches this percent (50-99). 0 or omitted follows the server's disk alert threshold.
  • enabledbooleanrequired
    Run the scheduled (daily, 04:00 UTC) and emergency cleanups
  • removeStoppedUnmanagedbooleanrequired
    Also remove stopped containers that NebulaCtrl does not manage. Their volumes are kept.
  • unusedImageMinAgeHoursinteger (int64)
    Remove unused images older than this many hours (1-8760). 0 or omitted keeps the default, 72.
Response 200 · OK · application/json
CleanupView
  • agentSupportedbooleanrequired
    The server's agent can run a cleanup
  • buildCacheMinAgeDaysinteger (int64)required
    Build cache older than this many days is pruned (default 7)
  • cronstringrequired
    The schedule as a 5-field cron expression, evaluated in UTC (default 0 4 * * *)
  • diskAlertbooleanrequired
    The disk alert is active now
  • diskAlertThresholdPercentinteger (int64)required
    The server's disk alert threshold, which starts the emergency cleanup when diskTriggerPercent is null
  • diskTriggerPercentinteger (int64) | nullrequired
    Disk usage (50-99) that starts an emergency cleanup; null follows the server's disk alert threshold
  • enabledbooleanrequired
    Scheduled and emergency cleanups run (default true)
  • nextRunAtstring (date-time) | nullrequired
    The next scheduled cleanup; null when cleanup is off
  • removeStoppedUnmanagedbooleanrequired
    Also remove stopped containers NebulaCtrl does not manage (default false)
  • runningbooleanrequired
    A cleanup is waiting for the agent or running
  • CleanupRun[]required
    The most recent runs, newest first
  • schedulestringrequired
    The schedule in words
  • unusedImageMinAgeHoursinteger (int64)required
    Unused images older than this are removed unless a release or the infrastructure needs them (default 72)
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 422Unprocessable Entityvalidation_failed
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

POST/servers/{serverId}/cleanup/runs

Run the Docker cleanup of a server now

Queues the same cleanup the schedule runs. The result (reclaimed bytes, items per step) appears in the server's cleanup history. 409 server_offline when the server is offline, 409 cleanup_running while one is in flight.

ParameterInTypeDescription
Idempotency-KeyheaderstringClient-chosen key (<=255 chars). A retry with the same key replays the original response for 24 hours.
serverIdrequiredpathstring
Response 202 · Accepted · application/json
CleanupRun
  • createdAtstring (date-time)required
  • errorstring
  • finishedAtstring (date-time) | nullrequired
  • idstringrequired
  • itemsinteger (int64)required
    Things removed: containers, images, networks or volumes
  • modeenum: standard | volumesrequired
    standard is the scheduled cleanup; volumes the explicit removal of unused volumes
  • reclaimedBytesinteger (int64)required
  • statusenum: pending | succeeded | failedrequired
  • CleanupStep[]required
    What each prune step did; empty until the agent reports
  • triggerenum: scheduled | emergency | manualrequired
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 409Conflictserver_offlinecleanup_running
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

POST/servers/{serverId}/cleanup/volumes

Remove unused Docker volumes of a server

Removes volumes that no container (running or stopped) mounts and that NebulaCtrl does not manage: anonymous volumes and volumes made outside NebulaCtrl. Volumes of NebulaCtrl services (nc-vol-*, or labeled as managed) are never removed. This deletes data and cannot be undone: confirm must be the server's name. The schedule never does this.

ParameterInTypeDescription
Idempotency-KeyheaderstringClient-chosen key (<=255 chars). A retry with the same key replays the original response for 24 hours.
serverIdrequiredpathstring
Request body · application/json · required
PruneVolumesInputBody
  • confirmstringrequired
    The server's name, typed to confirm
Response 202 · Accepted · application/json
CleanupRun
  • createdAtstring (date-time)required
  • errorstring
  • finishedAtstring (date-time) | nullrequired
  • idstringrequired
  • itemsinteger (int64)required
    Things removed: containers, images, networks or volumes
  • modeenum: standard | volumesrequired
    standard is the scheduled cleanup; volumes the explicit removal of unused volumes
  • reclaimedBytesinteger (int64)required
  • statusenum: pending | succeeded | failedrequired
  • CleanupStep[]required
    What each prune step did; empty until the agent reports
  • triggerenum: scheduled | emergency | manualrequired
Errors
  • 400Bad Request
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 409Conflict
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

GET/servers/{serverId}/hardening

Host hardening of a server: the Lynis index, the safe fixes and what is left

The Security tab: Lynis's hardening index from the latest audit, every curated safe fix with its state on the host (applied, already compliant, pending, unavailable), the findings that remain with an explanation and the commands to deal with them, and the history of runs. NebulaCtrl never offers a fix for SSH, the firewall or accounts.

ParameterInTypeDescription
serverIdrequiredpathstring
Response 200 · OK · application/json
HardeningView
  • agentSupportedbooleanrequired
    The server's agent can audit the host
  • auditedAtstring (date-time) | nullrequired
  • firstIndexinteger (int64) | nullrequired
    The score of the first audit
  • HardeningFix[]required
  • hardeningIndexinteger (int64) | nullrequired
    Lynis's 0 to 100 score from the latest audit; null before the first audit
  • lynisInstalledbooleanrequired
  • lynisVersionstring
  • modeenum: host | helper |
    How the agent reaches the host: directly, or through a privileged helper container
  • nextAuditAtstring (date-time) | nullrequired
    The next weekly audit; null when the weekly audit is off
  • pendingSafeinteger (int64)required
    Default fixes that would change something now
  • rebootRequiredbooleanrequired
    An applied fix takes effect after the next reboot
  • HardeningRemaining[]required
  • runningbooleanrequired
    An audit or fix run waits for the agent or is running
  • HardeningRun[]required
    The most recent runs, newest first
  • suggestionsinteger (int64)required
  • testsDoneinteger (int64)required
  • warningsinteger (int64)required
  • weeklybooleanrequired
    A weekly audit runs (default true)
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

PUT/servers/{serverId}/hardening

Switch the weekly Lynis audit of a server

Needs the servers:write scope and the Owner or Admin role. Audited.

ParameterInTypeDescription
serverIdrequiredpathstring
Request body · application/json · required
SettingsInputBody
  • weeklybooleanrequired
    Audit the host every week (default true)
Response 200 · OK · application/json
HardeningView
  • agentSupportedbooleanrequired
    The server's agent can audit the host
  • auditedAtstring (date-time) | nullrequired
  • firstIndexinteger (int64) | nullrequired
    The score of the first audit
  • HardeningFix[]required
  • hardeningIndexinteger (int64) | nullrequired
    Lynis's 0 to 100 score from the latest audit; null before the first audit
  • lynisInstalledbooleanrequired
  • lynisVersionstring
  • modeenum: host | helper |
    How the agent reaches the host: directly, or through a privileged helper container
  • nextAuditAtstring (date-time) | nullrequired
    The next weekly audit; null when the weekly audit is off
  • pendingSafeinteger (int64)required
    Default fixes that would change something now
  • rebootRequiredbooleanrequired
    An applied fix takes effect after the next reboot
  • HardeningRemaining[]required
  • runningbooleanrequired
    An audit or fix run waits for the agent or is running
  • HardeningRun[]required
    The most recent runs, newest first
  • suggestionsinteger (int64)required
  • testsDoneinteger (int64)required
  • warningsinteger (int64)required
  • weeklybooleanrequired
    A weekly audit runs (default true)
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

POST/servers/{serverId}/hardening/apply

Apply safe hardening fixes

Applies the selected fixes (the default set when none is selected), checks each one and undoes it by itself if it did not take effect, then audits again so the new index is known. Each fix is reversible with the rollback endpoint. Never changes SSH, the firewall or accounts. Needs the Owner or Admin role; audited.

ParameterInTypeDescription
Idempotency-KeyheaderstringClient-chosen key (<=255 chars). A retry with the same key replays the original response for 24 hours.
serverIdrequiredpathstring
Request body · application/json · required
FixesInputBody
  • fixIdsstring[] | null
    The fixes to apply or undo. Apply with none selects the default set (the ones marked default in the fix list); rollback needs at least one.
Response 202 · Accepted · application/json
HardeningRun
  • actionenum: audit | apply | rollbackrequired
  • createdAtstring (date-time)required
  • errorstring
  • finishedAtstring (date-time) | nullrequired
  • fixIdsstring[]required
  • hardeningIndexinteger (int64) | nullrequired
    The hardening index the run measured; null when it did not audit
  • idstringrequired
  • indexBeforeinteger (int64) | nullrequired
    The hardening index before the run; null when there was no audit yet
  • lynisVersionstring
  • messagestring
  • HardeningFixOutcome[]required
    What an apply or rollback did, per fix
  • statusenum: pending | succeeded | failed | skippedrequired
    skipped: Lynis is not installed on the server
  • triggerenum: scheduled | manualrequired
Errors
  • 400Bad Request
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 409Conflict
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

POST/servers/{serverId}/hardening/audit

Audit the host with Lynis now

Queues a Lynis audit on the server. It only reads the host. With installLynis, the agent first installs Lynis (from CISOfy's repository, else the distribution's). Needs the Owner or Admin role. 409 server_offline when the server is offline, 409 hardening_running while a run is in flight.

ParameterInTypeDescription
Idempotency-KeyheaderstringClient-chosen key (<=255 chars). A retry with the same key replays the original response for 24 hours.
serverIdrequiredpathstring
Request body · application/json · required
AuditInputBody
  • installLynisboolean
    Install Lynis from the distribution's or CISOfy's package repository when the server does not have it
Response 202 · Accepted · application/json
HardeningRun
  • actionenum: audit | apply | rollbackrequired
  • createdAtstring (date-time)required
  • errorstring
  • finishedAtstring (date-time) | nullrequired
  • fixIdsstring[]required
  • hardeningIndexinteger (int64) | nullrequired
    The hardening index the run measured; null when it did not audit
  • idstringrequired
  • indexBeforeinteger (int64) | nullrequired
    The hardening index before the run; null when there was no audit yet
  • lynisVersionstring
  • messagestring
  • HardeningFixOutcome[]required
    What an apply or rollback did, per fix
  • statusenum: pending | succeeded | failed | skippedrequired
    skipped: Lynis is not installed on the server
  • triggerenum: scheduled | manualrequired
Errors
  • 400Bad Request
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 409Conflictserver_offlinehardening_running
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

POST/servers/{serverId}/hardening/rollback

Undo safe hardening fixes

Restores what NebulaCtrl changed for the selected fixes: the previous sysctl values, file modes, login.defs lines and banners. A fix NebulaCtrl did not apply is left alone. Needs the Owner or Admin role; audited.

ParameterInTypeDescription
Idempotency-KeyheaderstringClient-chosen key (<=255 chars). A retry with the same key replays the original response for 24 hours.
serverIdrequiredpathstring
Request body · application/json · required
FixesInputBody
  • fixIdsstring[] | null
    The fixes to apply or undo. Apply with none selects the default set (the ones marked default in the fix list); rollback needs at least one.
Response 202 · Accepted · application/json
HardeningRun
  • actionenum: audit | apply | rollbackrequired
  • createdAtstring (date-time)required
  • errorstring
  • finishedAtstring (date-time) | nullrequired
  • fixIdsstring[]required
  • hardeningIndexinteger (int64) | nullrequired
    The hardening index the run measured; null when it did not audit
  • idstringrequired
  • indexBeforeinteger (int64) | nullrequired
    The hardening index before the run; null when there was no audit yet
  • lynisVersionstring
  • messagestring
  • HardeningFixOutcome[]required
    What an apply or rollback did, per fix
  • statusenum: pending | succeeded | failed | skippedrequired
    skipped: Lynis is not installed on the server
  • triggerenum: scheduled | manualrequired
Errors
  • 400Bad Request
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 409Conflict
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

GET/servers/{serverId}/mesh

Mesh node of a server

Whether the server joined the mesh, its node (state, tailnet addresses, peers, exposed services) and the link nodes that run on it.

ParameterInTypeDescription
serverIdrequiredpathstring
Response 200 · OK · application/json
ServerMeshView
  • agentCapablebooleanrequired
  • enabledbooleanrequired
  • MeshLinkView[] | nullrequired
    Link nodes that run on this server
  • NodeViewrequired
  • pausedbooleanrequired
  • tunDevicebooleanrequired
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

PUT/servers/{serverId}/mesh

Turn the mesh on or off for a server

Enabling adds one tagged device to the team's tailnet (it may be billed by Tailscale) and needs acceptMeshChanges; with ?dryRun=true it returns the plan instead (devices added, whether the host has /dev/net/tun, warnings and blockers). Disabling is refused (409 mesh_server_in_use) while replicas or cross-server links use the server's node. The node key is minted when the command is sent and never stored.

ParameterInTypeDescription
Idempotency-KeyheaderstringClient-chosen key (<=255 chars). A retry with the same key replays the original response for 24 hours.
serverIdrequiredpathstring
dryRunquerybooleanReturn the plan (devices added, blockers, warnings) without changing anything
Request body · application/json · required
SetServerMeshInputBody
  • acceptMeshChangesboolean
    Confirms that enabling adds tailnet devices (tagged devices may be billed by Tailscale)
  • enabledbooleanrequired
Response 202 · Accepted · application/json
ServerMeshResult
  • appliedbooleanrequired
  • enabledbooleanrequired
  • ServerMeshPlanrequired
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

POST/servers/{serverId}/mesh/check

Test the mesh connectivity of a server

The agent checks whether the server's node reaches the other servers' nodes (connected, refused, timeout, no_path). This is the ground truth for advisory ACL modes.

ParameterInTypeDescription
serverIdrequiredpathstring
Request body · application/json · required
CheckServerInputBody
  • peerServerIdstring
    Check only this peer (default: every other server with a mesh node)
Response 200 · OK · application/json
CheckServerOutputBody
  • ServerCheckResult[] | nullrequired
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

POST/servers/{serverId}/mesh/reprovision

Re-provision the mesh node of a server

Deletes the node's device from the tailnet and re-creates it with a fresh single-use key and a fresh state volume. The node gets a new tailnet IP and the access rules regenerate. Use it when the node needs attention.

ParameterInTypeDescription
Idempotency-KeyheaderstringClient-chosen key (<=255 chars). A retry with the same key replays the original response for 24 hours.
serverIdrequiredpathstring
Response 202 · Accepted · application/json
AcceptedOutputBody
  • acceptedbooleanrequired
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

GET/servers/{serverId}/patches

Pending OS updates and reboot-required of a server

The Updates panel: how many packages are waiting (and how many are security updates), whether the host asks for a reboot, the pending packages with a warning where an upgrade is risky, the production services that run on the server, and the recent runs. The agent checks every server about every 6 hours; known is false until the first check completes.

ParameterInTypeDescription
serverIdrequiredpathstring
Response 200 · OK · application/json
PatchView
  • agentSupportedbooleanrequired
    The agent advertised patching support; false means update the agent first
  • busyenum: check | apply | reboot | required
    The run in flight, if any
  • checkedAtstring (date-time) | nullrequired
  • controlPlanebooleanrequired
    This server runs the control plane: upgrades and reboots take the dashboard down
  • knownbooleanrequired
    A check has completed at least once
  • managerenum: apt | dnf | required
    Empty until the first check
  • messagestring
    A caution from the last check
  • onlinebooleanrequired
  • PatchPackage[]required
    Pending upgrades, security first, at most 200
  • ProductionService[]required
  • rebootPackagesstring[]required
    Packages that asked for the reboot, when the host says
  • rebootRequiredbooleanrequired
  • PatchRun[]required
    The most recent runs, newest first, without logs
  • securityinteger (int64)required
    How many of the updates are security updates
  • stalebooleanrequired
    The last check is older than 12 hours
  • supportedbooleanrequired
    The host has a supported package manager (apt or dnf)
  • updatesinteger (int64)required
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

POST/servers/{serverId}/patches/apply

Upgrade the server's packages

Runs apt-get upgrade or dnf upgrade (security updates only with securityOnly) on the host as root, keeping the configuration files you changed, then checks again. The upgrade runs detached on the host, so it finishes even when Docker restarts. Never reboots. Instance admin only; confirm must be the server's name; a server that runs production services or the control plane also needs acknowledgeProduction (422 production_ack_required), and a token that asks for production approvals gets 409 approval_required. Needs a completed check first (409 no_check_yet). Audited.

ParameterInTypeDescription
Idempotency-KeyheaderstringClient-chosen key (<=255 chars). A retry with the same key replays the original response for 24 hours.
serverIdrequiredpathstring
Request body · application/json · required
ApplyInputBody
  • acknowledgeProductionboolean
    Required when production services or the control plane run on the server
  • confirmstringrequired
    The server's name, typed by the person
  • securityOnlyboolean
    Upgrade only the packages with a security update
Response 202 · Accepted · application/json
PatchRun
  • actionenum: check | apply | rebootrequired
  • createdAtstring (date-time)required
  • errorstring
  • exitCodeinteger (int64) | nullrequired
    The package manager's exit status (upgrades only)
  • finishedAtstring (date-time) | nullrequired
  • idstringrequired
  • logstring
    The tail of what the package manager printed (upgrades only; only in the single-run read)
  • messagestring
  • rebootingSincestring (date-time) | nullrequired
  • requestedBystring
    The person who started the run; absent for automatic checks
  • securityOnlybooleanrequired
  • statusenum: pending | rebooting | succeeded | failedrequired
    rebooting: the host accepted the reboot and NebulaCtrl waits for the agent to reconnect on a new boot
  • triggerenum: scheduled | manualrequired
  • updatesAfterinteger (int64) | nullrequired
  • updatesBeforeinteger (int64) | nullrequired
Errors
  • 400Bad Request
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 409Conflictapproval_requiredno_check_yet
  • 422Unprocessable Entityproduction_ack_required
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

POST/servers/{serverId}/patches/check

Check the server for updates now

Refreshes the package lists on the host and records the pending updates and reboot-required. Changes no package. Needs the Owner or Admin role. 409 server_offline when the server is offline, 409 patching_running while a run is in flight.

ParameterInTypeDescription
Idempotency-KeyheaderstringClient-chosen key (<=255 chars). A retry with the same key replays the original response for 24 hours.
serverIdrequiredpathstring
Response 202 · Accepted · application/json
PatchRun
  • actionenum: check | apply | rebootrequired
  • createdAtstring (date-time)required
  • errorstring
  • exitCodeinteger (int64) | nullrequired
    The package manager's exit status (upgrades only)
  • finishedAtstring (date-time) | nullrequired
  • idstringrequired
  • logstring
    The tail of what the package manager printed (upgrades only; only in the single-run read)
  • messagestring
  • rebootingSincestring (date-time) | nullrequired
  • requestedBystring
    The person who started the run; absent for automatic checks
  • securityOnlybooleanrequired
  • statusenum: pending | rebooting | succeeded | failedrequired
    rebooting: the host accepted the reboot and NebulaCtrl waits for the agent to reconnect on a new boot
  • triggerenum: scheduled | manualrequired
  • updatesAfterinteger (int64) | nullrequired
  • updatesBeforeinteger (int64) | nullrequired
Errors
  • 400Bad Request
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 409Conflictserver_offlinepatching_running
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

GET/servers/{serverId}/patches/plan

What an upgrade of the server would do

The plan shown before the confirmation: the packages that would be upgraded, the risky ones among them and why, whether a reboot will probably be needed, whether Docker restarts, the production services on the server and what the apply request must carry (the server's name, and acknowledgeProduction when requiresAcknowledgement). Changes nothing.

ParameterInTypeDescription
serverIdrequiredpathstring
securityOnlyquerybooleanPlan to upgrade only the packages with a security update
Response 200 · OK · application/json
PatchPlan
  • checkedAtstring (date-time) | nullrequired
  • confirmstringrequired
    What the person types to confirm: the server's name
  • controlPlanebooleanrequired
  • managerenum: apt | dnf | required
  • notReadyReasonstring
  • PatchPackage[]required
  • ProductionService[]required
  • readybooleanrequired
    The plan can be applied now
  • rebootLikelybooleanrequired
    The upgrade probably leaves the server wanting a reboot
  • requiresAcknowledgementbooleanrequired
  • restartsDockerbooleanrequired
    Docker is among the packages: its daemon restarts and containers may stop for a moment
  • PatchRisk[]required
  • securityinteger (int64)required
  • securityOnlybooleanrequired
  • serverstringrequired
  • servicesOnServerinteger (int64)required
  • stalebooleanrequired
  • updatesinteger (int64)required
    Packages that would be upgraded
  • warningsstring[]required
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

POST/servers/{serverId}/patches/reboot

Reboot the server

Schedules a reboot of the host a few seconds ahead. Every service on the server goes down until it boots and Docker starts them again. The run stays rebooting until the agent reconnects on a new boot (it fails after 20 minutes). Instance admin only; confirm must be the server's name; a server that runs production services or the control plane also needs acknowledgeProduction. Audited.

ParameterInTypeDescription
Idempotency-KeyheaderstringClient-chosen key (<=255 chars). A retry with the same key replays the original response for 24 hours.
serverIdrequiredpathstring
Request body · application/json · required
RebootInputBody
  • acknowledgeProductionboolean
    Required when production services or the control plane run on the server
  • confirmstringrequired
    The server's name, typed by the person
Response 202 · Accepted · application/json
PatchRun
  • actionenum: check | apply | rebootrequired
  • createdAtstring (date-time)required
  • errorstring
  • exitCodeinteger (int64) | nullrequired
    The package manager's exit status (upgrades only)
  • finishedAtstring (date-time) | nullrequired
  • idstringrequired
  • logstring
    The tail of what the package manager printed (upgrades only; only in the single-run read)
  • messagestring
  • rebootingSincestring (date-time) | nullrequired
  • requestedBystring
    The person who started the run; absent for automatic checks
  • securityOnlybooleanrequired
  • statusenum: pending | rebooting | succeeded | failedrequired
    rebooting: the host accepted the reboot and NebulaCtrl waits for the agent to reconnect on a new boot
  • triggerenum: scheduled | manualrequired
  • updatesAfterinteger (int64) | nullrequired
  • updatesBeforeinteger (int64) | nullrequired
Errors
  • 400Bad Request
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 409Conflict
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

GET/servers/{serverId}/patches/runs/{runId}

One check, upgrade or reboot of a server, with the upgrade's log

The log is the tail of what the package manager printed. A run in rebooting waits for the agent to reconnect on a new boot.

ParameterInTypeDescription
serverIdrequiredpathstring
runIdrequiredpathstring
Response 200 · OK · application/json
PatchRun
  • actionenum: check | apply | rebootrequired
  • createdAtstring (date-time)required
  • errorstring
  • exitCodeinteger (int64) | nullrequired
    The package manager's exit status (upgrades only)
  • finishedAtstring (date-time) | nullrequired
  • idstringrequired
  • logstring
    The tail of what the package manager printed (upgrades only; only in the single-run read)
  • messagestring
  • rebootingSincestring (date-time) | nullrequired
  • requestedBystring
    The person who started the run; absent for automatic checks
  • securityOnlybooleanrequired
  • statusenum: pending | rebooting | succeeded | failedrequired
    rebooting: the host accepted the reboot and NebulaCtrl waits for the agent to reconnect on a new boot
  • triggerenum: scheduled | manualrequired
  • updatesAfterinteger (int64) | nullrequired
  • updatesBeforeinteger (int64) | nullrequired
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

POST/servers/{serverId}/revoke

Revoke a server's agent

Revokes the agent identity and pending enrollment tokens, cancels commands that were never delivered (their deployments fail with "Server revoked. No changes were made.") and disconnects the agent. Containers already running on the host are left untouched.

ParameterInTypeDescription
serverIdrequiredpathstring
Response 200 · OK · application/json
Server
  • acceptWorkloadsbooleanrequired
    Whether services may be scheduled on this server. Turning it off keeps what already runs here and refuses new placements and moves.
  • acmeEmailstring | nullrequired
  • agentVersionstring | nullrequired
  • baseDomainstring | nullrequired
  • buildAllowEmulationbooleanrequired
    Allow building for another CPU architecture through emulation (slow); needs the agent to report emulation for the platform
  • buildAllowPreviewsbooleanrequired
    Allow pull request previews (untrusted code) to build here; off by default
  • buildEnabledbooleanrequired
    The server builds images for other servers and pushes them to a registry (the Builds or Both role). Independent of acceptWorkloads.
  • buildMaxConcurrentinteger (int64)required
    Builds that run at the same time; more queue on the control plane
  • composeVersionstringrequired
    Docker Compose plugin version the agent reported, empty when it has none
  • controlPlanebooleanrequired
    The host the installer put the control plane on; its proxy serves the dashboard
  • createdAtstring (date-time)required
  • diskAlertbooleanrequired
    True while the root filesystem is at or above the threshold
  • diskAlertThresholdPercentinteger (int64)required
    Root filesystem usage that raises the disk alert (50-99)
  • drainMessagestringrequired
    Why the last drain failed or was canceled, empty otherwise
  • drainStartedAtstring (date-time) | nullrequired
  • drainStateenum: none | draining | drained | failedrequired
    Evacuation state; draining and drained servers accept no new services
  • Factsrequired
  • geoEnabledbooleanrequired
    Count where requests come from (country, and city at the city level) from the client IP; IPs are never stored
  • geoLevelenum: country | cityrequired
    country needs a ~8 MB database on the server, city ~130 MB
  • geoRefreshDaysinteger (int64)required
    Check for a newer database every N days (1-90)
  • geoSourceenum: dbip | maxmindrequired
    dbip = DB-IP Lite (CC BY 4.0, no key); maxmind = MaxMind GeoLite2 with the team's account
  • idstringrequired
  • lastSeenAtstring (date-time) | nullrequired
  • Latestrequired
  • metricsRetentionDaysinteger (int64)required
    How long resource metric history is kept (1-90)
  • namestringrequired
  • ServerPatchSummaryrequired
  • protocolVersioninteger (int32) | nullrequired
  • Proxyrequired
  • publicIpstring | nullrequired
  • serviceCountinteger (int64)required
  • statusenum: pending | online | offline | revokedrequired
  • trafficAnalyticsEnabledbooleanrequired
    Aggregate Traefik access logs into traffic analytics
  • trafficDailyRetentionDaysinteger (int64)required
    Daily traffic history (7-365 days)
  • trafficHourlyRetentionDaysinteger (int64)required
    Hourly traffic history (2-90 days)
  • ServerTunnelSummaryrequired
  • unrestrictedbooleanrequired
    An instance admin made this server unrestricted: stacks and services on it may use privileged mode, host networking, devices, GPUs, a runtime, the host PID namespace, unconfined seccomp or AppArmor, NET_ADMIN, SYS_ADMIN, the Docker socket and host bind mounts
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

GET/servers/{serverId}/tunnel

Cloudflare Tunnel state of a server

Whether the server has a Cloudflare Tunnel, the connector's observed state and the ingress sync. A server without a tunnel answers state: off and says whether one can be enabled.

ParameterInTypeDescription
serverIdrequiredpathstring
Response 200 · OK · application/json
TunnelView
  • accountIdstring
  • accountReadybooleanrequired
    The connection has an account ID (needed for tunnels)
  • activebooleanrequired
  • agentSupportedbooleanrequired
    The server's agent can run the cloudflared connector
  • cloudflareConnectedbooleanrequired
    The team has a Cloudflare connection
  • cnamestring
    The DNS target of the tunnel: <tunnelId>.cfargotunnel.com
  • connectionsinteger (int64)required
    Ready connections to Cloudflare's edge
  • enabledbooleanrequired
    The server has a tunnel (or is removing one)
  • imagestring
  • ingressErrorstring
  • ingressHostsinteger (int64)required
  • ingressSyncedAtstring (date-time) | nullrequired
  • messagestringrequired
    Why the connector needs attention, or the last teardown problem
  • observedAtstring (date-time) | nullrequired
  • stateenum: off | provisioning | online | offline | needs_attention | removingrequired
    Observed connector state; off when the server has no tunnel
  • tunnelIdstring
  • tunnelNamestring
  • upstreamstringrequired
    Where the tunnel forwards every request
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

POST/servers/{serverId}/tunnel

Enable a Cloudflare Tunnel on a server

Creates a remotely-managed tunnel with the team's Cloudflare connection, pushes its ingress rules (every hostname of the server's services to the proxy, then a 404 catch-all) and tells the agent to run the cloudflared connector. The connector token is fetched when the command is sent and is never stored. Once the connector connects, the server's domains in connected zones point at the tunnel and ports 80 and 443 may stay closed. Needs the servers:write and proxy:write scopes. The Cloudflare token needs the permission Account, Cloudflare Tunnel, Edit (422 cloudflare_tunnel_forbidden).

ParameterInTypeDescription
Idempotency-KeyheaderstringClient-chosen key (<=255 chars). A retry with the same key replays the original response for 24 hours.
serverIdrequiredpathstring
Response 202 · Accepted · application/json
TunnelView
  • accountIdstring
  • accountReadybooleanrequired
    The connection has an account ID (needed for tunnels)
  • activebooleanrequired
  • agentSupportedbooleanrequired
    The server's agent can run the cloudflared connector
  • cloudflareConnectedbooleanrequired
    The team has a Cloudflare connection
  • cnamestring
    The DNS target of the tunnel: <tunnelId>.cfargotunnel.com
  • connectionsinteger (int64)required
    Ready connections to Cloudflare's edge
  • enabledbooleanrequired
    The server has a tunnel (or is removing one)
  • imagestring
  • ingressErrorstring
  • ingressHostsinteger (int64)required
  • ingressSyncedAtstring (date-time) | nullrequired
  • messagestringrequired
    Why the connector needs attention, or the last teardown problem
  • observedAtstring (date-time) | nullrequired
  • stateenum: off | provisioning | online | offline | needs_attention | removingrequired
    Observed connector state; off when the server has no tunnel
  • tunnelIdstring
  • tunnelNamestring
  • upstreamstringrequired
    Where the tunnel forwards every request
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 409Conflict
  • 422Unprocessable Entitycloudflare_tunnel_forbidden
  • 500Internal Server Error
  • 502Bad Gateway

Errors are RFC 9457 application/problem+json with a stable code field.

DELETE/servers/{serverId}/tunnel

Disable the Cloudflare Tunnel of a server

Points the server's domains back at its public IP, removes the connector and deletes the tunnel at Cloudflare shortly afterwards. Disabling a tunnel that is already being removed retries the delete. Ports 80 and 443 must be reachable again before the DNS change propagates.

ParameterInTypeDescription
serverIdrequiredpathstring
forcequerybooleanDrop the tunnel record without asking Cloudflare (it may linger in the Cloudflare dashboard). Use it when the Cloudflare connection is gone or Cloudflare keeps refusing the delete.
Response 202 · Accepted · application/json
TunnelView
  • accountIdstring
  • accountReadybooleanrequired
    The connection has an account ID (needed for tunnels)
  • activebooleanrequired
  • agentSupportedbooleanrequired
    The server's agent can run the cloudflared connector
  • cloudflareConnectedbooleanrequired
    The team has a Cloudflare connection
  • cnamestring
    The DNS target of the tunnel: <tunnelId>.cfargotunnel.com
  • connectionsinteger (int64)required
    Ready connections to Cloudflare's edge
  • enabledbooleanrequired
    The server has a tunnel (or is removing one)
  • imagestring
  • ingressErrorstring
  • ingressHostsinteger (int64)required
  • ingressSyncedAtstring (date-time) | nullrequired
  • messagestringrequired
    Why the connector needs attention, or the last teardown problem
  • observedAtstring (date-time) | nullrequired
  • stateenum: off | provisioning | online | offline | needs_attention | removingrequired
    Observed connector state; off when the server has no tunnel
  • tunnelIdstring
  • tunnelNamestring
  • upstreamstringrequired
    Where the tunnel forwards every request
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

POST/servers/{serverId}/tunnel/sync

Re-sync the Cloudflare Tunnel of a server

Re-pushes the ingress rules and re-sends the connector command (creating the container again when it is gone). Use it when the connector needs attention.

ParameterInTypeDescription
Idempotency-KeyheaderstringClient-chosen key (<=255 chars). A retry with the same key replays the original response for 24 hours.
serverIdrequiredpathstring
Response 202 · Accepted · application/json
TunnelView
  • accountIdstring
  • accountReadybooleanrequired
    The connection has an account ID (needed for tunnels)
  • activebooleanrequired
  • agentSupportedbooleanrequired
    The server's agent can run the cloudflared connector
  • cloudflareConnectedbooleanrequired
    The team has a Cloudflare connection
  • cnamestring
    The DNS target of the tunnel: <tunnelId>.cfargotunnel.com
  • connectionsinteger (int64)required
    Ready connections to Cloudflare's edge
  • enabledbooleanrequired
    The server has a tunnel (or is removing one)
  • imagestring
  • ingressErrorstring
  • ingressHostsinteger (int64)required
  • ingressSyncedAtstring (date-time) | nullrequired
  • messagestringrequired
    Why the connector needs attention, or the last teardown problem
  • observedAtstring (date-time) | nullrequired
  • stateenum: off | provisioning | online | offline | needs_attention | removingrequired
    Observed connector state; off when the server has no tunnel
  • tunnelIdstring
  • tunnelNamestring
  • upstreamstringrequired
    Where the tunnel forwards every request
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 409Conflict
  • 422Unprocessable Entity
  • 500Internal Server Error
  • 502Bad Gateway

Errors are RFC 9457 application/problem+json with a stable code field.

GET/servers/{serverId}/unrestricted

The Unrestricted switch and Compose availability of a server

ParameterInTypeDescription
serverIdrequiredpathstring
Response 200 · OK · application/json
UnrestrictedSettings
  • availablebooleanrequired
    The agent can run Compose stacks (Docker Compose plugin 2.24 or newer)
  • composeVersionstringrequired
    Docker Compose plugin version the agent reported, empty when it has none
  • dockerServicesinteger (int64)required
    Live services placed on this server that use Docker options which need an unrestricted server
  • stacksinteger (int64)required
    Live Compose stacks placed on this server
  • unrestrictedbooleanrequired
    An instance admin allowed this server to run stacks and services with privileged mode, host networking, devices, GPUs, a runtime, the host PID namespace, unconfined seccomp or AppArmor, NET_ADMIN, SYS_ADMIN, the Docker socket and host bind mounts
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

PUT/servers/{serverId}/unrestricted

Make a server unrestricted, or restricted again

By default Compose stacks and services run under safe allow-lists: no privileged mode, host network, host PID namespace, devices, GPUs, custom runtime, unconfined seccomp or AppArmor, NET_ADMIN or SYS_ADMIN, Docker socket or host bind mounts. An unrestricted server lifts them for everything on it, so anyone who can deploy there can take over the server. Instance admin only; enabling needs confirm to equal the server's name. Audited as server.unrestricted.enable or .disable. Disabling does not touch running containers: the next deploy, rollback or reconcile of a stack or service that needs the lifted rules fails until it is edited or moved.

ParameterInTypeDescription
serverIdrequiredpathstring
Request body · application/json · required
SetUnrestrictedInputBody
  • confirmstring
    The server's name; required when enabling
  • unrestrictedbooleanrequired
Response 200 · OK · application/json
UnrestrictedSettings
  • availablebooleanrequired
    The agent can run Compose stacks (Docker Compose plugin 2.24 or newer)
  • composeVersionstringrequired
    Docker Compose plugin version the agent reported, empty when it has none
  • dockerServicesinteger (int64)required
    Live services placed on this server that use Docker options which need an unrestricted server
  • stacksinteger (int64)required
    Live Compose stacks placed on this server
  • unrestrictedbooleanrequired
    An instance admin allowed this server to run stacks and services with privileged mode, host networking, devices, GPUs, a runtime, the host PID namespace, unconfined seccomp or AppArmor, NET_ADMIN, SYS_ADMIN, the Docker socket and host bind mounts
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

POST/servers/agent-upgrades

Upgrade agents one server at a time (staged)

Upgrades the given servers (every server whose agent can be upgraded now when none are given) in name order. Each upgrade must be confirmed by the agent reconnecting with the new version before the next one starts; the first failure stops the rollout and leaves the remaining servers untouched. Needs the Owner or Admin role; audited. 409 nothing_to_upgrade when no agent qualifies.

ParameterInTypeDescription
Idempotency-KeyheaderstringClient-chosen key (<=255 chars). A retry with the same key replays the original response for 24 hours.
Request body · application/json · required
FleetInputBody
  • forceboolean
    Install a version an agent rolled back before.
  • serverIdsstring[] | null
    The servers to upgrade. Empty: every server whose agent can be upgraded now.
Response 202 · Accepted · application/json
RolloutView
  • serverIdsstring[] | nullrequired
    The servers in upgrade order. They are upgraded one at a time; the rollout stops at the first failure.
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 409Conflictnothing_to_upgrade
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

POST/servers/enrollment-tokens

Create a pending server and a one-time enrollment token

The token is valid for one hour and can enroll exactly one agent. It is returned only in this response (and in an idempotent replay of it).

ParameterInTypeDescription
Idempotency-KeyheaderstringClient-chosen key (<=255 chars). A retry with the same key replays the original response for 24 hours.
Request body · application/json · required
CreateTokenInputBody1
  • acmeEmailstring
  • baseDomainstring
  • namestringrequired
  • publicIpstring
Response 201 · Created · application/json
EnrollmentToken
  • expiresAtstring (date-time)required
  • installCommandstringrequired
  • Serverrequired
  • tokenstringrequired
    Shown once; only its hash is stored
Errors
  • 401Unauthorized
  • 403Forbidden
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.