Initializing a new Raspberry Pi as a Headless Server

Kriz Poon
4 min readFeb 6, 2021

A Raspberry Pi is such a compact device and yet can run a full-featured Linux OS. It would take out all the fun if it is attached to all those mouse, keyboard, monitor and ethernet. In this tutorial, we will setup our Pi such that it only requires one USB cable as power source.

First, we flash the official Raspberry Pi OS onto an SD card.

Enable SSH

We will use SSH to connect to our Pi and finish our configuration.

Enable SSH access by creating an empty file ssh in the boot folder (the actual boot folder location depends on you OS):

# Mac/Linux
touch boot/ssh

Connect to Wi-Fi

For the initial connection, you could use an ethernet cable. But if you have access to a Wi-Fi network. You could skip that by adding an initial Wi-Fi config to boot/wpa_supplicant.conf :

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=<Insert 2 letter ISO 3166-1 country code here>
network={
ssid="<Name of your wireless LAN>"
psk="<Password for your wireless LAN>"
}

You may add more Wi-Fi networks by repeating the network block.

First Boot

Insert the SD card to you Pi and connect it to a power source. It should be connected to the Wi-Fi in a few moments. For the first boot, it will take longer. Now, we need to connect to the Pi. By default, the hostname of the newly setup Pi is raspberrypi. If you ssh pi@raspberrypi.local, it may just work. If it doesn’t, try the following step:

On the computer connected to the same Wi-Fi, run the following command to inspect the ARP table:

# Mac/Linux
arp -an
# PowerShell
arp /a /n

The Pi should be listed in this table. If not, you may need to inspect the ARP table of your router.

Now we can SSH into the Pi:

ssh pi@<host-of-your-pi>

The default password of a freshly installed Raspbian is raspberry . We should change this as soon as possible:

passwd

We should also change the root password:

sudo passwd root

Password-less SSH authentication

You may want to access your Pi without typing a password every time. You could add your SSH key to ~/.ssh/authorized_keys manually or use the following command:

ssh-copy-id pi@<host-of-your-pi>

Timezone, locale and other stuffs

Once we are inside the Pi we can run the raspi-config to configure timezone, locale and other stuffs easily:

sudo raspi-config
Screenshot of raspi-config

Command aliases

If you use the command line a lot, it’s a good idea to add some command aliases to ~/.profile , for example:

# Add to bottom of ~/.profile
alias ll='ls -ahlF'

Then either logout and login or run the following to enable the aliases:

source ~/.profile

Connecting via USB type-C

If you have a Pi 4 model B and you don’t want to connect via WiFi or a clumsy ethernet cable, it’s possible to connect to your computer / iPad with a USB type-C cable.

Edit /boot/cmdline.txt , add modules-load=dwc2 after rootwait, e.g.:

console=serial0,115200 console=tty1 root=PARTUUID=e6bee249-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait modules-load=dwc2,g_ether quiet splash plymouth.ignore-serial-consoles

Edit /boot/config.txt , add dtoverlay=dwc2 at the bottom of the file, e.g.:

[all]
#dtoverlay=vc4-fkms-v3d
dtoverlay=dwc2

Add libcomposite to the end of /etc/modules

If you reboot the Pi now, there will be a new interface usb0 . Because we will be offering IP address to connecting devices, we need to opt-out of the DHCP client:

# Add to end of /etc/dhcpcd.confdenyinterfaces usb0

DHCP Server

We will setup a DHCP server for usb0. Install dnsmasq:

sudo apt update
sudo apt install dnsmasq -y

Create a configuration file at /etc/dnsmasq.d/usb

interface=usb0
dhcp-range=10.24.0.2,10.24.0.6,255.255.255.248,1h
dhcp-option=3
leasefile-ro

Here we defined an IP address range from 10.24.0.2 through 10.24.0.6 with a subnet mask 255.255.255.248 and lease time of 1 hour. You may choose any addresses from the private IPv4 address space that do not conflict with your other networks. Note that the range must not include the server itself and the broadcast address.

Next, we’ll choose a static IP for usb0 , create and edit a file /etc/network/interfaces.d/usb0 :

auto usb0
allow-hotplug usb0
iface usb0 inet static
address 10.24.0.1
netmask 255.255.255.248

Create Ethernet Gadget

We need to make our USB type-C port to behave as an ethernet device. Ben Hardill made an excellent script for this, you may copy the script from: https://www.hardill.me.uk/wordpress/2019/11/02/pi4-usb-c-gadget/

Paste the content to /root/usb and make it executable:

sudo chmod +x /root/usb.sh

Now we need to run the script at boot time:

sudo crontab -e

Add the following line:

@reboot bash /root/usb.sh

Finally, we can restart the Pi and test the connection!

sudo reboot now

avahi / zeroconf / Bonjour for Linux

Let’s go one step further. We can access our Pi with host name no matter it is connected to Wi-Fi or ethernet or USB-C using something like Bonjour on Mac: avahi:

sudo apt update
sudo apt install avahi-daemon

Create /etc/avahi/services/multiple.service with the following content:

<?xml version="1.0" standalone='no'?>
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
<name replace-wildcards="yes">%h</name>
<service>
<type>_device-info._tcp</type>
<port>0</port>
<txt-record>model=RackMac</txt-record>
</service>
<service>
<type>_ssh._tcp</type>
<port>22</port>
</service>
</service-group>

Start the service:

sudo systemctl restart avahi-daemon

Test connection:

ssh pi@<hostname>.local

Now that you can reliably connect to your Pi, you can run / build your favorite server application!

--

--