Skip to content

Upgrade Guide: v0.5.9 to v0.6.0

v0.6.0 reworks the VM image system to a Docker-style, ref-keyed model. This is a breaking server-config change with no automatic migration — the new binary rejects the old config keys at load. The change is small to apply, and the recommended path is "edit config, optionally wipe the image store, restart". No image manifest format change (so published images on ghcr.io are unaffected); the break is in the config schema and the on-disk image identity model.

What changed

Config: default_image + image_aliases + pull_policy replace base_rootfs + images

Each backend block (vz: / firecracker:) previously had a base_rootfs (the image used when no --image was given) plus an images: map of named variants. The internal runtime collapsed base_rootfs to a private tag named _base, which leaked into shed image ls and made the configured image un-addressable after a version bump.

v0.6.0 replaces those with:

Old (≤ v0.5.9) New (v0.6.0)
base_rootfs: <ref> default_image: <ref>
images: { base: …, full: … } image_aliases: { base: …, full: … } (optional)
(none) pull_policy: missing (missing | always | never)

The unused top-level default_image key (sibling of name:/http_port:) is also removed; default_image now lives only inside each backend block.

vz:
  default_image: ghcr.io/charliek/shed-vz-full:v0.6.0
  image_aliases:                       # optional; for `shed create --image <alias>`
    base: ghcr.io/charliek/shed-vz-base:v0.6.0
    extensions: ghcr.io/charliek/shed-vz-extensions:v0.6.0
    full: ghcr.io/charliek/shed-vz-full:v0.6.0
  pull_policy: missing                 # missing (default) | always | never

A config still containing base_rootfs or images: fails to load with a pointer to this guide — it is not silently ignored.

Images are identified by their Docker ref

The internal _base tag is gone. An image's identity is now its io.shed.source-ref annotation (the registry ref it was pulled from), and shed create resolves the configured default_image ref against the local store. shed image ls shows the ref as the primary identity; cosmetic labels (shed image pull <ref> -t <label>) are decoupled from resolution.

Pull policy

shed create reconciles the configured ref against the local store per pull_policy:

  • missing (default) — use the cached ref if present; pull only if absent. Keeps create fast and offline-tolerant. A configured version bump (…:v0.5.9 → …:v0.6.0) is a cache miss and pulls automatically on the next create — the v0.5.9 silent-no-pull behavior is fixed.
  • always — always pull, even if cached.
  • never — use the cached ref; error if absent (never contacts the registry).

Avoid mutable tags (:latest, :dev) with missing — a republished mutable tag won't be noticed. Pin to versioned tags. (Auto-refresh of mutable tags is a future addition.)

Config is read at server boot

shed-server loads its config once at startup. After editing the config you must restart shed-server for the change to take effect — editing the file alone does not re-resolve the image.

Operator upgrade steps

The simplest, lowest-risk path is delete-and-start-fresh: wipe the image store, update the config, restart. New images re-pull on first shed create.

macOS (Homebrew)

brew update && brew upgrade shed

Edit /opt/homebrew/etc/shed/server.yaml (or /usr/local/etc/shed/server.yaml on Intel Macs): rename base_rootfs → default_image, images: → image_aliases:, and add pull_policy: missing. Then optionally wipe the old image store and restart:

# Optional fresh start — reclaims old blobs; new images re-pull on first create.
rm -rf ~/Library/Application\ Support/shed/vz/blobs \
       ~/Library/Application\ Support/shed/vz/tags \
       ~/Library/Application\ Support/shed/vz/refs

brew services restart shed
shed -s <name> version   # expect v0.6.0

Linux (.deb)

curl -fsSL -o /tmp/shed-server.deb \
  https://github.com/charliek/shed/releases/download/v0.6.0/shed-server_0.6.0_amd64.deb
sudo dpkg -i /tmp/shed-server.deb

The upgrade will NOT restart into an un-migrated config

The .deb keeps your existing /etc/shed/server.yaml (config is noreplace). The postinstall now preflights the config and skips the automatic restart if it still contains the removed keys, so the old process keeps serving rather than crash-looping. You'll see a message pointing here. Migrate the config, then:

# Edit /etc/shed/server.yaml (base_rootfs → default_image, images → image_aliases,
# add pull_policy), then validate and restart:
sudo shed-server --config /etc/shed/server.yaml config-validate
sudo systemctl restart shed-server

Optional fresh start of the image store (Linux/Firecracker):

sudo rm -rf /var/lib/shed/firecracker/images/blobs \
            /var/lib/shed/firecracker/images/tags \
            /var/lib/shed/firecracker/images/refs

Verify after upgrade

shed -s <name> image ls       # images shown by Docker ref; no "_base"
shed -s <name> create smoke   # first create pulls the configured ref
shed -s <name> list -vv        # shows the image each shed runs

Local-build workflows

If you build images locally (shed image build … -t <label>) and reference them with --image <label>, that still works — the label resolves from the local store by digest, independent of pull_policy and the configured default_image. Local builds are no longer overwritten by a published ref.

Rollback

v0.6.0's config schema is incompatible with v0.5.9. To roll back:

# Linux
sudo apt install --reinstall shed-server=0.5.9
# macOS: reinstall the 0.5.9 formula

Then restore a base_rootfs + images: config (revert your edit) and restart. A fresh image store works on either version; the blobs themselves are format-compatible — only the config schema and on-disk refs/ index differ (the refs/ directory is ignored by v0.5.9 and rebuilt by v0.6.0).