Skip to content

Instantly share code, notes, and snippets.

@V-ed
Last active June 21, 2020 10:09
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save V-ed/161c3dac9db058e2aab65ed6b5b2feaf to your computer and use it in GitHub Desktop.
Save V-ed/161c3dac9db058e2aab65ed6b5b2feaf to your computer and use it in GitHub Desktop.
Raspberry Pi Basic Setup with Pi-hole + OpenVPN installation

Setting up a new headless Raspberry Pi from Scratch : A Quickstart Guide

Note : These instructions have been tested for the Raspberry Pi 3B+ and Raspberry Pi 4B. You can try these on older versions, but I have no guarantee that these instructions will work correctly.

Enabling SSH before the first boot of the Raspberry Pi

To enable SSH in your Raspberry pi before actually booting it up, simply create a file named ssh (with no extension) in the boot partition of your card.

Ref : https://www.raspberrypi.org/documentation/configuration/wireless/headless.md

Please read me from this point!

Before proceeding, please connect your Raspberry Pi to an Ethernet port. This will save you much trouble trying to connect to a Wi-Fi network and will make most of these enhancements much simpler to execute. You actually won't even need to setup internet, as it will be served automatically!

Changing the default pi user

The first thing I do on a headless Raspberry Pi is change the default pi user to give more security once the device will be online.

Steps for changing default pi user

  1. sudo adduser USERNAME
  2. for GROUP in $(groups pi | sed 's/.*:\spi//'); do sudo adduser USERNAME $GROUP; done
  3. Add new user USERNAME to sudoers to prevent entering the sudo password each session by replacing the pi sudoer's file :
    1. sudo mv /etc/sudoers.d/010_pi-nopasswd /etc/sudoers.d/010_USERNAME-nopasswd
    2. sudo nano /etc/sudoers.d/010_ved-nopasswd
      1. Rename the pi user in this file to the USERNAME you have created.
  4. sudo userdel -r pi

Refs (changing default pi user)

Removing the login messages

When login in the raspberry pi via SSH, alot of text is printed and this might be annoying. To remove those messages, simply login to your user account, and use this command :

touch ~/.hushlogin

This creates an empty file named .hushlogin at the root of your home directory, and this files tells the SSH session to not show the login message when connecting to your user.

Ref : https://www.raspberrypi.org/forums/viewtopic.php?t=124986

Mounting an external USB Drive automatically on boot

This section explains how to mount an external USB drive automatically on boot for having a NAS, for example.

Most of the explanations can be found here, this is mostly a wrap up.

Steps for mounting external USB device

  1. Plug the usb device
  2. List all disk partitions : sudo lsblk -o UUID,NAME,FSTYPE,SIZE,MOUNTPOINT,LABEL,MODEL
    • You should see your device, most probably with the name sda1
    • Take note of the UUID shown for your device, it will be used later!
  3. This part assumes your drive is of type NTFS : make sure the packages are present on the pi (they should be, but check to make sure) :
    1. sudo apt update
    2. sudo apt install ntfs-3g
  4. Use sudo blkid to find the location of the disk partition
    • It will probably be /dev/sda1 (or /dev/sdaN, replacing the N with a number)
    • It will have the same UUID of the device you found at step 2
  5. Create a mounting directory for your device :
    1. sudo mkdir /mnt/nas You can rename nas to anything, I named it that way to call it a Network Attached Storage
  6. (optional) Mount your device using the command sudo mount /dev/sda1 /mnt/nas (replace the /dev/sda1 /mnt/nas values with those tailored for you found in the previous steps)
    1. Verify if you can access your drive : ls /mnt/nas
  7. Edit your fstab file to mount your drive automatically
    1. sudo nano /etc/fstab
    2. Add UUID=YOUR_DEVICE_UUID /mnt/nas ntfs defaults,auto,users,rw,nofail,umask=000,x-systemd.device-timeout=30 0 0 at the end of the file Mine looks like this :
    proc            /proc           proc    defaults          0       0
    PARTUUID=6c586e13-01  /boot           vfat    defaults          0       2
    PARTUUID=6c586e13-02  /               ext4    defaults,noatime  0       1
    # a swapfile is not a swap partition, no line here
    #   use  dphys-swapfile swap[on|off]  for that
    
    UUID=MY_UUID /mnt/nas ntfs defaults,auto,users,rw,nofail,umask=000,x-systemd.device-timeout=30 0 0
    
  8. Reboot (sudo reboot) and verify after reboot if your external USB drive is accessible using ls /mnt/nas
  9. (optional) Create a symlink to easily access your device from your home directory : ln -s /mnt/nas[/... folders] ~/nas
    • This will create a symlink in your home directory named nas that you can treat as a folder (ex. : cd ~/nas/[...])
    • You can select a subfolder for your drive to be your default location for when you go into your home nas "folder" (symlink) by changing the [/... folders] part this command

