Basic Security Defaults for ARM Linux

Summary
This page describes a practical baseline for securing an ARM Linux single-board computer used as a server, development host, or always-on service. The goal is to reduce avoidable security risks without making the system difficult to operate or maintain. These measures address the most common attack vectors: weak authentication, unpatched software, unnecessary exposed services, and missing access logs.
Who this is for
Anyone running an SBC that accepts network connections, especially boards exposed to the public internet or untrusted networks. If your board runs SSH, web services, or network-attached storage, these security defaults are essential.
Prerequisites
Before applying these security measures, ensure you have:
- Direct console access: Serial console or HDMI + keyboard for recovery if you lock yourself out of SSH.
- Backup access method: A second way to log in (local console, VNC, or a management network) in case SSH configuration breaks.
- Time to test: Changes to SSH and firewall rules can lock you out. Test each step before disconnecting.
- Current backups: Before making security changes, back up /etc and critical configuration files.
Baseline security principles
- Authentication: Use SSH keys instead of passwords. Passwords are vulnerable to brute-force attacks; keys are not.
- Updates: Keep the system patched on a predictable schedule. Most exploits target known vulnerabilities with available patches.
- Exposure: Expose only the services and ports you intend to run. Every open port is a potential attack surface.
- Logging: Enable and monitor access logs. You cannot detect intrusions without logs.
- Principle of least privilege: Do not run services as root unless absolutely necessary. Use dedicated service accounts with minimal permissions.
Step-by-step security setup
Step 1: Generate and deploy SSH keys
On your workstation (not the SBC), generate an ED25519 key pair:
ssh-keygen -t ed25519 -C "your-email@example.com"
# Save to default location (~/.ssh/id_ed25519)
# Set a strong passphrase (optional but recommended)
Copy the public key to the SBC:
ssh-copy-id user@SBC_IP_ADDRESS
# Enter your password one last time
Test key-based login:
ssh user@SBC_IP_ADDRESS
# You should log in without a password (or with your key passphrase if you set one)
Step 2: Disable password authentication
Once key-based login works, disable password authentication on the SBC:
sudo nano /etc/ssh/sshd_config
# Find and set these directives:
# PasswordAuthentication no
# ChallengeResponseAuthentication no
# PermitRootLogin no
# PubkeyAuthentication yes
Or use sed to edit in place:
sudo sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo sed -i 's/^#\?ChallengeResponseAuthentication.*/ChallengeResponseAuthentication no/' /etc/ssh/sshd_config
sudo sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config
Reload SSH to apply changes:
sudo systemctl reload ssh || sudo systemctl reload sshd
Critical: Do not close your current SSH session until you have tested login from a new terminal window.
Step 3: Configure a firewall
Use ufw (Uncomplicated Firewall) for simple rule management:
# Install ufw (if not already present):
sudo apt install ufw
# Default policies: deny all incoming, allow all outgoing
sudo ufw default deny incoming
sudo ufw default allow outgoing
# Allow SSH (change port if you use non-standard):
sudo ufw allow 22/tcp
# Allow additional services as needed:
# sudo ufw allow 80/tcp # HTTP
# sudo ufw allow 443/tcp # HTTPS
# Enable firewall:
sudo ufw enable
# Check status:
sudo ufw status verbose
For iptables users:
# Flush existing rules:
sudo iptables -F
# Default policies:
sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP
sudo iptables -P OUTPUT ACCEPT
# Allow loopback:
sudo iptables -A INPUT -i lo -j ACCEPT
# Allow established connections:
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# Allow SSH:
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# Save rules (Debian/Ubuntu):
sudo apt install iptables-persistent
sudo netfilter-persistent save
Step 4: Create a non-root user for services
Avoid running applications as root. Create dedicated service accounts:
# Example: create a user for a web application
sudo useradd -r -s /bin/false -d /var/www webapp
# -r: system account (no login shell, no home directory by default)
# -s /bin/false: no interactive shell
# -d /var/www: home directory (if needed for app files)
Step 5: Enable automatic security updates (optional)
For Debian/Ubuntu/Armbian, install unattended-upgrades:
sudo apt install unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades
# Select "Yes" to enable automatic security updates
Verify configuration:
cat /etc/apt/apt.conf.d/50unattended-upgrades
# Confirm security updates are enabled
Note: For production systems, test updates on a staging board first before enabling unattended upgrades.
Step 6: Disable unused services
List all running services:
systemctl list-units --type=service --state=running
Disable services you don't need:
sudo systemctl disable --now
sudo systemctl mask # Prevent manual or automatic start
Common candidates for disabling: avahi-daemon (mDNS), bluetooth (if not used), cups (printing), ModemManager (if no cellular modem).
Verification checks
After applying security changes, verify the configuration:
# List all listening ports and associated services:
ss -tulpn
# or
sudo netstat -tulpn
# Check failed systemd units:
systemctl --failed
# Check recent SSH authentication logs:
sudo journalctl -u ssh -n 50
# or
sudo grep "Accepted\|Failed" /var/log/auth.log | tail -n 20
# Verify firewall rules:
sudo ufw status verbose
# or
sudo iptables -L -v -n
# Check for rootkits (optional, install rkhunter or chkrootkit):
sudo rkhunter --check --skip-keypress
Monitoring and logging
Enable persistent systemd journal:
sudo mkdir -p /var/log/journal
sudo systemctl restart systemd-journald
journalctl --disk-usage # Check current journal size
Configure log retention (edit /etc/systemd/journald.conf):
[Journal]
SystemMaxUse=500M
MaxRetentionSec=1month
Monitor failed login attempts:
sudo journalctl _SYSTEMD_UNIT=ssh.service | grep "Failed password"
Install fail2ban to block repeat attackers:
sudo apt install fail2ban
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd
Troubleshooting common issues
Locked out of SSH after disabling password authentication:
- Connect via serial console or HDMI + keyboard.
- Edit /etc/ssh/sshd_config and temporarily re-enable PasswordAuthentication yes.
- Reload SSH: sudo systemctl reload sshd.
- Test key-based login again from your workstation. Check ~/.ssh/authorized_keys permissions (must be 600 or 644).
Firewall blocks SSH after enabling ufw:
- If you have console access, run sudo ufw allow 22/tcp and sudo ufw reload.
- If you cannot access the board, boot from a rescue microSD card and edit firewall rules.
fail2ban bans your own IP address:
- Unban: sudo fail2ban-client set sshd unbanip YOUR_IP.
- Add your IP to the ignore list in /etc/fail2ban/jail.local: ignoreip = 127.0.0.1/8 YOUR_IP/32.
Automatic updates break the system:
- Check /var/log/unattended-upgrades/ for error logs.
- Roll back the kernel or package via serial console or rescue boot.
- Disable unattended-upgrades and apply updates manually during maintenance windows.
Frequently asked questions
Q: Should I change the SSH port from 22 to something else?
A: It reduces log noise from automated scans but does not improve security significantly. Key-based authentication and fail2ban are more effective. If you do change the port, update your firewall rules accordingly.
Q: Is fail2ban necessary if I use SSH keys?
A: Not strictly necessary, but it reduces log clutter and blocks scanning bots. It also protects other services (HTTP, FTP) if you expose them.
Q: How do I allow SSH only from specific IP addresses?
A: Use ufw: sudo ufw allow from YOUR_IP to any port 22 proto tcp. Or with iptables: sudo iptables -A INPUT -p tcp -s YOUR_IP --dport 22 -j ACCEPT.
Q: What should I back up before making security changes?
A: At minimum, back up /etc/ssh/sshd_config, /etc/ssh/authorized_keys (or ~/.ssh/authorized_keys for each user), and firewall rules (sudo iptables-save > iptables-backup.txt or sudo ufw status > ufw-backup.txt).
Q: How do I test firewall rules without locking myself out?
A: Use at command to schedule a firewall flush: echo "ufw disable" | at now + 5 minutes. If you lock yourself out, the firewall will disable automatically after 5 minutes.
Q: Should I install an intrusion detection system (IDS)?
A: For home/lab systems, fail2ban + log monitoring is sufficient. For production or high-value targets, consider OSSEC, Snort, or Suricata.
Q: How do I rotate SSH keys?
A: Generate a new key pair, add the new public key to ~/.ssh/authorized_keys, test login with the new key, then remove the old key from authorized_keys.
Related guides
Author: LeMaker Documentation Team
Last updated: 2026-01-10