Skip to content

Create, Use, and Manage Workers

Workers are deprecated

Use a service account as the identity for automation, and a Channel to consume events and to receive commands; see command bots. Existing Workers keep working. A Worker is still required to serve external functions until functions move to Channels.

A Worker is an identity in ConfigHub. Before service accounts, anything that talked to ConfigHub without a person signing in authenticated as one: a CI job, a script, an event consumer, a GitOps operator pulling a Release, any API client. A Worker has its own credentials and its own permissions, and what it does is attributed to it.

A process you run can also connect to ConfigHub as a Worker and stay connected, either to serve external functions, which ConfigHub then routes to it, or to consume events. Most Workers never do either.

Nothing is deployed through a Worker. Configuration reaches your infrastructure by publishing a Release that a GitOps operator pulls.

Create a Worker

Creating a Worker registers the identity and generates its secret:

cub worker create --space platform-dev deploy-bot

You can also create one in the UI, with Add on the workers page. Either way it appears in the list:

cub worker list

A Worker lives in a Space, which is where its own entity permissions are managed, but its identity is organization-wide: what it may do is decided by its organization role and by the permissions granted to it, not by the Space it was created in.

Use a Worker as a service identity

For automation that only calls ConfigHub, such as a CI pipeline or an agent, use a service account: it needs no Worker, and authenticates with a key. The rest of this section is about the identity a Worker has.

Fetch the credentials and hand them to whatever needs to talk to ConfigHub:

eval "$(cub worker get-envs --space platform-dev deploy-bot)"

This sets CONFIGHUB_WORKER_ID and CONFIGHUB_WORKER_SECRET. A client exchanges them for a standard authentication token; cub does it with:

cub auth login --as-worker

From there the client calls the API as the Worker. cub worker get-envs --no-export prints the same two values as plain KEY=value lines, for a .env file or a Kubernetes Secret.

Scope what it can do

Every Worker has a bot user, and permissions are granted to that user like to any other. Give the Worker an organization role with --org-role when you create or update it; none gives it no default access, so it can reach only what is granted to it explicitly. Then grant exactly that, on a Space for everything in it or on individual entities:

cub worker create --space platform-dev --org-role none release-bot
cub space update --permission UseChildren:<bot user ID> payments-prod

The bot user's ID is the UserID that cub worker get reports. Authorization describes the roles and the permission categories. Because the grant is to the Worker, its actions show up in revisions and the event log as the Worker's, not as those of whoever created it.

Instead of granting permissions to the Worker one by one, you can add it to a Group, so it gets whatever the Group is granted and acts as a member of that team:

cub group add-worker my-team platform-dev/release-bot

An Organization admin or manager may do this, and so may a member of the Group who has Manage permission on the Worker. The Worker picks up the change the next time it authenticates. cub group remove-worker takes it out again.

Server workers

A server worker is a credential a GitOps operator can present when it pulls a Release from the OCI endpoint. New setups use a service account instead, as integrating with GitOps operators describes, and cub cluster up creates one of those. A server worker is created with --is-server-worker, and one with ViewChildren permission on a Target can pull the Releases published for that Target, so existing ones keep working. To create one by hand:

cub worker create --space platform-dev --is-server-worker --allow-exists server-worker

Keys instead of a secret

A Worker can authenticate with a key pair instead of its secret. You register the public key, and the holder of the private key signs a short-lived assertion to get a token, so ConfigHub never receives or stores a secret for it:

cub worker key add --space platform-dev deploy-bot --public-key ./deploy-bot.pub.jwk
cub worker key list --space platform-dev deploy-bot

--generate creates an Ed25519 key pair instead, keeps the private key locally and registers the public half.

Registering a key hands out the identity, so it requires the admin or manager role.

Use a Worker for external functions

A process that serves external functions authenticates as a Worker and connects. The connection is outbound from the process over HTTP long-polling on the normal API port, so it works from behind a firewall. On connecting, the process reports which functions it serves, and from then on an invocation or a Trigger that names the Worker is routed to it over that connection:

cub function do --space app-dev --unit web --worker platform-dev/policy-worker vet-policy
cub trigger create --space app-dev --worker platform-dev/policy-worker policy Mutation Kubernetes/YAML vet-policy

The process is yours: ConfigHub does not ship one. External functions covers writing one, running it, and deploying it.

Use a Worker for event consumption

A process can also authenticate as a Worker to read the event log: it long-polls by a named cursor and acts on what ConfigHub records, such as a Release being published. It receives no function invocations. Event consumers covers writing one.

Connection status

ConfigHub reports the state of a Worker's connection as its condition. Ready means a process is connected and answering invocations and heartbeats. Connected is the moment after a process first connects, Unresponsive means it is connected but not answering heartbeats, NotReady means it answered a heartbeat with an error, and Disconnected means nothing is connected.

% cub worker list
NAME              CONDITION    SPACE            LAST-SEEN
policy-worker     Ready        platform-prod    2025-10-23 22:05:44
policy-worker     Ready        platform-dev     2025-10-23 22:05:33
deploy-bot        Disconnected platform-dev

A Worker used only as an identity shows Disconnected: nothing connects, and that is fine. If a Worker that functions depend on stays in a condition other than Ready for long enough, invocations directed at it fail immediately and Triggers that use it are disabled; validating configuration and enforcing policies describes that behaviour, and a Trigger's FailOpenAfter sets how long.

Replicas and high availability

Several processes can connect with the same Worker credentials. The first to connect is active and receives every invocation. Later ones are standbys: ConfigHub keeps their connections alive with a keepalive every 30 seconds, which they log and discard, and otherwise sends them nothing. Keepalives are distinct from the heartbeats a process sends to ConfigHub to report its health.

When the active connection drops, ConfigHub removes it, checks the health of the standbys, and promotes the first healthy one. The promoted process re-queues any invocation that was in flight to the previous one and not yet completed, then carries on. A Deployment with maxSurge 1 and maxUnavailable 0, as in the example, starts the replacement before the running process is terminated, so a rollout hands over without a gap.

Delete a Worker

If you no longer need a worker and nothing connects as it any more, you can delete it:

cub worker delete --space platform-dev deploy-bot

Targets don't name workers, so deleting one leaves every target as it was. Permissions granted to the worker's identity on a target stay in place; remove them with cub target update --permission -View:<user ID> --permission -ViewChildren:<user ID> if nothing should pull as it again.

You won't be able to delete a worker in use by triggers or invocations, even with --detach, without first deleting them or updating them to not use the worker. See deleting referenced entities.