Home Server with Raspberry Pi
Steps to install a web server, file server (NAS), and XRDP on a Raspberry Pi. This guide is easily adaptable to other SBC (Single Board Computers) boards like Orange Pi, Tinker Board, Nano Pi, etc.
1. Install Raspberry Pi OS (Raspbian)
Download the operating system image (full version):
wget -c [https://downloads.raspberrypi.org/raspbian_full_latest](https://downloads.raspberrypi.org/raspbian_full_latest)
Unzip the downloaded file:
unzip raspbian_full_latest
(The extracted file, for example 2020-02-13-raspbian-buster-full.img, will have the date of the version you downloaded).
Write the image to the MicroSD card. Make sure to replace /dev/sdX with the correct path to your card (you can find out using the KDE partition manager or a similar tool):
sudo dd if=2020-02-13-raspbian-buster-full.img of=/dev/sdX bs=512k
1.1. Enable SSH by default
For the SSH server to start automatically on the first boot, create an empty file named ssh in the boot partition of the card:
touch /path/to/boot/partition/ssh
1.2. First boot
Insert the MicroSD card into the Raspberry Pi, connect the ethernet network cable, and turn on the device.
2. Basic Configuration
2.1. First access and password change
To access remotely via SSH, run the following command from your main computer (replace X with the IP assigned by your router):
ssh pi@192.168.1.X
The default password is raspberry. For security, change it immediately:
passwd
2.2. Update the system
Update the repositories and installed software:
sudo apt update && sudo apt upgrade -y
Remove orphaned and unnecessary packages:
sudo apt autoremove -y
2.3. Change the server name (Hostname)
Start the Raspberry Pi configuration tool:
sudo raspi-config
Navigate to 2 Networking Options → N1 Hostname and set the new name for your server.
2.4. Localization and Language
Inside raspi-config, go to 4 Localisation Options. From here you must configure:
I1 Change Locale(System language)I2 Change TimezoneI3 Change Keyboard LayoutI4 Change Wi-fi Country
It will ask to reboot the system after applying these changes.
2.5. Disable the graphical environment on boot
By default, the system starts the X graphical server, which consumes unnecessary resources on a server. Disable it so that it only starts when logging in remotely with XRDP.
In raspi-config, go to 3 Boot Options → B1 Desktop / CLI and select B1 Console.
2.6. Change the default username
To change the username pi to a more secure one, we must first create a temporary user with administrator permissions:
sudo useradd -m temporary -s /bin/bash
sudo passwd temporary
sudo usermod -a -G sudo temporary
Close the current session with the user pi:
exit
Log in with the temporary user:
ssh temporary@192.168.1.X
Change the username pi (replace “other” with your desired name):
sudo usermod -l other -d /home/other -m pi
sudo groupmod -n other pi
Create a symbolic link from the old path to the new one to avoid errors with programs looking for the /home/pi folder:
sudo ln -s /home/other /home/pi
Log out and log back in with your new user:
exit
ssh other@192.168.1.X
Add your real name to the user metadata (standard characters only, without accents or ñ):
sudo chfn -f "Firstname Lastname"
Finally, delete the temporary user and their directory:
sudo userdel -r temporary
2.7. Configure a fixed private IP
It is essential to assign a static IP to the server so as not to depend on the router’s DHCP. Edit the configuration file:
sudo nano /etc/dhcpcd.conf
Add at the end of the file (adjusting to your network range). If you use Wi-Fi, change eth0 to wlan0:
interface eth0
static ip_address=192.168.1.XXX/24
static routers=192.168.1.1
static domain_name_servers=1.1.1.1 8.8.8.8
Reboot to apply the new IP:
sudo reboot
3. Services and Infrastructure
3.1. Secure SSH access (without password)
Generate a key pair (public/private) on your client computer if you haven’t already:
ssh-keygen
Copy the public key to the Raspberry Pi:
ssh-copy-id other@192.168.1.XXX
Edit the SSH daemon configuration on the server to harden security:
sudo nano /etc/ssh/sshd_config
Ensure these directives are configured as follows:
IgnoreRhosts yes
PasswordAuthentication no
PermitEmptyPasswords no
PermitRootLogin no
MaxAuthTries 3
PubkeyAuthentication yes
PrintMotd no
X11Forwarding no
ClientAliveInterval 300
ClientAliveCountMax 2
Recommendation: Change the default port (22) to another one to prevent automated brute-force attacks:
Port 2222
Open the new port in the firewall, reboot the Raspberry Pi, verify you can enter through the new port, and close port 22:
sudo ufw allow 2222/tcp
sudo reboot
Reconnect specifying the port:
ssh -p 2222 other@192.168.1.XXX
Close the old port on the server:
sudo ufw delete allow 22/tcp
3.2. RDP Server (XRDP)
To have remote desktop access from Windows or other RDP clients:
sudo apt install xrdp
For the traffic to be correctly encrypted, add the user to the ssl-cert group:
sudo adduser xrdp ssl-cert
3.3. File Server (NAS)
We are going to use a USB-connected SSD drive. First, format it (make sure /dev/sdX1 is your SSD):
sudo mkfs.ext4 /dev/sdX1
Mount it permanently at /mnt/my-ssd by editing the /etc/fstab file:
UUID=paste-partition-uuid-here /mnt/my-ssd ext4 defaults,noatime,errors=remount-ro 0 1
Create the folder you are going to share and grant permissions to your user:
sudo mkdir /mnt/my-ssd/Shared
sudo chown -R other:other /mnt/my-ssd/Shared
We can share this folder via several protocols:
3.3.1. Option A: NFS (Fast and native for Linux)
Install the NFS server:
sudo apt install nfs-kernel-server
Edit the /etc/exports file:
sudo nano /etc/exports
Add the path (you need to know your UID and GID, which is usually 1000. You can check this by running the id command):
/mnt/my-ssd/Shared *(rw,all_squash,insecure,async,no_subtree_check,anonuid=1000,anongid=1000)
Apply changes:
sudo exportfs -ra
3.3.2. Option B: Samba (CIFS - Universal for Windows/Mac/Linux)
Install Samba (if it asks about using DHCP WINS settings, answer “Yes”):
sudo apt install samba samba-common-bin
Edit the configuration /etc/samba/smb.conf and add to the end:
[shared]
comment = Shared Folder
path = /mnt/my-ssd/Shared
writeable = Yes
create mask = 0644
directory mask = 0755
browseable = Yes
valid users = @users
force user = other
Assign a Samba password to your user (Samba does not use PAM system passwords):
sudo smbpasswd -a other
Restart the services:
sudo systemctl restart smbd nmbd
4. Web Server (Apache)
Install Apache:
sudo apt install apache2
Adjust the web directory permissions so the www-data group can manage it:
sudo chown -R www-data:www-data /var/www/html
sudo find /var/www/html -type d -exec chmod 775 {} \;
sudo find /var/www/html -type f -exec chmod 664 {} \;
Add your user to the web group:
sudo usermod -a -G www-data other
Enable the HTTP/2 protocol for better performance:
sudo a2enmod http2
sudo systemctl restart apache2
Note: To implement HTTPS with Let’s Encrypt, you can follow this official DigitalOcean guide.
4.1. Dynamic DNS with NoIP
If you don’t have a static public IP at home, install the NoIP client:
mkdir noip-duc && cd noip-duc
wget [http://www.no-ip.com/client/linux/noip-duc-linux.tar.gz](http://www.no-ip.com/client/linux/noip-duc-linux.tar.gz)
tar xzf noip-duc-linux.tar.gz
cd noip-2.1.9-1
make
sudo make install
To create a daemon that starts automatically with systemd, create the file /etc/systemd/system/noip2.service:
[Unit]
Description=No-ip.com dynamic IP address updater
After=network.target syslog.target
[Install]
WantedBy=multi-user.target
Alias=noip.service
[Service]
ExecStart=/usr/local/bin/noip2
Restart=always
Type=forking
Enable and start the service:
sudo systemctl daemon-reload
sudo systemctl enable noip2
sudo systemctl start noip2
5. Calendars and Contacts (Radicale)
Radicale is a lightweight server for CalDAV (calendars) and CardDAV (contacts).
sudo apt install radicale apache2-utils python3-bcrypt python3-passlib
Create the users file and add the first one (the -c parameter creates the file, do not use it to add additional users):
sudo htpasswd -c -B /etc/radicale/users user
Prepare the necessary directories and permissions:
sudo mkdir -p /var/lib/radicale /var/log/radicale
sudo chown radicale:radicale /var/lib/radicale
sudo chown radicale:adm /var/log/radicale
sudo chmod g-w,o-rwx /var/lib/radicale /var/log/radicale
(For the rest of the configuration, follow the official Debian guide for Radicale).
6. File Sharing (P2P)
6.1. Transmission (Torrents)
Install the Transmission daemon:
sudo apt install transmission-daemon
Stop the service before editing the configuration:
sudo systemctl stop transmission-daemon
Edit /etc/transmission-daemon/settings.json paying special attention to these parameters:
"blocklist-enabled": true,
"blocklist-url": "[http://john.bitsurge.net/public/biglist.p2p.gz](http://john.bitsurge.net/public/biglist.p2p.gz)",
"download-dir": "/mnt/my-ssd/Shared/Downloads",
"incomplete-dir-enabled": true,
"incomplete-dir": "/mnt/my-ssd/Shared/Downloads/Incomplete",
"rpc-username": "YourUsername",
"rpc-password": "YourPassword",
Start the server again:
sudo systemctl start transmission-daemon
Access the web interface at: http://192.168.1.XXX:9091
6.1.1. Optional: Reverse proxy with Apache
If you want to access Transmission through the traditional port 80/443 instead of 9091:
sudo a2enmod proxy proxy_http
sudo systemctl restart apache2
Add this to the virtualhost block of your website in Apache (/etc/apache2/sites-available/yoursite.conf):
<IfModule mod_proxy.c>
ProxyRequests Off
<Proxy *>
AddDefaultCharset off
Require all granted
</Proxy>
ProxyPass /transmission http://localhost:9091/transmission
ProxyPassReverse /transmission http://localhost:9091/transmission
Redirect permanent /transmission [https://yourserver.com/transmission/web/](https://yourserver.com/transmission/web/)
</IfModule>
6.2. aMule
Pending documentation.
7. Security
7.1. Firewall (UFW)
My aspiration is to block all traffic, allowing only:
- Incoming: Web (80/443 TCP/UDP), XRDP (Local), Transmission, and SSH (on non-standard port).
- Outgoing: DNS, Web (updates), NTP (essential on Raspberry Pi since it has no RTC clock).
Install the UFW firewall:
sudo apt install ufw
Apply default policies (deny incoming, allow outgoing):
sudo ufw default deny incoming
sudo ufw default allow outgoing
Open the necessary ports:
# SSH on modified port (e.g., 2222)
sudo ufw limit 2222/tcp comment "Alternative SSH"
# Web Server (HTTP/HTTPS and future HTTP/3 over UDP)
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 443/udp
# Samba (Local network only)
sudo ufw allow from 192.168.1.0/24 to any port 137,138 proto udp
sudo ufw allow from 192.168.1.0/24 to any port 139,445 proto tcp
# NFS (Local network only)
sudo ufw allow from 192.168.1.0/24 to any port nfs
# XRDP (Local network only)
sudo ufw allow from 192.168.1.0/24 to any port 3389
# Transmission (Incoming P2P listening port)
sudo ufw allow 51413/tcp
# Transmission (Web interface access only from local network)
sudo ufw allow from 192.168.1.0/24 to any port 9091 proto tcp
Enable the firewall:
sudo ufw enable
7.2. Fail2ban (Intrusion protection)
Protect the server against brute-force attacks by blocking malicious IPs.
sudo apt install fail2ban
Copy the base configuration to create your own local configuration:
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local
Make sure to adjust the retries and the SSH port you have chosen:
maxretry = 3
[sshd]
enabled = true
filter = sshd
port = 2222
Restart the service:
sudo systemctl restart fail2ban
7.3. Unattended upgrades
To ensure the system receives security patches automatically:
sudo apt install unattended-upgrades