Arch Home Server Setup

I have 2 old Acer Aspire ES1 laptops from when my boys were in middle school that I intend to use as home servers. Even Debian is getting close to leaving the old P4 machine behind (it’s my current home server). I’m enjoying Arch on my old Macbook, and think I’m ready for an arch server. I’m using the official Arch installation guide as well as a couple of articles I found while looking for a good guide to setting up an encrypted btrfs root.

Remote connection

The article on nerdstuff.org has a great suggestion to do the install remotely via ssh. After creating my boot media, I took my server (to be) downstairs, plugged it into the network switch, and booted to the flash drive.

Start SSH and set root password
root@archiso ~ # systemctl start sshd.service
root@archiso ~ # passwd
root@archiso ~ # ip addr show

Now, I hardened my ssh some time back, and disabled password authentication on my client, so after reading through the man page for ssh, I found the following let me connect:

Connect to target machine via SSH
$ ssh -l root -o PasswordAuthentication=yes -o ChallengeResponseAuthentication=yes 192.168.0.199

Set the time and verify boot mode

Now that we’re in, let’s make sure the time is correct on the system and get started.

Time configuration and EFI check
root@archiso ~ # timedatectl
root@archiso ~ # cat /sys/firmware/efi/fw_platform_size

Should return 64 or uefi 64. I’m not currently seeing the efi directory under /sys/firmware, so it appears I’m not booted in uefi mode. Going to wait for the disk wipe I already started to finish, then check my bios settings.

Yep, I switched from legacy to UEFI, then disabled secure boot in the bios. To disable secure boot, I had to: 1. set a supervisor password in the bios 2. disable secure boot 3. unset the supervisor password

I guess the last step isn’t really necessary, but I don’t need a bios password…​

Setting up the filesystems

I ran the following to wipe the drive before partitioning:

Wipe hard drive
root@archiso ~ # cryptsetup open --type plain --key-file /dev/urandom --sector-size 4096 /dev/sda to_be_wiped
root@archiso ~ # dd if=/dev/zero of=/dev/mapper/to_be_wiped status=progress bs=1M

I’m going to partition it with a 1GB EFI system partition (esp) and the rest is going to btrfs.

Partition the drive
root@archiso ~ # gdisk /dev/sda
GPT fdisk (gdisk) version 1.0.10

Partition table scan:
  MBR: not present
  BSD: not present
  APM: not present
  GPT: not present

Creating new GPT entries in memory.

Command (? for help): 0 # create a new empty GUID Partition table (GPT)
This option deletes all partitions and creates a new protective MBR.
Proceed? (Y/N): y

Command (? for help): n # add a new partition
Partition number (1-128, default 1):
First sector (34-976773134, default = 2048) or {+-}size{KMGTP}:
Last sector {2048-976773134, default = 976773119) or {+-}size{KMGTP}: 1G
Current type is 8300 (Linux filesystem)
Hex code or GUID (L to show codes, Enter = 8300): EF00
Changed type of partition to 'EFI system partition'

Command (? for help): n
Partition number (2-128, default 2):
First sector (34-976773134, default = 2099200) or {+-}size{KMGTP}:
Last sector (2099200-976773134, default = 97677319) or {+-}size{KMGTP}:
Current type is 8300 (Linux filesystem)
Hex code or GUID (L to show codes, Enter = 8300):
Changed type of partition to 'Linux filesystem'

Command (? for help): w # write table to disk and exit

Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!

Do you want to proceed? (Y/N): y
OK; writing new GUID partition table (GPT) to /dev/sda.
The operation has completed successfully.
Format the partitions
root@archiso ~ # mkfs.fat -F 32 /dev/sda1
mkfs.fat 4.2 (2021-01-31)

root@archiso ~ # cryptsetup -v luksFormat /dev/sda2

root@archiso ~ # cryptsetup open /dev/sda2 root

WARNING!
========
This will overwrite data on /dev/sda2 irrevocably.

Are you sure? (Type 'yes' in capital letters): YES
Enter passphrase for /dev/sda2: <passphrase>
Verify passphrase: <passphrase>
Key slot 0 created.
Command successful.
cryptsetup -v luksFormat /dev/sda2 10.16s user 0.89x system 27% cpu 39.826 total

root@archiso ~ # cryptsetup open /dev/sda2 root

root@archiso ~ # mkfs.btrfs -L DOLGAN /dev/mapper/root
btrfs-progs v6.10.1

My primary concern with this system is uptime, so I’m setting up my subvolumes to that end. Also, I’m not going to snapshot the pacman db separately, because it should stay at the same version as the rest of the system. I’m also creating a separate subvolume for the logs, so I can debug things after restoring an earlier snapshot.

While this server has been up and running for a while, I only recently created a swap file. I used to mistakenly think that if I have enough ram, what use is a swap file / partition, except for hibernation. Well, I read a doc linked from the arch swap page, In defense of swap, and learned things. Then decided to create swap-files on all of my systems, using a btrfs swap file.

Yes, yes…​ I’m up to 2 arch servers and a different arch laptop (my old macbook is dead), than I started with. AND, I still haven’t published this article from the beginning of my journey (not quite, the first article was about installing arch on the old macbook).

