<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>TheShadowEevee&apos;s Blog</title><description>A place where I post some of the dumb things I do</description><link>https://shad.moe/</link><language>en</language><atom:link href="https://shad.moe/rss.xml" rel="self" type="application/rss+xml"/><lastBuildDate>Tue, 03 Feb 2026 00:00:00 GMT</lastBuildDate><copyright>CC BY 4.0</copyright><item><title>Gridania Roundup - The Advent of `.`</title><link>https://shad.moe/posts/gridania-roundup/2026/02/03/advent/</link><guid isPermaLink="true">https://shad.moe/posts/gridania-roundup/2026/02/03/advent/</guid><description>Edition no. 1 of the Gridania Roundup</description><pubDate>Tue, 03 Feb 2026 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;&lt;span&gt;&lt;div&gt;Gridania Roundup&lt;/div&gt;&lt;/span&gt;&lt;p&gt;This post is part of the Gridania Roundup series, a mock Newspaper based out of the MMORPG &lt;a&gt;Final Fantasy XIV&lt;/a&gt;. This is a creative writing series, and all information within should not be taken as fact.&lt;br /&gt;
This post was unfortunatly delayed for some time. The initial draft was written on December 17&lt;sup&gt;th&lt;/sup&gt;, 2025.&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;By &lt;a&gt;Sakura Yoshida&lt;/a&gt;, Staff Reporter of the Gridania Roundup&lt;br /&gt;
Published 17th Sun, 6th Umbral Moon&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A crowd has gathered in the Coerthas Western Highlands tonight, just beyond the Falcon’s Nest, to witness a spectacular creature, previously unknown to Eorzean wildlife biologists. The mysterious creature bears no name, though it takes an apperance similar to the common Steinbock or Antelope Doe. Many have taken to naming the creature, with some names including “Doe”, “Charles”, or “That Thing”. However, concensus has generally landed on the name &lt;code&gt;.&lt;/code&gt;.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://konpeki.solutions/xrpc/com.atproto.sync.getBlob?did=did%3Aplc%3Akrbzbucjaj76xjob6ju47ilo&amp;amp;cid=bafkreicjagrwg5yy3q2xrmhvvbeqw5ous5jcfge7pcp4exj3e3xzjdicfy&quot; alt=&quot;drawing&quot; /&gt;
  &lt;figcaption&gt;Staff Reporter Sakura Yoshida watching . in it&apos;s natural habitat.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;I spent multiple hours on the scene with one of the &lt;code&gt;.&lt;/code&gt; in the Western Highlands, chatting with adventurers and tourists. The crowd was often quite large, at one point exceeding 40 individuals. At least one Fan Club was started at the scene, and many tourists were riding Antelope Doe steeds to commemorate the occasion.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.&lt;/code&gt; was first sighted sometime on the 15th Sun of the 6th Umbral Moon by an unknown adventurer, and word of the strange creature quickly spread. The Temple Knights have determined &lt;code&gt;.&lt;/code&gt; to be a relatively harmless creature and one of the safest they’ve encountered in the Western Highlands to date, leaving curious individuals little reason to not venture to the Highlands themselves in search of &lt;code&gt;.&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The phenomenon has caused a short rise in the tourism to the Ishgard despite the slow travel season. Locals from the Firmament were unprepared for the increase in foot traffic during the Starlight season,&lt;/p&gt;
