KAMOS: gaming OS based on Bazzite stable, built via Forgejo Actions + Coolify runner

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
kmk1971 2026-07-29 17:57:49 +04:00
commit 6e3878f8c0
10 changed files with 338 additions and 0 deletions

View file

@ -0,0 +1,56 @@
name: Build KAMOS installer ISO
on:
workflow_dispatch:
inputs:
variant:
description: "Which variant to build an ISO for"
required: true
default: "kamos"
type: choice
options:
- kamos # AMD / Intel graphics
- kamos-nvidia # NVIDIA graphics
env:
# CHANGE_ME: your Forgejo domain (no https://)
REGISTRY_HOST: git.example.com
jobs:
build-iso:
name: ISO for ${{ inputs.variant }}
runs-on: ubuntu-latest
steps:
- name: Set image ref
run: |
echo "OWNER=${GITHUB_REPOSITORY_OWNER,,}" >> "$GITHUB_ENV"
echo "DATE_TAG=$(date +%Y%m%d)" >> "$GITHUB_ENV"
- name: Build ISO with bootc-image-builder
# Runs as a sibling container on the host Docker daemon (needs the
# kamos package set to PUBLIC in Forgejo so it can pull the image).
run: |
docker volume rm -f kamos-bib-output 2>/dev/null || true
docker volume create kamos-bib-output
docker run --rm --privileged \
-v kamos-bib-output:/output \
quay.io/centos-bootc/bootc-image-builder:latest \
--type anaconda-iso \
"${REGISTRY_HOST}/${OWNER}/${{ inputs.variant }}:stable"
- name: Extract ISO from volume
run: |
docker create --name kamos-bib-extract -v kamos-bib-output:/output alpine
docker cp "kamos-bib-extract:/output/bootiso/install.iso" \
"./${{ inputs.variant }}-${DATE_TAG}.iso"
docker rm kamos-bib-extract
docker volume rm kamos-bib-output
- name: Upload ISO to Forgejo package registry
run: |
ISO="${{ inputs.variant }}-${DATE_TAG}.iso"
curl --fail -u "${{ secrets.REGISTRY_USER }}:${{ secrets.REGISTRY_TOKEN }}" \
--upload-file "$ISO" \
"https://${REGISTRY_HOST}/api/packages/${OWNER}/generic/kamos-iso/${DATE_TAG}/${ISO}"
echo "ISO available at: https://${REGISTRY_HOST}/${OWNER}/-/packages/generic/kamos-iso/${DATE_TAG}"

View file

@ -0,0 +1,59 @@
name: Build KAMOS images
on:
push:
branches: [main]
paths-ignore:
- "README.md"
schedule:
# Weekly rebuild so KAMOS picks up upstream Bazzite stable updates
- cron: "0 6 * * 2"
workflow_dispatch:
env:
# CHANGE_ME: your Forgejo domain (no https://)
REGISTRY_HOST: git.example.com
jobs:
build:
name: Build ${{ matrix.image_name }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- image_name: kamos
base_image: ghcr.io/ublue-os/bazzite
- image_name: kamos-nvidia
base_image: ghcr.io/ublue-os/bazzite-nvidia
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set image ref
run: |
echo "IMAGE=${REGISTRY_HOST}/${GITHUB_REPOSITORY_OWNER,,}/${{ matrix.image_name }}" >> "$GITHUB_ENV"
echo "DATE_TAG=$(date +%Y%m%d)" >> "$GITHUB_ENV"
- name: Build image (uses host Docker via mounted socket)
run: |
docker build \
--build-arg BASE_IMAGE="${{ matrix.base_image }}" \
--build-arg BASE_TAG=stable \
-t "${IMAGE}:stable" \
-t "${IMAGE}:latest" \
-t "${IMAGE}:${DATE_TAG}" \
.
- name: Push to Forgejo container registry
run: |
echo "${{ secrets.REGISTRY_TOKEN }}" | \
docker login "${REGISTRY_HOST}" -u "${{ secrets.REGISTRY_USER }}" --password-stdin
for tag in stable latest "${DATE_TAG}"; do
docker push "${IMAGE}:${tag}"
done
- name: Clean up build cache (keep server disk healthy)
if: always()
run: docker image prune -f

5
.gitattributes vendored Normal file
View file

@ -0,0 +1,5 @@
* text=auto eol=lf
*.sh text eol=lf
Containerfile text eol=lf
*.yml text eol=lf
*.toml text eol=lf

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
output/
*.iso

22
Containerfile Normal file
View file

@ -0,0 +1,22 @@
# KAMOS — gaming OS built on top of Bazzite (stable channel)
#
# BASE_IMAGE is switched by CI to build the two variants:
# ghcr.io/ublue-os/bazzite -> KAMOS (AMD / Intel graphics)
# ghcr.io/ublue-os/bazzite-nvidia -> KAMOS NVIDIA (proprietary driver)
ARG BASE_IMAGE="ghcr.io/ublue-os/bazzite"
ARG BASE_TAG="stable"
FROM ${BASE_IMAGE}:${BASE_TAG}
LABEL org.opencontainers.image.title="KAMOS"
LABEL org.opencontainers.image.description="KAMOS — stable Linux gaming OS for PCs and laptops, based on Bazzite stable"
LABEL org.opencontainers.image.vendor="KAMOS"
# Overlay static files (branding, configs) onto the image
COPY system_files /
# Run the build script (install packages, rebrand, tweak defaults)
COPY build_files /tmp/build_files
RUN bash /tmp/build_files/build.sh && \
rm -rf /tmp/build_files && \
ostree container commit

135
README.md Normal file
View file

@ -0,0 +1,135 @@
# KAMOS — Gaming Linux OS
KAMOS is a custom Linux gaming operating system for PCs and laptops, built on top of
[Bazzite](https://bazzite.gg)'s **stable** channel (Fedora Atomic). It is an
*image-based* OS: the whole system ships as one tested image, updates are atomic,
and you can roll back from the boot menu if an update ever misbehaves.
Everything Bazzite ships is included out of the box: Steam with Proton, Gamescope,
MangoHud, GameMode, HDR/VRR support, the fsync gaming kernel, KDE Plasma, Distrobox,
and Waydroid.
KAMOS is built and hosted entirely on **your own Forgejo instance** — Forgejo
Actions builds the images, and Forgejo's container/package registry serves them.
The build runner is deployed as a **Coolify service** (your existing Forgejo is
not modified in any way).
## Variants
| Image | For |
|---|---|
| `kamos` | AMD and Intel graphics (uses built-in Mesa drivers) |
| `kamos-nvidia` | NVIDIA graphics (proprietary driver pre-installed) |
Both work on desktops and laptops. For laptops with hybrid AMD+NVIDIA or
Intel+NVIDIA graphics, use `kamos-nvidia`.
## One-time setup
Server needs **~40 GB free disk** and 4+ GB RAM. Coolify's job here is only to
run the build runner container — the runner connects to Forgejo with a token;
your existing Forgejo service is untouched.
### 1. Get a runner registration token from Forgejo
Forgejo → **Site administration → Actions → Runners → Create new runner**
copy the registration token. (This only *creates a token*; it changes nothing.)
### 2. Deploy the runner in Coolify
Coolify → your project → **New Resource** → search `git` → select **Gitea Runner**
(Forgejo's Actions runner is compatible with Gitea's — there is no separate
Forgejo Runner template). Before deploying, set the environment variables:
| Variable | Value |
|---|---|
| `GITEA_INSTANCE_URL` | `https://YOUR-FORGEJO-DOMAIN` |
| `GITEA_RUNNER_REGISTRATION_TOKEN` | the token from step 1 |
| `GITEA_RUNNER_NAME` | `kamos-builder` |
| `GITEA_RUNNER_LABELS` | `ubuntu-latest:docker://ghcr.io/catthehacker/ubuntu:act-22.04` |
(`GITEA_TOKEN` can stay empty — it's an alternative to the registration token.)
Then, still in the service before/after first deploy:
1. **Storages → Add File Mount**: destination `/config.yaml`, content = the file
[`coolify/runner-config.yaml`](coolify/runner-config.yaml) from this repo.
This lets build jobs use the host Docker daemon (required).
2. Add env var `CONFIG_FILE=/config.yaml`.
3. Deploy. In Forgejo → Site administration → Runners, `kamos-builder` should
appear as **online** with the `ubuntu-latest` label.
### 3. Configure the repo
1. Create a repository named `kamos` on your Forgejo and push this folder to it
(make sure Repository → Settings → **Actions** is enabled).
2. In both workflow files under `.forgejo/workflows/`, change
`REGISTRY_HOST: git.example.com` to your Forgejo domain.
3. In Forgejo: your avatar → **Settings → Applications → Generate new token**
with `package` read/write scope. Then in the repo:
**Settings → Actions → Secrets**, add:
- `REGISTRY_USER` — your Forgejo username
- `REGISTRY_TOKEN` — the token you just generated
4. Push to `main` — the **Build KAMOS images** workflow builds both variants
(3060 min first run; the ~8 GB Bazzite base download is cached after that).
5. After the first build: profile → **Packages**`kamos` and `kamos-nvidia`
package settings → visibility **Public** (so installed machines and the ISO
builder can pull without credentials).
### 4. Build an installer ISO
Repo → **Actions → Build KAMOS installer ISO → Run workflow** → pick `kamos` or
`kamos-nvidia`. The finished ISO is uploaded to your Forgejo **package registry**
under `kamos-iso` — download it from your profile's Packages page.
The weekly scheduled rebuild keeps KAMOS current with upstream Bazzite stable and
Fedora security updates; installed machines pick these up automatically.
## Installing
**Fresh install:** write the ISO to a 16 GB+ USB stick with
[Fedora Media Writer](https://fedoraproject.org/workstation/download) or
[Rufus](https://rufus.ie) (DD mode), boot from it, and follow the installer.
**Already running Bazzite / Fedora Atomic?** Rebase without reinstalling:
```bash
rpm-ostree rebase ostree-unverified-registry:YOUR-FORGEJO-DOMAIN/YOUR-USERNAME/kamos:stable
```
(use `kamos-nvidia:stable` for NVIDIA), then reboot.
> **Secure Boot:** Bazzite's kernel is signed with Universal Blue's key. Either
> disable Secure Boot in the BIOS, or enroll the key as described in the
> [Bazzite docs](https://docs.bazzite.gg/General/Installation_Guide/secure_boot/).
## Customizing KAMOS
- **Add packages baked into the OS:** edit `build_files/build.sh`
(`dnf5 -y install <package>`), push — CI rebuilds the image.
- **Add config files:** drop them under `system_files/` mirroring the target
path (e.g. `system_files/etc/foo.conf``/etc/foo.conf`).
- **Apps like Heroic, Lutris, Discord, OBS:** install as Flatpaks after boot
(Discover app store) — that's the intended pattern on image-based systems.
- **Download page:** if you want a public KAMOS website with download links,
deploy a small static site with Coolify pointing at the ISO URLs in your
Forgejo package registry.
## Building locally (optional)
Requires Linux or WSL2 with `podman` or `docker`:
```bash
docker build --build-arg BASE_IMAGE=ghcr.io/ublue-os/bazzite --build-arg BASE_TAG=stable -t kamos:stable .
```
## Layout
```
Containerfile OS image recipe (FROM bazzite:stable)
build_files/build.sh packages + branding applied at build time
system_files/ files overlaid onto the OS (/etc, /usr, ...)
disk_config/iso.toml installer ISO configuration (optional kickstart)
coolify/runner-config.yaml runner config for the Coolify Gitea Runner service
.forgejo/workflows/ CI: image build + ISO build (Forgejo Actions)
```

35
build_files/build.sh Normal file
View file

@ -0,0 +1,35 @@
#!/usr/bin/env bash
# KAMOS build script — runs once at image build time (not on user machines).
set -euxo pipefail
### ---------------------------------------------------------------
### 1. Branding: rename the OS to KAMOS
### (NAME/PRETTY_NAME only — ID/VERSION stay untouched so Bazzite
### and Fedora tooling keeps working)
### ---------------------------------------------------------------
sed -i 's/^NAME=.*/NAME="KAMOS"/' /usr/lib/os-release
sed -i 's/^PRETTY_NAME=.*/PRETTY_NAME="KAMOS (Gaming Edition)"/' /usr/lib/os-release
### ---------------------------------------------------------------
### 2. Extra packages layered on top of Bazzite
### Bazzite stable already ships: Steam, Gamescope, Proton (via
### Steam), MangoHud, vkBasalt, gamemode, Lutris deps, Waydroid,
### Distrobox, KDE Plasma, HDR/VRR support, fsync kernel.
### Add anything extra you want baked into the OS here.
### ---------------------------------------------------------------
dnf5 -y install \
btop \
fastfetch
# Examples (uncomment to include):
# dnf5 -y install openrgb # RGB peripheral control
# dnf5 -y install corectrl # AMD GPU/CPU tuning UI
# dnf5 -y install input-remapper # remap controller/keyboard
### ---------------------------------------------------------------
### 3. System defaults
### ---------------------------------------------------------------
# Enable weekly automatic OS updates (staged, applied on reboot)
systemctl enable rpm-ostreed-automatic.timer || true
echo "KAMOS build complete."

View file

@ -0,0 +1,11 @@
# act_runner / Forgejo runner config — paste this as a File Mount in the
# Coolify "Gitea Runner" service at /config.yaml, and add env CONFIG_FILE=/config.yaml
#
# Purpose: lets the job containers reach the host Docker daemon, which the
# KAMOS workflows need for `docker build` and bootc-image-builder.
log:
level: info
container:
options: "-v /var/run/docker.sock:/var/run/docker.sock"
valid_volumes:
- /var/run/docker.sock

10
disk_config/iso.toml Normal file
View file

@ -0,0 +1,10 @@
# bootc-image-builder config for the KAMOS installer ISO.
# The generated ISO uses the Anaconda installer (same as Fedora/Bazzite):
# the user picks disk, username and password during install.
# Example: preset keyboard/locale (uncomment and edit if wanted)
# [customizations.installer.kickstart]
# contents = """
# keyboard us
# lang en_US.UTF-8
# """

3
system_files/etc/motd Normal file
View file

@ -0,0 +1,3 @@
Welcome to KAMOS — Gaming Edition
Based on Bazzite stable (Fedora Atomic). Updates are atomic; roll back
from the boot menu if anything breaks.