Edge devices frequently run with broad network exposure and weak maintenance. Security hardening has to be practical, repeatable, and automation-friendly.
1. Identity and access control
Baseline rules:
- disable default credentials
- enforce key-based SSH
- restrict privileged users
- rotate keys on schedule
Avoid shared admin accounts; per-operator identity improves traceability.
In practice the highest-value change is locking down SSH first. On every node I drop the following into a dedicated file (/etc/ssh/sshd_config.d/10-hardening.conf) rather than editing the stock config, so upgrades do not clobber it:
# /etc/ssh/sshd_config.d/10-hardening.conf
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin no
PubkeyAuthentication yes
AuthenticationMethods publickey
MaxAuthTries 3
LoginGraceTime 20
X11Forwarding no
AllowUsers ops
Then validate the config before reloading — a broken sshd config on a headless field node is a site visit:
sudo sshd -t && sudo systemctl reload ssh
I only reload (never restart) after confirming I still have a working key-based session open, so a mistake never locks me out mid-change.
2. Service surface reduction
List every listening service and disable what is unnecessary. Least functionality is the simplest security win.
I start by enumerating what is actually bound, then disable and mask anything the node does not need:
ss -tulpn # what is listening, and which process
systemctl list-units --type=service --state=running
sudo systemctl disable --now avahi-daemon cups bluetooth
sudo systemctl mask avahi-daemon
disable --now stops the service and prevents boot start; mask goes further and makes it impossible to start accidentally by a dependency. Review open ports again after each software update — packages occasionally re-enable a helper daemon.
3. OS and package lifecycle
Keep patching predictable:
- regular update window
- staged rollout (test group before fleet)
- rollback plan for breaking updates
Unmanaged package drift increases vulnerability exposure.
For unattended nodes I let security patches apply automatically but keep feature upgrades manual. On Debian/Raspberry Pi OS that means enabling unattended-upgrades:
sudo apt install unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades
I scope it to security updates and turn on automatic reboots in a maintenance window in /etc/apt/apt.conf.d/50unattended-upgrades:
Unattended-Upgrade::Origins-Pattern {
"origin=Debian,codename=${distro_codename}-security,label=Debian-Security";
};
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "03:30";
The pairing that matters: automatic security updates plus a controlled reboot time, so a kernel or OpenSSL fix actually takes effect without me logging into every node.
4. Network segmentation
Place devices in dedicated VLAN or network segment. Allow only required northbound and management traffic.
Block lateral movement by default. On the host itself I back that up with a default-drop firewall. A minimal nftables ruleset that only permits SSH from the management subnet looks like this (/etc/nftables.conf):
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0;
policy drop;
iif lo accept
ct state established,related accept
ct state invalid drop
# ICMP for basic reachability
ip protocol icmp accept
ip6 nexthdr ipv6-icmp accept
# SSH only from the management subnet
ip saddr 10.20.0.0/24 tcp dport 22 accept
counter drop
}
chain forward { type filter hook forward priority 0; policy drop; }
chain output { type filter hook output priority 0; policy accept; }
}
Apply and persist it:
sudo nft -f /etc/nftables.conf
sudo systemctl enable --now nftables
If a node has any WAN-facing service, I add fail2ban so repeated auth failures get the source IP banned rather than left to grind against the login. The defaults ship a working sshd jail; I only raise bantime and lower maxretry in /etc/fail2ban/jail.local:
[sshd]
enabled = true
maxretry = 3
bantime = 1h
findtime = 10m
5. Secrets management
Never hardcode secrets in images. Use:
- environment-specific secret injection
- minimal secret scope per service
- rotation procedures with audit logs
Compromised one node should not expose fleet-wide credentials.
6. Integrity and persistence controls
Useful controls include:
- secure boot when hardware supports it
- immutable root filesystem patterns for fixed-function nodes
- tamper-evident logging
For remote unattended nodes, persistence strategy is part of security.
7. Monitoring and auditability
Collect:
- auth failure events
- service crash/restart anomalies
- update status
- config drift indicators
No visibility means delayed detection.
8. Incident response readiness
Prepare in advance:
- remote isolation procedure
- credential revocation workflow
- known-good image recovery path
- post-incident forensic data checklist
Fast containment matters more than perfect diagnosis in early incident stages.
Final note
Edge hardening is operational discipline, not one command. A short checklist enforced consistently is more effective than complex controls applied inconsistently.
Sources
- Imported from the previous version of the site (gaborl.hu). Original publication around 2024-05-17.
- CIS Benchmarks (Center for Internet Security) — Linux hardening baselines: https://www.cisecurity.org/cis-benchmarks
- NIST SP 800-123, Guide to General Server Security: https://csrc.nist.gov/pubs/sp/800/123/final
- Debian
unattended-upgradesdocumentation: https://wiki.debian.org/UnattendedUpgrades - OpenSSH
sshd_configmanual: https://man.openbsd.org/sshd_config
Update history
- — Adopted from previous gaborl.hu (Hugo) site via legacy import.