&lt;p&gt;We interviewed &lt;a&gt;Ashi Kar’toh&lt;/a&gt; at the scene for comment. [The following interview is edited for berevity.]&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Sakura Yoshida:&lt;br /&gt;
Hello Hello, I’m Sakura Yoshida with the Gridania Roundup. Can I interview you about the recent appearance of &lt;code&gt;.&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;Ashi Kar’toh:&lt;br /&gt;
What’s there to ask?&lt;/p&gt;
&lt;p&gt;Sakura Yoshida:&lt;br /&gt;
For starters, how do you feel about &lt;code&gt;.&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;Ashi Kar’toh:&lt;br /&gt;
Whereas a deity such as Skogs Fru would empower one to feel awestruck, &lt;code&gt;.&lt;/code&gt; instead warrants a feeling of calm and serenity&lt;/p&gt;
&lt;p&gt;Sakura Yoshida:&lt;br /&gt;
Mhm, mhm… And where do you think &lt;code&gt;.&lt;/code&gt; came from? Leading researchers haven’t found a conclusive answer to this question?&lt;/p&gt;
&lt;p&gt;Ashi Kar’toh:&lt;br /&gt;
It’s her presence, in the same way that one may feel empowered when hearing a speech by a smart and noble man. Though it may even go further than her contageous attitude and peaceful way of life - perhaps her aether itself is strong enough to be sensed by others.&lt;/p&gt;
&lt;p&gt;Sakura Yoshida:&lt;br /&gt;
Interesting take, I can’t help but see your logic. If I may ask on last question, is there anything you would like the readers to know about &lt;code&gt;.&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;Ashi Kar’toh:&lt;br /&gt;
Praise Skogs Fru.&lt;/p&gt;
&lt;p&gt;Sakura Yoshida:&lt;br /&gt;
I… I see. Well, thank you for your time today, Ashi.&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded><dc:creator>Sakura Yoshida</dc:creator><dc:creator>Nox</dc:creator><category>Gridania Roundup</category><category>FFXIV</category></item><item><title>The Appeals of Homelabbing</title><link>https://shad.moe/posts/2025/05/01/the-appeals-of-homelabbing/</link><guid isPermaLink="true">https://shad.moe/posts/2025/05/01/the-appeals-of-homelabbing/</guid><description>The Ups and Downs of having a Homelab</description><pubDate>Thu, 01 May 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Of my five blog posts prior to this, I consider three of them “real” posts. These are “&lt;a&gt;Renaming an Active Node in a Proxmox Cluster&lt;/a&gt;”, “&lt;a&gt;Notes for Self-Hosting an ATProto PDS&lt;/a&gt;”, and “&lt;a&gt;Welcome to the ATmosphere!&lt;/a&gt;”. In &lt;em&gt;each&lt;/em&gt; of these prior posts, I made some allusion to my personal Homelab, a set of hardware spread between two (or three, if you count my Oracle Cloud server) locations running nearly everything that is accessible on &lt;a&gt;shad.moe&lt;/a&gt; and &lt;a&gt;konpeki.solutions&lt;/a&gt;. I think it’s about time I actually &lt;em&gt;write&lt;/em&gt; about this homelab, and more-so why I have a homelab in the first place.&lt;/p&gt;
&lt;blockquote&gt;
&lt;section&gt;&lt;h4&gt;Definition: Homelab&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;”…Homelab is the name given to a server (or multiple server setup) that resides locally in your home and where you host several applications and virtualized systems for testing and developing or for home and functional usage.”&lt;/p&gt;&lt;p&gt;“This server can be a simple tower or small PC or a Raspberry Pi like device or a repurposed professional server that you can acquire from companies who discard them due to their age but are still usable.” - &lt;a&gt;Helder - Linux Handbook&lt;/a&gt;&lt;/p&gt;&lt;/section&gt;
&lt;/blockquote&gt;
&lt;p&gt;Actually, I disagree with this definition slightly. Where Helder specifies that the server “resides locally in your home”, I think that can be loosened a bit. This is indeed generally true, but there can be exceptions - your definition of a homelab can be different! At its core, a homelab is a machine or set of machines in your control on which you can run basically whatever you want! Some people make lists of their “recommended” services to host, but I won’t be doing that. What I host can vary quite a bit from what you may want, so instead I’ll direct to this &lt;a&gt;directory of selfhostable apps&lt;/a&gt; that you can explore at your leisure.&lt;/p&gt;
&lt;p&gt;Instead, my aim in writing this is to talk about my personal homelab, and why &lt;em&gt;you&lt;/em&gt; should consider creating your own!&lt;/p&gt;
&lt;blockquote&gt;&lt;span&gt;&lt;div&gt;Supplemental Information Notice&lt;/div&gt;&lt;/span&gt;&lt;p&gt;Much of this post consists of information about my own homelab setup. For this reason, a lot of what I talk about may contain links to other resources about this software / hardware.
If you are interested in learning about a piece of my homelab, feel free to follow the links! A lot of the discussion about my setup will be information dense, and the links will help to better explain a given topic for your own use.&lt;/p&gt;&lt;/blockquote&gt;
&lt;section&gt;&lt;h2&gt;My Hardware&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;I’ve talked in some length about my own Homelabbing equipment in my previous posts. At the time of publishing, my setup currently consists of two &lt;a&gt;Dell PowerEdge R640&lt;/a&gt; servers and one &lt;a&gt;Dell Optiplex 5040&lt;/a&gt;. I also have two Oracle Cloud free tier VPS servers. The &lt;em&gt;networking&lt;/em&gt; side of things is much more varied.&lt;/p&gt;&lt;p&gt;Currently, the two R640s are in a dorm room on the Purdue University campus, which are soon to be moved as the semester winds up. For those two servers, an &lt;a&gt;HP ProCurve 2910al-48G&lt;/a&gt; switch is used for local communication (as well as other clients in my dorm room), which is routed through an old &lt;a&gt;Netgear WNDR3400&lt;/a&gt; router running &lt;a&gt;dd-wrt&lt;/a&gt;, which is connected to Purdue’s network. At home, an hour and a half away, my Optiplex sits in a laundry room with a direct ethernet connection to the router there.&lt;/p&gt;&lt;p&gt;Communication between these servers is handled via &lt;a&gt;Tailscale&lt;/a&gt;, on their free tier. I am a fan of Tailscale, and have explored alternatives (&lt;a&gt;Headscale&lt;/a&gt;, &lt;a&gt;Netbird&lt;/a&gt;, &lt;a&gt;Self-Managed Wireguard&lt;/a&gt;) but kept returning to Tailscale in the end. All World-Accessible endpoints (mostly everything hosted on &lt;a&gt;shad.moe&lt;/a&gt;, &lt;a&gt;konpeki.solutions&lt;/a&gt;, or their subdomains) are routed to the two Oracle Cloud VPSs, which have the primary purpose of proxying traffic to the internal servers.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;So… Why bother homelabbing?&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Personally? I find homelabbing fun. Some people lab for learning, others to reduce their reliance on corporate oversight, and many others lab for reasons I don’t know. My homelab is what I jokingly call a “High Downtime Environment”. I break things, often, and the perceived usefulness or interest any given puzzle piece provides determines if it gets fixed or stays broken. This is a good thing! This freedom allows me to do a lot more than I could in a constrained environment.&lt;/p&gt;&lt;p&gt;I also enjoy playing with new software. Having a Homelab provides a perfect environment to tinker and put things into production! The most recent example I have is &lt;a&gt;Anubis&lt;/a&gt;. I do care a bit about resiliency, and security, so Anubis immediately struck my interest.&lt;/p&gt;&lt;blockquote&gt;
&lt;section&gt;&lt;h4&gt;What is Anubis?&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;“Anubis &lt;a&gt;weighs the soul of your connection&lt;/a&gt; using a sha256 proof-of-work challenge in order to protect upstream resources from scraper bots.”&lt;/p&gt;&lt;p&gt;“This program is designed to help protect the small internet from the endless storm of requests that flood in from AI companies. Anubis is as lightweight as possible to ensure that everyone can afford to protect the communities closest to them.” - &lt;a&gt;Anubis Documentation - April 2nd, 2025&lt;/a&gt;&lt;/p&gt;&lt;/section&gt;
&lt;/blockquote&gt;&lt;p&gt;I heard about Anubis directly from the source: a Bluesky post made in late March by the original developer, &lt;a&gt;Xe Iaso&lt;/a&gt;. If you haven’t heard of them before, I &lt;strong&gt;&lt;em&gt;highly&lt;/em&gt;&lt;/strong&gt; recommend checking out their site and blog! Anubis was a tool created to solve a specific problem: AI Scrapers bullying websites with overwhelming amounts of requests in their thirst for more data. I won’t be able to do right by &lt;a&gt;the first of Iaso’s blog posts&lt;/a&gt; on this, so I highly encourage checking their post out yourself.&lt;/p&gt;&lt;p&gt;Anubis is the latest example of software I thought was &lt;em&gt;interesting&lt;/em&gt; and/or could serve a useful purpose to me. Soon after I learned about Anubis, I overhauled my outward-facing networking (previously a number of muddled proxies between the world and my servers), and simplified the flow while implementing Anubis at the same time. Anubis doesn’t work on some of my subdomains - it’s not supposed to work on everything! - but for those it does, it now protects. This includes my &lt;a&gt;Forgejo/Git instance&lt;/a&gt; and my &lt;a&gt;SearXNG instance&lt;/a&gt; for example.&lt;/p&gt;&lt;p&gt;However, it’s important to know that homelabbing &lt;em&gt;can&lt;/em&gt; be time consuming if you let it, and you will oft find something broken for you to fix.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;There’s Always Trouble in Paradise&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Even now, as I begin the process of writing this blog post, I had to stop writing to fix a bug I noticed. I was on &lt;a&gt;Bluesky&lt;/a&gt;, and I attempted to follow the account &lt;a&gt;@techaro.lol&lt;/a&gt;, the company behind Anubis. I noticed however that while the BlueSky AppView reported for a moment that I now follow the account, BlueSky quickly forgot this fact and re-displayed the blue “follow button”. After some investigation, I discovered that this was because of a change I had made on a whim, which had consequences I hadn’t anticipated. Let me walk you through the journey I took to get this fixed - I documented each step as I took it to include in this post.&lt;/p&gt;&lt;p&gt;First, I tried to access my Nginx logs to check the network traffic to my self-hosted data server. I grabbed my phone to open the Proxmox mobile app, but I soon remembered I had been working on moving Nginx to a NixOS-based machine instead, so I would need to access that machine rather than one of my Proxmox containers. Unfortunately, the SSH key to connect is on a hardware token my phone wasn’t immediately able to use. So, I grabbed my laptop - and found it dead. After plugging it in and turning it on, I attempted to SSH into the Nginx container to discover that I still couldn’t access it; I had changed the SSH port earlier and forgot to allow the new port in the firewall. Luckily, one quick configuration change later, and I was in! And yet, after all of that, the access logs looked &lt;em&gt;fine&lt;/em&gt;. Any calls to the PDS were returning code 200 (HTTP code for “OK”) and no errors were being posted.&lt;/p&gt;&lt;p&gt;What gives? Well, further research online and in the “AT Protocol PDS Admins” Discord server turned up similar occurrences for instances with &lt;em&gt;WebSockets&lt;/em&gt; incorrectly configured. This couldn’t be my issue though - I had just added &lt;code&gt;proxyWebsockets = true;&lt;/code&gt; to all my Nginx configurations some hours ago! It couldn’t be possible that WebSockets weren’t being proxied. …Right?&lt;/p&gt;&lt;p&gt;Wrong, and it’s because I made a mistake. The configuration file that defines the url for the PDS instance, &lt;a&gt;&lt;code&gt;$/machines/servers/barrier-nginx/nginx/solutions/konpeki/default.nix&lt;/code&gt;&lt;/a&gt;, had apparently been overlooked and &lt;strong&gt;never had this configuration set&lt;/strong&gt;! Of course, adding the single missing line immediately resolved my issues. Problem solved! Now I can follow Techaro, and re-like the few post I had attempted to like in the downtime.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;A Place to Try New Things, and Break Old Ones&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;I host a fair amount of services on my personal hardware. For example, even this blog is running in two parts, &lt;a&gt;an Astro frontend&lt;/a&gt; and &lt;a&gt;my ATProto Personal Data Server&lt;/a&gt;. Both of these are hosted on different LXC containers, further separated from the Nginx server which is hosted on a free Oracle Cloud machine (one of the 1GB ram, 1 oCPU machines). While this may seem intimidating, I manage my efforts to prevent it from being a burden. Keeping my homelab together can be a chore at times, but it should never become like a job!&lt;/p&gt;&lt;p&gt;Allowing myself these freedoms opens up doors to the ability to make changes that you otherwise couldn’t in a more “production” or “corporate” setting. Most companies obviously wouldn’t allow an employee to haphazardly prop up software or reconfigure hardware that interests them with the ease you can in a homelab. In the same vein, I would be fired on the spot if I started completely reinstalling an entire server’s operating systems just because I “wanted to try NixOS”.&lt;/p&gt;&lt;p&gt;In fact, some people do treat their Homelabs as if they were in a company setting! I personally do a mix of both - many of my services run on the &lt;a&gt;shad.moe&lt;/a&gt; domain, often more personal services like my blog or my RSS Aggregator. However, I also make use of the name Konpeki Solutions for anything I target to be more like a company. This includes the domains &lt;a&gt;konpeki.solutions&lt;/a&gt; and konsol.internal, which host my BlueSky PDS.&lt;/p&gt;&lt;blockquote&gt;&lt;span&gt;&lt;div&gt;What is Konpeki Solutions?&lt;/div&gt;&lt;/span&gt;&lt;p&gt;Konpeki Solutions is a strange construct. It is an example company name, a legal name (currently as a DBA, with plans to incorporate using the name if/when I need to form a Corporation for something), and the setting of a fictional corporation. This fictional corporation and it’s employees (the universes’ characters) will someday appear in some form brought to life by me and my sibling &lt;a&gt;@axoblu&lt;/a&gt;. I will write more about Konpeki Solutions / KonSol in a future post.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;This type of organization of your homelab can help guide you in certain directions, and is a good way to focus your efforts! Sometimes having self-imposed constraints can make things more interesting and easier to work on then having no idea what to do next.&lt;/p&gt;&lt;p&gt;On top of this, this environment allows me to make mistakes and learn at a pace that far surpasses what i could achieve without. Simply having a two-node Proxmox cluster has given me knowledge that many people wouldn’t have prior to working in a more corporate Proxmox environment - and even in that case, I have a much deeper knowledge of some of aspects than the average tech would. (See my &lt;a&gt;Proxmox Cluster Post&lt;/a&gt; for an example. I’d bet most people haven’t had to hand repair a Proxmox Cluster!)&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;How does one start a homelab?&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;You can make your homelab as simple or as complicated as you want! There are plenty of reading resources on creating a homelab, and I’ve included some of my personal favorites.&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;a&gt;r/homelab on Reddit&lt;/a&gt; - A Reddit Community of other Homelabbers. Typically more hardware focused.&lt;/li&gt;
&lt;li&gt;&lt;a&gt;r/selfhosted on Reddit&lt;/a&gt; - A Reddit Community of people self-hosting services for their own uses. Typically more software focused.&lt;/li&gt;
&lt;li&gt;&lt;a&gt;Self-Host Weekly Newsletter&lt;/a&gt; - A Weekly Newsletter that shares updates in the self-hosting community, including new software, updates to software, and other general news.&lt;/li&gt;
&lt;li&gt;&lt;a&gt;Self-Host Apps Directory&lt;/a&gt; - A directory of self-hostable apps, managed by the same person behind the Self-Host Weekly Newsletter.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;As well as these resources, I’ve drafted a few different categories of ways you can start a homelab below. Feel free to read them all, or skip to the category that interests you most!&lt;/p&gt;&lt;blockquote&gt;&lt;span&gt;&lt;div&gt;Disclaimer&lt;/div&gt;&lt;/span&gt;&lt;p&gt;The following suggestions are a mix of personal experience and information I’ve heard from friends and online. Always know what you’re buying, what the policies on return are, etc.
TL;DR - Treat your money with the care it deserves!&lt;/p&gt;&lt;/blockquote&gt;&lt;section&gt;&lt;h4&gt;I don’t want to purchase anything&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;There are many ways to begin a homelab without spending a cent! Whether you want to get a taste of the experience or you want to avoid ever spending money, you have plenty of options. Some good places to start are with software that runs in Docker containers, as you can easily run a handful of these in the background on an existing desktop machine. If you have old hardware laying around, such as an old laptop, this can also make for a great start to a Homelab! Installing a Linux distribution (preferably without a graphical environment if it will be a server) is a great way to breathe some extra life into old tech you have laying around, and often times what you thought was e-waste can be a decent host.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;I want to own my hardware&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;Personally, each of my physical servers were obtained thanks to the Purdue University &lt;a&gt;Surplus Store&lt;/a&gt;. I’ve spent 350 US Dollars there, which seems like a lot at first glance, until you compare to the hardware. Each of my two R640s were obtained for 100 US Dollars each, while the Optiplex and the HP ProCurve switch were about 50 US Dollars each. These are really good deals on older server hardware, and everything worked great! I’ve since upgraded the RAM in the Optiplex and did have to purchase storage for each machine, as they don’t come with their storage installed for data security reasons. If you don’t have a similar store nearby, there are other places you can look for deals. Government and other Surplus sites online may offer hardware if you can arrange shipping, and sites like eBay can have some good deals as well.&lt;/p&gt;&lt;p&gt;Of course, you don’t need enterprise grade hardware either! In fact, for a lot of people this is an anomaly. Like if you were to purchase nothing, old laptops and desktops can be great servers. You can often get these for cheap (know the worth of what you’re buying though!), and in some areas even free! Ask some friends if they have old tech they don’t want anymore, hit up your local e-waste collections facility (some are amiable to letting you have some of their collected hardware, but most aren’t. They have to make money somehow!), or even check with your workplace, school, etc. to see if you can requisition some old hardware destined for recycling or destruction. As with before, in almost every case you’ll have to provide your own storage, and these methods are more likely to net you broken tech. For some people, fixing their hardware is part of the fun! For others, inspect anything before you buy or otherwise requisition it if possible.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;I want to rent a server&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;Renting a server is another way to get a machine to self-host a homelab. I can’t recommend any service providers myself, but a number of Cloud Service Providers (CSPs) offer Virtual Private Servers you can rent on a timed basis. You’ll often expect to pay for CPU hours, Network Ingress/Egress, etc., but CSPs have the advantage of uptime guarantees, fast networks, and no physical maintenance requirements. If you’ve heard of &lt;a&gt;Amazon Web Services&lt;/a&gt;, &lt;a&gt;Google Cloud&lt;/a&gt;, or &lt;a&gt;Microsoft Azure&lt;/a&gt;, you have an idea of what a CSP is. Many CSPs have free trials and free tiers, but they often end up with unexpected charges. Keep this in mind if you go this route!&lt;/p&gt;&lt;blockquote&gt;&lt;span&gt;&lt;div&gt;Oracle Cloud Free Tier&lt;/div&gt;&lt;/span&gt;&lt;p&gt;Oracle Cloud has a generous Free Tier for customers to try out, but I cannot recommend it despite the fact I use it myself. Oracle has a long history of shutting down free tier customer’s machines&lt;a&gt;&lt;sup&gt;[1]&lt;/sup&gt;&lt;/a&gt;, deleting entire accounts&lt;a&gt;&lt;sup&gt;[2]&lt;/sup&gt;&lt;/a&gt;, and preventing sign ups in the first place if they happen to decide they don’t like your email, location, credit card, etc.&lt;a&gt;&lt;sup&gt;[3]&lt;/sup&gt;&lt;/a&gt; Unless you’re willing to deal with these headaches, &lt;em&gt;avoid&lt;/em&gt; Oracle Cloud.&lt;/p&gt;&lt;/blockquote&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Conclusion&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;To some people, a homelab is a daunting idea. They may have heard stories about the amount of time, or effort, or cost some people put into their own homelabs, or maybe they just don’t know where to start. My goal in writing this post is of two parts - first, to write about an interest of mine. Secondly, however, I also hope to convince you - the reader - that a homelab isn’t this overwhelming concept. As with many things, a homelab is what you make out of it. You can put in as much or as little effort as you want. Maybe you want to host one or two services for yourself, or maybe you want to create an entire miniature network. Maybe you want to learn about Microsoft Active Directory, or maybe you want to participate in a community like &lt;a&gt;DN42&lt;/a&gt;, participating in a peer-to-peer BGP routed network!&lt;/p&gt;&lt;p&gt;All this is to say, don’t concern yourself with making a “perfect” or “correct” homelab. Anyone who has their own homelab will tell you that it can never be perfect. Something will always break, something can always be added, something can always be tweaked. In my own opinion, a homelab is not a static entity, it &lt;em&gt;evolves&lt;/em&gt; with you.&lt;/p&gt;&lt;blockquote&gt;&lt;span&gt;&lt;div&gt;Authors Note&lt;/div&gt;&lt;/span&gt;&lt;p&gt;I always try to write my blog posts semi-professionally, but always ending with a “Conclusion” feels almost too professional… I aim to write for a wider audience, often as an outlet for whatever I feel like writing about. If you have anything I may find interesting, or comments about this (or any!) post, don’t hesitate to reach out on &lt;a&gt;Bluesky&lt;/a&gt; or via &lt;a&gt;email&lt;/a&gt;!&lt;/p&gt;&lt;/blockquote&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;References&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;a&gt;&lt;sup&gt;[1]&lt;/sup&gt; r/oraclecloud on Reddit - How possible Oracle shut down my always free resources instance?&lt;/a&gt;&lt;br /&gt;
&lt;a&gt;&lt;sup&gt;[2]&lt;/sup&gt; r/oraclecloud on Reddit - Just like everybody says, Oracle Free Tier suddenly deletes your account&lt;/a&gt;&lt;br /&gt;
&lt;a&gt;&lt;sup&gt;[3]&lt;/sup&gt; r/oraclecloud on Reddit - Can’t sign up for free tier&lt;/a&gt;&lt;/p&gt;&lt;/section&gt;</content:encoded><dc:creator>Lumi</dc:creator><category>Homelab</category></item><item><title>Commit Overflow 2024 Log - A Purdue Hackers Adventure</title><link>https://shad.moe/posts/2025/03/06/commit-overflow-2024/</link><guid isPermaLink="true">https://shad.moe/posts/2025/03/06/commit-overflow-2024/</guid><description>Purdue Hackers Commit Overflow 2024</description><pubDate>Thu, 06 Mar 2025 00:00:00 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;Welcome to my Commit Overflow 2024 Log!&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;Commit Overflow is a &lt;a&gt;Purdue Hackers&lt;/a&gt; event that is held yearly over the Winter Recess at Purdue University.&lt;/p&gt;&lt;p&gt;This year, Commit Overflow ran from December 18&lt;sup&gt;th&lt;/sup&gt; to January 12&lt;sup&gt;th&lt;/sup&gt;, with a total of 43 participants. Every participant starts Commit Overflow by creating a thread in the forum channel (this years being &lt;code&gt;#🟩commit-overflow-2024&lt;/code&gt;). Then, the goal is to “commit” something every day over winter break! Commit is in quotation marks here, as a commit doesn’t have to be code. As long as it’s furthering a creative project, it’s a commit!&lt;/p&gt;&lt;p&gt;The event is held to encourage making things over the long break. Not only are you encouraged to make progress over time, but you can follow what others are doing as well simply by following their respective threads! In addition, two unique &lt;a&gt;Badges&lt;/a&gt; - one for commiting 10 or more days total (further engraved with your highest streak if it’s over 10), and another for anyone who managed to commit daily throughout the entire event, ending with a streak of 26 - were given out to participants meeting their requirements.&lt;/p&gt;&lt;p&gt;The format of this post will be a daily update log of my work, similar to what is being submitted to my Commit Overflow thread. Much of this is backfilled from my notes and work shown in my Commit Overflow thread. I consider myself a badge collector (I have every badge since Hack Night 5.0, and I don’t intend to miss one any time soon), so the promise of badges was tempting. At the same time, I was already looking for an excuse to work on something over break, so this was the perfect excuse.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://konpeki.solutions/xrpc/com.atproto.sync.getBlob?did=did%3Aplc%3Akrbzbucjaj76xjob6ju47ilo&amp;amp;cid=bafkreia5lzeihpwpokpaxvjkngyrsohinbee6kqpwrha7xxgp4i3qymdyi&quot; alt=&quot;Commit Overflow Badges&quot; title=&quot;Commit Overflow Badges&quot; /&gt;&lt;/p&gt;&lt;section&gt;&lt;h3&gt;Note to readers&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Beyond this point, this post will take on a much more relaxed tone. While everything is written with the intent of being in a post, it is also still a journal of sorts. The writing here won’t necessarily meet the same standard as my other writings do.&lt;/p&gt;&lt;p&gt;Each day will have the commit proof I submitted for Commit Overflow. Where applicable, this will either be a URL to my Forgejo instance (Previously Gitea, see &lt;a&gt;Day 21&lt;/a&gt;) or a screenshot.&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;December 18&lt;sup&gt;th&lt;/sup&gt;&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;While looking for inspiration to start Commit Overflow, I was going to take a look at my website. However, I was interrupted by a little icon on my GitHub homepage. Turns out, GitHub Copilot Free was announced a mere six hours before I began working.&lt;/p&gt;&lt;p&gt;This annoyed me, as I don’t like Copilot much, so my project for the day became the creation of a Firefox Add-on that blocks certain Copilot related requests on &lt;code&gt;https://github.com&lt;/code&gt; and &lt;code&gt;https://github.githubassets.com&lt;/code&gt;, as well as removed some elements from the DOM related to Copilot.&lt;/p&gt;&lt;p&gt;See: &lt;a&gt;Github-Copilot-Blocker&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://konpeki.solutions/xrpc/com.atproto.sync.getBlob?did=did%3Aplc%3Akrbzbucjaj76xjob6ju47ilo&amp;amp;cid=bafkreig5my352xfzuk6mej243qnizeqa3lzmj5g7zs3sq7lmax4gloxcfi&quot; alt=&quot;Copilot Blocker Before Screenshot&quot; title=&quot;Copilot Blocker Before Screenshot&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://konpeki.solutions/xrpc/com.atproto.sync.getBlob?did=did%3Aplc%3Akrbzbucjaj76xjob6ju47ilo&amp;amp;cid=bafkreig6fbixmaotrewds5kgn3mcc2kpxeqs5pjjzckuhzjtqwiwmooiku&quot; alt=&quot;Copilot Blocker After Screenshot&quot; title=&quot;Copilot Blocker After Screenshot&quot; /&gt;&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;December 19&lt;sup&gt;th&lt;/sup&gt;&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h4&gt;Commit 1&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;Picking up from the previous day, Github Copilot Blocker received Chromium browser support. This was basically plug-and-play as the code is quite simple to begin with. All that needed to be done was packaging a .crx and updating the Readme.&lt;/p&gt;&lt;p&gt;See: &lt;a&gt;Commit Comparison&lt;/a&gt;&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;Commit 2&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;My personal website &lt;a&gt;shad.moe&lt;/a&gt; has been in disrepair for awhile now, to the point of the entire site being a 404 for much of it’s existance.&lt;/p&gt;&lt;p&gt;Today marks the fourth revival attempt in “&lt;a&gt;Website But Again The Sequel To The Trilogy&lt;/a&gt;”. Today’s commit is the creation of a base layout in Astro with Shad/CN. A sidebar with filler information and a site theme was setup and repository was initialized. Vercel was used to stand the site up on my domain.&lt;/p&gt;&lt;p&gt;See: &lt;a&gt;Commit&lt;/a&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;span&gt;&lt;div&gt;Editors Note&lt;/div&gt;&lt;/span&gt;&lt;p&gt;This commit refers to my website at &lt;a&gt;shad.moe&lt;/a&gt;. All work that was done on this was thrown out at the start of February and the repository has since been deleted. The commit URLs will reference an archive on GitHub rather than my Forgejo instance.&lt;/p&gt;&lt;/blockquote&gt;&lt;hr /&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;December 20&lt;sup&gt;th&lt;/sup&gt;&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Since I didn’t know what the site would actually look like yesterday, I looked for some inspiration. Then, I spent some time refreshing my CSS knowledge by messing around with flexboxes. I used that to setup a further frame for how I wanted the site work to progress, and I fixed some issues with the Shad/CN sidebar.&lt;/p&gt;&lt;p&gt;See: &lt;a&gt;Commit&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;December 21&lt;sup&gt;st&lt;/sup&gt;&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;I spent some time today to replace my Gitea instance at &lt;a&gt;&lt;code&gt;git.konpeki.solutions&lt;/code&gt;&lt;/a&gt; with &lt;a&gt;Forgejo&lt;/a&gt; after hearing about it in the Purdue Hackers Discord server for some time. Forgejo is a Hard Fork of Gitea, but Forgejo maintains compatibility with Gitea. That means I could simply replace the Gitea binary with a Forgejo binary and call it a day!&lt;/p&gt;&lt;blockquote&gt;&lt;span&gt;&lt;div&gt;Editors Note&lt;/div&gt;&lt;/span&gt;&lt;p&gt;As of Forgejo v10.0 / Gitea v1.22, a transparent migration from Gitea to Forgejo may no longer be possible. See “&lt;a&gt;Gitea 1.22 is the last version to allow a transparent upgrade to Forgejo&lt;/a&gt;” on Forgejo’s website.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;I didn’t do that. I had some issues related to my configuration with Gitea in the past, so I decided it would be a better use of my time to create a brand new instance then clone each repository and push them to the new instance.&lt;/p&gt;&lt;p&gt;This worked pretty well. I created a new LXC container on one of my Proxmox instances and installed Forgejo. I configured it locally, connected authentik, and that was done. All I had to do after that was install Tailscale and update the proxy_pass in my Nginx configuration to point to the new container.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://konpeki.solutions/xrpc/com.atproto.sync.getBlob?did=did%3Aplc%3Akrbzbucjaj76xjob6ju47ilo&amp;amp;cid=bafkreicl5cgezq5c3oah7jpgexpxt2yqnthvtp7vimqb67rkpztueldwze&quot; alt=&quot;Forgejo Interface Screenshot&quot; title=&quot;Forgejo Interface Screenshot&quot; /&gt;&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;December 22&lt;sup&gt;nd&lt;/sup&gt;&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Ah, &lt;a&gt;Nextcloud&lt;/a&gt;. It’s great software, but I manage to have so many issues with it. My Nextcloud instance had been broken for weeks, so I opted to reinstall it.&lt;/p&gt;&lt;p&gt;Step 1: &lt;code&gt;rm -rf /&lt;/code&gt;. Yes, I actually did this. I was annoyed and wanted to so something about it so I took it out on the soon-to-be defunct container and ran the command that must not be ran. The container was Alpine flavored, so I didn’t need &lt;code&gt;--no-preserve-root&lt;/code&gt; - it just worked.&lt;/p&gt;&lt;p&gt;Step 2: Actually installing a new Nextcloud instance wasn’t that bad. I spun up a new LXC container after deleting the previous, installed Docker, and used the &lt;a&gt;Nextcloud AIO&lt;/a&gt; installer. I also had to update the Nginx proxy_pass directive.&lt;/p&gt;&lt;p&gt;See: &lt;a&gt;Commit - Nginx Configuration Update&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://konpeki.solutions/xrpc/com.atproto.sync.getBlob?did=did%3Aplc%3Akrbzbucjaj76xjob6ju47ilo&amp;amp;cid=bafkreibu3mkhpnxoq2njqqqe5sz5hou5e6fr3lpkems4k4emfzl6ics64e&quot; alt=&quot;Nextcloud Interface Screenshot&quot; title=&quot;Nextcloud Interface Screenshot&quot; /&gt;&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;December 23&lt;sup&gt;rd&lt;/sup&gt;&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;After hearing some off-hand complaints and thinking about how easy it would be to automate at least a chunk of the Commit Overflow threads for organizers checking commits on various days, I decided to actually do something about it.&lt;/p&gt;&lt;p&gt;Introducing “&lt;a&gt;Commit Overflow Test Bot&lt;/a&gt;”! Better name pending. This Discord bot can be activated by running &lt;code&gt;/commit-count&lt;/code&gt; in a Commit Overflow thread, and it will automatically check for at least one of the following each day:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Git Commit URLs (Via Regex)&lt;/li&gt;
&lt;li&gt;Attachments (Pictures, Audio, etc.)&lt;/li&gt;
&lt;li&gt;”🟩” Reactions&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;This last check allows Organizers to mark a text-only message as a commit. The bot then outputs each day with a commit (alongside the verification method from above) and each missed day. Below that is a readout of the total amount of commits and the threads longest streak.&lt;/p&gt;&lt;p&gt;See: &lt;a&gt;Commit&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;December 24&lt;sup&gt;th&lt;/sup&gt;&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Smaller commit today, as I was celebrating the holidays with family. I made a commit out of updating authentik, fixing configuration errors in Nextcloud, and reinstalling my private Komga instance.&lt;/p&gt;&lt;p&gt;I then rebooted the server due to mounting errors, hoping to clear them, and accidently knocked the server offline.&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;December 25&lt;sup&gt;th&lt;/sup&gt;&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Small commit again due to holidays. Fixed the broken Proxmox server. Then, reconfigured Proxmox Backup Server to allow my backups to be accessible with PBS offline.&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;December 26&lt;sup&gt;th&lt;/sup&gt;&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;See: &lt;a&gt;Grow With Google&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;December 27&lt;sup&gt;th&lt;/sup&gt;&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;I spent part of today reinstalling Windows on my desktop computer after a year of being in a semi-broken state, then spent another part debugging and fixing a WinGet package for one of two remote desktop tools I use, &lt;a&gt;NoMachine&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;See: &lt;a&gt;Pull Request&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;December 28&lt;sup&gt;th&lt;/sup&gt;&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;See: &lt;a&gt;Grow With Google&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;December 29&lt;sup&gt;th&lt;/sup&gt;&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h4&gt;Commit 1&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;Renamed the Commit Overflow bot to Commit Overflow Helper, updated the containers timezone to be correct (Needed to be ETC - 6 to match 6am being the day change), then fixed Pull Requests to be a valid type of Git link.&lt;/p&gt;&lt;p&gt;See: &lt;a&gt;Commit&lt;/a&gt;&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;Commit 2&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;Then, I fixed a bug I noticed yesterday in &lt;a&gt;winget-create&lt;/a&gt; that was the result of schema changes overtime. It was making multiple manifests crash the tool.&lt;/p&gt;&lt;p&gt;See: &lt;a&gt;Pull Request&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;December 30&lt;sup&gt;th&lt;/sup&gt;&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A bug with dates in the Commit Overflow Helper Discord bot was found a few days ago, and I finally got around to fixing it here. There were nine total commits, but the end result was a two line change.&lt;/p&gt;&lt;p&gt;I also created an icon for the bot, supposedly representing a bucket of commits.&lt;/p&gt;&lt;p&gt;See: &lt;a&gt;Commit&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://konpeki.solutions/xrpc/com.atproto.sync.getBlob?did=did%3Aplc%3Akrbzbucjaj76xjob6ju47ilo&amp;amp;cid=bafkreigmhfkqh4mgjxlroowmq2bkyvloc4yqfmf3d7dd2ds3k3dc5mi67q&quot; alt=&quot;Icon for the Commit Overflow Helper Discord Bot&quot; title=&quot;Icon for the Commit Overflow Helper Discord Bot&quot; /&gt;&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;December 31&lt;sup&gt;st&lt;/sup&gt;&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h4&gt;Commit 1&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;Further progress was made in completing the Grow with Google Cybersecurity Certificate coursework. Module 5 of 8, “Assets, Threats, and Vulnerabilities”, was completed.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;Commit 2&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;Once again had to update the timezone for the container the Commit Overflow Helper Discord bot was hosted on. This time it was switched to GMT-11.&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;January 1&lt;sup&gt;st&lt;/sup&gt;&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;This is an… “interesting” one. The commit for today day ended up being a worldbuilding adventure in another Discord server with some of my friends.&lt;/p&gt;&lt;p&gt;It started with one person in the server, &lt;a&gt;AxoBlu&lt;/a&gt;, changing their server nickname to “Obsidian Night” as a joke. This devolved into lore being created for the “character”, as well as many others creating their own personas and lore, with my own name being changed to “Princess Pawsalot”. It was mainly meant to be a purposly terrible joke, but it was taken and ran with.&lt;/p&gt;&lt;p&gt;In the end, we had come up with multiple different countries, kingdoms and even a pirate fleet, all encompased on a continent we titled “JOPFI” (The initials of our characters). This was multiple hours of goofing around, and the end result was really fun to look back at.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://konpeki.solutions/xrpc/com.atproto.sync.getBlob?did=did%3Aplc%3Akrbzbucjaj76xjob6ju47ilo&amp;amp;cid=bafkreigdrrbhnz3hmznfetvcmx7ss7lr4ewip3cignnxo6qy4si35txz5e&quot; alt=&quot;Service List for my ATProto Account&quot; title=&quot;Screenshot of the preview for the JOPFI Documentation&quot; /&gt;&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;January 2&lt;sup&gt;nd&lt;/sup&gt;&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;See: &lt;a&gt;Grow With Google&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;January 3&lt;sup&gt;rd&lt;/sup&gt;&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;See: &lt;a&gt;Grow With Google&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;January 4&lt;sup&gt;th&lt;/sup&gt;&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h4&gt;Commit 1&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;Small life commit, went with family to try Axe Throwing for the first time!&lt;/p&gt;&lt;blockquote&gt;&lt;span&gt;&lt;div&gt;Editors Note&lt;/div&gt;&lt;/span&gt;&lt;p&gt;Images not shared for privacy reasons.&lt;/p&gt;&lt;/blockquote&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;Commit 2&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;See: &lt;a&gt;Grow With Google&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;January 5&lt;sup&gt;th&lt;/sup&gt;&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Today is mostly minor things bundled into one commit. SyncThing was broken, so I re-setup the connection between my Laptop and Desktop, and synced my Documents folder between them. I then worked on some local homelab documentation, and worked in a group call to update old permissions on the &lt;a&gt;Purdue Hackers GitHub Organization&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;January 6&lt;sup&gt;th&lt;/sup&gt;&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Minor commit for today, I spent the day preparing to move back in to my residence hall on Purdue’s campus. Once moved in, I spent a few hours shuffling around Proxmox LXC containers to bring that part of my Homelab back online.&lt;/p&gt;&lt;blockquote&gt;&lt;span&gt;&lt;div&gt;Editors Note&lt;/div&gt;&lt;/span&gt;&lt;p&gt;Some Clarification - University Residences at Purdue has a policy of unplugging everything in your room over break. As a result, critical services were transfered from the two local Poweredge servers to the remote Optiplex server, and the Poweredges were taken offline until my return.&lt;/p&gt;&lt;/blockquote&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;January 7&lt;sup&gt;th&lt;/sup&gt;&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h4&gt;Commit 1&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;I did an audit of my Homelab network, identifying each endpoint and the network pathing between the public web and an endpoint, as well as the pathing for machines inside the network.&lt;/p&gt;&lt;blockquote&gt;&lt;span&gt;&lt;div&gt;Editors Note&lt;/div&gt;&lt;/span&gt;&lt;p&gt;The network graph was the proof of work for this commit, but I have opted not to attach it because it was pretty bad, exposed a fair amount of information about the internal networking of my Homelab, and would not embed well here.&lt;/p&gt;&lt;/blockquote&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;Commit 2&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;Once again a minor change was made in Commit Overflow Helper. I did a formatting pass with Prettier, and the code was updated to not include the current day as a missed day.&lt;/p&gt;&lt;p&gt;See: &lt;a&gt;Commit&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;January 8&lt;sup&gt;th&lt;/sup&gt;&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h4&gt;Commit 1&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;Worked on a small joke website dubbed &lt;a&gt;“The Pit”&lt;/a&gt;, a list of companies and people who have in one way or another annoyed me or a friend. The website takes the list and plays a looping animation of them falling into a pit. The list was changed to work in a JSX, and a button was added to view a full table of occupants.&lt;/p&gt;&lt;p&gt;See: &lt;a&gt;Commit&lt;/a&gt;&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;Commit 2&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;Bluesky and the AT Protocol have been on my mind &lt;a&gt;quite a bit recently&lt;/a&gt;. I quite like the AT Protocol, and I wanted to do something with it (and my PDS server) other than just have my Bluesky account. While researching, I discovered that one of the data fields returned when &lt;a&gt;looking up a user&lt;/a&gt;, the &lt;code&gt;service&lt;/code&gt; field, is fairly arbitrary. When an AppView needs to know where to find a service, it searches based on the service key. Since this is something a service queries versus a list a service has to parse through, you can realistically append any data you want harmlessly.&lt;/p&gt;&lt;p&gt;So I created the “service” &lt;a&gt;&lt;code&gt;#have_a_fox_image&lt;/code&gt;&lt;/a&gt;. You can guess &lt;a&gt;what it does&lt;/a&gt;. TL;DR, it’s a static URL pointing to a public domain image I grabbed and uploaded to my Nextcloud instance.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://konpeki.solutions/xrpc/com.atproto.sync.getBlob?did=did%3Aplc%3Akrbzbucjaj76xjob6ju47ilo&amp;amp;cid=bafkreihxvloz7s563ob5zx3j5o2sbmo3acmy53ytj7wigklm5aiowuq4ju&quot; alt=&quot;Service List for my ATProto Account&quot; title=&quot;Service List for my ATProto Account&quot; /&gt;&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;January 9&lt;sup&gt;th&lt;/sup&gt;&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;I came up with an idea yesterday. I was looking at things I could do with &lt;a&gt;ATProto&lt;/a&gt;, and stumbled upon &lt;a&gt;haileyok/blug&lt;/a&gt;, a blog built using the AT Protocol as it’s backend (essentially). I decided to see how difficult this would be, it’s possible all of this gets thrown out.&lt;/p&gt;&lt;p&gt;As of today, posts are already loaded when linked to directly, sans some markdown.&lt;/p&gt;&lt;p&gt;See: &lt;a&gt;Commit&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;January 10&lt;sup&gt;th&lt;/sup&gt;&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h4&gt;Commit 1&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;Made a variety of fixes and changes to my blog. These were mostly changing how data was passed around to better use the ATProto system I setup rather than Frontmatter.&lt;/p&gt;&lt;p&gt;See: &lt;a&gt;Commit&lt;/a&gt;&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;Commit 2&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;Fixed a date parsing bug in Commit Overflow Helper&lt;/p&gt;&lt;p&gt;See: &lt;a&gt;Commit&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;January 11&lt;sup&gt;th&lt;/sup&gt;&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;ATProtocol post fetching is finally mostly implemented, and Vercel now doesn’t have build errors. The page is now previewable live!&lt;/p&gt;&lt;p&gt;See: &lt;a&gt;Commit&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;January 12&lt;sup&gt;th&lt;/sup&gt;&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Final day, and with it comes a variety of fixes and changes from the todo list I made. As of now, the blog is in a state I’m happy with, and I may push it in a few days once I write the corresponding blog post!&lt;/p&gt;&lt;blockquote&gt;&lt;span&gt;&lt;div&gt;Editors Note&lt;/div&gt;&lt;/span&gt;&lt;p&gt;I didn’t intend for pushing this to be a full month, but I ended up cleaning the blog up much more before finally pushing the new version. I talk about this more in &lt;a&gt;Welcome to the Atmosphere!&lt;/a&gt;. You’re reading this post on the new blog!&lt;/p&gt;&lt;p&gt;Also of note, the blog is now hosted locally on my Homelab infrastructure. Vercel (nor any other platform) hosts this blog.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;See: &lt;a&gt;Commit&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Grow With Google&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Over Winter Recess, the Grow With Google Cybersecurity certificate was offered for free to Purdue students. I spent some time on December 26&lt;sup&gt;th&lt;/sup&gt;, 28&lt;sup&gt;th&lt;/sup&gt;, 31&lt;sup&gt;st&lt;/sup&gt; and Jan 2&lt;sup&gt;nd&lt;/sup&gt; completing this certificate.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://konpeki.solutions/xrpc/com.atproto.sync.getBlob?did=did%3Aplc%3Akrbzbucjaj76xjob6ju47ilo&amp;amp;cid=bafkreidvapg4twqie2udnrdjnvrsye4htdfrvab5evaebuzaypw6sfbwsq&quot; alt=&quot;Screenshot showing Grow With Google program completion&quot; title=&quot;Screenshot showing Grow With Google program completion&quot; /&gt;&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded><dc:creator>Lumi</dc:creator><category>Purdue Hackers</category><category>Journal</category></item><item><title>Welcome to the ATmosphere!</title><link>https://shad.moe/posts/2025/02/02/welcome-to-the-atmosphere/</link><guid isPermaLink="true">https://shad.moe/posts/2025/02/02/welcome-to-the-atmosphere/</guid><description>Now blogging in the Clouds</description><pubDate>Sun, 02 Feb 2025 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;&lt;span&gt;&lt;div&gt;Update&lt;/div&gt;&lt;/span&gt;&lt;p&gt;As of March 28&lt;sup&gt;th&lt;/sup&gt;, 2026 this post is outdated. While the technical challenge was interesting and fun to experiment with, tech debt and performance issues resulted in this blog being taken off of ATProto ~14 months after publishing. The ATProto version of the blog is archived and accessible at &lt;a&gt;https://git.konpeki.solutions/TheShadowEevee/atproto-blog&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;In a &lt;a&gt;previous post&lt;/a&gt;, I touched on &lt;a&gt;Bluesky&lt;/a&gt; and the &lt;a&gt;AT Protocol&lt;/a&gt; (or, ATProto for short). Since that post, I’ve looked further into the AT Protocol, and have come to be enticed by the concept. It’s not necessarily a novel system, but it is a system that’s becoming more widely used by the day.&lt;/p&gt;
&lt;blockquote&gt;
&lt;section&gt;&lt;h3&gt;Definition: The AT Protocol&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;“The AT Protocol stands for “Authenticated Transfer Protocol,” and is frequently shortened to “atproto.” The name is in reference to the fact that all user-data is signed by the authoring users, which makes it possible to broadcast the data through many services and prove it’s real without having to speak directly to the originating server.” - &lt;a&gt;atproto.com&lt;/a&gt;&lt;sup&gt;&lt;a&gt;[1]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;&lt;/section&gt;
&lt;/blockquote&gt;
&lt;p&gt;This was a fun project to work on and I’m glad to have everything in a working state! I’ll talk about my thought process behind this and some of the inner workings of the blog and the AT Protocol. At the end, I’ll also include a few caveats; this isn’t a perfect system after all!&lt;/p&gt;
&lt;blockquote&gt;&lt;span&gt;&lt;div&gt;View the Blog Source&lt;/div&gt;&lt;/span&gt;&lt;p&gt;If you would like to host this yourself, or would like to learn how this all works, the source code is available on &lt;a&gt;my Forgejo instance&lt;/a&gt; and &lt;a&gt;Github&lt;/a&gt;!&lt;/p&gt;&lt;/blockquote&gt;
&lt;section&gt;&lt;h3&gt;The What&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Before I get into any details, I should explain the title of this blog post. My personal blog, &lt;a&gt;blog.shad.moe&lt;/a&gt;, is now an ATProto AppView! What this means specifically is that my posts are no longer markdown files stored in a git repository. Instead, each post is an entry on my Personal Data Server (or PDS)!&lt;/p&gt;&lt;p&gt;It’s similar to a post on BlueSky. If you go to &lt;a&gt;my Bluesky profile&lt;/a&gt; right now, you will see a few posts. Clicking on one directs you to a URL resembling &lt;code&gt;https://bsky.app/profile/{Handle or DID}/post/{rKey}&lt;/code&gt;. The first blank is one of two identifiers for a Bluesky account; either a “handle”, a domain name like username, or a &lt;a&gt;unique DID (Decentralized Identifier)&lt;/a&gt;&lt;sup&gt;&lt;a&gt;[2]&lt;/a&gt;&lt;/sup&gt; for an account. If a handle changes, the DID stays the same unless a new account is made.&lt;/p&gt;&lt;p&gt;The second part is the key. Or quite literally, the Record Key (rKey for short). The rKey looks like a random string of characters at first, but it’s often actually something more. The most common rKey is the &lt;a&gt;TID format&lt;/a&gt;, but there are other formats that may be used. The important part is that the rKey is a unique key that when passed to a PDS server alongside a “&lt;a&gt;repository&lt;/a&gt;” AKA your handle or DID, will return a specific piece of content. In the case of Bluesky, that would look like a post.&lt;/p&gt;&lt;p&gt;Circling back to my blog, a familiar format is used! As the blog is intended for one person, the profile is hardcoded in for ease. With that being the case, the url scheme this blog follows drops the profile part to become &lt;a&gt;&lt;code&gt;https://shad.moe/posts/3lgbnigwdzk2r/&lt;/code&gt;&lt;/a&gt;! The rKey &lt;code&gt;3lgbnigwdzk2r&lt;/code&gt; is the key to this specific post on my PDS, and thus is all the information needed to render the post.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h3&gt;The Why&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;While I already was in control of my blog posts and the platform they were on, moving to the Atmosphere opens up federation of the posts, potentially increasing their view. In addition, I’ve been looking for a project I could use the AT Protocol on for some time now, cause I simply think it’s cool.&lt;/p&gt;&lt;p&gt;The AT Protocol is, as described by the developers, a social protocol. Despite being a relatively new system, many awesome projects all ready exist, testing the limits of the protocol! A short list of my favorites include &lt;a&gt;BlueSky&lt;/a&gt;, &lt;a&gt;WhiteWind&lt;/a&gt;, &lt;a&gt;GrayHaze&lt;/a&gt;, and &lt;a&gt;ATFile&lt;/a&gt;.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h3&gt;The How&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;The way I made this work is rather interesting, and pulled from a lot of existing community knowledge to cobble together. Perhaps the greatest help and inspiration was &lt;a&gt;WhiteWind&lt;/a&gt;. Whitewind is a pre-existing ATProto based blogging service, and their lexicon is what I’m using for my posts. Specifically, each blog post has a type of &lt;code&gt;com.whtwnd.blog.entry&lt;/code&gt;. Since these posts are inherently public, they can be viewed from &lt;a&gt;my blog&lt;/a&gt;, &lt;a&gt;WhiteWind’s website&lt;/a&gt;, or a PDS viewer such as &lt;a&gt;PDSls&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;section&gt;&lt;h4&gt;Similar projects that helped&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;I referred to &lt;a&gt;haileyok/blug&lt;/a&gt; and &lt;a&gt;rwietter/atproto-blog&lt;/a&gt; both multiple times during work on the transition. &lt;a&gt;haileyok&lt;/a&gt;’s blug project specifically pushed me to implement Redis caching for posts on the backend. If you attempt to do something similar to this, &lt;em&gt;please&lt;/em&gt; use a caching system of some sort. One downside of ATProto is that you generally have to make a web request for each view; a proper cache will immensly cut down traffic to your PDS and speed up loading times on your blog.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;The Blog’s Design Itself&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;If you’ve visited my blog before, you’ll notice it looks the same as it did before! I put a strong effort into retrofitting ATProto into &lt;a&gt;saicaca/fuwari&lt;/a&gt;, the &lt;a&gt;Astro&lt;/a&gt;-based blog view I used up till now. I really like the design of Fuwari, and didn’t want to sacrifice it for this.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;Loss of Metadata&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;One of the biggest challenges of retro-fitting was the loss of metadata. Fuwari uses &lt;a&gt;Frontmatter&lt;/a&gt; to store important data about a post, like it’s title, description, category, and tags (among a few other things). However, the &lt;a&gt;WhiteWind Lexicon for &lt;code&gt;com.whtwnd.blog.entry&lt;/code&gt;&lt;/a&gt; defines different data! The only matching field is the title field. To work around this, I did something I still consider a bit cursed. Markdown allows the use of HTML; I took advantage of this to use an HTML comment to act as a Frontmatter field of sorts.&lt;/p&gt;&lt;p&gt;It’s a strange solution, but it allows passing values Fuwari would have previously seen as what I’ve deemed “Extended Data”. When the blog view pulls a post, it will be parsed for a string like the following:
&lt;code&gt;&amp;lt;!-- ### ADDITIONAL DATA FIELD ### { &apos;description&apos;: &apos;Now blogging in the Clouds&apos;, &apos;published&apos;: &apos;2024-01-21&apos;, &apos;tags&apos;: [&apos;ATProto&apos;, &apos;Meta&apos;], &apos;category&apos;: &apos;ATProto&apos; } ### solutions.konpeki.post.extendedData ### ---&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;This string can be broken down into a header, a footer, and a JSON object. This JSON object is extracted when the header and footer are found, and serialized to be passed along as metadata. Notably, no AppView should display this data in the post! Both Fuwari and WhiteWind’s AppViews parse markdown, hiding the comment from the reader.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;Verceln’t&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;Something else of note is that Vercel no longer hosts this blog. I spent way too long on trying to get post fetching to work, but Vercel refused to build the project to have dynamic paths or serverless functions no matter what I tried. This gave me the excuse I needed to move from Vercel to my own infrastructure! This blog is currently hosted on an Optiplex that serves as the outer edge of my Homelab network, but will eventually be moved onto the Dell Poweredge R640 servers I mentioned in a &lt;a&gt;previous blog post&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h3&gt;The Caveats&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;As I mentioned before, the Atmosphere is not all sunshine and rainbows. There are a few notable issues with this system that are important to understand before undertaking this adventure.&lt;/p&gt;&lt;section&gt;&lt;h4&gt;Network Requests&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;Every time someone loads the blog, a web request is made. And often, more than one. This is something that is unavoidable; the entire point is that the blog AppView needs to call out to my (or the authors) PDS. This can result in longer load times as the web requests are made, and can be delayed if something is wrong with the network.&lt;/p&gt;&lt;p&gt;However, this is acceptable in many cases. In the case of network issues, it’s highly likely that your blog would be inaccessible in the first place since users can’t connect to it. In the case of sending many requests that can potentially take some time to resolve, this is relieved through the use of caching. Specifically, a KV database, Redis, is used in the backend to cache posts locally.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;Different AppViews&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;The first caveat is the potential for a post to differ slightly depending on where it’s viewed. As mentioned before, each post can be viewed directly on my blog or on Whitewind. It may &lt;em&gt;also&lt;/em&gt; be viewed by any other AppView that chooses to implement the Whitewind lexicon. While these posts are written in Markdown, which should be universal, there can be differences in how Markdown is rendered. A great example is Admonition cards: on my blog, they create a nice block to grab a readers attention! On other AppViews, these aren’t rendered and instead appear as text.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://konpeki.solutions/xrpc/com.atproto.sync.getBlob?did=did%3Aplc%3Akrbzbucjaj76xjob6ju47ilo&amp;amp;cid=bafkreicppjfmiuxgmrnsaiapyf5vcqo36meanoqlpcklehajw4jcf2lfgy&quot; alt=&quot;Image: An Admonition card as it would appear on my blog&quot; /&gt;&lt;/p&gt;&lt;section&gt;&lt;h6&gt;Image: An Admonition card as it would appear on my blog&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h6&gt;&lt;p&gt;&lt;img src=&quot;https://konpeki.solutions/xrpc/com.atproto.sync.getBlob?did=did%3Aplc%3Akrbzbucjaj76xjob6ju47ilo&amp;amp;cid=bafkreigphdkmqkdvqd643ksvbdxblv37be2syqbjgzyveerrvyzhxy53ky&quot; alt=&quot;Image: An Admonition card as it would appear on WhiteWind&quot; /&gt;&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h6&gt;Image: An Admonition card as it would appear on WhiteWind&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h6&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;Posts are Inherently Public&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;Finally, it’s important to note that posts are always public (unless you’ve configured your PDS to require authentication to view certain things. YMMV.), so if you’re drafting a post that you don’t want to be viewable, you should hold off on posting it to your PDS.&lt;/p&gt;&lt;p&gt;This is something I am fine with. My flow is to use the WhiteWind editor (eventually an editor on my own blog) in “Anyone with the link” privacy mode. This hides the post on Whitewind unless the reader has the exact rKey, and my blog is configured to not show these posts but to still allow direct URL access &lt;em&gt;without&lt;/em&gt; caching. This enables quick reviews everytime I save the post, and allows me to share the unlisted link with friends for review. Once a post is ready, simply changing the privacy mode to public “publishes” the post, making it appear on the blog’s front page and enabling my RSS.xml to pick up on the post and distribute it.&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h3&gt;(Potential) Future Plans:&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;Finish the editor at &lt;a&gt;blog.shad.moe/editor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Add comments and reactions sections&lt;/li&gt;
&lt;li&gt;Change URL Schema to allow multiple users? &lt;code&gt;b.s.moe/author/{acc}/post/{rKey}&lt;/code&gt;?
&lt;ul&gt;
&lt;li&gt;Currently possible but probably won’t be implemented for my blog
&lt;ul&gt;
&lt;li&gt;Changing URL schema could/would break SEO again&lt;/li&gt;
&lt;li&gt;Maybe have Single / Multi-User toggle in code?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;
&lt;section&gt;&lt;h3&gt;Conclusion&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;I don’t have much of a conclusion for this post. This is a project I started near the end of Commit Overflow (Post soon on this event!). I began on January 8th, 2024 and finished January 21st, 2025, which is less time than I thought until I typed it out. This project was honestly quite motivating, and I’m glad that I went through with it instead of scrapping it like I almost did on two seperate occasions. All in all, I’m excited for this new system! If anyone wants to try this for themselves, you can find the repository on &lt;a&gt;my Forgejo instance&lt;/a&gt; and &lt;a&gt;Github&lt;/a&gt; as mentioned above. If you have any questions, feel free to shoot me a message on BlueSky or through &lt;a&gt;email&lt;/a&gt;!&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h3&gt;References&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;a&gt;&lt;sup&gt;[1]&lt;/sup&gt; Quick start guide to building applications on AT Protocol - atproto.com&lt;/a&gt;&lt;br /&gt;
&lt;a&gt;&lt;sup&gt;[2]&lt;/sup&gt; ATProto DIDs - atproto.com&lt;/a&gt;&lt;/p&gt;&lt;/section&gt;</content:encoded><dc:creator>Lumi</dc:creator><category>ATProto</category><category>Meta</category></item><item><title>Notes for Self-Hosting an ATProto PDS</title><link>https://shad.moe/posts/2024/12/12/notes-for-self-hosting-an-atproto-pds/</link><guid isPermaLink="true">https://shad.moe/posts/2024/12/12/notes-for-self-hosting-an-atproto-pds/</guid><description>Self-Hosting ATProto PDS Notes</description><pubDate>Thu, 12 Dec 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Recently I’ve started using &lt;a&gt;Bluesky&lt;/a&gt;, a decentralized social media platform built on the &lt;a&gt;AT Protocol&lt;/a&gt;. When I was first looking into Bluesky, something that attracted my interest was the ability to host your own Personal Data Server, or PDS. To quote the AT Protocol Glossary:&lt;/p&gt;
&lt;blockquote&gt;
&lt;h3&gt;PDS (Personal Data Server)&lt;/h3&gt;
&lt;p&gt;A PDS, or Personal Data Server, is a server that hosts a user. A PDS will always store the user’s data repo and signing keys. It may also assign the user a handle and a DID. Many PDSes will host multiple users.&lt;/p&gt;
&lt;p&gt;A PDS communicates with AppViews to run applications. A PDS doesn’t typically run any applications itself, though it will have general account management interfaces such as the OAuth login screen. PDSes actively sync their data repos with Relays.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;All of that boils down to “This is where your user account and associated information is stored”. I personally host a private PDS at &lt;a&gt;konpeki.solutions&lt;/a&gt; - my Bluesky handle is &lt;code&gt;@theshadoweevee.konpeki.solutions&lt;/code&gt;. This is entirely local! Any time someone access my profile or a post, a request is sent to the domain &lt;code&gt;https://theshadoweevee.konpeki.solutions&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A lot more goes into this that I haven’t touched on (like the &lt;a&gt;Firehose&lt;/a&gt;) but I’ll stop here for now. It’s time to complain a bit.&lt;/p&gt;
&lt;p&gt;The AT Protocol has, in my opinion, great documentation on how the protocol works. It’s worth browsing through the documentation if you’re curious. Where it falls flat, however, is documenting any non-default configuration of the PDS.&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;Configuring Email&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Configuring an Outgoing SMTP Server is necessary for Email Verification and Password Resets (both nice to haves). There &lt;em&gt;is&lt;/em&gt; documentation for this now, but at the time I set up my PDS server, it was restricted to a &lt;a&gt;Pull Request&lt;/a&gt; and even then, the current documentation doesn’t really clarify what an SMTP URL is very well.&lt;/p&gt;&lt;p&gt;The trick to this is configuring an environment variable. My environment variable file is located at &lt;code&gt;/pds/pds.env&lt;/code&gt;, yours will likely be in a similar spot. You’ll append the following to the end of your environment variables:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;PDS_EMAIL_SMTP_URL=smtps://&amp;lt;Username&amp;gt;:&amp;lt;API Key / Password&amp;gt;@smtp.example.com:465/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;PDS_EMAIL_FROM_ADDRESS=&amp;lt;Username&amp;gt;@example.com&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;div&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;In some configurations for the url, such as mine, the username must be accompanied by the domain. In this case, replace the username with &lt;code&gt;&amp;lt;Username&amp;gt;%40example.com&lt;/code&gt; where example.com is your domain name.&lt;/p&gt;&lt;p&gt;After configuring, restart your PDS server. If you used the &lt;code&gt;install.sh&lt;/code&gt; / Official PDS installation method, you can run &lt;code&gt;systemctl restart pds&lt;/code&gt;.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Configuring Reverse Proxies&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Here’s a much more annoying task: Configuring a reverse proxy. The PDS Server runs it’s own Caddy instance, but there are many reasons you may want a reverse proxy in front of that. My main reason was that the PDS server should be accessible over &lt;a&gt;Tailscale&lt;/a&gt; to my Nginx server, which then serves to the world.&lt;/p&gt;&lt;p&gt;On top of this, I wanted to use my username + domain root and not a subdomain (No &lt;code&gt;theshadoweevee.pds.konpeki.solutions&lt;/code&gt;!). However, this raises the issue of &lt;code&gt;konpeki.solutions&lt;/code&gt; being the home of my PDS while I still wanted to host content on the domain. I did some… &lt;em&gt;funky&lt;/em&gt; workarounds to get this working.&lt;/p&gt;&lt;p&gt;Each of the following assumes I’ve already created an account on my PDS with the username &lt;code&gt;theshadoweevee.konpeki.solutions&lt;/code&gt; using &lt;code&gt;pdsadmin account create&lt;/code&gt; and that I know it’s DID, &lt;code&gt;did:plc:krbzbucjaj76xjob6ju47ilo&lt;/code&gt;, from &lt;code&gt;pdsadmin account list&lt;/code&gt;.&lt;/p&gt;&lt;section&gt;&lt;h3&gt;Setup A/AAAA records for your handle&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Your handle &lt;em&gt;must&lt;/em&gt; be a domain you have control over in some fashion. For all intents, your handle is also a domain. A DNS A/AAAA record needs to be configured for &lt;code&gt;theshadoweevee.@&lt;/code&gt; which will point to a server you control (where your reverse proxy is hosted, in this case). Ensure the server being pointed to has a valid SSL certificate for your handle, or a wildcard for the domain.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;Verifying your handle via DNS&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;If you have access to your DNS records, this is the easiest method to verify a handle and requires no setup on the PDS Server or reverse proxy. Head to your domain’s DNS records, and create a new TXT record with the following, substituting the Username and DID:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Name: _atproto.theshadoweevee&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Content: &quot;did=did:plc:krbzbucjaj76xjob6ju47ilo&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;div&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Note the quotation marks around the content, this is a requirement in TXT records. Wait for your DNS records to propagate, then check your handle with the &lt;a&gt;Bluesky Debug Page&lt;/a&gt;.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;Verifying your handle via HTTP&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;If DNS isn’t an option, or if you want to have both verification methods setup, then you can also verify your handle using a file. This file should be at &lt;code&gt;https://theshadoweevee.konpeki.solutions/.well-known/atproto-did&lt;/code&gt;, where your handle is the domain name. Inside &lt;code&gt;atproto-did&lt;/code&gt;, the contents should simply be your DID without quotes, such as &lt;code&gt;did:plc:krbzbucjaj76xjob6ju47ilo&lt;/code&gt;.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;Proxying actual content: Handle&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;At this point, you aren’t actually proxying any data from your PDS. To proxy a handle domain, you only need to proxy one path (that I’m currently aware of). Proxying &lt;code&gt;/xrpc&lt;/code&gt; to your PDS server will pass through any HTTP API requests made to your handle domain. It is &lt;em&gt;important&lt;/em&gt; that you correctly proxy websocket requests.&lt;/p&gt;&lt;p&gt;A nice to have you can implement on a handle-only domain is redirecting to your Bluesky profile. You can do this by redirecting or rewriting &lt;code&gt;/&lt;/code&gt; to &lt;code&gt;https://bsky.app/profile/did:plc:krbzbucjaj76xjob6ju47ilo&lt;/code&gt;, replacing the DID with your own username or DID (both work, however the DID survives handle changes in the future).&lt;/p&gt;&lt;p&gt;Example Nginx Configuration can be seen &lt;a&gt;on my Gitea instance&lt;/a&gt;.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;Proxying actual content: PDS&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Proxying your PDS root domain is more complicated, as there’s more paths to be aware of. As before, ensure you have a valid SSL configuration and websockets are proxied. Then, you’ll need to proxy each of the following to your PDS server:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/xrpc&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/.well-known/oauth-protected-resource&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/.well-known/oauth-authorization-server&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/oauth&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/@atproto&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Proxying these ensures HTTP API requests get through (&lt;code&gt;/xrpc&lt;/code&gt;), as well as a few other user management services such as OAuth. When Discord added Bluesky to their connections list, this was an issue I ran into as I hadn’t proxied the OAuth endpoints. This resulted in Discord returning an HTTP 500 error when trying to link the accounts.&lt;/p&gt;&lt;p&gt;Example Nginx Configuration can be seen &lt;a&gt;on my Gitea instance&lt;/a&gt;.&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Wrap Up&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;The AT Protocol is something I hope to see used more in the future, though currently I take some issue with the problematic self-hosting documentation. With enough googling and some investigative work however, there isn’t an issue that I haven’t deemed unsolvable yet.&lt;/p&gt;&lt;p&gt;I ended up running into my issue with Bluesky/Discord linking, fixing the issue, and writing the majority of this in one sitting at a campus Starbucks, so I feel I have to give some credit to the baristas who made my drink, and to the people on campus who put up with my complaining. Sometimes the most difficult issues become simpler with something to drink and a friend to vent to.&lt;/p&gt;&lt;/section&gt;</content:encoded><dc:creator>Lumi</dc:creator><category>ATProto</category><category>Bluesky</category><category>Homelab</category></item><item><title>Renaming an Active Node in a Proxmox Cluster</title><link>https://shad.moe/posts/2024/12/11/renaming-an-active-node-in-a-proxmox-cluster/</link><guid isPermaLink="true">https://shad.moe/posts/2024/12/11/renaming-an-active-node-in-a-proxmox-cluster/</guid><description>Renaming Proxmox Cluster Nodes (or, How not to run a Cluster)</description><pubDate>Wed, 11 Dec 2024 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;&lt;span&gt;&lt;div&gt;Renaming Instructions&lt;/div&gt;&lt;/span&gt;&lt;p&gt;Are you here for the instructions? &lt;a&gt;Click here to skip ahead!&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;So, there’s a bit of a story here. Back in September of this year, I made an impulsive purchase at the &lt;a&gt;Purdue Surplus Store&lt;/a&gt;. Specifically, I aquired two &lt;a&gt;Dell PowerEdge R640 Rack Servers&lt;/a&gt; for $100 USD each. I won’t go into the specs, but these were a nice upgrade to my Homelab environment from my then current Dell Optiplex 5040 SFF. (Also a Purdue Surplus purchase)&lt;/p&gt;
&lt;p&gt;It took some time to get the servers setup and connect to their iDRAC controllers, but once I found a Micro USB cable and the drivers I needed, I was ready to install an operating system! If it wasn’t clear, I went with Proxmox.&lt;/p&gt;
&lt;p&gt;Each of these machines was loaded up with a fresh install of Proxmox, and following my loose naming scheme of Touhou based hostnames, they were named &lt;code&gt;moriya-pve1&lt;/code&gt; and &lt;code&gt;moriya-pve2&lt;/code&gt;, referencing the &lt;a&gt;Moriya Shrine&lt;/a&gt;. Then, I installed &lt;a&gt;Tailscale&lt;/a&gt; on each machine, and clustered them into the &lt;code&gt;Moriya-Cluster&lt;/code&gt;&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;Early Mistakes&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;If you’ve worked with Proxmox clusters before, some of these mistakes may seem obvious. But when working on my own environment, I like to do things to see what they do, and clean up the mess later. Let the following mistakes be a warning to those who homelab the same way.&lt;/p&gt;&lt;section&gt;&lt;h3&gt;Joining a remote server to the cluster&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Very early on on the first creation of moriya-cluster, I had the bright idea to join my Optiplex to the cluster as well. This was not smart. To quote the &lt;a&gt;Proxmox Documentation&lt;/a&gt;, “[Corosync] needs a reliable network with latencies under 2 milliseconds […] to work properly”. Corosync is the name of the service that handles cluster management in Proxmox.
The main problem here, is that the Optiplex was over 75 miles north. The latency was… more than two milliseconds. The cluster threw a fit. Since I had no containers yet, this was the cause of the first full Proxmox reinstallation.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;Not planning names ahead of time&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;My homelab hostnames follow a pattern. The Optiplex is &lt;a&gt;&lt;code&gt;Momiji-Server&lt;/code&gt;&lt;/a&gt;, for example. So, the decision to use &lt;code&gt;Moriya-PVE1&lt;/code&gt; and &lt;code&gt;Moriya-PVE2&lt;/code&gt; was a poorly made one. Sure, the names worked, but they were certainly not ideal. For this reason, I opted to rename them on November 14th. This is “the incident” that I’m writing about now.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;Making changes with limited time&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;I opted to rename my nodes, a major change, with only an hour to work with. At the time, I was sitting in a public space, waiting for a &lt;a&gt;friend of mine&lt;/a&gt; to return with a U-Haul carrying a Robot Arm and Controller from a freight company. This is a whole other story, but in the realm of this post, what matters is I only had about 45 minutes to do repairs. This meant the whole cluster was down for many hours until I was free again.&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;What actually happened&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Renaming a node in Proxmox is not an easy task. There is a &lt;a&gt;wiki page&lt;/a&gt; on how, but it lays out the following requirements.&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;The node must be empty (No containers, VMs)&lt;/li&gt;
&lt;li&gt;The node must not be clustered
&lt;ul&gt;
&lt;li&gt;This rule can be ignored, but there is an extra step if you do&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;I read this, and in my infinite wisdom thought “what’s the worst that could happen?”. So I renamed my nodes.
Nodes that were clustered and had multiple LXC containers. That, and I renamed them both simultaneously.&lt;/p&gt;&lt;p&gt;I updated the &lt;code&gt;/etc/hosts&lt;/code&gt; and &lt;code&gt;/etc/hostname&lt;/code&gt; files (ignoring the optional files), and restarted the servers. Notably, I didn’t update the &lt;code&gt;corosync.conf&lt;/code&gt; file, but that was only a minor issue compared to what actually went wrong.&lt;/p&gt;&lt;p&gt;After &lt;em&gt;fifteen minutes&lt;/em&gt;, the servers connected back to my Tailscale network, and I opened the Proxmox webpages. Read-only. Forgetting to edit the &lt;code&gt;corosync.conf&lt;/code&gt; caused a quorum failure, which I was lucky able to fix using the terminal access provided by my iDRAC controllers (accessible over Tailscale).&lt;/p&gt;&lt;p&gt;Another reboot, and the core of the problem became evident. There were now &lt;em&gt;four&lt;/em&gt; nodes listed in the Server View. The newly renamed servers &lt;a&gt;&lt;code&gt;kanako-server&lt;/code&gt;&lt;/a&gt; and &lt;a&gt;&lt;code&gt;suwako-server&lt;/code&gt;&lt;/a&gt; were there, but they listed no LXC containers. There should have been 7 containers, so this was concerning. Also displayed was &lt;code&gt;Moriya-PVE1&lt;/code&gt; and &lt;code&gt;Moriya-PVE2&lt;/code&gt;, the old names. The LXC containers were found under those nodes, and all were offline as the non-existant nodes couldn’t be found. Uh oh.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Investigating&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;I promptly began searching for solutions. I had already spent a lot of time troubleshooting, and the group of people that had gone with the U-Haul were already on their way back.&lt;/p&gt;&lt;p&gt;My research was conclusive… I should reinstall my server and restore my containers from backups. In a seperate incident that same day, I had made my backups inaccessible as I switched to a new storage system. So I didn’t &lt;em&gt;have&lt;/em&gt; backups. Oops.&lt;/p&gt;&lt;p&gt;One Proxmox forum user, shodan, &lt;a&gt;then suggested to restore the backup of &lt;code&gt;/var/lib/pve-cluster/config.db&lt;/code&gt;&lt;/a&gt;. This made me curious, and turned out to be the key to restoration.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Instructions: Changing a Hostname on an Active Node&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;