Refs (usb mounting)

Setup a neat little Bash command prompt

This is mostly for me, but it gives a nice little terminal prompt that shows the current Git branch if you are in a git repository, shows the current time (useful to know when a previous command was entered!) and few color goodies.

Bash command prompt Preview

terminal prompt preview

Within a git repository :

terminal prompt preview within git repository

Steps for setting up bash prompt

  1. make sure Git is installed : sudo apt-get install git
  2. Follow one of the two options below

Option 1 : Manually editing your .bashrc

  1. Open your .bashrc file : nano ~/.bashrc
  2. Find the line that starts with PS1='
  3. Edit the PS1 line directly or simply add this line right under to overwrite the variable which tweaks the visuals of the prompt
    # Customized bash prompt
    PS1='\[\033[35m\][\A] \[\033[01;32m\]\u\[\033[01;35m\] @ \[\033[01;32m\]\h\[\033[0;36m\] \w\[\e[37m\]$(__git_ps1)\n\[\e[36m\]└─\[\e[36m\] \$\[\e[36m\] ▶\[\033[0m\] '

Option 2 : Copying my own .bashrc file

You can find my own .bashrc file in this gist. You simply have to copy it all in your own .bashrc and my prompt should now work for you.

Another way would be to download it and set it automatically via this command :

wget -O .bashrc https://gist.githubusercontent.com/V-ed/161c3dac9db058e2aab65ed6b5b2feaf/raw/13bbf798a0c4c332fb910f79c141a9b774d65a64/.bashrc

Add aliases file to quickly to mundane tasks

Setting up aliases lets you quickly do complex commands with a smaller alias or simply making common commands smaller to more quickly get around towhat you wanted to do.

The Raspbian .bashrc file loads up a file named .bash_aliases automatically on login if it exists. This file could then be used to setup the aliases for your prompt.

Steps for setting up your .bash_aliases file

Option 1 : Manually editing your .bash_aliases

  1. Open your .bashrc file : nano ~/.bash_aliases
    • This command will also create the file if it didn't exist before
  2. Add your own aliases here using the following notation :
    alias [ALIAS NAME]="[COMMAND TO EXECUTE]"
  3. ???
  4. Profit!

Option 2 : Copying my own .bash_aliases file

You can find my own .bash_aliases file in this gist. You simply have to copy it all in your own .bash_aliases and aliases should now work for you.

Another way would be to download it and set it automatically via this command :

wget -O .bash_aliases https://gist.githubusercontent.com/V-ed/161c3dac9db058e2aab65ed6b5b2feaf/raw/13bbf798a0c4c332fb910f79c141a9b774d65a64/.bash_aliases

Few things that my own .bash_aliases do

  • cl : Shorter way of typing clear, which lets you clear your terminal. You can also do this via Ctrl+L, but some application that embeds terminals might not fully clear it using the Ctrl+L shortcut.
  • update-packages : A quick and dirty way of doing a sudo apt-get update and sudo apt-get upgrade to update most if not all programs in your raspberry pi.

