Initial Setup (Arch Linux)
If at any point it is impossible to access your Raspberry Pi, then connect the micro SD card (containing your operating system) back to your main computer and edit any files necessary to get working again.
We can now insert the SD card into the Raspberry Pi, and connect the power (there is no on/off switch).
We should set up SSH on our main computer so that we can connect to the piserver simply with
ssh piserver. On our main computer we edit
Host piserver HostName <PISERVER IP ADDRESS>
Substituting in the IP address of the Raspberry Pi. We could:
- Try lots of random IP addresses until we find the right one (they're usually
192.168.1.x, and we can
pingto narrow down the list),
- Search for machines with
nmap 192.168.1.0/24 -sL | grep pi
- Use the MAC address on the Raspberry Pi obtained from
ip link listand look at the list of devices on our DHCP server (i.e. our router),
- Set a static IP address on the Raspberry Pi with
ip addr add,
- Set a static IP address for the Raspberry Pi on our DHCP server, or
- Set up Service Discovery (Avahi) so that we can
ssh piserver.localwhich works no matter what IP address the was given to the RPi from the DHCP server.
Users and Sudo
The Arch Linux ARM OS comes with two users:
root(the super-user), and
This is very easy to use but ultimately insecure, so we will remove access to both accounts.
We need to SSH into the piserver and switch to the root account.
# On your computer ssh alarm@piserver # Now on the Raspberry Pi su - root
We install some basic tools:
sudois used for security, allowing us to execute root commands without logging in as root.
pacmaticis a simple wrapper around
pacmanwhich can give warnings when doing system upgrades.
vimis the one true text editor.
htopis an excellent, intuitive monitoring tool.
pacman-key --init pacman-key --populate archlinuxarm pacman -Syu --needed sudo pacmatic vim htop
We create our adminstrative user and set its password, substituting
<YOU> for the username we like the most
useradd --groups wheel --create-home <YOU> passwd <YOU>
We give the adminstrative group
wheel sudo privileges by properly using
visudo -f /etc/sudoers.d/wheel
%wheel ALL=(ALL) NOPASSWD:ALL
We add our SSH key
Now we should logout, and SSH in as our new user to test everything is working.
Then we proced to remove the default
alarm user and lock
sudo userdel --remove alarm sudo passwd --lock root
The only way to login as root is to switch to it with
sudo su - root from your new administrative user account.
Hostname, Locale, Keymap, Timezone
We set a hostname, locale, keymap, and, if we don't want to use UTC, our local timezone.
sudo hostnamectl set-hostname piserver # Set the locale - view a list of locales with: # cat /etc/locale.gen or maybe localectl list-locales sudo localectl set-locale en_GB.UTF-8 sudo locale-gen # Set the keymap - view a list of keymaps with: # localectl list-keymaps sudo localectl set-keymap uk # Optionally, set our local timezone sudo timedatectl set-timezone $(tzselect)
Setting the keymap now is helpful if you ever need to plug in a keyboard.
Personal Preferences (Completely Optional)
- [ ] Move into the appendix and expand out.
~/.pam_environment for cross-shell environment variables.
This is a little more annoying than just using
.bashrc, but it does let us switch between shells more easily.
Install the fish shell and enable it for our user:
sudo pacmatic -S --needed fish chsh -s /usr/bin/fish $USER
We should make SSH more secure with some minor tweaks using
PermitRootLogin no AllowGroups wheel PasswordAuthentication no
Ensure you used
ssh-copy-idto copy over your SSH key before enabling
PasswordAuthentication noor else you will lose SSH access to the RPi.
Then, we can test our changes are valid and reload the service to pick up the new config:
sudo sshd -T sudo systemctl reload sshd
We enable time synchronisation because it is important for many different services. The built-in
systemd-timesyncd service is easy to use.
sudo systemctl enable --now systemd-timesyncd.service sudo timedatectl set-ntp true
Pacman will build up an infinite collection of cached system packages in
/etc/cache/pacman/pkg. This is not useful, and it is likely we have limited disk space on the PiServer. We can remove old cached packages using a pacman hook that runs after we execute certain pacman commands.
Keeping some old versions is useful for the (very) rare occasion that you want to downgrade.
Ensure the hooks directory is created
sudo mkdir -p /etc/pacman.d/hooks.
To remove all versions of an uninstalled package, we
[Trigger] Operation = Remove Type = Package Target = * [Action] Description = Removing package cache for uninstalled packages... When = PostTransaction Exec = /usr/bin/paccache -ruk0
To keep the last 3 versions of each package we still have installed, we
[Trigger] Operation = Upgrade Type = Package Target = * [Action] Description = Removing old cached packages... When = PostTransaction Exec = /usr/bin/paccache -rk3
Trim Flash Drives
Flash-based systems should be "trimmed" regularly to ensure optimal performance. This process physically clears the flash blocks for deleted files, which allows writes to those blocks to happen faster in the future.
SD cards and SSD drives normally support trim, while USB flash drives normally do not. The output of
mkfs.f2fs reveals whether trim is supported.
- [ ] In installation? What is the output?
It is possible trim when the file is deleted, but this is normally unnecessary. Therefore, we will enable
/usr/lib/systemd/system/fstrim.timer which trims all supported filesystems in
sudo systemctl enable --now fstrim.timer
On encrypted file systems, this will leak which areas of the drive are empty.
SD Card Longevity
Flash NAND storage has limited write durability. This can be worse than we think since even a tiny 1 byte write can cause an entire erase-block to be re-written, which might be 2 MB.
In general, leaving plenty of free space allows wear-levelling to function more effectively and increases the speed of the storage.
We can figure out what is writing to the disk with
sudo iotop -bktoqqq.
We can mount the filesystem to reduce metadata writes with
lazytime. The former stops writing file access times entirely, and the latter batches all file time updates to every minute.
/dev/mmcblk0p2 / ext4 rw,noatime,lazytime 0 0
View existing mounts with their options with
In addition to this, we can add a more dangerous mount option
commit=3600. This batches up all writes to the storage to commit every hour. Generally, this should not be used if you are storing or modifying any files on the RPi—which is certainly the case for our PiServer.
Check the validity of
sudo mount -a.
We can commit all changes to the filesystem using
The journal size for systemd is 10% of the filesystem, capped at 4 GiB. This is almost certainly fine for most situations, but it can be reduced in order to leave more free space for very small microSD cards.
The journal normally syncs to disk every 5 minutes for non-critical messages, this can be increased to batch up writes further. This is not recommended as it is likely to make debugging more difficult.
sudo mkdir -p /etc/systemd/journald.conf.d/ sudoedit /etc/systemd/journald.conf.d/00-journal-sdcard.conf
[Journal] SystemMaxUse=100M SyncIntervalSec=1h
It is also possible to keep log entries entirely in-memory with
Storage=volatile, but this is likely to make debugging more difficult.
We can keep swap disabled both because it is very slow on an RPi, and also because when it is in-use it causes a lot of writes.
- [ ] Consider setting up a tmpfs for
I would not recommend doing the following suggestion because
/var/tmp is supposed to survive reboots: mount
/var/tmp in-memory with
tmpfs /var/tmp tmpfs nodev,nosuid,size=50M 0 0.
We can improve the boot time by disabling unnecessary systemd services using
systemd-analyze blame and
For example, disabling:
- [ ] Fix network issues reported by netdata:
- [ ] Does this save?
sudo sysctl -a | grep netdev sudo sysctl net.core.netdev_budget=3000 sudo sysctl net.core.netdev_budget_usecs=4000
Simple Outbound Mail
- [ ] Migrate from blog. Move to "Things we can do".
There are further steps that we can take, however they offer increasingly diminishing returns. We do not consider MAC/ACLs/SELinux because they are, apparently, a PITA.
- [ ] Delay after login attempts (user accounts).
- [ ] Limit number of processes a user may have.
- [ ] Limit users which may login as root: https://wiki.archlinux.org/index.php/Security#Allow_only_certain_users
- [ ] Kernel hardening: https://wiki.archlinux.org/index.php/Security#Kernel_hardening
Firewall - UFW
https://wiki.archlinux.org/index.php/Umask#Set_the_mask_value. However, it might be really inconvenient.
Since it's headless we don't need those ports.
TBD: What does this protect against exactly?
We cannot just disable the USB controller because that would also disable the ethernet.
A few tips for
# Misc options Color TotalDownload