Documentation Index
Fetch the complete documentation index at: https://docs.ryoku.dev/llms.txt
Use this file to discover all available pages before exploring further.
Ryoku ISO Release Pipeline
How a Ryoku ISO gets built, signed, and published. The local equivalent of this flow isiso/bin/ryoku-iso-release (uses 1Password for
credentials); CI uses GitHub Secrets instead.
What runs in CI
.github/workflows/build-iso.yml builds the ISO end to end on a
GitHub-hosted ubuntu-latest runner:
- Checkout (full history so
.gitships into the ISO via--local-source) - Verify required secrets are present, fail with a clear message if not
- Free disk space on the runner (strip preinstalled toolchains we do not use)
- Build the ISO via
iso/bin/ryoku-iso-make --local-source --no-boot-offer - Prepare a support tracking ID (
r<run-number>-<short-sha>) and pass it into the ISO build. The live image also gets/etc/ryoku-iso-releasewith the same ID, commit, run URL, channel, and build timestamp. - Sign the ISO with the GPG key from
GPG_PRIVATE_KEYsecret, then export the public key asryoku-release-key.pub.ascso testers can verify - Generate
<iso>.sha256containing the iso + sig hashes - Generate
<iso>.json,<iso>.js, and channel-levellatest.json/latest.jsrelease manifests - Upload the ISO, signature, checksum, manifests, and public key to Cloudflare R2 via rclone
- Attach the same files as a workflow-run artifact for 14 days as a fallback
Triggers
workflow_dispatch(manual). Pick a release channel (stable,rc,edge). Defaultstable.- Pushing a
v*tag (e.g.v0.1.0). Always builds thestablechannel.
GitHub Secrets the workflow needs
Configure under Settings -> Secrets and variables -> Actions in the repo.| Secret | Required | Purpose |
|---|---|---|
R2_ACCESS_KEY_ID | yes | Cloudflare R2 API token, access key ID |
R2_SECRET_ACCESS_KEY | yes | Cloudflare R2 API token, secret access key |
R2_ENDPOINT | yes | Account-scoped R2 endpoint, e.g. https://<account>.r2.cloudflarestorage.com |
R2_BUCKET | optional | Bucket + prefix to upload into. Defaults to ryoku/<channel>. Set to e.g. ryoku-iso/stable if you use a different bucket name. |
GPG_PRIVATE_KEY | yes | Armored private GPG signing key, full block including -----BEGIN PGP PRIVATE KEY BLOCK----- and -----END PGP PRIVATE KEY BLOCK----- |
GPG_PASSPHRASE | optional | Passphrase for the GPG key, omit if the key has no passphrase |
Setting up Cloudflare R2
- Cloudflare dashboard -> R2 -> Create bucket. Name it whatever (the workflow defaults to
ryoku/<channel>as the upload path; if your bucket is also namedryokuyou do not need to setR2_BUCKET). - R2 -> Manage R2 API Tokens -> Create token. Permission: “Object Read & Write” on this bucket only. Copy the access key ID + secret access key when shown (they are not shown again).
- From the bucket detail page, copy the S3-compatible endpoint URL:
https://<account>.r2.cloudflarestorage.com. - Bucket settings -> Public Access -> enable the
r2.devsubdomain (development only, rate-limited) OR connect a custom domain (recommended for production). Ryoku uses the custom domainiso.ryoku.devconnected via Cloudflare DNS. - Add the three R2 values + the
GPG_PRIVATE_KEY(and passphrase if any) to GitHub Secrets.
Setting up the GPG signing key
If you do not already have a Ryoku release key:-----BEGIN/-----END lines) into the
GitHub Secret GPG_PRIVATE_KEY. Delete ryoku-release-key.asc from disk after pasting.
Export the public key for users to verify against:
ryoku-release-key.pub.asc to the repo (or publish to a key
server) so users have something to verify against. Standard locations:
keys/ryoku-release-key.pub.ascin the repo (canonical, bound to the source tree under tag history)- The R2 bucket alongside each release ISO (uploaded automatically by the workflow as a fallback for users who only have the ISO URL)
https://ryoku.dev/release-key.asconce the site is live
README.md
so a substituted pubkey would be obvious. Get it with:
Triggering a build
Manual:- GitHub repo -> Actions -> Build ISO
- Run workflow -> select channel -> Run
Where users download
After a successful run, the bucket has:r12-9019b9b segment in the example above. Ask
users for this value when triaging ISO or installer reports. In a booted
live ISO it is also available at /etc/ryoku-iso-release.
Public download URLs (served through Cloudflare CDN via the
iso.ryoku.dev custom domain):
latest.json is the website source of truth. latest.js exposes the same
payload as window.RYOKU_ISO_RELEASE for static pages that cannot fetch JSON
directly. The manifest contains the current tracking ID, commit, workflow run
URL, filenames, public URLs, and SHA256 values for the ISO and detached
signature. Do not make the website guess the ISO name from the latest workflow
date.
How users verify the ISO
Failure modes worth knowing
- Disk space exhausted on runner. Visible as
mkarchisofailing to write the squashfs. TheFree disk spacestep strips ~25 GB of preinstalled toolchains; if a future bump pushes the build past that, switch to a self-hosted runner or use alargerGitHub-hosted runner. - Build timeout. Workflow
timeout-minutes: 120. Cold builds rarely exceed 60 min; if Apple T2 orlinux-ptlget added to the boot overlay later, this may need to grow. - GPG sign fails. Usually a malformed
GPG_PRIVATE_KEY(missing the BEGIN/END lines, or a stray newline broke the armored block). Re-export and re-paste. - rclone upload fails. Typically an
R2_ENDPOINTmismatch (must be the account-scoped one, not the bucket URL).
Local equivalent (no CI required)
iso/bin/ryoku-iso-release v0.1.0 does the same chain locally if you have:
- 1Password CLI (
op) logged into the Ryoku account, OR - Manually configured
~/.config/rclone/rclone.confwith the[Ryoku]remote - A GPG signing key in your default keyring

