aethercert
Documentation

Unattended rollout

Rolling the agent out to a fleet: multi-provision tokens, golden images, cloud-init, configuration management and Group Policy.

Nothing extra is needed for a fleet rollout. It is the same install command with a multi-provision token, run by whatever already provisions your servers.

The token

Generate a multi-provision token under Manage > Agents. One token, one command, up to 500 hosts. Each host that redeems it becomes its own agent, named from its own reported hostname rather than from a name you typed.

Pick an agent group in the wizard before generating the token, and every host arrives already in that group - so a certificate policy on it applies before the agent's first ordinary check-in. Write the policy first, on an empty group, and servers provisioned months later get their certificate on the way up.

Tokens expire after an hour

A multi-provision token in an image is a secret in an image

The command

It is the same one-command install as on a single server, with the token in the command - exactly what the dashboard's enrollment wizard hands out:

curl -fsSL https://get.aethercert.com | sudo bash -s -- --token <token>

A provisioning run has no terminal - cloud-init, ssh without -t, a CI job, a remoting session, a scheduled task - so the script asks nothing and takes the token from --token / -Token or the AETHERCERT_TOKEN environment variable. Without either it stops with an error before downloading anything. A token in the command never stops for a review, terminal or not; -y / --yes (-Yes on Windows) additionally rules out every other question, such as the menu for a host that already runs aethercert.

LinuxWindowsMeaning
--token <token>-Token '<token>'The enrollment token. Both also read AETHERCERT_TOKEN.
--api <url>-Api '<url>'Control plane to enroll against. Both also read AETHERCERT_API.
--proxy <url>-Proxy '<url>'HTTPS proxy for the script's own downloads, and written into the agent's config.json.
--version <ver>-Version '<ver>'Pin a published installer version.
-y, --yes-YesNever ask anything.
-- <args>-InstallerArgs @(...)Passed straight to aethercert-installer - see below.

NO_COLOR turns off the Linux script's coloured output; a log that is not a terminal is never coloured anyway.

Naming the script explicitly

get.aethercert.com chooses the script by client - PowerShell gets install.ps1, everything else on the command line install.sh. Automation that should not depend on that guess can name the script directly; both addresses serve the same script to every client:

  • https://get.aethercert.com/install.sh
  • https://get.aethercert.com/install.ps1

Both verify the download against its published checksum - and, where release signing is configured, against a detached Ed25519 signature - before executing anything. Keep that property in whatever you script yourself.

Pin a version with --version / -Version so an image build is reproducible. Without it, the install tracks the current published build.

Existing automation keeps working

The commands handed out before get.aethercert.com existed fetch the same scripts from the CDN and remain supported, so a playbook, image recipe or GPO that uses them needs no change:

curl -fsSL https://cdn.aethercert.com/install.sh | sudo sh -s -- --token <token>
& ([scriptblock]::Create((irm https://cdn.aethercert.com/install.ps1))) -Token '<token>' -Yes

The Linux script is POSIX sh, so piping it into sh rather than bash is fine - and is what an Alpine host, which has no bash, needs.

Per-approach notes

ApproachHow
Golden imageBake the installer binary and the command into the image build. Pin a versioned CDN path so the image is reproducible. Mint the token at build time, since it will have expired long before the image is deployed - which means each build enrolls, not each boot.
cloud-init / user dataAdd the one-liner (curl -fsSL https://get.aethercert.com | bash -s -- --token <token> - cloud-init already runs as root) as a runcmd step, with the token injected by whatever renders the user data. This is the shape that works best with the one-hour expiry.
Ansible, Puppet, Chef, DSCRun the installer as an ordinary command resource, guarded by whether the service already exists. aethercert-installer status exits 0 either way, so it is safe as a check.
Group Policy / IntuneRun the script-block form with -Token and -Yes as a startup script, or deploy the installer binary and run it with the token as an argument.

A golden image enrolls once, not once per boot

Waiting for the install on Windows

The Windows installer is a GUI-subsystem executable, so PowerShell and cmd.exe do not wait for it. In a provisioning script that has to block:

Start-Process -Wait -NoNewWindow -FilePath .\aethercert-installer-windows-amd64.exe `
  -ArgumentList 'install','--api','https://api.aethercert.com','--token','<token>'

Piping its output also makes PowerShell wait.

Useful flags for a scripted install

FlagWhy
--quietPrint warnings and failures only.
--manual-startRegister the service without auto-start.
--no-startRegister it without starting it now.
--no-traySkip the tray icon on a headless Windows server.
--no-update-serviceSkip the Update Service. This host then never updates itself.
--service-account / --service-passwordRun the service as a named account instead of LocalSystem.
--config <path>An absolute path for config.json. Must be absolute; the installer rejects a relative one.
--lang en|deLanguage for the installer's own output.
--proxy <url> / --no-proxy <hosts>Hosts that reach the internet through a proxy - system uses the Windows machine proxy. Written into the component's config.json; see Outbound proxy.

The full list is in the CLI reference.

Behind a proxy

--proxy / -Proxy covers the script's own requests (the token check, the installer download, its checksum and signature) and is written into the agent's config.json. The very first request - the one that fetches the script itself - is not the script's yet, so give that one the proxy too:

curl -fsSL --proxy http://proxy.corp.example:3128 https://get.aethercert.com \
  | sudo bash -s -- --token <token> --proxy http://proxy.corp.example:3128
$env:AETHERCERT_TOKEN='<token>'
& ([scriptblock]::Create((irm -Proxy http://proxy.corp.example:3128 https://get.aethercert.com/install.ps1))) -Proxy 'http://proxy.corp.example:3128'

Without -Proxy, Windows uses the machine's proxy settings for the downloads.

Verifying a rollout

The dashboard's agent list is the reckoning: every host that redeemed the token appears there after its first check-in, with its hostname, version and last-seen time. An enrollment token's own page lists the agents that came from it, which is the quickest way to see whether 300 hosts became 300 agents.

On an individual host, aethercert-installer status prints what is installed and which control plane it points at.

On this page