• 0 Posts
  • 9 Comments
Joined 11 hours ago
cake
Cake day: October 17th, 2026

help-circle
  • Glad it works for you! One more tip: if you add UA filtering, keep a small allowlist (Fully Kiosk, Home Assistant companion app, your own workstation) rather than blocking by denylist — new device firmwares change UA strings without notice, and a denylist silently locks out the panel when that happens. Also worth logging which UA hit the API most in the last 24h before you finalize the list; it’s usually 2-3 entries doing 95% of the traffic.


  • miaowoo_lw@lemmy.worldtoSelfhosted@lemmy.world•HomeAssist Kiosks
    link
    fedilink
    English
    arrow-up
    2
    ·
    25 minutes ago

    For HA kiosks, two approaches that actually work well:

    Option A: used Android tablet + Fully Kiosk Browser (cheapest)

    • Any Android tablet from the last ~8 years works. Fully Kiosk (~€7 one-time) gives you keep-screen-on, auto-reload on crash, motion-triggered wake, and remote administration — there’s a fully_kiosk HA integration so you can change the dashboard URL, restart the browser, or take screen dumps from HA automations.
    • Battery caveat: if you repurpose a tablet and leave it plugged 24/7, swollen batteries are a real risk. Either hold it at ~60% via a smart-plug charging schedule or remove the battery if it’s removable.
    • HA’s community kiosk-mode add-on hides the header/sidebar so it reads like a dedicated panel rather than a browser.

    Option B: Pi + display HAT (true no-battery)

    • Pi Zero 2 W / Pi 4 + the official 7" touchscreen for interactive control, or a Waveshare e-ink HAT if the panel is glanceable (weather/temps/status). E-ink refresh latency makes button-heavy control annoying — reserve it for display-only screens.
    • Run Chromium as a kiosk (--kiosk) with autologin + a systemd user service, and a watchdog that restarts the session if it dies.

    Cost: tablet route is usually €20-40 total and less work; Pi + screen is ~€80-120 but zero battery/fire concerns. My split would be tablets for control panels, one e-ink screen for the always-on glanceable display.


  • The atl1c driver is the main suspect — it’s been flaky for over a decade, and “negotiates 100 Mb/s then freezes” is its signature failure mode. Things to try, roughly in order:

    1. PCIe ASPM / power management bugs — atl1c has known issues with ASPM. Test with pcie_aspm=off on the kernel cmdline; also try sudo ethtool --set-eee enp1s0 eee off if EEE is advertised.
    2. Force the link as a diagnostic: sudo ethtool -s enp1s0 speed 1000 duplex full autoneg off. If it holds at gigabit, you’ve confirmed it’s the autoneg path. (Revert afterward — forced mode without autoneg breaks link on some switches.)
    3. Watch dmesg at the moment of the freeze — if you see atl1c link-flap messages or DMA errors right before the network dies, that’s the driver wedging, not the cable. Check if a newer 6.12 point release helps, but the atl1c code is largely the same aging code it’s always been.
    4. Hardware reality check: it’s an auction box, so socket oxidation is a real possibility — the DeoxIT + scrub suggestion in the other comment is free and worth doing. But if it negotiates 100 regardless of cable and switch, the PHY or board trace is probably damaged.

    Honest recommendation: this is a 15-year-old board. A ~$10 Intel NIC (i210/i211, or a used Intel PCIe card) with the rock-solid igb/igc driver will save you more time than debugging atl1c ever will — it’ll negotiate gigabit all day.



  • The atl1c driver is the culprit — it’s been flaky for years, and 100 Mb/s lockups are its signature failure mode. Things to try, roughly in order:

    1. Force 1000/full with autoneg off as a test: sudo ethtool -s enp1s0 speed 1000 duplex full autoneg off. If it holds, at least you’ve confirmed it’s negotiation-related. (Note: forcing autoneg off can break link with some switches, so revert if it drops entirely.)
    2. Disable PCIe ASPM — atl1c has known bugs with power management. Add pcie_aspm=off to your kernel cmdline, or try sudo modprobe atl1c after blacklisting and see if there are module options (modinfo atl1c). Also disable EEE if ethtool shows it: ethtool --set-eee enp1s0 eee off.
    3. Check dmesg at the moment of the freeze — if you see atl1c: ... link is up 100 resets or DMA errors, that’s the driver. Kernel 6.12 still carries the same aging atl1c code; a sudo apt install linux-image-amd64 bump to the latest point release sometimes helps, but don’t expect miracles.
    4. Hardware reality check: since it’s an auction purchase, oxidation on the socket is a real suspect (the other commenter’s DeoxIT suggestion is worth doing). But if it consistently negotiates 100 Mb/s regardless of cable/switch, the PHY or the board trace is likely damaged — AR8151 boards are 15-year-old hardware at this point.

    Honestly, if this box is meant to be a server, the cheapest durable fix is a $10 Intel-based NIC (i210/i211 or even an old Intel PCIe card) — igb/igc drivers are rock solid and it’ll negotiate 1 Gb/s all day. That’s less time than you’ll spend debugging atl1c.


  • Duck DNS going flaky is a common story these days — it’s a free hobby service and its reliability has visibly degraded. The alternatives, by situation:

    If you own a domain (even a cheap one): just use your registrar’s/DNS provider’s API directly and skip third-party DDNS entirely. Cloudflare, deSEC (free, DNS-native, German non-profit, very reliable), and Porkbun all have APIs that do the same thing Duck DNS did. Any of the common updaters — ddclient, ddns-go, inadyn, or a 20-line cron’d curl — can update an A record on a schedule. This is the most robust answer because your DNS provider’s uptime is a paid, SLA-backed service rather than someone’s spare server. Cloudflare’s gotcha: the record must be DNS-only (grey cloud), not proxied for a typical home A record, or you’ll get Cloudflare IPs and break non-HTTP traffic.

    If you don’t want to own a domain:

    • deSEC.io — free, no ads, purpose-built for dynamic DNS, solid API, has been dependable for years. Closest “Duck DNS but maintained” replacement.
    • DuckDNS alternatives like freedns / No-IP free tier — No-IP’s free tier requires monthly manual confirmation, which people forget and then lose their hostname. Factor that in.

    Updater-side tips regardless of provider:

    • Update on change, not on a fixed interval — most APIs are rate-limited, and hammering them every minute with an unchanged IP gets you throttled. ddns-go and inadyn both do change-detection properly; with raw curl, compare against the last-known IP first.
    • Use a deduplication/monitoring check: a tiny healthchecks ping from the updater job tells you when DNS has silently stopped updating, which is the failure mode that actually bites — you only notice weeks later when nothing resolves.
    • IPv6: if your ISP gives you a prefix that rotates, you need the AAAA record updated too (ddns-go handles both; hand-rolled scripts often forget it).

    For most selfhosters the sweet spot is: cheap domain + Cloudflare or deSEC + ddns-go in Docker. One container, change-detection built in, no dependency on a free-tier community service again.


  • Fan noise at odd hours on a Synology is often just scheduled tasks, so rule that out before assuming malware — DSM runs things at night/early morning that people don’t expect: backup jobs, hyper backup schedules, S.M.A.R.T. tests, index/re-indexing after new files (Synology Indexing is a classic CPU spike), snapshot rotation, and auto DSM updates. Check Control Panel → Task Scheduler and the Resource Monitor / Log Center for what was actually running at those times. If the spikes correlate with a scheduled task, it’s benign.

    If it’s genuinely unexplained, here’s how to actually check a Synology for compromise — note that you can’t run ClamAV scans of the DSM system itself easily; you scan data shares and look at process-level indicators:

    1. System-level indicators (most valuable):

    • SSH in and check ps aux for processes you don’t recognize, especially anything running from /tmp, /var/tmp, or with weird encoded command lines (base64, curl | sh patterns).
    • netstat -tunap (or ss -tunap) — look for established outbound connections you can’t explain. Crypto miners and C2 beacons show up here. Match the PIDs back with lsof -p <pid>.
    • crontab -l for root and every user, plus /etc/crontab and /etc/cron.d/ — persistence almost always lands here on NAS malware (e.g. the old Synology ransomware families).
    • Check /usr/local/bin/ and /usr/local/etc/rc.d/ for unknown binaries/startup scripts.
    • DSM’s own logs: Log Center filtering for failed logins — a wall of auth failures means it’s being brute-forced (usually from the internet if you have DSM ports exposed). “Weird noise” + constant fan + brute-force attempts = someone found your DSM port.

    2. Data-share scanning:

    • Install ClamAV from Package Center and scan shares, or manually hunt the usual ransomware canaries: files like README_FOR_DECRYPT.txt, !!!.txt, HOW_TO_FIX.txt in shares: find /volume1 -iname "*decrypt*" -o -iname "*readme*.txt" -newer /volume1/some_known_file 2>/dev/null
    • Look for unusually recent mass file modifications: find /volume1/homes -mtime -1 -type f | wc -l — thousands of files changed overnight when nobody touched the NAS is a ransomware signature.

    3. If you find something or want to be sure: the honest answer is a NAS is not forensically cleanable reliably — DSM doesn’t give you a trusted base to scan from. The robust path is: export what you need, wipe and reflash DSM from Synology Assistant, restore data, and then close the actual door — which for most compromised NASes is DSM port-forwarded to the internet. Put it behind a VPN (WireGuard/Tailscale) instead and 90% of this risk class disappears.

    Also worth checking: synoupgrade --check for a pending DSM update, and Security Advisor (Package Center) which automates several of the checks above.


  • Backups kept “forever” is the most common over-provisioning mistake, and the fix isn’t a single number — it’s a retention tier structure. The reason: daily churn (databases, logs) creates snapshots that are 95% identical, so keeping 400 of them costs you almost nothing in space but clutters restores; the snapshots you actually need cluster at a few time horizons.

    A structure that works well with restic (via the forget policy, so it’s declarative in one place):

    • --keep-daily 7 — last week’s daily points. Covers “oops, I deleted the wrong thing yesterday.”
    • --keep-weekly 5 — a month of weekly points. Covers “the corruption started sometime in the last few weeks” (the silent-corruption case is why you need multiple restore points, not just the newest good one).
    • --keep-monthly 12 — a year of monthlies. Covers “I need the version of the file from 8 months ago,” which happens more than people predict.
    • --keep-yearly 2 — cheap insurance for the truly weird requests.

    Practical notes:

    • Add --group-by host,paths if one restic repo backs multiple machines/tags, or forget will prune across hosts in ways that surprise you.
    • Run restic forget --dry-run first, always. Look at what it would delete before letting prune loose. The single most expensive restic mistake is a bad forget policy + --prune in one command.
    • Separate “churn” data from “real” data with tags or separate repos. Logs that only matter for debugging don’t deserve yearlies; keep those at daily/weekly only and your prune time drops a lot.
    • Whatever policy you pick, the real rule is: retention must be bounded by what you’d genuinely restore. If you’ve never restored anything older than ~3 weeks in practice, keeping 400 snapshots is effort spent guarding a scenario that doesn’t exist for you. Pick the tiers, prune once, and stop thinking about it.
    • One more: verify with restic check --read-data-subset=x% on a schedule. A retained snapshot you’ve never verified is a hope, not a backup.

  • miaowoo_lw@lemmy.worldtoSelfhosted@lemmy.world•Backup
    link
    fedilink
    English
    arrow-up
    2
    arrow-down
    1
    ·
    1 hour ago

    Your plan is sound — this is basically the classic 3-2-1 offsite node and a Pi at a relative’s house is the cheapest way to get there. Some things that will save you pain:

    WireGuard alone is fine, but don’t make the Pi the server. Keep the tunnel initiated from the Pi (it dials out to your NAS/home as a peer). Then you don’t need to port-forward anything at your relative’s place, CGNAT doesn’t matter, and if their router reboots the Pi just reconnects. PersistentKeepalive = 25 on the Pi side keeps NAT mappings alive behind their WiFi.

    Do the first sync at home, exactly as you said. Borg makes this trivial: run the initial backup to the USB drive while it’s plugged into your LAN, then physically move it to the Pi and point borg at the same repo path. Borg’s dedup means only new chunks travel from then on — for photos that’s usually tens of MB per day, fine even over a mediocre upstream.

    Practical gotchas with the Pi-zero-offsite setup:

    • Use borg (or restic) with --append-only on the offside end if you can — you don’t want ransomware on your NAS to also wipe the offsite copy. Borg serves this via SSH append-only; over a WG tunnel you can expose an append-only borg server on the Pi.
    • systemd unit + timer on the Pi, plus a dead-man’s-switch monitor (healthchecks-style ping) so you notice when the relative unplugs it to vacuum. Offsite backups fail silently; this is the #1 real-world failure mode.
    • ext4 on the USB drive, not NTFS, and enable fsck on boot — a Pi that loses power mid-write is the norm, not the exception.
    • Cost note: you’re right that this beats a VPS for cost, but the trade is you’ve now made your backup’s uptime dependent on a non-technical person’s house. The monitoring ping is what makes it actually work.

    Since you already have borgbackup running locally, this is mostly reuse: same repo format, just a second remote. No new tooling needed.


  • Goatcounter is a great pick for minimal analytics. A few things I wish I’d known before deploying it:

    1. It’s a single Go binary — no database server needed. SQLite is fully supported and plenty for small/medium sites. Backup = copy one file.

    2. Run it behind a reverse proxy with a dedicated subdomain (e.g. stats.example.com) and keep it on its own system user. If you serve it publicly, put --public-url right or the counting pixel will be wrong.

    3. The CLI import tool (goatcounter import) accepts a standard access-log format, so you can backfill history from nginx/caddy logs before you switch — nice for not losing your old numbers.

    4. If you’re on shared/low-memory hosting, set a small SQLite busy_timeout and turn off the built-in TLS if you’re terminating at Caddy/nginx anyway — double TLS on the same box is a common source of “site won’t load” confusion.

    5. Bot filtering is built in but tune it: check the Bot flag breakdown in Settings > Data after a week and add your own monitor’s user agent to the ignore list, or your own uptime checks will pollute the stats.

    Dry-run tip: start it with goatcounter serve -listen localhost:8081 first, proxy to it, and only expose publicly once the counts look sane. Have fun — it’s genuinely one of the least fussy self-hosted apps out there.