How to Set Up Raspberry Pi with Docker, Portainer & iptables
Raspberry Pi has come a long way from being just a tinkering board. The latest models pack up to 16GB of RAM, making them powerful enough to act as a lightweight Docker server capable of running multiple containers. Setting up a Raspberry Pi as part of your homelab is an excellent way to learn about servers, containers, and network security in a low-power, cost-effective environment.
With Docker and Portainer installed, you can quickly deploy and manage applications through both the command line and a clean web interface. By adding iptables firewall rules, youβll ensure your system is secure, protecting your services while still giving you full control over what to expose.
This guide will walk you through:
- Setting up Raspberry Pi OS
- Configuring cooling, networking, and security
- Installing Docker and Portainer
- Setting up firewall rules with iptables
Part 1 β Raspberry Pi OS Setup
Step 1 β Download Raspberry Pi Imager
Download the official Raspberry Pi Imager: π Raspberry Pi Software
Step 2 β Flash the OS to the SD Card
Use the Raspberry Pi Imager to flash the OS. During setup, configure:
- β Enable SSH
- β Set Wi-Fi SSID & password
- β Set hostname
- β Create username & password
Step 3 β Boot the Raspberry Pi
Insert the SD card into the Raspberry Pi and power it on.
Step 4 β Update the System
Run the following to update all packages:
1
sudo apt update && sudo apt upgrade -y
Step 5 β Configure Fan, Wi-Fi, and Bluetooth
Edit the configuration file:
1
sudo nano /boot/firmware/config.txt
Add these lines at the bottom:
1
2
3
4
5
6
7
8
9
10
11
[all]
# Fan control settings
dtparam=fan_temp0=35000
dtparam=fan_temp0_hyst=5000
dtparam=fan_temp0_speed=175
# Disable Wi-Fi
dtoverlay=disable-wifi
# Disable Bluetooth
dtoverlay=disable-bt
Save, exit, and reboot.
Step 6 β Assign a Static IP
1. List connections
1
nmcli connection show
Find the connection linked to eth0
(e.g., Wired connection 1).
2. Set static IP
Replace <conn-name>
with your connection name:
1
2
3
4
sudo nmcli connection modify "<conn-name>" ipv4.addresses 192.168.1.50/24
sudo nmcli connection modify "<conn-name>" ipv4.gateway 192.168.1.1
sudo nmcli connection modify "<conn-name>" ipv4.dns 8.8.8.8
sudo nmcli connection modify "<conn-name>" ipv4.method manual
3. Apply changes
1
2
sudo nmcli connection down "<conn-name>"
sudo nmcli connection up "<conn-name>"
β οΈ Warning: If youβre on SSH, youβll be disconnected after down
.
4. Verify IP
1
ip addr show eth0
5. Test internet
1
ping google.com
Part 2 β Install Docker
Follow the official Docker guide: π Install Docker Engine
Then complete the post-install steps: π Linux Post-Installation Guide
Part 3 β Install Portainer
What is Portainer?
Portainer is a simple web UI for managing Docker containers. It makes it much easier for beginners to deploy and monitor containers without using only the command line.
π‘ Note: Portainer Business Edition (BE) includes a free plan for up to 3 nodes.
Part 4 β Configure iptables Firewall
Use the following script to secure your system with iptables:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# Check if the script is being run as root
if [ "$EUID" -ne 0 ]; then
echo "Please run as root or with sudo"
exit 1
fi
# Function to prompt for persistent firewall installation
install_persistent() {
read -p "iptables-persistent/iptables-services not installed. Install now? (yes/no): " choice
case "$choice" in
y|Y|yes|Yes )
if [ -x "$(command -v apt-get)" ]; then
apt-get update && apt-get install -y iptables-persistent || { echo "Installation failed."; exit 1; }
elif [ -x "$(command -v yum)" ]; then
yum install -y iptables-services || { echo "Installation failed."; exit 1; }
else
echo "Unknown package manager. Install manually."
exit 1
fi
;;
* )
echo "Skipping installation. Rules wonβt persist after reboot."
;;
esac
}
# Detect system type
if [ -x "$(command -v dpkg-query)" ]; then
SYSTEM="debian"
dpkg-query -W iptables-persistent &>/dev/null || install_persistent
elif [ -x "$(command -v rpm)" ]; then
SYSTEM="redhat"
rpm -q iptables-services &>/dev/null || install_persistent
else
echo "Unsupported system."
exit 1
fi
# Reset existing rules
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -t raw -F
iptables -t raw -X
# Default policies
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# Allow loopback
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
# Allow established connections
iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# SSH protection
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 --name SSH -j DROP
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# Optional: Web traffic
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# Optional: Portainer ports
iptables -A INPUT -p tcp --dport 81 -j ACCEPT
iptables -A INPUT -p tcp --dport 9443 -j ACCEPT
# Logging
iptables -A INPUT -m limit --limit 5/min --limit-burst 10 -j LOG --log-prefix "iptables denied: " --log-level 7
# Save configuration
if [ "$SYSTEM" == "debian" ]; then
iptables-save > /etc/iptables/rules.v4
elif [ "$SYSTEM" == "redhat" ]; then
service iptables save
fi
echo "iptables rules configured and saved."
echo "Check with: sudo iptables -L -v"
β At this point your Raspberry Pi should be:
- Running the latest OS
- Secured with a firewall
- Ready with Docker & Portainer