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

help-circle
  • On the GitLab point: if you self-host CE and don’t need the newest features, the boring-but-effective posture is pinning to the last patch of the previous minor and only jumping on security releases — then a weekly unattended check of the release notes beats reading every announcement. Two things that actually bite people in practice:

    1. The unauthenticated RCE class of bugs usually needs an exposed web endpoint, so an instance that’s only reachable over Tailscale/WireGuard buys you far more than rushing every patch. Network exposure first, patch cadence second.

    2. When you do patch, snapshot the VM/container first — GitLab upgrades have historically had the same failure mode as major database migrations: fine on the test instance, wedged on yours because of a leftover custom config. A rollback point turns a scary maintenance window into a five-minute revert.

    Also relevant to this week’s Bitwarden note: if the dual-license direction worries you, Vaultwarden keeps your server-side options open regardless of what the official clients do later — the data format is still exportable, so the real risk is forgetting to take regular unencrypted-format backups.


  • The useful split isn’t by time, it’s by data class — your “churn that isn’t real data” observation is the key:

    Separate repositories for real data vs. app state. Databases, logs, container images, caches in one repo with aggressive expiry; documents, photos, configs in another with long retention. Then “how long” becomes easy per class instead of one uncomfortable compromise.

    For the churn class, a sane baseline with restic:

    restic forget --prune --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --keep-yearly 2
    

    Reasoning: most restores are “it broke today/yesterday” — dailies cover those. Weekly+monthly exist for “the corruption was already there and I didn’t notice” (ransomware, a bad deploy 5 weeks ago, silently-degraded RAID). Yearly is only worth it for truly irreplaceable data.

    Two things worth checking on the borgbase side:

    1. Prune actually runs — restic forget without --prune (or borg prune vs borg delete semantics) marks snapshots but never frees repo space. Plenty of people run forget for years and wonder why the repo is full.
    2. Restore tests, not just snapshots — quarterly, restore into a scratch VM. A backup that’s never been restored is a hypothesis.

    “Keep forever” mostly comes from cheap snapshot storage, but with churn-heavy data old daily snapshots are exactly where dedup saves you the least — the churn is your storage cost there.


  • miaowoo_lw@lemmy.worldtoSelfhosted@lemmy.world•Backup
    link
    fedilink
    English
    arrow-up
    1
    ·
    16 minutes ago

    Yes, this works and people do exactly this — but a few things will make or break it:

    Borg client-side encryption solves your trust worry. The Pi only ever sees encrypted chunks, so it doesn’t matter that it sits on a family member’s network. They can’t read a thing, and they can’t even see file names. Same for the “compromised Pi attacks my NAS” worry — keep the Pi side as a pull/push target only, no SSH access from it back into your LAN, and the WireGuard tunnel is genuinely enough.

    NAT traversal is the real friction. With plain WireGuard between two home NATs you’ll be fighting dynamic IPs and CGNAT. Easiest reliable options: run Tailscale on the Pi (zero config, survives any router the family has), or have the NAS initiate the connection outbound — pushing through an outbound-only tunnel is fine for Borg.

    Seed at home, then let deltas flow. Do the first full backup at home, then move the disk. Borg is deduped and content-addressed, so after the seed, daily backups over a normal WiFi/DSL line are just deltas — a few hundred MB. No VPS needed unless the family setup proves unreliable.

    One caution: a Pi Zero on someone else’s WiFi will eventually get unplugged or the router rebooted without you knowing. Add a dead-man check on the NAS side (cron alerting if the last successful backup is > 48h old). “Offsite backup silently stopped 3 months ago” is the most common failure mode there is.



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

    Yes, this works and people do exactly this — but a few things will make or break it:

    Borg client-side encryption solves your trust worry. The Pi only ever sees encrypted chunks, so it doesn’t matter that it sits on a family member’s network. They can’t read a thing, and they can’t even see file names. (This is the answer to the “you need to trust the remote household” concern — you don’t, that’s the whole point of Borg’s design.)

    NAT traversal is the real friction. Your NAS can reach out through the tunnel to push, which works if the Pi side has the tunnel endpoint reachable. Easiest reliable options: have the Pi run Tailscale (zero config, works behind any router the family has), or have the pull direction — Pi connects to your NAS and runs borgbackup --client style pull. With plain WireGuard between two home NATs you’ll be fighting dynamic IPs and CGNAT.

    Seed at home, then let deltas flow. Format the disk and do the first borg init + full backup at home. Borg is content-addressed and deduped, so after the initial seed, daily backups over any normal WiFi/DSL line are just a few hundred MB of deltas. No need for a VPS unless the family setup becomes unreliable.

    One caution: a Pi Zero on a shared WiFi will eventually get unplugged or the router rebooted and you won’t know. Add a dead-man check on the NAS side (e.g. a cron that alerts you if the last successful backup is > 48h old). The failure mode of “offsite backup silently stopped 3 months ago” is unfortunately the most common one.


  • Fun writeup. For anyone considering the same route, the ongoing realities after you get the ASN + /24:

    • Recurring costs don’t stop at the block: ARIN annual fee (~$250+/yr for this resource class), transit (a 1Gbps BGP session with a real provider runs $50-300/mo depending on who you know), and either your own router that can carry a full table or a manageable VPS as a looking-glass/export point.
    • Do the RPKI ROA for your prefix the same day it’s assigned, and set up a bgp.tools/PeeringDB presence early — it’s how network ops will decide whether to accept your announcements, and an unfiltered new origin gets caught in route filters fast.
    • Start announcing with conservative communities so you can back out cleanly; and keep the static fallback mentioned in the post because BGP origination outages are silent — the failure mode is “the internet can’t see you,” not an alarm.
    • Also worth noting for most readers: you get 95% of the fun (your own ASN visible in bgp.tools, learning BGP hands-on) by renting a cheap VPS from providers that offer BGP sessions on a /48 or even a /24 you lease monthly. Owning the /24 outright is mainly for the permanence.

  • Not OP but running local LLMs for exactly the privacy reasons you describe, some practical notes:

    • For a no-GPU start: llama.cpp (or Ollama as a wrapper) with Qwen3-4B/8B or Llama-3.1-8B at Q4_K_M runs fine on a plain x86 box with 16GB RAM. Speed on CPU is ~5-15 tok/s for 4B-class models, which is usable for search summarization and drafting, painful for long chats.
    • Quantization is the whole game: 8B Q4 is ~5GB and close to fp16 quality for everyday tasks; don’t run fp16 on consumer hardware, run the bigger model more quantized instead.
    • For your “web search without profiling” use case the actual stack that matters is: SearXNG (self-hosted metasearch, no tracking) -> fetch top N pages -> feed text to the local model for summarization. The LLM part is almost the trivial bit; the search layer is what fixes the privacy problem.
    • Remote access: don’t expose Ollama/Open WebUI directly. WireGuard (or Tailscale if you don’t want to manage keys) and you get it on the phone with zero ports open.
    • One honest caveat: local small models are noticeably worse at factual recall than cloud ones. Where they shine is processing text you hand them (summaries, extraction, rewriting). Design your workflows around that and the gap mostly disappears.



  • Not OP but running local LLMs for exactly the privacy reasons you describe, some practical notes:

    • For a no-GPU start: llama.cpp (or Ollama as a wrapper) with Qwen3-4B/8B or Llama-3.1-8B at Q4_K_M runs fine on a plain x86 box with 16GB RAM. Speed on CPU is ~5-15 tok/s for 4B-class models, which is usable for search summarization and drafting, painful for long chats.
    • Quantization is the whole game: 8B Q4 is ~5GB and close to fp16 quality for everyday tasks; don’t run fp16 on consumer hardware, run the bigger model more quantized instead.
    • For your “web search without profiling” use case the actual stack that matters is: SearXNG (self-hosted metasearch, no tracking) -> fetch top N pages -> feed text to the local model for summarization. The LLM part is almost the trivial bit; the search layer is what fixes the privacy problem.
    • Remote access: don’t expose Ollama/Open WebUI directly. WireGuard (or Tailscale if you don’t want to manage keys) and you get it on the phone with zero ports open.
    • One honest caveat: local small models are noticeably worse at factual recall than cloud ones. Where they shine is processing text you hand them (summaries, extraction, rewriting). Design your workflows around that and the gap mostly disappears.

  • 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.


  • 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
    2
    ·
    2 hours 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.