Configuring Ubuntu Server on a Raspberry Pi
I have a standard base configuration for my Raspberry Pi Ubuntu servers. These are the changes I make from the standard install.

This is a list of the changes I typically make to a standard Ubuntu Server install on a Raspberry Pi (and other hardware) to get them up and running on my local network.
You should be able to ssh into the Pi as the default user from your computer, the Pi should be able to access the Internet, and you should be able to use a text editor such as nano or vi and understand what the sudo
command does.
Basic Operating System configuration
Set the root password using sudo root passwd
, making sure it is a secure password that you will remember.
Make sure the operating system is up to date by running sudo apt update
and then sudo apt upgrade
, answering [Y
]es to any prompts.
If the Pi is fitted with a PoE hat with a fan, adding these lines to the file /boot/firmware/config.txt
in the [pi4]
or the [all]
section will ensure the fan works reliably. Edit the file (as you do with all the file edits below) with sudo nano /boot/firmware/config.txt
[pi4]
max_framebuffers=2
arm_boost=1
# PHIL - ADDED FOR PI PoE Hat Fan
dtoverlay=rpi-poe
dtparam=poe_fan_temp0=50000
dtparam=poe_fan_temp1=58000
dtparam=poe_fan_temp2=64000
dtparam=poe_fan_temp3=68000
If you are using Prometheus to monitor your servers (any more than a handful and you should be!), install the prometheus-node-exporter
with sudo apt install prometheus-node-exporter
.
Install zsh as a shell option for users with sudo apt install zsh
.
Fix unattended upgrades configuration to automatically upgrade your OS while you sleep. In /etc/apt/apt.conf.d/50unattended-upgrades
uncomment (by removing the #) the line "${distro_id}:${distro_codename}-updates"
and then find and change these settings:
Unattended-Upgrade::Remove-Unused-Dependencies "true";
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "02:00";
Make sure that unattended upgrades does more housekeeping than it would normal do by adding these lines to /etc/apt/apt.conf.d/20auto-upgrades
:
APT::Periodic::Download-Upgradeable-Packages "1";
APT::Periodic::AutocleanInterval "30";
The Raspberry Pi doesn't come with an Intelligent Platform Management Interface (IPMI), so you can safely disable that with sudo systemctl disable openipmi
.
If you are going to run Docker (and why wouldn't you...) then you can install it using this series of commands:
sudo apt install \
ca-certificates \
curl \
gnupg \
python3-pip\
lsb-release
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin docker-compose
Add your default user to the docker
group and to www-data
while you are at it:
sudo usermod -aG docker <INSERT USER NAME>
sudo usermod -aG www-data <INSERT USER_NAME>
Configure the docker daemon for json-file format logs with a maximum size to make sure they don't fill up your drive, and enable the Prometheus metrics exporter if you are using Prometheus. If you don't know your Pi's IP address then you can find it with ip address show dev eth0
. Create the file /etc/docker/daemon.json
with the following contents:
{
"metrics-addr" : "<YOUR IP ADDRESS>:9323",
"experimental" : true,
"log-driver": "json-file",
"log-opts": {
"max-size": "250m",
"max-file": "3"
}
}
Install chrony to keep the system clock in decent shape with sudo apt install chrony
. If you have a local NTP time server (something you trust as the Pi 4 has no battery backed clock by default) then add it to /etc/chrony/chrony.conf
after the ntp pools, I use one of my Synology NAS's that is setup to serve time:
pool ntp.ubuntu.com iburst maxsources 4
pool 0.ubuntu.pool.ntp.org iburst maxsources 1
pool 1.ubuntu.pool.ntp.org iburst maxsources 1
pool 2.ubuntu.pool.ntp.org iburst maxsources 2
server nas-2.little.place
Install some handy system admin tools with sudo apt install bmon nmap network-manager
.
If you are not using WiFi and Bluetooth, turn them off with sudo nmcli radio wifi off
.
Install the Raspberry Pi configuration tool with sudo apt install raspi-config
and then run it using sudo raspi-config
and go to the Performance Options
section and set the GPU memory
to the smallest allowed 16
as this is a headless server and so you will not need any display memory.
Reboot the Pi, and log back in once it is up and running.
Remove the news and help sections from the message of the day that appears every time you login by running sudo chmod a-x /etc/update-motd.d/10-help-text
and changing ENABLED=1
to ENABLED=0
in /etc/default/motd-news
.
Create your ssh keys by running ssh-keygen
.
Install oh-my-zsh for zsh by running sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
and then edit ~/.zshrc
to load the following components (this is a matter of taste - you can drop macos
if you don't use Mac's for example):
# Which plugins would you like to load?
# Standard plugins can be found in $ZSH/plugins/
# Custom plugins may be added to $ZSH_CUSTOM/plugins/
# Example format: plugins=(rails git textmate ruby lighthouse)
# Add wisely, as too many plugins slow down shell startup.
plugins=(z wd macos screen history history-substring-search git common-aliases zsh-syntax-highlighting docker docker-compose)
Installing Mac and PC file services
If you want to serve files to PC's and Mac's as a file server (which you almost certainly do) then sudo apt install netatalk samba
. Configure Samba by editing /etc/samba/smb.conf
like this:
Add these lines to the [global]
section of /etc/samba/smb.conf:
[global]
# Phil added
min protocol = SMB2
vfs objects = catia fruit streams_xattr
fruit:metadata = stream
fruit:model = MacSamba
fruit:posix_rename = yes
fruit:veto_appledouble = no
fruit:wipe_intentionally_left_blank_rfork = yes
fruit:delete_empty_adfiles = yes
multicast dns register = no
Set up the [homes]
section like this:
[homes]
comment = Home Directories
browseable = no
read only = no
create mask = 0700
directory mask = 0700
valid users = %S
Set up the [printers]
section like this:
[printers]
comment = All Printers
browseable = no
path = /var/tmp
printable = yes
guest ok = yes
read only = yes
create mask = 0700
[print$]
comment = Printer Drivers
path = /var/lib/samba/printers
browseable = yes
read only = yes
guest ok = yes
Fix the Avahi configuration by changing the following parameters in /etc/avahi/avahi-daemon.conf
:
[server]
domain-name=local
use-ipv4=yes
use-ipv6=yes
ratelimit-interval-usec=1000000
ratelimit-burst=1000
[wide-area]
enable-wide-area=yes
[publish]
add-service-cookie=yes
publish-hinfo=yes
publish-workstation=yes
Make sure Avahi is advertising local file and samba services by creating the following two files:
Create /etc/avahi/services/afpd.service
containing:
<?xml version="1.0" standalone='no'?><!--*-nxml-*-->
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
<name replace-wildcards="yes">%h</name>
<service>
<type>_afpovertcp._tcp</type>
<port>548</port>
</service>
<service>
<type>_device-info._tcp</type>
<port>0</port>
<txt-record>model=iMac</txt-record>
</service>
</service-group>
Create /etc/avahi/services/smb.service
containing:
<?xml version="1.0" standalone='no'?><!--*-nxml-*-->
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
<name replace-wildcards="yes">%h</name>
<service>
<type>_smb._tcp</type>
<port>445</port>
</service>
<service>
<type>_device-info._tcp</type>
<port>0</port>
<txt-record>model=iMac</txt-record>
</service>
</service-group>
Enable Mac file services by editing /etc/netatalk/afp.conf
to set where home directories can be found:
[Homes]
basedir regex = /home
Fix permissions on those files with sudo chmod 644 /etc/samba/smb.conf /etc/avahi/avahi-daemon.conf /etc/avahi/services/afpd.service /etc/avahi/services/smb.service
and then restart everything with sudo systemctl restart smbd netatalk nmbd avahi-daemon
.
Setting up things like email and docker containers is next on the list.