Making your pi use a static address

This helps as your pi will always be on the same address, which prevents your router from changing its IP address and prevents you from searching in your router's DHCP table which address your pi is at every time it changes (which can be really whenever your router wants to).

Steps for using a static IP address

  1. sudo nano /etc/dhcpcd.conf
  2. Find the lines that starts with # Example static IP configuration:, this is an example that we will use to make our IP address static
  3. Remove the # at the start of the following lines and edit the static ip_address= line to your own ip of choice
  4. It should look like this in the end :
    # Example static IP configuration:
    interface eth0
    static ip_address=192.168.0.51/24
    static ip6_address=fd51:42f8:caae:d92e::ff/64
    static routers=192.168.0.1
    static domain_name_servers=192.168.0.1 8.8.8.8 fd51:42f8:caae:d92e::1
  5. Make sure that your routers line matches the address used to connect to your router in a web browser (it might be 192.168.0.0, so in that case, use that instead!)
    • The static ip_address you used should not be in the range of allowed addresses that your router provides : check your router information for this, as otherwise, your router might give the address to another device, and you can't have two devices on your network with the same address as one will not have internet access!
      • For example, if the range allowed in your router is 192.168.0.100 to 192.168.0.200, it would be safe to use 192.168.0.75. Just change the last digits (192.168.0.XXX) to a number you want between 0 and 255 that is not in the range of your router.
  6. Reboot your device using sudo reboot. If it was successfull, trying to ssh into your device should now work using the number you used for the static ip_address line : in my case, I can access it using ssh ved@192.168.0.51.

Refs for setting up a static IP address

Create a free DNS and keeping it up to date your your public IP address

This will allow you to easily connect to your raspberry pi anywhere in the world by using your public IP address without having to remember the actual IP address that might even change based on your Internet Service Provider.

I am using DynuDNS to host my free DNS name. This DNS provider is amazing since you don't need to confirm that you are using it every month, for example (looking at you, No-IP...).

Once you have created an account at DynuDNS, and als created a DNS of your choice, make sure that your IP Update Password is set in your DynuDNS account. To do so, go to this page (it should go to your own accountif you were logged in your account when going to this link) and enter a password in the New IP Update Password field. Enter the same password in the Confirm New IP Update Password field, enter nothing in the remaining fields, and click on Save. Remember this password, as you will need it later on.

Once this is done, we need to let DynuDNS know what is the public IP address that will be available for this DNS. To do so, follow these steps :

  1. mkdir ~/dynudns
  2. nano ~/dynudns/dynu.sh
  3. In this file, write this :
    curl "https://api.dynu.com/nic/update?username=[USERNAME]&password=[IP_UPDATE_PASSWORD]"
    
    echo
    • Replace the [USERNAME] and the [IP_UPDATE_PASSWORD] with your own values.
  4. chmod 700 ~/dynudns/dynu.sh
  5. crontab -e
    • In this crontab, add the line 0 * * * * /home/[YOUR_USER]/dynudns/dynu.sh >/dev/null 2>&1 at the very bottom
      • Make sure to replace [YOUR_USER] with your user!
      • This will run the script every hour automatically to update the public IP address if required.
  6. To update DynuDNS and test the script at the same time, you can run the script manually whenever you want : cd ~ && ./dynudns/dynu.sh.
    • I forgot what it says on a successfull update, but if it hasn't changed, you will see nochg, which is good news.

You can now use your new DNS to SSH into your pi from wherever your are in the world!

Make sure your port for SSH are open in your router and pointing to your raspberry pi though, as your router will prevent access otherwise. This step is so different for every router that you will need to look up how to do so in your own router. A general tip however is that the port 22 is the default one for SSH, so this is the port to open to access your raspberry pi over SSH anywhere in the world.

Opening a port on your router is a security risk however. Please read the answers on this page to know more about the risks associated with opening ports on your router.

Refs for setting up your DNS

Installing Pi-hole

