Merge remote-tracking branch 'origin/main' into feat/hostclaim-moves-recovery
2 files changed,
+6
−9
infra/remote-host.md+5 −8internal/lease/endpoint.go+1 −1
CI passed — run details
diff --git a/infra/remote-host.md b/infra/remote-host.md| index f08826c0a..dfe9fed54 100644 |
| --- a/infra/remote-host.md |
| +++ b/infra/remote-host.md |
| @@ -16,14 +16,13 @@ GOOS-GOARCH — linux-arm64 or linux-amd64; a 32-bit OS resolves nothing). |
| Roles Anywhere is the long-term, hq-grade alternative (no long-lived |
| key on the box at all). |
| -2. Stage `/etc/carlos/credentials` (mode 0600): |
| +2. Stage `/etc/carlos/credentials`, owned by root, group `carlos`, mode 0640: |
| [default] |
| aws_access_key_id=... |
| aws_secret_access_key=... |
| - `carlos bootstrap -offcloud` refuses to proceed if this file is |
| - missing or not exactly 0600 — it will name this path in the error. |
| + Static keys only. `carlos bootstrap -offcloud` refuses to proceed if this file is missing or is not mode 0600 or 0640. It will name this path in the error. The agent will not use a file that holds anything else, such as a `credential_process` line or a second profile. |
| 3. Stage `/etc/carlos/host.env` — the usual agent env, plus the |
| credentials pointer and the three tunnel variables. All three tunnel |
| @@ -35,15 +34,13 @@ GOOS-GOARCH — linux-arm64 or linux-amd64; a 32-bit OS resolves nothing). |
| CARLOS_TUNNEL_TOKEN=<this host's token> |
| CARLOS_TUNNEL_NAME=<this host's channel name> |
| + Do not set `AWS_PROFILE` or `AWS_DEFAULT_PROFILE` in `host.env`. The agent ignores both and logs an alert. |
| + |
| 4. Stage the binary at `/opt/carlos/carlos` (matching GOOS-GOARCH). |
| 5. Run: `carlos bootstrap -offcloud` |
| - This does everything the normal `carlos bootstrap` does (units, dirs, |
| - service user, timers) and, before any of it, checks the credentials |
| - precondition from step 2 — a failed check leaves the box untouched. On |
| - a live root it also chowns the credentials file to the service user |
| - (still mode 0600). |
| + This does everything the normal `carlos bootstrap` does (units, dirs, service user, timers) and, before any of it, checks the credentials precondition from step 2. A failed check leaves the box untouched. On a live root, bootstrap and every agent start rewrite the credentials file as a new file owned by root, group `carlos`, mode 0640, keeping only the static keys. The service user can read it but not change it. A file that is already right is left alone. |
| 6. `systemctl start carlos-edge.service` |
diff --git a/internal/lease/endpoint.go b/internal/lease/endpoint.go| index 37deb79a4..4ec0156a9 100644 |
| --- a/internal/lease/endpoint.go |
| +++ b/internal/lease/endpoint.go |
| @@ -125,7 +125,7 @@ func newReplicaClient(bucket, prefix, region string) (*lss3.ReplicaClient, error |
| return newReplicaClientForUID(bucket, prefix, region, os.Geteuid(), rootaws.OffcloudCredentials) |
| } |
| -var errRootReplicaSessionToken = errors.ErrUnsupported |
| +var errRootReplicaSessionToken = errors.New("root Litestream cannot use a session token from /etc/carlos/credentials. set the keys in the environment instead, or use an EC2 instance profile") |
| func newReplicaClientForUID(bucket, prefix, region string, euid int, offcloud func() (aws.Credentials, error)) (*lss3.ReplicaClient, error) { |
| c := lss3.NewReplicaClient() |