Raspberry Pi Headless Setup

Getting started with the Pi

I was waiting a long time to get my hands on one of these. Raspberry Pi is SBC (Single-Board Computer) with which you can do almost anything. Because of the pocket size of this full fledged computer you can use it as a web / mail / git server, cloud storage / NAS, seedbox, VPN, media center, SDR etc. and power all kinds of creative IoT projects. The beauty of the Pi lies in that it can be easily expanded with additional components such as sensors or even microcontrollers such as an Arduino.

Raspberry Pi 3 Model B

SoC Broadcom BCM2837 64bit
CPU 4× ARM Cortex-A53 | 1.2GHz
Instruction Set ARMv8
GPU Broadcom VideoCore IV @ 400 MHz
Memory 1 GB LPDDR2-900 SDRAM (900 MHz)
Networking 10/100 Ethernet | Broadcom BCM43438 2.4GHz 802.11n wireless LAN
Bluetooth Bluetooth 4.1 Classic | Bluetooth Low Energy
GPIO 40-pin header | Populated
Storage microSD
Ports HDMI | 3.5mm analogue audio-video jack, 4× USB 2.0 | Ethernet | Camera Serial Interface (CSI) | Display Serial Interface (DSI) | Micro SD port
Power Supply 5.1V | Micro USB power source up to 2.5A

The Pi tends to get hot (37-80°C in a 20-25°C environment). Putting a fan or heatsink is a great thing to do.

The Pi with a Heatsink

Flashing an OS

The Pi is the most widely worked on and supported SBC. As such you have a good choice of Operating System images to flash - from almost any Linux distribution to Windows 10. The Pi’s default OS is Raspbian. It comes in 2 flavors - the lite one without desktop environment and the with desktop. For this installation we’ll be using the Raspbian with Desktop - the current version being Raspbian Strech based on Debian Strech. Here’s a short list of available alternatives.

OS Installers NOOBS
Linux Raspbian
pi-get 1
Comitup 2
Ubuntu MATE
Ubuntu Core
Kali Linux
The Void (Linux) 3
Windows Windows 10 IoT Core
Gamebox RetroPi
Media Box LibreELEC
  • 1 Build tool for Raspbian images - A recomendation by fs111
  • 2 Raspbian extended with a service for wireless headless setup by David Steele
  • 3 A recomendation by zge
  1. It’s recommended to use class 10 microSD card. Plug in your card reader with the microSD card inside to your PC and flash the image. The easiest way to do this is by using the cross-platform tool called Etcher.
  2. Since we’re doing the headless installation (without monitor, keyboard and mouse) we have to create an empty ssh file in the boot directory to enable the OpenSSH server which is disabled by default.
  3. Now we’re ready to put the microSD card back in the Pi, connect the Ethernet cable to our PC and power it on.

SSH & .local Domain

In order to access our Pi through SSH we need to find it’s IPv4 address on our local network.


