diff --git a/content/posts/2026-03-18-building-dumpsterchat.md b/content/posts/2026-03-18-building-dumpsterchat.md new file mode 100644 index 0000000..77eff50 --- /dev/null +++ b/content/posts/2026-03-18-building-dumpsterchat.md @@ -0,0 +1,79 @@ +--- +layout: post +title: "brewing dumpsterchat: a self-hosted chat for ~12 degenerates" +date: "2026-03-18" +categories: [tech, development, homelab, projects] +tags: [go, react, websocket, self-hosted, chat, discord-alternative] +--- + +the kettle's on and the terminal is warm. + +so let me tell you about dumpsterChat — the self-hosted chat platform i built for a group of about twelve friends because we got tired of wondering if some corporation was reading our terrible jokes. yes, the name is intentionally ridiculous. yes, the server it runs on is called SmoothBrainCollective. no, i will not be taking questions about our naming conventions. we contain multitudes. dumb, dumb multitudes. + +## why not just use discord? + +look, discord is fine. it's a good product. but every few months they'd change something, shove another feature nobody asked for into the sidebar, or we'd read another headline about data practices that made us squirm. we're not paranoid — we're just twelve people who like owning our stuff. there's a certain warmth in knowing that every message, every emoji reaction, every embarrassing late-night rant lives on hardware we control. it's the difference between renting an apartment and owning a house. sure, the landlord handled the plumbing, but you couldn't knock down a wall when you felt like it. + +so one weekend, fueled by an unreasonable amount of dark roast, i started building. + +## the stack: go in the back, react in the front + +the backend is Go with Chi as the router. i picked Go because it compiles to a single binary, handles concurrency like it was born for it (it was), and doesn't make me think about garbage collection at 2am. Chi is lightweight, composable, and doesn't try to be a framework — it's just a good router with sensible middleware. that's all i wanted. i didn't need an opinionated monolith telling me how to structure my feelings. + +the frontend is Vite + React + Tailwind CSS. Vite because hot module replacement is the closest thing to magic i've experienced in web development. React because, love it or hate it, the ecosystem is enormous and the component model just clicks in my brain. Tailwind because i'd rather write twelve utility classes than maintain a stylesheet that grows like kudzu across the project. it's not elegant. it's effective. like a french press. + +WebSocket for real-time messaging. no long-polling, no SSE workarounds — just a clean persistent connection that pushes messages the moment they're sent. typing indicators, presence updates, new messages, reactions — all streamed through the same socket. the latency is low enough that it genuinely feels instant, even with our janky but beloved infrastructure. + +## the features nobody asked me to build but i built anyway + +this is the part where scope creep became a lifestyle. + +**direct messages.** because sometimes you need to privately tell someone their take is unhinged. + +**full markdown support.** bold, italic, code blocks, lists, links — the whole thing. we're degenerates, but we're literate degenerates. writing a message with a properly formatted code block in it? chef's kiss. + +**link embeds.** paste a URL and it pulls the title, description, and thumbnail. youtube videos get a playable embed. it's a small thing but it makes the chat feel alive, like it's actually connected to the internet and not just a text box screaming into the void. + +**search.** full-text search across messages. because three weeks from now someone's going to say "what was that link you shared?" and we need to find it without scrolling through a thousand messages about whether a hot dog is a sandwich. + +**moderation tools: kick, ban, and mute.** we're friends, but we're also twelve people with strong opinions. sometimes someone needs a time-out. the mute function was built with great affection and a specific person in mind (they know who they are, and they've earned it). + +**slowmode.** for when the chat is moving too fast and people are talking over each other like a caffeine-fueled debate club. set a cooldown per channel, breathe a little, think before you type. revolutionary concept. + +**threads.** reply chains that don't derail the main conversation. discord got this one right and i stole it unapologetically. + +**forums.** structured discussion channels where topics get their own threads with statuses — open, resolved, closed. great for the friend who always has a "quick question" that turns into a seventeen-message troubleshooting saga. + +**calendar channels.** channel type for events. create events with dates, descriptions, and RSVPs. because coordinating twelve adults across three time zones via "who's free saturday?" messages is a nightmare i refuse to live in. + +**docs channels.** collaborative document channels for shared notes, guides, recipes, whatever. think wiki pages that live inside the chat. the friend group cookbook lives here now and it's glorious. + +**role-based permissions with bitflags.** roles aren't just labels — they carry actual permission sets implemented as bitflags. each permission is a bit, roles are bitwise OR'd together, and checking access is a single bitwise AND operation. it's fast, it's clean, and it made me feel like a real systems programmer for about fifteen minutes. roles like admin, moderator, member — each with granular permissions for managing channels, kicking users, editing docs, creating events. the system is simple enough for twelve people but built to scale to... well, maybe thirteen people someday. + +## where it lives + +dumpsterChat runs on a Proxmox LXC container at `172.20.0.125` on SmoothBrainCollective — my homelab server that also hosts a growing collection of services i've convinced myself i need. the container is lightweight, the Go binary sips memory, and the whole thing sits behind a reverse proxy with TLS. it's not enterprise-grade infrastructure. it's a house of cards built with love and held together by systemd services and prayer. + +backups happen. i promise. mostly. + +## what i learned (or: things the coffee told me) + +**building for twelve people is liberating.** you don't need to optimize for ten thousand concurrent users when your entire user base could fit in a minivan. the queries can be a little naive. the WebSocket hub can broadcast to everyone instead of maintaining subscription trees. simplicity is a feature when your scale is small and your friends are patient. + +**go is genuinely fun for this kind of thing.** the concurrency model with goroutines and channels maps beautifully to a chat server. each WebSocket connection is a goroutine. messages flow through channels. the whole thing hums. + +**react + tailwind is fast to iterate on.** i could sketch a feature in the morning and have it working by lunch. the component model makes it easy to add new channel types — forums, calendars, docs — without touching the existing ones. + +**self-hosting is a mindset.** it's not just about running your own server. it's about understanding every layer of the stack. when something breaks at 11pm, i know exactly where to look because i built it. there's no support ticket, no status page, just me and the logs and another cup of coffee. + +## the point + +dumpsterChat isn't trying to replace discord. it's not trying to be the next big thing. it's a chat app for twelve friends who wanted to own their conversations, built by one person who had too much coffee and a free weekend (okay, several free weekends). it does what we need, it runs on hardware we control, and it has a name that makes us laugh every time we say it out loud. + +that's enough. that's the whole point. + +if you've been thinking about self-hosting something — a chat app, a wiki, a file server, whatever — just start. it doesn't have to be perfect. it doesn't have to scale. it just has to work for the people who use it. the rest is just more coffee and more commits. + +stay warm. brew something. + +-dustin diff --git a/content/posts/2026-04-15-gophergate-and-the-ai-stack.md b/content/posts/2026-04-15-gophergate-and-the-ai-stack.md new file mode 100644 index 0000000..3d2f001 --- /dev/null +++ b/content/posts/2026-04-15-gophergate-and-the-ai-stack.md @@ -0,0 +1,81 @@ +--- +layout: post +title: "gophergate and the ai stack: proxies, agents, and local models" +date: "2026-04-15" +categories: [tech, ai, homelab, projects] +tags: [go, llm, ai-agents, hermes, gophergate, local-models] +--- + +it started with a billing problem. + +i was running an off-the-shelf llm proxy to route requests between providers — the kind of thing you drop into a docker compose, point at your api keys, and hope for the best. it worked. mostly. except the usage tracking was wrong. not a little wrong — *wrong* wrong. like, "i thought i'd spent $12 and it was actually $47" wrong. when you're routing traffic across xai, google, openai, deepseek, and moonshot, that kind of imprecision isn't a rounding error. it's a leak in the bottom of the boat. + +so i built gophergate. + +## gophergate: a precision gooseneck kettle for api credits + +think of gophergate like a gooseneck kettle — the kind coffee nerds use for pour-overs. a regular kettle dumps water everywhere. a gooseneck gives you exact control over flow, direction, and volume. that's what gophergate does for llm api requests. + +it's a custom proxy gateway written in go. nothing fancy — go's stdlib http server, clean routing, and an obsession with accurate token counting. every request that comes in gets routed to the right provider based on model, cost, availability, and whatever fallback logic makes sense. if openai is being flaky, it can fall back to deepseek. if you want moonshot's pricing on a particular model, it routes there. the config is straightforward — model aliases map to provider endpoints, and the proxy handles the translation layer. + +the core win is spend tracking that actually matches provider dashboards. i count input and output tokens per request, multiply by the provider's published rates, and log it. no estimating, no "we'll figure it out at the end of the month." you can see exactly what each request costs in real time. when you're running an ai coding agent that makes hundreds of calls a day, that visibility matters. + +the architecture is intentionally boring: + +- incoming request hits gophergate +- gophergate resolves the model alias to a provider config +- it proxies the request, streams the response back +- it logs token counts and cost +- if the provider returns an error or times out, it tries the next fallback + +that's it. no magic, no ai-powered routing decisions. just a well-tuned reverse proxy with a billing brain. go was the right call here — fast startup, tiny binary, stdlib does 90% of the work, and it compiles to a single binary i can drop anywhere on the homelab. + +i've been running it for a few months now and the numbers are tight. gophergate's tracked spend matches what i see on provider dashboards within a few cents. that's the kind of boring reliability i want from infrastructure. + +## the agent swap: from pi.dev to hermes + +for a while i was using pi.dev (formerly opencode) as my ai coding assistant. it was fine — got the job done, decent model support, the usual "type a prompt, get code" workflow. but "fine" has a shelf life, and mine ran out. + +i switched to [hermes agent](https://hermes-agent.nousresearch.com/docs) by nous research, and the difference is less about any single feature and more about the *texture* of working with it. hermes doesn't just answer questions — it builds up a persistent understanding of how you work, what you care about, and what you've already tried. + +the skills system is the big one. skills are like procedural memory — reusable workflows that encode how to do specific tasks. i've got skills for deployment patterns, debugging workflows, tdd enforcement, code review. when hermes encounters a task that matches a skill, it loads the relevant knowledge and follows the proven approach instead of reinventing it every time. it's like having a senior engineer who actually remembers what they learned last sprint. + +then there's mnemosyne — hermes' persistent memory system. it remembers things across sessions. not just "what did we talk about yesterday" but real operational context: which services live where, what the last deployment broke, what naming conventions we use. i can come back to a project after a week and hermes picks up the thread without me re-explaining the whole setup. + +cron jobs are another thing that surprised me. hermes can run scheduled tasks — monitoring, health checks, periodic reports. i've got a few set up to check service status and flag issues before they become problems. it's the kind of thing you'd normally wire up with a separate tool, but having it built into the agent means the agent that understands the codebase is also the one monitoring it. + +and then there's multi-agent delegation. for complex tasks, hermes can spin up sub-agents to work on independent pieces in parallel. it's not just "do this one thing" — it's "here's a plan, go execute it on multiple fronts." the parent agent coordinates, the sub-agents execute, and the whole thing converges faster than a single-threaded approach. + +replacing pi.dev wasn't a dramatic moment. it was more like switching from a drip machine to a proper pour-over — the coffee is still coffee, but the control and consistency are on another level. + +## local models: the experimental corner + +while the cloud providers power most of my daily work through gophergate, i've been poking at running smaller models locally on the homelab. this is more "weekend curiosity" than "production workflow" at this point, but it's been fun. + +the homelab has a decent gpu — nothing datacenter-grade, but enough to run quantized models in the 7b-13b range at reasonable speeds. i've been experimenting with a few things: + +- **coding assistants for quick edits** — small models that can handle "rename this variable" or "add error handling here" without burning cloud credits. they're not as good as the big models, but for simple tasks they're surprisingly capable. +- **summarization and classification** — routing and categorizing logs, summarizing long threads, tagging content. these tasks don't need frontier intelligence, and running them locally means zero latency and zero cost. +- **fine-tuning experiments** — i've been playing with lora adapters on smaller models to see if i can make them better at specific tasks in my workflow. early days, but the idea of a model that's tuned to *my* codebase is compelling. + +the trick is knowing where local models shine and where they don't. they're great at well-defined, pattern-heavy tasks. they're not great at "architect a new feature from scratch" or "debug this subtle concurrency issue." the cloud models through gophergate handle the hard stuff; the local models handle the grunt work. + +i've been using ollama to manage local models — it makes pulling, running, and switching between models dead simple. combined with hermes as the orchestrator, i can have the agent decide when a task needs the big guns and when a local model will do. that's not wired up as a formal workflow yet, but the pieces are all there. + +## the stack as it stands + +so here's where things land today: + +**gophergate** sits at the edge, routing all llm traffic. it knows about every provider, tracks every dollar, and fails over gracefully. it's the barista that knows exactly how much each pour costs. + +**hermes agent** is the brain. it's the thing i actually interact with — the agent with memory, skills, scheduled tasks, and the ability to delegate. it talks to the outside world through gophergate. + +**local models** are the experimental wing. small, fast, free, good enough for a growing number of tasks. they sit on the homelab and handle what they can. + +and underneath all of it, go and the homelab keep things running. no kubernetes, no terraform, no 47 microservices. just well-understood tools doing their job. + +the ai tooling landscape moves fast — what's best-in-class today is legacy tomorrow. but the *principles* are stable: accurate billing, persistent context, composable workflows, and knowing when a $0 local model beats a $0.02 cloud call. build for the principles and the tools can swap underneath. + +now if you'll excuse me, i need to go adjust my pour-over recipe. i think the grind is a touch too fine. + +-dustin diff --git a/content/posts/2026-06-10-coop-credits-and-the-media-economy.md b/content/posts/2026-06-10-coop-credits-and-the-media-economy.md new file mode 100644 index 0000000..6ef6351 --- /dev/null +++ b/content/posts/2026-06-10-coop-credits-and-the-media-economy.md @@ -0,0 +1,59 @@ +--- +layout: post +title: "coop credits: turning watch time into currency" +date: "2026-06-10" +categories: [tech, homelab, plex, projects] +tags: [plex, tautulli, overseerr, economy, self-hosted, matrix] +--- + +okay so this one's been brewing for a while — like a good pour-over, you can't rush it. i've been running plex for the homelab crew for years now, and the one thing that always bugged me was the request dynamic. someone wants a movie, they text me, i find it, i grab it, they say thanks. repeat forever. it's not sustainable, and honestly it's not fun after the fiftieth "can you add blade runner 2049 again" message (it's already there, kevin). + +so i built something. it's called **coop credits** — ticker symbol `$COOP` if you're feeling fancy — and it turns the one thing people actually do on plex into the thing that lets them request more: watch time. + +## the grind: how $COOP works + +the flow is dead simple. users sign in with their plex account. that's it for auth — plex oauth handles it, no extra passwords, no "forgot my password" tickets for me to deal with. once they're in, tautulli starts tracking their watch time behind the scenes. every minute watched earns credits. spend credits to request movies and tv shows through overseerr. + +think of it like an arcade. you put in time, you get tokens, you spend tokens on what you want to play. except the arcade is my server room and the games are 4k remuxes of the lord of the rings extended editions. + +## the pricing: why it scales + +here's where it gets interesting. credits aren't flat-rate. the cost of a request scales with two factors: **drive storage usage** and **episode count**. + +why? because storage isn't free, and requesting the entire 23-season run of a procedural costs a hell of a lot more than one movie. if the drives are getting full, prices go up — a gentle throttle that keeps the library curated instead of becoming a dumping ground. if someone wants a single film? cheap. someone wants all 400 episodes of law and order svu? that's gonna cost 'em. it's a little economy that self-regulates. + +## the shortcut: ko-fi integration + +not everyone wants to grind. some folks just want to request stuff now, and that's fine — i wired up ko-fi so people can buy credits directly. **$5 gets you 500 credits, $10 gets you 1000.** ko-fi handles the payment processing so i don't have to deal with any of that, and credits land in their account automatically. + +it's not about monetizing the server — it's about covering the ever-growing storage costs and giving people a fast lane when they don't feel like earning their way up. + +## the sunset: overseerr steps back + +here's a thing i did that might be controversial: i **sunsetted overseerr as a user-facing service**. it's still running, still doing the heavy lifting behind the scenes for actually processing requests — but users don't touch it directly anymore. coop credits sits in front of it now. + +the reason is simple: overseerr is a great tool but it's a *tool*. it doesn't have a concept of cost, priority, or scarcity. it's just "request button go brr." by putting coop credits in front, every request flows through the economy first. did you earn enough? can you afford this one? is the library getting full and prices are high? that context matters, and overseerr was never designed to provide it. + +so now the flow is: plex auth → coop credits dashboard → earn or buy → spend → credits talk to overseerr's api under the hood. users see a clean interface that shows their balance, watch history, and what things cost. overseerr sees requests coming in from a trusted source. everybody wins. + +## the comms: matrix via ess + +quick sidebar on infrastructure — i also deployed **element server suite (ess)** for the homelab's matrix stack. this gives us a proper self-hosted, encrypted messaging setup. why mention it here? because the media economy needs a place to live. announcements about new content, price changes, community discussion — it all happens in matrix now instead of scattered across discord and text messages. + +ess made the matrix deployment stupid easy compared to my last attempt at running synapse manually. it's got proper federation support, voice and video calling, and the encryption actually works without me babysitting it. if you're running any kind of homelab community, having a self-hosted comms layer you control is worth its weight in gold. + +## the stack: media improvements + +while i was in there plumbing coop credits together, i took the opportunity to clean up the broader media stack too. the usual suspects — plex, tautulli, overseerr, radarr, sonarr — all got updated, containerized properly, and wired into the new flow. tautulli's api is the backbone of the whole credits system, so getting that dialed in was priority one. + +the whole thing runs on docker compose, reverse-proxied, the standard homelab playbook. nothing exotic, just well-oiled. + +## the philosophy + +at the end of the day, coop credits is about one thing: making a shared media library feel like a *community* instead of a vending machine that only i operate. when people earn what they request, they watch more intentionally. when they can buy credits, they contribute to the infrastructure. when prices fluctuate with storage, the whole thing stays sustainable without me playing librarian. + +it's a little economy. it's a little weird. and honestly? it's the most fun i've had with the homelab in a while. + +pour yourself a coffee, spin up tautulli's api, and start counting minutes. the grind is the game. + +-dustin diff --git a/content/posts/2026-07-08-lobotomy-labs-when-your-homelab-needs-an-org.md b/content/posts/2026-07-08-lobotomy-labs-when-your-homelab-needs-an-org.md new file mode 100644 index 0000000..e98ad23 --- /dev/null +++ b/content/posts/2026-07-08-lobotomy-labs-when-your-homelab-needs-an-org.md @@ -0,0 +1,62 @@ +--- +layout: post +title: "lobotomy labs: when your homelab needs an org" +date: "2026-07-08" +categories: [tech, homelab, projects, ai] +tags: [gitea, github, organizations, homelab, gophergate, dumpsterchat] +--- + +the kettle's been whistling for a while, but i've been too busy wiring things together to pour. let's catch up. + +## from personal projects to an organization + +somewhere between building gophergate, shipping dumpsterchat, and wiring up coop credits, a pattern emerged: i wasn't just tinkering anymore. i was running infrastructure. real services, real users (even if those users are ~12 degenerates in a chat server named smoothbraincollective). + +so i did what any reasonable person with a homelab addiction would do: i made it official. meet **[lobotomy labs](https://git.dustin.coffee/LobotomyLabs)** — the org that now owns the chaos. + +why "lobotomy labs"? because we do unspeakable things to infrastructure so you don't have to. also because naming things is hard and this one stuck. + +## what lives under the org + +right now, two main projects anchor the org: + +### gophergate + +the custom llm proxy gateway that routes traffic across xai, google, openai, deepseek, and moonshot. it tracks spend, handles failover routing, and gives me a single endpoint for every ai-powered tool in the stack. it's the reason i can run hermes agent, grok-bot, and a dozen other llm consumers without surprise bills. + +gophergate started as a "this existing proxy is inaccurate" frustration project and turned into the spine of the whole ai stack. written in go, runs like a freight train. + +### dumpsterchat + +the self-hosted discord-like platform that's been my biggest build this year. go/chi backend, vite/react/tailwind frontend, websocket real-time messaging. threads, forums, calendar channels, docs, moderation tools, role-based permissions with bitflags. all running on a proxmox lxc container that costs me roughly nothing per month. + +the full breakdown is in its own post, but the short version: building your own chat platform is simultaneously the dumbest and most rewarding thing you can do with a weekend. or twelve weekends. who's counting. + +## why an org matters + +it's a small thing, but it changes how you think about projects. when dumpsterchat lived under my personal gitea account, it was "dustin's side project." under lobotomy labs, it's a thing with a name and a home that isn't just my brain. + +it also sets up the future: if friends want to contribute, they have a place. if i spin up new services (and i will, because i apparently can't stop), they have a home that isn't buried in a personal repo list. + +## the ai stack update + +since the last post, the ai toolkit has evolved significantly: + +- **hermes agent** by nous research has replaced opencode/pi.dev as my primary coding assistant. it's got a persistent memory system (mnemosyne), a skills framework for reusable workflows, cron job support, and multi-agent delegation. it remembers what we worked on last session. it's like having a senior dev who never forgets context. +- **gophergate** continues to be the routing layer for all of this. every ai call goes through it, gets logged, gets tracked. +- **local models** are getting more viable. smaller instruction-tuned models running on the homelab handle quick tasks without hitting external apis. + +## what's brewing next + +- **lobotomy labs website** — probably a simple landing page that links to the projects and the git org. +- **gophergate open source** — the codebase is close to presentable. a few more docs and it goes public. +- **dumpsterchat phase 6** — voice channels are on the roadmap. because apparently text chat isn't enough chaos. +- **more infrastructure surgery** — the homelab never stops growing, and neither does the list of things to automate. + +the org is small now, but it's a foundation. and in the homelab world, foundations are what you build everything else on top of. + +thanks for reading. if you're running your own lab and haven't organized your projects into something coherent yet, maybe consider it. it's a small move, but it clarifies a lot. + +what's brewing in your setup? drop a comment or reach out. + +-dustin