Generalized provisioning for a homelab machine. Not every machine needs every section: pick by role.
openssh-server. On Ubuntu 24.04 it listens via ssh.socket; ssh.service spawns on demand./etc/ssh/sshd_config.d/60-key-only.conf: PasswordAuthentication no, PermitRootLogin noauthorized_keys curated: record which key belongs to which machine and remove dead keys.ufw deny incoming + ufw allow 22/tcp.For machines that should be reachable outside the LAN without port forwarding (and immune to routers without hairpin NAT), a Cloudflare tunnel:
curl -L -o ~/.local/bin/cloudflared \ https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 cloudflared tunnel login # browser auth, picks the zone cloudflared tunnel create <name> # writes ~/.cloudflared/<id>.json (secret) cloudflared tunnel route dns <name> <host> # one route per hostname
service: http://127.0.0.1:PORT for web, service: ssh://localhost:22 for SSH, always ending with a http_status:404 catch-all.ProxyCommand cloudflared access ssh –hostname %h under a Host alias in ~/.ssh/config.python3 -m http.server is a fine origin for a static ~/public.For a laptop acting as a server:
sleep/suspend/hibernate/hybrid-sleep targets: immediate and needs no logind restart./etc/systemd/logind.conf.d/: HandleLidSwitch=ignore for lids (takes effect next boot).IgnoreLid=true; consider CriticalPowerAction=PowerOff so a dying battery cleanly shuts down instead of failing a hybrid-sleep.nmcli con mod <ssid> 802-11-wireless.powersave 2 plus a NetworkManager conf.d default.
For laptops on permanent AC: where firmware exposes /sys/class/power_supply/BAT*/charge_control_end_threshold (recent ThinkPads and many ASUS do), write 75-80 and persist it with a oneshot systemd unit. Undo by setting 100 and disabling the unit.
Unattended jobs need non-interactive credentials. Never store passphrases in files.
keychain. Passphrase typed once per boot at an interactive login; cron jobs source ~/.keychain/<host>-sh for SSH_AUTH_SOCK. If the agent is empty after a fresh boot, jobs fail gracefully.
A daily cron script with functional probes, not just is-active: actually curl the service's own URL to catch running but unresponsive processes.
curl -d msg https://ntfy.sh/<topic>: free, no account. Pick an obscure topic name per machine.runuser -u), –ff-only, failing gracefully on dirty trees.For low-spec or focused machines:
snap set system refresh.retain=2 and drop disabled snap revisions.type(scope): description.git -c commit.gpgsign=false so a signing-key passphrase prompt cannot block a cron commit.[ ] sshd + key-only auth + authorized_keys [ ] ufw allows 22 [ ] machine recorded in inventory docs [ ] (optional) cloudflared tunnel + systemd service [ ] (optional, laptop) battery threshold + always-on [ ] keychain wired in ~/.profile [ ] health-check cron job installed [ ] ntfy topic chosen + subscribed