Pi-hole is a tool that lets you block alot of ads for every single device in your network before they are even downloaded, making your network generally faster and providing you with the ability to view a log of your network usage via their web server.

The installation is pretty simple, but I recommend you following setting up a static IP address beforehand, since a step during installation uses it.

The command is simple : curl -sSL https://install.pi-hole.net | bash, then follow the instructions on screen.

Here are some details that may be useful during installation :

  1. When asking for which Interface to use, assuming you are using an Ethernet port for your internet access on your Raspberry Pi, select eth0
  2. For the Upstream DNS Provider, I recommend using CloudFlare. Their DNS is pretty solid
  3. You can keep most Third party lists enabled. This helps removing most ads found on the internet by default
  4. Keep both Protocols selected
  5. Assuming you followed the steps to make your IP static, simply answer Yes when asked if you want to use your current network settings as static address
  6. Do install the web admin interface, it is very useful to monitor your Pi-hole (and even your pi) status
  7. Yes, also install the lighttpd web server
  8. For the question about logging traffic, I personnaly answer yes since it is nice to see which request have been sent to what address from which device. You can tailor your own customization for this step (the next question, if answered Yes, will be at which level the logging needs to be done)
  9. After the installer finishes, a password is shown for you to login to your Pi-hole web admin page. You can change it by using the command pihole -a -p and entering your new password as asked.

Note : If you use the Cancel option on any page (even those that are technically "sub-menus"), the whole installation will cancel. Simply run curl -sSL https://install.pi-hole.net | bash again and follow the same steps to try again.

You should now be able to enter the address of your pi (mine is 192.168.0.51, for example), followed by /admin in your web browser (example of full address : 192.168.0.51/admin) and you will be able to use your Pi-hole web admin interface!

Learn more about Pi-hole here :

Installing OpenVPN to access your network remotely

Installing OpenVPN will allow you to use your own network wherever you are in the world. This also means that networks that blocks certain domains will not be able to block them, as you will be using your own network (example : gaming at school). This of course means that your network speed will be capped at the lowest maximum speed between your current Wifi / Cellular network speed and your home speed.

Installing OpenVPN using PiVPN

The installation of OpenVPN and its user management is fairly simple thanks to pivpn, which automates the installation and the usage of the OpenVPN server that will run on your raspberry pi.

