cloudoshandbook

cloudos handbook

installing cloudos 1.0 on x86_64.

1. about cloudos

cloudos is a minimal linux that you build yourself. after installation the system has only a console.

parametervalue
architecturex86_64
libcglibc
initopenrc
kernelvanilla from kernel.org
bootloaderlimine
filesystemsext4 and btrfs
packagesonly from source, the command cloudpkg
notethe handbook is meant for those who are ready to figure things out. for a quick install there is the install wizard: it gives you a ready script for your disk, while this handbook describes every step.

1.1 what you need

whatguideline
cpux86_64. arm is not supported
ramfrom 2 gb, for building the kernel and packages 4 gb or more is better
diskfrom 10 gb, for building packages 20 gb or more is better
bootuefi or legacy bios
networkwired, address by dhcp
mediaa usb stick with the cloudos live iso

the numbers are approximate, there are no hard checks.

1.2 what is inside stage 3

stage 3 is built from scratch following lfs 12.4 (sysv variant) and extended with everything needed for installation and building packages. versions are given for cloudos 1.0.

partwhat is inside
toolchaingcc 15.2.0, glibc 2.42, binutils 2.45, python 3.13.7
initopenrc 0.63, /sbin/init points to openrc-init
devices and consoleudev, agetty on tty1
logsysklogd
networkdhcpcd 10.1.0, curl 8.15.0, git 2.51.0, ca-certificates
permissionsopendoas 6.8.2 instead of sudo
editornano 8.4
disksdosfstools 4.2, btrfs-progs 6.16.1, ext4 from e2fsprogs
bootdracut-ng for initramfs. stage 3 has no kernel or bootloader

1.3 what the system does not have

1.4 installation order

  1. boot from the live iso, check the network and boot mode
  2. partition the disk and create the filesystems
  3. download and unpack stage 3
  4. enter chroot and set up the build
  5. build the kernel
  6. make the initramfs, fstab and install limine
  7. set a password, enable services and reboot
  8. set up the system after the first boot

1.5 how to use the handbook

at the top of the left panel there is a switch between uefi and bios. choose your mode and only the needed commands will remain in the handbook. the choice is remembered in the browser.

search opens with the button in the header or with the keys ctrl + k. every command block has a copy button at the top right.

commands contain placeholders, replace them with your own values:

placeholderwhat to put
/dev/sda, /dev/sda1, /dev/sda2your disk and partitions from lsblk. nvme has different names, see appendix a
ROOT_UUIDuuid of the root partition from blkid
ESP_UUID, BOOT_UUIDuuid of the /boot partition from blkid
6.18.10kernel version, if you build a different one

2. preparation

boot from the cloudos live iso and check the network.

dhcpcd
ping -c1 github.com

determine the boot mode.

[ -d /sys/firmware/efi ] && echo uefi || echo bios

2.1 date and time

if the system date is wrong, https certificates will fail verification and downloads will fail with confusing errors. check the date:

date

if it differs a lot from the real one, set it manually (format year-month-day hour:minutes:seconds):

date -s "YYYY-MM-DD HH:MM:SS"

2.2 disks

look at the disks and partitions. the disk name you need is then used everywhere instead of /dev/sda.

lsblk -f

sata and usb disks are called sda, sdb, nvme is nvme0n1, virtual vda. you can tell which one is the live iso stick by its size.

IMPORTANTdo not mix up the disk. the partitioning and formatting commands irreversibly erase data.

2.3 network

check that the interface is visible and got an address:

ip link
ip addr

if there is no address, run dhcpcd again for the needed interface (see the name in ip link):

dhcpcd eth0

only wired network is set up out of the box. wifi is not configured in the live iso.

2.4 if sites do not open

github, kernel.org and some mirrors may be unavailable from your network. then download the file on another device and move it with a usb stick:

mkdir -p /mnt/usb
mount /dev/sdb1 /mnt/usb
ls /mnt/usb

instead of /dev/sdb1 put the partition of your second usb stick from lsblk. there are mirrors for the kernel, see 7.3.

notenot sure what hardware your computer has? detect it automatically: paste the output of two commands and get disks for the wizard and kernel settings.

3. disk and filesystems

3.1 partitioning

cfdisk /dev/sda
modetablepartitions
uefigptsda1 512 mb, type efi system. sda2 the rest
biosdossda1 512 mb, bootable flag, this is /boot. sda2 the rest
IMPORTANTall data on the disk will be erased (only on the one you chose)

3.2 filesystems

for uefi the /boot partition is formatted as fat32:

mkfs.fat -F32 /dev/sda1

for bios the /boot partition is always fat32:

mkfs.fat -F32 /dev/sda1

format the root partition as ext4:

mkfs.ext4 /dev/sda2

or as btrfs:

mkfs.btrfs /dev/sda2

3.3 mounting

mkdir -p /mnt/cloudos
mount /dev/sda2 /mnt/cloudos
mkdir -p /mnt/cloudos/boot
mount /dev/sda1 /mnt/cloudos/boot

3.4 example layout

partitionsizetypemount pointfilesystem
sda1512 mbefi system/bootfat32
sda2the restlinux filesystem/ext4 or btrfs
partitionsizeflagmount pointfilesystem
sda1512 mbbootable/bootfat32
sda2the rest-/ext4 or btrfs

if you need a swap partition, make it the third, not the first. more about swap in 10.7. swap can also be a file after installation, then a separate partition is not needed.

3.5 checking

