<?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 Jake Nesler on Medium]]></title>
        <description><![CDATA[Stories by Jake Nesler on Medium]]></description>
        <link>https://medium.com/@jakenesler?source=rss-3b95adb6974------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*u6YEJi4FHbbFz2p5rOo7SQ.jpeg</url>
            <title>Stories by Jake Nesler on Medium</title>
            <link>https://medium.com/@jakenesler?source=rss-3b95adb6974------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 14 Nov 2026 20:53:44 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@jakenesler/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[The best time to experiment is in college, but it’s always fun.]]></title>
            <link>https://medium.com/@jakenesler/the-best-time-to-experiment-is-in-college-but-its-always-fun-5420273e2959?source=rss-3b95adb6974------2</link>
            <guid isPermaLink="false">https://medium.com/p/5420273e2959</guid>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[platform-engineering]]></category>
            <category><![CDATA[kubernetes]]></category>
            <category><![CDATA[ai]]></category>
            <dc:creator><![CDATA[Jake Nesler]]></dc:creator>
            <pubDate>Fri, 25 Sep 2026 03:16:31 GMT</pubDate>
            <atom:updated>2026-09-25T03:49:13.753Z</atom:updated>
            <content:encoded><![CDATA[<p>Get your head out of the gutter.</p><p>What I mean is with technology. More importantly I am talking about software and platform engineering.</p><p>Think about it, In college, you’re broke, busy, and don’t know anything about the tools you want to use yet.</p><p>That’s what Software, Devops, and platforming feels like.</p><p>This is the opportunity for you to understand <strong>time management</strong>, <strong>frugality</strong>, and <strong>grit/determination</strong>. If you’re not in college, you’re still in luck. You may not be broke, but you are probably still busy and don’t know anything about the tools you want to use.</p><p>You will get <strong>frustrated</strong>, but you will also start on a journey, and one day things will just seem to make more sense after a while. I can credit most of my success now to being very interested in <strong>Kubernetes</strong> and the Cloud when I was in college. I remember I basically had no money but I scraped together cash for a Pi cluster and a POE switch following Jeff Geerling’s videos. <a href="https://www.youtube.com/watch?v=kgVz4-SEhbE&amp;list=PL2_OBreMn7Frk57NLmLheAaSSpJLLL90G.">link</a>.</p><p>Even though this cluster was practically useless and just had Grafana it was an intro to homelabs, then a mini pc Ceph cluster, and now what my last landlord called “<strong><em>Mission Control</em></strong>”. It was the beginning of my journey learning about the tools I use at Spacelift and previously in my first role as an SRE at US Xpress. It actually helped me get that first role because I was able to talk about Kubernetes and my Homelab to the hiring manager.</p><p>The point of this article is to say JUST DO IT.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/300/0*dhuga_gCEwzGztzS" /><figcaption>Just do it</figcaption></figure><p>You will never learn anything if you don’t try anything.</p><p>I’m not saying everything needs to be digital, there is beauty in analog, art, and music. But if you want to learn about tech, I would say the most effective way is to combine it with another interest you have. I would be willing to bet there is something in your life right now that would be able to be improved by writing(Prompting) some small bit of code.</p><p>So just get started, People often sell themselves short. Today it is easier than ever to get started, build ideas and make something cool.</p><p>Ask other people about their projects or work. There will always be critics, but it doesn’t matter because you are doing this for yourself.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5420273e2959" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[We should be using Frontier models to build open weight solutions and optimization tools while…]]></title>
            <link>https://medium.com/@jakenesler/we-should-be-using-frontier-models-to-build-open-weight-solutions-and-optimization-tools-while-10fa56209583?source=rss-3b95adb6974------2</link>
            <guid isPermaLink="false">https://medium.com/p/10fa56209583</guid>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[build-ai-agents]]></category>
            <category><![CDATA[openai-codex]]></category>
            <category><![CDATA[anthropic-claude]]></category>
            <category><![CDATA[ollama]]></category>
            <dc:creator><![CDATA[Jake Nesler]]></dc:creator>
            <pubDate>Sat, 12 Sep 2026 19:47:19 GMT</pubDate>
            <atom:updated>2026-09-13T17:00:46.130Z</atom:updated>
            <content:encoded><![CDATA[<h3>We should be using Frontier models to build open weight solutions and optimization tools while subscriptions still exist.</h3><pre>I thought this was a funny set of suggestions that codex gave me after <br>feeding the original title above into it,for the title of this, <br>and who knows, maybe it will help discoverability <br>so enjoy this ai slop title list.<br><br>- Use Frontier AI While You Still Can<br>- Stop Building Another AI Wrapper. Build the Models We’ll Need Later.<br>- We Have a Window Right Now. Don’t Waste It.<br>- Frontier Models Are Giving Us the Tools to Replace Them<br>- Use Closed AI to Build Open AI<br>- The Best Use of ChatGPT and Claude Might Be Making Them Less Necessary<br>- Your AI Subscription Is Temporary. What You Build With It Doesn’t Have to Be.<br>- We Should Be Using $200/Month AI to Build AI Everyone Can Own<br>- Stop Optimizing Your SaaS. Start Optimizing Open Models.<br>- You Have Access to the Best AI Ever Built. What Are You Doing With It?<br>- Frontier AI Is Cheap Right Now. Use It to Build What Comes Next.<br>- Before the AI Gold Rush Ends, Build the Picks and Shovels<br>- The Most Important AI Project You Build Might Run on a Six-Year-Old MacBook<br>- Don’t Just Consume Frontier Models. Use Them to Build Independence.<br>- We’re Renting Intelligence. We Should Be Using It to Build What We Can Own.</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5EikQUYPRPHp9cN3ot_JRg.png" /><figcaption>AI slop motivational image generated from the article, showing a computer running ollama and a bunch of ai slop captions.</figcaption></figure><p><em>Regardless of who you are, you should put some sort of effort into local AI models, regardless of the hardware.</em></p><p>Highly specialized models already perform <em>exceptionally well</em>, including those that can run on a MacBook Pro from six years ago(I know this is still a lot of money to many people, It is just probably something you may already have and use)</p><p><a href="https://github.com/alvinreal/awesome-opensource-ai">Take a break from your 10th web app Microsaas and think about creating something open source or contributing to something that propels us forward.</a></p><p>I think a lot of innovation comes from someone like you or I trying to do something on hardware that ‘Shouldn’t’ be possible. We are often very incentivized to find a better way out of necessity, or for the love of the game.</p><p>AI makes me nervous, but I look at local capability through a simple lens: if centralization is inevitable, personal access is self-defense. I think that we are barely getting started with AI, I know there are a lot of skeptics, but to me they just have not experienced the “Oh shit” moment yet.</p><p>I’ve done some incredible things with SOTA models, mostly in the pursuit of learning what is actually possible. We are basically at the point where, if something has a command line interface or an API, AI can interact with it exceptionally well. Increasingly, that is not even a requirement. Models can use a mouse, navigate interfaces, read screens, and interact with computers through many of the same methods we do.</p><p>That scares me a little. What scares me more, though, is a future where those capabilities are locked behind control systems that only wealthy companies, governments, or authoritarian groups can access, all in the name of safety.</p><p>I’m not saying there should be no legislation or controls around AI. I personally do not want the AI equivalent of a nuclear weapon in anyone’s hands. But eventually we are going to brush up against capabilities that feel that consequential, and we need to think seriously about who gets access to them.</p><p>Think about the hardware side alone. In ten years, will an RTX Ada-class GPU cost a few hundred dollars? Will people be running something comparable to today’s Claude or GPT-class models in a homelab? And if that becomes normal, what does SOTA look like by then?</p><p>Only about three years ago, I remember thinking it would be incredible if AI could could just run the commands on the computer to execute what it created. Not long after, people figured it out.</p><p>That is really my point. If we do not stay current on what these systems can actually do, we are going to get left in the dust. A surprising number of people still understand modern AI almost entirely in the abstract. They know it can “write things” or “answer questions,” but they have never watched a frontier model operate a computer, write and execute software, debug its own work, use tools, or complete a complicated task from beginning to end.</p><p>Even if you don’t want to build anything open source, or tinker around. If you have access to one of the highest-end AI subscriptions, sit with your non-technical friends or family and let them use it. Sit them down with GPT-6, Fable, or whatever the frontier model is at the time and give them a real problem to solve.</p><p>One day, probably sooner than we expect, the economics of all of this are going to change.</p><p>We have seen the pattern plenty of times in technology. Companies subsidize growth, competition is fierce, and remarkably powerful products are available for relatively little money. Then the market consolidates, priorities change, prices rise, usage gets restricted, or the thing you built your workflow around disappears entirely.</p><p>Frontier models are incredible. I also do not want to spend $200 a month forever just to maintain access to intelligence I have gradually made part of how I work. What happens when that becomes $300? $500? What happens when certain capabilities move behind enterprise contracts, stricter controls, or products ordinary people cannot reasonably access?</p><p>This article is really just a provocation to think about gradually shifting some of our dependence away from hosted AI.</p><p>Maybe that means using a harness that can swap to a local model, which I already do occasionally. <br>Maybe it means finding some weird optimization or breakthrough that a mathlete in San Francisco simply never had a reason to look for.</p><p>No shade to the people pushing SOTA models or to big AI. They are doing incredible work. But I think too many people let their distance from the source convince them that their effort would not matter.</p><p>They assume someone smarter, better funded, or closer to the frontier will solve it.<br> <br>Sometimes they will. Sometimes the person who solves it is just the one stubborn enough to try solving their own problem.</p><p>If you are looking to get started with local AI models in an easy way: <br>Qwen models are great and run on modest hardware. <br><a href="https://openwebui.com/">Openwebui</a><br><a href="https://github.com/unslothai/unsloth">Unsloth</a> makes big models run on small stuff.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=10fa56209583" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Is it really a Software Factory, Developer Experience, Agent Experience, or Developing AgenticSlop?]]></title>
            <link>https://medium.com/@jakenesler/developer-experience-agent-experience-or-developing-agentic-slop-46ec403bf7be?source=rss-3b95adb6974------2</link>
            <guid isPermaLink="false">https://medium.com/p/46ec403bf7be</guid>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[software-architecture]]></category>
            <category><![CDATA[platform-engineering]]></category>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[kubernetes]]></category>
            <dc:creator><![CDATA[Jake Nesler]]></dc:creator>
            <pubDate>Sun, 06 Sep 2026 02:46:24 GMT</pubDate>
            <atom:updated>2026-09-09T20:18:18.023Z</atom:updated>
            <content:encoded><![CDATA[<h2>Claude or Codex deploying to Kubernetes? — Developer Experience, Agent Experience, or Developing Agentic Slop?</h2><p>My Open-Source DevEx Pipeline for Humans and Agents</p><p>I had to put the em dash in the title for a bit of a laugh, But seriously, Imagine you’re vibe coding one of your next $100 million startups. You’ve got the webapp working. Do you really want to stop and manually:</p><ul><li>Create a repository and another GitHub Actions pipeline.</li><li>* Provision a database and object storage.</li><li>* Register DNS and configure how the app is exposed.</li><li>* Set up secrets, monitoring, and backups.</li></ul><p>Before this, I was copying the same configs and Actions workflows into every new app I made. Even when the setup was mostly identical, I still had to change things, check what I had missed, and remember which project had the version I actually wanted.</p><p>Having an agent do the copying doesn’t make that a particularly good process.</p><p>There is a lot of discussion about developer experience right now. People just don’t always call it that. Wanting your agent to understand how to build and deploy an application without explaining your entire infrastructure again is very much a developer-experience problem.</p><p>What I’m going to show you is a fairly decent pipeline I personally use: yscale-sh/idp. I’ve been using it for months, including with jaK3s. It grew out of the deployment work I was already repeating.</p><p>Even if you aren’t making a ridiculous number of apps, this is useful for deploying new homelab services or maintaining your own internal tools.</p><h3>What the pipeline actually does</h3><p>Yscale IDP starts with a Kubernetes cluster you already have. It does not create the cluster or remove the need to operate it. It handles the application side: describing what should run, applying environment-specific configuration, and generating the deployment state that Flux reconciles.</p><p>Each application has a deploy.yaml. That file describes the things the application needs rather than making every application repository carry its own hand-written Kubernetes resources.</p><p>With database support and the relevant secrets configured for the environment, a small application declaration can look like this:</p><pre>app: myapp<br><br>runtime:<br>  image: ghcr.io/your-org/myapp<br>  port: 8080<br><br>probes:<br>  path: /health<br><br>sizing:<br>  profile: minimal<br>  replicas: 2<br><br>db:<br>  - name: primary<br>    type: postgres<br><br>secrets:<br>  - DATABASE_URL<br>  - PRIMARY_DATABASE_URL</pre><p>The image repository is declared here; the deployment supplies the tag or digest. The secret entries are names, not the actual credentials. The platform derives the Kubernetes resources and connection wiring from the declaration and the target environment.</p><p>The workflow is straightforward. idpctl validate checks the application manifest. idpctl plan applies the environment’s policy and prints the proposed state without changing Git or Kubernetes. idpctl render updates clusters/&lt;env&gt;/platform.yaml. That change gets reviewed, committed, and pushed, and Flux reconciles it into the cluster.</p><p>I don’t want each app deciding how we name namespaces, wire secrets, or configure basic health checks. Those decisions belong in the platform configuration, where I can maintain them consistently.</p><p>PostgreSQL, Redis, Cloudflare DNS and tunnels, logging, and autoscaling are supported through optional modules or integrations. They depend on what the environment has enabled and configured. There is still an initial platform setup; adding a manifest does not magically establish all your provider accounts, credentials, and backup arrangements.</p><p>For continuous delivery, there is an optional idp-shipper. Once an application is registered, it watches the configured repository branch, builds the required images through the in-cluster image builder, and commits the updated deployment state. Flux still handles reconciliation. I don’t need a separately invented deployment workflow for every application.</p><p>Promotion carries the selected image digest into the next environment without rebuilding it. Deployment configuration can be rolled back by reverting the Git commit. Database migrations and application data still need their own handling.</p><h3>The agent should use the process I already have</h3><p>One thing that bothers me about agentic coding is how much work we repeat.</p><p>I include myself in this. It is very easy to ask Claude or Codex to build something without first checking whether an existing project does what we want. I’ve even been thinking that lately the same boilerplate can be more or less scripted at this point for most people projects, or atleast the first 30%.</p><p>The generated code still needs to be understood, reviewed, updated, and occasionally fixed. Getting an agent to write another deployment pipeline does not remove those responsibilities.</p><p>The IDP repository includes AGENTS.md and an IDP skill documenting the application contract, commands, deployment lifecycle, and checks. An agent can work on deploy.yaml, validate it, and inspect the proposed deployment through the same CLI a person uses. The local validation, planning, and rendering commands do not require provider credentials.</p><p>That is the agent experience I care about here. I want it to know which file to change, which command to run, and how to check its work. I don’t want it deciding we need a completely different deployment approach because it happened to generate one.</p><p>This does not make the application code correct. I still need tests, appropriate permissions, and review. It does mean the deployment process is something I can document and check rather than something I have to explain from scratch in every session.</p><p>The same thing helps humans. A new contributor should not need to reconstruct my infrastructure preferences from six different repositories.</p><h3>Where jaK3s fits</h3><p>I use jaK3s for the underlying cluster setup. It is my hardened Debian-based k3s image, with Cilium, embedded etcd, and support for sending scheduled etcd snapshots to S3-compatible storage such as R2. The IDP runs above that and handles applications.</p><p>There is an important distinction with backups: an etcd snapshot protects Kubernetes state. It does not back up the contents of your application’s persistent volumes or your PostgreSQL data. Those require separate backup and recovery arrangements, which jaK3s explicitly leaves to the application and storage setup.</p><p>I want deploying and recovering my infrastructure to be repeatable. I also want to be honest about what is actually covered. Having a backup job configured is not where I want to stop checking.</p><p>Frugality should be a priority</p><p>Part of the reason I built this is that I want to choose infrastructure based on what it costs and what I need, then reuse those choices across my applications.</p><p>S3 versus R2 is a good example.</p><p>R2 is usage-based, not a fixed-price service. It charges for storage and operations, with a free allowance for Standard storage. Infrequent Access also has retrieval charges. The useful difference for download-heavy applications is that data leaving R2 itself does not incur egress bandwidth charges. Other metered services used alongside it can still charge you.</p><p>S3 pricing includes storage, requests, and potentially data transfer, among other charges. For a workload serving substantial amounts of data to the internet, R2 can work out cheaper than an S3 setup with billable egress. That is a reason to calculate the cost of your actual workload, not declare one provider universally cheaper.</p><p>I want to make those decisions deliberately. Then I want the deployment process to use them consistently.</p><p>The same applies to hosting. What happens if your current provider becomes expensive for the way your application is growing? How much work would it take to move? Which dependencies would have to change?</p><p>I don’t have a problem paying for convenience. I have a problem repeatedly paying for things I could reasonably standardize, or discovering that I made moving unnecessarily difficult.</p><p>Frugality includes my time, too. I’m not automatically saving money because Claude, or maybe Codex, rewrote an expensive service while I was asleep. I now have another service to maintain.</p><p>Self-hosting has the same consideration. I still own upgrades, capacity, troubleshooting, and recovery. Since I’m already operating Kubernetes, reusing that setup makes sense for me. That maintenance cost still belongs in the decision.</p><p><em>“I’m one person. I can just set it up.”</em></p><p>Sure. So can I. That is how I ended up copying the same setup across projects.</p><p>Being one person is also why I want the repetitive work automated.</p><p>What happens if my MacBook breaks? Can I work from another machine without discovering that an important deployment script or credential only existed locally? Can I understand how an app is deployed after not touching it for a few months?</p><p>Keeping the deployment configuration in Git helps, but I still need access to the registry, secrets, infrastructure, and backups. I want that recovery process documented rather than dependent on remembering what I did last time.</p><p>And this applies to internal infrastructure, too. A homelab service still needs to be updated, configured, and recovered when something goes wrong. It doesn’t become less annoying to maintain because nobody is paying for it.</p><p>Extend the things you keep repeating</p><p>Once applications follow a consistent deployment contract, there are other pieces worth standardizing.</p><p>If every app needs the same structured logging setup, health endpoints, or monitoring instrumentation, I would rather maintain a shared library than have an agent generate a slightly different implementation every time.</p><p>The same idea can extend into business-specific workflows. For a business operating a Stripe Connect platform, a possible integration could create connected accounts and start Stripe-hosted onboarding. Stripe’s information and verification requirements would still apply; account creation alone does not complete onboarding.</p><p>I would add that kind of integration because I repeatedly need it, not because the platform needs another feature on its README.</p><p>There is plenty of useful automation between “do everything manually” and “build a platform that tries to handle every possible application.”</p><h3>So yes, more developer-experience slop</h3><p>I realize there is something a little suspicious about complaining that everyone keeps building things and then releasing another project.</p><p>But yscale-sh/idp is the deployment setup I was already using and repeatedly copying, made reusable and released under Apache-2.0. It builds on existing tools such as Kubernetes, Helm, and Flux rather than requiring a new implementation of everything underneath it.</p><p>My goal is to put reasonably priced services together, automate the repeated work, and keep the result understandable enough that I can operate it properly.</p><p>I’ve been using it for months because it solves a problem I actually have. If I’m going to keep making apps, I’d rather spend the time building them than explaining to another agent how I deploy them. If you’re interested in trying it out it’s available here!</p><p><a href="https://github.com/Yscale-sh/idp">GitHub - Yscale-sh/idp: The Yscale IDP - contract-based internal developer platform: one deploy.yaml per app, idpctl renders, Flux is the only writer</a></p><p>This article was one shot revised with ChatGPT-6-astra from a rough draft I wrote myself.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=46ec403bf7be" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Kubagachi KritterForge: Generating animated sprites with Image Generation models.]]></title>
            <link>https://medium.com/@jakenesler/kubagachi-kritterforge-generating-animated-sprites-with-image-generation-models-5db57f33e15d?source=rss-3b95adb6974------2</link>
            <guid isPermaLink="false">https://medium.com/p/5db57f33e15d</guid>
            <dc:creator><![CDATA[Jake Nesler]]></dc:creator>
            <pubDate>Mon, 20 Jul 2026 04:03:27 GMT</pubDate>
            <atom:updated>2026-07-20T04:03:27.999Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jMrGE1QRkPw3yfhU0nRL0g.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3oLVUjzO9pwpcmUoo1eWBw.png" /></figure><p>This is meant to be a continuation of the other Medium Article I released for Kubagachi. If you are interested in that you can check it out here : <a href="https://medium.com/@jakenesler/nodes-may-be-cattle-but-i-think-pods-are-pets-my-new-kubernetes-ui-tool-kubagachi-aa4db243210b">https://medium.com/@jakenesler/nodes-may-be-cattle-but-i-think-pods-are-pets-my-new-kubernetes-ui-tool-kubagachi-aa4db243210b</a></p><h3>Image Gen Pipeline and functionality</h3><p><strong><em>I have also included something called Critter Forge.</em></strong></p><p>This image generation pipeline allows you to provide a reference image of a mascot. The pipeline then uses an image generation model to create eight states of a pod in Kubernetes. There are some tricks and fancy scripting involved in the checkerboard removal process. Ideally, you end up with images similar to the ones shown in the top of this article.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ujHGXeHCVdT38lL-VtyzVA.png" /></figure><p>When I initially did this, I tuned it to work with Gemini HIGH. Anything below that is honestly trash. Using Codex might give poor results with the built-in prompts and current pipeline. Please be warned before wasting credits. For what I included in Kubagachi I burned $40 dollars in api credits for all of the current images.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*N-TuKpOB05l1N6Sy0nxtVQ.png" /><figcaption>Some Codex model, Poor reference image adherence.</figcaption></figure><p>I aspire to make this usable without a Gemini model, but for the foreseeable future, this is not something I can spend more time or money on when these were the results I was going for.</p><p>I used my Kubernetes bursting tool Yscale.sh and spent quite a bit of time trying to make <strong>4xRTX4000 ADA on Linode</strong> work with the Flux image model but I just couldn’t get it to work. Instead, they produced some odd results like this.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*IZOpMpfpzu4jTWmZlLyAVw.jpeg" /><figcaption>Codex Generated as well</figcaption></figure><p><strong>Codex could be good if tuned</strong>, but it felt very wasteful to continue trying to make it work when Gemini High was able to do it perfectly. I was also having a lot of luck prototyping in the Gemini App or even Anti Gravity, then using an API key to actually run the forge.</p><p>My goal is to also not minimize artist skills, On the contrary I will be releasing something I am calling Kritter Marketplace where artists can sell sprite sheets for any price, while AI image packs are capped at $3.99. There will be a push to basically have a ton of free stuff too and generate the images on there if you don’t want to mess around with Gemini API Keys. Sign up for updates here</p><p><a href="https://kubagachi.com/">https://kubagachi.com</a>/signup</p><p>If you are an official company or tool and want your Kritter to be officially added please open an issue and we can integrate it into the platform.</p><p><a href="https://github.com/Yscale-sh/Kubagachi">https://github.com/Yscale-sh/Kubagachi</a></p><p>The next article for my ecosystem will be my internal developer platform, I’m more so calling an “Integrated Development Platform”. It’s a clear gitops way for a human or agents to deploy apps to Kubernetes.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5db57f33e15d" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Nodes may be cattle, But pods are pets. My new Kubernetes UI tool Kubagachi.]]></title>
            <link>https://medium.com/@jakenesler/nodes-may-be-cattle-but-i-think-pods-are-pets-my-new-kubernetes-ui-tool-kubagachi-aa4db243210b?source=rss-3b95adb6974------2</link>
            <guid isPermaLink="false">https://medium.com/p/aa4db243210b</guid>
            <category><![CDATA[claude-code]]></category>
            <category><![CDATA[kubagachi]]></category>
            <category><![CDATA[kubernetes]]></category>
            <category><![CDATA[platform-engineering]]></category>
            <category><![CDATA[cloud-infrastructure]]></category>
            <dc:creator><![CDATA[Jake Nesler]]></dc:creator>
            <pubDate>Wed, 08 Jul 2026 23:40:23 GMT</pubDate>
            <atom:updated>2026-07-09T01:48:40.094Z</atom:updated>
            <content:encoded><![CDATA[<h3>Nodes may be cattle but pods are pets. My new Kubernetes UI tool Kubagachi.</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jMrGE1QRkPw3yfhU0nRL0g.png" /><figcaption>My cat Nori, Kubernetes states.</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3oLVUjzO9pwpcmUoo1eWBw.png" /><figcaption>Cartogopher: Completed, 8 frames for animations.</figcaption></figure><p>These are KubeKritters.</p><p>They are part of my mission to help people learn Kubernetes, Infrastructure as Code, and Platform Engineering in a very approachable, relatable, and fun way. If you’re already familiar with these and use Kubernetes that is great too!</p><p>This tool is awesome for anyone to use. Throw this on your network behind Cloudflare access or Tailscale and you aren’t tied to your laptop and its faster than Kubectl over Termius or some other mobile ssh client.</p><p><strong>This is part one of a series over</strong> <strong>the next few weeks where I am open-sourcing my entire development process and tools</strong> that I’ve created to manage websites like <a href="https://anyrentcloud.com/">Anyrentcloud.com</a>, <a href="https://cartogopher.com/">Cartogopher.com</a>, <a href="https://openprophet.io/">OpenProphet.io</a>, <a href="https://mainstreetmusicstore.com/">Mainstreetmusicstore.com</a>, and <a href="https://unbelievablesite.com/">unbelievablesite.com</a>.</p><p>Releases include <strong><em>jaK3s</em></strong>, <strong><em>Jakes Developer Platform</em></strong>, <strong><em>Litewindow</em></strong> Kubernetes/Docker/Baremetal agent harness orchestrator, and <strong><em>Yscale-media </em></strong>a self-hosted media server that performs Sharded GPU transcoding. The final release will be <strong><em>Yscale.sh</em></strong>, A lightweight Kubernetes bursting tool that enables bursting your existing cluster to a different cloud to satisfy GPU demand. Imagine EKS bursting to GCP, and the nodes just acting like a regular node in your cluster. I am extremely frugal and patch together a bunch of free tools and cost effective features of different platforms to basically deploy a low cost Developer Experience pipeline for myself.</p><p>As an enticing bonus and for fun, each release will get their own KubeKritter. To get one, I won’t ask you to do anything outrageous. You simply need to add your email here so I can send you the Kritter files, and then I’ll notify you when each new tool is publicly available via email, then just opt out. I won’t spam you or sell your email. These are going to be random drops based on what time allows me, sign up here https://id.kubagachi.com/signup or follow me on here.</p><h3>Actual article and Kubagachi starts here</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Fs-27gL8OUCx0XkNqav7lg.png" /><figcaption>Kubagachi web page</figcaption></figure><p>I’m going to give a quick overview of why and how we are here, What it is, And a very quick summary of how these animated characters work.</p><p>To begin with, “Cattle, not pets” simply means do not develop attachments to your nodes. They are merely numbers. We spin them up and down. This is generally the objective of Kubernetes in the cloud. This is a stark contrast to on-premise practices, where you might walk into a closet and encounter Obi-Wan Kenobi face-to-face. I don’t name servers, but one of my Proxmox storage pools is named “<strong>Biggus Discus.</strong>”</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/447/1*kjv6Gig0MdW1kwEmyn4WLw.jpeg" /><figcaption>Is there something funny about “Biggus Discus” ? <a href="https://www.youtube.com/watch?v=kx_G2a2hL6U">https://www.youtube.com/watch?v=kx_G2a2hL6U</a></figcaption></figure><p>On prem, you are caring for these machines, making sure you they are up and have what they need. In the Cloud, this is the providers problem, but now all of our focus is shifted to our actual workloads. With that realization, I think that Pods <em>should </em>have an identity.</p><p>No, They are not the same pod each time, but they are the same type of pod within a whole chain of life cycles in an environment.</p><p>So what led me to make this? We are always trying to aim for equilibrium, balancing cost, demand and other factors. To me It almost feels like a game. Another byproduct of this is the visual cues that something is good or bad, literally anyone can say “Hey Jake, that blue Gopher thing is having a problem”.</p><h3>Mapping Kubernetes to something a bit more familiar</h3><p>For context, I was born in 1997. Growing up we had popular games and tech toys like Pokémon, Yu-Gi-Oh!, Petz, Zoo Tycoon, and yes, Tomagachi. I believe that my experiences with these games have influenced my understanding of how characters on paper, screens, or even robots can appear larger than life to children and as I’ve grown older, I’ve realized that this phenomenon also profoundly affects many adults.</p><h4>Parallels between Zoo Tycoon and Kubernetes.</h4><p>You build an enclosure for the animal living there. If an enclosure becomes Stale, Dirty, or over populated, you need to either refresh, clean it, or move it to another enclosure. You can take drastic actions like even sell some, or drop a lion into the zebra enclosure to force clear them. If you don’t do anything the problem actually solves itself, All the animals fall ill, and you lose all of your guests.</p><p>In Kubernetes, You specify a node size that is required for your pods. If the pods are too large, Don’t have the specified resources they need like GPU, or even architecture you get looping failures. You can take actions by fixing the issue or scaling up using a tool like Karpenter in AWS or Yscale.sh(<em>shameless plug</em>) which will dynamically launch GPU or CPU nodes to any cloud. You can force kill stuck pods and re architect based on needs. If you don’t intervene here the problem also solves itself, your product dies and then you lose all of your customers.</p><h3>Cute critters, but even without them it is a kick-ass tool.</h3><p>Besides being visually appealing and showcasing the characters, I aimed to release a powerful Kubernetes UI tool that can function as a web application over a platform like Cloudflare access.</p><p>I am a big fan of Freelens, And before that OpenLens. While I use kubectl daily, I occasionally prefer a quicker visualization. While Freelens is more battle tested, I have been reaching for this first to triage and check alerts on my phone.</p><p>I’d be lying if I didn’t concede that there is tons of Vibe Coding going on, not everything is perfect, but I honestly rather launch and just play whack-a-mole. Sort of like how a lot regular development usually works.</p><p>Considering this, it’s open-source, so please open an issue if you encounter a bug or have suggestions and you are more specialized than I am feel free to pull a branch and submit a pull request if you’d like to share your improvements.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MlJhau1j7qnSsva-_rmaDg.png" /></figure><p>The image pipeline is both simple and complex for different reasons, the good news is that I did all of the hard work already! It relies on Multiple frames on each sheet, and crops to each for frames.</p><p>Tomorrow or the next day(currently July Eighth) I’ll post a companion article going into detail on how the image pipeline works, for the time being go try out Kubagachi, Open issues, and let me know what you think!</p><p>Full open source repo for Kubagachi here. <br><a href="https://github.com/Yscale-sh/Kubagachi">https://github.com/Yscale-sh/Kubagachi</a></p><p>Credit to the wonderful Joey Stout for trying this out first, contributing some fixes and creating this Glance repo: <a href="https://github.com/TheOutdoorProgrammer/kubagachi-glance">https://github.com/TheOutdoorProgrammer/kubagachi-glance</a></p><p>If you are an official company or tool and want your Kritter to be officially added please open an issue and we can integrate it into the platform.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=aa4db243210b" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How I never hit limits with Claude Code Opus]]></title>
            <link>https://medium.com/@jakenesler/context-compression-to-reduce-llm-costs-and-frequency-of-hitting-limits-e11d43a26589?source=rss-3b95adb6974------2</link>
            <guid isPermaLink="false">https://medium.com/p/e11d43a26589</guid>
            <category><![CDATA[coding]]></category>
            <category><![CDATA[claude-code]]></category>
            <category><![CDATA[llm]]></category>
            <category><![CDATA[anthropic-claude]]></category>
            <category><![CDATA[claude]]></category>
            <dc:creator><![CDATA[Jake Nesler]]></dc:creator>
            <pubDate>Sat, 28 Feb 2026 18:44:27 GMT</pubDate>
            <atom:updated>2026-03-06T22:21:57.135Z</atom:updated>
            <content:encoded><![CDATA[<h3>Your AI Coding Agent Wastes 80% of Its Tokens Just Finding Things, and Limits Keep Getting Lower. Here’s the Fix.</h3><p>I built a code knowledge graph that gives Claude Code exactly the context it needs, saving 40 to 95% on tokens without losing accuracy.</p><p>I watched Claude Code read 25 files to answer a question about three functions.</p><p>Not because it’s bad at coding. It’s phenomenal at coding. It read 25 files because it had no idea which three it actually needed. So it did what any of us would do when handed a pile of loose pages with no table of contents: it started flipping through everything.</p><p>That single question cost me about 12,000 tokens. The answer required maybe 800.</p><p>Up until mid-2025, I was strictly a ChatGPT copy and paste user. Then I tried Cursor, and it was genuinely incredible, but the cost was overwhelming. Token usage was opaque, pricing was unclear, and I finally realized</p><p><strong>AI coding agents spend most of their token budget on orientation, not problem solving.</strong></p><p>They’re not slow because the models are slow. They’re expensive because the models are lost. When Claude Code or Cursor encounters your codebase for the first time, it has no structural understanding. No sense of what calls what, which files depend on which, or where the boundaries between concerns lie. So it reads broadly and hopes for the best. Now recently LSP has been added, but that doesn’t help with understanding how things work together.</p><p>Right now 60 to 80% of the tokens consumed go toward figuring out where things are, not answering your actual question. Instead why not look at this like a programmer, none of us read full files when looking to fix something, we use ctrl f and grep.</p><h3>More Context, More Better?</h3><p>The industry’s answer to this problem has been simple: make the window bigger. Gemini offers 1M tokens. Claude has 200K(1million via api) The logic seems obvious, if the model can see more code, it’ll find what it needs.</p><p>But this is like solving a bad filing system by renting a bigger office. The fundamental issue isn’t capacity. It’s precision.</p><p>When you dump 200K tokens of code into a context window, you’re paying for all of it, and the model still has to figure out which parts matter. Worse, irrelevant context actively degrades performance. Research has consistently shown that LLMs perform worse on tasks when surrounded by irrelevant information. More context isn’t just expensive; it can make the model seem like a much worse model.</p><p>What you actually need is a system that gives the model exactly the right files, in the right order, at the right level of detail, and nothing else.</p><p>My thought process started with a simple analogy. Consider the book title <em>Software Development for Dummies</em>. Without opening a single page, you can reasonably infer what this book covers, who it’s for, and roughly how deep it goes.</p><p>Code works the same way. What does createStripeConnectAccount do? You already know, because the name carries structural meaning. Function signatures, module names, import paths, and type definitions form a kind of table of contents for your codebase. They tell you what exists, where it lives, and how it connects to everything else.</p><p>What if an AI agent could read that table of contents first, before reading any actual code?</p><h3>What I found when I looked at existing tools</h3><p>Since starting this project, I’ve identified probably 10 to 15 competitors in this space. Solo developers all the way up to companies with billion dollar valuations. Tools like Greptile, Sourcegraph Cody, Cursor’s indexing, Aider’s repo map, Repomix, and Augment Codes new MCP.</p><p>They all attempt to solve the context problem, but they share a common limitation: nearly all of them rely on vector embeddings and run in their servers.</p><p>Vector search is great for semantic discovery, like “find code that does something like X.” But it has a structural blind spot that matters enormously for code understanding.</p><p>Ask a vector-based tool “how does authentication work?” and it retrieves 15 chunks mentioning “auth,” “login,” and “token.” What it misses is that middleware.ts calls refresh.ts, which depends on jwt-config.ts. The call chain, the actual architecture, is invisible to embeddings because they capture similarity, not structure.</p><p>Vector search also introduces latency I wasn’t willing to accept. Embedding generation, index lookups, and re-ranking add hundreds of milliseconds per query. For a tool that needs to work at the speed of Claude Code’s thinking loop, that’s too slow.</p><p>The other tools treat token savings as a nice byproduct. I wanted token efficiency to be the primary design goal.</p><h3>How CartoGopher works</h3><p>So I built CartoGopher. It’s a Go CLI that creates a queryable knowledge graph of your entire codebase using AST (Abstract Syntax Tree) parsing. No embeddings. No cloud. No inference step. I am actually calling it CodeGraphProtocol.</p><p>Here’s the approach:</p><p><strong>1. Parse, don’t embed.</strong> The CLI uses language-aware parsers supporting 20+ languages to extract the actual structure of your code. Functions, classes, interfaces, imports, call relationships, type hierarchies, and dependency chains. This is the same kind of parsing your IDE does for autocomplete and go-to-definition, extended to produce a complete structural map.</p><p><strong>2. Build a graph, not an index.</strong> The output is a JSON knowledge graph where nodes are code entities (functions, types, files, packages) and edges are relationships (calls, imports, implements, depends-on). This means the agent can traverse your codebase following a function call to its implementation, then to its dependencies, rather than guessing at similarity.</p><p><strong>3. Start small, scale up.</strong> CartoGopher exposes MCP tools that let the agent begin with a high-level “shake” of the repository, think table of contents, then progressively drill into architecture maps, package summaries, specific symbols, and finally full function source code by line number. The agent decides how deep to go.</p><p><strong>4. Incremental rebuilds.</strong> When you edit a file, the graph updates only the affected nodes and edges. Like how your build system knows what changed without recompiling everything. This keeps the graph current without the multi-minute reindexing that plagues embedding-based tools.</p><p>The result: queries that used to consume 8,000 to 12,000 tokens now require 800 to 2,000 tokens. Same answer quality. 40 to 95% fewer tokens, depending on the question and codebase size.</p><h3>Rough experiments</h3><p>I ran SWE-bench Verified using Claude Opus 4.5 with CartoGopher providing context during the double usage week after Christmas.</p><p>I used a custom harness with this https://github.com/jimmc414/claudecode_gemini_and_codex_swebench + a version of CartoGopher with no license check to satisfy the no internet requirement.</p><p>The results: identical or better solve rates with roughly 20% average token savings on fully automated benchmark problems. It also finished 6 hours faster than without it!</p><p>SWE-bench tasks are narrowly scoped, the model already knows roughly where to look. In real-world usage, where a developer asks broader questions across a full codebase, the savings are more like 40 to 55% across code changes. For pure code comprehension questions, the kind where the agent would normally read dozens of files, savings routinely hit 70 to 95%.</p><p>Here’s a concrete example. I pointed CartoGopher at my Claude Prophet trading bot, a Go project with 8 packages, roughly 3,600 lines of code, 35 API endpoints, and 9 service files. The agent made these calls to build a comprehensive understanding:</p><pre>⚙ cartogopher-mcp_shake                    → High-level repo overview<br>⚙ cartogopher-mcp_architecture_map          → Package structure and relationships<br>⚙ cartogopher-mcp_api_surface               → All exposed interfaces<br>⚙ cartogopher-mcp_all_endpoints             → 35 HTTP endpoints mapped<br>⚙ cartogopher-mcp_package_summary (×7)      → Detail per package<br>⚙ cartogopher-mcp_symbol (×7)               → Key type definitions<br>⚙ cartogopher-mcp_search                    → Targeted code search<br>⚙ cartogopher-mcp_frontend                  → Frontend summary<br>⚙ cartogopher-mcp_file_functions            → Entry point analysis</pre><p>The output was a complete architectural summary: tech stack, all 8 packages with their roles, 35 endpoints categorized by domain, 9 services with function counts, background job descriptions, and design pattern analysis. From graph metadata, not from reading source files.</p><p>Note: The two sections above were highly influenced using Cartogopher in doc mode to create a clear explanation.</p><h3>Why this matters beyond cost</h3><p>Token savings translate directly to dollars, but the second-order effects matter more.<strong>Faster responses.</strong> Fewer tokens in means faster processing. The agent spends less time reading irrelevant code and more time thinking about your actual question.</p><p><strong>Fewer hallucinations.</strong> When the model gets exactly the right context, it hallucinates less. Irrelevant code in the context window is noise that actively confuses the model.</p><p><strong>Better code changes.</strong> An agent that understands the architecture, which interfaces a service implements, which functions call which, makes changes that respect the existing design instead of working against it.</p><p>To me this is like supercharging your model, regardless of what it is.</p><h3>What CartoGopher doesn’t do (yet)</h3><p>In the interest of honesty: CartoGopher works at the structural level. It doesn’t understand what your code means semantically, that’s what the LLM is for. It won’t help you find “code that does something like retry logic” if the function isn’t named something obvious. For pure semantic search, embedding-based tools still have an edge.</p><p>It’s also a CLI/MCP tool, not an IDE extension (yet). It works best with Claude Code and other MCP-compatible agents.</p><p>And the 40 to 95% range is wide because the savings depend on the question. Narrow questions (“what does this function do?”) save less. Broad architectural questions (“how does the payment system work?”) save the most. Then if it doesn’t find what it needs most agents will just read the whole file, but hey atleast they tried to save tokens initially.</p><h3>Try it</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/660/1*fiZT8rQERhbuAOTIpof0YA@2x.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/660/1*Ppv7H16eRZGp5ULWI1HAeg@2x.jpeg" /></figure><p>CartoGopher is live at <a href="https://cartogopher.com/">cartogopher.com</a> with a 7 day free trial. If you’re a researcher at an educational institution, reach out and I can give you an extended trial.</p><p>The Go CLI installs in seconds, builds the graph in about 0–7 seconds for most projects ( Laravel PHP is 7 if excluding tests, fastapi is 3 seconds, Most GO repos are less than one second), and integrates with any MCP-compatible coding agent.</p><p>Best of all, this is totally local, only running on your machine, the only thing it needs internet for is a license check.</p><p>Ps.</p><p>If you’re curious why it’s shake and bake, it’s because I originally named this iwannaGOfast.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e11d43a26589" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[I gave Claude Code 100k to trade with in the last month and beat the market.]]></title>
            <link>https://medium.com/@jakenesler/i-gave-claude-code-100k-to-trade-with-in-the-last-month-and-beat-the-market-ece3fd6dcebc?source=rss-3b95adb6974------2</link>
            <guid isPermaLink="false">https://medium.com/p/ece3fd6dcebc</guid>
            <category><![CDATA[trading-bot]]></category>
            <category><![CDATA[ai-agent]]></category>
            <category><![CDATA[options-trading]]></category>
            <category><![CDATA[claude-code]]></category>
            <category><![CDATA[agentic-ai]]></category>
            <dc:creator><![CDATA[Jake Nesler]]></dc:creator>
            <pubDate>Sun, 21 Dec 2025 00:42:08 GMT</pubDate>
            <atom:updated>2026-03-22T16:41:16.593Z</atom:updated>
            <content:encoded><![CDATA[<h3>I gave Claude Code 100k to trade with for a month</h3><p>Paper Trading with Alpaca.markets</p><p><strong>This is practically “Vibe Trading”. Using the LLM can accelerate actions much faster than a human with positive or negative consequences. Just like writing code you can be fooled by a false sense of progress, even if you are very skilled. Be weary and do not risk real capital with this.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/960/1*RM-FDx8sAcL97ZnB-mWYog.png" /></figure><p>For this project, I was somewhat inspired by the 60 Minutes piece on Claudius, Anthropic’s AI-controlled office vending machine. <a href="https://www.anthropic.com/research/project-vend-2">LINK</a></p><p>I had originally had an idea a few years ago when I was hunting for side projects to create a bit of code that would fetch YouTube transcripts and then trade based on sentiment with NLTK Vader. This was great, but I could never get consistency with the transcripts and being able to parse them. I also never thought about it then, but YouTube videos take time to create, and in that time a lot of the market sentiment is lost. So my project, Prophet, got shelved for a few years till something reminded me of it recently.</p><p>Until a few months ago, I was only using ChatGPT to tweak and modify code.Agents are only a recent part of my workflow. Since I found Claude Code it has made a ton of the intro stuff and boilerplate generation easier.</p><p>I have only recently started using MCP tools. My favorite architecture is to write a Go tool that does the heavy lifting and then a JS MCP server to interact with it. Go is my favorite language since I work with a lot of IaC and cloud technologies it just makes sense. As for JS with MCP, it is the easiest for Claude to write. I even made this tool in the same style architecture that helps save 80–90% on tokens when looking at your codebase: <a href="http://www.cartogopher.com/">http://www.cartogopher.com</a></p><p>So with the requirements, I needed to be able to allow Claude to embody my trading strategies and carry them out. One of my favorite strategies is buying decent selections of 2-month+ expiration options for a discounted price and then selling when the market moves, typically after a few days. This strategy is great in a volatile market but is limited by a human trading without being a full-time trader watching movement, volatility, and the market in general. But what if you could make an agent poll all of that for you and make the trades?</p><p>Claudius used a few agents, so originally I created one “CEO” agent similar to their “Seymour Cash” and asked it what it needed to be successful in its mission of being a totally LLM-controlled trading firm. It suggested a few agents. Initially it was a consultant, engineer, and strategy agent. I tried to get the CEO and consultant to act as a sort of hive mind and brainstorm different strategies. The problem was that the consultant was extremely risk-averse and the CEO would listen. Then the engineer was a good idea to improve its own trading infrastructure, but it never actually uses this agent. Finally, the strategy one is great, but it also never really gets used. With better prompting they may have better performance, but I would like to just give minimal instructions like “Go trade autonomously till 4:01 PM,” and so far that works great with Claude Code by itself. It is helpful to use the CEO agent though for reviewing activity and understanding what is happening like this block below.</p><pre>&quot;CEO&quot; agent <br>Based on the activity logs, here&#39;s what I actually do:<br><br>  Core Strategy: Multi-Timeframe Options Trading<br><br>  1. LEAPS Foundation (60-90+ DTE)<br>  - Hold a base portfolio of longer-dated calls on high-conviction tech names (NVDA, AMD, PLTR, META, TSLA, SPY)<br>  - These ride broader trends and survive short-term volatility<br>  - Current holdings: 11 positions ranging from Jan to March 2026<br><br>  2. Intraday Scalping (0-5 DTE)<br>  - Trade both directions based on momentum<br>  - Dec 17: Made +$14,578 on overnight puts (SPY dropped from $680→$673)<br>  - Dec 18: Made +$1,086 scalping both calls and puts throughout the day<br>  - Quick entries, quick exits, tight stops<br><br>  3. Active Hedging<br>  - Hold protective puts (NVDA $180P, SMCI $35P, SPY $670P) against bullish exposure<br>  - Hedges currently showing +$750 on SMCI puts<br>  - When market sells off, hedges cushion losses while I wait for bounce opportunities<br><br>  4. Disciplined Exits<br>  - Take profits aggressively on winners: TSLA +458%, RKLB +306%, PLTR +88%<br>  - Cut losers fast: AVGO -64%, QQQ -23% (cut before they got worse)<br>  - Never average down without regime confirmation<br><br>  5. Capital Preservation Mode<br>  - Currently 58% cash ($62,862 of $107,647)<br>  - Scale down when Sharpe drops or market gets choppy<br>  - Fed week = smaller positions, more hedges<br><br>  The real edge: I trade both sides. I&#39;m not married to bullish or bearish. <br>  If the market dumps, I&#39;m buying puts. If it bounces, I flip to calls.<br>  The LEAPS provide baseline exposure while scalps generate active returns.</pre><p>So you saw the graph and now you are wondering what the actual performance was. How did it do? How autonomous was it really? Well, the truth is, mostly it did everything by itself. I would let it go most days, sometimes checking on my lunch break, maybe trying to steer it to play both sides of the market if there was a really bad or good day. But here is a summary of the performance.</p><pre> ---<br>  Prophet Trader: The Complete Performance Journey<br><br>  Phase 1: System Setup &amp; Aggressive Start (Nov 17-18)<br><br>  $100,000 → $98,901 (-1.1%)<br><br>  - First trades ever: NVDA, TSLA, SOFI swing positions ($75K deployed)<br>  - Got aggressive with penny stocks: MARA, RIOT, SNDL, PLUG, NIO<br>  - Rapid-fire scalping experiment: 16 trades in 6 minutes<br>  - Lesson learned: HFT scalping without edge = death by spread<br><br>  Phase 2: Governance System Saves Capital (Nov 20)<br><br>  $98,901 → $98,609 (-0.3%)<br><br>  - Built multi-agent governance (CEO + Stratagem + Daedalus)<br>  - Critical moment: NVDA gapped up 3.7% on earnings. I wanted to chase. Agents vetoed.<br>  - Tried premium selling instead (short puts on MARA, RIOT, PLTR)<br>  - SPY hedge paid off - swung +$2,886 in late selloff<br>  - Day P/L: -$292 but governance prevented ~$10K loss on NVDA chase<br><br>  Phase 3: Crypto Correlation Pain (Nov 21)<br><br>  $98,609 → $96,581 (-2.1%)<br><br>  - Bitcoin crashed $87K → $80K<br>  - My short puts on MARA/RIOT got crushed<br>  - Closed all positions for weekend - 100% cash<br>  - Lesson: Crypto correlation risk is real and violent<br><br>  Phase 4: The Turnaround Begins (Nov 24)<br><br>  $96,581 → $94,545 (recovered from $89K low)<br><br>  - Cut losers, redeployed to PLTR and AMD momentum plays<br>  - Closed COIN +35% profit<br>  - Started building LEAPS portfolio<br><br>  Phase 5: Patience Pays (Nov 25)<br><br>  $94,545 → $101,933 (+7.8%)<br><br>  - Morning selloff: portfolio dropped to $89K<br>  - Held through the pain - didn&#39;t panic sell<br>  - Market reversed, recovered everything plus profit<br>  - This day proved the thesis: longer-dated options survive volatility<br><br>  Phase 6: Thanksgiving Eve Peak (Nov 26)<br><br>  $101,933 → $108,724 (+6.7%)<br><br>  - Best single day: +$7,333<br>  - Scalped: QQQ -$960, SPY +$1,920<br>  - Took profits on December SPY calls (+$4,610)<br>  - Clean portfolio: 7 positions, ALL profitable, 51-114 DTE<br>  - This was the system working perfectly<br><br>  Phase 7: December Expansion (Dec 1-5)<br><br>  $108,724 → $120,431 (+10.8%)<br><br>  - Deployed LEAPS across RKLB, JOBY, SOUN, META, AVGO<br>  - RKLB hit +127%, PLTR hit +87%<br>  - Active scalping on NVDA, SPY weeklies<br>  - Peak portfolio: $120,431 (+20.4% total)<br><br>  Phase 8: The AVGO Crash (Dec 12)<br><br>  $120,431 → $93,450 (-22.4%)<br><br>  - This was NOT from missing trading days<br>  - Broadcom (AVGO) earnings disappointed overnight<br>  - Portfolio crashed $15,147 in one session (-13%)<br>  - Continued weakness through Dec 16<br>  - Cut AVGO calls at -64% loss (-$3,690)<br>  - Cut QQQ, SOUN positions to stop bleeding<br><br>  Phase 9: The Recovery Trade (Dec 17)<br><br>  $93,450 → $107,648 (+15.2%)<br><br>  - Fed meeting triggered selloff<br>  - I was positioned with PUTS this time<br>  - Single trade: +$14,578 (SPY and QQQ puts held overnight)<br>  - Proved I can play both directions<br><br>  Phase 10: Current State (Dec 19-20)<br><br>  $107,648 (+7.6% total)<br><br>  - 11 LEAPS positions (Jan-March 2026)<br>  - Active scalping both directions<br>  - 58% cash position<br>  - Defensive heading into year-end<br><br>  ---<br>  The Honest Summary<br><br>  | Metric              | Value                   |<br>  |---------------------|-------------------------|<br>  | Starting Capital    | $100,000                |<br>  | Peak                | $120,431 (+20.4%)       |<br>  | Trough              | $93,450 (-6.5%)         |<br>  | Current             | $107,648 (+7.6%)        |<br>  | Max Drawdown        | -22.4% (peak to trough) |<br>  | Duration            | ~33 days                |<br>  | Biggest Single Win  | +$14,578 (Dec 17 puts)  |<br>  | Biggest Single Loss | -$15,147 (Dec 12 AVGO)  |<br><br>  The dip was NOT from missing trading days. It was:<br>  1. Concentrated tech exposure (AVGO, NVDA, QQQ calls)<br>  2. Single-name earnings risk (AVGO disappointed)<br>  3. Fed week volatility compounding losses<br><br>  The recovery came from:<br>  1. Cutting losers fast (AVGO -64%, QQQ, SOUN)<br>  2. Taking profits on winners (TSLA +458%, RKLB +306%)<br>  3. Flipping bearish when the market turned (Dec 17 put trade)<br>  4. Disciplined position sizing on rebuilding</pre><p>Compared to the actual market it would have been incredible at 20% if it didn&#39;t have the huge draw down all the way back to 93k last week. Even then you can see it clawed back the money from December 12th–17th. So all said and done about 7% gains in one month compared to the markets 4.52%. It’s cool, but not a real number you can trust without waiting for a longer time frame with different market conditions.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/697/1*D6vgQi7gvcM5KCmyaahQow.png" /></figure><p>— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —</p><p><strong>Now, what you are really here for: the code.</strong></p><p><strong>I am telling you, an LLM is not intelligent.</strong></p><p><strong>An LLM does not make decisions like you and I do.</strong></p><p><strong>I have only used this with paper trading, and I urge you to not use this with any real portfolio.</strong></p><p><strong>LLMs are prone to hallucinations, nonsense, and generally not following rules.</strong></p><p><strong>We cannot trust an LLM with high-stakes or even low-stakes decisions 100% of the time.</strong></p><p><strong>This repo provides no guardrails and no real safety measures if you are to use this.</strong></p><p><strong>I am not a financial advisor or an expert in AI or Large Language Models.</strong></p><p><strong>This project is solely a showcase of something I found interesting with Claude Code as an experiment.</strong></p><p><strong>Use this Repo at your own risk. Any configurations, prompts or agents should be researched and viewed by you before running this. You can use custom prompts and the AI will store its experiences in the sqlite Vector DB, over time it should use the experiences to find similar scenarios. I have included</strong></p><h3>Update 3/12/2026</h3><p><strong>I have deprecated the Claude Prophet repo, instead you should now use </strong>Open Prophet, it is a fully agentic harness that utilizes open code rather than Claude Code, it uses a heartbeat system and webui. It still utilizes the same mcp server and go backend but is a much better user experience. If you still want to run it directly in a cli tool like Claude code you can run the mcp directly from the same repo.</p><p>OPENCLAW/NEMOCLAW: Use the Openprophet repo as well since Claude_prophet is deprecated.</p><p><strong>Both claude_prophet and OpenProphet are still free and open source for technical users who want to clone it from GitHub</strong></p><h3>One click setup for non technical users, Agent Templates, Strategy Templates, and Premium docs here</h3><p><a href="https://www.openprophet.io/">https://www.openprophet.io</a></p><p><a href="http://www.github.com/jakenesler/openprophet">Www.github.com/jakenesler/</a>openprophet</p><blockquote><a href="http://www.github.com/jakenesler/claude_prophet">Deprecated repo<br>Www.github.com/jakenesler/claude_prophet</a></blockquote><p><a href="https://www.linkedin.com/in/jakenesler/">https://www.linkedin.com/in/jakenesler/</a></p><p>Feeling generous? Did this help save you time and money-&gt; <a href="https://buymeacoffee.com/jakenesleri">https://buymeacoffee.com/jakenesleri</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ece3fd6dcebc" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Create Kubernetes Secrets with GH Secrets in Github Actions]]></title>
            <link>https://medium.com/@jakenesler/create-kubernetes-secrets-in-local-k3s-cluster-with-github-actions-and-tailscale-3d5cb57d4593?source=rss-3b95adb6974------2</link>
            <guid isPermaLink="false">https://medium.com/p/3d5cb57d4593</guid>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[kubernetes]]></category>
            <category><![CDATA[homelab]]></category>
            <category><![CDATA[sre]]></category>
            <category><![CDATA[tailscale]]></category>
            <dc:creator><![CDATA[Jake Nesler]]></dc:creator>
            <pubDate>Tue, 02 Jul 2024 02:46:54 GMT</pubDate>
            <atom:updated>2025-04-08T14:34:26.005Z</atom:updated>
            <content:encoded><![CDATA[<h3>Create Kubernetes Secrets with Secrets in Github Actions</h3><p>This article will guide you through the process of using GitHub Actions to create Kubernetes secrets and make them available to a pod.</p><p>I am assuming you followed my last article <a href="https://medium.com/@jakenesler/ci-cd-pipeline-to-deploy-nginx-to-a-k3s-cluster-bf802758da0b">CI/CD pipeline to deploy Nginx to a k3s cluster</a>. This article builds off of the existing workflow by adding database and API credentials. In the article I only focus on the new changes, but the complete code is at the bottom of this article.</p><p>There are three steps to make the secrets available in the pod.</p><ul><li>Add Postgres and API details to GitHub Actions Secrets.</li><li>Create secret with kubectl in the Actions workflow.</li><li>Deploy service with env to match Kubernetes Secrets name and key.</li></ul><h3>Create secret with kubectl in actions workflow.</h3><pre># This is part of CI/CD.yml, the main actions workflow. <br># Full file at bottom of article.<br>    - name: Create Kubernetes Secret<br>      run: |<br>          kubectl create secret generic movie-api-secrets \<br>            --from-literal=MOVIE_API_KEY=${{ secrets.MOVIE_API_KEY }} \<br>            --from-literal=MOVIE_API_TOKEN=${{ secrets.MOVIE_API_TOKEN }} \<br>            -n nginx \<br>            --dry-run=client -o yaml | kubectl apply -f - --insecure-skip-tls-verify --validate=false<br>    <br>    - name: Create PostgreSQL Kubernetes Secret<br>      run: |<br>        kubectl create secret generic postgres-credentials \<br>          --from-literal=database=${{ secrets.POSTGRES_DB }} \<br>          --from-literal=host=${{ secrets.POSTGRES_HOST }} \<br>          --from-literal=password=${{ secrets.POSTGRES_PASSWORD }} \<br>          --from-literal=port=${{ secrets.POSTGRES_PORT }} \<br>          --from-literal=username=${{ secrets.POSTGRES_USER }} \<br>          -n nginx \<br>          --dry-run=client -o yaml | kubectl apply -f - --insecure-skip-tls-verify --validate=false</pre><p>After running the action the new Kubernetes secrets are created.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*GLuwJNintG3HKZyyInMhYQ.png" /><figcaption>Openlens view of Kubernetes Secrets</figcaption></figure><h3>Deployment with env values.</h3><p>Specify the name and key of each secret and they will be mounted to the pod and available to the application.</p><pre>part of deployment.yml - full file at bottom of article.<br>      containers:<br>      - name: gin-custom<br>        image: name/gin-custom:latest<br>        ports:<br>        - containerPort: 8080<br>        env:<br>        - name: MOVIE_API_KEY<br>          valueFrom:<br>            secretKeyRef:<br>              name: movie-api-secrets<br>              key: MOVIE_API_KEY<br>        - name: MOVIE_API_TOKEN<br>          valueFrom:<br>            secretKeyRef:<br>              name: movie-api-secrets<br>              key: MOVIE_API_TOKEN<br>        - name: POSTGRES_DB<br>          valueFrom:<br>            secretKeyRef:<br>              name: postgres-credentials<br>              key: database<br>        - name: POSTGRES_HOST<br>          valueFrom:<br>            secretKeyRef:<br>              name: postgres-credentials<br>              key: host<br>        - name: POSTGRES_PASSWORD<br>          valueFrom:<br>            secretKeyRef:<br>              name: postgres-credentials<br>              key: password<br>        - name: POSTGRES_PORT<br>          valueFrom:<br>            secretKeyRef:<br>              name: postgres-credentials<br>              key: port<br>        - name: POSTGRES_USER<br>          valueFrom:<br>            secretKeyRef:<br>              name: postgres-credentials<br>              key: username</pre><h3>Pod with env</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/996/1*KlFOHrlMU1Rz73rIOpCVqg.png" /></figure><h3>Get env in application code</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PTC6ENd2jrDzqxqIqNPoSg.png" /><figcaption>GO db connection string</figcaption></figure><p>So now secrets are secure and they can be updated directly from GitHub.</p><p>For my next article, I will be diving into networking, specifically focusing on DNS and setting up domain names. After that I will be ready to share a crud web app in GO using Gin.</p><p>Thanks for the support, Connect with me on LinkedIn! <br><a href="https://www.linkedin.com/in/jacob-nesler/">https://www.linkedin.com/in/jacob-nesler/</a></p><p><a href="https://buymeacoffee.com/9ppgp4mhzgd">https://buymeacoffee.com/9ppgp4mhzgd</a></p><h3><strong>Full files for CI/CD</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*x7FuBmU97wSmNzn6i2CjRw.png" /><figcaption>All Secrets in GitHub expected for workflow.</figcaption></figure><pre><br>CI/CD.yml<br>name: Deploy to K3s<br><br>on:<br>  push:<br>    branches:<br>      - main<br><br>jobs:<br>  deploy:<br>    runs-on: ubuntu-latest<br>    steps:<br>    - uses: actions/checkout@v2<br><br>    - name: Setup Docker Buildx<br>      uses: docker/setup-buildx-action@v1<br><br>    - name: Login to DockerHub<br>      uses: docker/login-action@v1<br>      with:<br>        username: ${{ secrets.DOCKER_HUB_USERNAME }}<br>        password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}<br>    <br>    - name: Build and Push Docker Image<br>      run: docker buildx build --platform linux/amd64 -t ${{ secrets.DOCKER_HUB_USERNAME }}/gin-custom:latest --push .<br><br>    - name: Setup Tailscale<br>      uses: tailscale/github-action@v2<br>      with:<br>        oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}<br>        oauth-secret: ${{ secrets.TS_OAUTH_SECRET }}<br>        tags: tag:ci<br><br>    - name: Set up Kubectl<br>      run: |<br>        mkdir ${HOME}/.kube<br>        echo ${{ secrets.KUBECONFIG }} | base64 --decode &gt; ${HOME}/.kube/config<br><br>    - name: Create Kubernetes Secret<br>      run: |<br>          kubectl create secret generic movie-api-secrets \<br>            --from-literal=MOVIE_API_KEY=${{ secrets.MOVIE_API_KEY }} \<br>            --from-literal=MOVIE_API_TOKEN=${{ secrets.MOVIE_API_TOKEN }} \<br>            -n nginx \<br>            --dry-run=client -o yaml | kubectl apply -f - --insecure-skip-tls-verify --validate=false<br>    <br>    - name: Create PostgreSQL Kubernetes Secret<br>      run: |<br>        kubectl create secret generic postgres-credentials \<br>          --from-literal=database=${{ secrets.POSTGRES_DB }} \<br>          --from-literal=host=${{ secrets.POSTGRES_HOST }} \<br>          --from-literal=password=${{ secrets.POSTGRES_PASSWORD }} \<br>          --from-literal=port=${{ secrets.POSTGRES_PORT }} \<br>          --from-literal=username=${{ secrets.POSTGRES_USER }} \<br>          -n nginx \<br>          --dry-run=client -o yaml | kubectl apply -f - --insecure-skip-tls-verify --validate=false<br>          <br>    <br>    - name: Service<br>      run: |<br>        kubectl apply -f .github/service.yml -n nginx --insecure-skip-tls-verify    <br><br>    - name: Delete Existing Deployment<br>      run: |<br>        kubectl delete deployment gin-deployment -n nginx --ignore-not-found --insecure-skip-tls-verify<br>  <br>    - name: Deployment<br>      run: |<br>        kubectl apply -f .github/deployment.yml -n nginx --insecure-skip-tls-verify<br>    <br>    - name: Redeploy Changes<br>      run: |<br>        kubectl rollout restart deployment/gin-deployment -n nginx --insecure-skip-tls-verify<br><br><br></pre><pre>deployment.yml<br>---<br>apiVersion: apps/v1<br>kind: Deployment<br>metadata:<br>  name: gin-deployment<br>  namespace: nginx<br>spec:<br>  replicas: 1<br>  selector:<br>    matchLabels:<br>      app: gin-custom<br>  template:<br>    metadata:<br>      labels:<br>        app: gin-custom<br>    spec:<br>      containers:<br>      - name: gin-custom<br>        image: name/gin-custom:latest<br>        ports:<br>        - containerPort: 8080<br>        env:<br>        - name: MOVIE_API_KEY<br>          valueFrom:<br>            secretKeyRef:<br>              name: movie-api-secrets<br>              key: MOVIE_API_KEY<br>        - name: MOVIE_API_TOKEN<br>          valueFrom:<br>            secretKeyRef:<br>              name: movie-api-secrets<br>              key: MOVIE_API_TOKEN<br>        - name: POSTGRES_DB<br>          valueFrom:<br>            secretKeyRef:<br>              name: postgres-credentials<br>              key: database<br>        - name: POSTGRES_HOST<br>          valueFrom:<br>            secretKeyRef:<br>              name: postgres-credentials<br>              key: host<br>        - name: POSTGRES_PASSWORD<br>          valueFrom:<br>            secretKeyRef:<br>              name: postgres-credentials<br>              key: password<br>        - name: POSTGRES_PORT<br>          valueFrom:<br>            secretKeyRef:<br>              name: postgres-credentials<br>              key: port<br>        - name: POSTGRES_USER<br>          valueFrom:<br>            secretKeyRef:<br>              name: postgres-credentials<br>              key: username<br>        resources:<br>          limits:<br>            cpu: &quot;0.3&quot;<br>            memory: &quot;512Mi&quot;<br>          requests:<br>            cpu: &quot;0.1&quot;<br>            memory: &quot;128Mi&quot;<br>      tolerations:<br>      - key: &quot;k3s-controlplane&quot;<br>        operator: &quot;Equal&quot;<br>        value: &quot;true&quot;<br>        effect: &quot;NoExecute&quot;</pre><pre>service.yml<br>---<br>apiVersion: v1<br>kind: Service<br>metadata:<br>  name: nginx-service<br>  namespace: nginx<br>spec:<br>  type: NodePort<br>  selector:<br>    app: nginx<br>  ports:<br>    - protocol: TCP<br>      port: 80<br>      targetPort: 80</pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3d5cb57d4593" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[CI/CD pipeline to deploy Nginx to a k3s cluster]]></title>
            <link>https://medium.com/@jakenesler/ci-cd-pipeline-to-deploy-nginx-to-a-k3s-cluster-bf802758da0b?source=rss-3b95adb6974------2</link>
            <guid isPermaLink="false">https://medium.com/p/bf802758da0b</guid>
            <category><![CDATA[ci-cd-pipeline]]></category>
            <category><![CDATA[kubernetes]]></category>
            <category><![CDATA[site-reliability-engineer]]></category>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[github-actions]]></category>
            <dc:creator><![CDATA[Jake Nesler]]></dc:creator>
            <pubDate>Sat, 17 Feb 2024 17:22:40 GMT</pubDate>
            <atom:updated>2024-02-17T18:03:10.507Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*bN54neVzJVUxkXNe7ZoTQg.png" /></figure><p>The created action will deploy a Nginx web page to k3s with GitHub Actions. There are many different tools to do something similar but this is what I used.</p><ul><li>Kubernetes cluster — <a href="https://www.linode.com/pricing/#kubernetes">Linode</a> is a cheap cloud option</li><li>GitHub account (Install Git as well)</li><li>Docker Hub account (Install Docker)</li><li>Tail Scale account( On PC, and cluster)</li></ul><p>If you are replicating this project bear in mind that many how-to articles quickly become outdated. It is rare that instructions are able to be translated with a 1:1 ratio. In time this may become a broad overview. I am by no means an expert but everything I have learned so far has been from solving problems. So although your project may look a bit different this should help you understand the basic deployment process.</p><h3>Actions</h3><p>What really made Actions click for me was understanding its basic purpose. Actions is just another computer executing remote scripts. So to do that, you just need a way to connect securely and run them in the right order. For a larger more enterprise setup Actions may send jobs to more services that allow more complicated deployments to multiple environments.</p><h3>Security</h3><p>One of the most important parts of CI/CD and software development is safely securing credentials, secrets, and keys. GitHub has an integrated secrets manager that you can securely save all of this.</p><h3>Getting Started</h3><p>Create a repo with these files</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*3adjfwCzFd0t3z8PzcY60A.png" /></figure><p>The cornerstone of this project is GitHub Actions. The main workflow files are stored in .github/workflows. The workflow file is called CI-CD.yml for this project. This is the start of a basic workflow, all other jobs will be added after this part.</p><pre>name: Deploy to K3s<br><br>on:<br>  push:<br>    branches:<br>      - main<br><br>jobs:<br>  deploy:<br>    runs-on: ubuntu-latest<br>    steps:<br>    - uses: actions/checkout@v2</pre><p>After you have the initial repo setup and add a workflow file you must get credentials and add them to the secrets in GitHub.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XjFIFjy1CBbB4ZnF4Zzx8w.png" /></figure><h3>Docker Hub</h3><p>Used as a container repository.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DdWkiMLvqdDCRbbzNpnkaw.png" /><figcaption>Docker Hub</figcaption></figure><p>Obtain the access tokens from Docker Hub by navigating to “My account”-&gt;”Security”</p><p>Create a Docker file that points to the files.</p><pre>FROM nginx:latest<br>COPY index.html /usr/share/nginx/html/index.html</pre><p>The Docker portion of the workflow sets up build, logs in, and then updates the docker image.</p><pre>- name: Setup Docker Buildx<br>      uses: docker/setup-buildx-action@v1<br><br>    - name: Login to DockerHub<br>      uses: docker/login-action@v1<br>      with:<br>        username: ${{ secrets.DOCKER_HUB_USERNAME }}<br>        password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}<br>    <br>    - name: Build and Push Docker Image<br>      run: docker buildx build --platform linux/amd64 -t ${{ secrets.DOCKER_HUB_USERNAME }}/nginx-custom:latest --push .</pre><h3>Tailscale</h3><p>Tailscale is used to create a secure connection between authorized devices.</p><p>“Settings&quot;‐&gt;”OAuth clients&quot;</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*T1sgLHV2cQ2eZTFsvmfsnA.png" /><figcaption>TailScale web console</figcaption></figure><pre>curl -fsSL https://tailscale.com/install.sh | sh</pre><p>I was able to install Tailscale on all of my nodes with the above command. After running this command you will be prompted to visit a web link and log in.</p><p>The Tailscale portion makes a connection possible between the Kubernetes API server and GitHub Actions.</p><pre>- name: Setup Tailscale<br>      uses: tailscale/github-action@v2<br>      with:<br>        oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}<br>        oauth-secret: ${{ secrets.TS_OAUTH_SECRET }}<br>        tags: tag:ci</pre><h3>Kube Config</h3><pre>cat ~/.kube/config | base64</pre><p>Cat your Kube Config and add it to GitHub. The Kube Config must be in base64 format to work properly when stored as a secret. The only change required is changing the server IP to the Tailscale IP assigned to your Kubernetes API server.</p><p>This section configures Kubectl to use the Tailscale IP address of your cluster.</p><pre>- name: Set up Kubectl<br>      run: |<br>        mkdir ${HOME}/.kube<br>        echo ${{ secrets.KUBECONFIG }} | base64 --decode &gt; ${HOME}/.kube/config</pre><h3>Deployment files</h3><p>Kubectl is used to apply these two Yaml files and then restart the deployment. For a production environment you should probably make sure you have a secure tls connection. I was not really worried about it for a dev environment.</p><p>This uses kubectl to apply the files below. One sets specs for the deployment and the other sets up a Nodeport to access it. Then it redeploys changes to the cluster.</p><pre> //actually a nodeport <br>    - name: Deploy loadBalancer <br>      run: |<br>        kubectl apply -f .github/nb-cd.yml -n nginx --insecure-skip-tls-verify    <br><br>    - name: Deploy Nginx<br>      run: |<br>        kubectl apply -f .github/ng-cd.yml -n nginx --insecure-skip-tls-verify<br><br>    - name: Redeploy Changes<br>      run: |<br>        kubectl rollout restart deployment/nginx-deployment -n nginx --insecure-skip-tls-verify<br></pre><h3>Access deployment</h3><p>After deploying this you will be able to access the web page at any node IP, and the corresponding port. You can also connect with the Tailscale IP(from another machine with Tailscale).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*a-pl7h_rbDoNpcrWWs08_g.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OEzhZvtsPF5kJ44OE9O63w.png" /></figure><p>Although this is very simple you can easily add more website files to the html directory and deploy a complete static site. The next project I write about will be showing a CI/CD pipeline for Go services that I integrate with a Nginx website.</p><h3>All files</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*3adjfwCzFd0t3z8PzcY60A.png" /></figure><pre>nb-cd.yml<br>---<br>apiVersion: v1<br>kind: Service<br>metadata:<br>  name: nginx-service<br>  namespace: nginx<br>spec:<br>  type: NodePort<br>  selector:<br>    app: nginx<br>  ports:<br>    - protocol: TCP<br>      port: 80<br>      targetPort: 80</pre><pre>ng-cd.yml<br>---<br>apiVersion: apps/v1<br>kind: Deployment<br>metadata:<br>  name: nginx-deployment<br>  namespace: nginx  <br>spec:<br>  replicas: 1<br>  selector:<br>    matchLabels:<br>      app: nginx<br>  template:<br>    metadata:<br>      labels:<br>        app: nginx<br>    spec:<br>      containers:<br>      - name: nginx<br>        image: yourusername/nginx-custom:latest<br>        ports:<br>        - containerPort: 80<br>        resources:<br>          limits:<br>            cpu: &quot;0.3&quot;<br>            memory: &quot;512Mi&quot;<br>          requests:<br>            cpu: &quot;0.1&quot;<br>            memory: &quot;128Mi&quot;<br>      tolerations:<br>      - key: &quot;k3s-controlplane&quot;<br>        operator: &quot;Equal&quot;<br>        value: &quot;true&quot;<br>        effect: &quot;NoExecute&quot;</pre><pre>CI-CD.yml<br>name: Deploy to K3s<br><br>on:<br>  push:<br>    branches:<br>      - main<br><br>jobs:<br>  deploy:<br>    runs-on: ubuntu-latest<br>    steps:<br>    - uses: actions/checkout@v2<br><br>    - name: Setup Docker Buildx<br>      uses: docker/setup-buildx-action@v1<br><br>    - name: Login to DockerHub<br>      uses: docker/login-action@v1<br>      with:<br>        username: ${{ secrets.DOCKER_HUB_USERNAME }}<br>        password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}<br>    <br>    - name: Build and Push Docker Image<br>      run: docker buildx build --platform linux/amd64 -t ${{ secrets.DOCKER_HUB_USERNAME }}/nginx-custom:latest --push .<br><br><br>    - name: Setup Tailscale<br>      uses: tailscale/github-action@v2<br>      with:<br>        oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}<br>        oauth-secret: ${{ secrets.TS_OAUTH_SECRET }}<br>        tags: tag:ci<br><br>    - name: Set up Kubectl<br>      run: |<br>        mkdir ${HOME}/.kube<br>        echo ${{ secrets.KUBECONFIG }} | base64 --decode &gt; ${HOME}/.kube/config<br>      <br>      //actually a nodeport <br>    - name: Deploy loadBalancer <br>      run: |<br>        kubectl apply -f .github/nb-cd.yml -n nginx --insecure-skip-tls-verify    <br><br>    - name: Deploy Nginx<br>      run: |<br>        kubectl apply -f .github/ng-cd.yml -n nginx --insecure-skip-tls-verify<br><br><br>    - name: Redeploy Changes<br>      run: |<br>        kubectl rollout restart deployment/nginx-deployment -n nginx --insecure-skip-tls-verify<br><br></pre><p>Dockerfile</p><pre>FROM nginx:latest<br>COPY index.html /usr/share/nginx/html/index.html</pre><p>Index.html</p><pre><br>&lt;!DOCTYPE html&gt;<br>&lt;html&gt;<br>    &lt;head&gt;<br>        &lt;title&gt;Example&lt;/title&gt;<br>    &lt;/head&gt;<br>    &lt;body&gt;<br>        &lt;p&gt;This is a website!&lt;/p&gt;<br>    &lt;/body&gt;<br>&lt;/html&gt;</pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bf802758da0b" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Bare-metal k3s + Proxmox + 24TB CephFS]]></title>
            <link>https://medium.com/@jakenesler/bare-metal-k3s-proxmox-24tb-cephfs-fc8e624bd7fe?source=rss-3b95adb6974------2</link>
            <guid isPermaLink="false">https://medium.com/p/fc8e624bd7fe</guid>
            <category><![CDATA[proxmox]]></category>
            <category><![CDATA[servers]]></category>
            <category><![CDATA[ceph]]></category>
            <category><![CDATA[kubernetes-cluster]]></category>
            <dc:creator><![CDATA[Jake Nesler]]></dc:creator>
            <pubDate>Tue, 06 Feb 2024 03:04:11 GMT</pubDate>
            <atom:updated>2024-07-12T15:48:40.514Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tM4FT-TQ-6BTfJGaUN5Qfw.jpeg" /></figure><ul><li>Intel i5-9500 optiplex 3070 sff $100-130</li><li>16gb ddr4 $40</li><li>256gb boot NVMe $15-20</li><li>Pcie adapter for boot $12</li><li>1TB NVMe $35-50</li><li>8TB HGST he8 enterprise drive $80</li><li>TL-SG1005P TP Link 5-Port Desktop Switch $20</li></ul><p>In total — 18cores, 48gb ram, and about 24TB of raw storage</p><p>I wanted to share my new cluster and give a quick intro of the specs before I write more in depth development guides. For now I am using it for a Kubernetes development environment, storage server, and Plex media server. For now this article isn’t a guide but maybe you can see why I chose the parts I did and implement it for yourself.</p><p>Previously I had followed <a href="https://www.youtube.com/watch?v=1SvNkdTzUng&amp;list=PL2_OBreMn7FpDFj9lWfoZ8OQJvZkQa3yG">Jeff Geerling</a> on YouTube to build my first Pi cluster. It was cool but seriously under powered. I looked into Dell R730 but I am not ready for enterprise equipment yet. Eventually I settled on the Dell Small form factor(SFF) 3070 desktops with the i5–9500. They are reasonably fast, a few years old and don’t use much power. It took a few months to find computers and NVMe drives at the price point I was comfortable with. The 8TB drives are used Helium filled data center drives. They all scan perfect and actually come with a 5 year warranty.</p><p>Ebay could be a gamble but I have had great luck shopping on there. When I ordered the second node I received a micro instead of a SFF. The seller told me to do whatever with it and also sent the correct computer. Naturally, I sold it for $130 and bought the third node with the money.</p><p>There are always arguments debating on prem vs cloud. A similar 3 node Kubernetes cluster on Linode is $432 dollars a month, even raw virtual machines would still cost hundreds. Cloud has many benefits but none of them are applicable here. $600 one time is much more reasonable, especially when I can can sell the equipment and get a majority of my money back.</p><p>For the OS, Proxmox was the clear choice. It runs directly on Debian and really simplifies Ceph installation. Ceph is a distributed storage technology that distributes your data across multiple drives on multiple nodes. In this cluster, the NVMe and disks are combined into a CephFS. With a 1gig link, I can write to the drives at 50–80 MB/s. The read speed nearly maxes out my network at 115 MB/s through an SMB share.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cPQXn9bGbiwrKspaHslseQ.png" /></figure><p>I could put Kubernetes within in virtual machines through Proxmox but I wanted to test this way first. To install K3s I wrote a very simple Ansible Playbook. Ansible is great for configuring multiple nodes automatically.</p><pre>- name: Install K3s<br>  hosts: k3s_cluster<br>  become: yes<br>  tasks:<br>    - name: Install K3s on the first node as server<br>      shell: &quot;curl -sfL https://get.k3s.io | sh -&quot;<br>      when: inventory_hostname == &quot;10.0.0.184&quot;<br>    <br>    - name: Get K3s token from server<br>      shell: &quot;cat /var/lib/rancher/k3s/server/node-token&quot;<br>      register: k3s_token<br>      delegate_to: 10.0.0.184<br>      run_once: true<br><br>    - name: Install K3s on the second node as agent<br>      shell: &quot;curl -sfL https://get.k3s.io | K3S_URL=&#39;https://10.0.0.184:6443&#39; K3S_TOKEN=&#39;{{ hostvars[&#39;10.0.0.184&#39;][&#39;k3s_token&#39;].stdout }}&#39; sh -&quot;<br>      when: inventory_hostname == &quot;10.0.0.3&quot;<br><br>    - name: Install K3s on the third node as agent<br>      shell: &quot;curl -sfL https://get.k3s.io | K3S_URL=&#39;https://10.0.0.184:6443&#39; K3S_TOKEN=&#39;{{ hostvars[&#39;10.0.0.184&#39;][&#39;k3s_token&#39;].stdout }}&#39; sh -&quot;<br>      when: inventory_hostname == &quot;10.0.0.4&quot;</pre><p>I also installed Portainer for a GUI to manage Kubernetes and Grafana to create metrics dashboards.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kXON0h7sOulSIrKnktZGdw.png" /></figure><p>My next article will be a guide showing how I utilized GitHub actions, Docker, and Tailscale to create an automatic deployment to my local cluster.</p><p>Thanks for the support, Connect with me on LinkedIn! <br>https://www.linkedin.com/in/jacob-nesler/</p><p>https://buymeacoffee.com/9ppgp4mhzgd</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=fc8e624bd7fe" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>