Skip to content

Your first fleet

A fleet is one CloudFormation foundation in one AWS account and region, plus the agents you create in it. This page takes you from an empty account to a first running agent. The operations runbook has the detail behind each step.

You need four things in place before init will succeed.

An AWS profile. Add one to ~/.aws/config for the account you want to use. SSO, assume-role and static credentials all work. hermetic reads the profile you pick and ignores AWS_PROFILE and AWS_ACCESS_KEY_ID; it warns if either is set. The profile needs permission to create a CloudFormation stack, DynamoDB tables, an S3 bucket, and EC2 and SSM resources.

A tag owner in your tailnet policy. Paste this one line into your Tailscale policy file first, because the OAuth client form only offers tags that already have an owner:

"tagOwners": { "tag:hermetic": ["autogroup:admin"] }

That is the only policy edit you make by hand. hermetic writes its own ssh and acls entries later.

A Tailscale OAuth client. Create it in the Tailscale admin console; there is no API for this. Give it these scopes:

Scope Restricted to What hermetic uses it for
auth_keys write tag:hermetic Minting each agent’s join key
devices:core read and write tag:hermetic Checking device drift in doctor, removing an old device on recreate and destroy
policy_file whole tailnet Keeping hermetic’s own entries in your policy file current

Tailscale cannot restrict policy_file to a tag. If you would rather not grant it, leave it off and paste the entries yourself; hermetic policy prints them. Copy the client secret when Tailscale shows it; it is shown once.

HTTPS certificates on the tailnet. Turn on MagicDNS and HTTPS Certificates in the admin console’s DNS settings. Every agent serves its dashboard over HTTPS on its tailnet name, and init --create refuses without it. Agent hostnames will appear in public Certificate Transparency logs.

Open the app. A home that has never been initialized opens the init wizard: pick a profile, check the connection, create or attach to the foundation, and watch it run.

Or use the CLI:

Terminal window
hermetic init # attach if this account already has a foundation, else create one
hermetic init --create # create, and fail if one exists
hermetic init --attach # attach, and fail if none exists

init resolves your identity through STS and shows you the twelve-digit account id. On the CLI you type it back; in the app you tick a box confirming it is the account you mean, and the core checks it again either way. From then on this home is frozen to that account, and every command re-checks STS before it touches AWS.

When it creates a foundation, init:

  • creates a CloudFormation stack named hermetic-<fleet_id> with a dedicated VPC, a security group with no inbound rules, one IAM role for the fleet’s agents, a versioned S3 bucket and two DynamoDB tables;
  • stores the Tailscale OAuth secret in SSM Parameter Store;
  • writes hermetic’s entries into your tailnet policy between // hermetic:managed markers, as its last step, if the client has policy_file. Pass --skip-policy if you deploy the policy from git.

Then check the result:

Terminal window
hermetic doctor

doctor compares the agents table, EC2’s view of managed instances and Tailscale’s device list, and reports the account and fleet guard.

Terminal window
hermetic agent create atlas

With no flags you get a medium agent (t4g.2xlarge, 8 vCPU, 32 GiB) with a 100 GiB data volume, using the fleet’s default provider profile. It takes about eight minutes. Follow it with hermetic agent status atlas or the dashboard’s progress drawer.

If a create fails, the agent is left half-made on purpose. Run the same command again to finish it, or hermetic agent destroy atlas --yes to clear it. --rollback-on-failure undoes what the run itself created instead.

Terminal window
hermetic ssh atlas # Tailscale SSH, no key pair
hermetic logs atlas -f # stream the agent's logs

The agent’s dashboard is served at https://<fleet_id>-<name>.<tailnet>.ts.net to anyone your tailnet policy lets reach tag:hermetic on port 443. It has no login of its own. Read the security model before you widen that ACL.