• 1 Post
  • 24 Comments
Joined 2 months ago
cake
Cake day: September 17th, 2026

help-circle
  • nice, the “draw from your phone and see it at home” thing is pretty much the same problem I have with a small shared pixel canvas game I run, so on your open questions this is what ended up working for me. I didn’t go websocket, it’s SSE for server to client and a plain POST for every action, the POST response is kind of the “rpc return” and the change goes out to everyone else through the SSE stream. conflicts were a non issue because it’s one node process with the state in memory, two clicks on the same cell just apply in order and last one wins, the only place I needed a real check was undo (it answers 409 if someone touched the cell after you). for reconnects I don’t try to replay what you missed, EventSource reconnects by itself and on reopen the client just fetches the whole canvas again, it’s small enough that it’s cheaper than being clever about it. curious if the phone going to sleep gave you trouble with the websocket



  • i run a small browser game on a hetzner vps and for me the bots were never a load problem, it was the stats. the game shows how many people are online and every crawler that opened the live stream counted as a new player, in early october it was 28 of 61 stream opens. then a headless chromium on residential proxies, different ip every time, made 40 fake players in two days. what caught it was the Sec-CH-UA header, it said chromium 146 while the user agent said chrome 120, real browsers don’t mismatch like that. i don’t block them now, they just stop counting as people, which is kind of depressing too i guess


  • nice! for anyone with postgres in the mix, what bit me wasn’t the backup itself but the disk. a table in my side project kept one snapshot per minute and never deleted any, the disk hit 100% and postgres went down with a PANIC for like 40 min. now the nightly pg_dump writes to a .tmp, checks it with gzip -t and only then replaces the old file, and the app warns me if the newest dump is older than 26h or suspiciously small. restoring is just loading it into an empty db and starting the app, boring but it’s the part you actually want to know works



  • Plan sounds fine to me, debian + immich in docker + tailscale is pretty much the boring setup and boring is good for a box in a shed. one thing I’d do before carrying it out there, install tailscale and ssh, reboot it a couple of times and make sure it comes back on its own without a screen, because walking to the shed with a monitor gets old fast. also something like uptime kuma on another machine (or your NAS) pinging it, so you know it’s down before you’re on holiday and the photos stop uploading. I run a box at home I only reach over tailscale and that’s the part that saved me most.





  • They don’t go away on their own, every installed snap is mounted as its own loop device and snapd keeps an older revision or two so it can roll back, so the number moves around after updates. snap list --all shows which snaps they are, if one says disabled that’s the old revision and you can remove it with sudo snap remove <name> --revision=<rev>. about libation, if it’s installed as a snap itself that could be the actual problem, snaps are confined and can’t read folders outside your home or on other drives unless you connect the removable-media interface, so I’d check that before worrying about the loop devices.












  • Same conclusion here from the other side, I have a small multiplayer browser game where everyone paints cells on one shared grid (node, postgres, SSE), the client applies the paint right away and the server either confirms it or answers with a 409/429 and the client puts the old cell back. the rejection part is the one that took me longest honestly, a mutation that is valid locally but the server says no (out of charges, same color already there, world paused) and you need a different message for each, otherwise people think it’s lag. conflicts are just last write wins per cell, but that works because every write is a row in an append only events table, so nothing is really lost and you can replay or undo. and on reconnect I don’t try to merge anything, the client asks for the whole state again, at that size it’s cheaper than being clever.