Repository navigation
docs: refresh infra docs for post-Hetzner architecture #57
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
abtreece
wants to merge
8
commits into
fullstaq-ruby:main
Choose a base branch
from
abtreece:docs/post-hetzner-refresh
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
05f8966
docs: refresh infra docs for post-Hetzner architecture
abtreece f754aa2
docs: clarify CI artifacts storage section
abtreece b13c909
docs(apiserver): rewrite README for post-Hetzner hosting
abtreece b0b5fe7
docs: add API server deployment step to bootstrapping guide
abtreece dcb6700
docs: reference .github/workflows/ instead of apiserver.yml
abtreece fd09d2f
docs: simplify API server bootstrapping step
abtreece cfb8b15
docs: trim drift-prone detail and fix stale refs in infra overview
abtreece 0d01a99
docs: restore drawio infrastructure diagram in place of Mermaid
abtreece File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,17 +1,58 @@ | ||
| # API server | ||
|
|
||
| The API server is a service that allows performing limited management operations on the infrastructure. It mainly exists to securely allow the Server Edition's CI to tell Caddy about the fact that new packages have been deployed. | ||
| The API server is a small service that exposes a couple of privileged management | ||
| operations to the project's GitHub Actions workflows — primarily so that CI can | ||
| trigger restarts of Caddy and self-upgrades of the API server itself, without | ||
| needing SSH access to the backend host. | ||
|
|
||
| Presently, there is only one endpoint: `POST /admin/restart_web_server`. This endpoint initiates restarting of Caddy, but does not wait for it to finish. | ||
| It runs as a systemd-managed Puma process (`apiserver.service`) on the Hetzner | ||
| backend host, listening on a Unix socket at `/run/apiserver/server.sock`. Caddy | ||
| reverse-proxies the `/admin/*` paths from `apt.fullstaqruby.org` and | ||
| `yum.fullstaqruby.org` to that socket — there is no dedicated `apiserver.*` | ||
| hostname. | ||
|
|
||
| ## Calling the production instance | ||
| ## Endpoints | ||
|
|
||
| The production instance is deployed at https://apiserver-f7awo4fcoa-uk.a.run.app/. To call it, you need to include your Google Cloud identity token in the Authorization header. | ||
| - `GET /` — health check, returns `ok`. | ||
| - `POST /admin/upgrade_apiserver` — kicks off `apiserver-deployer` (which fetches | ||
| the latest API server release from GitHub and activates it), then restarts | ||
| `apiserver` itself. Callable only from `fullstaq-ruby/infra`'s `deploy` | ||
| GitHub Actions environment. | ||
| - `POST /admin/restart_web_server` — restarts Caddy. Callable only from | ||
| `fullstaq-ruby/server-edition`'s `deploy` GitHub Actions environment. | ||
|
|
||
| ```bash | ||
| curl -v -H "Authorization: Bearer $(gcloud auth print-identity-token)" https://apiserver-f7awo4fcoa-uk.a.run.app/ | ||
| ``` | ||
| ## Authentication | ||
|
|
||
| The API server authenticates callers using **GitHub Actions OIDC**. Every | ||
| request must carry an `Authorization: Bearer <token>` header where the token | ||
| is an ID token minted by GitHub's OIDC provider with audience claim | ||
| `backend.fullstaqruby.org`. The server verifies the JWT signature against | ||
| GitHub's JWKS and rejects the request unless the token's `repository`, `sub`, | ||
| `runner_environment`, and `environment` claims match the calling repo's | ||
| expected `deploy` environment for that endpoint. | ||
|
|
||
| Because the audience and claim shape are tied to GitHub-hosted runners, the | ||
| endpoints are not callable directly by a human or from a local machine. | ||
|
|
||
| ## Continuous deployment | ||
|
|
||
| New API server code changes, when pushed to main, are automatically deployed by the Infrastructure project's CI. | ||
| API server builds and deployments are driven by two workflows in | ||
| `.github/workflows/`: | ||
|
|
||
| - **Test and build** (`test-and-build.yml`) runs on every push. When a push | ||
| touches `apiserver/**`, its `apiserver-build` job packages the API server | ||
| into a tarball and uploads it as a workflow artifact. | ||
| - **Deploy** (`deploy.yml`) runs after a successful Test and build run on | ||
| `main`. It tags the commit, publishes a GitHub release with the tarball, and | ||
| calls `POST https://apt.fullstaqruby.org/admin/upgrade_apiserver` with a | ||
| freshly minted OIDC token. | ||
|
|
||
| On the host, `apiserver-deployer` (a oneshot systemd unit running | ||
| `/usr/local/bin/apiserver-deployer`) handles the actual install: it fetches | ||
| the latest release metadata from the GitHub API, downloads the asset matching | ||
| the host's distribution and architecture, extracts it into | ||
| `/opt/apiserver/versions/<tag>-<dist>-<version>-<arch>`, installs any runtime | ||
| dependencies declared in `dpkg-dependencies.txt`, prunes all but the last five | ||
| versions, and atomically swaps the `/opt/apiserver/versions/latest` symlink. | ||
| The API server's working directory points at that symlink, so the subsequent | ||
| `systemctl restart apiserver` brings the new version online. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.