Setup subvolumes
root@archiso ~ # mount /dev/mapper/root /mnt
root@archiso ~ # btrfs sub create /mnt/@
root@archiso ~ # btrfs sub create /mnt/@home
root@archiso ~ # btrfs sub create /mnt/@snapshots
root@archiso ~ # btrfs sub create /mnt/@var_log
root@archiso ~ # btrfs sub create /mnt/@swap

root@archiso ~ # umount /mnt
Mount the volumes
root@archiso ~ # mount -o compress=zstd,subvol=@ /dev/mapper/root /mnt
root@archiso ~ # mkdir -p /mnt/{boot,home,var/log,.snapshots}
root@archiso ~ # mount -o compress=zstd,subvol=@home /dev/mapper/root /mnt/home
root@archiso ~ # mount -o compress=zstd,subvol=@var_log /dev/mapper/root /mnt/var/log
root@archiso ~ # mount -o compress=zstd,subvol=@snapshots /dev/mapper/root /mnt/.snapshots
root@archiso ~ # mount -o compress=zstd,subvol=@swap /dev/mapper/root /mnt/swap

root@archiso ~ # mount /dev/sda1 /mnt/boot
Create the swap file
root@archiso ~ # btrfs filesystem mkswapfile --size 8g --uuid clear /swap/swapfile
root@archiso ~ # swapon /swap/swapfile

Bootstrap Arch

Since I’m using this system as a server, I’m going to be leaving out a few things that I would normally install. I don’t intend to install a desktop environment, sound software, display drivers, etc…​

Base system
base linux linux-firmware
Almost base system
intel-ucode zsh neovim openssh man sudo iwd
Development software
base-devel git nodejs rustup python
System administration
btrfs-progs grml-zsh-config
Install arch
root@archiso ~ # pacstrap -K /mnt base linux linux-firmware intel-ucode zsh neovim openssh man sudo iwd base-devel git nodejs rustup python btrfs-progs grml-zsh-config
pacstrap -K /mnt base linux linux-firmware intel-ucode zsh neovim openssh man  156.28s user 75.57s system 83% cpu 4:38.34 total

I found that the generated fstab contained both subvolid= and subvol=. I’m removing the subvolid= from each entry.

It is preferable to mount using subvol=/path/to/subvolume, rather than the subvolid, as the subvolid may change when restoring #Snapshots, requiring a change of mount configuration.

Generate and fix the fstab
root@archiso ~ # genfstab -U /mnt >> /mnt/etc/fstab
root@archiso ~ # vim /mnt/etc/fstab

Final configuration

Change root, generate adjtime, and setup time syncronization. I’m skipping timezone configuration, due to this being a server.

root@archiso ~ # chroot /mnt
[root@archiso /]# hwclock --systohc
[root@archiso /]# systemctl enable systemd-timesyncd.service

Localization

Uncomment en_US.UTF-8 UTF-8 in the local.gen file then generate locale files. Add LANG=en_US.UTF-8 to locale.conf.

[root@archiso /]# nvim /etc/locale.gen
[root@archiso /]# locale-gen
[root@archiso /]# nvim /etc/locale.conf

Network setup

Set the hostname and hosts file

[root@archiso /]# nvim /etc/hostname
[root@archiso /]# nvim /etc/hosts
Hosts
127.0.0.1 localhost
::1 localhost
127.0.0.1 dolgan
Enable networking services
[root@archiso /]# systemctl enable systemd-networkd.service
[root@archiso /]# systemctl enable systemd-resolved.service
[root@archiso /]# nvim /etc/systemd/network/20-wired.network
[root@archiso /]# systemctl sshd.service

I tend to use IP reservations for managing the network, so let’s set this using DHCP.

20-wired.network
[Match]
Name=en*

[Network]
DHCP=yes

Boot setup

Modify HOOKS in mkinitcpio.conf for the encrypted btrfs filesystem.

mkinitcpio.conf
HOOKS=(base keyboard udev autodetect modconf block keymap encrypt btrfs filesystems)
[root@archiso /]# nvim /etc/mkinitcpio.conf
[root@archiso /]# mkinitcpio -P
[root@archiso /]# bootctl install
[root@archiso /]# nvim /boot/loader/entries/default.conf
[root@archiso /]# nvim /boot/loader/loader.conf
default.conf
title Dolgan (Arch Linux)
linux /vmlinuz-linux
initrd /intel-ucode.img
initrd /initramfs-linux.img
options cryptdevice=UUID=cbd43d7e-a7fe-45e1-870f-c6a7db88a1e6:root root=/dev/mapper/root rootflags=subvol=@
loader.conf
default dolgan.conf
timeout 4
console-mode max
editor yes

Set passwords / add user

[root@archiso /]# passwd
[root@archiso /]# useradd -mG wheel phil
[root@archiso /]# passwd phil
[root@archiso /]# EDITOR=nvim visudo
[root@archiso /]# exit
root@archiso ~ # ln -sf ../run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
root@archiso ~ # umount -R /mnt
root@archiso ~ # reboot

@phillipwills #ArchHomeServer

Published