Mass provisioning
The problem
Per-agent tokens are one-shot — one click in the dashboard yields one token good for one registration. That doesn’t scale when Terraform or an autoscaling group spins up 20 or 100 VMs in parallel. You want a single secret that all hosts may use, with a built-in counter and an expiry.
Enrolment tokens
An enrolment token (prefix enrl_) is a multi-use secret with:
max_uses— hard ceiling on the number of registrationsexpires_at— TTL between 1 hour and 30 daysdefault_tags+default_role— auto-applied to every agent it registersallowed_cidrs(optional) — source-IP allowlist for extra hardeningrevoked_at— instant kill switch from the dashboard
The hub stores only the SHA-256; the raw token is shown once and from then on only lives in your secret store.
Mint a token
- Dashboard → Settings → Enrolment tokens
- Name: e.g.
production-cluster-eu-west - TTL: 72 h, max uses: 50, default tags:
prod,eu-west,web, role:web - (Optional) Allowed CIDRs: e.g.
10.0.0.0/8if hosts sit inside the VPC - Create — copy the
enrl_…token immediately
Use in cloud-init
#cloud-configruncmd: - bash -c ' export MONSYS_TOKEN="enrl_xxxxx" export MONSYS_TAGS="$(curl -fsS http://169.254.169.254/latest/meta-data/placement/availability-zone)" curl -fsSL https://get.monsys.ai/install.sh | sudo -E bash 'The installer detects the enrl_ prefix, calls
POST /api/v1/agents/enrol on the hub, and gets a fresh per-agent token
(agt_…) back. That token is written to /etc/monsys/agent.toml. The
enrolment token is never persisted on the host — from then on the agent
uses only its own one-shot token.
Use in Terraform
module "monsys" { source = "git::https://github.com/gotrust/monsys.git//agent/packaging/terraform" monsys_token = var.monsys_enrolment_token # from Vault / SOPS tags = ["shard-${count.index}"] role = "web"}
resource "aws_instance" "web" { count = 50 ami = "ami-..." instance_type = "t4g.small" user_data = module.monsys.cloud_init}50 instances, one secret. Every host comes up with its own agt_… token
plus tags prod,eu-west,web,shard-N.
Use in Ansible
- name: install monsys agent hosts: all become: true vars: monsys_token: "{{ lookup('hashi_vault', 'secret/monsys/enrolment') }}" tasks: - shell: | export MONSYS_TOKEN="{{ monsys_token }}" export MONSYS_TAGS="{{ group_names | join(',') }}" export MONSYS_ROLE="{{ ansible_role | default('') }}" curl -fsSL https://get.monsys.ai/install.sh | bash args: creates: /etc/monsys/agent.tomlTag merging
Token default_tags come first; tags passed via MONSYS_TAGS or the
Terraform tags variable are appended (deduplicated). Same for role:
the token default wins unless the installer is given an explicit
MONSYS_ROLE.
Audit
Every registration is recorded in enrolment_uses with:
- token id
- new agent id
- source IP
- timestamp
When 100 agents appear in 5 minutes you can see immediately in the enrolment-tokens list which token authorised them, and you can revoke it in one click if there’s a suspicious host in the batch.
Failure modes
All cases below return 401 — deliberately indistinguishable to deny an
attacker useful signal:
- token doesn’t exist (wrong hash)
- token expired (
expires_atpassed) - token revoked
max_usesreached- source IP outside
allowed_cidrs
Operator feedback comes from the dashboard (uses counter, expiry, status).
Rotation
Tokens don’t renew themselves — you mint a new one and revoke the old when the batch is done. Registered agents keep working; only new registrations through that token are blocked.