Simply use the command curl -L https://install.pivpn.dev | bash which will run the installer using on-screen prompts. Here are some details about this installation :

  1. When asked about using the DHCP Reservation on your Router, assuming you followed the steps to make your IP static, you can simply enter No, then Yes for using your current network settings.
  2. Select your user that will manage your OpenVPN resources
    • This will probably show only one user, which is fine, just enter yes
  3. PiVPN will now ask you whether you want to install Wireguard or OpenVPN. In my experience, OpenVPN is better as there is more documentation available, the clients are more diversified and more beautiful (IMO) and it just works. This however might change, as Wireguard seems to still be in development and might actually be better than OpenVPN in term of performances, but was more of an hassle in my own testing than something better.
    • I will check from time to time if Wireguard gets better support than OpenVPN, but until then, I will assume that OpenVPN is better for my needs.
  4. When asked about the Protocol, select UDP
  5. You can keep the default OpenVPN port. Keep this number (default is 1194) somewhere, as it will need to be opened up later in your router
  6. The installer should detect your Pi-hole installation if you followed the steps to install Pi-hole beforehand. If so, answer Yes to allow PiVPN to use Pi-hole as your DNS to get adblocking wherever you are in the world.
  7. When asked about a custom search domain, simply answer No
  8. The question about Will clients use a Public IP or DNS name, that is up to you : I already setup a DNS for pi network, so I used the option DNS entry, but you could use your public IP address instead. Keep in mind that it might change when your Internet Service Provider decides to if you select that option! Using a DNS for your network will allow you to not think about updating your IP tables for this (I never did that, so I can't help much on this).
  9. When asked about the Installation mode (in other words, you should see somewhere If your clients do run OpenVPN 2.4 or later), simply answer Yes
  10. You can keep the default desired size of your certificates. A bigger number might introduce bigger latency when using your VPN, but will be more secure. It's up to you to make that decision!
  11. When asked about enabling unattended upgrades, I strongly recommend answering Yes.
  12. The installation should now be finished. A prompt is shown that tells you that it is recommended to reboot : I also strongly recommend rebooting your raspberry pi after this point : Answer Yes to the question or, when in the terminal prompt, type sudo reboot.

If no problem occured, you should now have OpenVPN installed and running on your Raspberry Pi! You will now need to create profiles for the devices you want to allow to join your VPN. These profiles will automate the connection details, which will make connecting to your VNP a breeze.

Creating the user profiles for OpenVPN

To add a new user that will have access to your OpenVPN server, simply use the command pivpn -a. You will need to use this command for each new device that will connect to your server, as a single profile cannot be used on two devices at the same time. When run, thiscommand will then ask you for few details for this profile. Here are some details that might be useful :

  1. The name of the client should have some sort of easily recognizable property to it. For example, if I wanted to create a profile for my phone, I could name the "Client" vedPhone.
  2. The numbers of days that the certificate lasts is up to you. The default 1080 days is about 3 years after all, which isn't bad, but I prefer to bump it to 2080. 6 years is better IMO, I won't have to think about it too much.
  3. The password is the one that will be entered on the device that will use the profile. Either let the person which will use this profile create its own password, or remember it well.

After few moemnts, a profile will be created, usually in the directory ~/ovpns. You can safely move this file around, and it is recommended to not copy this file, as only one device can use it anyway. Transfer this file to the device you wish to use it on and voilà!

Opening up the OpenVPN port on your router to allow external access to your VPN

As discussed in the section about setting up a DNS, accessing your OpenVPN server from outside your network will require you to open up your OpenVPN server port to the open world.

The port to open is by default 1194, but if you changed it at the step 5 of "Installing OpenVPN using PiVPN", you will need to open up that port instead. This is up to you to figure it out, and to search online your router model to see if a guide is there to open your ports.

This step is so different for every router that you will need to look up how to do so in your own router.

Opening a port on your router is a security risk however. Please read the answers on this page to know more about the risks associated with opening ports on your router.

Connecting to the OpenVPN server on the client devices

As for the software used to connect to your server, you can use anything that connects to an OpenVPN server using a profile : I recommend the official application of OpenVPN :

Here are some links for untested clients on other devices types :

Simply transfer the [client name].ovpn file created previously to the device you want and follow your device's app settings to import the profile from a file / URL. For further informations about this, search online for your own device, as there is too many to cover them all in this Gist.

Fun things about this OpenVPN access

You might be wondering "well, what can I do with this VPN?". Here's a little list of things you can do when connected to your own VPN :

  • Access sites / online games that your current network is blocking (example : school blocking online games)
  • Access your Pi-hole admin page to monitor it anywhere in the world
  • Access your other device at your own when using Smart devices
  • Secure your public Wi-Fi usage by using your home network instead
  • Stop using free VPN as there is no guarantee that your data isn't being used against you in these free VPN (when using your own server, you know that YOU have your own data)
  • Any other suggestions? :)

Refs for OpenVPN settings

Setting up a Samba share to use an external drive as a sharable drive in a local network

Samba is a protocol that allows an easy access for Windows machines to a Linux file system with the appropriate permissions control. Such protocol can laos be used on different devices, such as Android devices, that implements this protocol.

It is useful to have access to a Smaba share since it is generally faster than an SFTP transfer (less overhead) and can be integrated directly as a Network Drive in Windows, making the access to the drive attached to the raspberry pi feels native in a Windoows machine.

