Table of Contents
New Machine Setup Playbook
Generalized provisioning for a homelab machine. Not every machine needs every section: pick by role.
1. SSH Access (every machine)
- Install
openssh-server. On Ubuntu 24.04 it listens viassh.socket;ssh.servicespawns on demand. - Key-only auth, drop-in
/etc/ssh/sshd_config.d/60-key-only.conf:PasswordAuthentication no,PermitRootLogin no - Keep
authorized_keyscurated: record which key belongs to which machine and remove dead keys. - Firewall:
ufw deny incoming+ufw allow 22/tcp.
2. Off-LAN Reachability
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
- Ingress config:
service: http://127.0.0.1:PORTfor web,service: ssh://localhost:22for SSH, always ending with ahttp_status:404catch-all. - SSH client side:
ProxyCommand cloudflared access ssh –hostname %hunder aHostalias in~/.ssh/config. - Cost: ~20-40 MB RAM.
python3 -m http.serveris a fine origin for a static~/public.
3. Always-On Duty
For a laptop acting as a server:
- Mask
sleep/suspend/hibernate/hybrid-sleeptargets: immediate and needs no logind restart. - logind drop-in
/etc/systemd/logind.conf.d/:HandleLidSwitch=ignorefor lids (takes effect next boot). - UPower:
IgnoreLid=true; considerCriticalPowerAction=PowerOffso a dying battery cleanly shuts down instead of failing a hybrid-sleep. - Wi-Fi powersave off for server duty:
nmcli con mod <ssid> 802-11-wireless.powersave 2plus a NetworkManagerconf.ddefault. - Screen blanking is fine to keep: it does not suspend anything.
4. Battery Longevity
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.
5. Unattended Credentials
Unattended jobs need non-interactive credentials. Never store passphrases in files.
- Preferred:
keychain. Passphrase typed once per boot at an interactive login; cron jobs source~/.keychain/<host>-shforSSH_AUTH_SOCK. If the agent is empty after a fresh boot, jobs fail gracefully. - Alternative: per-repo deploy keys (read-only, scoped). More secure than an account-wide passphrase-less key; never reuse one across repos.
- Anti-pattern: a passphrase-less personal key on the account. Do not.
6. Health Checks and Alerts
A daily cron script with functional probes, not just is-active: actually curl the service's own URL to catch running but unresponsive processes.
- Check connectivity first: do not churn restarts on a dead network.
- Retries: 2 attempts, 10 seconds apart, all logged. Self-trim the log.
- Alerts via
curl -d msg https://ntfy.sh/<topic>: free, no account. Pick an obscure topic name per machine. - Daily git pulls run as the owning user (
runuser -u),–ff-only, failing gracefully on dirty trees.
7. Lightweight Strip-Down
For low-spec or focused machines:
- Mask unused services: bluetooth, cups, avahi, ModemManager.
- Hide login autostart entries.
snap set system refresh.retain=2and drop disabled snap revisions.
8. Git Conventions
- One-line conventional commits:
type(scope): description. - Automation runs
git -c commit.gpgsign=falseso a signing-key passphrase prompt cannot block a cron commit.
Checklist
[ ] 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
