INTRODUCTION
A Raspberry Pi micro computer is an amazing tool. We use it for example as a cheap alternative to expensive BrightSign Players to loop videos, both in full HD and in 4K, as a key component in kinetic art installations and as a networking tool to enhance our privacy - just to name a few use cases.
Raspberry Pi Os is a Linux distribution specifically develloped for the Raspberry Pi and yes, it is FOSS (Free and Open Source Software)!
There are several different ways to setup a Raspberry Pi. The outline below is just one of several possible examples. However, this specific example is focused on security (and some minor performance tweaks) and will be the basic setup we use for all of our tutorials based on a Raspberry Pi. For this tutorial we will use an Apple computer running MacOS. You neither need an external monitor, nor an additional mouse and keyboard for your Raspberry Pi, because we will do a so-called headless setup.
INSTALLATION
- 0 - REQUIRED HARDWARE
- 1 - DOWNLOAD RASPBERRY PI IMAGER
- 2 - FLASH RASPBERRY PI OS
- 3 - Boot up your Raspberry Pi and find it on your local network
- 4 - Connect to your Raspberry Pi via SSH
SECURITY
- 0 - UPDATE!
- 1 - Create Separate Admin & Login User Accounts
- 2 - Harden SSH Security
- 3 - setup a FIREWALL
- 4 - fail2ban
- 5 - Disable IPv6 (optional)
TWEAKS
INSTALLATION
headless setup
0 - REQUIRED HARDWARE
- Your Apple computer (MacOS), either with built-in SD-Card reader or external SD-Card adapter
- Local Wifi-Connection (your home router)
- Raspberry Pi board
- Micro-SD Card
- A good Power Supply for your Raspberry Pi
- Ethernet cable (optional)
1 - DOWNLOAD RASPBERRY PI IMAGER
Download the official Raspberry Pi Imager.app. Instead of using the app, you can also install a Linux System manually. However, the official app is the easiest and most user-friendly way to install an operating system on your SD-Card.
2 - FLASH RASPBERRY PI OS
To flash Raspberry Pi OS onto your SD-Card, select the following options based on your device and preference for an Operating System and click [Next]:
- Choose Device: Select your Raspberry Pi board
- Choose OS: Choose your Operating System
- Choose Storage: Select your Micro SD Card
This action will erase all content that is stored on your SD-Card!
The purpose of a headless setup is to skip the Welcome Wizard and be able to access the Raspberry Pi directly from a remote computer after the first boot. To do this, the username, password and network configuration must be completed through the OS customization settings.
If you want to follow our tutorials, you should apply those customisation settings. You will also need a strong password. Open your Terminal.app (found with Spotlight: press ⌘ and [SPACE], then type Terminal, or find it in your Applications -> Utilities Folder) and type the following command:
# Generate random passwordopenssl rand -base64 48 | cut -c1-32
Safe this password in a secure environment, i.e. in a KeePassXC database. If you use KeePassXC, you can also generate a strong password there.
Click on [Edit Settings] and enter the following parameters in GENERAL:
- Set hostname: term7
- Set username and password
- Username: term7
- Password: copy & paste the password you generated earlier
- Configure wireless LAN
- SSID: Your-Wifi-SSID
- Password: Your-Wifi-Password
- Wireless LAN country: Your coutry, i.e. CZ if you are in the Czech Republic or FR if you are in France
- Set locale settings
- Time zone: select your own time zone
- Keyboard layout: select your keyboard layout
In SERVICES, make sure you select Enable SSH and Use password authentication. SSH is the remote access protocol that will allow you to access the Raspberry Pi via your Mac's Terminal.app over your Wifi connection. It’s not enabled by default, unless you check this box, and have a username and password set.
Finally you will see a warning that all data on your SD-Card will be erased. Click [YES] to proceed.
3 - Boot up your Raspberry Pi and find it on your local network
Insert your SD Card into your Raspberry Pi and connect it to a power supply. Its status LED's will blink for a while before it will connect to your local network because the Raspberry Pi is performing its first time setup. Depending on your Raspberry Pi model it may take up to 5 minutes to complete!
Furthermore, if your local Wifi uses the latest WPA3 encryption, your Raspberry Pi may not be able to connect automatically during headless setup! If you experience this problem (we did, when we tried a Raspberry Pi 3B+ with Raspberry Pi OS -Legacy, 32-bit), either change WPA3 to WPA2 in your router settings, or connect your Raspberry Pi directly to your router with an ethernet cable.
The best way to find your Raspberry Pi on the local network is nmap. Nmap is a network scanner that can be used to list all the devices connected to a specific network. If you installed MacPorts on your computer you can easily install nmap with this command:
# Install nmap:sudo port install nmap
We wrote a blog post about MacPorts a while ago:
Once you installed nmap, type this command in your Terminal.app to list all devices that are connected to you local network:
# List all connected devices:sudo nmap -sP 192.168.1.0/24
You will see a list with nmap scan reports. Find the scan report that shows you a Mac Address followed by "(Raspberr Pi Foundation)". This is your Raspberry Pi on the local network. In the next step you will need its IP-address, which in our example is 192.168.1.123:
Alternatively, instead of using nmap, you can also connect to your router and look up the local IP address of your Raspberry Pi there...
4 - Connect to your Raspberry Pi via SSH
To connect to your Raspberry Pi via SSH, type the following command:
# Replace the IP Address with your own local IP Address:ssh term7@192.168.1.123
Your computer will warn you: The authenticity of host '192.168.1.123 (192.168.1.123)' can't be established. This is ok! Type Yes and press [ENTER]. Next enter the Raspberry Pi user password you set up earlier to log in.
Congratulations! You should now be connected to your Raspberry Pi!
SECURITY
initial configuration
0 - UPDATE!
Before we update, we want to configure the locale settings to avoid constant error messages when we update (in this example in English):
export LANGUAGE="en_GB.UTF-8" && export LANG="en_GB.UTF-8" && export LC_ALL="en_GB.UTF-8"
Next enter this command:
sudo dpkg-reconfigure locales
This will open the locales configuration software. Select twice OK and press [ENTER]:
Finally, edit the locales configuration file (in this example we use nano, a command line text editor):
sudo nano /etc/default/locale
Add the following lines:
LC_ALL=en_GB.UTF-8
LANGUAGE=en_GB.UTF-8
Your file should now look like this:
Once you finished to edit the file, press [control] + X. Press Y to confirm the changes, press [ENTER] to close nano.
Now you are ready to update Raspberry Pi OS:
sudo apt update && sudo apt upgrade
Confirm with Y + [ENTER] to start the update.
Once finished, remove all packages that are no longer necessary:
sudo apt autoremove
Again, confirm with Y + [ENTER].
1 - Create Separate Admin and Login User Accounts
Often our projects need to be connected to the internet. For security reasons, we do not want the admin user (who can install software via the sudo command) to be able to log into our Raspberry Pi remotely. This is why we create a privileged admin user to install software and a low privileged user account to log into our Raspberry Pi.
Create an admin account:
sudo adduser admin
Again generate and enter a strong new password (and store it in a safe location). The additional info can be left empty. Just press [ENTER] several times until the admin user account is created.
Add the admin user to all necessary groups:
sudo usermod -a -G adm,tty,dialout,cdrom,audio,video,plugdev,games,users,input,netdev,gpio,i2c,spi,sudo,term7 admin
Edit the sudoers configuration file with nano:
sudo nano /etc/sudoers.d/010_pi-nopasswd
Change the name of your sudoer to admin. Once you finished to edit the file, press [control] + X. Press Y to confirm the changes, press [ENTER] to close nano:
Next, we want to remove our standard user, in this example term7, from the group that grants admin privileges. In order to do that you first have to access your new admin user account:
su admin
Enter your strong password and press [ENTER].
Next execute this remove term7 from the sudo group (use your standard user name that you used to set up your Raspberry Pi):
sudo deluser term7 sudo
Yet we still want our standard user to execute basic shutdown and reboot commands. For this reason we need to create a new sudoers policy file for common_users to include shutdown and reboot commands as new privileges:
sudo nano /etc/sudoers.d/common_users
Copy & paste the following content:
# Shutdown and Reboot Policy:term7 ALL = NOPASSWD: /usr/sbin/reboot, /usr/sbin/shutdown
Again, once you finished to edit the file, press [control] + X. Press Y to confirm the changes, press [ENTER] to close nano.
Sometimes, with a new distribution of Raspberry Pi OS, the location of the shutdown & reboot commands may change. Use this command to find out the correct full path:
which shutdown
which reboot
Changes will take effect once you reboot your Raspberry Pi:
sudo reboot now
If you ssh into your Raspberry Pi (do not use your admin account, but your standard user account) and you try to run a command with sudo, you will notice that it does not work.
2 - Harden SSH Security
At the moment you can still use SSH to access your admin account directly. For security reasons, we do not want this! This is why we now change the ssh configuration file to disallow root login. We will also change a few more settings to improve ssh security in general:
- Disable Root Login
- Change the Default SSH Port
- Use SSH Key Authentication
- Limit User Access
- Configure Timeout Values & Authetication Sessions
- Enforce Strong Encryption
- Setup Logging
- Configure Warning Banner (Optional)
Edit the configuration file:
sudo nano /etc/ssh/sshd_config
Find the following options to implement your changes:
DISABLE ROOT LOGIN
To reduce the attack surface you should disable root login (then your admin account cannot be used to log into your machine).
# Disable Root Login:PermitRootLogin no
CHANGE THE DEFAULT SSH PORT
The default SSH port is port 22. Malicious threat actors routinely try to see if SSH port 22 is open (nmap is the tool that most often is used). If yes, automatic brute force attacks are started to break into the machine, which is why you should change the port number of your SSH connection.
# Change the port number:Port 6666
# Choose a number between 1024 and 65535
IMPORTANT: AS SOON AS YOU CHANGE THE DEFAULT SSH PORT, YOU NEED TO SPECIFY THE PORT YOU WANT TO USE WHEN YOU CONNECT TO YOUR RASPBERRY PI!
# Replace the IP Address with your own local IP Address
# Add your custom SSH Port:
ssh term7@192.168.1.123 -p 6666
USE SSH KEY AUTHENTICATION
SSH key authentication is more secure than password authentication. A set of SSH keys consists of a private key and a public key. They both work in combination with each other. The private key stays on your Mac, the public key will be copied to your Raspberry Pi. Afterwards only your Mac can log into the Raspberry Pi (unless your private key gets stolen).
First, on your Mac, open a new Terminal window to generate a new set of SSH keys:
# Generate SSH keys:ssh-keygen -t ed25519 -C "your_email@example.com"
You can protect your key with a passphrase if you whish.
Next, copy the public key to your Raspberry Pi:
# Copy public key to your Raspberry Pi:ssh-copy-id -i ~/.ssh/id_ed25519.pub term7@192.168.1.123
# Our example IP address still is 192.168.1.123 - replace it with your Raspberry Pi's actual local IP address!
Finally, enable your SSH key in your Mac's SSH configuration file:
# Edit ~/.ssh/config:nano ~/.ssh/config
Make sure this line is present:
# IdentityFileIdentityFile ~/.ssh/id_ed25519
You can now close this Terminal window. Back in your initial Terminal window (where you should still be logged into your Raspberry Pi), change these settings:
# In /etc/ssh/sshd_config, disable Password Authentication:PasswordAuthentication no
# In /etc/ssh/sshd_config, enable PubKey Authentication:PubkeyAuthentication yes
# In /etc/ssh/sshd_config, define AuthorizedKeysFile:AuthorizedKeysFile .ssh/authorized_keys
An even stronger setup would be the use of a hardware key like a Nitrokey or a Yubikey. However these keys need to be purchased first and set up correctly, which would blow the size of this tutorial. We might write an additional tutorial about hardware keys later...
LIMIT USER ACCESS
Only allow your standard user (without administrator privileges) to log in via SSH:
# Limit User Access:AllowUsers term7
CONFIGURE TIMEOUT VALUES & AUTHENTICATION SESSIONS
Implement connection timeouts to prevent idle sessions:
# Timeout Value 1:ClientAliveInterval 300
# Timeout Value 2:ClientAliveCountMax 2
Limit active sessions allowed login attempts to reduce attack surface:
# MaxAuthTries:MaxAuthTries 2
# MaxSessions:MaxSessions 2
ENFORCE STRONG ENCRYPTION
Enforce strong encryption algorithms by adding these three lines:
# Encryption Algorithms:Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group16-sha512
MACs hmac-sha2-512-etm@openssh.com
SETUP LOGGING
You can create access logs for SSH in order to be able to monitor SSH access:
# Setup Logging:LogLevel VERBOSE
Use this command to view login attempts:
sudo journalctl -u ssh
CONFIGURE WARNING BANNER (OPTIONAL)
A warning banner lets unauthorized users know that they are not allowed to connect:
# Default Banner Path:Banner /etc/issue.net
To save your configuration file, press [control] + X. Press Y to confirm the changes. Then press [ENTER] to close nano.
Now edit your warning banner:
sudo nano /etc/issue.net
Here is our example for a warning banner (feel free to Copy & Paste):
/ Unauthorized access to this machine is prohibited /
################################################################################
# #
# Welcome... #
# ...all connections to this machine are monitored and recorded... #
# #
# Disconnect IMMEDIATELY unless you are AUTHORIZED! #
# #
# #
################################################################################
/ Unless authorized you will be disconnected shortly /
To save, press [control] + X again. Then press Y to confirm the changes and [ENTER] to close nano.
Finally, reboot your Raspberry Pi or enter the following command to restart ssh in its hardened configuration:
# Restart SSH:sudo systemctl restart sshd
If you are unsure, you can Copy & Paste our full sample configuration file here. Make sure that you adjust the necessary details to match your configuration (i.e. AllowUsers term7 -> your username!), otherwise you will be locked out of your Raspberry Pi!
sudo nano /etc/ssh/sshd_config
# $OpenBSD: sshd_config,v 1.103 2018/04/09 20:41:22 tj Exp $
# This is the sshd server system-wide configuration file. See
# sshd_config(5) for more information.
# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin
# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented. Uncommented options override the
# default value.
Include /etc/ssh/sshd_config.d/*.conf
Port 6666
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::
#HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_ecdsa_key
#HostKey /etc/ssh/ssh_host_ed25519_key
# Ciphers and keying
#RekeyLimit default none
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group16-sha512
MACs hmac-sha2-512-etm@openssh.com
# Logging
#SyslogFacility AUTH
LogLevel VERBOSE
# Authentication:
#LoginGraceTime 2m
PermitRootLogin no
AllowUsers term7
#StrictModes yes
MaxAuthTries 2
MaxSessions 2
PubkeyAuthentication yes
# Expect .ssh/authorized_keys2 to be disregarded by default in future.
AuthorizedKeysFile .ssh/authorized_keys
#AuthorizedPrincipalsFile none
#AuthorizedKeysCommand none
#AuthorizedKeysCommandUser nobody
# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# HostbasedAuthentication
#IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
#IgnoreRhosts yes
# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication no
#PermitEmptyPasswords no
# Change to yes to enable challenge-response passwords (beware issues with
# some PAM modules and threads)
ChallengeResponseAuthentication no
# Kerberos options
#KerberosAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosGetAFSToken no
# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes
#GSSAPIStrictAcceptorCheck yes
#GSSAPIKeyExchange no
# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the ChallengeResponseAuthentication and
# PasswordAuthentication. Depending on your PAM configuration,
# PAM authentication via ChallengeResponseAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
UsePAM yes
#AllowAgentForwarding yes
#AllowTcpForwarding yes
#GatewayPorts no
X11Forwarding yes
#X11DisplayOffset 10
#X11UseLocalhost yes
#PermitTTY yes
PrintMotd no
#PrintLastLog yes
#TCPKeepAlive yes
#PermitUserEnvironment no
#Compression delayed
ClientAliveInterval 300
ClientAliveCountMax 2
#UseDNS no
#PidFile /var/run/sshd.pid
#MaxStartups 10:30:100
#PermitTunnel no
#ChrootDirectory none
#VersionAddendum none
# no default banner path
Banner /etc/issue.net
# Allow client to pass locale environment variables
AcceptEnv LANG LC_*
# override default of no subsystems
Subsystem sftp /usr/lib/openssh/sftp-server
# Example of overriding settings on a per-user basis
#Match User anoncvs
# X11Forwarding no
# AllowTcpForwarding no
# PermitTTY no
# ForceCommand cvs server
3 - setup a Firewall
We use iptables as a firewall to lock down ports on our Raspberry Pi. First we need to install the required software that allows our iptable rules to persist across reboots:
# Install iptables:sudo apt install netfilter-persistent iptables-persistent
To make things a little bit easier we prepared a couple of firewall scripts. Prepare script location:
mkdir script && cd script
mkdir iptables && cd iptables
Create Firewall script for IPv4:
sudo nano iptables.sh
Copy & Paste the following content:
#/bin/sh
# Allow SSH on port 6666:
iptables -A INPUT -p tcp --dport 6666 -m state --state NEW -j ACCEPT
# Allow HTTP and HTTPS connections from anywhere
# (the normal ports for web servers: uncomment if you need to use them).
#iptables -A INPUT -p tcp --dport 80 -m state --state NEW -j ACCEPT
#iptables -A INPUT -p tcp --dport 443 -m state --state NEW -j ACCEPT
# Allow inbound traffic from established connections.
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Allow loopback traffic:
iptables -I INPUT -i lo -j ACCEPT
# Reject all access from anywhere else:
iptables -P INPUT DROP
# Save iptables
netfilter-persistent save
To save, press [control] + X. Then press Y to confirm the changes and [ENTER] to close nano.
Next, we create the same script for IPv6:
sudo nano ip6tables.sh
Copy & Paste the following content:
#bin/sh
# Allow SSH on port 6666:
ip6tables -A INPUT -p tcp --dport 6666 -m state --state NEW -j ACCEPT
# Allow HTTP and HTTPS connections from anywhere
# (the normal ports for web servers: uncomment if you need to use them).
#ip6tables -A INPUT -p tcp --dport 80 -m state --state NEW -j ACCEPT
#ip6tables -A INPUT -p tcp --dport 443 -m state --state NEW -j ACCEPT
# Allow inbound traffic from established connections.
ip6tables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Allow loopback traffic:
ip6tables -I INPUT -i lo -j ACCEPT
# Reject all access from anywhere else:
ip6tables -P INPUT DROP
# Save iptables
netfilter-persistent save
Again press [control] + X to save the script. Then press Y to confirm the changes and [ENTER] to close nano.
If we ever encounter problems, we want to be able to flush all iptables. This is why we prepared two additional scripts.
For IPv4:
sudo nano flush-iptables.sh
Copy & Paste the following content:
#bin/sh
# Accept all traffic first to avoid ssh lockdown via iptables firewall rules #
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
# Flush All Iptables Chains/Firewall rules #
iptables -F
# Delete all Iptables Chains #
iptables -X
# Flush all counters too #
iptables -Z
# Uncomment to flush and delete all nat and mangle #
#iptables -t nat -F
#iptables -t nat -X
#iptables -t mangle -F
#iptables -t mangle -X
#iptables iptables -t raw -F
#iptables -t raw -X
# Save iptables
netfilter-persistent save
Again press [control] + X to save the script. Then press Y to confirm the changes and [ENTER] to close nano.
For IPv6:
sudo nano flush-ip6tables.sh
Copy & Paste the following content:
#bin/sh
# Accept all traffic first to avoid ssh lockdown via iptables firewall rules #
ip6tables -P INPUT ACCEPT
ip6tables -P FORWARD ACCEPT
ip6tables -P OUTPUT ACCEPT
# Flush All Iptables Chains/Firewall rules #
ip6tables -F
# Delete all Iptables Chains #
ip6tables -X
# Flush all counters too #
ip6tables -Z
# Uncomment to flush and delete all nat and mangle #
#ip6tables -t nat -F
#ip6tables -t nat -X
#ip6tables -t mangle -F
#ip6tables -t mangle -X
#ip6tables iptables -t raw -F
#ip6tables -t raw -X
# Save ip6tables
netfilter-persistent save
Again press [control] + X to save the script. Then press Y to confirm the changes and [ENTER] to close nano.
Next, we need to make all four scripts executable:
sudo chmod +x iptables.sh
sudo chmod +x ip6tables.sh
sudo chmod +x flush-iptables.sh
sudo chmod +x flush-ip6tables.sh
Finally, start your firewall with these two commands:
sudo ./iptables.sh
sudo ./ip6tables.sh
To view all current iptable IPv4 rules, enter this command:
# View IPv4 Firewall:sudo iptables -L -v -n
To view all current iptable IPv6 rules, enter this command:
# View IPv6 Firewall:sudo ip6tables -L -v -n
Disable IPv6 (optional)
IPv6 is inherently less secure than IPv4. We recommend you disable IPv6 on your Raspberry Pi:
# Disable IPv6:sudo nano /etc/sysctl.conf
At the end of the file, insert:
# Insert:#Disable IPv6:
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
Press [control] + X to save your configuration. Then press Y to confirm the changes and [ENTER] to close nano.
The changes will take effect after the next reboot. If you want the changes to take effect immideately, execute the following command:
sudo sysctl -p
4 - fail2ban
Before you can use fail2ban, make sure your Raspberry Pi has logging enabled (otherwise fail2ban will not work). If your version of Raspberry Pi OS does not have logging set up, install rsyslog with this command:
# Install rsyslog:sudo apt install rsyslog
fail2ban adds an extra layer of protection. It examines log files and checks for suspicious activity, like multiple brute-force login attempts and automatically blocks IP addresses that show malicious signs. Install fail2ban with this command:
# Install fail2ban:sudo apt install fail2ban
Edit the fail2ban configuration file:
# Fail2ban SSH Configuration:sudo nano /etc/fail2ban/jail.d/defaults-debian.conf
Edit the file to look like this:
[sshd]
enabled = true
port = 6666
filter = sshd
logpath = /var/log/auth.log
maxretry = 2
findtime = 300
bantime = 1w
Press [control] + X to save your configuration. Then press Y to confirm the changes and [ENTER] to close nano.
TWEAKS
performance tweaks and simple tools
0 - Z-RAM
ZRAM creates RAM based block storage named /dev/zram0 (or 1, 2, 3, etc). Pages written there are compressed and stored in memory. This allows for very fast I/O and the compression savings provide additional memory.
We set up Z-RAM for all our Raspberry Pi's because it improves its all-over performance significantly!
To view your current memory, type this command:
free -m
We use this zram-swap script to install and auto-configure:
mkdir build && cd build
# Clone Script:git clone https://github.com/foundObjects/zram-swap
If this command fails, install git and try again:
# Install git:sudo apt install git
Then install ZRAM:
# Install Script:cd zram-swap && sudo ./install.sh
If you need to, you can edit the configuration file here:
# Edit Configuration:sudo nano /etc/default/zram-swap
Furthermore, to delay running our of memory, we increase the kernel's cache pressure and we want to increase the tendency of our Raspberry Pi to swap. Swap will now be stored via much faster Z-RAM.
Again, edit your /etc/sysctl.conf file:
# Edit /etc/sysctl.conf:sudo nano /etc/sysctl.conf
Insert at the end:
# Insert:#Z-RAM tweaks:
vm.vfs_cache_pressure=500
vm.swappiness=100
vm.dirty_background_ratio=1
vm.dirty_ratio=50
Either reboot, or execute the following command if you want to enable your changes immideately:
sudo sysctl -p
If you now check your Raspberry Pi's memory again, you should see that Z-RAM is enabled:
free -m
Special thanks to Hayden James for his very informative blog post:
1 - MOTD (MESSAGE OF THE DAY)
Whenever you log into your Raspberry Pi via SSH it schows you a copyright notice, the default message of the day (motd):
This space can be used to display useful information about your system, i.e. system load, memory information, swap usage, system uptime, etc.
This is how you set up our example configuration:
Install required software packages:
# Install dnsutils and figlet:sudo apt install dnsutils figlet
To set up dynamic motd (our example configuration - feel free to adjust!), run the following commands:
cd /etc/update-motd.d
# Create empty Header, Sysinfo & Footer:sudo touch 00-header && sudo touch 10-sysinfo && sudo touch 90-footer
# Make executable:sudo chmod +x /etc/update-motd.d/*
# Delete original /etc/motdsudo rm /etc/motd
# Delete /etc/update-motd.d/10-uname:sudo rm /etc/update-motd.d/10-uname
# Create Symlink:sudo ln -s /var/run/motd /etc/motd
Next, edit /etc/pam.d/ssh:
sudo nano /etc/pam.d/ssh
Insert:
# Insert:session optional pam_motd.so motd=/run/motd.dynamic
# session optional pam_motd.so noupdate
Now we create the dynamic motd header:
sudo nano /etc/update-motd.d/00-header
Insert:
#!/bin/sh
[ -r /etc/lsb-release ] ; /etc/lsb-release
if [ -z "$DISTRIB_DESCRIPTION" ] ; [ -x /usr/bin/lsb_release ]; then
# Fall back to using the very slow lsb_release utility
DISTRIB_DESCRIPTION=$(lsb_release -s -d)
fi
echo "--------------------------------------------------------------------------------"
printf "\n"
figlet $(hostname)
printf "* %s (%s).\n" "$DISTRIB_DESCRIPTION" "$(uname -rm)"
printf "\n"
echo "--------------------------------------------------------------------------------
:MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM;
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMWMMMMMMMMMMMMMMMMMMMMm0lccccccoxl::ccc:cccMMMMMMMMMMMMMMMMMMMMMMMM
MMMMX; .c: o. . ,. , ,c. dMMMM
MMMMK, , . , dMMMM
MMMMK, ,::::::::::::::cc:::::::::::::ccccccccccccccccc:. oMMMM
MMMMK, :NMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMO. lWMMM
MMMMK, lWMMN0xolccccodOXWMMMMMMMMMMMMMMWKOdlcccclokKWMMMO' oMMMM
MMMMX; lWKo,. ..,,....;oONMMMMMMMMNOo;. .... .;dXMO' oMMMM
MMMMX; ck' . ,c:lco00kl,..'lONMMNkc'..;okkl:c;:c... ,0O. oMMMM
MMMMX; ,' .'c0WWWO;:KMMWKx:..,::'..cxKWMKc;kNWWWO;.. :x' lWMMM
MMMMX; .. .''kMMMMNo,OMMMMWKc. .oXWMMM0,lNWMMWNl.,. 'o' lWMMM
MMMMX; ;; .,;d0kkl;xNMWKx:. .lddc. .cxXWWkc:dkxxc;;. lO' lWMMM
MMMMX; c0c .....,cdkdl,. .ckXMMMWXx:. .;lxdlc;',''. .lX0, lWMMM
MMMMN: cNNOl,..........;lkXWMMMMMMMMWXkl;..........;o0WMK, lWMMM
MMMMN: :NMMMWX0OOkOO0KNWMMMMMMMMMMMMMMMMWXKOOOkOO0XWMMMMK, lWMMM
MMMMN: d000000000000000000000000000000000O000000000000kc lWMMM
MMMMN: oWMMM
MMMMMMMMMMMMMW0lcc:cc:::::::cccc:::c::::cccccccccccldXMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
'MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM'
--------------------------------------------------------------------------------"
Below the header we insert a script that will display useful system information:
sudo nano /etc/update-motd.d/10-sysinfo
Insert:
#!/bin/bash
date=`date`
load=`cat /proc/loadavg | awk '{print $1}'`
memory_usage=`free -m | awk '/Mem:/ { total=$2; used=$3 } END { printf("%3.1f%%", used/total*100)}'`
processes=`ps aux | wc -l`
swap_usage=`free -m | awk '/Swap/ { printf("%3.1f%%", $3/$2*100) }'`
temperature=`/usr/bin/vcgencmd measure_temp | cut -c "6-9"`
time=`uptime | grep -ohe 'up .*' | sed 's/,/\ hours/g' | awk '{ printf $2" "$3 }'`
echo
echo "System Information: $date"
echo
printf "\e[1;36mSystem Load:\t%s\t Memory Usage:\t%s\n" $load $memory_usage
printf "Processes:\t%s\t Swap Usage:\t%s\n" $processes $swap_usage
printf "CPU Temp.:\t%s°C\t System Uptime:\t%s\n\e[0m" $temperature "$time"
echo
Finally we create the motd footer:
sudo nano /etc/update-motd.d/90-footer
Insert:
#!/bin/sh
[ -f /etc/motd.tail ] ; cat /etc/motd.tail || true
echo "--------------------------------------------------------------------------------"
2 - NETWORK CONNECTION INFO (OPTIONAL)
For some projects it is useful to display the current local IP-address, as well as the external IP-address and which network your Raspberry Pi is connected to.
First, to exit your admin account, type:
# Exit admin account:exit
Edit your .bash_profile:
# Edit .bash_profile:nano .bash_profile
Insert:
#!/bin/sh
# GWII (global web interface info)
if [ -s ~/.bashrc ]; then
source ~/.bashrc;
fi
echo
echo "$(tput setaf 6)$(tput bold)IP Addresses: wlan0 `if [ "$(cat /sys/class/net/wlan0/operstate)" = "dormant" ]; then printf Dormant; elif [ "$(cat /sys/class/net/wlan0/operstate)" = "down" ]; then printf Down; elif [ "$(cat /sys/class/net/wlan0/operstate)" = "up" ]; then printf %s "$(ip -4 addr show wlan0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}')"; fi`";
echo " ext `if [ "$(cat /sys/class/net/eth0/operstate)" = "up" ]; then printf %s "$(dig +short myip.opendns.com @resolver1.opendns.com 2>/dev/null)"; elif [ "$(cat /sys/class/net/wlan0/operstate)" = "dormant" ]; then printf Disconnected; elif [ "$(cat /sys/class/net/wlan0/operstate)" = "down" ]; then printf Disconnected; elif [ "$(cat /sys/class/net/wlan0/operstate)" = "up" ]; then printf %s "$(dig +short myip.opendns.com @resolver1.opendns.com 2>/dev/null)"; fi`";
echo
echo "WiFi ESSID: wlan0 \"$(iwgetid wlan0 --raw)\"$(tput sgr0)"
echo
printf "\e[0;32m--------------------------------------------------------------------------------\n"
echo
Wow - that was a lot!
If you managed to get here, then you know our basic setup for all of our Raspberry Pi based projects. Congratulations!