make sure everything is mounted as it should be:

lsblk -f
findmnt /mnt/cloudos
findmnt /mnt/cloudos/boot

the root should be on the second partition, /boot on the first. if one of the commands printed nothing, the partition is not mounted.

noteif the root is on btrfs and you want subvolumes, see appendix b before mounting.

4. stage 3

stage 3 is a ready base cloudos system without a kernel and bootloader. the files are in the releases section of the repository.

github.com/wh1laye/cloudos-repo/releases

cloudos-stage3-1.0-x86_64.tar.xz
cloudos-stage3-1.0-x86_64.tar.xz.sha256

4.1 verification (can be skipped)

sha256sum -c cloudos-stage3-1.0-x86_64.tar.xz.sha256

4.2 unpacking

tar xpvf cloudos-stage3-1.0-x86_64.tar.xz --xattrs-include='*.*' --numeric-owner -C /mnt/cloudos

4.3 downloading

download straight onto the root partition, the live system has little memory:

cd /mnt/cloudos
curl -LO https://github.com/wh1laye/cloudos-repo/releases/download/cloudos/cloudos-stage3-1.0-x86_64.tar.xz
curl -LO https://github.com/wh1laye/cloudos-repo/releases/download/cloudos/cloudos-stage3-1.0-x86_64.tar.xz.sha256

then do the verification from 4.1 and the unpacking from 4.2. run the unpacking from the same folder where the archive is.

4.4 after unpacking

the archive is no longer needed, delete it so it does not take space:

rm /mnt/cloudos/cloudos-stage3-1.0-x86_64.tar.xz*
ls /mnt/cloudos

the list should contain bin, boot, etc, usr, var and other system folders. if the folder is empty, the archive was unpacked to the wrong place.

noteyou can always download the archive manually from the releases page and put it on the disk through a usb stick.

5. entering chroot

mount --types proc /proc /mnt/cloudos/proc
mount --rbind /sys /mnt/cloudos/sys
mount --make-rslave /mnt/cloudos/sys
mount --rbind /dev /mnt/cloudos/dev
mount --make-rslave /mnt/cloudos/dev
cp --dereference /etc/resolv.conf /mnt/cloudos/etc/
chroot /mnt/cloudos /bin/bash
source /etc/profile

5.1 what the commands do

commandwhy
mount --types procgives the system in chroot access to process information
mount --rbind /sys, /devpasses devices and sysfs from the live system inside
--make-rslaveso that unmounting inside chroot does not affect the live system
cp --dereference /etc/resolv.confcarries over dns settings, without them there will be no site names inside chroot
chroot /mnt/cloudos /bin/bashmakes /mnt/cloudos the root and starts bash in it
source /etc/profilepulls in the cloudos paths and environment variables

5.2 prompt

so you do not forget you are in chroot, change the prompt:

export PS1="(cloudos chroot) $PS1"

5.3 entering again

if you rebooted the live iso or left chroot, mount the partitions again and repeat the entry. you do not need to unpack the archive again:

mount /dev/sda2 /mnt/cloudos
mount /dev/sda1 /mnt/cloudos/boot
mount --types proc /proc /mnt/cloudos/proc
mount --rbind /sys /mnt/cloudos/sys
mount --make-rslave /mnt/cloudos/sys
mount --rbind /dev /mnt/cloudos/dev
mount --make-rslave /mnt/cloudos/dev
cp --dereference /etc/resolv.conf /mnt/cloudos/etc/
chroot /mnt/cloudos /bin/bash
source /etc/profile

you enter the system the same way for repair if it stopped booting, see 14.9.

5.4 leaving

exit
umount -R /mnt/cloudos

if unmounting says target is busy, close all terminal windows where you were in chroot and repeat.

6. build setup

build flags are set in one file, /etc/cloudpkg/make.conf:

CC="gcc"
CFLAGS="-O2 -march=native"
MAKEOPTS="-j$(nproc)"
USE=""

for clang set CC="clang". then update the recipe list:

cloudpkg sync

6.1 locales

echo "en_US.UTF-8 UTF-8" > /etc/locale.gen
localedef -i en_US -f UTF-8 en_US.UTF-8
echo "LANG=en_US.UTF-8" > /etc/locale.conf

6.2 build flags

parameterwhat it means
CCcompiler: gcc or clang
CFLAGScompilation flags. -O2 is ordinary optimization
-march=nativecode for the cpu of this machine. faster, but will not run on an older cpu
-march=x86-64generic code, will run on any x86_64
MAKEOPTSmake parameters. -j is the number of parallel jobs
USEpackage feature switches, empty by default

if you build on the same machine where you will work, leave -march=native. if you later move the disk to another computer, change it to -march=x86-64. stage 3 itself is built with generic flags.

6.3 parallel build

-j$(nproc) starts as many jobs as the cpu has threads. with little ram the build may fail with the message killed. then reduce the number:

MAKEOPTS="-j2"

6.4 gcc 15 and build errors

gcc 15 uses the c23 standard by default, and some old packages do not build with it. typical signs: errors about bool, true, false or function declarations without arguments. in that case return the previous standard:

CC="gcc -std=gnu17"

change the value CC in /etc/cloudpkg/make.conf and repeat the package installation.

7. kernel

the kernel is taken from kernel.org and configured by hand

