User:M1cha/Install Arch Linux inside OSTree

From ArchWiki

This article is not officially supported.

The Arch Linux community does not offer support for the information contained in this page; for installation procedures, the Installation guide is the only officially supported document. The content below is mainly maintained by User:M1cha, who last reviewed it on 11:23, 31 December 2023, and it may be out of date or inaccurate.

Introduction

ostree is a toolset, that allows booting from readonly root filesystem images similar to how smartphones work. ostree is a little bit more than that so it's recommended to read their introduction first. A good summary would probably be that ostree is like "git for operating system binaries". To clear up the confusion right away: What you may call "image" or "root filesystem" is simply called a "tree". You deploy a "tree" to a system and boot from it.

Most distributions like Fedora Kinoite or CoreOS regularly build up-to-date versions of their OS and publish them to public ostree repositories. For Arch Linux that's less useful, because almost every system has different packages installed and everyone makes different modifications to the system. So instead, this guide shows a simple way to build your own trees using archlinux-ostree and your own shell script, so you can build them on the machine you want to deploy them to.

Advantages of using ostree

While these are best documented by the official ostree documentation, here's a few that are specific to Arch Linux:

  • If you install a new tree, it'll be applied after the next reboot, so no more issues with loading kernel modules after updating the kernel.
  • ostree manages /etc and does a three-way merge on it during updates. You'll never have pacnew files again and you can easily see your changes by comparing /usr/etc against /etc.

Why we need the arch-ostree tool

This guide utilizes archlinux-ostree. It has a very specific, and limited purpose:

  • Simplify building and committing pacman based trees.
  • Simplify setting up a fresh ostree installation from within the official arch live ISO.

So after you are done with the initial setup, you'll only need that tool to build a new, updated tree.

Pre-installation

Note:
  • While OSTree supports multiple bootloaders, this guide was only tested with GRUB2.
  • This guide assumes that you already have a working rootfs build script

Follow Installation_guide#Pre-installation with the goal of having both your root file system and essential partitions like the EFI system partition and the boot partition mounted at /mnt.

Prepare the live environment

Increase live root partition size

We need to install some bigger packages like Podman, so you'll have to make some space as described in Archiso#Adjusting the size of the root file system. Make sure you have enough RAM for that.

Refresh / Update pacman

Since we will install new packages we have to make sure wen can install them. Usually you just need to sync:

 # pacman -Sy

Depending on the age of the ISO you might run into issues with that and you'll have to update the whole system. Before you do that you should add linux to the ignore list so you don't loose the ability to load kernel modules:

 ...
 [options]
 ...
 IgnorePkg=linux

And then:

 # pacman -Syu

Create a setup directory

We'll have to create lots of files so you should create a temporary directory for them on your mounted rootfs:

 # mkdir /mnt/setup

Since that directory is also used by arch-ostree, you can't put it anywhere else.

Install arch-ostree

 # pacman -S git
 # git clone https://github.com/M1cha/archlinux-ostree.git /mnt/setup/archlinux-ostree
 # export PATH="/mnt/setup/archlinux-ostree:$PATH"

Download your rootfs build script

If you have them on a public GitHub repository:

 # git clone https://github.com/USER/REPO.git /mnt/setup/ostree-build-script

Run preparation script

The rest of the steps are automated. It just installs some dependencies and configures podman to store it's data at /mnt/setup.

 # arch-ostree prepare_live_env

Installation

Initialize ostree

This creates a stateroot called archlinux:

 # ostree admin init-fs --sysroot /mnt --modern /mnt
 # ostree admin stateroot-init --sysroot /mnt archlinux
 # ostree config --repo /mnt/ostree/repo set sysroot.bootprefix 1

Build builder container

Many arch-ostree commands run code inside a container. This container first needs to be built using:

 # arch-ostree build_builder_container

Build your tree

First build your new tree into a directory:

 # arch-ostree \
       --aur-dir /mnt/setup/aur \
       --pacman-cache /mnt/setup/pacman_cache \
       --rootfs-dir /mnt/setup/rootfs \
       build_rootfs_directory \
       /mnt/setup/ostree-build-script/build_rootfs.sh

Then commit it into your freshly created OSTree repository on the branch archlinux:

 # arch-ostree \
     --rootfs-dir /mnt/setup/rootfs \
     --ostree-repo /mnt/ostree/repo \
     commit_rootfs_directory \
     -- -v -b archlinux

Create deployment environment

We need to deploy the tree from an environment that looks similar to the booted system. This is especially true for installing the bootloader. For that reason we checkout the freshly committed tree into a directory so arch-ostree can use it as a chroot environment:

 # ostree checkout \
     --repo /mnt/ostree/repo \
     --require-hardlinks \
     archlinux /mnt/setup/deployment
Warning:

The deployment directory needs to be on the rootfs partition, so the deployment-environment from which you'll install your bootloader, will see that as it's root partition.

Deploy

First open a shell inside the deployment environment. All other commands in this section have to be run inside it:

 # arch-ostree \
     --deploy-env-dir /mnt/setup/deployment \
     --sysroot-dir /mnt \
     deploy_env -- \
     /bin/bash

Install bootloader

Note:

Don't use GRUB config files to add kernel command line arguments. You can manage them using OSTree.

See [GRUB2]] for more information. You can use ostree with all kinds of setups including UEFI, BIOS and LVM. If your preferred setup doesn't work with this, open a discussion.

Here's a common example where your EFI system partition was mounted at /efi and your boot partition was mounted at /boot. First, run the normal grub installer:

 # grub-install --target x86_64-efi --efi-directory /efi --bootloader-id=GRUB

Then we have to symlink the grub config to where OSTree will generate it:

 # ln -sf ../loader/grub.cfg /boot/grub/grub.cfg

Create the deployment

Deploy the branch archlinux into the stateroot archlinux. Modify the --karg= arguments according to your setup.

 # ostree admin deploy \
     --os=archlinux \
     --no-merge \
     --karg-none \
     --karg=root=UUID="MY_UUID" \
     --karg=rw \
     archlinux

Configure

Since you just created a new deployment with a clear copy of /etc, you have to do some basic setup before you can boot into it.

Generate fstab

 # genfstab -U /mnt >> /mnt/ostree/deploy/archlinux/deploy/*/etc/fstab

Set root password

 # vim /mnt/ostree/deploy/archlinux/deploy/*/etc/shadow

Set-up home directory

/home within the tree is a symlink to /var/home. If this directory doesn't exist, systemd will create another symlink in it's place that points to /home on your root partition(/sysroot/home on a booted ostree system). This allows sharing /home between multiple stateroots. If that's what you want, you have to create that directory:

 # mkdir /mnt/home

If you want a separate home directory for every stateroot, you can create one on {{ic|/var|| and systemd will leave it alone:

 # mkdir /mnt/ostree/deploy/archlinux/var/home
Note:

The path to you /var partition might be different depending on you partition scheme.

Reboot

Everything is ready to use and you can reboot into your new system now.

Update

Updating the currently running system is much easier, because ostree detects the stateroot it's running in and uses that as the default.

First, build new tree:

 # arch-ostree \
       --aur-dir /mnt/setup/aur \
       --pacman-cache /mnt/setup/pacman_cache \
       --rootfs-dir /mnt/setup/rootfs \
       build_rootfs_directory \
       /mnt/setup/ostree-build-script/build_rootfs.sh

Then, commit it:

 # arch-ostree \
     --rootfs-dir /mnt/setup/rootfs \
     commit_rootfs_directory \
     -- -v -b archlinux

And deploy it:

 # ostree admin deploy archlinux