Skip to content

Enrollment and key rotation

Enrollment is how a host proves once that it belongs to your organization. Everything after that is signed with a key the Sentinel generated itself.

Your organization has one enrollment token. It starts with ncse_, and it is reusable: every host you deploy uses the same one. You’ll find it under Sentinels → Deploy Sentinel.

Operators and owners can view it. Only an owner can renew it.

Renewing invalidates the old token immediately. Any VM template or cloud-init file still carrying it stops being able to enroll new hosts, so you have to update them. Sentinels that already enrolled keep working, because they no longer depend on the token.

The Sentinel generates an Ed25519 key pair on the host and sends the public half. The private key is written to /etc/nocert-sentinel/sentinel-key.json with mode 0600 and never leaves the machine.

It also sends what the fleet list needs to tell your hosts apart: hostname, operating system, architecture, agent version, the host’s primary IP, and the IPv4 subnets of its physical interfaces.

From then on it signs every request with its key (RFC 9421), and the token plays no further part.

Where you put it What happens
--enroll-token on the command line One-shot. Forces a fresh enrollment, replacing any key already on the host, restarts the service so it picks the new identity up, then exits.
NOCERT_ENROLL_TOKEN in /etc/nocert-sentinel/enroll.env Read by the service at startup. Enrolls if the host has no key yet, or if the key it holds was enrolled under a different machine ID. Ignored otherwise.
enroll_token in config.yaml Same as the environment variable, which wins if both are set.

The flag is destructive; the environment file is idempotent. That is why a token left in a template never re-enrolls a clone that already holds a key.

The command line is also visible in ps while it runs, so prefer the environment file on any host you share.

Install the package in the template, but do not enroll it there. A key baked into the image would be shared by every clone.

  1. Install nocert-sentinel in the template, following Install the Sentinel.

  2. Clear the machine ID so each clone gets a fresh one on first boot:

    Terminal window
    sudo truncate -s 0 /etc/machine-id
  3. Seal the image.

  4. Give each clone the token at first boot. With cloud-init:

    #cloud-config
    write_files:
    - path: /etc/nocert-sentinel/enroll.env
    permissions: '0600'
    content: |
    NOCERT_ENROLL_TOKEN=ncse_...

Any provisioning tool works, as long as the file is in place before the service first starts. Each clone enrolls on its own and ends up with its own private key.

Inject the token at first boot rather than baking it into the image. Anyone who can read the image can enroll into your organization with it.

Clearing the machine ID is standard golden-image practice, and the Sentinel leans on it: it records the machine ID it enrolled under and re-enrolls rather than reusing a key it finds on a host reporting a different one. A clone that kept the template’s machine ID would defeat that check.

The Sentinel checks its key every 6 hours and rotates it once it has less than 5 days left. The rotation request is signed with the old key, so it needs no token and nothing from you.

Run the enroll command again:

Terminal window
sudo nocert-sentinel --enroll-token ncse_...

It replaces the credentials on disk and restarts the service, so the host is back at work when the command returns.

Every enrollment mints a new identity, so this leaves the old entry behind in the Sentinels list under the same hostname. Delete the stale one to revoke its access. Deleting it also drops the filesystem, local and Kubernetes findings that entry reported, so expect that history to restart from the new one.

Deleting a Sentinel revokes it for good. The host keeps polling with credentials that no longer exist and its entry never comes back, so the service logs:

level=ERROR msg="the backend keeps rejecting this sentinel"

Re-enroll the host to give it a new identity. Other cases produce the same line, so read the reason logged next to it first: a clock that has drifted too far for NoCert to accept the host’s signatures, a Sentinel someone set to inactive, a signature NoCert could not verify, and an expired key.

That last one is the case worth knowing. A key is minted for 30 days and the Sentinel renews it while it runs, checking every 6 hours and rotating with 5 days to spare. A host powered off for longer than that comes back with a key nothing will accept, and re-enrollment is the way out.