To install Samba, you can follow these steps :

  1. sudo apt-get install samba samba-common-bin
  2. When asked about If your computer gets IP address from a DHCP server on the network, assuming you followed the steps to make your IP static, simply say No to the question during installation
  3. sudo nano /etc/samba/smb.conf
  4. Edit the file by going to the very bottom and adding these lines :
    [RaspberryPiNAS]
    path = /mnt/nas/share
    writeable = Yes
    create mask = 0777
    directory mask = 0777
    public = no
    
  5. sudo smbpasswd -a [USERNAME]
    • You can set any username here, this will be the username required for connecting to the samba machine. I personally used the same as my linux username.
    • Set the password for the user.
  6. sudo systemctl restart smbd

Voilà! A share should now be available to connect to using a Windows machine or any other device that comply to the SAMBA protocol.

You can use the command hostname -I to know what is the address that you will need to use to connect to this share.

More explanations can be found on this site.

Refs for creating a Samba Share

alias update-packages="sudo apt-get update && sudo apt-get upgrade"
alias cl="clear"
# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
# don't put duplicate lines or lines starting with space in the history.
# See bash(1) for more options
HISTCONTROL=ignoreboth
# append to the history file, don't overwrite it
shopt -s histappend
# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
HISTSIZE=1000
HISTFILESIZE=2000
# check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS.
shopt -s checkwinsize
# If set, the pattern "**" used in a pathname expansion context will
# match all files and zero or more directories and subdirectories.
#shopt -s globstar
# make less more friendly for non-text input files, see lesspipe(1)
#[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"
# set variable identifying the chroot you work in (used in the prompt below)
if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
debian_chroot=$(cat /etc/debian_chroot)
fi
# set a fancy prompt (non-color, unless we know we "want" color)
case "$TERM" in
xterm-color|*-256color) color_prompt=yes;;
esac
# uncomment for a colored prompt, if the terminal has the capability; turned
# off by default to not distract the user: the focus in a terminal window
# should be on the output of commands, not on the prompt
force_color_prompt=yes
if [ -n "$force_color_prompt" ]; then
if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
# We have color support; assume it's compliant with Ecma-48
# (ISO/IEC-6429). (Lack of such support is extremely rare, and such
# a case would tend to support setf rather than setaf.)
color_prompt=yes
else
color_prompt=
fi
fi
if [ "$color_prompt" = yes ]; then
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w \$\[\033[00m\] '
# Customized bash prompt
PS1='\[\033[35m\][\A] \[\033[01;32m\]\u\[\033[01;35m\] @ \[\033[01;32m\]\h\[\033[0;36m\] \w\[\e[37m\]$(__git_ps1)\n\[\e[36m\]└─\[\e[36m\] \$\[\e[36m\] ▶\[\033[0m\] '
else
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
fi
unset color_prompt force_color_prompt
# If this is an xterm set the title to user@host:dir
case "$TERM" in
xterm*|rxvt*)
PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
;;
*)
;;
esac
# enable color support of ls and also add handy aliases
if [ -x /usr/bin/dircolors ]; then
test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
alias ls='ls --color=auto'
#alias dir='dir --color=auto'
#alias vdir='vdir --color=auto'
alias grep='grep --color=auto'
alias fgrep='fgrep --color=auto'
alias egrep='egrep --color=auto'
fi
# colored GCC warnings and errors
#export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'
# some more ls aliases
#alias ll='ls -l'
#alias la='ls -A'
#alias l='ls -CF'
# Alias definitions.
# You may want to put all your additions into a separate file like
# ~/.bash_aliases, instead of adding them here directly.
# See /usr/share/doc/bash-doc/examples in the bash-doc package.
if [ -f ~/.bash_aliases ]; then
. ~/.bash_aliases
fi
# enable programmable completion features (you don't need to enable
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
# sources /etc/bash.bashrc).
if ! shopt -oq posix; then
if [ -f /usr/share/bash-completion/bash_completion ]; then
. /usr/share/bash-completion/bash_completion
elif [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
fi
# Startup scripts, when all of bash's stuff is loaded, before the
# user prompt is shown.
if [ -f ~/.bash_startup ]; then
. ~/.bash_startup
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment