sorcery-go/docs/GETTING_STARTED_SMGL_CHROOT.md

12 KiB
Executable File

Getting Started with an existing Source Mage chroot

"Resurrect the ancient tarball. Strip the relics. Drop in the new engine."

Note: Sorcery-Go is developed by dcos.net and is not affiliated with Source Mage GNU/Linux or sourcemage.org. This guide explains how to use Sorcery-Go with Source Mage chroots (which are produced by the Source Mage project). The two projects are independent.

This guide walks you through bringing a frozen Source Mage chroot tarball (the classic 0.62-11 release or a 0.63 test branch) into the modern era, then dropping in sorcery-go as the new engine — coexisting with the legacy Bash sorcery so you can migrate at your own pace.

The whole flow is automated by scripts/smgl-getting-started.sh. This document is the long-form companion: it explains why each phase exists, what to do when something breaks, and how the host-side and chroot-side subcommands fit together.


Why this guide exists

Source Mage hasn't seen an official stable ISO update in years. If you boot a raw 0.62-11 tarball on modern hardware it will crash on two fronts:

  1. Ancient kernel panic — no support for modern storage / NVMe controllers.
  2. GRUB 1 (Legacy) — can't read GPT partition tables or modern ext4 metadata.

On top of that, the toolchain inside the tarball is frozen at ~2017-era GCC/glibc, which can't compile modern spell recipes (GCC 15+, 6.x kernels, LLVM 22). So we stage everything inside a chroot from a modern host, rip out the broken pieces, and inject modern scaffolding before we ever try to boot.


The 8-phase pipeline

Phase What Where Script subcommand
1 Extract + mount API filesystems host extract, mount
2 Purge GRUB 1, cast GRUB 2 chroot chroot-purge-grub1, chroot-cast-grub2
3 Strip old kernel, inject modern host-built kernel host inject-kernel
4 Rewrite fstab with UUID identifiers host fix-fstab
5 Inject modern sorcery engine (Bash) host inject-sorcery
6 Set conservative CFLAGS for the step-upgrade chroot (part of chroot-stepupgrade)
7 Cut over from dead stable grimoire to live test branch chroot chroot-scribe-test
8 Step-upgrade ladder: make → binutils → gcc → glibc chroot chroot-stepupgrade
9 Drop in sorcery-go and init both inject-sorcery-go (host) + chroot-init-sorcery-go (chroot)

Prerequisites

On your modern host OS (the machine doing the surgery):

  • root (sudo) — required for mount, chroot, setcap
  • tar, wget, bash ≥ 4
  • A modern kernel build at /usr/src/linux/arch/x86/boot/bzImage (or wherever your custom 6.x kernel lives)
  • The matching module tree at /lib/modules/<version>
  • Go ≥ 1.21 (only if you want to build sorcery-go yourself; you can also use a pre-built binary)
  • setcap (from libcap) — optional, for non-root OverlayFS

On the chroot tarball:

  • source-mage-x86_64-0.62-11.tar.xz (or similar test-branch tarball)
  • ~2 GB free disk for the extracted rootfs + state

Walkthrough

Phase 1 — Extract + mount (host)

# From the sorcery-go project root:
sudo ./scripts/smgl-getting-started.sh extract \
    ~/Downloads/source-mage-x86_64-0.62-11.tar.xz \
    /mnt/AI/sourcemage_root

sudo ./scripts/smgl-getting-started.sh mount /mnt/AI/sourcemage_root

This bind-mounts /dev, /proc, /sys into the chroot and copies your host's /etc/resolv.conf so the chroot has working DNS. Don't skip the resolv.conf copy — without it every wget inside the chroot fails with "connection timed out" and you'll waste an hour debugging.

Phase 5 — Inject the modern Bash sorcery engine (host)

Do this before entering the chroot so the modern cast / scribe / dispel scripts are in place when you arrive:

sudo ./scripts/smgl-getting-started.sh inject-sorcery /mnt/AI/sourcemage_root

This downloads https://sourcemage.org/codex/sorcery-stable.tar.bz2 and overlays its usr/ and etc/sorcery/ into the chroot. If the download fails (firewall, dead mirror), pass a local copy:

sudo ./scripts/smgl-getting-started.sh inject-sorcery \
    /mnt/AI/sourcemage_root ~/Downloads/sorcery-stable.tar.bz2

Phase 3 — Inject a modern kernel (host)

You cannot compile a 6.x kernel with the 2017-era GCC inside the chroot — it'll segfault. Build the kernel on your modern host first, then slide it in:

sudo ./scripts/smgl-getting-started.sh inject-kernel \
    /mnt/AI/sourcemage_root \
    /usr/src/linux/arch/x86/boot/bzImage \
    /lib/modules/6.12.4-custom

The script purges /boot/vmlinuz*, /boot/initrd*, and /lib/modules/* before copying the new files in, so there's no risk of the bootloader finding a stale kernel.

Drop in sorcery-go (host)

Now is the time to drop the new engine in — but do not init it yet. The chroot's glibc is still ancient; sorcery-go init would index a grimoire it can't actually cast against.

# Build it first if you haven't:
make build

sudo ./scripts/smgl-getting-started.sh inject-sorcery-go \
    /mnt/AI/sourcemage_root

This installs to /usr/local/sbin/sorcery-go (NOT /usr/sbin/sorcery — the legacy Bash binary stays put). State goes to /var/lib/sorcery-go/, completely separate from /var/lib/sorcery/.

Phase 4 — Fix fstab (host)

sudo blkid /dev/sdX1   # find your root partition's UUID
sudo blkid /dev/sdX2   # and boot, if separate

sudo ./scripts/smgl-getting-started.sh fix-fstab \
    /mnt/AI/sourcemage_root \
    XXXX-XXXX-XXXX-XXXX \
    YYYY-YYYY

The original fstab is backed up to etc/fstab.pre-sorcery-go.bak.

Enter the chroot

sudo ./scripts/smgl-getting-started.sh enter /mnt/AI/sourcemage_root

This chroots in with a login shell and copies the script itself into /usr/local/sbin/smgl-getting-started.sh so the chroot-* subcommands work from inside.

Phase 2 — Purge GRUB 1, cast GRUB 2 (chroot)

smgl-getting-started.sh chroot-purge-grub1
smgl-getting-started.sh chroot-cast-grub2

chroot-cast-grub2 will likely fail at this point — the 2017-era toolchain can't compile modern GRUB. That's fine; skip it. After Phase 8 completes you can run grub-install from your modern host instead:

# From the host, after the step-upgrade:
sudo grub-install --boot-directory=/mnt/AI/sourcemage_root/boot /dev/sdX

Phase 7 — Cut over to the test grimoire (chroot)

smgl-getting-started.sh chroot-scribe-test

This drops the dead stable codex and anchors scribe to the live test branch:

scribe remove stable
scribe add test from git://download.sourcemage.org/smgl/grimoire.git

The test branch is where the active development happens — modern spells for GCC 15/16, LLVM 22, Firefox 151, and 6.x kernel configs land there daily. The stable grimoire is a museum piece; don't waste time on it.

If git:// is firewalled, the script falls back to https:// automatically.

Phase 8 — Step-upgrade the toolchain (chroot)

This is the most fragile phase. The script walks the ladder in the correct order:

smgl-getting-started.sh chroot-stepupgrade

What it does, in order:

  1. Phase 6 (prep) — writes conservative OPTIMIZATION_FLAGS="-O2 -march=native" to /etc/sorcery/config and disables experimental GCC flags. This prevents the ancient compiler from choking on modern syntax variations.

  2. 8.1 cast make — modern make first, so the rest of the ladder has a working build system.

  3. 8.2 cast binutils — modern assembler/linker so modern binary headers parse correctly.

  4. 8.3 cast gcc — an intermediate GCC that can parse modern syntax but can still be compiled by the ancient root compiler. If cast gcc tries to jump straight to GCC 15 and fails, edit the spell version downward (GCC 9 or 10 is a safe stepping stone).

  5. 8.4 cast glibc — the cutover. Once glibc builds, the runtime shifts under your feet: modern syscall wrappers (statx, clone3) are now bound to the chroot.

If any step segfaults, don't panic. Use the escape hatch from the path document: build the offending package statically on your modern host and copy the binary into the chroot's /usr/local/bin/:

# On the host:
gcc -static -o /tmp/modern-gcc-wrapper ...
cp /tmp/modern-gcc-wrapper /mnt/AI/sourcemage_root/usr/local/bin/

# Or copy a whole modern compiler:
cp -a /usr/bin/gcc-something /mnt/AI/sourcemage_root/usr/local/bin/gcc-host

Phase 9 — Init sorcery-go (chroot)

Now that the toolchain is modern, init the Go engine:

smgl-getting-started.sh chroot-init-sorcery-go

This runs sorcery-go init --force against the test grimoire, indexes every spell into memory, and prints the spell count. You should see thousands of spells indexed on a real test-branch grimoire.

Try your first Go-powered cast:

sorcery-go gaze depends wget
sudo sorcery-go cast busybox --static --default
sorcery-go tomb list

Launch the Coven Mirror WebUI:

sudo sorcery-go web --port 8080

Leave + unmount (host)

# Inside the chroot:
exit

# Back on the host:
sudo ./scripts/smgl-getting-started.sh unmount /mnt/AI/sourcemage_root

The rootfs is now safe to tar up, dd onto a partition, or NFS-export.


Troubleshooting

"dispel: command not found" inside the chroot

You skipped Phase 5 (inject-sorcery). Leave the chroot, run inject-sorcery from the host, then re-enter.

"scribe add test" fails with SSL errors

The chroot's CA certificates are 9 years old. Two options:

  1. Use the https fallback (the script tries it automatically).
  2. Copy modern certs from the host:
    sudo cp /etc/ssl/certs/ca-certificates.crt \
        /mnt/AI/sourcemage_root/etc/ssl/certs/ca-certificates.crt
    

"cast gcc" segfaults

The 2017-era compiler can't bootstrap a modern GCC. Use the escape hatch: copy a host-built intermediate GCC (9 or 10) into the chroot's /usr/local/bin/, then re-run cast gcc — it'll use the host binary as the bootstrap compiler.

"cast glibc" fails with "kernel headers too old"

The chroot's linux-headers are ancient. Cast a modern linux-headers spell first:

cast linux-headers
cast glibc

sorcery-go init reports 0 spells indexed

You're pointing at the wrong grimoire path. Check what scribe indexed:

ls /var/lib/sorcery/codex/
# Should show: test/  (and possibly stable/ if you didn't remove it)

Then set SORCERY_GO_GRIMOIRE=/var/lib/sorcery/codex/test and re-run sorcery-go init --force.

The chroot's network is dead

You probably skipped the resolv.conf copy in Phase 1. From the host:

sudo cp /etc/resolv.conf /mnt/AI/sourcemage_root/etc/resolv.conf

If your host uses systemd-resolved, the actual resolv.conf is at /run/systemd/resolve/resolv.conf — copy that instead.


Coexistence with legacy Bash sorcery

After the full pipeline completes, both engines live in the chroot:

Tool Binary State Reads grimoire
Legacy Bash sorcery /usr/sbin/cast /var/lib/sorcery/ /var/lib/sorcery/codex/test/
Sorcery-Go /usr/local/sbin/sorcery-go /var/lib/sorcery-go/ same (read-only)

They never touch each other's state. You can switch freely:

sudo cast wget              # legacy Bash cast
sudo sorcery-go cast wget   # new Go cast

A broken sorcery-go cast never affects the Bash install, and vice versa.


Next steps

  • Disaster recovery: see docs/DISASTER_RECOVERY.md for how to back up the Tomb and Tablet once you've cast real spells.
  • Coven Mirror WebUI: see docs/QUICKSTART.md for the dashboard tabs.
  • Warding setup: see docs/SECURITY.md for eBPF Tomb Guard and firewall configuration once the chroot is booted on bare metal.
  • Custom toolchains: see docs/TOOLCHAIN_SPEC.md if you want sorcery-go to use your own GCC/LLVM instead of the chroot's defaults.

"The Ley-Lines are humming. The Tomb is secure. The Coven is active."