Setting up a home server can seem daunting, but with this blog post, you too can transform an old PC into a secure home server! This blog post will walk you through every step, from basic SSH setup to advanced security hardening.
Prerequisites
Before we begin, ensure you have:
- A PC with Ubuntu Desktop installed (not Ubuntu Server, though the steps work similarly)
- Basic command line familiarity
- Administrative access to your home router
- Another computer to test SSH connections
Quick Reference: Essential Commands
Here are some handy vim commands you might use throughout this guide. If you’re not familiar with vim, you can use any text editor of your choice.
- Open remote files:
vim scp://user@server//home/user/file.py
- Open multiple files in tabs:
vim -p file1.txt file2.txt
(may need:tab all
)
Step 1: Setting Up SSH Access
SSH (Secure Shell) is the foundation of remote server management. Let’s get it configured first.
Install and Enable OpenSSH Server
sudo apt install openssh-server
sudo systemctl enable ssh
sudo systemctl status ssh
Find Your Server’s IP Address
hostname -I
This will return something like 10.0.0.207
- note this down as we’ll use it throughout the guide.
Test SSH Connection
From your client computer, try connecting:
ssh user@10.0.0.207
You’ll need to enter your password at this point.
Set Up Key-Based Authentication
For better security and convenience, set up SSH key authentication:
ssh-copy-id user@10.0.0.207
After this, you should be able to SSH without entering a password.
Step 2: Configuring a Static IP Address
Dynamic IP addresses can change, which gets troublesome whenever you need to connect to your server. Let’s set up a static IP to avoid this.
Understanding Netplan
Ubuntu uses Netplan for network configuration. Navigate to the netplan directory:
cd /etc/netplan/
ls
You should see a file like 01-network-manager-all.yaml
.
Create a Backup
Always backup before making changes:
sudo cp /etc/netplan/01-network-manager-all.yaml /etc/netplan/01-network-manager-all-BACKUP.yaml
Create Static IP Configuration
Create a new configuration file:
sudo vim /etc/netplan/static.yaml
Use this template (we’ll customize it next):
network:
version: 2
renderer: networkd
ethernets:
eth0:
addresses:
- 10.10.10.2/24
routes:
- to: default
via: 10.10.10.1
nameservers:
addresses: [1.1.1.1, 1.0.0.1]
Get Your Network Interface Information
Find your network interface name:
ifconfig -a
Look for something like enp42s0
(ignore the lo
interface). You’ll also note your current IP address.
Customize the Configuration
Update your static.yaml
file:
- Replace
eth0
with your actual interface name (e.g.,enp42s0
) - Set your desired static IP (e.g.,
10.0.0.207/24
) - Set your router’s gateway (usually
10.0.0.1
for most home routers) - Use Cloudflare’s DNS servers:
[1.1.1.1, 1.0.0.1]
Apply the Configuration
Set proper permissions and apply:
sudo chmod 600 /etc/netplan/static.yaml
sudo netplan apply
sudo reboot
Test the connection from your client:
ssh user@10.0.0.207
Step 3: Hardening with UFW Firewall
UFW (Uncomplicated Firewall) provides an easy way to manage iptables rules.
Install and Enable UFW
sudo apt install ufw
sudo systemctl status ufw
sudo ufw enable
Set Default Policies
Start with a deny-all approach:
sudo ufw default deny incoming
sudo ufw default deny outgoing
Allow Essential Services
Open only the ports you need:
# Web traffic
sudo ufw allow 80,443/tcp
sudo ufw allow out 80,443/tcp
# SSH (we'll change this port later)
sudo ufw allow 22/tcp
sudo ufw allow out 22/tcp
# NTP for time synchronization
sudo ufw allow 123/udp
sudo ufw allow out 123/udp
# DNS resolution
sudo ufw allow in from any to any port 53
sudo ufw allow out from any to any port 53
Check Firewall Status
sudo ufw status numbered
You should see a comprehensive list of rules for both IPv4 and IPv6.
Step 4: Network Time Protocol (NTP) Setup
Accurate time is crucial for security certificates and log correlation.
Backup Current Configuration
sudo cp --archive /etc/systemd/timesyncd.conf /etc/systemd/timesyncd.conf-COPY-$(date +"%Y%m%d%H%M%S")
Configure NTP
Edit the configuration file:
sudo vim /etc/systemd/timesyncd.conf
Add these lines:
[Time]
NTP=0.pool.ntp.org 1.pool.ntp.org
FallbackNTP=ntp.ubuntu.com
Restart and Verify
sudo systemctl restart systemd-timesyncd
sudo systemctl status systemd-timesyncd
Set Your Timezone
Check current timezone:
timedatectl | grep Time
If needed, set it correctly:
sudo timedatectl set-timezone America/Vancouver
Step 5: Advanced SSH Security
Now let’s seriously harden SSH security.
Change SSH Port
First, allow the new port through UFW:
sudo ufw allow 2222/tcp
sudo ufw allow out 2222/tcp
Backup SSH Configuration
sudo cp --preserve /etc/ssh/sshd_config /etc/ssh/sshd_config.$(date +"%Y%m%d%H%M%S")
Apply Hardened SSH Configuration
Edit the SSH config:
sudo vim /etc/ssh/sshd_config
Delete everything (:%d
in vim) and paste this hardened configuration:
# Supported HostKey algorithms by order of preference
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
# Cryptographic settings
KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com
# Security settings
Port 2222
LogLevel VERBOSE
Protocol 2
PermitUserEnvironment no
PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
PermitEmptyPasswords no
MaxAuthTries 3
MaxSessions 2
X11Forwarding no
IgnoreRhosts yes
UseDNS no
ClientAliveCountMax 0
ClientAliveInterval 300
AllowUsers YOUR_USERNAME # CHANGE THIS!
# Disable port forwarding
AllowAgentForwarding no
AllowTcpForwarding no
AllowStreamLocalForwarding no
GatewayPorts no
PermitTunnel no
# SFTP logging
Subsystem sftp /usr/lib/openssh/sftp-server
# Additional security
Compression no
PrintMotd no
TCPKeepAlive no
ChallengeResponseAuthentication no
UsePAM yes
AcceptEnv LANG LC_*
Important: Replace YOUR_USERNAME
with your actual username!
Restart SSH and Verify
sudo systemctl restart sshd
sudo ss -tlpn | grep ssh
You should see SSH listening on port 2222.
Test New SSH Configuration
From your client computer:
ssh -p 2222 user@10.0.0.207
Once you confirm the new port works, delete the old SSH port:
sudo ufw delete allow 22/tcp
sudo ufw delete allow out 22/tcp
Optional: Auto-logout After Inactivity
Add automatic logout after 5 minutes of inactivity:
echo 'TMOUT=300' >> ~/.bashrc
Strengthen SSH Keys
Remove weak moduli:
# Backup existing moduli file
sudo cp --archive /etc/ssh/moduli /etc/ssh/moduli-COPY-$(date +"%Y%m%d%H%M%S")
# Remove keys weaker than 3072 bits
sudo awk '$5 >= 3071' /etc/ssh/moduli | sudo tee /etc/ssh/moduli.tmp
sudo mv /etc/ssh/moduli.tmp /etc/ssh/moduli
Add Legal Banner
Create a warning banner:
sudo vim /etc/issue.net
Add this message:
This system is for the use of authorised users only.
Individuals using this computer system without authority, or in excess of their authority, are subject to having all of their activities on this system monitored and recorded by system personnel.
In the course of monitoring individuals improperly using this system, or in the course of system maintenance, the activities of authorised users may also be monitored.
Anyone using this system expressly consents to such monitoring and is advised that if such monitoring reveals possible evidence of criminal activity, system personnel may provide the evidence of such monitoring to law enforcement officials.
Step 6: Git Configuration for Development
If you plan to use your server for development, configure Git properly.
Allow Git Port (Optional)
sudo ufw allow 9418/tcp
Configure Git for SSH
Instead of the standard GitHub SSH URL, use the HTTPS port for better firewall compatibility:
# Standard approach
git remote add origin git@github.com:username/repository.git
# Firewall-friendly approach
git remote add origin ssh://git@ssh.github.com:443/username/repository.git
Additional Security Considerations
Network-Level Restrictions
For maximum security, consider restricting SSH access to your local network only. You can modify UFW rules to only allow connections from your local subnet:
sudo ufw allow from 10.0.0.0/24 to any port 2222
Regular Maintenance
- Keep your system updated:
sudo apt update && sudo apt upgrade
- Monitor SSH logs:
sudo journalctl -u ssh
- Review firewall logs:
sudo ufw status verbose
- Check for failed login attempts:
sudo grep "Failed password" /var/log/auth.log
Conclusion
You now have a secure Ubuntu home server with:
- ✅ SSH access with key-based authentication
- ✅ Static IP configuration
- ✅ Hardened firewall rules
- ✅ Network time synchronization
- ✅ Secure SSH configuration on a non-standard port
- ✅ Git development capabilities
This setup provides a solid foundation for hosting services, running development environments, or managing home automation systems. Remember to regularly update your system and monitor logs for any suspicious activity.