cd /usr/src
curl -LO https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.18.10.tar.xz
tar xf linux-6.18.10.tar.xz
cd linux-6.18.10
make menuconfig
make -j$(nproc)
make modules_install
cp arch/x86/boot/bzImage /boot/vmlinuz-6.18.10
IMPORTANT you need to use everywhere the name of the disk you want to install to, you can find it with the lsblk command (again, the disk can be called /dev/nvme0n1 /dev/sda /dev/sdb

7.1 what to enable in menuconfig

in make menuconfig search opens with the key /, there you can find any option by name. a kernel without the needed drivers will not boot, so check at least these items. an asterisk [*] means built into the kernel, M means a module.

optionwhy
DEVTMPFS, DEVTMPFS_MOUNTthe /dev directory, needed by udev
BLK_DEV_INITRDbooting with initramfs
RD_GZIP, RD_XZ, RD_ZSTDunpacking initramfs. enable all three so you do not have to guess how dracut compressed it
EXT4_FS, BTRFS_FSthe root filesystem. enable built in, not as a module
VFAT_FS, FAT_FS, NLS_CODEPAGE_437, NLS_ISO8859_1the /boot partition on fat32
TMPFS, PROC_FS, SYSFSbasic virtual filesystems
BLK_DEV_NVMEnvme disks
ATA, SATA_AHCI, BLK_DEV_SDsata disks
USB_XHCI_HCD, USB_XHCI_PCI, USB_HIDusb ports and keyboard
NET, INET, PACKET, UNIXnetwork. without PACKET dhcpcd will not work
network card driverfor example E1000E for intel, R8169 for realtek. find out your card with the command lspci in the live iso
INOTIFY_USER, SIGNALFD, TIMERFD, EPOLL, FHANDLEudev needs this
CGROUPSopenrc needs this
VT, VT_CONSOLE, FRAMEBUFFER_CONSOLE, DRM_SIMPLEDRMconsole output to the screen without a video card driver
notevideo card drivers (amdgpu, i915, nouveau) require firmware files firmware, which stage 3 does not have. without a driver the console still works through DRM_SIMPLEDRM.

a convenient start: if the live iso is built with support for /proc/config.gz, take its config as a base and add to it:

zcat /proc/config.gz > .config
make olddefconfig
make menuconfig

7.2 what the build commands do

commandwhy
make menuconfigkernel configuration, the result is written to the file .config
make -j$(nproc)kernel build, takes from several minutes to an hour depending on the cpu
make modules_installinstalls the modules into /lib/modules/6.18.10, they are needed by dracut
cp arch/x86/boot/bzImageputs the kernel itself into /boot

save the config and the symbol map, they will be useful when updating the kernel:

cp .config /boot/config-6.18.10
cp System.map /boot/System.map-6.18.10

7.3 kernel mirrors

if cdn.kernel.org does not open, download the same archive from a mirror:

curl -LO https://mirrors.aliyun.com/linux-kernel/v6.x/linux-6.18.10.tar.xz
curl -LO https://mirrors.ustc.edu.cn/kernel.org/linux/kernel/v6.x/linux-6.18.10.tar.xz

paths on mirrors sometimes change. if the link does not work, open the mirror directory in the browser and find the file by hand.

7.4 another kernel version

in all commands replace 6.18.10 with your version. the file names in /boot, in initramfs and in limine.conf must match.

notedo not want to hunt for drivers in menuconfig? the kernel helper gives you a ready configuration command for your hardware.

8. bootloader

8.1 initramfs

cloudpkg install dracut
dracut --kver 6.18.10 /boot/initramfs-6.18.10.img

8.2 fstab

partition uuids are shown by blkid. the file /etc/fstab for uefi:

UUID=ROOT_UUID  /      ext4  defaults  0 1
UUID=ESP_UUID   /boot  vfat  defaults  0 2

for bios:

UUID=ROOT_UUID  /      ext4  defaults  0 1
UUID=BOOT_UUID  /boot  vfat  defaults  0 2

if the root is on btrfs, replace ext4 in the first line with btrfs.

8.3 limine

cloudpkg install limine

the file /boot/limine.conf is the same for uefi and bios:

timeout: 5

/CloudOS
    protocol: linux
    path: boot():/vmlinuz-6.18.10
    cmdline: root=UUID=ROOT_UUID rw
    module_path: boot():/initramfs-6.18.10.img

installation for uefi:

mkdir -p /boot/EFI/BOOT
cp /usr/share/limine/BOOTX64.EFI /boot/EFI/BOOT/BOOTX64.EFI

installation for bios, put it on the partition:

cp /usr/share/limine/limine-bios.sys /boot/
limine bios-install /dev/ (your disk name /dev/sda1 /dev/sdb1 /dev/nvme0n1)

8.4 check before rebooting

look at what is in /boot:

ls -l /boot

there should be vmlinuz-6.18.10, initramfs-6.18.10.img, limine.conf and the folder EFI/BOOT with the file BOOTX64.EFI.

there should be vmlinuz-6.18.10, initramfs-6.18.10.img, limine.conf and limine-bios.sys.

compare the uuids in the configs with the real ones:

blkid
grep UUID /etc/fstab /boot/limine.conf

the uuid of the root partition in limine.conf and in fstab must match the output of blkid. most failed first boots are due to a typo here.

8.5 writing to nvram (uefi only, optional)

this step is not needed in bios mode.

the file BOOTX64.EFI in EFI/BOOT the firmware finds by itself, and that is enough. if you want a separate boot menu entry, create it with this command from the live iso (not from chroot):

efibootmgr --create --disk /dev/sda --part 1 --loader '\EFI\BOOT\BOOTX64.EFI' --label CloudOS

for an nvme disk: --disk /dev/nvme0n1 --part 1. in the firmware settings disable secure boot, limine without a signature will not boot.

8.6 several kernels

before updating the kernel add a second entry to /boot/limine.conf, and do not delete the old one. if the new kernel does not boot, you pick the old one in the menu:

timeout: 5

/CloudOS
    protocol: linux
    path: boot():/vmlinuz-NEW
    cmdline: root=UUID=ROOT_UUID rw
    module_path: boot():/initramfs-NEW.img

/CloudOS (old kernel)
    protocol: linux
    path: boot():/vmlinuz-OLD
    cmdline: root=UUID=ROOT_UUID rw
    module_path: boot():/initramfs-OLD.img

instead of NEW and OLD put the kernel versions.

8.7 grub instead of limine

if you prefer grub, install it instead of limine (inside chroot, after the kernel and initramfs are installed):

cloudpkg sync
cloudpkg install sys-boot/grub

for uefi:

grub-install --target=x86_64-efi --efi-directory=/boot --boot-directory=/boot --removable

for bios:

grub-install --target=i386-pc --boot-directory=/boot /dev/sda

the config is written by hand to /boot/grub/grub.cfg:

set timeout=5
menuentry "CloudOS" {
    search --no-floppy --fs-uuid --set=root ESP_UUID
    linux /vmlinuz-6.18.10 root=UUID=ROOT_UUID rw
    initrd /initramfs-6.18.10.img
}
notereplace ESP_UUID and ROOT_UUID with the values from blkid (the /boot partition and the root partition). with btrfs add the rootflags=subvol=@ parameter to the linux line. the install wizard on the site does all of this for you.
notehow all of this fits together is shown on the boot flow page: files of every stage, check commands and typical failures.

9. finishing

enable the network and the log, set the root password:

cloudpkg install dhcpcd
cloudpkg install syslog-ng
rc-update add dhcpcd default
rc-update add syslog-ng default
passwd

leave chroot, unmount and reboot:

exit
umount -R /mnt/cloudos
reboot
notecloudos does not create other users!), you add the user and doas yourself.
importantthe disk you install to can be nvme as well as sda or sdb, tested on 7 5700X (AMD) RX9060XT (AMD) and on sda (not nvme. i chose limine for speed and convenience, grub support MAYBE will come.

9.1 checking services

before rebooting make sure the services are added:

rc-update show

the list should contain dhcpcd and the log at the level default.

9.2 first boot

after the reboot remove the usb stick and choose the disk in the boot menu if it was not chosen by itself. the prompt will appear login: on tty1. enter root and the password you set with the command passwd.

then set up the system, it is described in chapter 10.

notestage 3 already includes dhcpcd, sysklogd, dracut and doas, so there is no need to install them with cloudpkg. the system uses sysklogd instead of syslog-ng. cloudpkg works on top of portage: cloudpkg sync updates the recipe tree, cloudpkg install name builds from source, cloudpkg doctor checks the setup.

10. first boot

after installation the system has only a console and root. this chapter is about what is worth doing right away.

10.1 login

at the prompt login: , enter root and the password you set in chapter 9. if you did not set one, the password is empty, set it right away with the command passwd.

10.2 user and doas

working as root all the time is unsafe. create a regular user and allow the wheel group to use doas:

grep wheel /etc/group || groupadd wheel
useradd -m -G wheel -s /bin/bash name
passwd name
echo "permit :wheel" > /etc/doas.conf
chmod 0400 /etc/doas.conf

instead of name put your own. after that, commands as root are run like this:

doas cloudpkg install nano

if you do not want to type the password every time, replace the rule with permit nopass :wheel. this is more convenient, but safer with a password.

10.3 computer name

echo "cloudos" > /etc/hostname
echo 'hostname="cloudos"' > /etc/conf.d/hostname
rc-update add hostname boot

if the service hostname is already enabled, the last command will report that and change nothing. instead of cloudos you can write any name in latin letters.

10.4 time zone

ls /usr/share/zoneinfo
ln -sfv /usr/share/zoneinfo/Europe/Moscow /etc/localtime

instead of Europe/Moscow choose your zone from the list. check the result with the command date.

10.5 network

dhcpcd gets the address and dns automatically. check:

ip addr
ping -c1 github.com

if you need a permanent address, add to /etc/dhcpcd.conf (see the interface name in ip link):

interface eth0
static ip_address=192.168.1.50/24
static routers=192.168.1.1
static domain_name_servers=1.1.1.1 8.8.8.8

then restart the service: rc-service dhcpcd restart.

10.6 openrc services

commandwhat it does
rc-statusshows the running services
rc-update showshows the services and the runlevels they are enabled on
rc-update add name defaultenables the service at boot
rc-update del name defaultdisables autostart
rc-service name startstarts the service now
rc-service name stopstops it
rc-service name restartrestarts it
rc-service name statusshows the status

levels: boot for what is needed early (for example the computer name), default for ordinary services.

10.7 swap

swap is not required, but it helps when building big packages with little ram. the easiest way is a file.

for ext4:

dd if=/dev/zero of=/swapfile bs=1M count=4096 status=progress
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile

for btrfs (also works for ext4):

btrfs filesystem mkswapfile --size 4g /swapfile
swapon /swapfile

so that swap turns on by itself, add a line to /etc/fstab:

/swapfile  none  swap  defaults  0 0

a swap partition is made like this: mkswap /dev/sda3, swapon /dev/sda3 and a fstab line with UUID=... instead of /swapfile.

11. packages and cloudpkg

all packages in cloudos are built from source. this is done by the manager cloudpkg. its recipes are taken from gentoo.

IMPORTANTcloudpkg is under development. there are no package signatures yet, the integrity of sources is checked only by the sha256 from the recipe. some recipes may need fixes.

11.1 commands

commandwhat it does
cloudpkg syncupdates the recipe list
cloudpkg install namebuilds and installs a package together with its dependencies
cloudpkg remove nameremoves a package
cloudpkg upgradeupdates installed packages to newer versions
cloudpkg cleancleans downloaded sources and temporary build files

11.2 how the installation goes

  1. the package recipe and its dependency list are read
  2. the sources are downloaded through curl
  3. sha256 is checked
  4. the package is built with your flags from /etc/cloudpkg/make.conf
  5. the result is installed into the system

a build takes time and disk space. big packages such as compilers build for a long time, this is normal.

11.3 examples

cloudpkg sync
cloudpkg install limine
cloudpkg install dracut
cloudpkg install nano

11.4 if a package failed to build

  1. read the last lines with error
  2. if the error is about the c standard, set CC="gcc -std=gnu17", see 6.4
  3. if the build fails with killed, reduce -j in MAKEOPTS
  4. try cloudpkg sync and repeat, maybe the recipe is already fixed
  5. write on the forum in the questions section, attaching the last 10-15 lines of output

12. maintenance

12.1 updating packages

cloudpkg sync
cloudpkg upgrade
cloudpkg clean

12.2 updating the kernel

a new version is installed next to the old one. do not delete the old kernel until you are sure the new one boots.

  1. download and unpack the new kernel into /usr/src, as in chapter 7
  2. take the old config as a base and pull in the new options:
cd /usr/src/linux-NEW
cp /boot/config-OLD .config
make olddefconfig
  1. build and install:
make -j$(nproc)
make modules_install
cp arch/x86/boot/bzImage /boot/vmlinuz-NEW
cp .config /boot/config-NEW
dracut --kver NEW /boot/initramfs-NEW.img
  1. add a second entry to /boot/limine.conf, as in 8.6, and reboot
  2. if everything works, the old files can be deleted:
rm /boot/vmlinuz-OLD /boot/initramfs-OLD.img /boot/config-OLD
rm -r /lib/modules/OLD

instead of NEW and OLD put the versions, for example 6.18.10.

12.3 backup

a full copy of the system in one archive with the same keys as when unpacking stage 3. save it to another disk or usb stick:

tar cpf /mnt/usb/cloudos-backup.tar.xz --xattrs-include='*.*' --numeric-owner --one-file-system -I xz /

btrfs has snapshots, they are faster and take less space, see appendix b.

12.4 freeing space

df -h
cloudpkg clean
du -sh /usr/src/* /var/* 2>/dev/null

the old kernel folders in /usr/src can be deleted if you have their configs saved in /boot.

13. what next

cloudos is installed minimal. everything else you add as needed.

whathow
soundyou install pipewire yourself through cloudpkg install, if there is a recipe for it
graphics and desktopnone by default. install the components by hand from recipes, you will need a video card driver in the kernel and firmware files
ssh servernone by default. install the package and enable the service through rc-update add
firewallnone by default
other editors and utilitiesthrough cloudpkg install
man pagesare not installed. use command --help and this handbook

13.1 other locales

in chapter 6.1 one locale was created. to add another, for example russian:

localedef -i ru_RU -f UTF-8 ru_RU.UTF-8
echo "LANG=ru_RU.UTF-8" > /etc/locale.conf

in the kernel console cyrillic may display incorrectly without a separate font, so for the console it is safer to keep en_US.UTF-8.

13.2 help and feedback

14. errors and fixes

click the error text to see the cause and what to do. if your error is not in the list, use search.

14.1 live iso, network and time

ping: connect: network is unreachable or no reply

the interface did not get an address. check the cable, then:

ip link
dhcpcd eth0

take the interface name from ip link. if the interface is not in the list, the live iso has no driver for your network card.

ping by ip works, by name does not (temporary failure in name resolution)

dns is not set up. in the live iso it comes from dhcpcd. inside chroot check that this was done: cp --dereference /etc/resolv.conf /mnt/cloudos/etc/.

certificate verify failed or ssl certificate problem

almost always a wrong date. set it with 2.1 and repeat. if that does not help, download the file on another device and move it with a usb stick.

curl: (6) could not resolve host or (7) failed to connect

no network or the site is unavailable from your network. check ping against another site. for github and kernel.org see 2.4.

14.2 partitioning and filesystems

mount: unknown filesystem type or wrong fs type

the partition is not formatted or you specified the wrong partition. check lsblk -f: in the column FSTYPE there must be a filesystem. if empty, repeat the formatting from 3.2.

mount: special device does not exist

wrong partition name. nvme ones are called nvme0n1p1, not nvme0n11, see appendix a.

mkfs.fat: command not found or mkfs.btrfs: command not found

the live iso lacks the needed tool. dosfstools and btrfs-progs must be part of the image, check that you have an up-to-date iso.

cfdisk does not see the disk

the live iso has no driver for the disk controller. for a virtual machine choose a sata or nvme disk, not a non-standard controller.

14.3 downloading and unpacking

sha256sum: WARNING: 1 computed checksum did NOT match

the file was not downloaded fully or is corrupted. delete the archive and download again. make sure the .sha256 file and the archive are in the same folder and the names match.

tar: Unexpected EOF in archive or xz: file format not recognized

the archive is truncated. download again and compare the size with the one shown on the releases page.

tar: No space left on device

there was not enough space on the partition or the archive was in the live iso's ram. download straight into /mnt/cloudos, as in 4.3, and check the partition size with the command df -h /mnt/cloudos.

14.4 chroot

chroot: failed to run command '/bin/bash': No such file or directory

stage 3 is not unpacked or unpacked into another folder. run ls /mnt/cloudos/bin. if the folder is empty, go back to 4.2.

mount: /mnt/cloudos/proc: mount point does not exist

the same thing, stage 3 is not unpacked, so the proc, sys, dev folders do not exist yet.

sites do not open inside chroot

copy the dns settings again: cp --dereference /etc/resolv.conf /mnt/cloudos/etc/ (run outside chroot).

umount: target is busy

some program is still using the files. close all terminals where you were in chroot and repeat umount -R /mnt/cloudos.

14.5 building packages

errors about bool, true, false, prototype

an old package does not build with the c23 standard enabled in gcc 15. add to make.conf CC="gcc -std=gnu17", see 6.4.

gcc: fatal error: Killed signal terminated program cc1

not enough ram. reduce -j in MAKEOPTS or enable swap, see 10.7.

sha256 does not match when downloading sources

the file at the source may have changed or was downloaded with an error. run cloudpkg sync and repeat the installation. if the error repeats, write about it on the forum.

No space left on device during the build

out of space. run cloudpkg clean and check df -h. for building packages it is better to have 20 gb or more.

14.6 kernel

make menuconfig: Unable to find the ncurses libraries

the system has no ncurses with headers. install the package through cloudpkg or use make config (slow) or move a ready .config.

dracut: Cannot find module directory /lib/modules/6.18.10

you did not run make modules_install or the version in the command does not match the one you built. run ls /lib/modules and use the version you have.

make: *** No rule to make target ...

you ran make not in the kernel source folder. go to /usr/src/linux-6.18.10 and repeat.

14.7 booting

after the reboot no bootable device or another system boots right away

check that the file /boot/EFI/BOOT/BOOTX64.EFIexists, that partition 1 has type efi system and that secure boot is off in the firmware. choose the disk in the boot menu manually (usually the key f12 or esc at power on).

check that the /boot partition is marked with the flag bootable and that the command limine bios-install was run for the right disk or partition. in the firmware settings enable legacy or csm mode.

limine shows the menu, but the kernel does not start (file not found)

the path in limine.conf does not match the file name. check ls /boot and fix path: and module_path:.

Kernel panic: VFS: Unable to mount root fs on unknown-block

the kernel did not find the root partition. the most common causes:

  • wrong ROOT_UUID in cmdline, compare with blkid
  • the kernel has no disk driver (BLK_DEV_NVME or SATA_AHCI) or filesystem (EXT4_FS, BTRFS_FS)
  • the module_path with initramfs is not specified in limine.conf

boot from the live iso, enter chroot (14.9), fix it and rebuild.

dracut: waits for the root device and drops to the dracut console

initramfs did not find the root. compare the uuid, and also check that the disk driver and the root filesystem are built into the kernel.

empty screen after choosing the limine entry

most likely the console is not output. enable in the kernel DRM_SIMPLEDRM, FRAMEBUFFER_CONSOLE, VT_CONSOLE, see 7.1. video card drivers without firmware files can give a black screen, then do not enable them.

Kernel panic: No init found

the root mounted, but there is no /sbin/initin it. check that stage 3 is fully unpacked and that the root partition is the right one.

14.8 after booting

login incorrect

wrong password or it was not set. boot from the live iso, enter chroot and set the password again with the command passwd.

no network after booting

check rc-status. if dhcpcd is not running, run rc-update add dhcpcd default and rc-service dhcpcd start. if the interface is not in ip link, the kernel has no driver for the card.

doas: Operation not permitted

the user is not in the wheel group or there is no file /etc/doas.conf. check with 10.2: id name must show the group wheel.

setlocale: LC_ALL: cannot change locale

the specified locale was not created. create it with the command localedef from 6.1 or change LANG to an existing one.

the service does not start: rc-service ... start

look at the output of the command and the log. the list of the service with an error is given by rc-status --crashed.

14.9 emergency system access

if the system does not boot, it can almost always be repaired from the live iso:

  1. boot from the live iso and check the network
  2. mount the partitions and enter chroot per 5.3
  3. fix the config, rebuild initramfs with the command dracut --kver 6.18.10 /boot/initramfs-6.18.10.img --force or fix limine.conf
  4. leave chroot, unmount and reboot

14.10 how to report an error

so that you get help quickly, attach:

14.11 installer wizard and grub

no disk /dev/sda or no partitions (wizard script message)

the script could not find the disk or the partitions. check the disk name and that partitions have the right names (nvme adds the letter p: nvme0n1p1):

lsblk
partprobe /dev/sda

if the name differs, fix the disk field in the wizard and copy the script again.

the wizard script exits immediately and does not ask for yes

the script was not run from a terminal (through a pipe or with replaced input), so it cannot read your answer. run it directly:

bash /root/cloudos-s1.sh
limine not found in the live system or grub not found in the live system

the live image does not include the chosen bootloader. pick the other one in the wizard, or install the bootloader from the handbook inside chroot (8.7 for grub). check what the live system has:

ls /usr/share/limine
command -v grub-install
curl: (22) The requested URL returned error: 404 when downloading stage 3

the file name or the release tag has changed. open the releases page, copy the exact file name and put it at the top of the script (the STAGE variable), then run the script again.

curl: (28) connection timed out when downloading the kernel in step 2

the mirror is unreachable. the script tries three addresses in turn. if none answers, download linux-6.18.10.tar.xz in a browser (with a vpn), put it into /mnt/cloudos/usr/src and run step 2 again: the download will be skipped.

menuconfig: Your display is too small to run Menuconfig

the terminal is too small. you need at least 80 columns and 19 rows. enlarge the window or reduce the font and run step 2 again.

grub-install: error: cannot find EFI directory

the /boot partition is not mounted, or the live image was booted in bios mode instead of uefi. check:

ls /sys/firmware/efi
mountpoint /mnt/cloudos/boot

if the efi folder is missing, reboot in uefi mode (in the firmware settings); if /boot is not mounted, mount the partition and retry.

grub-install: warning: this GPT partition label contains no BIOS Boot Partition

you are installing grub in bios mode on a gpt disk. for bios cloudos uses a dos (mbr) table. recreate the partitions in bios mode (the wizard does this itself) or add a small bios boot partition (type ef02) and repeat the grub install.

grub: error: no such partition and the grub rescue prompt

grub could not find its files. in the rescue prompt type (use your own partition):

ls
set root=(hd0,msdos1)
set prefix=(hd0,msdos1)/grub
insmod normal
normal

after booting, log in and reinstall grub as in 8.7. for uefi use gpt1 instead of msdos1.

grub> prompt instead of the menu (no grub.cfg)

grub is installed but there is no config. boot the system by hand (use your own version and partition), then create /boot/grub/grub.cfg as in 8.7:

ls
set root=(hd0,msdos1)
linux /vmlinuz-6.18.10 root=/dev/sda2 rw
initrd /initramfs-6.18.10.img
boot
grub: error: file '/vmlinuz-6.18.10' not found

the version in grub.cfg does not match the kernel file. look at what is in /boot and fix the names in the config:

ls /boot
nano /boot/grub/grub.cfg
efibootmgr: EFI variables are not supported on this system

the system was booted in bios mode. reboot in uefi mode. the bootloader itself installs without efibootmgr: an nvram entry is optional.

14.12 cloudpkg and portage

cloudpkg: no mirror answered

the tree snapshot was not downloaded. turn on a vpn and repeat cloudpkg sync, or download portage-latest.tar.xz (the snapshots folder on any gentoo mirror) in a browser, put it into /var/cache/distfiles and run sync again.

!!! Invalid Repository Location (not a dir): '/var/db/repos/gentoo'

the recipe tree has not been downloaded yet. run:

cloudpkg sync
cloudpkg doctor
cloudpkg doctor shows НЕТ for the profile (make.profile)

the profile link is created after the first sync. create it by hand:

ln -sfn /var/db/repos/gentoo/profiles/default/linux/amd64/23.0 /etc/portage/make.profile
emerge: command not found or ModuleNotFoundError: No module named 'portage'

portage is not installed or is broken. run the auto-setup script from the repository or reinstall it:

python3 -m pip install --force-reinstall --index-url https://mirrors.aliyun.com/pypi/simple/ portage
cloudpkg: root rights required

install, remove, upgrade and clean work only as root. log in as root or use doas:

doas cloudpkg install name
emerge: there are no ebuilds to satisfy ...

there is no such package or the name is incomplete. find the exact name with the category:

cloudpkg search name
cloudpkg install category/name

if the tree is old, run cloudpkg sync first.

The following keyword changes are necessary to proceed (masked by ~amd64)

the needed version exists only in the testing branch. if you accept a less tested version, add the -t flag:

cloudpkg install -t category/name
emerge wants to rebuild glibc, gcc or bash (blocked packages, slot conflict)

portage does not know these packages are already built by hand. declare the package in /etc/portage/profile/package.provided (one line per package, with a version):

echo "sys-libs/glibc-2.42" >> /etc/portage/profile/package.provided
cloudpkg install -p name

the version must not be lower than the one the package requires.

Fetch failed for ... or Digest verification failed

the sources were not downloaded or were downloaded corrupted. clean the cache and retry. if a mirror does not answer, change the order of addresses in GENTOO_MIRRORS in /etc/portage/make.conf:

cloudpkg clean
cloudpkg install name
* ERROR: ... failed (compile phase)

the package failed to build. the path to the build log is in the message (the build.log file). show the last lines:

tail -n 30 /var/tmp/portage/category/name/temp/build.log

a common cause is the new gcc 15. make.conf already has CC="gcc -std=gnu17", check that the line is in place. attach the last 15 lines when you report an error.

15. cheat sheet

15.1 disks

commandwhat it does
lsblk -fdisks, partitions, filesystems, uuid
blkiduuid and filesystem type of partitions
fdisk -lpartition tables in detail
cfdisk /dev/sdadisk partitioning menu
mount /dev/sda2 /mnt/cloudosmount a partition
umount -R /mnt/cloudosunmount everything recursively
findmntwhat is mounted where
df -hfree space on partitions
du -sh folderhow much a folder takes

15.2 network

commandwhat it does
ip linklist of network interfaces
ip addrinterface addresses
ip routeroutes and gateway
dhcpcd eth0get an address on an interface
ping -c1 github.comcheck connectivity and names
curl -LO linkdownload a file

15.3 system

commandwhat it does
dmesg | tail -50latest kernel messages
free -hmemory and swap
topprocesses and load
uname -rversion of the running kernel
lsmodloaded kernel modules
lspcipci devices, shows the network and video card
datedate and time
reboot, poweroffreboot and shutdown

15.4 files and archives

commandwhat it does
tar xf archive.tar.xzunpack an archive
tar cf archive.tar.xz folder -I xzcreate an xz archive
cp -a what wherecopy preserving permissions
nano fileopen the editor. save ctrl + o, exit ctrl + x
grep text filefind a line in a file

15.5 btrfs

commandwhat it does
btrfs filesystem df /space used by data types
btrfs subvolume list /list of subvolumes
btrfs subvolume snapshot -r source targetread-only snapshot of a subvolume
btrfs scrub start /data integrity check

15.6 cloudpkg

commandwhat it does
cloudpkg syncupdate recipes
cloudpkg install nameinstall a package
cloudpkg remove nameremove a package
cloudpkg upgradeupdate packages
cloudpkg cleanclean the build cache

openrc services are collected in the table 10.6.

16. questions and answers

why is cloudos built by hand, is there an installer

the idea is to understand every step and control the whole system. the installation goes like in gentoo: partitioning, stage 3, chroot, kernel, bootloader.

if you do not want to type commands one by one, use the install wizard on the site: it builds a script for your disk. understanding the steps is still useful.

which bootloader is used, is there grub

limine and grub are supported. limine is installed by default: it is fast and configured with one file. grub is described in 8.7, and the install wizard can install either of the two.

why openrc and not systemd

openrc is simple, without extra dependencies and fits a minimal system. init in cloudos is openrc-init.

can it be installed on arm

no, only x86_64 is supported, in uefi and legacy bios modes.

what is the root password after unpacking stage 3

the password is empty. set it in chapter 9 with the command passwd.

why are there no man pages

they were removed to make the system smaller. help is the handbook and the key --help of the commands.

can sudo be used

doas is used instead, it is simpler and smaller. the rules are in /etc/doas.conf, see 10.2.

how to install a graphical environment

there is none by default. it has to be built by hand through cloudpkg, and the kernel will need a video card driver with firmware files, see chapter 13.

what license

the project's own parts are under mit, you must keep the author's name and the project name. package recipes are based on gentoo and stay under gpl-2.

where to get the live iso

the image is prepared after the stage 3 release and will appear on the releases page. until then you can use any live linux with the set of utilities from 1.1.

what does beta in the release name mean

the system works, but the project is young: cloudpkg and the live iso are still in development. more on the news page.

appendix a. disk names

the partition name depends on the disk type. for nvme the letter is added before the partition number: p.

disk typediskfirst partitionsecond partition
sata, usb/dev/sda/dev/sda1/dev/sda2
nvme/dev/nvme0n1/dev/nvme0n1p1/dev/nvme0n1p2
virtual (virtio)/dev/vda/dev/vda1/dev/vda2

if you install on nvme, replace /dev/sda1 with /dev/nvme0n1p1 and /dev/sda2 with /dev/nvme0n1p2 in all commands.

appendix b. btrfs with subvolumes

optional. subvolumes allow fast system snapshots and rollbacks. described for the layout from 3.4.

b.1 creating subvolumes

mkfs.btrfs /dev/sda2
mount /dev/sda2 /mnt/cloudos
btrfs subvolume create /mnt/cloudos/@
btrfs subvolume create /mnt/cloudos/@home
umount /mnt/cloudos

b.2 mounting

mount -o subvol=@ /dev/sda2 /mnt/cloudos
mkdir -p /mnt/cloudos/boot /mnt/cloudos/home
mount /dev/sda1 /mnt/cloudos/boot
mount -o subvol=@home /dev/sda2 /mnt/cloudos/home

b.3 fstab and bootloader

UUID=ROOT_UUID  /      btrfs  subvol=@,noatime      0 0
UUID=ROOT_UUID  /home  btrfs  subvol=@home,noatime  0 0
UUID=ESP_UUID   /boot  vfat   defaults              0 2

in /boot/limine.conf in the line cmdline add the subvolume parameter:

cmdline: root=UUID=ROOT_UUID rootflags=subvol=@ rw

b.4 system snapshot

mkdir -p /mnt/top
mount -o subvolid=5 /dev/sda2 /mnt/top
btrfs subvolume snapshot -r /mnt/top/@ /mnt/top/@-snap-1
umount /mnt/top

the snapshot lies next to the subvolume @ and takes no space until the data changes.

appendix c. glossary

wordwhat it means
stage 3a ready base system in one archive, without a kernel and bootloader
chrootstarting a shell with a different root directory. this is how you work in the new system while the live iso is loaded
uefimodern firmware. boots from the esp partition
bios (legacy, csm)old firmware, the bootloader is written to the start of the disk or partition
espefi system partition, a fat32 partition with the bootloader for uefi
initramfsa small temporary system that boots before the main one and finds the root partition
uuida unique partition identifier, does not change when the disk name changes
liminea bootloader that reads /boot/limine.conf
dracuta program that builds initramfs
openrcinit and service management system
doasrunning commands as root, a replacement for sudo
recipea package description for cloudpkg: where to get the sources and how to build
subvolumea separate branch of the btrfs filesystem for which snapshots can be made