<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Chris Kirby on Medium]]></title>
        <description><![CDATA[Stories by Chris Kirby on Medium]]></description>
        <link>https://medium.com/@sirkirby?source=rss-8c693b99d86a------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*3f58TbE8hVMlAmOZY0xfig@2x.jpeg</url>
            <title>Stories by Chris Kirby on Medium</title>
            <link>https://medium.com/@sirkirby?source=rss-8c693b99d86a------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 15:21:26 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@sirkirby/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Myco Cortex — lifecycle-driven project intelligence for your agent harness]]></title>
            <link>https://medium.com/@sirkirby/myco-cortex-lifecycle-driven-project-intelligence-for-your-agent-harness-d8d9bd2abaae?source=rss-8c693b99d86a------2</link>
            <guid isPermaLink="false">https://medium.com/p/d8d9bd2abaae</guid>
            <category><![CDATA[agentic-ai]]></category>
            <category><![CDATA[open-source]]></category>
            <category><![CDATA[ai-agent]]></category>
            <category><![CDATA[agent-harness]]></category>
            <dc:creator><![CDATA[Chris Kirby]]></dc:creator>
            <pubDate>Mon, 08 Jun 2026 12:04:53 GMT</pubDate>
            <atom:updated>2026-06-12T12:16:00.772Z</atom:updated>
            <content:encoded><![CDATA[<p><a href="https://chriskirby.net/tag/ai-agents/">AI Agents</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*2t6uHi-jRiRpK2JQ.png" /></figure><p>This is the second post in a series discussing my research and development into solutions for building better, faster, higher-quality, and more secure code with any agent harness, solo or with a team. Before we dive in, let’s briefly reflect on how we’ve traditionally approached this and look at how some companies and teams are adapting with agentic AI. Over the years, we’ve developed all kinds of processes, frameworks, organizational structures, and team roles to solve for the better/faster/quality challenge. Agile software development, 2-Pizza teams, EM’s, reporting to Senior EM’s, reporting to Directors, Staff and Principal engineers, with TPM’s, PM’s driving and supporting. Now, in the agentic era, companies are experimenting with compressed processes, dropping ceremonies, flattening organizational structures, and widening team roles, emphasizing reasoning and architectural skills with a generalist scope. This shift in how we, software engineers and engineering leaders, work fundamentally changes how we think about product knowledge, codebase knowledge (sometimes called tribal knowledge), and even code quality and automation. Skilled agentic practitioners are not writing the code; the models are very good at that now. They are applying patterns, rules, skills, and procedures to make critical architectural decisions. Your role now is to think through and around solutions, as Models will fixate on patching and narrow scope. You must think in patterns and architecture, whereas models will only seek what they consider the most efficient solutions. Combining the agent’s reasoning with your own to develop a complete solution. Now you add a multiplier to that as you’re driving several threads at once and almost unlearning what you spent a career mastering: deep focus, long mental debugging sessions, and even careful architectural planning. We now must keep those skills, set them aside, and master moving in and out of product context, spec building, rapid decision-making, continuous review and rework cycles, and, with that, codifying those practices so agents can work on your behalf autonomously. Now do all of that with a team, teams of teams (humans and agents), with improved quality, security, and release cadence. For companies all-in on agentic AI, this is the reality now, and it’s not one most are prepared for.</p><p>This is a hard problem, and I love hard problems like this. There are so many AI Influencer YouTube videos that say, “Solved it!” “Do this to 10x!” “This skill changes everything!” There is, of course, truth to some of it, even though it reads like click bait. It’s a puzzle everyone is trying to solve, with the pieces changing daily. Harnesses are improving their ability to organize and retrieve memory; they are also advancing their own system prompts, increasing context window size and efficiency through caching, improving compression, and getting faster while “reasoning” more. We layer into that our rules (AGENTS.md), skills, and tools, which the agent will “re-learn” each and every session, like an operating system you boot up, do a series of tasks, shut down when done, and repeat. Agent sessions are ephemeral; treat them that way. Now, I don’t see this as a bad thing; it’s actually incredibly powerful if you understand this and focus on working with it rather than forcing old patterns into this new agentic world. Modern harnesses are highly extensible, with a full set of lifecycle hooks, protocols for standardized tool access (MCP), native exploration and execution tools, and native workflows such as planning mode and code reviews. My goal with Myco is to enhance and augment the already powerful coding harness. A fun example would be something like Spider-Man’s suit (The Tony Stark version). Without the suit, Peter Parker is still Spider-Man, but with the suit, he’s faster, stronger, smarter, and more resilient. So can we tap into all those senses and enhance them? If so, can we build faster, smarter, and more reliable solutions, too? That’s the hypothesis for Myco’s Cortex features, which serve as the connection to those senses.</p><p>In my <a href="https://chriskirby.net/from-memory-to-intelligence-building-at-scale-with-agentic-ai/">first post</a>, I talked about data capture. <a href="https://github.com/goondocks-co/myco/blob/main/docs/symbionts.md?ref=chriskirby.net">Capture in Myco is automatic</a> and universal. If <a href="https://myco.sh/?ref=chriskirby.net">Myco</a> is installed and you start a supported harness, Myco will provision your project locally and begin capture immediately in the background, with zero-touch configuration. Data capture in this context is the work being done by your agents, all of their reasoning, all of your initial prompts and steering prompts, and all of the tools being used and their results. This telemetry is the foundation for the enhanced nervous system we want to build. So let’s talk about what Cortex is, how it works, and see it in action with real sessions driving real outcomes.</p><h3>Myco Cortex</h3><p>Cortex is a collection of features in the Myco package designed to provide your agent harness with instructions, project context, and codebase knowledge in real time as the agent works and you interact with it. I’ll break down each of its components, how it works, along with where and how it integrates into your harness’s lifecycle.</p><h3>Injection lifecycle</h3><p>Most harnesses offer points in the lifecycle where plugins and integrations can inject relevant information into the session context. The most common points are on Session Start, Subagent Start, after you submit a prompt, and, more rarely, before a tool is executed. The most popular, Claude Code and Codex, support all of them, but you’ll see broad support for the first 3, including open-source harnesses like OpenCode and Pi, and in the enterprise with Copilot and Antigravity. See the full list at <a href="https://myco.sh/?ref=chriskirby.net">myco.sh</a>.</p><h3>Instructions</h3><p>When enabled, Cortex will automatically inject a compact set of instructions to inform the agent of its enhanced nervous system, explain what it can do and what you can do with it, and provide a quick sit-rep. These instructions are fully generated by the Myco Agent harness (more on that in an upcoming post) to ensure they’re always accurate. Here is a live example from the Myco project itself, where I dogfood Myco, and another from my <a href="https://github.com/sirkirby/unifi-mcp?ref=chriskirby.net">unifi-mcp</a> project. You can see that the content is largely the same, since it is generated by the same harness using the same prompts and tools, with only recent workstreams varying.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*mbYT1dJU9Yhuwtic3uSx6A.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vvZ-OygAu65Ac-1TUhlJVA.png" /></figure><p>Instructions can also be used with subagents and team agents. Often, when doing complex work with your harness of choice, it may choose to spawn subagents. This is a very effective pattern when building large implementation plans or any set of scoped work. It’s also effective for context management, as each subagent will operate with its own process and context. Since it operates in a fresh context, it will have only the information provided by the primary or orchestrating agent in its initial prompt. Myco will still collect all work performed by this subagent; however, the subagent will not know about Myco explicitly. For harnesses that support this injection point, we simply provide the subagent with the same instructions (slightly tweaked), so it too can choose to tap into the project intelligence layer. For those harnesses without this (about 50/50 of the popular ones), we also have a short paragraph in the primary agents’ instructions that tells them to enhance their subagent prompt with Instructions. Myco may also tailor some content to specific agents. For example, here is a recorded injection for Codex, where we asked it to start working on a plan built in another session:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*u1LMOk3V4yeww36G.png" /></figure><p>There are quite a few things happening here, which can give you a sense of how the intersection of knowledge, tools, context, and planning can work symbiotically between Myco and your agent harness. I’m starting the session with a built-in skill, which allows me to seamlessly handoff a plan from another session (captured with myco using harness native planning), it then tells Codex, “hey you don’t have MCP for these tools; you should use the CLI”, which is customized for Codex (which supports MCP, just not for myco, as we cannot determine project tenancy from the global mcp server install), then all the tools, sit-rep, what branch they are on, and its session id. As part of the handoff, the plan may also tell the agent to load recommended skills (like using-superpowers). It then consults its own memory, grabs the plan from myco, and gets to work. Oh, it did a great job too btw 😉</p><h3>Spores</h3><p>Spores are the living knowledge of your project. They are created and maintained by the Myco Agent harness and by the coding harness you are using. They represent active decisions, gotchas, discoveries, and bug fixes. As themes and groupings start to emerge, Wisdom spores are created. Similar to us humans, Wisdom is gathered from experience…three different angles of the same gotcha? We are wise to it now, never again. Spores can be active, be superseded by new or updated Spores, and then become obsolete. Spores are the collective knowledge and history of working on and building your project. You can search for them semantically via a local vector store, and agents can find and access them through tools. In Cortex, semantically relevant Spores are automatically injected into the session context after you type your user prompt, providing your agent with the wisdom it may need to be more effective. Let’s see this in action! This is a session I started yesterday to figure out why Myco’s MCP install for Codex was failing to connect.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ITvduY_jaulmyrObyfk8Zg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*HF-X2S_WuT9dsgY9kSTjiw.png" /></figure><p>This is a Claude Code session. I’m starting with a basic debugging investigation project with an example screenshot from the Codex CLI throwing connection errors related to our MCP server. I also lazily just pasted in my notes, as the prompt could have been better, but that’s kind of the point: myco fills in the gaps for me. Claude gets the instructions, and then it gets some Spores. This was a sub-second search against the SQLite vector store (all spores are automatically embedded when created or updated) based on my prompt. Myco applies a basic algorithm to determine the relevance of the search result, and if it clears that, it is then injected back into the session context. You can see by the Spores injected that this is not the first time we’ve had these issues (I actually forgot). We have some Wisdom from an earlier session: Codex, based on how it’s launched, may not pass along knowledge of which project it’s working on. We then have more Wisdom regarding the MCP stdio bridge, when it was missing authentication, so something for Claude to check. Finally, notes on the MCP server not surviving daemon restarts during a live session (this was solved a while back). So all relevant experience to the task at hand with a rich set of Spores and session references for Claude to investigate, along with its own native tool calls. Spore content can be rich and detailed (as shown), so we provide the agent with a brief overview and a reference to retrieve more details. The goal is the highest relevance with the fewest tokens.</p><h3>Digest</h3><p>The Cortex Digest is an actively curated and maintained set of compressed project knowledge that agents, or humans, can use to onboard quickly, possibly circumventing the need for lengthy manual exploration and discovery. There are three tiers. T1500 “Executive Briefing”, T5000 “Deep Onboarding”, and T10000 “Institutional Knowledge”, where T{Number} represents the amount of tokens the Myco Agent targets when writing and maintaining them. This is a very rich source of knowledge that remains on tap at all times for the agent to access via the Cortex tool, and it can also be automatically injected into your session context if you opt in. This can be used in combination with Instructions for rapid onboarding for one-shot prompts or in place of instructions to leverage the knowledge, but let your harness lean on its native tooling instead of being biased towards Myco.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*KKI_AwFKtMRubYfZ.png" /></figure><h3>Canopy</h3><p>Canopy is your project’s live code index. It maps your entire codebase, analyzes all relevant project files, describes each file, and embeds that metadata (not the file’s contents) into the local vector store for easy retrieval and injection. Like all Cortex features, this is not designed to replace the coding harnesses’ native code exploration tooling; it’s meant to enhance it.</p><p>Let’s start with the Canopy Map. The map is the context-rich cheat sheet for coding harnesses to quickly orient themselves to the project. Rather than general exploration, they can reach the target area after a single tool call that tells them where to go. It’s not just a directory tree; it provides high-level structural guidance, but more than that, it offers semantic knowledge of those files. Not just where the API is, but what it is. You have a GraphQL and REST API located in apps/api; here are the key areas to pay attention to, along with key files in those sections. Updating your CI workflows: where the workflows are and what each one is responsible for. Working on architectural patterns? Here is what’s in use today and how it fits together. Adding a feature? Here is what a good feature looks like.</p><p>The instructions tell the agent about the map, why and when to use it, and in my experience, they will use it more often than not, getting the solution faster. Maps are generated by the Myco Agent from the live code index, Spores, and actual project contents. You had two sessions today. When complete, the Agent gets to work reasoning, distilling, and updating your Map so that it remains current for your next session. The best way to understand it is to see it. This is the full and complete live Map Myco generated for the <a href="https://github.com/sirkirby/unifi-mcp?ref=chriskirby.net">unifi-mcp</a> project</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f7d40b6c432d5ded503f834bb15c53ce/href">https://medium.com/media/f7d40b6c432d5ded503f834bb15c53ce/href</a></iframe><p>The above Map is, in part, generated from the Canopy Entries. Entries are the files in your project, but Myco only captures the important bits. We don’t need to ingest the file’s contents; your agent will handle that, and it’s always changing anyway. We want to know where it is, what kind of file it is, and what the file is for. This, along with other metadata, is then stored in the local database and embedded for semantic search. For example, when a file is first scanned or its contents change, the Myco Agent harness will “describe” the file in 1–2 sentences and store that description along with its metadata. The file apps/network/src/unifi_network_mcp/runtime.py has the following description &quot; <em>Provides the UniFi‑Network MCP server&#39;s core singletons-config, FastMCP instance, and manager helpers-and exposes lazy getters for testable substitution.</em>&quot; ...yep, that&#39;s what it does.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OfzNNdmfvzt0A4gm79vgvg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2SwJ6ybcQRJPIGeSZeWRXQ.png" /></figure><p>Now, for Agent harnesses that support it, we can also use canopy data to inject it back into the context before a file is read, allowing the Agent to skip the read and save the tokens. Canopy tracks this as token savings, which not only can improve the speed of your work but also save you some money. Let’s now see how Entries and Map are used in a live session. This is a recent session for <a href="https://github.com/sirkirby/unifi-mcp?ref=chriskirby.net">unifi-mcp</a>, the same session from earlier in this post, where we are investigating some API changes in the UniFi Alarm Manager and updating our mutating tools based on that investigation. This is a complex task; we are navigating legacy private API’s and a new V2 api surface, abstracting that knowledge from the tool surface and grounding this work in real data gathered from Playwright, and applying that knowledge using established patterns that will be fully tested, unit and smoke, without introducing regression. aka, product development and software engineering. To see it in action, let’s look at my first prompt again, which, if you remember, was a plan handoff from another session that Myco will facilitate. After the agent finishes reading and updating the plans (there are 4 of them), it orients itself by requesting the Map, decides what to do first, then pauses for a Human-in-the-Loop to proceed (as instructed by the handoff skill), and the work begins.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*r82O5R296MtqonACJ54dSA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Svvtds6vYkfaSX0y_sUUkQ.png" /></figure><p>Codex, in this example, calls for the Map 4 times throughout the session. Myco also opportunistically injects canopy entry context while Codex is actively exploring files. As you can see above, we provide metadata, file imports/exports, and a description, along with a note encouraging the agent to skip the full read if they have what they need. For this session, an estimated 42k tokens were saved through agent read skips. This is rough and not precise; it also does not yet account for Map reads and exploration tokens saved. We’ll dial this in as it continues to prove useful. Canopy never prevents a read and aims to be as efficient as possible, which in this case is estimated at 10x efficiency.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/856/0*Jhg-3g2CDvFpd_4L.png" /></figure><h3>Wrap up</h3><p>Give your smartest engineer the most complex work on an existing project they’ve never worked on, and tell them they have an hour to build, test, and ship it. They know how to code anything, in any language, using any pattern. They have no idea what language the project is in, its patterns, its rules, or, more importantly, why that language, those patterns, and those rules. It’s almost silly to write that, but it’s true. Every time you fire up the harness, your smartest do-anything engineer, this is the reality. Nothing you do today, including all of this, will teach your agent anything, nor will it remember anything… and if you happen to fill that 1M context window, it likely won’t recall an hour ago. Those of us using these tools know this, and there are ways you should use these tools and ways you should not, if you care about high-quality outcomes. I don’t focus on what it can’t do, but rather on what it can do and is good at. It’s good at code exploration; give it a map. It’s curious and seeks why; tell it how to find out. Same for humans. The prompt isn’t perfect; improve it with wisdom. You get it. Cortex is the result of the Myco Symbiont integration system, data capture, FTS, semantic search, MCP server, and the custom Myco Agent harness. So there is more to share and see over on <a href="https://github.com/goondocks-co/myco?ref=chriskirby.net">GitHub</a>. May you forever have double usage on your Max plan. See you in the next post.</p><p><em>Originally published at </em><a href="https://chriskirby.net/myco-cortex-lifecycle-driven-project-intelligence-for-your-agent-harness/"><em>https://chriskirby.net</em></a><em> on June 8, 2026.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d8d9bd2abaae" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[From memory to intelligence — building at scale with agentic AI]]></title>
            <link>https://medium.com/@sirkirby/from-memory-to-intelligence-building-at-scale-with-agentic-ai-5a31ee41a97d?source=rss-8c693b99d86a------2</link>
            <guid isPermaLink="false">https://medium.com/p/5a31ee41a97d</guid>
            <category><![CDATA[agentic-ai]]></category>
            <category><![CDATA[agent-memory]]></category>
            <category><![CDATA[agent-harness]]></category>
            <category><![CDATA[open-source]]></category>
            <dc:creator><![CDATA[Chris Kirby]]></dc:creator>
            <pubDate>Thu, 16 Apr 2026 13:05:00 GMT</pubDate>
            <atom:updated>2026-06-08T20:30:34.221Z</atom:updated>
            <content:encoded><![CDATA[<p><a href="https://chriskirby.net/tag/ai-agents/">AI Agents</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*AB5x2sX5vnamiZBR.png" /></figure><p>In my previous post, I went in depth on the issue of agentic memory and how to address it when working with multiple agents locally and with team members who are also using multiple agents, while trying to preserve institutional knowledge. <a href="https://chriskirby.net/solving-the-groundhog-day-problem-in-ai-software-development-introducting-oak/">OAK, was a project i worked on</a>, starting late last year, to start to understand and solve these problems for professional developers and teams. Much of the research and development that went into OAK was rooted in the idea of comprehensive data collection. Can we reliably collect rich data from users, coding agent sessions, and then try to pull meaningful memories from them? And then can we make those accessible via semantic search that’s easily accessible to agents and users alike? Spoiler: the answer is yes. While not trivial, certainly possible and becoming more so as these agents mature. There are many projects out there doing some of this well. Many focused on single-agent ecosystems; however, the premise is consistent. Keep as much context resident with your project as possible to make future agent sessions more successful. This is so critical that agents themselves ship comprehensive memory systems, such as Claude Code’s undocumented dream feature. Which automatically recognizes key concepts, follow-ups, and user cues, and curates them to the local file system as a series of markdown documents. Or just search on the dozens of projects based on <a href="https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f?ref=chriskirby.net">Karpathy’s wiki for building personal knowledge bases</a>. Memory is table stakes.</p><p>Over the several weeks, my interest in this subject hasn’t dwindled; it’s only gotten stronger. OAK was fun and challenging to build. However, where it started (an SDD toolkit) and where it ended up led to a high level of code complexity, with features that were a little disjointed and an ecosystem that had evolved. I also had new ideas I wanted to explore, and since they were so fundamental to the core architecture, it made sense to start fresh, so I began building <a href="https://myco.sh/?ref=chriskirby.net">Myco</a>. Over the next several posts, I’m going to discuss the features of Myco, the problems I think are worth solving, and how you and your team could benefit from either this project or these ideas as you build moving forward.</p><p>Let’s start with the name. Why Myco? First, I love themes. It’s just more fun that way. And second, the previous metaphor: OAK “strong” and memory like the rings of a tree, now moving to a more biological metaphor: Myco or mycorrhizal networks, is a more apt mental model. We have spores, akin to memories and concepts. Symbionts, which combined with you, are the originators of knowledge (agents, skills, prompts, summaries, plans). Digests, which are produced by the Myco agent as it consumes spores and synthesizes raw data. This then gets fed back into the Symbionts, and the cycle continues. It’s a living intelligence right inside your project, changing and evolving as you build. See, I told you I like themes 😄</p><h3>Setup and Collection</h3><p>Symbiont’s (aka coding agents). This is the Claude Code session that you’re using to build. We want to understand everything you and Claude are doing and inject relevant intelligence back into the context to ensure that each session, short or long, maintains a consistent, evolving understanding of your code, the project, and what it’s doing. And when you open Codex alongside to make sure Claude’s solution is sound, it starts with the same understanding, and its results add to the collective intelligence, which Claude can then benefit from. Most builders use multiple agents, not just one, so Myco’s data collection and integration are comprehensive. Use Claude, Codex, Cursor, Copilot, Antigravity, Windsurf, Pi, and opencode in the same project.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8174fea2dc4408aa02025207bff3cc85/href">https://medium.com/media/8174fea2dc4408aa02025207bff3cc85/href</a></iframe><p>Setup is simple. It’s going to install the myco NPM package, set up a service to host the daemon locally, and establish a .myco directory in your user home. Any supported coding harnesses you have installed will be automatically detected and configured for data collection and intelligence integration via hooks, plugins, transcripts, and local MCP connectivity to access the myco tools. Your project will be automatically registered on your next session, post-Myco install. Simple, easy, and automatic.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*yfc2q_QAqmzlWHRm.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*vwfV4BMa92R-mvIr.png" /></figure><p>Here’s what’s going on at a high level:</p><ul><li>You start a new session in Claude, and through its lifecycle hooks, we can identify that session.</li><li>You submit a prompt. Claude kicks off a series of work on your behalf, including all tool calls, code exploration, skills loaded, MCP tools used, how it accessed them, and the results returned. We capture it all.</li><li>Finally, wrapping up with the summary from the agent. This completes the turn.</li></ul><p>This general pattern is applied to each Symbiont you enabled to ensure consistent, uniform collection as you switch between them. Some are also enabled for advanced capture, which leverages the agent’s transcript or hook patterns to collect things like screenshots that you’ve added or plans generated from plan mode or skills like /superpowers specs and plans. SDD gets captured here, too. No need to keep and maintain endless markdown files and artifacts in your repo. This is all stored locally in your myco project’s SQLite database and accessible via the web interface and to your agents via MCP.</p><p>Now, that’s pretty cool in and of itself, but it’s just the start. This is when myco really gets to work. In the next post, I’m going to do a deep dive on the Myco agent, which is a <a href="https://github.com/goondocks-co/myco/blob/main/docs/agent-harness.md?ref=chriskirby.net">purpose-built agent harness</a> that drives the intelligence cycle. The agent has specific tasks to perform. Some are as simple as setting the session title and generating a summary, and as complex as building the edges of a graph to interconnect concepts, spores, plans, and sessions. Here is a preview:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5gg3IWgVH6mrUbQctQGrXw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*fO_PLPYS_HaK4IY0IzM_DA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LYaLapJcRWlGJmGH76F1eA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ip0Y1Bmvlrv7ldG2JYQyXw.png" /></figure><p>So stay tuned for the Myco Agent deep dive, followed by Teams and Collectives. Myco is in active development, so try it out for yourself. If you find a bug or have a suggestion, engage with me over on <a href="https://github.com/goondocks-co/myco?ref=chriskirby.net">GitHub</a>. See you there!</p><p><em>Originally published at </em><a href="https://chriskirby.net/from-memory-to-intelligence-building-at-scale-with-agentic-ai/"><em>https://chriskirby.net</em></a><em> on April 16, 2026.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5a31ee41a97d" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Solving the “Groundhog Day” Problem in AI Software Development: Introducing OAK]]></title>
            <link>https://medium.com/@sirkirby/solving-the-groundhog-day-problem-in-ai-software-development-introducing-oak-d291fc5252da?source=rss-8c693b99d86a------2</link>
            <guid isPermaLink="false">https://medium.com/p/d291fc5252da</guid>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[claude-code]]></category>
            <category><![CDATA[cursor-ai]]></category>
            <category><![CDATA[agentic-ai]]></category>
            <dc:creator><![CDATA[Chris Kirby]]></dc:creator>
            <pubDate>Sun, 15 Feb 2026 14:00:27 GMT</pubDate>
            <atom:updated>2026-02-22T16:38:33.115Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*SFIGcmCloVIq4NUj.png" /></figure><p>If you read my previous post on <a href="https://chriskirby.net/the-joy-and-agony-of-building-with-ai-agents/"><em>The Joy and Agony of Building with AI Agents</em></a>, you know I’m all in on agentic workflows. Being able to architect a feature and have the agent build it is a superpower. But that was just the start.</p><p>Over the past 3+ years, I have been working with AI-generated code, and around 2 years into working with coding agents, much has changed. Capability, model quality, speed, and tooling have all improved dramatically; however, some core challenges remain, and new ones have emerged. The new challenges, especially, have been an interesting avenue of research for me.</p><p>As these tools are now geared towards professional software development within businesses and enterprises, those of us who do this for a living are rethinking everything, from how we build teams to how we budget to how we estimate to the entire software development lifecycle. When we, the humans, are no longer the ones writing the code, this fundamentally disrupts the way we’ve done these things for the past 20 years.</p><p>We have to think beyond the hyperbole and grand claims of job replacement and start thinking pragmatically. Now, we’re not going to cover the whole industry in this post, but I do want to talk about some practical ways that we can integrate agents and agentic workflows into the teams that we’re in today. And alongside them have tools that solve real problems, don’t get in the way of the rapid innovation, and genuinely offer something new and useful.</p><h3>The “Groundhog Day” Problem</h3><p>The most immediate friction point in this new lifecycle is what we call the “Groundhog Day” effect.</p><p>You spend an hour teaching an agent <em>why</em> we structure our API responses the way we do. It nods (metaphorically), writes great code, and you close the session. The next day, you spin up a new agent for a related task, only for it to completely ignore yesterday’s architectural decision. Why? Because that context vanished the moment the session ended. This is not an indictment of your prompting skills (well, mostly 😄) but rather a fundamental limitation of the technology itself.</p><p>Git captures the code, but it doesn’t capture the <strong>story</strong>. It doesn’t capture the trade-offs, the “gotchas,” or the architectural plans we discussed. We are left with a diff that lacks intention…lacks soul.</p><h3>Why “Just More Prompts” Isn’t the Answer</h3><p>Before building a solution, I tried to solve this manually. I maintained massive context.md and prompt.md files. I meticulously updated .cursorrules and CLAUDE.md. Asked the agent to update the docs, keep the readme current, save the plan to docs.</p><p>But here is the hard truth: <strong>If a process requires manual discipline to maintain, it will eventually fail.</strong></p><p>In the heat of a debugging session, you stop updating the rules file. Your custom agent drifts from the actual architecture. We need something that works <em>for</em> us-an automated background process that brings it all together.</p><h3>Enter Open Agent Kit (OAK)</h3><p>I built <a href="https://openagentkit.app/?ref=chriskirby.net"><strong>Open Agent Kit</strong></a><strong> (OAK)</strong> to be the “flight recorder” for this new era of development. Many agents, working on many things, with many developers, in a single project.</p><p>OAK sits quietly in the background while you work with tools like <strong>Claude Code, Cursor, Windsurf, Codex, OpenCode, CoPilot,</strong> or <strong>Gemini</strong>. It automatically captures the plans, decisions, and trade-offs that usually vanish. Then, crucially, it <strong>injects that context back</strong> into your future sessions…and much more.</p><h3>The “Tower of Babel”: Solving for Teams</h3><p>If “Groundhog Day” is the pain of working alone, the “Tower of Babel” is what happens when you bring a team into the mix.</p><p>In a modern engineering team, I might be using <strong>Claude Code</strong> to scaffold a microservice. My lead engineer is refining the frontend in <strong>Cursor</strong>. Another dev is writing tests with <strong>CoPilot</strong>. We are all committing code to Git, so the <em>files</em> are in sync. But the <em>brains</em> are not. This is not a new problem, but rather an amplified one in this new era of software development.</p><p>OAK includes backup and team sync capabilities that allow you to import session data from your teammates. This creates a form of <strong>contextual osmosis</strong>. When I synchronize and pull in the team’s session history, my local agent suddenly “knows” why you chose that specific implementation last week. It could prevent the junior dev’s agent from hallucinating a solution that breaks the senior dev’s architecture.</p><h3>Privacy First: The Local Advantage</h3><p>If you read my articles on <a href="https://chriskirby.net/tag/homelab/">Home Lab</a> or <a href="https://chriskirby.net/tag/privacy/">Privacy</a>, you know I don’t take “just send your data to the cloud” lightly. And it’s not just personally, I think businesses need to take this seriously as well. Local also helps keep costs down. My $5,000 MacBook Pro can do a lot more than browse web pages. Fully leverage your investment and save on AI API costs.</p><p>OAK is designed to run locally, per project. The daemon runs on your machine. The index, telemetry, and inteligence lives on your machine with your project. When we talk about team sync, we aren’t talking about uploading your data to a mystery SaaS API. You control the data flow.</p><p>It uses <strong>AST-aware semantic search</strong> to index your code locally. When an agent asks, “Where is the auth logic?”, OAK finds it conceptually, even if the file is named login_manager.py.</p><p>It uses local LLM providers that run open-source models, such as gpt-oss, gemma, deepseek, and qwen. Size the models for your hardware, and OAK does the rest. Inference happens in real-time while your agents are working.</p><h3>Getting Started</h3><p>I’m a fan of tools that are easy to deploy, upgrade, and maintain. <a href="https://openagentkit.app/features/codebase-intelligence/getting-started/?ref=chriskirby.net">Getting OAK running</a> takes about 30 seconds.</p><ol><li><strong>Install the CLI.</strong> I recommend using Homebrew on a Mac, or our install scripts, which will handle and guide you through the pipx or uv install for you on Mac or Windows:</li></ol><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b0ba47872b16d7885cf57bfb8fbf1abf/href">https://medium.com/media/b0ba47872b16d7885cf57bfb8fbf1abf/href</a></iframe><p><strong>2. Initialize your project. </strong>Open your <a href="https://app.warp.dev/referral/EJK58L?ref=chriskirby.net">favorite terminal</a> and navigate to your repo, and run init. This interactive mode lets you select your agents and languages. Run again any time after to adjust.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8039587c35ff131b70196246c6752ef1/href">https://medium.com/media/8039587c35ff131b70196246c6752ef1/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dK3rJ2IDE0475j1QAY_97Q.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4pegoZ7_EGCTJnCPfeFnoA.png" /></figure><p><strong>3. Launch the Dashboard.</strong> Start the daemon and pop open the UI to start working with OAK:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/428c1a6665ad3d5382010d504f3ee037/href">https://medium.com/media/428c1a6665ad3d5382010d504f3ee037/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*8MAscM6F1Ryugo8g.png" /></figure><p>This takes you to the local web interface for your project, where you need to complete the final configuration step: <a href="https://openagentkit.app/features/codebase-intelligence/configuration/?ref=chriskirby.net">setting up your local models</a>. You will need something to run those models locally, and any OpenAI-compatible provider will work, though I recommend <a href="https://ollama.com/?ref=chriskirby.net">Ollama</a> or <a href="https://lmstudio.ai/?ref=chriskirby.net">LM Studio</a>. Then you’ll need to pull at least one text embedding model and one general-use LLM. I highly recommend viewing the included help docs for a complete walkthrough, but a very basic setup would look like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/cd356ce9955f456cd862b6c97ad58a97/href">https://medium.com/media/cd356ce9955f456cd862b6c97ad58a97/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hg8g7pxScRTYtlSnrVUwuw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-BqmIaopuPqWVR9cR6d4FQ.png" /></figure><p>OAK is now running in the background, indexing your code, and listening. The next time you fire up Claude, Cursor, OpenCode, etc, OAK will be there. Now on to the good stuff. Keep reading for a deep dive into what OAK can do today and where it’s going in the future.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/860/1*mR8rh1h8ZEjvfMuipEmG-w@2x.png" /></figure><h3>Activity &amp; Semantic search: The “Flight Recorder”</h3><p>Once OAK is up and running, the Dashboard is your first stop. This gives an at-a-glance view of all OAK activity. Quick stats like Files indexed, total Memories, Session, and Plans, along with System Health and recent Session.</p><h3>Search</h3><p>Oak maintains a local vector database in the background, which powers our semantic search across agent sessions, memories, plans, and the current source code. All new activities processed by Oak are embedded in real time and available for you to search via the UI and the agent via the MCP server and skills. This is an incredibly fast and powerful way to get the relevant context quickly. For example, I use OAK to build OAK, so I search for “team sync” across all categories, only with high confidence.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*WJWqX_1PS85izrFw.png" /></figure><p>Let’s just quickly reflect on what I just did. Now, I have over 230 agent sessions across Claude, Cursor, Codex, and others. Over 83 plans, actual planning sessions with agents that generate plans, e.g., spec-driven development. Over 5k memories, and over 500 code files. And in less than 1 second, my agent and I can get to the most relevant context and content. Then I drill in, read my plan, view the complete session that generated it, and browse to the actual code.</p><p>Now, under the hood, without getting too into the weeds, for that, jump over to <a href="https://github.com/goondocks-co/open-agent-kit?ref=chriskirby.net">GitHub</a>, let’s talk briefly about how this content is getting created.</p><p><strong>Code</strong>. I’m using AST-based chunking, which preserves the syntax of your code as it was meant to be understood, and combines it with vector embeddings, allowing you to search by concept rather than keywords.</p><p><strong>Memories</strong>. These are observations Oak will make in real time using captured agent activity. e.g., your prompts, tool calls, plans, and agent responses. Then, prompting the local LLM to classify and reason about them.</p><p><strong>Plans</strong>. Markdown plans are captured from plan mode in Claude, Windsurf, Cursor, CoPilot, and other apps that support it. OAK will store this, associate it with the agent session to link the spec to the work, and finally, with the outcome.</p><p><strong>Sessions</strong>. OAK generates and embeds a session summary, which offers an efficient way to find relevant sessions. Sessions themselves could be long and dense, with dozens of prompts, hundreds of activities, and one or more plans. The session summary compresses all of that, and then you can drill into the details.</p><h3>Sessions</h3><p>This is just what it sounds like. I fired up Claud Code, gave it a prompt, and we got to work. The moment you do, OAK gets to work, recording your prompt (save all that fancy prompt engineering), all the work the agent is doing, bash, grep, sub agent exploration, file reads/edits, and finally the agent response summary when work is complete. We call that a prompt batch, which is just one chunk of work, with a session consisting of many. Sessions also have lineage. Complex work that may start with a plan, be executed by an agent team or sub-agents, and then tested and verified, can consist of many Claude code sessions. Claude itself will offer to clear context after a plan and auto-compact context, so that a fresher context can result in a new session. OAK can identify this and automatically link those sessions together. And when that can’t be detected, you can manually link them, and OAK will also suggest related sessions to link in the UI, based on conceptually similar summaries. Here is a meaty session from recent OAK work that illustrates these concepts well.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*rLXGg0K29JlAfDOpieUQkw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BeYnfCNKuyQGxSiis6Ws5A.png" /></figure><p>The above sessions show me working on a recent overhaul of the memory and observation system in OAK. The initial design was very useful, but also quite simple. This work was about adding the ability to “observe” whether a memory was no longer relevant or had been superseded by a new one, essentially building in some wisdom, if you will. Unlike raw history, memories should evolve; what was once true may no longer be, or we may know more now, making memories more detailed. As you can see, this was not easy, and it’s still evolving. Let’s just highlight the stats. <em>Three</em> Claude code sessions, <em>37 prompts</em>, over <em>2,000 activities</em>, and <em>2 plans</em>, each built by an agent team with <em>5 or more agents per team</em>. Super easy to remember, right? Oh, your team member did it? I’m sure they explained it to you 😄. OAK’s got your back.</p><h3>Plans</h3><p>Plan mode is awesome, and you should be using it with your agent, and if your agent doesn’t have it, switch to one that does. I would say that, for me, about two out of three sessions start in plan mode and often spawn another plan, depending on how complex the work I’m doing is. This is spec-driven development at its best when it seamlessly integrates into your natural workflow. All OAK is doing here is capturing it, associating it with the session, and embedding it for search. SDD has always lived with the code, whether it’s an RFC, a PRD, or just a really good document. However, these plans live with the context, the work, the memory, the observations. I find this to be much richer and more valuable in the long term.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9XctZDgeQuLVU58cFkXC7A.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Vbbxs74Y-UurzVjfFFudaA.png" /></figure><h3>Memories</h3><p>The Memories interface offers a simple way to view all the observations Oak has collected over time. Gotchas, discoveries, decisions, fixes, trade-offs, and session summaries, all available. You can also permanently delete and resolve memories individually and in batches. For the most part, just a visual audit and management interface for all of the observations and content that OAK generates in the background. All of this content is also available via the search, but there are a couple of important things happening here: what you see here is everything we store in the SQLite database locally. What’s available in search is everything from the embedded database in our vector database. We do it this way so that the vector database can be rebuilt from the source of truth at any time, or whenever data becomes corrupted or lost. It’s a good idea to rebuild every once in a while to control the file size of the Chroma DB database, and it’s also how we automatically embed sessions and observations from team member files once we sync up. Tools are provided to manage all of this, and most is done automatically.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*ML4b1av9f_T_iz5A.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*joM1-vDAdkn5Q6xp0D2iAg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ekeCSl6PvDAGZDWHeTQNeg.png" /></figure><h3>Team Sync: Building the Hive Mind</h3><p>Team Sync aims to solve the “Tower of Babel” problem for teams and organizations in the agentic AI age. How do we get all of my agent sessions, context observations, and everything we’ve discussed so far into your context agent sessions and observations? Not only that, but how do we differentiate which ones came from my machine or your machine, and then synchronize them so they all play nice together locally? Well, we built a bunch of tooling 🤖.</p><p>In practice, we talk a lot about tribal knowledge in organizations, but in the context of how we’re building software today, it has a completely different meaning. Me as the developer and the leader of my own tribe. My tribe consists of an army of AI agents all doing work independently and sometimes collectively. However, I still work on a team on a project, and my team member is doing the same. We still have the code and the pull requests, and those are still incredibly valuable. However, as we’ve discussed, the way it was built, why it was built the way it was, and the problems it solved as it was being built are all incredibly valuable context for the next time you go in and work on a similar feature. And the next time might be a different team member. It might be a junior team member.</p><p>With Oak, we’ve preserved the context, we’ve preserved the why. Now, Team Sync, as it stands today, is pretty simple. We back up the SQLite database to a directory that is ideally set up with Git, then commit it. By default, this is in the same project in oak/history, or you can easily override it to a shared or more secure location. The file is named in a way that identifies it as yours, and it&#39;s tagged to the specific machine. If you use multiple machines, you&#39;ll have multiple backup files, one for each. OAK provides an interface and CI tooling to both generate those files and import them into your local database. It then embeds all the new content for indexing so it&#39;s available to you and your agents. Tribal knowledge was transferred successfully in just a couple of minutes.</p><p>Automatic backup -&gt; project/shared directory&gt; oak ci sync --team --include-activities</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*CndrLprB2RkyT2BC.png" /></figure><p>Also in the Team area is the Sharing section. Sharing came about when I wanted to show someone a session I had been working on, but since it was only local on my machine and the person wasn’t sitting next to me, I wanted an easy way to do it. Simply start sharing, and a reverse proxy tunnel is opened with cloudflared or ngrok (your choice) using a random URL, and share it with a team member. I have bigger plans for this feature in the future, but for now, it’s pretty useful as is…just don’t forget to turn it off 😉</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*CgDy85iktM1_2v0xhzUpGA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*60AipSBH9iQ0WlCt_GL9UQ.png" /></figure><h3>OAK Agents: Turning Context into Action</h3><p>If the Activity Dashboard is the “Flight Recorder,” then <strong>OAK Agents</strong> are the autopilot. Recording context is vital, but the real power comes when you put it to work. I didn’t just build OAK to be a librarian; I built it to be an active member of the engineering team.</p><p>OAK supports <strong>Claude Agent SDK-powered agents</strong> and autonomous tasks that can perform work in the background. Because these agents have access to the full OAK “memory index”-including <strong>context-rich automations</strong>. We can give our agents specific tools, skills, system prompts, and task prompts to perform specific, repeatable tasks that produce very high-quality results. Agents have a rich schema, a declarative manifest for building custom agent tasks, and we ship many built-in agent tasks available after initialization. By leveraging Claude Code under the hood, it uses your same subscription to perform the work. We also have experimental support for using local LLMs with the agent SDK through Ollama and LM Studio. Examples of the built-in agent tasks:</p><p><strong>Auto-Documentation:</strong> Instead of writing CHANGELOG updates manually, an OAK agent can scan the week&#39;s changes, cross-reference them with the &quot;intent&quot; captured in our sessions, and generate documentation that explains <em>why</em> changes were made, not just <em>what</em> changed.</p><p><strong>Surfacing Insights:</strong> OAK Agents can analyze the development velocity and friction points, highlighting areas where the team seems to be fighting the codebase.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*emvOCGoia0QYbM-o.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*E9MAboZnzxIUkQ1eIh2Yug.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*bGCYGnt-Lrjb1Q_AEmKX4A.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ySqoigPWIk-RTkEagH4VFA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*UshZNjIHBebRacSilNkTJA.png" /></figure><p>This is just the start of this feature. I have many ideas and big plans. OAK agents today are already maintaining all OAK project documentation, including the Atstro documentation site. Maintaining an active, semantically rich changelog. As well as analyzing my prompt and session quality, offering suggestions and insights. But you can see the power of this. A bug hunting and fixing agent, with all of the context of OAK at its disposal, with specific tools and guard rails only possible with using the Agent SDK, and some of those hyperbolic claims get closer to reality.</p><h3>The Plumbing</h3><p>As I’ve been building Oak, it’s become increasingly complex. With that complexity, the drive to push for simplicity. Most of the tooling I package with OAK is meant to be used by agents and agents alone. However, there is some tooling designed for you, the developer, to ensure everything stays up to date and running. Let’s talk a little bit now about the underbelly, some of the things you’ll interact with, and what some of the things wired up behind the scenes do.</p><h3>Upgrade lifecycle</h3><p>Keep the package up to date: brew upgrade oak-ci . When upgraded, most functionality just works. The daemon ui will see the update and ask you to restart. You click, it starts, and you get the new stuff. When changes to the installed assets of OAK are updated, things like agent skills, configuration, etc, you run oak upgrade in your project, and OAK handles the rest. When you are working with a new agent and want to wire it up with OAK, oak init Select the agent, and then the hooks, skills, and MCP are wired up.</p><h3>OAK’s MCP server</h3><p>When you enable an agent like Claude or Cursor in your project with oak init OAK&#39;s MCP server is automatically configured for each agent, and it runs in the background alongside the UI and API. The MCP server has four tools:</p><ul><li>oak_remember - When the agent makes a decision, gotcha, discovery, etc., it chooses to preserve that in OAK. This is a valuable and frequently used tool for agents, offering rich, accurate memories.</li><li>oak_search - searches our vector database across code and all memory categories.</li><li>oak_context - gets memory-related information on specific files in the codebase.</li><li>oak_resolve - new tool for resolving outdated or superseded memories, often used in combination with search</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*WnNgzFi0yua8f-UF.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*MP3GrOXgIu3Lth21.png" /></figure><h3>Skills</h3><p>Two skills are installed by default when you initialize OAK:</p><ol><li>The <strong>Codebase Intelligence</strong> Skill — An agent and user invokable skill to fully interact with the OAK platform. It knows how to work with both the SQLite and ChromaDB databases. When asking an agent about sessions, memories, and plans, the skill quickly retrieves the information and loads it into context. It’s also useful to invoke the skill yourself and just use the agent to do anything and everything you could do with the UI. /codebase-intelligence find the work we completed on the memory lifecycle feature and lets start work on adding proper lineage, mentiond as future work in the plan. Skip the token eating exploration and get to the relevant info sooner.</li><li>The <strong>Project Governance</strong> Skill — While OAK is the keeper of context, that doesn’t mean your project doesn’t need a strong project Constitution, aka, the rules file or system prompt. With OAK’s support for multiple agents in a single project, each with their own rules files and standards, project governance is a skill that helps you manage them all. It will build your projects oak/constitution.md and synchronize them with all of the rules files CLAUDE.md, AGENTS.md, copilot-instructions.md, etc. This works for brownfield or greenfield projects and will not replace or overwrite your rules files; it will, in fact, use that information to build your constitution. /project-governnance lets build our projects&#39;s constitution. or amending our constitution. Use project governance to add a new rule, no magic strings or numbers, we must use constants.</li></ol><h3>Wrap up and the road ahead</h3><p>This has been a fun project to work on, and I plan to continue working on it. I’m also curious to hear other ideas, as I know many people are thinking about these challenges and coming up with ways to solve them. This is just my take on it. First and foremost, I built this to solve the challenges I was having. I want to use multiple agents in a project and have a way to preserve and understand all the work being done without getting in the way of the coding agent. That’s why OAK is not an agent framework. It’s not a wrapper around Claude. It simply sits beside it. How do you trust everything the agent is doing? You could review everything line by line, and I often still do. But now I think about the problem differently. The agents and the models they use are highly capable but will make mistakes, so offer them better context to help reduce them and use other agents to verify their work. We are just at the very beginning of these types of workflows. So I can’t wait to see how the tooling evolves and how we evolve with it.</p><p>There’s so much more that I didn’t cover in this already very long blog post. So come join me over on <a href="https://github.com/goondocks-co/open-agent-kit?ref=chriskirby.net">GitHub</a> to dig in further. See you there!</p><p><em>Originally published at </em><a href="https://chriskirby.net/solving-the-groundhog-day-problem-in-ai-software-development-introducting-oak/"><em>https://chriskirby.net</em></a><em> on February 15, 2026.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d291fc5252da" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Why Your Work Laptop Belongs in Its Own VLAN (and How to Do It)]]></title>
            <link>https://medium.com/@sirkirby/why-your-work-laptop-belongs-in-its-own-vlan-and-how-to-do-it-4ae343db2caa?source=rss-8c693b99d86a------2</link>
            <guid isPermaLink="false">https://medium.com/p/4ae343db2caa</guid>
            <category><![CDATA[work-from-home]]></category>
            <category><![CDATA[information-security]]></category>
            <category><![CDATA[networking]]></category>
            <category><![CDATA[homelab]]></category>
            <dc:creator><![CDATA[Chris Kirby]]></dc:creator>
            <pubDate>Fri, 01 Aug 2025 12:01:17 GMT</pubDate>
            <atom:updated>2025-09-12T15:23:28.157Z</atom:updated>
            <content:encoded><![CDATA[<p><a href="https://chriskirby.net/tag/homelab/">Homelab</a></p><figure><img alt="A laptop in a jail cell, the name on the cell is VLAN’s" src="https://cdn-images-1.medium.com/max/1024/0*lXNmt2PsOJw05cze.png" /></figure><p>Ever feel like Big Brother is lurking behind your screen? Spoiler: it probably is. It’s called Data Loss Prevention (DLP) software, and it lives on your work laptop-it’s a vital guardrail for company data. But once you step through your front door, most of that telemetry is just dead weight: scanning your network, rerouting DNS, and logging IoT devices without delivering meaningful value. Outside the office, your laptop only needs plain‑vanilla internet access. In this walkthrough, I’ll show you how to carve out a dedicated VLAN for your corporate machine-preserving the protections you need while keeping your personal network private, performant, and uncluttered.</p><h3>Things you’ll need</h3><ul><li>A WiFi router that you manage (not the thing your ISP gave you 🗑️), which supports multiple virtual networks and multiple wireless networks (SSIDs). I highly recommend a UniFi Dream Router or UniFi Express device, similar to what I’m using in the screenshots below. This setup will also work with any router with similar capabilities, such as TP-Link Omada EAP, Asus RT-AX86U, Linksys VELOP, and others, all in the $150-$300 price range.</li><li>Your work computer, Mac or Windows PC, connected via WiFi or Ethernet.</li></ul><h3>Create your new virtual network</h3><p>If your house is like most, you likely have 20, 30, or more devices connected to your home WiFi. Smart speakers, TVs, Phones, and even your kitchen appliances. Nearly all of these devices are connecting to the internet, and nearly all of them are collecting data on you. Now, I have several other posts on how to help you with that, which I’ll link below; however, it all starts with the VLAN. The best way to ensure those devices follow your rules is to first put them in the same group. Once grouped, you can set up rules (also known as policies), which control how that group can behave on your network.</p><p>In this example, I’m configuring a new virtual network in UniFi that I’ll call <strong>Work. </strong>Most settings can be left to the default, but ensure you allow internet access, and I recommend checking the isolate network option. You can always adjust your settings later if you want to customize things like your VLAN ID / Tag or Subnet, both will be important later. Settings -&gt; Networks -&gt; New virtual network</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*P0roidaVD1BgUI-9.png" /></figure><blockquote>Optional: Create a new Zone (if using zone-based firewall)</blockquote><p>This is a nice option if on UniFi, which makes configuring polices a bit more straightforward and offers automatic isolation from your Internal zone by default.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/812/1*6ath99-DNGQg5o4EZcNhuw.png" /><figcaption><a href="https://www.youtube.com/watch?v=RTgBfRTABs4&amp;ref=chriskirby.net">Can’t trust the System</a></figcaption></figure><h3>Add a new Wifi Network (SSID)</h3><p>I create a new network and ensure that my VLAN <strong>Work</strong> is set as the default network. This ensures that any device connected to this WiFi is on the Work network. Settings -&gt; WiFi -&gt; Create New</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*EARSSF8FUTPdE1T5.png" /></figure><blockquote>Optional: route all Work internet traffic over a permanent VPN connection</blockquote><p>This will add an additional layer of privacy and security. This may cause issues if your work device is using another VPN; if so, skip or disable the policy. Settings -&gt; Policy Engine -&gt; Policy based routes</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/796/0*xXeA1VIsaY_rVffV.png" /></figure><p>That’s it for your basic network setup. Any device that is on this new network will automatically be isolated. From here, you can create more advanced policies as you get more comfortable. For example, you might restrict this WiFi and network to your work device only, or create policies that block your work device from connecting to your other home WiFi network. Policies are a powerful way to control what happens on your network, and I encourage you to learn how to leverage them.</p><h3>Configure your work laptop to use your new network</h3><p>There are a few things to consider here, and it may depend on the type of computer you have. I’ll break down both WiFi and wired connections (for dock users) for Mac and Windows to cover the basics.</p><h3>WiFi Configuration</h3><p>This is the easy one; simply connect to your new SSID, which will automatically route all traffic to your new VLAN. However, there are a few more things you should consider. When logged into a Mac with your iCloud account or a Windows computer with your work and/or personal Outlook/Office 365 account, it will save your network settings. This means your laptop may unintentionally connect back to your home WiFi. Here are some steps to check off to ensure that doesn’t happen.</p><blockquote>Make sure to forget your home WiFi network in your WiFi settings.</blockquote><h3>Mac </h3><p>Don’t log in with your personal iCloud account on your work laptop. Now, I do this for Notes, Contacts, etc, and you may too. iCloud is very aggressive about switching network settings to “help”. If you don’t, you’re good. I would still recommend following the steps below for good measure.</p><p><strong><em>OR</em></strong></p><p>Log in with your personal iCloud account, or use an iCloud account associated with your work email. This feature saves all network connection credentials across devices and automatically connects to the first available one. Great for personal devices, but we don’t want this for our work laptop.</p><p>If you’re able, turn off Private WiFi Address on your new SSID Settings -&gt; Network -&gt; WiFi -&gt; ... Network Settings This allows us to consistently identify this device when connected to our network.</p><ol><li>Change Private Wi-Fi address to Fixed.</li><li>Copy the Wi-Fi address (a.k.a. MAC Address)</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/942/0*sEZPNLXHoKLGF3xw.png" /></figure><h3>Windows</h3><p>Similar to Mac’s private Wi-Fi address, you should turn off Random hardware addresses in Network &amp; Internet -Wi-Fi -&gt; Work SSID</p><ol><li>Turn off Random hardware addresses</li><li>Copy the Physical address (MAC)</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*AnkPefBrACqsKN3v.png" /></figure><h3>Optional: Exclude your MAC address from your home WiFi</h3><p>If you made those changes and your MAC is now fixed, this is a sure-fire way to make sure you are never connected to your home WiFi.</p><p>3. Go to your WiFi settings on your router for your home network and exclude your work MAC address. Even if your laptop tries to switch, your router will deny the connection; Work WiFi, or nothing.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*xXQcXumQrvdJxo4S.png" /></figure><h3>Wired Configuration</h3><p>I always prefer to hardwire if I have the option. It’s faster and more reliable. To ensure proper isolation on a wired connection, you will need to either be directly connected to an available switch port on your router or to a managed switch that is connected to your router. Because we are using VLANS, you may need to adjust the settings on the port of your switch you are connecting to, or the port you are connected to must be configured to forward tagged network traffic. This is very easy to do on most managed switches; I’ll be showing UniFi, but the same settings will apply to others.</p><h3>Dedicated port</h3><p>The easiest way to configure this is to dedicate a port on our router or switch to this new VLAN you created. When configured for that VLAN, any device you connect via Ethernet to that port will automatically be on that virtual network.</p><ul><li>Find the port your laptop or dock is connected to. In UniFi, this is Port Manager -&gt; Select Port</li><li>Change the name of the port (optional, but helpful)</li><li>In the Native VLAN dropdown, select your new <strong>Work</strong> network</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/0*oC7XT20S-m2MUEOg.png" /></figure><h3>Same dock, different network</h3><p>I’ll offer some more advanced configurations for those that may have elevated permissions on their work laptop or perhaps share a dock and display, and want to swap between work and personal laptops on the same setup (this is what I do)</p><blockquote>Create a new Virtual Network on your personal computer</blockquote><p>You may not be able to change your network settings on your work computer, and even if you can, it’s not necessary. You just need to change the settings on your personal computer. If you see in the screenshot above, while we made the default VLAN ‘ <em>Work</em>’, we still have <em>Allow All</em> for other tagged VLANS. That means if your laptop is ‘tagged’ for your home network, then when you dock your personal laptop, it will be on your home network without changing anything on your work laptop, router, or switch.</p><h3>Mac Configuration</h3><ol><li>Network Settings -&gt; Manage Virtual Interfaces</li><li>➕ New VLAN</li><li>Name it “Home VLAN”, Tag should match the tag you set up in one of the very first setups for your VLAN on your router, mine is 1, which is a common default.</li><li>The interface should be your Ethernet interface; mine is my dock, showing as USB 10/100/1G/2.5G LAN</li><li>Now set your service order, and move Home VLAN to the top.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/544/1*7uk0zR0JWYvFqMG9Lbc8qA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/836/1*ZBi_WlM6YpMtevBDzA40KQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/824/1*_yAOv4uRDIKSsRC5DVdLJw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/968/1*jwroZ_d9ToLgXTeopHTYOw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/490/1*FBFJhMqwJhkbCTdhu85hqA.png" /></figure><h3>Windows</h3><p>Here, we’ll just use the existing adapter and tag the traffic to your home network.</p><ol><li>Network &amp; Internet -&gt; Ethernet -&gt; More adapter options</li><li>This will bring up the old control panel, because Windows.</li><li>Select Client for Microsoft Networks, then the Configure button</li><li>Advanced tab, scroll to VLAN ID, change the value to 1 (or your home network tag)</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3Ue3vrgq8livJ6TWS4xEag.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/448/1*rj_uTqU_w0GDRjV0E4HRpw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/528/1*xDQY-AIG1gXduIgg0wtvxQ.png" /></figure><p>There may be other ways to do this in Windows, but this was the most direct way I could find. Once changed, your computer will request an IP from your home network instead of being on your new Work network.</p><h3>Wrap up</h3><p>Pretty painless, right? Now your work computer has its little corner of your home network, complete with unrestricted internet access. Great way to boost your privacy without compromising work security — everyone wins! Let me know how your setup goes.</p><p>You can use these same techniques to isolate other smart home devices. To get a more comprehensive breakdown of how you might approach that, check out my homelab guide below.</p><p><em>Originally published at </em><a href="https://chriskirby.net/why-your-work-laptop-belongs-in-its-own-vlan-and-how-to-do-it/"><em>https://chriskirby.net</em></a><em> on August 1, 2025.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4ae343db2caa" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The Joy and Agony of Building with AI Agents]]></title>
            <link>https://medium.com/@sirkirby/the-joy-and-agony-of-building-with-ai-agents-4244fbd81570?source=rss-8c693b99d86a------2</link>
            <guid isPermaLink="false">https://medium.com/p/4244fbd81570</guid>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[agentic-ai]]></category>
            <category><![CDATA[cursor]]></category>
            <category><![CDATA[vscode]]></category>
            <dc:creator><![CDATA[Chris Kirby]]></dc:creator>
            <pubDate>Thu, 20 Mar 2025 22:37:33 GMT</pubDate>
            <atom:updated>2025-03-27T22:33:18.232Z</atom:updated>
            <content:encoded><![CDATA[<p><a href="https://chriskirby.net/tag/artificial-intelligence/">Artificial Intelligence</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*9j8xhwAngXFjTa9Z.png" /></figure><p>As I work on my Home Lab, various <a href="https://github.com/sirkirby?ref=chriskirby.net">open source projects</a>, and projects for work, I’m increasingly leveraging agentic AI tools-tools you can now interact with and act on your behalf directly inside your code editor. I primarily use <a href="https://www.cursor.com/?ref=chriskirby.net">Cursor</a> and <a href="https://code.visualstudio.com/?ref=chriskirby.net">VS Code</a> w/ <a href="https://github.com/features/copilot?ref=chriskirby.net">Copilot</a>, which are both developing interactive agents to improve coding productivity. <a href="https://docs.anthropic.com/en/docs/agents-and-tools/claude-code/overview?ref=chriskirby.net">Claude Code</a> is also impressive and worth a mention as well. These agents can leverage the latest models from, <a href="https://www.anthropic.com/news/claude-3-7-sonnet?ref=chriskirby.net">Anthropic</a>, and others to write code and execute commands directly in your code editor. In many ways, it’s the interface you are already familiar with in ChatGPT or Claude, but now, with the ability to automatically gather context from your codebase, create new files, run unit tests, anything you can do manually in your editor or via the CLI. This is incredibly powerful, amazing even…at first. Now, you can certainly “vibe” your way to something, but because we are using natural language with all of the limitations and unpredictability of LLMs, you must know what questions to ask, challenge assumptions, and define consistent context and rules to achieve better, more consistent results. In the hands of a skilled operator (or aspiring, in my case), you can genuinely create code you would feel proud to ship 🐿️. I’m still learning daily, but I wanted to stop and share some of what I’ve learned thus far in the hope that it may also help you on your journey to developing this vital new skill.</p><h3>Set the ground rules</h3><p>With all LLMs, your outcomes are only as good as the context you provide and the accompanying prompts or instructions. To achieve better consistency, especially with coding, it’s essential to define a set of rules that will accompany all of your requests. This is a simple markdown or text file you will add manually or configure to include automatically with every chat request. This will help establish the boundaries and the type of code you would like the agent to produce. Cursor offers a first-class feature called <a href="https://docs.cursor.com/context/rules-for-ai?ref=chriskirby.net">Rules</a> to formalize this and even offers ways to automatically include one or more rule files in your chat session. Copilot offers <a href="https://code.visualstudio.com/docs/copilot/prompt-crafting?ref=chriskirby.net">some conventions</a> for defining your prompt files as well, which can be manually included in your chat session. Simply put, LLMs have vast general knowledge but no long-term memory and minimal short-term memory; think of <a href="https://youtu.be/Lm9riFCqUag?si=N8nmt0NuoxuA26kv&amp;ref=chriskirby.net">10-second Tom</a> from the movie 50 First Dates; every chat is a new introduction. “Hi, I’m Chris”. Now, the tools understand this and are getting better at solving this problem every day, but for now, this step is essential to achieving better results. Here are some of my general guidelines, along with some examples:</p><ul><li>Clearly define coding styles and patterns. &quot;I prefer idiomatic C# using the latest language features&quot;, &quot;Keep the code DRY&quot;.</li><li>Describe the purpose of your project &quot;To make an awesome home assistant custom integration&quot;</li><li>Provide repeatable instructions &quot;Keep a rolling log of each change you make in a file called agent-changelog.md&quot;</li></ul><p>Here is an example of a complete global rules file I use when working on my <a href="https://github.com/sirkirby/unifi-network-rules?ref=chriskirby.net">unifi network rules</a> custom integration for home assistant:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8fb00365acd55bc401ab436a2fdf5381/href">https://medium.com/media/8fb00365acd55bc401ab436a2fdf5381/href</a></iframe><h3>There is no substitute for Wisdom, yet</h3><p>Like very smart and helpful people or perhaps your favorite medical practitioner, agents often focus on treating the symptom and not the root cause. This is by far the most common issue I encounter and where your experience will be leveraged the most. Perhaps you are diagnosing a bug, providing necessary context, logs, and screenshots, and doing all of the right things. However, you must stay diligent. Review the code and ensure the implementation is thorough. Challenge it. &quot;Why are you removing x?&quot;, &quot;What about x?&quot;. Force it to follow the rules and write better, more thoughtful code. Your best chance of that is when the context is fresh. I reject nearly as many changes as I accept, and you should, too. It&#39;s best to be clear about what you want from the start.</p><p>Avoid something like:</p><blockquote><em>“help me debug this. here is the log:”</em></blockquote><p>Prefer something like:</p><blockquote><em>“I see we have a problem with x. Lets try to address this in a targeted way, as all other functionality is working correctly. Let’s also ensure that any changes we make are consistent with established rules and patterns. Here is the debug log to help us get started. Analyze and provide recommendations”.</em></blockquote><p>The more instructions and intentions you provide, the better and more consistent the outcome.</p><h3>Context is King-Give It Everything, Assume Nothing</h3><p>Just like rules and prompt files can be used to establish general context, it’s vital that you consistently provide relevant context to the agent to get thorough results. Well-written code is complex and uses abstractions, libraries, APIs, and unit tests. A single feature will likely cross dozens of code files. Unless you provide those files, assume it has no clue. Thankfully, VS Code and Cursor make this incredibly easy and are actively improving the tooling for this. Within the agent chat window on the right, you can ➕ files and use syntax like @ or # to include entire folders, individual files, previous chats, and even websites. Do it every time. Missing key context will almost certainly lead to incorrect, incomplete, or duplicate code.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/650/0*Jce4G7uTKvuG6_A7.png" /></figure><h3>Keep your agent sessions small</h3><p>While context is critical, as illustrated above, it’s also limited. You’ll often find diminishing returns the longer you chat, so keep each session small and focused. Once you achieve or even get close to the outcome, stop there and start a new chat. Cursor has a nice feature that will summarize your current session and add that summary as context for the new chat. This will keep your agent sessions more productive. Like a good commit or an easy-to-review pull request. This can be a fine line, so use your best judgment here. The general rule I follow here is big context, targeted ask. Avoid small context and vague asks.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/638/0*Bfv8UYBO2u3YNhgt.png" /></figure><h3>Know when to fold ‘em</h3><p>Agents will take you down a rabbit hole. I’ve spent hours in a single session just trying to get there. What seems like a simple ask can sometimes be 25, 50, or more steps as the agent “thinks” its way through each prompt. Cursor knows this and stops the agent at 25 steps per prompt, asking you if you would like it to continue. By the end, perhaps you can’t keep any of it. Stash it and start over. Sometimes, too much has changed and you’ve risked existing functionality, too many test are broken. I understand the desire to roll forward because things may be worth keeping. The good news is, YOUR short-term memory is outstanding, so use everything you have learned and hit that plus sign to start a new chat. It will be better this time, and you will keep things small. At the first sign of spiraling, stop it, revert, and go back to the previous prompt and change it. The tools are built in a way to manage the state for each session, so use that. Both Cursor and VS Code have chat history and record each step in the history. This has saved me a lot of time and will save time for you too.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/503/0*4gYL-4zNM2m2dwz_.png" /></figure><h3>Simple is Hard, Hard is Simple</h3><p>File, project new, &quot;Create me a new console app with an API endpoint that will summarize today&#39;s stock market data&quot;. No problem! &quot;Add a new API endpoint to x&quot;, whole project destroyed! Boy, can AI Agents overcomplicate the most straightforward thing? You&#39;ve told it not to, given it instructions, but there it goes again. For lack of a better term, it lacks elegance. Simple, clean code seems hard for it. You can get there, but you have to be very clear and hold it accountable to the rules. I hit the stop button the second it starts to deviate or overcomplicate. I&#39;ll sometimes go back and update my rules, too. Then, start again. In times like this, I find just getting in the editor myself and making the changes using inline code complete is faster. Agents aren&#39;t the tool for every problem; they can slow you down too. You know how to write clean code, so get in there and show the agent how it&#39;s done!</p><h3>REVIEW, REVIEW, and REVIEW AGAIN</h3><p>I treat AI-generated changes like a junior dev’s pull request. The changes are just a starting point and can often be implemented more thoughtfully. You are the senior engineer, the gatekeeper, if you will. You have the wisdom, and this is where you should apply it. Don’t wholesale accept the changes. Look at each file and each diff; it’s worth it. Reinforce your design principles, be additive, and you will get a better result than you could have achieved alone.</p><h3>Final thoughts</h3><p>Coding is complex, so having these incredible tools by your side is truly a shift in how things will be crafted moving forward. AI will touch every pull request, bug fix, and product release, and I say that optimistically. The more we can understand and master our tools, the more prepared and productive we will be moving forward. With that said, things are moving quickly…dare I say too quickly. Trust, but verify, has never been more apt in this context than it is today. If you are a software engineer, engineer adjacent, or a maker, this is the now and most certainly the future. I’m very interested to hear how your experience has been working with these tools. Have you tried them? Had similar experiences or learnings to me? Let me know, and have fun!</p><p><em>Originally published at </em><a href="https://chriskirby.net/the-joy-and-agony-of-building-with-ai-agents/"><em>https://chriskirby.net</em></a><em> on March 20, 2025.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4244fbd81570" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Add free private AI chat to your HomeLab with Ollama and Open WebUI]]></title>
            <link>https://medium.com/@sirkirby/add-free-private-ai-chat-to-your-homelab-with-ollama-and-open-webui-50945f7f58d0?source=rss-8c693b99d86a------2</link>
            <guid isPermaLink="false">https://medium.com/p/50945f7f58d0</guid>
            <category><![CDATA[open-source]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[homelab]]></category>
            <category><![CDATA[ollama]]></category>
            <dc:creator><![CDATA[Chris Kirby]]></dc:creator>
            <pubDate>Fri, 24 Jan 2025 17:02:14 GMT</pubDate>
            <atom:updated>2025-01-31T16:42:05.595Z</atom:updated>
            <content:encoded><![CDATA[<p><a href="https://chriskirby.net/tag/artificial-intelligence/">Artificial Intelligence</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*mTbVyYNumh1bziUu27gyOQ.png" /></figure><p>That is actually good, fast, and uses the hardware you already have; no<strong> subscription required</strong>. It’s not only comparable to ChatGPT, Claude, and Perplexity, but you can use those services as well, along with the latest local open-source models from Meta, Microsoft, Google, and others. If you are like me, you might have one or two Apple M-series Macs and maybe a gaming PC or laptop with an RTX GPU. You can use all of that hardware, that is otherwise used for work, web browsing, and games, to serve up local AI queries that can search the web, analyze images, and many more tasks you can enable or even develop yourself. These chats will be run locally, are stored locally, and never leave your home network…unless you want it to. We’ll use the very cool and rapidly improving project <a href="https://github.com/open-webui/open-webui?ref=chriskirby.net">Open WebUI</a> as our ChatGPT-like interface and <a href="https://github.com/ollama/ollama?ref=chriskirby.net">Ollama</a> as our model runner and local API to respond to local chat queries. I’ve been using and fine-tuning my setup for a couple of weeks now and have been having a lot of fun. I think you will, too, so let’s get into it!</p><h3>We’ll cover</h3><ol><li>Setting up Ollama 🦙 on Mac and Windows as a service that is accessible on your local network.</li><li>Setting up Open WebUI in Docker 🙂 and Kubernetes via a customized Helm chart 🤓. Choose what works best for you.</li><li>Fully configuring Open Web UI to run local models like <a href="https://ollama.com/library/llama3.3?ref=chriskirby.net">llama3.3</a>, <a href="https://ollama.com/library/deepseek-r1?ref=chriskirby.net">deepseek-r1</a>, <a href="https://ollama.com/library/phi4?ref=chriskirby.net">phi4</a>, and <a href="https://ollama.com/library/gemma2?ref=chriskirby.net">gemma2</a> across multiple machines and integrating with OpenAI, Claude, Gemini, and Perplexity for a no-compromise local chat experience…for the whole family 🏠</li><li>Finally, can this replace my AI subscriptions? I think it could, with some considerations 💪.</li></ol><h3>Ollama as a Service</h3><p>Ollama is an awesome tool that I’ve been using for quite a while now, all by itself. With Ollama, you can pull down a model that is cable of running on your computer, and start chatting directly from <a href="https://app.warp.dev/referral/EJK58L?ref=chriskirby.net">your favorite terminal</a>. Ollama will load the model and recognize your computer and architecture, automatically leveraging GPU Offloading via Apple Metal or Nvidia RTX to optimize performance. It’s this functionality, along with their built-in API and your metal, that will power our local chat application.</p><p>We’ll have to enable Ollama to do two things it doesn’t do by default.</p><ol><li>Run all the time in the background</li><li>Allow connections to its API from other machines on the local network by setting two environment variables OLLAMA_ORIGINS=”*” and OLLAMA_HOST=”0.0.0.0&quot;</li></ol><h3>Configuring Mac M4 Mac mini</h3><pre>brew install ollama</pre><pre>nano ~/Library/LaunchAgents/com.user.ollama.plist</pre><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/84dea5c2832e0f34a7b7c6a1b69dfd7a/href">https://medium.com/media/84dea5c2832e0f34a7b7c6a1b69dfd7a/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9a0b2c95ddfac04017ba3e6cd3527866/href">https://medium.com/media/9a0b2c95ddfac04017ba3e6cd3527866/href</a></iframe><h3>Configuring Windows 11 gaming rig</h3><pre># install both ollama and nssm <br>winget install ollama nssm</pre><p>Now open your terminal as an administrator and run the remaining commands</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/bde1ba1b186a4993948b9a6cd9eae9c7/href">https://medium.com/media/bde1ba1b186a4993948b9a6cd9eae9c7/href</a></iframe><h3>Getting and sizing models</h3><h3>Mac 🖥️</h3><p>If you are memory-constrained, meaning you’re on an M series machine with 8 or 16 GB of shared memory, then stick to the 3b, 7b, and 13b sized models. If you’re on an M2-M4 Mac with 24–64 GB of shared memory, then you can jump up to the higher quality models, like 27b, 30b, and even 70b, like llama3.3 which is comparable to the latest cloud versions of ChatGPT, Claude, and Gemini. From my testing on my M4 Pro, the inference speed and quality sweet spot are 14b to 27b models, like Gemma2 and phi4. I can run llama3.3:70b, thanks to my 64 gigs of RAM, but it’s slow. Nonetheless, it’s very impressive for a computer that looks like my Apple TV…. I just plan for a coffee break while waiting for a response.</p><pre>ollama pull phi4<br>ollama pull gemma2<br>ollama pull qwen2.5<br>ollama pull llama3.3<br>ollama pull deepseek-r1:70b</pre><h3>Windows RTX 🕹️</h3><p>With Windows and a dedicated graphics card, you get the benefits of much higher GPU performance, but are much more memory-constrained. From my research, you can utilize 20, 30, and 40 series cards to run local models; the later the series and the higher in that series you are, the better your results. Older cards, like a 2080 super, are going to be in the 7b range, maybe 13b depending on Vram and model quantization. Similar with the 30 series but with better overall performance. In general, the offload limit seems to be 30–34b models with a high-end card like a 3090 or a 4090 with 24 gigs of Vram. I’m testing with a 4090 with 24 gigs Vram, which performs incredibly well on models like Gemma2:27b, deepseek-r1:32b, qwen2.5:32b, and many others. Performance and responsiveness are comparable to the fastest cloud models, which is quite impressive. If I go up in model size, however, performance drops off a cliff, as work shifts to the CPU.</p><pre>ollama pull gemma2:27b<br>ollama pull deepseek-r1:32b<br>ollama pull qwen2.5:32b<br>ollama pull codellama:34b</pre><h3>Deploy Open WebUI</h3><p>OK, Ollama is up and running as a service on one or more machines, and now it’s time to start working with those models you downloaded. My preferred tool for doing this is Open WebUI. I came across the project recently and have been loving it. It’s under active development right now, so you and I should expect many changes to come, but I love that it is open source and is something I can contribute to. It has all of the features you would expect in ChatGPT, Claude, or Gemini, but unlike those tools, Open WebUI allows you to aggregate local and cloud models into the same environment and context. This will enable you to choose the best AI for the task at hand. Not only that but all your chats, even when using Cloud AI models, are stored locally. I’m way underselling this, so please check out their <a href="https://github.com/open-webui/open-webui?ref=chriskirby.net">Github</a> and the <a href="https://docs.openwebui.com/?ref=chriskirby.net">docs site</a> …and keep reading to see it in action!</p><h3>Docker</h3><p>Docker is the best way to get started quickly and is well-documented on their site, but we’ll be using the Advanced configuration, which allows us to use Ollama on another computer. You can, of course, run Docker on the same computer you installed Ollama, which is how I started, and a great way to make sure everything is working and performing well.</p><pre># if my ollama service is running on 10.1.1.75<br>docker run -d -p 3000:8080 -e OLLAMA_BASE_URL=http://10.1.1.75 \<br>  -v open-webui:/app/backend/data --name open-webui \<br>  --restart always ghcr.io/open-webui/open-webui:main</pre><p>You can also run a Pipelines container (optional), which allows for building customizable workflows, like filters and functions. You may not leverage it now, but it’s so easy to set up, so go for it. Open Web UI will automatically recognize it on startup.</p><pre>docker run -d -p 9099:9099 --add-host=host.docker.internal:host-gateway \<br>  -v pipelines:/app/pipelines --name pipelines \<br>  --restart always ghcr.io/open-webui/pipelines:main</pre><p>And finally, to keep everything updated.</p><pre>docker run -d --name watchtower \<br>  --volume /var/run/docker.sock:/var/run/docker.sock \<br>  containrrr/watchtower -i 300 open-webui</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Ufl7M_7LFdyleIlF.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*mllxtXEcIpz0xhSI.png" /></figure><h3>Kubernetes</h3><p>I shifted most of my homelab apps over to Kubernetes quite a while ago now, and my services run with reasonable high-availability, shared persistent volumes, and TLS termination, so this is where I put my most critical apps. We’ll have the same base functionality of the Docker setup, with quite a bit more. Open WebUI has a <a href="https://github.com/open-webui/helm-charts/tree/main/charts/open-webui?ref=chriskirby.net">helm chart</a> to get you started with some default configuration, but you can easily tweak it to your liking by passing your own custom <a href="https://github.com/open-webui/helm-charts/blob/main/charts/open-webui/values.yaml?ref=chriskirby.net">values file</a>.</p><p>If you’re interested in setting up your own cluster, <a href="https://chriskirby.net/highly-available-pi-hole-setup-in-kubernetes-with-secure-dns-over-https-doh/">check out this post</a>, which walks through a basic K3s setup, and then meet back here.</p><p>I’m doing a few things with my custom values that are not enabled by default.</p><ul><li>I’m enabling pipelines, which will automatically install the pipelines chart as part of this release.</li><li>I’m enabling persistent storage using my NFS provisioner. It is important to note that because Open WebUI uses SQLite as the primary database, it doesn’t play nice with some PV provisioners. NFS on my NAS was my first choice, but I also use SMB and Longhorn. When I tested those, it created locking issues with the database. You can use an external Postgres database, but migrations are not yet supported with external databases, which may change. Stick to local storage (default), a manual persistent volume, NFS, or another provider you think may work.</li><li>I’m enabling WebSockets and Redis for caching.</li><li>Finally, I’m setting up ingress with TLS and nginx as my reverse proxy to ensure I have secure local access through Cloudflare Warp. Open WebUI was tricky to configure behind the proxy, though I managed to get it working through some trial and error.</li></ul><blockquote>Optional: To create your own free certificate via Let’s Encrypt, check out my other post <a href="https://chriskirby.net/migrating-from-pi-hole-to-adguard-home-with-some-upgrades-along-the-way/">Migrating from Pi-hole to AdGuard home</a> and scroll down to configuration and deployment.</blockquote><pre>kubectl create secret tls owui-tls-cert --namespace=openwebui \<br>  --cert=fullchain.pem --key=privkey.pemhelm repo add open-webui https://helm.openwebui.com/ helm repo update helm upgrade --install open-webui open-webui/open-webui \ --namespace openwebui --create-namespace \ --values openwebui-values.yaml</pre><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/24ce49a24b48a889b28f493797a22611/href">https://medium.com/media/24ce49a24b48a889b28f493797a22611/href</a></iframe><pre>helm repo add open-webui https://helm.openwebui.com/<br>helm repo update<br>helm upgrade --install open-webui open-webui/open-webui \<br>  --namespace openwebui --create-namespace \<br>  --values openwebui-values.yaml</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*3M_e12X292eCFHR5.png" /></figure><h3>Configuration</h3><p>Now that you are fully deployed, the configuration should be pretty straightforward. You’ve already specified your local Ollama endpoints in your Docker or Helm configuration, so those models should be connected and available after you create your admin account on your first login.</p><h3>External API’s</h3><p>For OpenAI, you can add your API key and the default API URL (if not already there) directly on the connections page. This will pull all models available by default unless you are using a project key on the OpenAI side, which restricts the models available to use.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/948/0*zB0MGC_AthNrrwmf.png" /></figure><p>For <a href="https://aistudio.google.com/apikey?ref=chriskirby.net">Gemini</a>, <a href="https://console.anthropic.com/settings/keys?ref=chriskirby.net">Claude</a>, <a href="https://www.perplexity.ai/settings/api?ref=chriskirby.net">Perplexity</a>, Hugging Face, and others. You’ll need to use Functions or Pipelines. Essentially, Python code runs and integrates with the respective API’s. There are already <a href="https://openwebui.com/functions?ref=chriskirby.net">commununity Fuctions</a> avaialble to get you up and running quickly, just add your key. There are also <a href="https://github.com/open-webui/pipelines/tree/main/examples/pipelines/providers?ref=chriskirby.net">pipeline providers</a>, which offer very similar functionality. You’ll need API credits, and usage will vary by model, but it is generally very affordable for normal chats. Add $5 and have fun.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*9m_V2OYHgk10LQel.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2lhV0jWA0VQMZdWN6P6TIQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kgr5XQenjZKUeFw2oyTuMw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-4oYTTQVfK4PMLddngconQ.png" /></figure><h3>Web Search</h3><p>You can enable this same functionality with Open WebUI, a feature you may be used to in ChatGPT and something Perpelexity does out of the box. Navigate to Admin Panel -&gt; Settings -&gt; Web Search and then choose your search provider and get their respective API key. I chose <a href="https://brave.com/search/api/?ref=chriskirby.net">Brave search</a> on their Free tier, which is perfect for my needs.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*W61QVurdvLv99kDV.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*zbD6dwNhMC_5B0Qr.png" /></figure><h3>Chat Flex 💪</h3><p>Now, let us have some fun with a little 1v1 chat-off.</p><h4>Metal Specs:</h4><p>Mac Mini M2 Pro SOC, 32GB Shared Memory<br>Mac Mini M4 Pro SOC, 64GB Shared Memory<br>AMD 9800X3d CPU, NVIDIA RTX 4090 GPU, 64GB System Mem, 24GB Video Mem</p><h3>Side by side Phi4:14b (M2 Pro) vs Gemma2:27b (M4 Pro)</h3><blockquote>I just purchased a new Unifi Dream Machine Pro; help me learn how to properly set it up using best practices</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/749/0*Zt6P72022qTqIN_I.gif" /></figure><p>Gemm2:27b is a significantly larger model and performs very well on the M4 Pro, but gotta love the speed of Phi4 on the M2 Pro, and the quality isn’t bad either.</p><h3>Side by side Gemma2:27b M4 Pro vs Gemma2:27b RTX 4090</h3><blockquote>Tell me how Ollama supports GPU Offloading for improved model inference.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/924/1*u8iYVAbL8cdmoNfe_vMPiw.gif" /></figure><p>That RTX 4090 crushes the M4 Pro, taking less than half the time. If only it weren’t so memory-constrained…perhaps a 5090 is in my future 🏦</p><h3>Side by side Claude 3.5 Sonnet vs ChatGPT 4o latest</h3><blockquote>Help me write a short blog post on the benefits of setting up my own home lab</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*yXtzZNyny4ijEpguLbpuRw.gif" /></figure><p>Speed: Both were very fast, as expected. Content: I give it to Claude.</p><h3>I want my $20!</h3><p>If you’ve made it this far, you might wonder, do I still need my subscriptions? Honestly, not really. After all, you’re building a Home Lab, so what fun would it be to take the easy way? This is, of course, not completely free, as my M4 Pro fully loaded was quite expensive, as was my 4090 gaming rig, but I was going to buy those things anyway for my normal work and casual gaming. In fact, I was running those side-by-side queries while using the computers, so it’s not disruptive to normal usage. The APIs are also not free, but the cost structures are very reasonable (or included with your sub) if you use the right model for the job. For example, not using use o1 when mini will do, or haiku instead of sonnet or opus will matter more when using the API. Bigger models for bigger tasks and smaller ones for smaller tasks are generally a good rule of thumb. The same goes for the open-source models. If you have the compute and sometimes the patience, skip the API&#39;s altogether. There are also product features to consider, like Projects, Web Search, local app integration, and Agents. Open WebUI and open-source projects have tackled many of those, but seeing how those products evolve will be interesting and perhaps worth the subscription fee. Either way, I like keeping my chats saved locally and I like that this is all in-house, I&#39;m sure you will too. Have fun, and let me know how it goes.</p><p><em>Originally published at </em><a href="https://chriskirby.net/add-free-private-ai-chat-to-your-home-lab-with-ollama-and-open-webui/"><em>https://chriskirby.net</em></a><em> on January 24, 2025.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=50945f7f58d0" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Migrating from Pi-hole to AdGuard home, with some upgrades along the way]]></title>
            <link>https://medium.com/@sirkirby/migrating-from-pi-hole-to-adguard-home-with-some-upgrades-along-the-way-e8bf7d51b0c9?source=rss-8c693b99d86a------2</link>
            <guid isPermaLink="false">https://medium.com/p/e8bf7d51b0c9</guid>
            <category><![CDATA[pihole]]></category>
            <category><![CDATA[kubernetes]]></category>
            <category><![CDATA[dns]]></category>
            <category><![CDATA[adguard]]></category>
            <category><![CDATA[homelab]]></category>
            <dc:creator><![CDATA[Chris Kirby]]></dc:creator>
            <pubDate>Fri, 20 Dec 2024 16:42:26 GMT</pubDate>
            <atom:updated>2024-12-21T13:31:25.938Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*aEyPf1u5LT48TUd-UhESZQ.png" /></figure><p><a href="https://chriskirby.net/tag/homelab/">Homelab</a></p><p>First off, I still love and use Pi-hole, which, for now, remains part of my ad blocking and local DNS. However, it’s not without its downsides. For years, Pi-hole has been the go-to solution for network-wide ad blocking, and for good reason. It’s practical, lightweight, and easy to set up. <a href="https://chriskirby.net/tag/pi-hole/">Many articles on this site</a> talk about the various ways I’ve used and deployed pi-hole over the years. However, as my home network becomes more complex, I continue to increase security and level up ways to configure, deploy, and maintain my home lab. Pi-hole shows its limitations when you want features like <a href="https://en.wikipedia.org/wiki/DNS_over_HTTPS?ref=chriskirby.net">DoH</a> and <a href="https://en.wikipedia.org/wiki/DNS_over_TLS?ref=chriskirby.net">DOT</a> locally and DoH for upstream DNS. It’s also challenging to deploy fully configured, lacks advanced filtering, and has an aging interface that could use design and performance improvements. I’ve worked around many of these challenges, however there are alternatives worth considering, and this article is about exploring and configuring one of the most popular alternatives, <a href="https://github.com/AdguardTeam/AdGuardHome?ref=chriskirby.net">AdGuard home</a>. From advanced filters to built-in parental and safe browsing controls, local and upstream DoH, and overall performance as a single Go binary, many compelling reasons exist to consider making the switch yourself. However, there were a few challenges to solve for me to consider this as a complete replacement.</p><h3>We’ll cover</h3><ol><li>Automatically converting most, if not all, of your Pi-hole configuration to an AdGuard-supported format. Lists, Filters, and even local DNS.</li><li>Creating a verified TLS certificate, configuring it with AdGuard, enabling SSL web interface access, DNS over HTTPS (DoH), and DNS over TLS (DOT) locally.</li><li>Complete configuration via the <a href="https://github.com/AdguardTeam/AdGuardHome/wiki/Configuration?ref=chriskirby.net">AdGuard configuration file</a>, allowing you to make changes and deploy them locally or from Git.</li><li>Deployment to Kubernetes via Helm, with a custom values file configuring and deploying all of the above.</li></ol><p>Let’s first establish a baseline of what we must accomplish, with the underlying goal of losing no existing functionality. <a href="https://chriskirby.net/highly-available-pi-hole-setup-in-kubernetes-with-secure-dns-over-https-doh/">Check out this post</a> as an example starting point. The tldr; network-wide ad blocking with curated and updated open source ad lists, all upstream DNS over DoH, local DNS resolution, and deployable as a container via Docker or Kubernetes.</p><h3>Migration</h3><p>Nearly every feature of AdGuard home can be set via their yaml-based configuration file, which I’ll reference in each area of migration below, along with new functionality. We won’t cover every feature, but I’ll call out some options to consider or chat with AI about what makes sense for your environment along the way.</p><p>First, run a Teleporter backup Settings-&gt;Teleporter-&gt;Backup on your Pi-hole instance, and then download and extract the archive. You&#39;ll need these files for some of the following migration scripts.</p><p>pi-hole-backup/<br> ├── dnsmasq.d/<br> │ ├── 01-pihole.conf<br> │ ├── 05-pihole-custom-cname.conf<br> │ └── 06-rfc6761.conf<br> ├── etc/<br> │ └── hosts<br> ├── pihole-FTL.conf<br> ├── custom.list<br> ├── dhcp.leases<br> ├── setupVars.conf<br> ├── client_by_group.json<br> ├── adlist_by_group.json<br> ├── domainlist_by_group.json<br> ├── client.json<br> ├── group.json<br> ├── domain_audit.json<br> ├── adlist.json<br> ├── blacklist.regex.json<br> ├── blacklist.exact.json<br> ├── whitelist.regex.json<br> └── whitelist.exact.json</p><h3>Migrate Adlists</h3><p>The first good news is that the lists you use for Pi-hole will work with AdGuard out of the box. Adlists will now be DNS blocklists. This is just a matter of converting from one format to another, and I used Claude to help me generate a Python script to do just that.</p><pre>pip install PyYAML</pre><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d28ea4b8fd31c80e4b7b98e0c2b3748d/href">https://medium.com/media/d28ea4b8fd31c80e4b7b98e0c2b3748d/href</a></iframe><pre>python migrate_adlists_filters.py pi-hole-backup/adlist.json &gt; filters.yaml</pre><blockquote>Alternative. You can query the gravity.db directly if you prefer: sudo sqlite3 /etc/pihole/gravity.db &quot;SELECT domain FROM domainlist WHERE enabled = 1 AND type = 1;&quot; &gt; blocklist.txt</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/737/0*y7YJTbpkp0BtfJ5S.png" /></figure><h3>Whitelists and Blacklists</h3><p>This is a little more complicated, as Pi-hole allows you to define four types of domain rules, whitelist exact &amp; regex, and blacklist exact &amp; regex. With regex rules, you may need to adjust some based on the complexity, as AdGuard’s interpreter may differ. This script takes all four input JSON files and outputs user_rules: yaml for your configuration file.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9a96cdf00a9528614736bd867f145db7/href">https://medium.com/media/9a96cdf00a9528614736bd867f145db7/href</a></iframe><pre>python migrate-domains-user-rules.py pi-hole-backup/whitelist.exact.json pi-hole-backup/whitelist.regex.json pi-hole-backup/blacklist.exact.json pi-hole-backup/blacklist.regex.json &gt; user_rules.yaml</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*UetLBpkrNBISe7ol.png" /></figure><h3>Local DNS resolution</h3><p>I’ve relied on Pi-hole to resolve my local DNS records by creating A and CNAME records for all my homelab resources. Managing those records in AdGuard is less straightforward as it does not have first-class local DNS management like Pi-hole. With that said, we can accomplish the same thing by using the DNS rewrites rules feature. If a request comes in for mywebsite.chriskirby.net, you configure the response to be 10.100.1.45, which simulates an A host response, or it could respond with k3s.chriskirby.net, which simulates a CNAME response. The request is not sent upstream and still shows in the query log as a rewrite, not a resolved DNS entry. It&#39;s not as elegant, but it works just fine. Here is how you can convert your DNS records into the corresponding rules.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5a3f4cc56699b951eddc01bc8d886660/href">https://medium.com/media/5a3f4cc56699b951eddc01bc8d886660/href</a></iframe><pre>python migrate-dns.py pi-hole-backup/custom.list pi-hole-backup/dnsmasq.d/05-pihole-custom-cname.conf &gt; dns_rewrites.yaml</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/299/0*8SnM9tTlX2AFyLVF.png" /></figure><h3>DoH upstream</h3><p>This one is easy and requires no special conversion. Instead of having to relay through a cloudflared proxy to ensure my upstream was encrypted, AdGuard home supports this out of the box.</p><pre>upstream_dns: <br>  - https://cloudflare-dns.com/dns-query <br>  - https://dns.google/dns-query</pre><blockquote>For info on how to configure your network to ensure all local DNS goes through your AdGuard server and is encrypted on the way out, read: <a href="https://chriskirby.net/setting-up-and-leveling-up-your-homelab-a-comprehensive-guide/">Setting up and leveling up your homelab — a comprehensive guide</a></blockquote><h3>Configuration and Deployment</h3><blockquote>with TLS to Kubernetes</blockquote><h3>Get your certificate</h3><p>I will cover one common way to do this via <a href="https://letsencrypt.org/?ref=chriskirby.net">Let’s Encrypt</a>. However, there are many other ways to generate your certificate. However, using <a href="https://github.com/acmesh-official/acme.sh?ref=chriskirby.net">acme.sh</a> combined with Cloudflare will do away with those annoying privacy warnings when accessing services locally over TLS, like your UDM-Pro, using the default private cert. The steps are simple, but you’ll need a few things to get started:</p><h3>Get a Cloudflare API key</h3><p>From your free (or paid) Cloudflare account with both DNS modify and read permissions on the Zone (domain/website) you want to use for your certificate. We’ll generate a wildcard certificate so that this certificate will work for many other services you have that support custom certificates, like your NAS, Proxmox, or Unifi. Cloudflare Dashboard -&gt; Manage Account -&gt; Account API Tokens</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/498/1*aXyKCcOYdABGgfH2cuzM2w.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*H7BmyqcHJPoHpYh32tQk-g.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*R9VEfmjAzG7YfW9-2Rp2Mg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5XJCqPOpZ0gKMuJfGm433A.png" /></figure><h3>Generate with acme.sh</h3><p>Install acme.sh and any dependencies you may need that aren’t included with the install script.</p><blockquote>Install acme.sh and generate the script on a machine that is running all the time, or regularly. The created cert will be automatically renewed from the machine it was created from and is only valid for 90 days. I recommend a Proxmox container or a raspberry pi thats always running.</blockquote><pre># Mac via homebrew <br>brew install curl socat openssl coreutils</pre><pre># Ubuntu or WSL <br>sudo apt update &amp;&amp; sudo apt install -y \ <br>  curl socat openssl ca-certificates cron</pre><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/00bc82b08f7920b2aac88aef3d3c9cd5/href">https://medium.com/media/00bc82b08f7920b2aac88aef3d3c9cd5/href</a></iframe><p>You now have the privkey.pem and the fullchain.pem files needed for your deployment!</p><h3>AdGuard configuration</h3><p>We now have everything we need to complete our configuration. Here is what your complete yaml file should look like:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ff8a506d1447f6d58ee869b3941466eb/href">https://medium.com/media/ff8a506d1447f6d58ee869b3941466eb/href</a></iframe><h3>Shipit 🐿️</h3><p>Running AdGuard in Kubernetes adds some complexity. If your home lab isn’t there yet, no worries! You can take everything you’ve done to this point and run your new AdGuard home instance via <a href="https://github.com/AdguardTeam/AdGuardHome/wiki/Docker?ref=chriskirby.net">Docker</a> or directly on <a href="https://github.com/AdguardTeam/AdGuardHome/wiki/Raspberry-Pi?ref=chriskirby.net">Metal</a> by following the <a href="https://github.com/AdguardTeam/AdGuardHome/wiki/Platforms?ref=chriskirby.net">community-supported guides</a>. Enjoy!</p><p>If you are still here, then let’s get into it. We’ll be running some kubectl commands on our already deployed cluster and configuring our custom values for an existing <a href="https://charts.gabe565.com/?ref=chriskirby.net">open-source chart for AdGuard</a>.</p><h3>Namespace and secrets</h3><p>Let’s set up our namespace and create a secret resource to store our new certificate. We’ll use that later to add it to a mounted volume for our pod in the helm deployment.</p><pre># Create the namespace <br>kubectl create namespace adguard-dns <br><br># Create the TLS secret from your certificate files <br>kubectl create secret tls adguard-tls-cert \ <br>  --cert=yourdomain-cert/fullchain.pem \ <br>  --key=yourdomain-cert/privkey.pem \ <br>  --namespace=adguard-dns <br><br># Add annotation to prevent Helm from deleting the secret <br>kubectl annotate secret adguard-tls-cert \ <br>  --namespace=adguard-dns \ &quot;helm.sh/resource-policy=keep&quot;</pre><pre># Add the Helm repository <br>helm repo add gabe565 https://charts.gabe565.com <br>helm repo update</pre><h3>Deploy via Helm</h3><p>First, we need to create our custom values file, which allows us to override some of the default configuration options the chart provides. We can also do this via command line arguments. However, I find this method more straightforward to understand and manage. I’m adding a custom configuration for my service, using the LoadBalancer to ensure my DNS ports are accessible outside the cluster, similar to Host networking in Docker. In the persistence section, I’m using Longhorn for my storage provider and creating a custom mount for my TLS cert. Finally, I’m adding probes to ensure the pods start and remain healthy.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6cf95263ff43b7b287b7277c179cc126/href">https://medium.com/media/6cf95263ff43b7b287b7277c179cc126/href</a></iframe><p>Deploy and re-deploy AdGuard home to your cluster.</p><pre># remove previous release, if any<br>helm delete adguard-home -n adguard-dns || true<br>      <br># Wait for pods to terminate<br>kubectl wait --for=delete pod --selector app.kubernetes.io/name=adguard-home -n adguard-dns --timeout=30s || true<br>      <br># remove the previous config which will be replaced by the new one<br># the data pvc will remain<br>kubectl delete pvc -n adguard-dns adguard-home-config --force --grace-period=0 || true<br><br># Install AdGuard Home<br>helm install adguard-home gabe565/adguard-home \<br>  --namespace adguard-dns \<br>  --values adguard-values.yaml \<br>  --set-file config=AdGuardHome.yaml \<br>  --set podAnnotations.recreate=$(sha256sum adguard-values.yaml | awk &#39;{print $1}&#39;) \<br>  --atomic \<br>  --cleanup-on-fail \<br>  --force \<br>  --replace \<br>  --reset-values \<br>  --wait</pre><p>Good luck, and feel free to let me know how it goes!</p><p><em>Originally published at </em><a href="https://chriskirby.net/migrating-from-pi-hole-to-adguard-home-with-some-upgrades-along-the-way/"><em>https://chriskirby.net</em></a><em> on December 20, 2024.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e8bf7d51b0c9" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Automate your Unifi network firewall and traffic rules with Home Assistant]]></title>
            <link>https://medium.com/@sirkirby/automate-your-unifi-network-firewall-and-traffic-rules-with-home-assistant-93f2b23bd138?source=rss-8c693b99d86a------2</link>
            <guid isPermaLink="false">https://medium.com/p/93f2b23bd138</guid>
            <category><![CDATA[home-assistant]]></category>
            <category><![CDATA[homelab]]></category>
            <category><![CDATA[unifi]]></category>
            <category><![CDATA[home-automation]]></category>
            <dc:creator><![CDATA[Chris Kirby]]></dc:creator>
            <pubDate>Sat, 21 Sep 2024 18:23:43 GMT</pubDate>
            <atom:updated>2024-10-17T19:24:57.420Z</atom:updated>
            <content:encoded><![CDATA[<p><a href="https://chriskirby.net/tag/homelab/">Homelab</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*6miaX8Emq5et1jMgZI0HBQ.png" /></figure><p>Unifi network traffic rules are one of the most valuable and versatile ways to manage traffic and devices on your network. It’s a feature that’s been around for a little while, and it enables you to quickly set up basic rules like blocking specific devices from accessing the internet at specific times, blocking particular domains and apps on the entire network, or even setting up speed limits on my guest network. One specific use case of interest to me right now is to help manage my kid’s screen time. My kids use many devices: phones, laptops, tablets, gaming handhelds, VR headsets, etc. There are usually ways to manage screen time on those devices individually, but it’s different for iOS, Windows, Chrome/Google, Meta, etc. Frankly, it’s too much. The common denominator is that all these devices need internet access, bringing us back to why we are here. Traffic rules will help identify and block all of those devices, even apps on those devices, but we lose some of the ease of use that many of those OS-specific screen time services provide. Services like extending screen time, temporarily disabling it, or enabling it on-demand. This is where <a href="https://www.home-assistant.io/?ref=chriskirby.net">Home Assistant</a> (HA) comes in. Like many of you, HA is the “brains” of my smart home and where all of my other devices and sensors integrate, which makes it an ideal choice to integrate this functionally in an easy-to-use way. We’re getting into the weeds on this one, so let’s get into it!</p><h3>Establishing the Rules</h3><p>Let’s create a rule or two. Navigate to Unif Network -&gt; Settings -&gt; Security -&gt; Traffic &amp; Firewall, where there are two tabs: Simple and Advanced. Simple is synonymous with Traffic rules, and Advanced is synonymous with Firewall rules. Though they are different and offer different features in the user interface, they are both essentially firewall rules. The difference is important, though, as Unifi stores them differently, which will matter when it’s time to integrate with HA. From what I can gather, a traffic rule is essentially a feature-wrapped firewall rule that allows you to do additional things, like set a schedule and target specific devices without setting up Profile groups or other more advanced ways of identifying devices on the network. It’s more or less a user-friendly way to set up a rather complicated thing, which is basically why you might want to use Unifi over something like <a href="https://pfsense.org/?ref=chriskirby.net">pfsense</a>, for example.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ukVAJEJ4msaT7ovMAGqV9g.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*wW9jFeIxTr0f_S_td9q5TQ.png" /></figure><h3>Integrating with UDM</h3><p>Currently, there is no officially supported way to integrate with most of the advanced features of Unfi devices, like my Dream Machine Pro SE. This may eventually change, given the recent announcement of an <a href="https://x.com/Ubiquiti/status/1828070162710368662?ref=chriskirby.net">official API</a>, but this first version focuses on integrating site manager with 3rd party applications. For now, we have to get a bit more creative and leverage some of the existing private APIs utilized by the web and mobile app interfaces we use today. I wanted to start with something simple: enable my spouse and I to quickly and easily turn the rules we’ve just established on and off. As you see above, I’m already leveraging the schedule feature of the traffic rule, which is fine most of the time, but we needed more flexibility than that. Perhaps there are exceptions; it’s the holidays, or they are on break, etc. Logging into the UDM network application, finding the rule, managing, and then pausing is fine and normal for me, but this is an interface for network administrators. And even though I know where to go and what to do, it’s far less than ideal for this type of functionality. I want Apple Home-level simplicity and the ability to set up automations and triggers. Now, <strong>let’s figure out how to do it!</strong></p><p>To help you (and me) along, I’ve created a <a href="https://www.usebruno.com/?ref=chriskirby.net">Bruno</a> collection with all of the requests you’ll need to get started. <a href="https://github.com/sirkirby/bruno-udm-api?ref=chriskirby.net">Get it on GitHub</a>.</p><h3>Logging in</h3><p>I’m going to log in programmatically just like the Unifi web interface logs in, by calling the private API. There are a couple of caveats to this. Typically, in a public API, I’m either assigned a token that I can use to access, or I authenticate to request and refresh a token. I do need a token here as well, but it’s stored in a cookie, and I also need to capture and send my CSRF token, which ensures my request is authentic.</p><p>First, I send a POST with my username and password in the JSON body, then I grab the cookie and the csrf-token and set them to environment variables, which I can use in subsequent requests. You&#39;ll also receive a full json payload with your user information, roles, groups, etc. Using a Local Admin account is necessary to get the required permissions to manage firewall rules. You can see here that I&#39;m using the local account homeassistant.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*m6KHXiKpDmMKcwM2CGhabw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/954/1*dYVeaKr1-nlOHZG4ho3YQw.png" /></figure><h3>Getting the Rules</h3><p>This was a little harder to discover, but with some investigation using the browser development tools and the help of <a href="https://claude.ai/?ref=chriskirby.net">Claude</a>, I found that we need two endpoints. One to pull the list of Firewall (advanced) rules, and one to get the list of Traffic (simple) rules. Here, I’m sending two separate GET requests, first pulling the csrf-token and cookie from the environment (saved from the login request) and then passing in the header. You&#39;ll receive a JSON array with each rule and its associated details.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JZc9y8tGwXeSReVWnGdMqQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2AUZl2A3XkTo2JNysE062Q.png" /></figure><h3>Toggling the Rules</h3><p>This one was even more challenging to discover and to get working correctly. To toggle the enabled flag on a Traffic or Firewall rule, we need to send back the entire rule, similar to what a form submission would do on a web page. So, let’s first get the individual rules to ensure we have the complete shape expected, modify the enabled property, and then post back the modified payload. Use caution here, as posting incorrect values could cause some severe issues. Here, you&#39;ll see that we have the same GET and PUT endpoint for Firewall rules and separate GET and PUT endpoints for Traffic rules, along with the full rule payload in both Toggle requests.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kUq1DRpT6t3StVnfQEO2tw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*HPD9-pGas6PGkTvjzq4Alg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_ZACtbrs0Xln7naUxAq6xg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*eoMJmbpc0GhI_VVWjPdkfA.png" /></figure><p>Now that we have proved we can modify both sets of rules via the API, it’s time to use that knowledge for home automation.</p><h3>Home Assistant</h3><p>HA has a rich ecosystem of integrations and components, and there are several out-of-the-box integrations for Unifi network and Unifi protect, both of which I highly recommend. In this case, I’m exposing more advanced functionality not covered by those existing extensions, which means building a new integration. More specifically, creating my own custom component. There are quite a few excellent tutorials, along with HA’s excellent <a href="https://developers.home-assistant.io/docs/creating_component_index?ref=chriskirby.net">developer documentation</a>. Still, since I’m not a Python developer and we are in the AI age, I leveraged Claude and ChatGPT to scaffold out my new integration. Many, many chats later, I had something that was starting to resemble the functionality I wanted. It was a great way to get to the 90% mark faster, but I needed good old-fashioned coding and debugging skills to get that last 10%. I’ve found this typical for prototyping and building apps with AI.</p><p>This integration has been tested on my local instance of HA, is open source, and is ready for anyone else to test and contribute to. <a href="https://github.com/sirkirby/ha-udm-rule-manager?ref=chriskirby.net">Get it on Github</a> and <a href="https://github.com/hacs/default/pull/2732?ref=chriskirby.net"><em>soon</em></a> via <a href="https://my.home-assistant.io/redirect/hacs_repository/?owner=sirkirby&amp;repository=unifi-network-rules&amp;category=integration&amp;ref=chriskirby.net">Home Assistant Community Store</a> (HACS)</p><h3>Configuration</h3><p>Once installed, go to Devices and Services and Add Integration, select the Unifi Rule Manager, and enter your UDM’s IP address, username, and password.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*vWfFSm-x_rIF0v_s.png" /></figure><h3>Entities</h3><p>Once configured, all your rules will now be available as switch entities, allowing you to toggle them on/off on demand. The integration will also look for changes every 5 minutes and pull those in as they occur.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*KQTjiVGzKNq8Ylk_.png" /></figure><h3>Build a Dashboard</h3><p>I love using custom dashboards in HA. They’re a great way to organize functionality around a room, topic, or set of devices. In this case, I created a new dashboard called Screen Time and will place the Traffic rules I want to toggle as big, giant buttons that are easy to use from your phone.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BKOZ1dakcFs4QQjKZly-Gg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*eaB2_PUHx1bQCA3MIx1eBA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*YYH4y7bE9EtowVj26NZdtQ.gif" /></figure><h3>Wrap up</h3><p>It was a non-trivial 😉 amount of work just for a few buttons, but it was a lot of fun, which is what it was all about for me. It’s working well, and I plan to keep it working as changes occur and as time allows. Good luck on your own integration and automation journey, and let me know how it goes!</p><p><em>Originally published at </em><a href="https://chriskirby.net/automate-your-unifi-network-firewall-and-traffic-rules-with-home-assistant/"><em>https://chriskirby.net</em></a><em> on September 21, 2024.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=93f2b23bd138" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Setting up and leveling up your homelab — a comprehensive guide]]></title>
            <link>https://medium.com/@sirkirby/setting-up-and-leveling-up-your-homelab-a-comprehensive-guide-ce47ef6fa21c?source=rss-8c693b99d86a------2</link>
            <guid isPermaLink="false">https://medium.com/p/ce47ef6fa21c</guid>
            <category><![CDATA[computer-networking]]></category>
            <category><![CDATA[kubernetes]]></category>
            <category><![CDATA[ubiquiti]]></category>
            <category><![CDATA[homelab]]></category>
            <category><![CDATA[dns]]></category>
            <dc:creator><![CDATA[Chris Kirby]]></dc:creator>
            <pubDate>Fri, 26 Jul 2024 18:24:14 GMT</pubDate>
            <atom:updated>2024-08-13T15:57:05.226Z</atom:updated>
            <content:encoded><![CDATA[<h3>Setting up and leveling up your homelab — a comprehensive guide</h3><p><a href="https://chriskirby.net/tag/homelab/">Homelab</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DF--a93Dfa7KaMQHyR0RiQ.png" /></figure><p>I’ve been running some form of a homelab for a long time now. From the early days of broadband, hosting my own active directory and email servers, to where I’m at today (which is quite a bit better, btw). I find owning and operating my own equipment and services to be both fun and rewarding. If you think you’re in the same camp, then you’re in the right place. I’m writing this guide to share some of the things I’ve learned, so if you’re starting out or looking for what to do next, perhaps you can grab an idea or two for your setup. I would always advise starting small, getting comfortable, and then deciding if you are ready for more.</p><h3>Goals</h3><p>I found it helpful first to identify what I was trying to accomplish. As a long-time software engineer, platform engineer, and engineering leader, I know certain practices and ideas have become second nature in the workplace. Ideas like the principle of least privilege and practices like Infrastructure as Code (IaC), Site Reliability Engineering (SRE), Automated Testing, and others can and probably should be applied to your personal production environment, your Home.</p><h3>Better privacy</h3><ul><li>I want better control over what data is collected about me and my family. This means first finding out what is being sent or tracked and then deciding what is acceptable and what isn’t.</li><li>I want an easy-to-configure “whole home” VPN for devices that either can’t run a VPN locally or don’t, along with an easy way to opt-out.</li><li>I want to ditch my cloud cameras and move to cameras that operate locally, which will give me full control over my live feeds, recordings, and integrations.</li></ul><h3>Better security</h3><ul><li>I want to isolate connected devices (IoT), such as smart speakers, smart appliances, thermostats, TVs, etc., from communicating with the other trusted devices on my network unless expressly allowed. If one of these devices, which I do not control, were to be compromised, I would like to minimize what a potential bad actor could access. This is often a best practice recommended by security professionals and even the <a href="https://www.fbi.gov/contact-us/field-offices/portland/news/press-releases/tech-tuesday-internet-of-things-iot?ref=chriskirby.net">FBI</a>.</li><li>I want to limit what guests can do on my network. Anyone who does not live here 24/7, does not need forever and unfettered access to my network. No more sharing the Wi-Fi password with extended family, friends, or house guests.</li><li>I want a network firewall that offers packet inspection, intrusion prevention, and other security and network features not found in typical consumer wifi routers or the junk most ISPs give you.</li></ul><h3>Better remote access</h3><ul><li>Once I set all of these services up, I want an easy way to access them. One of the first devices I purchased was a Synology NAS, which has been rock solid for me. There are a few ways to connect to it remotely, the main one being QuickConnect. I won’t get into how it works, but it has and does work fine; however, I want one way to access everything, including my NAS.</li><li>I want remote access to be simple and work on every device I own or have access to.</li><li>I want to avoid traditional VPN servers with broad network access when accessing the individual app or service will suffice without compromising security.</li></ul><blockquote>Such simple goals-no problem! Now, let’s take a look at some of the choices I made to accomplish these goals.</blockquote><h3>Network</h3><p><em>It all starts here, and it’s easier than you think</em></p><p>I’ve gone through many iterations over the years. My first “prosumer” router/firewall was a Sonicwall appliance. It was relatively easy to use, but was expensive, slow, and had subscription and add-on fees for more advanced features. Then I tried <a href="https://www.pfsense.org/?ref=chriskirby.net">pfsense</a>, and <a href="https://opnsense.org/?ref=chriskirby.net">OPNsense</a>, for a while, running on dedicated hardware, which is good but has a fairly high learning curve and had some strange limitations that ultimately caused me to move on to something else. Finally, I found the ubiquiti edgerouter, which was the perfect balance of cost and functionality…which eventually became unsupported in favor of the new, far superior, <a href="https://store.ui.com/us/en/pro/category/all-unifi-cloud-gateways/products/udm-se?ref=chriskirby.net">Unifi Dream Machine SE</a>, which is where I’m at today. Here’s some gear to consider then we’ll get into some configuration.</p><ul><li><a href="https://store.ui.com/us/en?category=all-unifi-cloud-gateways&amp;ref=chriskirby.net">Dream Machine</a>. This is the centerpiece and will manage the rest of your gear. If you have fiber, then go with the PRO series, as you’ll want the IPS routing speed to be at or greater than your connection speed. I currently have a 2.5GPS fiber connection and Starlink as a backup, which my PRO SE more than handles. How many devices you buy and adopt are also a factor here, so consider your future growth plans and size accordingly. The Dream Router and Unifi Express are great options for smaller setups especially if you are space-constrained.</li><li>Rack switching. There are so many things to consider here. I have a mix of 2.5GB, 1GB, 1GB PoE++, and 10GB network devices, spread across many floors, inside and outside. I started with a single <a href="https://store.ui.com/us/en/pro/category/switching-professional/products/usw-pro-24?ref=chriskirby.net">PoE Pro series switch</a>, which is still in use, and am currently expanding to the <a href="https://store.ui.com/us/en?category=switching-professional-max&amp;ref=chriskirby.net">Pro Max switches</a> with etherlighting. Given the investment, I would size up a bit if you can spend the money.</li><li><a href="https://store.ui.com/us/en?category=switching-utility&amp;ref=chriskirby.net">Utility switching</a>. I hard-wire everything I can. It’s more reliable, not subject to (most) interference, and I like to make and run cables. I use a mix of the Flex (PoE++ powered &amp; passthrough), Flex mini (PoE powered), Lite PoE (PoE+), and the new Ultra line. Overall, I prefer PoE powered and passthrough switches so that all of the power comes from the central rack, which is easier to manage in power outages and understand my overall power consumption.</li><li><a href="https://store.ui.com/us/en?category=all-wifi&amp;ref=chriskirby.net">Wi-FI</a>. The Unifi access points are powerful, so if your in a new-ish home, no need to overdo it, one or two access points will do. If, like me, you are in an old home with plaster and lathe, then you may need a lot more. I’m currently using a mix of the U6 gear and will likely leap to U7 gear at some point. Just know that U7, not only is it very new with little device support, but you’ll also want 2.5G PoE uplinks and at least a 2.5G internet connection to really take advantage. If that is not you, then a <a href="https://store.ui.com/us/en/pro/category/all-wifi/products/u6-pro?ref=chriskirby.net">U6 Pro</a> or a <a href="https://store.ui.com/us/en/pro/category/all-wifi/products/u6-lr?ref=chriskirby.net">U6 Long range</a> are great starting points. If that doesn’t cover it, then consider adding more coverage through smaller <a href="https://store.ui.com/us/en/pro/category/all-wifi/products/u6-plus?ref=chriskirby.net">U6+</a> APs. If you can’t hardwire and need to Mesh, then I love the <a href="https://store.ui.com/us/en/pro/category/all-wifi/products/u6-mesh?ref=chriskirby.net">U6 Mesh</a>. I use two inside, where ceiling mounting is not an option (still use PoE, but not necessary), and one outside for backyard coverage. Always hardwire the backhaul if you can.</li><li>Cameras. You’ve come this far, so why not go all in? The <a href="https://store.ui.com/us/en?category=all-cameras-nvrs&amp;ref=chriskirby.net">Protect cameras</a> are amazing, as is the software. Most can be powered via PoE and are managed with your Dream Machine or if you’re like me and want more storage retention and protection from drive failure, a dedicated <a href="https://store.ui.com/us/en?category=cameras-nvr&amp;ref=chriskirby.net">NVR</a>. My goal was to move away from cloud cameras, so this was an easy choice.</li></ul><h4>VLANS!</h4><p>An advanced and sometimes confusing, essential part of your homelab. Most consumer routers typically have one LAN, like 192.168.1.0/24. One LAN means all devices connected to your WiFi will all be on the same network talking to each other. To accomplish my privacy and security goals, I needed multiple LANs and multiple WiFI networks, so it was time to make the leap into virtual local area networks. I say leap because once you start putting devices on different networks that do need to talk to each other, like your Hue hub and your phone for example, it no longer works without some new firewall rules and profiles you will have to create. It’s going to require a little bit of work and trial and error, but it’s worth it. I’m not the best person to walk you through this, so instead, I will point you to the resources I used in setting up my VLANs. Check out <a href="https://www.youtube.com/watch?v=JszGeQPTo4w&amp;ref=chriskirby.net">VLANs made easy</a> and <a href="https://www.youtube.com/watch?v=6ElI8QeYbZQ&amp;ref=chriskirby.net">Secure IoT Network</a> configuration, as you’ll need this knowledge to keep everything working together correctly. Once done, you may want a similar setup to mine:</p><ul><li>Default — the LAN you first set up with your router, is now my trusted device network where all of my family’s personal devices are connected and has a <strong>dedicated WiFI SSID</strong>.</li><li>IoT — my first VLAN created for all “smart” devices on my network that require internet access and are not personal devices. Devices on this network are not permitted to communicate with any device on the Default network, but are allowed to communicate with other devices on the IoT network. This also has a <strong>dedicated SSID</strong>, so anything joining that WiFI SSID will be on the IoT network.</li><li>Guest — a network dedicated for people who need temporary access, like house guests, friends, etc. Devices on this network can access the internet, cannot access any other networks, and can not access or see any other device on the guest network (device isolation). A dedicated and unencrypted WiFI SSID controls access to this network with a hotspot landing page, where you enter a password and accept terms, similar to a coffee shop or a hotel. After 24 hours access is automatically removed.</li><li>Secure — a network similar to the Default network, but all internet access flows through an always-on <a href="https://chriskirby.net/upgrade-your-online-privacy-and-security-on-any-budget/">Proton VPN</a> tunnel. Once connected via a dedicated WiFI SSID, all traffic is secure, and no VPN app is required.</li><li>Homelab — a network dedicated to hardware and services that I host within my homelab. Devices on this network have full access to the internet and can talk to other networks. I created this primarily to get a dedicated pool of IP addresses, so I have plenty of room to expand. I’m slightly less concerned about isolation between this and my default and IoT network. For example, Home Assistant lives on Homelab and interacts with select devices in IoT and Default, and that’s what I need it to do. No WiFI SSID is associated with this network, as everything is connected via Cat-6.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uZhkdQPNSuJtdI5hVSvB0w.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1cn-JnLs6Be_HrSSTRt4sw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XiV0kTxnLw-PXnLgkIOBQA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dxl3vn96Tf5Rm1QKG_P5NQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*iyvnJXZ5o1gvl-aieigdDA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JgLXZD6B0qIaiRptgRjCFQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Zh7sxbEvci0v8FjjZG0Sjg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*FBQaNQV9327GK2hVP5IOog.png" /><figcaption>Unifi Network Setting Screenshots</figcaption></figure><h4>VLAN Considerations</h4><ul><li>For AirPlay, Chromecast, and similar devices on separate VLANs, enable IGMP Snooping and mDNS (bonjour) to ensure multicast works properly. If you are still having difficulty, you may want to specify LAN IN firewall rules based on the service network/default/settings/security/firewall-rules.</li><li>Sonos with VLANS. Many have tried, many have failed. The tldr; is that Sonos does not play well with VLANs. Check <a href="https://www.reddit.com/r/sonos/?ref=chriskirby.net">r/sonos</a> and <a href="https://www.reddit.com/r/UNIFI/?ref=chriskirby.net">r/UNIFI</a> for the latest; however, I recommend leaving your speakers on Default to save yourself the headache.</li></ul><h4>Firewall Rules &amp; Profiles</h4><p>The videos I reference above cover many of the basics, but I’ll cover some of them here as well since they are essential for your initial setup. Once you start putting devices, like your Hue bridge for example, on your IoT network, you’ll still want access from your personal devices in order to maintain the functionality you are used to. This will get you started.</p><p>Create a new IP Group Profile called <strong>Private Local Networks</strong> network/default/settings/profiles/port-ip-groups and add the following:</p><ul><li>192.168.0.0/16</li><li>10.0.0.0/8</li><li>172.16.0.0/12</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*R2U9w8pkFtaaZr4W.png" /></figure><p>Create a new <em>LAN in</em> firewall rule called <strong>Allow established and related</strong>. This rule essentially allows devices on other VLANs to “talk back” if established on the Default network, but devices on the VLAN cannot initiate a connection to the Default network.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*TQz9PONUncFLVykq.png" /></figure><p>Create a new LAN in firewall rule called Allow LAN to anywhere. This rule allows devices on the Default network to communicate with devices on any VLAN.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*zjQWLVPjr-ehJ3qf.png" /></figure><p>This is just the start and we’ll cover more rules when I talk about services, like DNS, further down.</p><h3>Storage</h3><p><em>Your personal cloud storage for videos, photos, and backups</em></p><p>Resilient, high capacity, shared storage was at the top of my list, as it’s central to achieving all my homelab goals. There are so many ways to approach this, however I will keep my recommendations simple here. Get a dedicated network-attached storage (NAS) device, add some <a href="https://www.amazon.com/Western-Digital-Plus-Internal-Drive/dp/B09QQX27GM?ref=chriskirby.net">Western Digitial Red drives</a>, set up some shares, and now you’ve got plenty of storage accessible by any device on your network to store your photos, movies, backups, and more. I highly recommend <a href="https://www.synology.com/en-us/products/DS923+?ref=chriskirby.net">Synology</a>, as it’s easy to configure, has a full suite of out-of-the-box and community software (photos, video, docker), you can expand your storage over time using their proprietary raid format (saving big money), and they seem to last damn near forever. I have two 4-bay NAS devices from them and my first one is still running on the original drives for 10 years now and counting (still gets security updates but no new features). Going on 4 years for my second NAS. If you don’t want a dedicated appliance and feel like rolling your own, then it’s <a href="https://www.truenas.com/?ref=chriskirby.net">TrueNAS</a>. Powerful, flexible, and based on the hardware you have or buy, you could run your entire homelab in it with its equally expansive 3rd party app support.</p><h3>Considerations</h3><ul><li>Hard drives can fail, especially if you are not using ones designed for 24/7 operation. Multiple drives in a RAID or ZFS configuration are a must if your data is to survive.</li><li>Backup your must-not-lose data to the cloud on a regular schedule. Synology has an app called Hyper-Backup that allows you to select files and folders, encrypt them, and then send them to a cloud provider like Azure Blob Storage, AWS Glacier, Dropbox, and many others. It’s cost-effective and will provide you with some peace of mind.</li><li>A dedicated appliance can also host services like Plex, Pi-Hole, and Docker, as discussed below. Note that these devices are very constrained in terms of memory and compute power and lack dedicated GPUs for transcoding. Consider what your plans are for this device and shop accordingly. The higher desktop and rack-mounted Synology models pack considerably more computing, have memory expansion and high-speed networking…and are considerably more expensive. For me, it’s storage, backup, light media and containers, and that’s it. It keeps my costs down and gets me exactly what I want from a device like this.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*RY4bu2emmDldcSLoCpq2Zg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*IziGauM7BZSFrH4kIoI4IA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*me_oCFgU95Wy1P0LMJwbEg.png" /></figure><h3>Taking up space</h3><p><em>Time to get the tools out and install some stuff</em></p><p>Homelabs come in all shapes and sizes. For me, it started as an old Dell Windows desktop and a Raspberry Pi and then moved to a 42u rack with networking, storage, IoT, and mini-PCs. Budget, space, power, and climate are factors I would consider when approaching this, but this is what’s worked for me.</p><h4>Rack mounting</h4><p>Rack everything that can be racked. It’s a universal standard for networking equipment, servers, along with shelves, storage, and so much more. I have two racks in two separate locations. one 42u rack, which I consider the homelab and where the majority of devices are, and I have a 25u rack in my office, which keeps my office networking, receiver, and game consoles (you can rack those).</p><ul><li><a href="https://www.amazon.com/StarTech-Network-Rolling-Computer-Equipment/dp/B00HVKOPBW?ref=chriskirby.net">StarTech open rack</a>. I rack gear on the front and the back, as you can control the depth, and it’s affordable. It’s also easy to keep cool, and I still have a bit more room for future expansion.</li><li><a href="https://www.amazon.com/StarTech-com-Server-Rack-Shelf-Cantilever/dp/B008X3JHJQ?ref=chriskirby.net">StarTech shelves</a>. These are for anything you can’t rack, like your NAS, your Starlink router, mini-pc’s, etc. I have many of these and I love them. I recommend the 2u for heavy stuff and the 1u for the small and light stuff. There is no need to take up more space than you need.</li><li><a href="https://www.amazon.com/Rackstuds-R100-Rack-Mount-Solution/dp/B07W57W234?ref=chriskirby.net">Rack Studs</a>. Forget the nuts and screws, Rack Studs all the way. You will thank me…and them for making such an awesome thing.</li><li><a href="https://www.amazon.com/s?k=rack+mount+pdu&amp;i=electronics&amp;crid=2NVULHR8390BC&amp;sprefix=rack+mount+pdu%2Celectronics%2C73&amp;ref=chriskirby.net">Rack mounted PDUs</a>. I use these, as well as Unifi’s power gear, but they are a cost-effective way to get started with power management.</li><li><a href="https://www.amazon.com/s?k=thin+cat6+patch+cable&amp;i=electronics&amp;crid=UC3UMXRQUMOV&amp;sprefix=thin+cat%2Celectronics%2C77&amp;ref=chriskirby.net">Slim Cat-6 patch cables</a>. I LOVE these, and they can also handle PoE (it varies by brand). They are much easier to manipulate and cable manage and come in all sizes. I make a lot of my own cable as well, but I use these on the rack.</li><li>Rack patch panels. You can buy them with the inline keystones or by the panel and keystones separately; it just depends on what you want to do. I have some patch panels with <a href="https://www.amazon.com/Keystone-Support-Rapink-Shielded-Removable/dp/B092QX76QJ?ref=chriskirby.net">inline keystones</a> and some <a href="https://www.amazon.com/TRENDnet-24-Port-Keystone-Rackmount-TC-KP24/dp/B07M5QBL8G?ref=chriskirby.net">blank panels</a>. I love the blank ones for putting in a mix of <a href="https://www.amazon.com/Keystone-Inserts-Adapters-Connector-Coupler/dp/B08ZN247XV?ref=chriskirby.net">USB</a>, <a href="https://www.amazon.com/Cable-Matters-2-Pack-Keystone-Coupler/dp/B09JV2FM85?ref=chriskirby.net">HDMI</a>, and <a href="https://www.amazon.com/Cable-Matters-5-Pack-Multimode-Keystone/dp/B01B5AG0TI?ref=chriskirby.net">Fiber</a> keystones for easy connectivity to rack-mounted gear.</li></ul><h4>Metal</h4><p>You’ll need some metal to run your local data center properly. My current setup relies on mini-PCs and a few Raspberry Pi 4s. They are inexpensive, cool and quiet, and power efficient. I’m not trying to be a data center; I’m just trying to block some ads. There are quite a few choices here, and they do matter based on your plan. I suggest keeping it simple, though I rarely follow my own advice 🤓.</p><ul><li><a href="https://www.amazon.com/gp/product/B0CTTMV3N8?ref=chriskirby.net">MINISFORUM PC</a>. I only have one, and it hosts many of my more resource-intensive services. There are lots of sizes and shapes, but if you want a mini-PC with a discrete GPU, more CPU and RAM, and 2.5G networking, then look no further. I love it and will buy more when I need to expand.</li><li><a href="https://www.amazon.com/gp/product/B0C339KVH9?ref=chriskirby.net">Beelink Mini PC</a>. I bought three of these, primarily to serve as my K3s control-plane nodes. They are very inexpensive, have some expandability, and have dual 2.5G networking-a perfect combo for me. Three of these cost as much as one of the MINISFORUM. For me, these are about introducing some physical High Availability, not about the muscle.</li><li><a href="https://www.amazon.com/gp/product/B09STTXWZZ?ref=chriskirby.net">Rack-mounted Raspberry Pi </a>4’s, <a href="https://www.amazon.com/SABRENT-SATA-USB-Cable-Converter/dp/B011M8YACM?ref=chriskirby.net">with SSD’s</a> and PoE hats. I love Raspberry Pi’s, they have amazing utility. They aren’t the device to do anything substantial, but for services like DNS, reverse-proxy tunnels, cron jobs, they are perfect. They run on 5W of PoE each and are an indispensable part of my homelab.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qR6ZZ2rpH3sK57c_2e69LA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ntZHhWvlzJUYQWuvvvvmDQ.png" /></figure><h3>Virtualization with Proxmox</h3><p><em>Bring the cloud to your homelab</em></p><p>It’s time to get into some software. I will keep this simple. Other than my PIs, I don’t run any services on the metal directly. Server management is hard and can get very enterprizey very quickly. Hardware management is virtual now, we spin up a new VM or service in Azure or AWS and delete it when we’re done. It should still be that easy at home, so let’s discuss how we can get close to that. This will get you started, but there is much more to delve into as you get comfortable.</p><p>Other than the Pis, if it’s running in my homelab, then it’s running on <a href="https://www.proxmox.com/en/proxmox-virtual-environment/overview?ref=chriskirby.net">Proxmox VE</a>. Proxmox not only makes hardware management easy through its easy-to-use UI and terminal but also supports clustering and high availability out of the box. I won’t list <a href="https://www.proxmox.com/en/proxmox-virtual-environment/features?ref=chriskirby.net">all the features</a> here; know it’s free to use, supports near-native performance VMs and Linux containers, and runs on almost anything. There is an excellent <a href="https://forum.proxmox.com/?ref=chriskirby.net">support community</a>, which I contribute to, and has helped me out more than a few times. I’ve used Proxmox VE for many years, and I expect many more years to come…don’t homelab without it.</p><blockquote><a href="https://tteck.github.io/Proxmox/?ref=chriskirby.net#proxmox-ve-tools"><em>Proxmox VE helper scripts</em></a><em>. An assortment of scripts to help you automate and manage Proxmox. Along with some useful scripts to help you set up your services in Proxmox containers. </em>Thanks for the tip Andy!</blockquote><h4>Volumes and backup</h4><p>Using your NAS as a primary storage device for Proxmox is a great way to get started. First, add a volume share to Proxmox using NFS: Datacenter -&gt; Storage -&gt; Add -&gt; NFS. This is now shared with every node in your cluster and can be used to store your virtual disks, backups, and ISO images. It is network-attached storage, so it will be a bit slower (1G fine, 2.5G better). However, you get the full resiliency of your NAS to protect from data loss. Unless disk latency is paramount, consider this as a good option for all of the above. For everything else, a local volume running on an SSD with regular backups to the NAS.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/750/1*zth_qlwpiNK7GrvO-0MA7Q.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uWn8d0H3-bC9tY6r5eROfw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*EgYJymW5OxetZnJX_3mVEw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vVNekzQggHJfyfBVuM488A.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*nsfGZ3V-QROKYlO8b2hxhw.png" /></figure><h4>Networking</h4><p>One of my favorite features of Proxmox is the software-defined network. In these screenshots, you can see that I have two bridge networks defined on the host bound to the physical network devices: vmbr0 (bridge) to enp1s0 (nic) and vmbr1 to enp2s0 and I&#39;ve given the bridge a static IP on the homelab network. Now see my homebridge container, which has two virtual network interfaces, one on the default VLAN (homelab) and one on a separate VLAN (110 aka IoT). Both interfaces use the vmbr0 bridge, which is assigned to only one physical nic. This allows homebridge to easily discover devices within the IoT network while existing and being managed on the homelab network over a single physical device. I use a similar configuration for Home Assistant. Overall, it is more flexible than using port profiles and attempting this same configuration on my managed switches. Sometimes, what should work doesn&#39;t, so this is a clean way to cut through that. I find it best to keep the configuration close to the implementation.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*r8PWZs47ius_wp-fHpCCjw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2M8Gw4cw3u0d4AVkvklzlg.png" /></figure><h4>Cloning</h4><p>This feature can be your best friend when setting up multiple VMs of the same type or having a ready-to-go Ubuntu VM fully updated with your SSH key to save you time. Set up your VM in the usual way and get it all configured, then right-click the VM and select Clone. This is a massive time saver and worth mentioning.</p><h3>Kubernetes</h3><p><em>Containerize your homelab</em></p><p>Proxmox is up and running, managing the metal and some key services, so it’s a solid foundation for the next layer. With Kubernetes, we have a fully managed way to host services that are resilient, auto-scale, and easy to manage and deploy with Infrastructure as Code (IaC) tooling like <a href="https://www.terraform.io/?ref=chriskirby.net">Terraform</a> and <a href="https://helm.sh/?ref=chriskirby.net">Helm</a>. This is where things really get fun. So let’s set up a cluster and get things ready to deploy some homelab essentials. I highly recommend running <a href="https://k3s.io/?ref=chriskirby.net">k3s</a> in your homelab, as it’s a certified Kubernetes distribution with a single binary and can run on a wide variety of devices.</p><p>Rather than repeat myself, I have a good setup guide in another post. I discuss how to get your k3s cluster up and running, along with setting up kube-vip, which I recommend you do as well. For each node in your cluster, I recommend three Proxmox VMs running the latest LTS release of <a href="https://ubuntu.com/download/server?ref=chriskirby.net">Ubuntu server</a>.</p><blockquote><a href="https://chriskirby.net/highly-available-pi-hole-setup-in-kubernetes-with-secure-dns-over-https-doh/">Highly available Pi-hole setup in Kubernetes with secure DNS over HTTPS DoH</a></blockquote><h4>Recommended Addons and Tools</h4><ul><li><a href="https://kube-vip.io/?ref=chriskirby.net">kube-vip</a> — Adds high availability to your cluster through a virtual IP (VIP) and control-plane and service load balancing. Use their <a href="https://github.com/kube-vip/helm-charts?ref=chriskirby.net">Helm chart</a> to deploy or via <a href="https://kube-vip.io/docs/installation/daemonset/?ref=chriskirby.net">kubectl</a> to apply directly.</li><li><a href="https://longhorn.io/?ref=chriskirby.net">longhorn</a> — Adds highly available distributed block storage to your cluster. A great way to add persistent storage to your cluster, along with regular volume backups. This has saved me more than a few times and gives me confidence when doing some basic maintenance.</li><li><a href="https://docs.nginx.com/nginx-ingress-controller/installation/installing-nic/installation-with-helm/?ref=chriskirby.net">nginx</a> — k3s ships with <a href="https://doc.traefik.io/traefik/providers/kubernetes-ingress/?ref=chriskirby.net">traefik</a>, which works well, however some may prefer or be used to nginx. Many helm charts ship with annotations for nginx, so you may just want the option and have both.</li><li><a href="https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/?ref=chriskirby.net">Kubernetes dashboard</a> — A nice web interface for managing your cluster, with your cluster.</li><li><a href="https://k8slens.dev/?ref=chriskirby.net">Lens</a> — The best way to manage your cluster. It’s free for personal use and will help you better understand Kubernetes and well as easily maintain your cluster. Absolutely indispensable for me and probably wouldn’t continue running Kubernetes in my homelab without it.</li><li><a href="https://app.warp.dev/referral/EJK58L?ref=chriskirby.net">Warp</a> — The best terminal for Mac, Linux, and now Windows.</li><li>CLI Tools — brew install kubernetes-cli helm</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZE119FMIwaKgp2wNGgdhLw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Z8aPvmEoggEMl15894gHwA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qua_qyEbbt8PXHY88HZvxA.png" /></figure><h3>Services</h3><p><em>Deploy, configure, get your homelab up and running</em></p><p>We’ve now covered how I organize, host, and run my devices, which is ever-evolving. Now let’s go through what I run in my homelab to bring it all together.</p><h4>Secure DNS with Pi-Hole</h4><p>Basic privacy starts with DNS. It is such a simple thing yet it has quite a bit of complexity. DNS is an OG internet protocol and service that has received many privacy-related upgrades over the years; however, backward compatibility remains. By hosting your own, you get the best of both: maximum compatibility with the latest security.</p><p>First, decide how you want to run Pi-Hole. There are so many ways, and I’ve probably done all of them. I started with a single Raspberry Pi until the SD card failed…which took down the “internet.” If I was going to do this, then I needed to <em>do this</em>. It should be highly available, to make it <em>hard to kill</em>, along with faster and resilient storage, making it <em>hard to break </em>(sounds like a 90’s Segal or Van Damme movie 🥷). I have several other posts on this as I progressed in my journey; check these out as they cover the majority of my setup. Once back, let’s get into some firewall rules to round things out.</p><blockquote><a href="https://chriskirby.net/highly-available-pi-hole-setup-with-secure-dns-queries-to-cloudflare/">Highly available Pi-hole setup with secure DNS queries to Cloudflare</a></blockquote><blockquote><a href="https://chriskirby.net/highly-available-pi-hole-setup-in-kubernetes-with-secure-dns-over-https-doh/">Highly available Pi-hole setup in Kubernetes with secure DNS over HTTPS DoH</a></blockquote><blockquote><a href="https://chriskirby.net/load-balanced-and-highly-avaialble-local-dns-with-dnsdist-and-keepalived/">Load balanced and highly available local DNS with DNSDist and Keepalived</a></blockquote><p>Ok, so Pi-Hole is up and running, is highly available, and is resilient. Now I want to ensure every device on my network can only use Pi-Hole to resolve DNS queries. Now this is a little difficult. Devices can set their own DNS servers, even when using DHCP. Certain devices from Amazon, Apple, and others are especially disobedient and will either try to force 1.1.1.1 or even a public DoH address. My solution is a set of firewall rules to drop the DNS requests that misbehave. No Pi-Hole, no internet. It&#39;s not perfect, especially with DoH, as they just look like normal 443 traffic, but there are ways, and this will get you started.</p><h4>VLAN access to Pi-Hole</h4><p>Make sure your devices on other VLANs can reach your Pi-Hole servers. First create a <em>Profile IP Group</em> <strong>Pi-Hole DNS Servers</strong> and enter the IP addresses of each server. Then create two additional <em>Port Groups</em>: one to define the DNS Ports called DNS, and one to define DNS DoH ports called TLS-DoH (you’ll use this later). Finally, create the LAN In rule to allow devices on your VLAN to access Pi-Hole DNS on any other VLAN called Allow IoT Pi-Hole DNS.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*unmKK6Ux_QCfJC7mX3jnrQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hLUArymbHPXdN3KbWs3WKg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*TeqAZlNSgIkT9Y1th8-I0A.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JgQJNwZjL7QATGUdB0b8CQ.png" /></figure><h4>Block 3rd Party DNS</h4><p>Now, it’s time to block access to all DNS requests that attempt to circumvent Pi-Hole. As I stated above, these settings can be manually changed; some devices ignore your settings and use their own, and some devices and browsers use DNS over HTTPS or DoH, by default. DoH is great, and how I resolve any queries that come through Pi-Hole, through providers I trust with rules I maintain. Here’s what we can do to block the ones we don’t.</p><p>Create two new <em>Profile IP Groups</em> containing the list of public DNS DoH providers, <strong>Public-DNS-IPv4</strong> and <strong>Public-DNS-IPv6</strong>. I’ve created a Gist below to help get you started. This will cover the main public providers, and I provide a few links in the comments of the Gist for lesser-known providers you may want to add for good measure. For reference, I have about 200 IP4 and 55 IP6 addresses in my lists and counting.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/178b453db0eb5c838a308628b2ef75e8/href">https://medium.com/media/178b453db0eb5c838a308628b2ef75e8/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*773GQDe6H8GD_6TKqFJWOA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7VTKX4phaCOCFXCwsFQ7PQ.png" /></figure><p>Now create some new Internet firewall rules that will allow us to access public DoH servers from our Pi-Holes and not anywhere else. Create two new <em>Internet Out</em> rules to Accept all DNS traffic from Pi-Hole servers and two new <em>Internet Out</em> rules that Drop all other DNS traffic from non-Pi-Hole servers. The Accept rules should be above the Drop rules; order matters.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*SQW8QbxSCVqScmklWA2VCw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*HPHWlSme7Wm18IfpIb5MeA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*i6XMzKz3GlUEyJY8LHMK-A.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BF1T6HN33-jac-mxhpO5NQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*248EoNVnvZtshth9DR90Jg.png" /></figure><h4>Remote Access with Cloudflare ZeroTrust</h4><p>I love Cloudflare ZeroTrust, so much so, that I’ve already written several posts on my journey. Check those out first, then come back for some new tips and changes since then.</p><blockquote><a href="https://chriskirby.net/replace-your-homelab-vpn-with-cloudflare-zero-trust/">Replace your Homelab VPN with Cloudflare Zero Trust</a></blockquote><blockquote><a href="https://chriskirby.net/use-your-domain-with-cloudflare-to-securely-access-services-on-your-home-network/">Use your domain with Cloudflare to securely access services on your home network</a></blockquote><blockquote><a href="https://chriskirby.net/load-balanced-highly-available-cloudflare-tunnels-with-docker-swarm/">Load balanced highly available Cloudflare tunnels with Docker Swarm</a></blockquote><p>Through those articles, you’ve seen how to deploy cloudflared tunnels to your Kubernetes cluster, leverage your local Pi-Hole DNS servers via the Warp client split tunnels, and use your own domain with TLS termination to access all of your services remotely and securely-very cool stuff. By now, you’ve guessed that I’m a fan of making my services highly available. Here are some things you can do just to add a bit more resiliency to your homelab.</p><h4>Run additional cloudflared tunnel containers on your NAS</h4><p>Maybe your k3s cluster is down, or maybe you’re doing some maintenance, but why not have a few extra tunnels running just in case? Running lightweight containers on your always on NAS is a simple way to add some additional piece of mind. Create a new tunnel in your ZeroTrust dashboard Network -&gt; Tunnels. Once created, you can create as many instances of the tunnel as you want to. For this tunnel, I’m setting up several of my local VLAN routes, to ensure I always have remote, VPN style, access to my network with the Warp client. If my k3s tunnels fail, and I lose public app access, I’ll still have local network access through this set of tunnels running on separate metal.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*yJBvMP1cNlEY-JcKTMJhQw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/908/1*tYGGXv5Cvd0h0VBmtWo5Yw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Fymk6fCi_YmTJ6NwpXeUHg.png" /></figure><h4>Terraform your ZeroTrust configuration</h4><p>Click-ops is a fine practice for getting up and running, however, I prefer the IaC approach. Terraform is easy to use and, with the help of ChatGPT, easy to get started with your configuration. Here is a snapshot of the Terraform to see how straightforward it is using the <a href="https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs?ref=chriskirby.net">Cloudflare Terraform provider</a>. If anyone is interested in the code, perhaps I’ll throw it up on Github, let me know.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/542/1*sjnF4d4wXtVGtQ_C2b3SNw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*k7AQ44NrzeXIqkjMZF0eKg.png" /></figure><h4>Home Automation with Home Assistant</h4><p>The ultimate automation services for everything in your smart home. I integrate my home solar and storage, all of my lighting, locks, Unifi network and camera, and even some custom integrations I created myself. The <a href="https://www.home-assistant.io/help/?ref=chriskirby.net">community for HA</a> is awesome, which will make getting started very easy. I recommend installing via one of the <a href="https://tteck.github.io/Proxmox/?ref=chriskirby.net#home-assistant">Proxmox scripts here</a>. I’m currently using the VM script, which I find the most flexible as I need to pass through several physical USB devices, like Zigbee, Z-Wave, and Bluetooth antennas. I would recommend a good amount of CPU cores and a healthy amount of RAM if you are a heavy user like me. You’ll also notice that I have several network adapters, to help with device discovery on separate VLANs.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*IIZZ3sIdBBS_1zft0418Qw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*wKNMtO6RnUA--1ygBJUaOw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BzAsRZ_xX7Xhn0rQJk6NWA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_cNLZoGaG7xX51l_x4yE6Q.png" /></figure><h4>HACS</h4><p>The <a href="https://hacs.xyz/?ref=chriskirby.net">Home Assistant Community Store</a> (HACS) is a must-have once you’re up and running. The officially supported add-ons are essential. However, there are a few blind spots. I use some community integrations for my Govee lights and many others.</p><h4>Homekit integration with Homebridge</h4><p>If you are a HomePod/Homekit family, then Homebridge is a must-have addition to your homelab. <a href="https://homebridge.io/?ref=chriskirby.net">Homebridge</a> acts as an unofficial bridge that can be added as a device to your Apple Home ecosystem and allows you to bring smart devices that are not officially supported to Homekit. This allows me to reliably control Switchbot, Elgato lights, LG TV, and a few others. It is very well suited to host on a lightweight <a href="https://tteck.github.io/Proxmox/?ref=chriskirby.net#homebridge-lxc">Proxmox LXC container</a>. Here are some snapshots of my Proxmox config, homebridge dashboard, and the Apple Home app on my phone showing the integration.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*iHsCag1LVVpwMqdWeONOjg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*SGXC-oGNVWNbChpvcDp9sQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*i7OV5guhndXZXu4PPlX9Pw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8YjA1kKe7CX866tMRCYFkA.png" /></figure><h4>Cameras with Scrypted</h4><p>Forget the integrations for Home Assistant and Homebridge for your Unifi, Nest, Ring, etc cameras; this is what you want. <a href="https://www.scrypted.app/?ref=chriskirby.net">Scrypted</a> pulls the RTSPS streams from my cameras, and then rebroadcasts the feeds to Homekit. Once my Protect cameras are integrated with Scrypted via their Unifi plugin (you’ll set up a special local login on your console), I simply enable the Homekit plugin on each Camera, and then I can Scan and add the camera like any other Apple Home accessory. This enables things like Apple TV, phone, and watch popups and video notifications from my <a href="https://store.ui.com/us/en/pro/category/cameras-doorbells/collections/pro-store-doorbells-chimes/products/uvc-g4-doorbell-pro-poe-kit?variant=UVC-G4+Doorbell+Pro+PoE+Kit&amp;ref=chriskirby.net">G4 Doorbell Pro</a>, as if it was all meant to work together. You can even enable recording for people and package detection, as Unifi’s AI detection does not natively work with Apple. This project is just awesome. They also have an excellent paid <a href="https://docs.scrypted.app/scrypted-nvr/?ref=chriskirby.net">NVR service</a>, which if you’re not using a local NVR like me, will give you similar functionality.</p><blockquote><em>Deep cut, </em><a href="https://github.com/koush?ref=chriskirby.net"><em>Koushik Dutta (koush)</em></a><em> is the developer and I used to use his Android ROM’s and tools back in the day. Still killing it!</em></blockquote><p>Hosting with a Proxmox container is the recommended way to run Scrypted, and they provide an <a href="https://docs.scrypted.app/installation.html?ref=chriskirby.net#proxmox-ve">install script</a> that will also enable hardware encoding support for your camera streams. This one runs on my MINISFORUM mini PC, with dedicated graphics and it works very well. This will consume a decent amount of CPU, so make sure you run this on something that can handle it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*bNbHzOfTzDiIYxAsvRbpHQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3I4yWQ2pJnbtQV4jaR2BBA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9_Hx2KcohxiUZisXgdllBw.png" /></figure><h4>Media with Plex</h4><p><a href="https://www.plex.tv/?ref=chriskirby.net">Plex</a> needs no introduction. I need a seamless way to stream all of it at home and when I’m away, and there is no better way than Plex. By itself, Plex is pretty great. It will run on an old Windows machine with a big hard drive just fine…which is exactly how I used to do it. As you’ve seen by now, we can do much better than that. First, I don’t need UPNP or port forwarding for Plex, It’s a configured app with Cloudflare ZeroTrust, which is how I access it remotely. Second, I keep all of my media on my two NAS devices, which are locally resilient and backed up to the cloud every night. Finally, I have Proxmox to host my server in an LXC container with full hardware acceleration support.</p><h4>Install and configure</h4><p>Start with this <a href="https://tteck.github.io/Proxmox/?ref=chriskirby.net#plex-media-server-lxc">handy script</a> to install Plex on one of your Proxmox nodes. Don’t overthink the resource allocation, as you can always just allocate it later. If you need frequent transcoding, then you’ll need to allocate a larger amount of resources. However, if you direct play most of your content, it will use very little CPU. Plex does like RAM, so be more generous there.</p><h4>Mount your NFS shares to Plex</h4><p>SSH into your new Plex server or open the Console in the Proxmox web interface. From there install NFS support sudo apt install nfs-common and then edit your /etc/fstab file sudo nano /etc/fstab and add entries to mount your NFS shares.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b00cf9ab76c26e0eb8df00f131264fcc/href">https://medium.com/media/b00cf9ab76c26e0eb8df00f131264fcc/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*s-zxiwU4vGdaJBf-.png" /></figure><h3>Conclusion</h3><p><em>All posts must end</em></p><p>There’s more, but this post is long enough 😀. It was fun to write, and I hope it helps you with your own homelab or inspires you to start one. Good luck, and feel free to reach out and let me know how it goes!</p><p><em>Originally published at </em><a href="https://chriskirby.net/setting-up-and-leveling-up-your-homelab-a-comprehensive-guide/"><em>https://chriskirby.net</em></a><em> on July 26, 2024.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ce47ef6fa21c" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Upgrade your online privacy and security on any budget]]></title>
            <link>https://medium.com/@sirkirby/upgrade-your-online-privacy-and-security-on-any-budget-6483e586025e?source=rss-8c693b99d86a------2</link>
            <guid isPermaLink="false">https://medium.com/p/6483e586025e</guid>
            <category><![CDATA[dns]]></category>
            <category><![CDATA[toolkit]]></category>
            <category><![CDATA[privacy]]></category>
            <category><![CDATA[security]]></category>
            <category><![CDATA[password-management]]></category>
            <dc:creator><![CDATA[Chris Kirby]]></dc:creator>
            <pubDate>Wed, 27 Mar 2024 11:00:53 GMT</pubDate>
            <atom:updated>2024-04-04T00:40:26.434Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*oulaGj1-Bbw51-qJ.png" /></figure><p>I hope to convince you that good personal online privacy and security is essential, accessible, and works on any budget. I was inspired by several friends and colleagues of mine who are still not managing their secrets (passwords, pins, account information, etc) securely and often don’t consider how their activity is being logged, tracked, and sold online. I want to help them and you with some great options that I use personally, for work, and for my home network that I believe is accessible to anyone, no matter your technical prowess.</p><p>Consider that all of the emails and passwords you’ve used over the years are in dozens, possibly hundreds, of databases available to online marketing companies and to those with less legitimate intentions. These companies are often called data brokers, a business-sounding way of saying they have your information, likely without your knowledge, and it’s for sale. Yes, you can ask them to remove it, and some companies offer to do this for you for a fee; however, whether they comply is voluntary. Even if they remove your data, it will likely reappear. How? past and future data breaches, from banks you’ve used, to retailers you shop at, or to some website you were on ten years ago. Data breaches are unfortunate and beyond our control, but some of the data we provide to each site, company, bank, etc, IS. It’s never too late, so let’s get started.</p><h3>Upgrade your security; it’s time for a password manager</h3><p>I’m not talking about the popup in Safari or your browser of choice that offers to save and sometimes generates a password for you. We can do much better than that. The term password manager doesn’t do it justice; it’s a secure vault for all of your secrets, meaning the things that are private or personal to you, an email and password to log in to your bank, a PIN for a debit card, or the actual debit card information itself. Essentially, it is anything you would keep in your wallet, bag, a post-it note, or commit to memory.</p><h3><a href="https://1password.com/personal?ref=chriskirby.net">1Password</a> — security for everyone</h3><p>I’m a longtime personal and family customer, and I believe there is no better product on the market. They don’t pay me to say that, though they are welcome to if they read this :) <strong>We’re talking $3/month</strong>, and you’ll make a giant leap towards better security. My kids have been using 1Password before they had phones because family doesn’t let family use the same password for both Xbox and Discord. They also store their SSN’s, ID’s, and soon credit cards and bank information all in one place. Need a copy of your birth certificate, np, it’s in 1Password. Driver’s license, covered. Your crypto wallet? yeah, I still have a few of those. It’s my digital wallet, and it’s indispensable. You’ll need to <em>create one more new password that you will remember, </em>but that will be the last. I recommend a long phrase, sentence, or several random words; most importantly, make it unique. 1Password will also be secured with your Face ID, Touch ID, Windows Hello, or any biometric system your phone or computer uses, making it even more secure and easier to use at the same time.</p><p>Once installed on all of your devices, 1Password can:</p><ul><li>Create new credentials and Fill in your existing ones automatically in any web browser, phone app, or desktop app.</li><li>Manage passwordless sign-in automatically, like <a href="https://blog.1password.com/what-are-passkeys/?ref=chriskirby.net">passkeys</a> now used by Google, Apple, and others. (passwords are antiquated and will soon be gone for good)</li><li>Manage your 2-factor codes, no more separate apps or losing account access when you get a new phone or forget which app you used.</li><li>Automatically scan and notify you if you have credentials that have been compromised due to a data breach</li><li>Manage your travel, insurance, and identity documents (and more) in one place.</li><li>If you’re a network, software, or platform engineer, it will also manage your SSH keys via its built-in SSH agent.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*UfVxYqeYmIHTHf1CZW1W1w.png" /><figcaption>1password new item selection screen</figcaption></figure><h3>Upgrade your online privacy; it’s time to part ways with Gmail</h3><p>You have a Gmail account, an Outlook account, or an iCloud account, just like I do. They are nice services, with nice apps to go along with them. They throw in online file storage and sharing, shared calendars, and other helpful stuff. oh, and they also scan your emails, data, and activity and sell it to advertisers, all outlined in their privacy policy. Google is an ad company, after all. and hey, it’s free, right? Marketers already know enough about me from what I choose to buy and the rewards cards I’m obligated to use lest I pay 30% more at Kroger or CVS…all in the name of data collection. Let’s make it a bit harder for the rest, shall we? Convenience and privacy are not mutually exclusive; there’s a better way.</p><h3><a href="https://pr.tn/ref/XTWNWXZEGAV0?ref=chriskirby.net">Proton</a> — digital privacy for everyone</h3><p>I don’t internet without it! I’ve been a customer since their crowdfunding days many years ago, and it’s only gotten better over time. This is your one-stop shop replacement for many services Google, Microsoft, and Apple provide. And guess what? You can also start for Free, so there is no reason not to. Their services include a very fast and secure VPN, Mail, Calendar, Drive (files), and their new password manager, which would be my second choice after 1Password (perhaps not for long). Moving to paid is worth it, as it gets you more storage, a faster VPN, and more customization and features for each product, all for $10/month. They offer family plans, too…yes, I made my kids use Proton as well 😄. Proton is also based in Switzerland, which has some of the strictest privacy laws in the world.</p><h3>Mail &amp; Calendar</h3><p>First, <a href="https://pr.tn/ref/XTWNWXZEGAV0?ref=chriskirby.net">sign up</a> and pick a username, which is your new default email address (username@proton.me). If you decide to pay, you can also use your custom domain (e.g. myname.com). Ok, now the fun part: this is not the email address you will give out! Proton has a built-in ability to create new email aliases in the desktop app or via Proton Pass. What is that? This is a unique email address that will be forwarded to your main address. Why? this allows you to use a unique email for every account, newsletter, and rewards program you have. So? well, those data breaches I mentioned earlier, if your info gets exposed, the email they will get is unique for that service. This does not make it impossible to identify you; it just makes it much harder. If you want to stop spam from a certain site that makes it hard to unsubscribe, kill the alias, and that email address will no longer work. You can’t spam someone with a bad email address. Proton Mail has so many other features that you’ll already be familiar with from other email providers, and some new ones.</p><p><strong>Switch checklist:</strong></p><p>✅ Forward new Gmail, Outlook, etc. messages to Proton Mail. Login to your email and go to settings / all settings. You’ll find something like Forwarding. Enable that and have it forward all messages to your new email address or alias</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*_aurdufVyOSNVmXF.png" /></figure><p>✅ Import all existing messages from your current email provider. Proton’s Easy Switch feature makes this easy. Go to your settings in Proton and select import via Easy Switch. Then follow the instructions. Once imported, you can safely delete them from your old provider.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*OzOZVLdAUlgjSgYR.png" /></figure><p>✅ Create your first alias in the Proton Mail app.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/768/0*ZMJOmVU1wb9TqrtN.png" /></figure><h3>Files and Documents</h3><p>Google Drive is convenient, but you give up a lot for using its free or paid personal services. First and foremost, it scans all of your files, and if you share them publicly, it examines their contents. It also offers encryption; however, like many cloud providers, it has all the keys. Think of it like the landlord in your apartment building. You have a key to your door, but so do they. We have a right to privacy, no matter how innocent or mundane the content is. If I’ve convinced you, the next step is as easy as the first: use Proton Drive. Your files are just as easy to access and share, with one major difference: they are end-to-end encrypted. No one can access those files except you and those you share them with, not even Proton. Something you probably thought was already true, but now you know.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*vs2Z3NnxXo-aGCkc.png" /></figure><h3>VPN</h3><p>I’m sure you’ve seen ads for VPNs; they are popular, especially on social media and YouTube. VPNs are an essential part of protecting your online privacy. However, not all VPNs are created equal. You’ll want a VPN that works on every platform, is reliable, has global coverage, and, most importantly, has a strict no-log policy. Proton VPN’s free tier meets all of those criteria, and it just gets better from there as you move to a paid tier. You can use a VPN in many ways, but I think for most people, having it on your phone and your laptop for casual browsing or when using public wifi will cover most of your privacy needs. It also comes in handy for watching streaming content from other countries 💻 . If you opt for the Ultimate sub, you’ll get faster connection options and more privacy through the Secure Core feature (Tor).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Hy2rccd4_8Ihrylo.png" /></figure><h3>Upgrade your WiFi</h3><p>Your ISP knows you well, very well, in fact, since they often supply the hardware you use to access the Internet along with their own DNS servers, which tell them the sites you visit and the services you use. A few simple steps will enhance your privacy and even speed things up.</p><h3>Equipment</h3><p>If you can, buy your own WiFi router. For as little as $50, you can improve your WiFi speeds and gain significantly more control over your internet settings. You don’t have to be an expert; most of these devices are very easy to set up via a phone app.</p><ul><li>The best plug-in-and-go budget option is <a href="https://www.amazon.com/Introducing-Amazon-eero-mesh-router/dp/B07WGJ8ZD3/?ref=chriskirby.net">Eero</a>. You can start with one for less than $50 and add more if you have a large space.</li><li>The best budget feature-rich option that is also easy to set up are <a href="https://www.amazon.com/WiFi-6-Router-Gigabit-Wireless/dp/B08H8ZLKKK?ref=chriskirby.net">TP-Link Wi-Fi routers</a>. This one is $75 and is loaded with goodies, like whole-home VPN support and even faster WiFi with more coverage.</li><li>The best of the best in the budget category is the <a href="https://store.ui.com/us/en/pro/category/all-unifi-cloud-gateways/products/ux?ref=chriskirby.net">Unifi Express</a>. It’s just as easy as eero to set up, even more goodies that TP-Link, and the polish of an Apple product. For $149, this is the best home router for most people, and it gets you into one of the best ecosystems for future expansion, like cameras that don’t send your video to Amazon or Google.</li></ul><h3>DNS</h3><p>Changing your DNS settings can improve your privacy and speed things up a bit, whether using your equipment or your internet providers. The best way to do this is to modify the settings of your WiFi router, which ensures that all of your devices can benefit. It’s easy to do, and you only have to do it once.</p><p>Open the app for your router. If there is no app, you may need to access it from your web browser. If this is the device your internet provider gave you, that website address is usually on the back or bottom of the device, along with the password to login. Once in, look for your DHCP settings. In those settings, you’ll see an option for setting DNS servers. The default for that setting is typically Auto. Change that from Auto to Manual; now you can add your own. If you see existing entries, replace them. There are some great public options here. My recommendation is to use <a href="https://developers.cloudflare.com/1.1.1.1/ip-addresses/?ref=chriskirby.net">Cloudflare’s servers</a>, as they are not in the business of selling your data and have a good privacy policy.</p><p>For most people, use these addresses:</p><ol><li>1.1.1.1</li><li>1.0.0.1</li></ol><p>For those who want to filter dangerous or malware sites:</p><ol><li>1.1.1.2</li><li>1.0.0.2</li></ol><p>For families who want to filter both malware and adult sites:</p><ol><li>1.1.1.3</li><li>1.0.0.3</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*g4QD6pZwAVxnpX0u.png" /></figure><h3>Wrapping up</h3><p>First, I hope you found this helpful. If you’ve come this far, you’re now in more control of your online identities and personal data. Your passwords are random and secure, your emails, files, and web traffic are more private, and your internet is snappier. Nice work!</p><p><em>Originally published at </em><a href="https://chriskirby.net/upgrade-your-online-privacy-and-security-on-any-budget/"><em>https://chriskirby.net</em></a><em> on March 27, 2024.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6483e586025e" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>