| Title: How-to install Alpine Linux in full ram with persistency | |
| Author: Solène | |
| Date: 14 July 2023 | |
| Tags: immutability linux alpine | |
| Description: In this article, you will learn how to install and | |
| configure Alpine Linux to run your system from memory and save its | |
| state for next boots. | |
| # Introduction | |
| In this guide, I'd like to share with you how to install Alpine Linux, | |
| so it runs entirely from RAM, but using its built-in tool to handle | |
| persistency. Perfect setup for a NAS or router, so you don't waste a | |
| disk for the system, and this can even be used for a workstation. | |
| Alpine Linux official project website | |
| Alpine Linux wiki: Alpine local backup | |
| # The plan | |
| Basically, we want to get the Alpine installer on a writable disk | |
| formatted in FAT instead of a read only image like official installers, | |
| then we will use the command `lbu` to handle persistency, and we will | |
| see what need to be configured to have a working system. | |
| This is only a list of steps, they will be detailed later: | |
| 1. boot from an Alpine Installer (if you are using Alpine, you don't | |
| need too) | |
| 2. format an usb memory drive with an ESP partition and make it | |
| bootable | |
| 3. run `setup-bootloader` to copy the bootloader from the installer to | |
| the freshly formatted drive | |
| 4. reboot on the usb drive | |
| 5. run `setup-alpine` | |
| 6. you are on your new Alpine system | |
| 7. run `lbu commit` to make changes persistent across reboot | |
| 8. make changes, run `lbu commit` again | |
| A mad scientist Girl with a t-shirt labeled "rare t-shirt" is looking at a peng… | |
| Artwork above by Prahou | |
| # The setup | |
| ## Booting Alpine | |
| For this step you have to download an Alpine Linux installer, take the | |
| one that suits your needs, if unsure, take the "Extended" one. Don't | |
| forget to verify the file checksum. | |
| => https://www.alpinelinux.org/downloads/ | |
| Once you have the ISO file, create the installation media: | |
| Alpine Linux documentation: Using the image | |
| Now, boot your system using your brand-new installer. | |
| ## Writable boot media creation | |
| In this step, we will need to boot on the Alpine installer to create a | |
| new Alpine installer, but writable. | |
| You need another USB media for this step, the one that will keep your | |
| system and data. | |
| On Alpine Linux, you can use `setup-alpine` to configure your network, | |
| key map and a few things for the current system. You only have to say | |
| "none" when you are asked what you want to install, where, and if you | |
| want to store the configuration somewhere. | |
| Run the following commands on the destination USB drive (networking is | |
| required to install a package), this will format it and use all the | |
| space as a FAT32 partition. In the example below, the drive is | |
| `/dev/sdc`. | |
| ```shell | |
| apk add parted | |
| parted /dev/sdc -- mklabel gpt | |
| parted /dev/sdc -- mkpart ESP fat32 1MB 100% | |
| parted /dev/sdc -- set 1 esp on | |
| ``` | |
| This creates a GPT table on `/dev/sdc`, then creates a first partition | |
| as FAT32 from the first megabyte up to the full disk size, and finally | |
| marks it bootable. This guide is only for UEFI compatible systems. | |
| We actually have to format the drive as FAT32, otherwise it's just a | |
| partition type without a way to mount it as FAT32: | |
| ``` | |
| mkfs.vfat /dev/sdc1 | |
| modprobe vfat | |
| ``` | |
| Final step, we use an Alpine tool to copy the bootloader from the | |
| installer to our new disk. In the example below, your installer may be | |
| `/media/usb` and the destination `/dev/sdc1`, you could figure the | |
| first one using `mount`. | |
| ``` | |
| setup-bootable /media/usb /dev/sdc1 | |
| ``` | |
| At this step, you made a USB disk in FAT32 containing the Alpine Linux | |
| installer you were using live. Reboot on the new one. | |
| ## System installation | |
| On your new installation media, run `setup-alpine` as if you were | |
| installing Alpine Linux, but answer "none" when you are asked which | |
| disk you want to use. When asked "Enter where to store configs", you | |
| should be prompted your new device by default, accept. Immediately, | |
| after, you will be prompted for an APK cache, accept. | |
| At this point, we can say Alpine is installed! Don't reboot yet, you | |
| are already on your new system! | |
| Just use it, and run `lbu commit` when you need to save changes done to | |
| packages or `/etc/`. `lbu commit` creates a new tarball in your USB | |
| disk containing a list of files configured in | |
| `/etc/apk/protected_paths.d/`, and this tarball is loaded at boot time, | |
| and will install your package list quickly from the local cache. | |
| Alpine Linux wiki: Alpine local backup (lbu command documentation) | |
| Please take extra care that if you include more files, everything you | |
| commit the changes, they have to be stored on your USB media. You | |
| could modify the fstab to add an extra disk/partition for persistent | |
| data on a performant drive. | |
| # Updating the kernel | |
| The kernel can't be upgraded using apk, you have to use the script | |
| `update-kernel` that will create a "modloop" file in the boot partition | |
| which contains the boot image. You can't rollback this file. | |
| You will need a few gigabytes in your in-memory filesystem, or use a | |
| temporary build directory by affecting `TMPDIR` variable to a | |
| persistent storage. | |
| By default, tmpfs on root is set to 1 GB, this can be increased given | |
| you have enough memory using the command: `mount -o remount,size=6G /`. | |
| The script should have the boot directory as a parameter, so it should | |
| look like `update-kernel /media/usb/boot` in a default setup, if you | |
| use an external partition, this would look like `env | |
| TMPDIR=/mnt/something/ update-kernel /media/usb/boot`. | |
| ## Extra configuration | |
| Here is a list of tweaks to improve your experience! | |
| ### keep last n configuration | |
| By default, lbu will only keep the last version you save, by | |
| setting`BACKUP_LIMIT` to a number n, you will always have the last n | |
| versions of your system stored in the boot media, this is practical if | |
| you want to roll back a change. | |
| ### apk repositories | |
| Edit `/etc/apk/repositories` to uncomment the community repository. | |
| ### fstab check | |
| Edit `/etc/fstab` to make sure the disk you are using is explicitly | |
| configured using a UUID entry, if you only have this: | |
| ``` | |
| /dev/cdrom /media/cdrom iso9660 noauto,ro 0 0 | |
| /dev/usbdisk /media/usb vfat noauto,ro 0 0 | |
| ``` | |
| This mean your system may have troubles if you use it on a different | |
| computer or that you plug another USB disk in it. Fix by using the | |
| UUID of your partition, you can find it using the program `blkid` from | |
| the eponym package, and fix the fstab like this: | |
| ``` | |
| UUID=61B2-04FA /media/persist vfat noauto,ro 0 0 | |
| /dev/cdrom /media/cdrom iso9660 noauto,ro 0 0 | |
| /dev/usbdisk /media/usb vfat noauto,ro 0 0 | |
| ``` | |
| This will ALWAYS mount your drive as `/media/persist`. | |
| If you had to make the change, you need to make some extra changes to | |
| keep things coherent: | |
| * set `LBU_MEDIA=persist` into `/etc/lbu/lbu.conf` | |
| * umount the drive in `/media` and run `mkdir -p /media/persist && | |
| mount -a`, you should have `/media/persist` with data in it | |
| * run `lbu commit` to save the changes | |
| ### desktop setup | |
| You can install a graphical desktop, this can easily be done with these | |
| commands: | |
| ``` | |
| setup-desktop xfce | |
| setup-xorg-base | |
| ``` | |
| Due to a bug, we have to re-enable some important services, otherwise | |
| you would not have networking at the next boot: | |
| ``` | |
| rc-update add hwdrivers sysinit | |
| ``` | |
| Alpine bug report #9653 | |
| You may want to enable the display manager at boot, which may be | |
| lightdm, gdm or sddm depending on your desktop: | |
| ``` | |
| rc-update add lightdm | |
| ``` | |
| ### user persistency | |
| If you added a user during `setup-alpine`, its home directory has been | |
| automatically added to `/etc/apk/protected_paths.d/lbu.list`, when you | |
| run `lbu commit`, its whole home is stored. This may not be desired. | |
| If you don't want to save the whole home directory, but only a | |
| selection of files/directories, here is how to proceed: | |
| 1. edit `/etc/apk/protected_paths.d/lbu.list` to remove the line adding | |
| your user directory | |
| 2. you need to create the user directory at boot with the correct | |
| permissions: `echo "install -d -o solene -g solene -m 700 /home/solene" | |
| | doas tee /etc/local.d/00-user.start` | |
| 3. in case you have some persistency set at least one user sub | |
| directories, it's important to fix the permissions of all the user data | |
| after the boot: `echo "chown -R solene:solene /home/solene | doas tee | |
| -a /etc/local.d/00-user.start` | |
| 4. you need to mark this script as executable: `doas chmod +x | |
| /etc/local.d/00-user.start` | |
| 5. you need to run the local scripts at boot time: `doas rc-update add | |
| local` | |
| 6. save the changes: `doas lbu commit` | |
| I'd recommend the use of a directory named `Persist` and adding it to | |
| the lbu list. Doing so, you have a place to store some important data | |
| without having to save all your home directory (including garbage such | |
| as cache). This is even nicer if you use ecryptfs as explained below. | |
| ### extra convenience | |
| Because Alpine Linux is packaged in a minimalistic manner, you may have | |
| to install a lot of extra packages to have all the fonts, icons, | |
| emojis, cursors etc... working correctly as you would expect for a | |
| standard Linux desktop. | |
| Fortunately, there is a community guide explaining each section you may | |
| want to configure. | |
| Alpine Linux wiki: Post installation | |
| ### Set X default keyboard layout | |
| Alpine insists of you using a qwerty desktop for X until you log into | |
| your session, this can be complicated to type passwords. | |
| You can create a file `/etc/X11/xorg.conf.d/00-keyboard.conf` like in | |
| the linked example and choose your default keyboard layout. You will | |
| have to create the directories `/etc/X11/xorg.conf.d` first. | |
| Arch Linux wiki: Keyboard configuration | |
| ### encrypted personal directory | |
| You could use ecryptfs to either encrypt the home partition of your | |
| user, or just give it a Private directory that could be unlocked on | |
| demand AND made persistent without pulling all the user files at every | |
| configuration commit. | |
| ``` | |
| $ doas apk add ecryptfs-utils | |
| $ doas modprobe ecryptfs | |
| $ ecryptfs-setup-private | |
| Enter your login passphrase [solene]: | |
| Enter your mount passphrase [leave blank to generate one]: | |
| [...] | |
| $ doas lbu add $HOME/.Private | |
| $ doas lbu add $HOME/.ecryptfs | |
| $ echo "install -d -o solene -g solene -m 700 /home/solene/Private" | doas tee … | |
| $ doas chmod +x /etc/local.d/50-ecryptfs.start | |
| $ doas rc-update add local | |
| $ doas lbu commit | |
| ``` | |
| Now, when you need to access your private directory, run | |
| `ecryptfs-mount-private` and you have your `$HOME/Private` directory | |
| which is encrypted. | |
| You could use ecryptfs to encrypt the whole user directory, this | |
| requires extra steps and changes into `/etc/pam.d/base-auth`, don't | |
| forget to add `/home/.ecryptfs` to the lbu include list. | |
| Using ecryptfs guide | |
| # Security | |
| Let's be clear, this setup isn't secure! The weak part is the boot | |
| media, which doesn't use secure boot, could easily be modified, and has | |
| nothing encrypted (except the local backups, but NOT BY DEFAULT). | |
| However, once the system has booted, if you remove the boot media, | |
| nothing can be damaged as everything lives in memory, but you should | |
| still use passwords for your users. | |
| # Conclusion | |
| Alpine is a very good platform for this kind of setup, and they provide | |
| all the tools out of the box! It's a very fun setup to play with. | |
| Don't forget that by default everything runs from memory without | |
| persistency, so be careful if you generate data you don't want to lose | |
| (passwords, downloads, etc...). | |
| # Going further | |
| The lbu configuration can be encrypted, this is recommended if you plan | |
| to carry your disk around, especially if it contains sensitive data. | |
| You can use the fat32 partition only for the bootloader and the local | |
| backup files, but you could have an extra partition that could be | |
| mounted for /home or something, and why not a layer of LUKS for | |
| encryption. | |
| You may want to use zram if you are tight on memory, this creates a | |
| compressed block device that could be used for swap, it's basically | |
| compressed RAM, it's very efficient but less useful if you have a slow | |
| CPU. |