Skip to content

Immutable OS image with in-place upgrade #21

Description

@hbrodin

Summary

Separate the OS image (read-only, shared) from instance data (writable, per-instance) using two disks per VM. This enables a coop upgrade command that swaps the OS image while preserving all user data.

Relates to #4 (persistent volumes across VM restarts).

Motivation

Currently each instance is a mutable clone of the golden template. Upgrading the base image (new packages, new Claude Code version, security patches) requires destroying the instance and losing all in-guest state — Docker images, shell history, installed tools, workspace changes.

auditbox solves this with an immutable NixOS image plus a persistent /persist volume. The OS can be swapped atomically while work survives.

Design

Two disks per instance:

  • OS disk (read-only): Points directly at the golden template image. Shared across instances using the same image. No per-instance copy needed.
  • Data disk (read-write): Per-instance volume mounted at /persist. Contains bind-mounted directories for /home/ubuntu, /workspace, /var/lib/docker, and SSH host keys.

coop upgrade <name>:

  1. Stop the instance
  2. Build or fetch the new golden image
  3. Update the OS disk reference to point to the new image
  4. Start the instance — boots into new OS, data volume mounts automatically

Both backends support this natively:

  • Firecracker: multiple entries in the drives JSON config, with is_read_only: true for the OS drive
  • Lima: additionalDisks: in the YAML template

Guest-side changes:

  • Systemd units or init scripts to mount the data volume and create bind-mounts
  • First-boot initialization of the data volume (directory structure, formatting)

Migration: Existing single-disk instances would need a one-time migration to extract user data into the new data volume format.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions