Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,29 +55,32 @@ skip rests on it.
- **[go-task](https://taskfile.dev/)**: `brew install go-task`.
- **The 1Password CLI** `op`, signed in, for anything that needs the vault on the laptop.
- **Accounts**: two GitHub tokens, Proton Drive, a Cloudflare R2 bucket, a healthchecks.io
check, and a 1Password vault dedicated to this repo.
check, and a 1Password vault.

## 🚀 First-time setup

Every value that names an account is stored in the vault and referenced in
[op.env](op.env), ten `op://katoptra-github/<item>/<field>` lines:
[op.env](op.env), ten `op://<vault>/github/<section>/<field>` lines, one item with five
sections:

| Item | Fields | Reaches a run as |
| Section | Fields | Reaches a run as |
|---|---|---|
| `github` | `token_jshvn`, `token_katoptra` | `MIRROR_GITHUB_TOKEN_JSHVN`, `MIRROR_GITHUB_TOKEN_KATOPTRA` |
| `proton` | `destination`, `destination_uid` | `MIRROR_PROTON_DESTINATION`, `MIRROR_PROTON_DESTINATION_UID` |
| `r2` | `access_key_id`, `secret_access_key`, `endpoint`, `bucket` | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_ENDPOINT_URL_S3`, `MIRROR_R2_BUCKET` |
| `age` | `identity` | `MIRROR_AGE_IDENTITY` |
| `healthcheck` | `url` | `HEALTHCHECK_URL` |

1. **1Password.** Create the vault `katoptra-github` and a service account scoped to it
alone. Store the service-account token as the one repository secret,
`OP_SERVICE_ACCOUNT_TOKEN`.
1. **1Password.** An item `github` with the five sections above, in the vault `op.env`
names by UUID. This organization keeps one vault, `Katoptra`, with one item per mirror,
and one service account that reads it, stored as the organization secret
`OP_SERVICE_ACCOUNT_TOKEN`. A fork makes its own vault and service account and puts
the token in a repository secret of the same name.
2. **GitHub.** One fine-grained personal access token per owner, since a fine-grained token
has exactly one resource owner: one with jshvn as the owner, one with katoptra, each
for all repositories with `Contents: read` and `Metadata: read` and nothing else. The
mirror can never write to GitHub. An owner whose token lists another owner's
repositories fails the run. Store them as the two fields of item `github`.
repositories fails the run. Store them as the two fields of section `github`.
3. **Proton Drive.** The CLI can only be seeded by a browser sign-in, so the session is
made once on the laptop and carried to CI encrypted. It is this mirror's own: two
mirrors sharing one session race its rotating refresh token, and the loser needs a
Expand Down
22 changes: 11 additions & 11 deletions op.env
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# op:// references only; `op run --env-file=op.env` resolves them at run time.
# The vault is addressed by name; a vault name with a slash needs its UUID instead.
MIRROR_GITHUB_TOKEN_JSHVN=op://katoptra-github/github/token_jshvn
MIRROR_GITHUB_TOKEN_KATOPTRA=op://katoptra-github/github/token_katoptra
MIRROR_PROTON_DESTINATION=op://katoptra-github/proton/destination
MIRROR_PROTON_DESTINATION_UID=op://katoptra-github/proton/destination_uid
AWS_ACCESS_KEY_ID=op://katoptra-github/r2/access_key_id
AWS_SECRET_ACCESS_KEY=op://katoptra-github/r2/secret_access_key
AWS_ENDPOINT_URL_S3=op://katoptra-github/r2/endpoint
MIRROR_R2_BUCKET=op://katoptra-github/r2/bucket
MIRROR_AGE_IDENTITY=op://katoptra-github/age/identity
HEALTHCHECK_URL=op://katoptra-github/healthcheck/url
# Vault Katoptra, item github, addressed by UUID so a rename cannot break it.
MIRROR_GITHUB_TOKEN_JSHVN=op://y6y6b6l2zjbpv7szc5ym5sprne/github/github/token_jshvn
MIRROR_GITHUB_TOKEN_KATOPTRA=op://y6y6b6l2zjbpv7szc5ym5sprne/github/github/token_katoptra
MIRROR_PROTON_DESTINATION=op://y6y6b6l2zjbpv7szc5ym5sprne/github/proton/destination
MIRROR_PROTON_DESTINATION_UID=op://y6y6b6l2zjbpv7szc5ym5sprne/github/proton/destination_uid
AWS_ACCESS_KEY_ID=op://y6y6b6l2zjbpv7szc5ym5sprne/github/r2/access_key_id
AWS_SECRET_ACCESS_KEY=op://y6y6b6l2zjbpv7szc5ym5sprne/github/r2/secret_access_key
AWS_ENDPOINT_URL_S3=op://y6y6b6l2zjbpv7szc5ym5sprne/github/r2/endpoint
MIRROR_R2_BUCKET=op://y6y6b6l2zjbpv7szc5ym5sprne/github/r2/bucket
MIRROR_AGE_IDENTITY=op://y6y6b6l2zjbpv7szc5ym5sprne/github/age/identity
HEALTHCHECK_URL=op://y6y6b6l2zjbpv7szc5ym5sprne/github/healthcheck/url