The fastest and most reliable way to find the Pi’s IP is using the mDNS protocol. It resolves hostnames ending with the .local domain. The default hostname of the Pi is raspberrypi.

  • Windows has a limited mDNS support. Using Apple’s Bonjour implementation can fix this. Install Bonjour Print Services. If you already have iTunes you don’t need to install it. mDNS should now be working. After that ping the Pi to find it’s local IP using command prompt:

    ping -4 raspberry.local
    And example output if it works:
    Pinging raspberrypi.local [] with 32 bytes of data:
    Reply from bytes=32 time<1ms TTL=64
    Reply from bytes=32 time=2ms TTL=64
    Reply from bytes=32 time<1ms TTL=64
    Reply from bytes=32 time<1ms TTL=64
    Ping statistics for
        Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
    Approximate round trip times in milli-seconds:
        Minimum = 0ms, Maximum = 2ms, Average = 0ms
  • For Linux machnes there is Avahi - a fantastic open source mDNS implementation. Install it on your distro and you’re ready to go.

    • Debian Based

      sudo apt-get update && sudo apt-get upgrade
      sudo apt install avahi-daemon libnss3 libnss-mdns libnss-myhostname libnss-mymachines libnss3-tools
      # Enalbe Avahi
      systemctl enable avahi-daemon --now
      If after that the .local is not resolving follow the Arch nsswitch.conf instructions below.
    • Arch Based

      sudo pacman -Syu
      sudo pacman -S avahi nss-mdns
      # Enalbe Avahi
      systemctl enable avahi-daemon --now

      Then to enable IP multicast DNS lookups, edit the file /etc/nsswitch.conf and change the hosts line to include if it already doesn’t mdns_minimal(resolves both IPv4 & IPv6) / mdns4_minimal(resolves only IPv4) / mdns6_minimal(resolves only IPv6) before [NOTFOUND=return], resolve and dns and append mdns / mdns4 / mdns6 after. Here is example config for resolving IPv4 addresses.

      hosts: files mymachines mdns4_minimal [NOTFOUND=return] resolve [!UNAVAIL=return] dns mdns4 myhostname

    Now lets ping the Pi.
    ping raspberry.local
    Expected output:
    PING raspberry.local ( 56(84) bytes of data.
    64 bytes from icmp_seq=1 ttl=51 time=84.9 ms
    64 bytes from icmp_seq=2 ttl=51 time=81.9 ms
    64 bytes from icmp_seq=3 ttl=51 time=85.1 ms
    64 bytes from icmp_seq=4 ttl=51 time=81.7 ms
    --- raspberry.local ping statistics ---
    4 packets transmitted, 4 received, 0% packet loss, time 3002ms
    rtt min/avg/max/mdev = 81.784/82.232/83.373/0.662 ms


Now when we got the Pi’s IP sorted out let’s connect to it.

Hostname rasberrypi
User pi
Password raspberry
# Using the IP obtained above
ssh pi@
# Or if you already have mDNS working
ssh pi@raspberrypi.local

Enter the password when asked and at last you’ve been connected to your Pi.

Initial Configuration

The first thing to do when you access your Pi is to change its configuration. To modify the defaults type sudo raspi-config in your terminal. You’ll see the Software Configuration Tool:

  1. The most important things to change are to enable the SSH and VNC servers on boot. You can do this by going to 5 Interfacing Options. If you forget to enable the SSH server to create again empty ssh file in the boot directory. It enables the SSH server for the current session and deletes the file afterwards.
  2. From 2 Boot Options > B1 Desktop / CLI you can choose to enable or disable the Desktop Environment on boot
  3. If are going to use the Pi for some GPU intensive task allocate more memory to the GPU. By default it has 64 MB. 128 MB is a good amount. You can change it from 7 Advanced Options > A3 Memory Split.
  4. From 7 Advanced Options > A5 Resolution change the screen resolution. The default is 720x480
  5. From 7 Advanced Options > A1 Expand Filesystem makes all free SD Card space available to the OS


This is an optional step if you want to use the Desktop Environment. Open your VNC Viewer of choice and enter the IPv4 address we used to connect through SSH. My preferred VNC Viewer is RealVNC. Some of the best alternatives include TigerVNC and TightVNC. If you don’t intend to do any privacy-sensitive work you can disable Encryption on the Pi’s VNC Server to improve the overall quality.

This is a handy function to install the RealVNC as Standalone on Linux. Replace name with the current version.

function realvnc_install(){
    wget https://www.realvnc.com/download/file/viewer.files/$name
    mv ./$name ~/ && sudo chmod +x ~/$name

It’s also a good idea to create an alias for quick startup. Replace .bashrc with your preferred file for storing your aliases.

echo 'alias vnc="~/VNC-Viewer-6.17.1113-Linux-x64"' >> ~/.bashrc


Network Manager

Installing network manager can make your life easier when configuring network connections. The 2 most used ones are the Gnome’s NetworkManager and wicd. On my Pi I use wicd. It has both GUI and a more lightweight CLI interface.

sudo apt-get install wicd wicd-gtk wicd-curses

To start the CLI interface type sudo wicd-curses.


Getting your Pi connected to the internet can prove to be quite challenging when you don’t use your Ethernet cable only for this purpose. Until this moment we managed to connect to the Pi using the Ethernet cable through SSH. If you haven’t already noticed the Pi has no access to the internet.

To deal with this I’ll share my PC’s Wifi internet to the Pi. In my experience the only way that proved to work regardless of what Operating System you use is to set a static IP. The Pi connects to the host with that IP and the host’s Ethernet adaptor forwards the Wifi’s internet using the same one.

  • Assign Static IP address on the Pi

    To set the static IP on the Pi’s side we need to edit /etc/dhcpcd.conf file containing the DHCP Server configuration. Append the following to the end of that file.

    interface eth0
    static ip_address=
    static routers=
    static domain_name_servers=

    Now the Pi will repsond to as it’s static address. If you want a different one change the last digit on the line static ip_address to a number in the range 2-254 included. One more thing. Make sure you comment everything in /etc/network/interfaces file out. It contains autodiscovery adaptor settings that may interfere with those of for DHCP. Next we need to modify our hosts to respond to this adress.

  • Windows 10 Host Configuration

    • On Windows there are no dependencies you need to install.

    • Enable Packet Forwarding

      Go to Control Panel > Network and Sharing Center > Change adapter settings. Right click on you Wifi Adaptor and go to Properties. In the Sharing tab tick Allow other network users to connect through this computer's internet connection and then under Home network connection: select your Ethernet adapter and click OK. Now besides your Wifi SSID you’ll see the label Shared.

    • Assign Static IP address

      Windows by default set the static IPv4 address for your Ethernet adapter to with subnet mask To double check right-click you Ethernet adapter and go to Properties. Under Internet Protocol Version 4 (TCP/IPv4) click Properties and you should see the following:

      If you don’t change the setting accordingly and restart your Pi. After reboot SSH to the Pi and voila. You should now have internet access. Ping for example google.com to make sure you indeed have internet.

  • Linux Host Configuration

    • Install Dependencies

      • Debian Based

        yes Y | sudo apt install net-tools iptables iproute2
      • Arch Based

        yes Y | sudo pacman -S net-tools iptables iproute2
    • Assign Static IP address

      Use this to list all available network adapters.
      sudo ip link
      If you're using network manager enter the following for the IPv4 settings for the Ethernet adaptor.
      Or assign the static IP from the command line. Replace enp3s0 with your adaptor.
      sudo ip link set up dev enp3s0
      sudo ip addr add dev enp3s0 # arbitrary address
    • Enable Packet Forwarding

      To share the internet connection we need to enable packet forwarding. To check the current settings.
      sysctl -a | grep forward

      Edit or create if it doesn’t exist /etc/sysctl.d/30-ipforward.conf and add to it. This ensures that the packet forwarding is going to be enabled on boot.

    • Enable NAT

      • Host Configuration
        function iptables_config(){
            sudo iptables -t nat -A POSTROUTING -o wlp2s0 -j MASQUERADE
            sudo iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
            sudo iptables -A FORWARD -i enp3s0 -o wlp2s0 -j ACCEPT
        Replace wlp2s0 with your Wifi adaptor and enp3s0 with your Ethernet adaptor.
      • Save the rules and apply them automatically on boot

        • Arch Based

          # Save the rules
          iptables=/etc/iptables/iptables.rules && \ 
          sudo iptables-save > /etc/iptables/iptables.rules
          # Load them on boot
          systemctl enable iptables.service
        • Debian Based

          # Save the rules
          sudo touch /etc/iptables.rules
          sudo iptables-save > /etc/iptables.rules
          # Load them on boot
          sudo touch /etc/network/if-pre-up.d/iptables && \ 
          sudo chmod +x /etc/network/if-pre-up.d/iptables && \ 
          echo -e '#!/bin/sh\n/sbin/iptables-restore < /etc/iptables.rules' | \ 
          sudo tee -a /etc/network/if-pre-up.d/iptables > /dev/null
      • Client Configuration (Pi)

        function iptables_client(){
            sudo iptables -I INPUT -p udp --dport 67 -i et0 -j ACCEPT
            sudo iptables -I INPUT -p tcp --dport 53 -s -j ACCEPT
            sudo iptables -I INPUT -p udp --dport 53 -s -j ACCEPT
        After adding these rules on the Pi execute the same steps as for Debian above to save and apply them on boot.

An example iptables.rules files for enabling NAT can be found here. They also contain some additional configurations such as for accepting input from the http/https ports.


Connecting the Pi to Wifi is way more straightforward. Here I’m gonna show you how to let the Pi connect to a Wifi network automatically on boot. Append the following to /etc/network/interfaces file on the Pi.

  • Open

    auto wlan0
    allow-hotplug wlan0
    iface wlan0 inet dhcp
        wireless-essid MySSID
  • Password Protected

    auto wlan0
    allow-hotplug wlan0
    iface wlan0 inet dhcp
        wpa-ssid MySSID
        wpa-psk MyPass

Replace MySSID with your Wifi SSID and MyPass with the password. Reboot to apply the changes. You can now connect to the Pi wirelessly.


Overclocking the Pi usually doesn’t yield huge performance improvements. If you still want to give it a try you can overclock the Pi by editing the /boot/config.txt file. These are some useful functions for getting some stats about the Pi.

# Install bc - a calculator library
sudo apt install bc

# CPU Frequency in MHz
function cpu_frequency(){
    var=$(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq)
    echo $(echo "$var/1000" | bc)

# Temperature in Celsius
function temperature(){
    var=$(cat /sys/class/thermal/thermal_zone0/temp)
    echo $(echo "$var/1000" | bc)

The most common overclocking options are for increasing the CPU and GPU Frequency. You can also overvoltage the Pi but we won’t do it for this tuturial. Edit the following options in /boot/config.txt, reboot and now you have overclocked your Pi. Below you can see an example configuration.

# Frequency of the ARM CPU in MHz. The default value is 1200 for the Pi 3.

# Sets core_freq, h264_freq, isp_freq, and  v3d_freq together.
# On Pi 3 core_freq defaults to 400 and h264_freq,  isp_freq and v3d_freq default to 300.

# Frequency of the GPU processor core in MHz.
# core_freq

Thank you for reading my article. You can find related reading material below.