Click here to view the instructions!
&lt;blockquote&gt;&lt;span&gt;&lt;div&gt;Disclaimer&lt;/div&gt;&lt;/span&gt;&lt;p&gt;The following commands can cause irreversible damage and data loss!&lt;/p&gt;&lt;p&gt;It is advised to understand these steps yourself before running them. These commands have only been tested in a sandbox, and vary slightly from my recovery steps.&lt;/p&gt;&lt;p&gt;I am not liable for any issues that may arise from these commands.&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;span&gt;&lt;div&gt;Version Notice&lt;/div&gt;&lt;/span&gt;&lt;p&gt;These steps were ran on Proxmox VE 8.2.7, and may or may not work on other versions.&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;span&gt;&lt;div&gt;Restarting Nodes&lt;/div&gt;&lt;/span&gt;&lt;p&gt;Do not restart any nodes until reaching the restart step! Restarting nodes early can cause a number of issues and junk folders. It is recommended to use the reboot command.&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;span&gt;&lt;div&gt;Recovering Nodes&lt;/div&gt;&lt;/span&gt;&lt;p&gt;If you need to recover a node that you already renamed, try changing the hostname back. If that doesn’t work, you will need to manually change &lt;code&gt;inode&lt;/code&gt; and &lt;code&gt;parent&lt;/code&gt; ids in the database for each folder and relevent file.&lt;/p&gt;&lt;/blockquote&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Choose new hostnames for one or more nodes&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Connect locally to the Proxmox server&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Do not use the web interface, as the next step will temporarily stop the services it needs to run&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Change the hostname in &lt;code&gt;/etc/pve/corosync.conf&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Stop all running Proxmox services &lt;sup&gt;&lt;a&gt;[1]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;killall&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-9&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;corosync&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;systemctl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;restart&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pve-cluster&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;systemctl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;restart&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pvedaemon&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;systemctl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;restart&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pveproxy&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;systemctl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;restart&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pvestatsd&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;div&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Change the hostname in &lt;code&gt;/etc/hosts&lt;/code&gt; and &lt;code&gt;/etc/hostname&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;On the renamed node, run:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;sqlite3&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/var/lib/pve-cluster/config.db&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;div&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Making note of the entries, run:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FROM&lt;/span&gt;&lt;span&gt; tree &lt;/span&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type=&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;div&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Alternatively use an online viewer such as &lt;a&gt;this one&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The most important fields are &lt;code&gt;inode&lt;/code&gt; (First Column) and &lt;code&gt;name&lt;/code&gt; (Seventh Column)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Identify the entry for &lt;em&gt;each&lt;/em&gt; node you are renaming&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For each node being renamed, run:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;UPDATE&lt;/span&gt;&lt;span&gt; tree &lt;/span&gt;&lt;span&gt;SET&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;NEW_NAME&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; inode&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;div&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Change &lt;code&gt;NEW_NAME&lt;/code&gt; to the new hostname, and &lt;code&gt;0&lt;/code&gt; to the inode number for the entry of the node&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If the node is in a cluster, repeat steps 2-9 on &lt;em&gt;each node in the cluster&lt;/em&gt;, even if it’s not being renamed&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;This is important, as in a cluster environment corosync can sync the old database to the server, deleting the changes&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Restart each modified node&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ideally, have an alternative access plan for the servers; if there is an error, the web interface may not come back up over the network&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Edit &lt;code&gt;/etc/pve/nodes/NEW_NAME/ssh_known_hosts&lt;/code&gt; and correct the hostname on all nodes - Replace &lt;code&gt;NEW_NAME&lt;/code&gt; with the new hostname&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Conclusion&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;The clear moral here is to listen to warnings, especially when given by multiple sources. I was clearly warned by the documentation and multiple forum posts, however I opted to do it anyway, as I consider my homelab a breakable environment. Proxmox is certainly good at what it does, but it also cares a lot about it’s state. Messing with configurations Proxmox expects not to change was as bad of an idea as I was warned, but luckily I was determined to make it work.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;References&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;a&gt;&lt;sup&gt;[1]&lt;/sup&gt; spirit - Stopping all proxmox services on a node&lt;/a&gt;&lt;/p&gt;&lt;/section&gt;</content:encoded><dc:creator>Lumi</dc:creator><category>Proxmox</category><category>Homelab</category></item><item><title>A writeup of KC7&apos;s New2Cyber 2023 event</title><link>https://shad.moe/posts/2023/03/16/kc7-new2cyber-2023-writeup/</link><guid isPermaLink="true">https://shad.moe/posts/2023/03/16/kc7-new2cyber-2023-writeup/</guid><description>KC7 New2Cyber 2023 Writeup</description><pubDate>Thu, 16 Mar 2023 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;&lt;span&gt;&lt;div&gt;Update 11/20/24&lt;/div&gt;&lt;/span&gt;&lt;p&gt;When reviewing this post, I noticed some changes to the KC7 platform. All links have been updated, but will retain the original name as written. For reference, the old New2Cyber challenge is now called “Envolve Labs - With a twist!”.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The KC7 New2Cyber Game was a Cybersecurity challenge hosted on the KC7 platform alongside the SANS New2Cyber Summit on March 14th. It was a “Jeopardy” style challenge, meaning it was broken into sections of questions you could answer at your leisure. This writeup will consider the main part of the event as sections 2 and 3, given they hold the majority of the KQL work and all of the incident discovery.&lt;/p&gt;
&lt;p&gt;For more information on this event, you can visit the KC7 page for it at &lt;a&gt;SANS New2Cyber - KC7 (kc7cyber.com)&lt;/a&gt;. This page includes the dataset used, a link to the event leaderboard/submission page, and their training guide. The training guide is a very well written explanation of Module 1 meant to guide you through learning the basics of KQL while completing most of Section 1.&lt;/p&gt;
&lt;p&gt;Going forward, the bulk of this event will be referred to as “the security incident” or just “incident”. This writeup will both go over the event’s main portion giving a narrative of the incident and guiding through many of the steps taken throughout.&lt;/p&gt;
&lt;blockquote&gt;&lt;span&gt;&lt;div&gt;Warning: Spoilers / Answers Ahead&lt;/div&gt;&lt;/span&gt;&lt;p&gt;&lt;em&gt;This event has finished, but the organizers at KC7 have said it will stay live indefinitely. If you haven’t tried the event yet, give it a go yourself first! This is a good learning tool to go in blind for at first; you can always come back here for guidance along the way.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;Sections 2 and 3 of this event are discussed to the point of basically giving away solutions below. Sections 4 and 5 are not included and can be mostly found with some googling.&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;section&gt;&lt;h2&gt;The Scenario&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;em&gt;View the KC7 New2Cyber training guide to read the full scenario! &lt;a&gt;SANS New2Cyber - KC7 (kc7cyber.com)&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;Paraphrased scenario from the training guide:&lt;/em&gt;&lt;br /&gt;
Today is your first day as a Junior Security Operations Center (SOC) Analyst at Envolve Labs Corporation. Envolve Labs is a (fictional!) 2012 med-tech startup with a goal of designing flexible vaccine tech. Envolve Tech has 4 key partners (listed in the training guide) that will be seen throughout this event.&lt;/p&gt;&lt;p&gt;Envolve Tech has hired you as they realize they need to invest more in Cybersecurity efforts. Envolve Labs collects log data about the activities its employees perform on the corporate network. These audit logs will be the subject of your investigations as you determine whether the company is being targeted by malicious actors.&lt;br /&gt;
&lt;sub&gt;All credit for the above scenario goes to KC7!&lt;/sub&gt;&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Activity Summary&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;After receiving the tip on the potential phishing domain, a larger investigation was started. One person had clicked on the malicious domain and investigating this further led to discovery of potentially 2 different potential malicious actors.&lt;/p&gt;&lt;p&gt;Hereby referred to as Actor A and Actor B, these two actors are for now suspected to be different based on their methods and time of intrusion. Actor A used a wide scale phishing campaign to steal credentials and deliver malicious files meant to allow exfiltration of data. Actor B appears to be a different, more advanced actor using more targeted phishing using compromised emails, and more persistent tools on infected systems.&lt;/p&gt;&lt;p&gt;Actor A could potentially be a group of malicious actors, as many domains and IP addresses showed similar methods and similar timing. There were 3 total groups of interconnected IPs and domains that fit the exhibited behavior, and the similarity in their operations are what linked the 3 groups as one larger actor.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Actor Methods of Operation&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h3&gt;Actor A&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Actor A used a simple phishing scheme in order to get a handful of employees to share login information or download malicious files. The extent of this campaign appears to have aimed to gain login credentials, which were used to download files from the email system.&lt;/p&gt;&lt;p&gt;Actor A operated primarily on January 4th, 8th, and 9th.&lt;/p&gt;




































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Recon&lt;/td&gt;&lt;td&gt;Collected Email Addresses of multiple employees, did research on important company figures (i.e., the CEO)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Weaponization&lt;/td&gt;&lt;td&gt;Unknown&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Delivery&lt;/td&gt;&lt;td&gt;Shared malicious files and URLs through email via phishing campaign&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Exploitation&lt;/td&gt;&lt;td&gt;Unknown&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Installation&lt;/td&gt;&lt;td&gt;Unknown&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Command and Control&lt;/td&gt;&lt;td&gt;N/A&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Actions&lt;/td&gt;&lt;td&gt;Used access to user accounts to download critical files over open internet&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;Actor B&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Actor B appears to be a more advanced actor than Actor A. Actor B used similar methods of initial infection, sharing malicious files via phishing emails. However, there were less emails suggesting a more targeted approach. On top of this, the infected files were better hidden using file names such as “EnvolveLabs_Research_Tool.7z”, and “updater.dll”. These files were designed to be stealthy and remain undetected.&lt;/p&gt;&lt;p&gt;The updater.dll file that extracted itself from the .7z file allowed a direct, persistent connection to the malicious actor. Once the updater.dll was installed, it appears to drop the file “infector.exe” and operate it via a Windows Scheduled Task. Together, these two files opened up paths for the actor to control the computers via Ligolo and PuTTY. In total, only 7 employees were infected, again suggesting a more targeted attack.&lt;/p&gt;&lt;p&gt;Actor B operated primarily on January 5th.&lt;/p&gt;




































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Recon&lt;/td&gt;&lt;td&gt;Likely to have researched various positions within the company&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Weaponization&lt;/td&gt;&lt;td&gt;Use of common and specialized file names are meant to avoid detection and maximize attack ability&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Delivery&lt;/td&gt;&lt;td&gt;Shared malicious files through email via phishing campaign&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Exploitation&lt;/td&gt;&lt;td&gt;Extraction of a malicious 7z file resulted in infection&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Installation&lt;/td&gt;&lt;td&gt;updater.dll was used to create a persistent infector.exe&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Command and Control&lt;/td&gt;&lt;td&gt;Actor opened paths for remote control via Ligolo and PuTTY&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Actions&lt;/td&gt;&lt;td&gt;Unknown&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Impact&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;The impact level of this event is hard to determine. However, this appears to be a Mid-High severity incident (on an arbitrary scale) given what impact we &lt;em&gt;do&lt;/em&gt; know of.&lt;/p&gt;&lt;p&gt;Actor A has gained access to a large number of employee accounts, compromising security in more ways than they may know how to take advantage of yet. They have already compromised email accounts in order to download seemingly sensitive files (based purely on file name) and may be able to use the compromised accounts to send emails spreading their phishing campaign further.&lt;/p&gt;&lt;p&gt;Actor B on the other hand has direct, persistent access to multiple systems potentially owned by higher ups, putting unknown amounts of information at risk. Actor B’s method of infection makes it hard if not impossible to tell what files may have been exfiltrated already using the logs provided here.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Discovery Process and KQL Examples&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;The discovery process for this incident will follow the order of the questions asked in the KC7 answer submission page. Not all questions will be explored as there were 39 questions total in Sections 2 and 3, with some being repeats or not closely related enough to others to make a quick narrative from.&lt;/p&gt;&lt;p&gt;The KQL queries used during the discovery process will be shared to show what is happening and make it easy to follow along. This should ideally be understandable if you haven’t looked at the KC7 challenge but will be a good guide if you are actively working on it or have completed it.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Disclaimer: All URLs, IP addresses, Names, Emails, and other data is generated for this event by the KC7 team, and any mention is NOT an endorsement or claim of malicious intent for or against listed entities.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;&lt;section&gt;&lt;h3&gt;Section 2 - Introducing the Hackers&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Section 2 has a general focus on identifying the suspicious domain and learning initial information about our first actor.&lt;/p&gt;&lt;section&gt;&lt;h4&gt;Questions 2.1 - 2.4&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;The incident discovery begins with a suspicious domain, &lt;code&gt;immune.tech&lt;/code&gt;. In the training guide, it is stated that the domain was found by a security researcher and publicly shared as a suspicious domain found while looking into phishing activity.&lt;/p&gt;&lt;p&gt;Since this domain was potentially related in phishing activity, we should check to see if any of our employees have received emails with a link to this domain. We can search with the following KQL query.&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Email&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt; link has &lt;/span&gt;&lt;span&gt;&quot;immune.tech&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;div&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;This query shows all the emails received with a link to &lt;code&gt;immune.tech&lt;/code&gt;, which will be used to answer the questions. This query checks the Email table, searches all entries in the link column for the text &lt;code&gt;immune.tech&lt;/code&gt;, and returns any positive results.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;Questions 2.5 - 2.8&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;Knowing that multiple employees received an email with the suspicious domain, the next step is to identify if a user clicked on the link at any point. We can search the OutboundBrowsing table to identify any potential clicks.&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;OutboundBrowsing&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;url&lt;/span&gt;&lt;span&gt; has &lt;/span&gt;&lt;span&gt;&quot;immune.tech&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;-- One result was returned with a src_ip of 192.168.0.234, we can search the Employee table to see who this was&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Employees&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt; ip_addr has &lt;/span&gt;&lt;span&gt;&quot;192.168.0.234&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;div&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;It appears that “Marissa Stephens” did in fact click the link in one of the emails. It is likely this was a phishing email, and they may have given away their login to the actor behind the domain. We should check logins to their account.&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;-- Visible in the Employee table, usernames are first two letters of their first name, and their full last name, all lowercase.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;AuthenticationEvents&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt; username has &lt;/span&gt;&lt;span&gt;&quot;mastephens&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;div&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;As we worried, it appears that there was a login to Marissa’s account 9 hours later from IP address &lt;code&gt;88.150.11.111&lt;/code&gt;. Now, this could be Marissa logging in, we can’t be certain yet. Let’s check if this IP has been used to log in before.&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;AuthenticationEvents&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt; src_ip has &lt;/span&gt;&lt;span&gt;&quot;88.150.11.111&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;div&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;It appears this issue runs far deeper than anticipated. We can use a new KQL term, count, to get the number of returned results. Running the query again with &lt;code&gt;| count&lt;/code&gt; added on a new line shows a total of 21 logins from this IP address, all on separate accounts. Not only is this very likely to be a malicious actor, but it also seems they have access to more than expected.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;Tips for Questions 2.9 - 2.13&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;2.9&lt;/strong&gt; - &lt;code&gt;.gzip&lt;/code&gt; is a file extension, try searching for a URL ending in this extension.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2.11&lt;/strong&gt; - Searching for this person as a recipient will turn up multiple results, look for a suspicious sender or misspellings!&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2.13&lt;/strong&gt; - Use the &lt;code&gt;distinct&lt;/code&gt; query on the link field to isolate unique instances.&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;Section 3 Examples - Hackers sending malware docs&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Section 3 begins to focus on another type of threat. The bad actors have sent multiple malicious documents over email, from a variety of emails, some being compromised emails from partner companies. Our second actor makes an appearance for a short time here.&lt;/p&gt;&lt;section&gt;&lt;h4&gt;Questions 3.1 - 3.5&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;The continuation of the discovery process starts with a new suspicious domain, &lt;code&gt;notice.io&lt;/code&gt;. This domain was called out for having a specific malicious file, “Critical_Security_Path.docx”.&lt;/p&gt;&lt;p&gt;Following up on this domain, we need to see if anyone was targeted.&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;-- How many emails with this domain were recieved&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Email&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt; link contains &lt;/span&gt;&lt;span&gt;&quot;notice.io&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;| count&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;-- Who sent the emails, and what was the subject line&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Email&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt; link contains &lt;/span&gt;&lt;span&gt;&quot;notice.io&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;div&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;It appears this email has found it’s way into some employee’s inboxes. Using the same methods as section 2, it’s possible to find out that one of the employees clicked the link, and what time the hosted file was downloaded at.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;Questions 3.7, 3.12, 3.14&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;Between questions 3.5 and 3.16, the questions are similar to previous questions. These 3 however are new.&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;/* 3.7 - What other domains are hosted on the same IPs as notice.io? */&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;-- Using PassiveDns, we can determine the IP address for notice.io&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;PassiveDns&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt; domain contains &lt;/span&gt;&lt;span&gt;&quot;notice.io&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;-- Then, we can test the returned IP addresses and see what other domains they might resolve to&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;PassiveDns&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt; ip contains &lt;/span&gt;&lt;span&gt;&quot;21.101.248.158&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;/* 3.12 - How many IPs does scanverify.com resolve to? */&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;-- Similar to part one of 3.7, see what IPs scanverify resolves to and count them&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;PassiveDns&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt; domain contains &lt;/span&gt;&lt;span&gt;&quot;scanverify.com&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;| count&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;/* 3.14 - What is the name of the file hosted on scanverify.com? */&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;-- One way to do this is to check OutboundBrowsing for someone who has already navigated to the file, and copy the file name from the end of the link&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;OutboundBrowsing&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;url&lt;/span&gt;&lt;span&gt; contains &lt;/span&gt;&lt;span&gt;&quot;scanverify.com&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;div&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;Questions 3.16 - 3.26&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;Starting here, we go deeper into what this actor is doing for recon and how they are infecting machines once their email is clicked on.&lt;/p&gt;&lt;p&gt;First, we can look into what recon the actor may be doing. They may have searched for some systems, and what we’re looking for is guided by Q 3.16 and 3.17.&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;-- The full query is &quot;helpdesk ticket system&quot;, but using just helpdesk works better since we can&apos;t use spaces&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;InboundBrowsing&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;url&lt;/span&gt;&lt;span&gt; contains &lt;/span&gt;&lt;span&gt;&quot;helpdesk&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;-- The next query asks what policy they&apos;re looking for. The following returns multiple results, some with the search we&apos;re looking for of &quot;Password Expiration Policy&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;InboundBrowsing&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;url&lt;/span&gt;&lt;span&gt; contains &lt;/span&gt;&lt;span&gt;&quot;policy&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;div&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Now we want to look into what the “EnvolveLabs_Research_Tool.7z” file does. We’re told a .dll was dropped on the machine after downloading the 7z file, and we have to find the name of it.&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;-- Find IP Addresses that downloaded the file&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;OutboundBrowsing&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;url&lt;/span&gt;&lt;span&gt; contains &lt;/span&gt;&lt;span&gt;&quot;EnvolveLabs_Research_Tool.7z&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;-- Find the employee to get their computer hostname&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Employees&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt; ip_addr contains &lt;/span&gt;&lt;span&gt;&quot;192.168.1.129&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;-- Search for file creations using the computer hostname&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;FileCreationEvents&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt; hostname contains &lt;/span&gt;&lt;span&gt;&quot;5RT9-MACHINE&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;div&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;This reveals a .dll file being created about 40 seconds after the .7z file is downloaded, named updater.dll.
We should now check to see if any commands have been run on this computer.&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;ProcessEvents&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt; hostname contains &lt;/span&gt;&lt;span&gt;&quot;5RT9-MACHINE&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;div&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;This reveals the updater.dll file running 2 commands, “whoami” and a command using Windows Task Scheduler.&lt;br /&gt;
&lt;sub&gt;Note: This command (starting with schtasks) is the answer to Q 3.20. Use this information to complete Q 3.21; Q 3.20 does not exist due to an error.&lt;/sub&gt;&lt;/p&gt;&lt;p&gt;We can take the task scheduler command and check to see if other systems may have run it.&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;-- The full command was omitted here. It is recommended to search using the entire command in most scenarios.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;ProcessEvents&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt; process_commandline contains &lt;/span&gt;&lt;span&gt;&quot;schtasks&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;div&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Now that we know more machines are infected, we need to check for this file on other machines.&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;FileCreationEvents&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;filename&lt;/span&gt;&lt;span&gt; contains &lt;/span&gt;&lt;span&gt;&quot;updater.dll&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;div&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Using the sha256 hashes provided, we can see 4 unique files with the same name, on 4 different machines. We can search the hash of one of them on &lt;a&gt;VirusTotal&lt;/a&gt; to see how many antivirus programs detect it as malicious.
We can search for known tunneling tools to see if they have been used on these infected machines. First we can check for the use of ligolo, as well as see if any other tools are being used.&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;-- We&apos;re asked to look at a specific employee first&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Employees&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt; contains &lt;/span&gt;&lt;span&gt;&quot;Michelle Beal&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;-- See what IP address is being tunnled to&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;ProcessEvents&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt; hostname contains &lt;/span&gt;&lt;span&gt;&quot;UY2V-LAPTOP&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt; process_name contains &lt;/span&gt;&lt;span&gt;&quot;ligolo&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;-- Check for other systems and programs contacting the found IP address&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;ProcessEvents&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt; process_commandline contains &lt;/span&gt;&lt;span&gt;&quot;158.129.161.214&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;-- Check to see how many ligolo tunnels are in use across the network&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;ProcessEvents&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt; process_name contains &lt;/span&gt;&lt;span&gt;&quot;ligolo&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;| count&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;div&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Finishing this, that’s the extent of the discovery asked for. If you’d like, feel free to look around more and play with the data, and make your own assumptions on what is going on behind the scenes! Who knows, I may be wrong entirely with my assumptions on the number of actors and their roles. It’s up to how you interpret the data in front of you.&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Conclusion&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;If you are interested in participating in future KC7 events, I recommend checking out their website at &lt;a&gt;https://kc7cyber.com/&lt;/a&gt;. I had a great time talking with others in the slack channel created for this event, and I can safely say that Question 5.20 has scarred many of us for life with how many attempts were poured into it. (The answer was a &lt;code&gt;hack and leak&lt;/code&gt; attack by the way! You can read some interesting news stories if you google it.) Question 20 was the last question I had left and was the only question that resulted in me finishing everything second instead of first. Congrats to oclku9rt for pulling that out from under me for the first 100% completion!&lt;/p&gt;&lt;p&gt;All in all, this was a great event, and I had a great time working through some of the problems presented. The KC7 platform seems to be a great learning tool with this hands-on exploration into a realistic environment simulating an actual security event you may encounter as a Security Analyst. As a participant who hasn’t done something like this before, KC7 did a great job making this engaging while still keeping everything at a good skill level for those participating in the SANS New2Cyber Summit, from anyone brand new to the Cyber scene as well as long time members of the field.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Related Resources&lt;a&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a&gt;SANS Summits&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a&gt;KC7&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;</content:encoded><dc:creator>Lumi</dc:creator><category>KC7</category><category>Writeup</category><category>CTF</category></item></channel></rss>