<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Aaron Ogle</title><link>https://aaronogle.dev/</link><description>Recent content on Aaron Ogle</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Mon, 23 Mar 2026 00:00:00 +0000</lastBuildDate><item><title>A Decade at Rocket.Chat: Looking Back on 10 Years of Building, Breaking, and Growing</title><link>https://aaronogle.dev/2026/03/23/a-decade-at-rocket.chat-looking-back-on-10-years-of-building-breaking-and-growing/</link><pubDate>Mon, 23 Mar 2026 00:00:00 +0000</pubDate><guid>https://aaronogle.dev/2026/03/23/a-decade-at-rocket.chat-looking-back-on-10-years-of-building-breaking-and-growing/</guid><description>
&lt;p&gt;It&amp;rsquo;s hard to believe I&amp;rsquo;m writing this. After nearly 10 years at Rocket.Chat, I&amp;rsquo;m saying goodbye. What started as just a guy on the internet submitting pull requests to fix image stretching&amp;hellip; Turned into a decade of building across multiple cloud platforms, traveling the world, meeting/working with great people, making friends, leading teams, and learning &lt;strong&gt;A Lot&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;I want to look back on this journey. Not just the technical milestones, but how I grew as a technical professional, the team evolution, the org changes, the migrations that aged me, and the people who made it all worth it.&lt;/p&gt;
&lt;h2 id="the-very-beginning-a-community-contributor-fixing-bugs-2015"&gt;The Very Beginning: A Community Contributor Fixing Bugs (2015)&lt;/h2&gt;
&lt;p&gt;I discovered Rocket.Chat in 2015. &lt;strong&gt;Bradley Hilton&lt;/strong&gt; and I had actually been building our own chat application. It started because he needed a staff chat for his Minecraft server and was tired of using Slack (and definitely didn&amp;rsquo;t want to pay for it). We couldn&amp;rsquo;t find anything that fit, so we started building our own. When I found Rocket.Chat it was exactly what we were trying to build. So instead of reinventing the wheel, I started using it, hit rough edges, and started fixing them. My first pull request on August 21st, 2015 was titled &amp;ldquo;Fix image stretching.&amp;rdquo; The second one came the same day: &amp;ldquo;Fix search not coming up.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Within a week I was submitting PRs for pin/unpin functionality, configuring the site name via environment variables, adding &lt;code&gt;/invite&lt;/code&gt; and &lt;code&gt;/leave&lt;/code&gt; slash commands, and improving hubot-rocketchat. 33 PRs across 4 repos before the year was out. I wasn&amp;rsquo;t an employee. I wasn&amp;rsquo;t getting paid. I was just a guy who liked the product enough to make it better.&lt;/p&gt;
&lt;p&gt;In October of 2015, Diego Sampaio built the first easy way to try Rocket.Chat, a proof-of-concept system brought online for &lt;strong&gt;OSCON in Amsterdam&lt;/strong&gt;. You&amp;rsquo;d enter your email and a subdomain like &lt;code&gt;something.rocket.chat&lt;/code&gt; and it would spin up a workspace. Built on Rackspace with Tutum, a single Mongo node, a single worker, and Hipache for load balancing. The address was &lt;code&gt;deploy.rocket.chat&lt;/code&gt;. Simple. Scrappy. It worked.&lt;/p&gt;
&lt;p&gt;The seeds of everything that would come later were planted right there.&lt;/p&gt;
&lt;p&gt;By mid-2016 I was going deeper, I contributed the original &lt;strong&gt;Jitsi video conferencing integration&lt;/strong&gt; in the hotel lobby across from &lt;strong&gt;OSCON in Austin&lt;/strong&gt;. We met Emil Ivov the founder of Jitsi earlier that day in the Atlassian office. Got excited and started building.&lt;/p&gt;
&lt;h2 id="fleetcommand-and-the-cloud-team-2016---2018"&gt;Fleetcommand and the Cloud Team (2016 - 2018)&lt;/h2&gt;
&lt;p&gt;In &lt;strong&gt;September 2016&lt;/strong&gt;, we built the &lt;code&gt;rocketchat-server&lt;/code&gt; snap, one of the very first snaps created. This was a direct result of interactions with Mark Shuttleworth from Canonical. A small but cool moment in our open-source story.&lt;/p&gt;
&lt;p&gt;By &lt;strong&gt;October 2016&lt;/strong&gt;, it was becoming clear that Rocket.Chat was going to receive its first round of funding (which officially came in &lt;strong&gt;November 2016&lt;/strong&gt;). I started building &lt;strong&gt;Fleetcommand&lt;/strong&gt;, the software that would manage trials, handle Stripe billing, and automate provisioning for our hosted customers. The original vision was a portal at &lt;code&gt;my.rocket.chat&lt;/code&gt; for users to manage their workspaces. We explored many options like using Juju by Canonical(after earlier success with snaps), docker swarm, mesos, nomad and several other ideas. But ultimately decided on kubernetes and utilizing its API and specifically the same go packages kubectl leveraged.&lt;/p&gt;
&lt;p&gt;In &lt;strong&gt;January 2017&lt;/strong&gt; we received our Google Cloud credits, and Fleetcommand went live around &lt;strong&gt;March 4th, 2017&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;A fun story during this time: I had traveled to Brazil on February 23rd, 2017 for our first ever company summit. While there, we received an opportunity for a free booth at Google Next in San Francisco only a few days later, March 8th to 10th. So we flew from Brazil to San Francisco. I was gone for 20 days. My wife was not so sure about this new startup I had joined! 😂&lt;/p&gt;
&lt;p&gt;&lt;img src="/images/2017-03-08/google-next-rocketchat.jpeg" alt="The Rocket.Chat team at Google Cloud Next 2017" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;At the booth, we switched the deployment of workspaces from rackspace/tutum to run on Kubernetes on Google Cloud.&lt;/strong&gt; We were literally refining the process and deploying fixes live from the conference floor. We even rushed a proof of concept that automatically linked users to their Google accounts. Once it was finished, we actually then returned to Brazil and had our summit.&lt;/p&gt;
&lt;p&gt;&lt;img src="/images/2017-03-08/google-next-fleetcommand-live.png" alt="Fleetcommand hosting page going live" loading="lazy"&gt;&lt;/p&gt;
&lt;h3 id="the-first-great-migration"&gt;The First Great Migration&lt;/h3&gt;
&lt;p&gt;For a while we supported Google Cloud alongside the original Tutum deployment. But as the Rackspace credits ran out, we needed to migrate everything over. This was our &lt;strong&gt;first zero-downtime migration&lt;/strong&gt; and we developed the pattern we&amp;rsquo;d use for every migration after.&lt;/p&gt;
&lt;p&gt;The strategy: extend the existing &lt;code&gt;use1-db1&lt;/code&gt; MongoDB replica set by standing up additional replicas within Google Cloud. Once the new replicas were healthy, switch the primary over. Spin up all new workspaces in Kubernetes on Google Cloud. Switch the DNS records. Completed &lt;strong&gt;March 26th, 2017&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;At this point I was basically a solo operation as the &amp;ldquo;Cloud Architect.&amp;rdquo; I was writing Fleetcommand, managing infrastructure, handling deployments, writing documentation. 93 PRs across 23 different repositories in 2017 alone. My fingerprint was across the entire ecosystem.&lt;/p&gt;
&lt;h3 id="becoming-a-team"&gt;Becoming a Team&lt;/h3&gt;
&lt;p&gt;Early &lt;strong&gt;2018&lt;/strong&gt; after our summit is when the &amp;ldquo;cloud&amp;rdquo; team was born. Bradley, who had been present since the company was formed, joined the cloud team. He was initially focused on the Apps Engine, but his focus pivoted to needing a way to distribute apps, which led to the creation of the &lt;strong&gt;Marketplace&lt;/strong&gt;. Its first commit landed on &lt;strong&gt;July 14th, 2018&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;In &lt;strong&gt;July 2018&lt;/strong&gt; we also made our first infrastructure-specific hire. The team grew from 2 to 3.&lt;/p&gt;
&lt;p&gt;If you look at my GitHub history from the second half of 2018 there&amp;rsquo;s a clear pattern: take a service, containerize it, add automated builds with Google Cloud Build, deploy it. On &lt;strong&gt;July 31st&lt;/strong&gt; alone I submitted PRs adding a Dockerfile and auto-deploy to the marketplace-api &lt;em&gt;and&lt;/em&gt; adding Prometheus to Fleetcommand. Three days later: &amp;ldquo;Release initial version&amp;rdquo; of cloud-portal. Then statuscentral, our status page which we&amp;rsquo;d built in about 2-3 days in Go inspired by another open-source status page, got Docker and Cloud Build (September 27th). That little project would keep evolving for the next seven years: maintenance windows, a CLI, snapshot ability, incident history, even a Twitter integration so customers could follow along during outages. Then the Push Gateway was rewritten from JavaScript to Go and containerized (November 15th). The JavaScript version had been locking up under load; the process would just stop responding and the only fix was killing the pod. The Go rewrite was night and day. Memory went from around a gigabyte down to megabytes. Go&amp;rsquo;s built-in concurrency handled the high-throughput push notification traffic without breaking a sweat. The OmniChannel Gateway got a multi-stage Docker build. The Federation Hub got simplified and containerized. One by one, the cloud platform took shape.&lt;/p&gt;
&lt;p&gt;By the end of 2018 we had the bones of the cloud platform. I had 142 PRs across 27 repos that year, and the operational burden of managing a growing hosted customer base was growing right alongside it.&lt;/p&gt;
&lt;h2 id="the-great-migrations-2019---2020"&gt;The Great Migrations (2019 - 2020)&lt;/h2&gt;
&lt;h3 id="google-cloud-to-aws-2019"&gt;Google Cloud to AWS (2019)&lt;/h3&gt;
&lt;p&gt;We operated on Google Cloud until those credits also began to diminish. Amazon approached us with AWS credits, so we kicked off our &lt;strong&gt;second major migration&lt;/strong&gt;. This time the approach was a little bit more sophisticated. Like last time, we established a secure tunnel between the two environments so they could talk to each other, and extended MongoDB replica sets from Google Cloud into AWS. This time we introduced ingress records in the new infrastructure that would proxy traffic back to Google Cloud. We shifted DNS to point to the new AWS ingress, then migrated customers in controlled batches, spinning up workspaces in AWS and flipping their specific ingress records one by one.&lt;/p&gt;
&lt;p&gt;I later documented this migration pattern in a blog post: &lt;a href="https://aaronogle.dev/2020/05/01/a-k8s-migration-concept/"&gt;A K8s Migration Concept&lt;/a&gt;. The migration was completed on &lt;strong&gt;March 1st, 2019&lt;/strong&gt;. The most satisfying PR? &amp;ldquo;Remove GCP&amp;rdquo;, 5,279 lines deleted. Goodbye Google Cloud.&lt;/p&gt;
&lt;h3 id="the-bare-metal-leap-ovh-2020"&gt;The Bare Metal Leap: OVH (2020)&lt;/h3&gt;
&lt;p&gt;In 2020, we needed to decrease our operational costs. Oracle offered credits but their infrastructure and consoles were challenging. Our search led us to &lt;strong&gt;OVH&lt;/strong&gt; and bare metal servers.&lt;/p&gt;
&lt;p&gt;This was a whole new world. We had to master deploying Kubernetes on bare metal with Rancher, deal with OVH&amp;rsquo;s unique &amp;ldquo;vracks&amp;rdquo; requiring manual IP assignment, set up bastions for access, and learn that their firewall rules only protected against traffic from &lt;em&gt;outside&lt;/em&gt; OVH, meaning other OVH customers could bypass them entirely. Storage was another challenge. On managed cloud you just request a volume and it appears. On bare metal there&amp;rsquo;s nothing. We found &lt;strong&gt;Longhorn&lt;/strong&gt;, which let us carve out persistent volumes from some nodes we provisioned with big raid disk arrays, giving us the storage layer Kubernetes needed.&lt;/p&gt;
&lt;p&gt;We executed &lt;strong&gt;another zero-downtime migration&lt;/strong&gt;, completing it on &lt;strong&gt;July 3rd, 2020&lt;/strong&gt;. We refined our process further, exposing many ingress switching functionalities as API calls within Fleetcommand.&lt;/p&gt;
&lt;p&gt;OVH also taught us about hardware failures. Nodes just die on bare metal and way more often than we thought. CPU overheating and bootlooping randomly. Water cooling manifold related issues, thermal paste etc. Not things we expected to be having to raise support tickets and deal with. You also learn quickly about capacity planning when there&amp;rsquo;s no auto-scaling button. You learn to have spares ready. You build close relationships with your vendors.&lt;/p&gt;
&lt;p&gt;Throughout all of this, three major migrations, multiple cloud providers, growing customer demands, a small team of 3-4 people kept everything running. 199 PRs in 2020 alone. &amp;ldquo;Begin OVH adventure&amp;rdquo; (16,539 lines), &amp;ldquo;Svc migration to ovh&amp;rdquo; (18,593 lines). Not glamorous work, but the kind of work that keeps a platform alive.&lt;/p&gt;
&lt;h2 id="the-spotify-era-tribes-squads-and-chapters-2021"&gt;The Spotify Era: Tribes, Squads and Chapters (2021)&lt;/h2&gt;
&lt;p&gt;In early &lt;strong&gt;2021&lt;/strong&gt;, the company adopted a Spotify-style organizational model. Tribes, Squads with Product Managers, Engineering Managers, and Tech Leads. Chapters for disciplines like frontend, backend and infrastructure.&lt;/p&gt;
&lt;p&gt;Up until this point I&amp;rsquo;d been doing everything: writing code, managing infrastructure, &lt;em&gt;and&lt;/em&gt; being the engineering manager. Running 1:1s, performance reviews, salary negotiations, hiring. I was listed as the hiring manager for the whole cloud team. It was too much for one person, and something had to give.&lt;/p&gt;
&lt;p&gt;The squad reorg changed that. What had been &amp;ldquo;the cloud team&amp;rdquo; became a cloud tribe with multiple squads. I moved into the &lt;strong&gt;Tech Lead/Architect role across the Cloud tribe&lt;/strong&gt;, specifically the &lt;strong&gt;Cloud Service Squad&lt;/strong&gt; (Fleetcommand, cloud portal, push gateway, and others), the &lt;strong&gt;Marketplace Squad&lt;/strong&gt; and still was involved in the &lt;strong&gt;Infrastructure Squad&lt;/strong&gt; as a major stakeholder/architect as we did have a team member step up as the main lead for that team.&lt;/p&gt;
&lt;p&gt;This was also a period of significant growth. We brought on our first PMs. New engineers joined like Debdut and Daniel, both coming in as interns (and still at Rocket.Chat today). The team was bigger than ever. And crucially, &lt;strong&gt;Gabriel Casals&lt;/strong&gt; came on as an Engineering Manager for the Cloud squads. This was a turning point for me. He was the first non-technical EM I worked closely with, and he showed me what the role should actually look like: handling the people side, the process, the coordination, so I could focus on technical direction. That partnership taught me how a strong EM and a strong tech lead can complement each other instead of stepping on each other&amp;rsquo;s toes. After years of carrying both loads, it was a huge relief to no longer be responsible for the people side of things.&lt;/p&gt;
&lt;h2 id="floating-splitting-and-beginning-of-the-sre-transformation-2022---2023"&gt;Floating, Splitting, and beginning of the SRE Transformation (2022 - 2023)&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;2022&lt;/strong&gt; brought major changes. Our PM for the Cloud tribe left in January. &lt;strong&gt;Julio Bertelli&lt;/strong&gt; joined. The company went through a restructuring that impacted 12 people.&lt;/p&gt;
&lt;p&gt;I found myself increasingly acting as a &lt;strong&gt;floating architect&lt;/strong&gt; across squads rather than being embedded in one. The Cloud Service Squad, the Cloud Hosting efforts, and the infrastructure team all needed technical direction, and I was the thread connecting them. But it was getting harder. The infrastructure team and the service squad had different priorities, and things were falling through the cracks.&lt;/p&gt;
&lt;p&gt;Meanwhile, a new Engineering Manager came in, initially working across QA and security, and eventually taking on the infrastructure team as well. By early 2023 he was EM for both the security team and the infra team. The arrangement meant I could focus on the technical side while he handled the people management.&lt;/p&gt;
&lt;p&gt;Around this time, the Marketplace Squad was dissolved and absorbed into the Cloud Services Squad, which was then renamed to the &lt;strong&gt;Connectivity Squad&lt;/strong&gt; under Gabriel Casals as EM, handling registration, licensing, marketplace, and workspace connection services. The Infra team we started calling the &lt;strong&gt;SRE team&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The catalyst for the SRE transformation was the launch of &lt;strong&gt;Premium and Dedicated offerings on February 2nd, 2023&lt;/strong&gt;, with a commitment to a &lt;strong&gt;99.9% SLA&lt;/strong&gt;. That kind of promise changes how you think about everything. It&amp;rsquo;s not &amp;ldquo;best effort&amp;rdquo; anymore. You need monitoring, runbooks, incident response, post-mortems, on-call rotations. You need to think like an SRE team, not just an infrastructure team.&lt;/p&gt;
&lt;p&gt;This was probably the most intense period of my career. I was the technical lead spanning both squads, setting direction for the SRE team on the infrastructure side and the Connectivity Squad on the services side, each with their own EM handling the people management. It meant I was the common thread between the two; the person who understood how the infrastructure and the services fit together end-to-end. We were reshaping what had been a purely infrastructure-focused group into a team that thought about reliability as its core mandate.&lt;/p&gt;
&lt;h3 id="writing-things-down-rfcs-rfds-adrs-and-post-mortems"&gt;Writing Things Down: RFCs, RFDs, ADRs, and Post-Mortems&lt;/h3&gt;
&lt;p&gt;One of the things I&amp;rsquo;m most proud of across my entire time at Rocket.Chat isn&amp;rsquo;t code; it&amp;rsquo;s process. Specifically, the evolution of how we made and documented technical decisions.&lt;/p&gt;
&lt;p&gt;It started in &lt;strong&gt;November 2018&lt;/strong&gt; when I created &lt;strong&gt;[RFC 1] Self Hosted Registering with Rocket.Chat Cloud&lt;/strong&gt; on our internal Discourse forum. The idea was borrowed from the open-source world: before you build something significant, write it down. Explain the problem, propose solutions, invite discussion.&lt;/p&gt;
&lt;p&gt;That first RFC kicked off a real discussion, 13 posts from me, Gabriel Engel, Guilherme Gazzo, Rodrigo, and others. RFC 2 (Cloud Multi-Region) followed two days later. Then RFC 3 (Marketplace Licensing) in February 2019. Over the next few years, 39 RFCs were written on Discourse covering everything from marketplace subscriptions to the pros and cons of moving away from Meteor to airgapped workspace registration. I personally authored about a dozen of them, mostly around cloud architecture, marketplace, and workspace connectivity.&lt;/p&gt;
&lt;p&gt;The post-mortem practice started around the same time. My first one was the &lt;strong&gt;Cloud Workspace Outage of May 2nd, 2018&lt;/strong&gt;. Then the Community Server Outage. Then the Push Gateway Outage. We wrote them up on the same Discourse forum, creating an internal record of what went wrong and what we learned. The post-mortem practice started on our Discourse forum with around 23 incident write-ups between 2018 and 2022. When we moved to GitHub, we imported those and kept going, ending up with roughly 45 unique post-mortems across both. Cloud disruptions, certificate expirations, database elections, a Game Day DR exercise where we discovered our backup credentials were broken.&lt;/p&gt;
&lt;p&gt;By &lt;strong&gt;2021&lt;/strong&gt;, the RFC process had evolved. We started calling them &lt;strong&gt;RFDs&lt;/strong&gt; (Requests for Discussion), a subtle but meaningful shift. RFCs felt like they were asking for permission. RFDs were asking for engagement. I migrated everything from Discourse into a GitHub repo, 18 documents in a single day, pulling together the existing RFCs about microservices architecture, moving away from Meteor, the identity service, and more into one place where they could live alongside the code.&lt;/p&gt;
&lt;p&gt;But having them in GitHub wasn&amp;rsquo;t enough. ADRs were still scattered across different team folders in GitBook. Someone would share a link to an ADR and you&amp;rsquo;d never find it again. The problem was discoverability.&lt;/p&gt;
&lt;p&gt;So in &lt;strong&gt;August 2023&lt;/strong&gt; I built &lt;a href="https://github.com/geekgonecrazy/rfd-tool"&gt;rfd-tool&lt;/a&gt;, a small Go service that read from the GitHub repo and published to &lt;strong&gt;adr.rocket.chat&lt;/strong&gt;. A searchable, tagged, browsable dashboard of every architectural decision. You could filter by project, by author, by tag. In that single month we pushed through 13 ADRs: License v3, RabbitMQ to NATS, Statistics Enforcement, Cloud Credential Storage, and more. The naming settled on &lt;strong&gt;ADR&lt;/strong&gt; (Architecture Decision Record) as the umbrella term, with the understanding that discussion was always implied.&lt;/p&gt;
&lt;p&gt;The tool kept evolving right up to the end. I added support for D2 diagrams, switched the backend from BoltDB to SQLite, added the ability to create ADRs from the web UI, and eventually added support for making specific ADRs public. One of my last PRs at the company was adding GitHub PR links to each ADR to make collaboration easier.&lt;/p&gt;
&lt;p&gt;RFC → RFD → ADR. Discourse → GitHub → adr.rocket.chat. The format changed, the tools changed, but the core idea stayed the same from RFC 1 in 2018 to ADR 148 in 2025: write it down, invite discussion, make it discoverable.&lt;/p&gt;
&lt;h2 id="stepping-away-and-coming-back-2024---2025"&gt;Stepping Away and Coming Back (2024 - 2025)&lt;/h2&gt;
&lt;p&gt;By mid-&lt;strong&gt;2024&lt;/strong&gt;, after nearly nine years, I decided to step away. I transitioned out in July 2024 and stayed on in an advisory capacity, keeping a connection to the team and the platform I&amp;rsquo;d helped build.&lt;/p&gt;
&lt;p&gt;The time away was valuable. I found balance. I picked up hobbies outside of work, something I hadn&amp;rsquo;t really had in years. But I also realized how much I missed the work itself. Building things that matter. Solving hard problems with good people. I &lt;a href="https://aaronogle.dev/2024/12/31/year-in-review-2024/#work--professional"&gt;wrote more about that period&lt;/a&gt; in my 2024 year in review.&lt;/p&gt;
&lt;p&gt;On &lt;strong&gt;May 19th, 2025&lt;/strong&gt;, I officially returned as &lt;strong&gt;Head of Infrastructure &amp;amp; Deployment&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;This time I took both People and Tech hats deliberately. No split between a technical lead and an engineering manager. I&amp;rsquo;d seen what happened when those roles were separated and the partnership didn&amp;rsquo;t gel. Simpler is better.&lt;/p&gt;
&lt;h2 id="the-sre-team-building-something-that-would-outlast-me-2025---2026"&gt;The SRE Team: Building Something That Would Outlast Me (2025 - 2026)&lt;/h2&gt;
&lt;p&gt;When I came back, one of the first things I did was write a &lt;strong&gt;team charter&lt;/strong&gt;, a document that made clear the team&amp;rsquo;s purpose, scope, and strategic objectives. We started an SRE book club. We formalized documentation practices in Confluence. I wrote a lot&amp;hellip; Posted priority alignments every week making sure that any adjustments in priority were clearly communicated to the team, every month setting the months priorities. The main goal was to increase alignment so it was very clear what we were working towards. I pushed for post-mortems after every incident, and tried to build a culture where reliability wasn&amp;rsquo;t just my obsession but the team&amp;rsquo;s identity.&lt;/p&gt;
&lt;p&gt;We launched &lt;strong&gt;Launchpad&lt;/strong&gt; (our opinionated deployment tool), drove SLO definitions across services, and pushed forward on everything from Helm chart improvements to airgapped deployment support.&lt;/p&gt;
&lt;h2 id="by-the-numbers"&gt;By The Numbers&lt;/h2&gt;
&lt;p&gt;Looking back across the data (because of course I had AI build a tool to analyze all of it):&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;&lt;strong&gt;Years&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~10.5 (Aug 2015 - Mar 2026)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GitHub PRs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1,520 across 84 repositories&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PR Review Comments&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2,885 (lower then I expected. But we dog fooded a bit heavy and tilted towards feedback often times inside of Rocket.Chat&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rocket.Chat Messages&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;359,980&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rooms Active In&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1,665&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Confluence Pages Created&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;98 (Note we migrated across 3 different documentation tools over the years so this number is just for confluence since it was adopted in 2024)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Confluence Edits&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;221&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Zero-Downtime Migrations&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;4 (Rackspace→GCP, GCP→AWS, AWS→OVH, OVH→AWS)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cloud Providers Operated On&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;5 (Rackspace, Google Cloud, AWS, Oracle, OVH)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Post-Mortems&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~45 unique (This isn&amp;rsquo;t how many I wrote but total over the years. We started this process in 2018)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;RFCs/RFDs/ADRs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;148 total, ~30 authored by me&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Services &amp;amp; Tools Built/Contributed To&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fleetcommand, cloud-portal, Push Gateway, Marketplace API, marketplace-worker, marketplace-ui, statuscentral, statscollector, omni-gateway, launchcontrol, airlock, Launchpad, billing-service, sponsorship-service, rfd-tool, filestore-migrator, portmaster, Go SDK, FederationHub, and many more&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Team Names&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cloud → Cloud Service Squad → SaaS Squad → Connectivity Services → SRE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;My peak year in the data was &lt;strong&gt;2020&lt;/strong&gt;: 199 PRs and 29,097 Rocket.Chat messages. I&amp;rsquo;d contribute a large part of the total to OVH migration. The year I was building, reviewing, deploying, and firefighting simultaneously. It was a massive learning curve for us. A small team of 3-4 people running an entire cloud platform.&lt;/p&gt;
&lt;p&gt;The relationship that shows up most clearly in the data is with &lt;strong&gt;Rodrigo Nascimento&lt;/strong&gt;, the CTO. 8,324 DMs over the years, peaking at 2,407 messages in 2020. That was the builder-manager relationship during the most intensive infrastructure work. He believed in me when I was just a community contributor, and that belief shaped my entire career.&lt;/p&gt;
&lt;h2 id="what-ive-learned"&gt;What I&amp;rsquo;ve Learned&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Start by showing up.&lt;/strong&gt; I got here by fixing a bug. Then another. Then another. Nobody gave me a role. I just kept contributing until the role found me.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Small teams can move mountains.&lt;/strong&gt; Three to four people executed four zero-downtime migrations across five cloud providers. We didn&amp;rsquo;t wait for permission or headcount. We just figured it out.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Titles don&amp;rsquo;t matter as much as you think.&lt;/strong&gt; I was a &amp;ldquo;Cloud Architect&amp;rdquo; with no official title. An &amp;ldquo;Engineering Manager&amp;rdquo; who didn&amp;rsquo;t know his own job description. A &amp;ldquo;Staff Engineer&amp;rdquo; who also managed people. Through all of it, the work was the same: understand the system, set direction, build the thing, help the people.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Take the break when you need it.&lt;/strong&gt; I left burned out and came back with perspective. The hobbies I found during that gap made me a better leader when I returned.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Build things that outlast you.&lt;/strong&gt; The team charter, the documentation culture, the post-mortem practice, the SRE book club. Those matter more than any code I wrote. Code gets replaced. Culture persists.&lt;/p&gt;
&lt;h2 id="thank-you"&gt;Thank You&lt;/h2&gt;
&lt;p&gt;To everyone I&amp;rsquo;ve worked with over these 10 years, thank you. There are too many people to name, but a few I want to call out:&lt;/p&gt;
&lt;p&gt;Bradley, for jumping into this crazy startup with me. Having a friend along for the ride made it a lot more comfortable to take that leap, and together we kept the cloud alive in those early days. Lucia, for keeping the infrastructure running when it was just us. Joseph, my favorite designer and an absolute joy to collaborate with during the squad era. Daniel, Debdut, and Paul on the SRE team. I&amp;rsquo;m proud of what we built together.&lt;/p&gt;
&lt;p&gt;Gabriel Casals, for showing me what a great EM looks like. You set the example for how to genuinely care for the people on your team. Rodrigo, Gabriel Engel, and Chris Skelly, for the trust at every stage.&lt;/p&gt;
&lt;p&gt;Guilherme Gazzo, for the partnership across engineering. Sing Li, for being a constant sounding board from the very beginning, always encouraging me to write more and take the leaps into the unknown that the startup world demands. Julio Bertelli &amp;ldquo;the Professional,&amp;rdquo; one of the most talented Go developers I&amp;rsquo;ve had the chance to work with. Douglas Gubert, for the many Ketchup sessions where we&amp;rsquo;d talk about anything and everything. And Julio Araujo, the coolest head of security I&amp;rsquo;ve ever worked with, and one of the most talented security engineers too.&lt;/p&gt;
&lt;p&gt;To the Rocket.Chat community, you&amp;rsquo;re the reason I started. A product good enough that strangers on the internet wanted to make it better. That&amp;rsquo;s special. And a big part of what makes it special comes from the founders themselves. There&amp;rsquo;s a warmth that Gabriel Engel and Rodrigo, Diego, Marcelo have always brought to this project from day one, always welcoming, always open. I remember the first time meeting everyone in person and receiving big hugs like we&amp;rsquo;d known each other for years. That warmth is something you can feel throughout the entire company. It&amp;rsquo;s invisible on paper but you feel it in every interaction, and honestly it&amp;rsquo;s what kept me going through all the hard times.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s been an incredible ride. From &amp;ldquo;Fix image stretching&amp;rdquo; to Head of Infrastructure &amp;amp; Deployment. From 1 repo to 84. From fixing UI bugs to architectural decisions that shaped how tens of thousands of workspaces run.&lt;/p&gt;
&lt;p&gt;Time for the next adventure.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;- Aaron Ogle&lt;/em&gt;&lt;/p&gt;</description></item><item><title>Year In Review: 2024</title><link>https://aaronogle.dev/2024/12/31/year-in-review-2024/</link><pubDate>Tue, 31 Dec 2024 00:00:00 +0000</pubDate><guid>https://aaronogle.dev/2024/12/31/year-in-review-2024/</guid><description>
&lt;h1 id="2024-is-now-in-the-books"&gt;2024 is now in the books!&lt;/h1&gt;
&lt;p&gt;In previous years, I wrote internal posts at work to reflect on the year and highlight accomplishments. This exercise was revealing. It was often a great way to see how much we’d achieved that you might lose sight of in the daily grind. This year, I decided to apply the same reflection to my personal life.&lt;/p&gt;
&lt;p&gt;Here’s a TL;DR of 2024:&lt;/p&gt;
&lt;h2 id="personal-life"&gt;Personal Life&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#a-year-free-from-caffeine"&gt;A Year Free From Caffeine&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Returned to &lt;a href="#martial-arts"&gt;Martial Arts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Increased focus on &lt;a href="#working-out"&gt;Working Out&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Lost &lt;a href="#impact"&gt;12 pounds&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Traveled to Brazil and London&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="professionally"&gt;Professionally&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Emphasized &lt;a href="#production-readiness"&gt;Production Readiness&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Grew as a &lt;a href="#staff-engineer"&gt;Staff Engineer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#new-job"&gt;Changed jobs&lt;/a&gt; after nearly a decade&lt;/li&gt;
&lt;li&gt;Explored &lt;a href="#technology"&gt;New Technology&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Adopted a &lt;a href="#daily-tech-stack"&gt;Streamlined Tech Setup&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h1 id="personal-life-1"&gt;Personal Life&lt;/h1&gt;
&lt;p&gt;2024 was full of ups and downs, but I made meaningful progress in key areas.&lt;/p&gt;
&lt;h2 id="health"&gt;Health&lt;/h2&gt;
&lt;p&gt;Improving my health became a major focus. Thankfully not due to any serious issues, but because I&amp;rsquo;ve started to realized it’s easier to get and maintain health now than to regain it later.&lt;/p&gt;
&lt;h3 id="a-year-free-from-caffeine"&gt;A Year Free From Caffeine&lt;/h3&gt;
&lt;p&gt;In October 2023, I noticed I couldn’t function without caffeine. Specifically, I was drinking at least 2-3 Dr. Pepper a day. Worse, if I ran out at home it meant struggling through the day. It felt like an addiction, so I quit cold turkey (that weekend headache sucked).&lt;/p&gt;
&lt;p&gt;As of October 2024, I’ve gone an entire year without any caffeinated soda. However, I replaced it with sugary alternatives, which completely negated any health benefits that could be had. This year, I’ve started removing soda altogether to reduce my sugar intake.&lt;/p&gt;
&lt;h3 id="martial-arts"&gt;Martial Arts&lt;/h3&gt;
&lt;p&gt;Martial arts have always been a passion i&amp;rsquo;ve mine. I earned a yellow belt while taking Karate for a PE credit in college. Sadly I didn&amp;rsquo;t continue because I was a poor college student that didn&amp;rsquo;t think it was worth going to the dojo and paying for sessions. This year my kids started doing Karate. After I was good and behind them.. 2 belts. I decided to join.&lt;/p&gt;
&lt;p&gt;I’ve regained my yellow belt and plan to continue. It’s a great way to completely disconnect. Not to mention the practice for sparring got me moving which was really good for me.&lt;/p&gt;
&lt;h3 id="working-out"&gt;Working Out&lt;/h3&gt;
&lt;p&gt;I’ve been gradually building a home gym to be able to practice Martial Arts at home as well as lift some weights. The beauty of it being at home is makes it easier to go at weird times. Sometimes even work out with my kids and encourage them to be more physically active as well.&lt;/p&gt;
&lt;h3 id="impact"&gt;Impact&lt;/h3&gt;
&lt;p&gt;These efforts have been paying off. So far, i’ve lost 12 pounds in the last four months. Not to mention I feel much better overall. I can even spar without feeling like I’m going to pass out!&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="travel"&gt;Travel&lt;/h2&gt;
&lt;p&gt;I traveled internationally twice this year:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Brazil&lt;/strong&gt;: A work trip brought me to Porto Alegre just a week before the airport was severely flooded.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;London&lt;/strong&gt;: I took my family on a trip to London. The kids first trip overseas. They were finally all old enough I felt like they would remember and appreciate it a lot more. Not to mention a lot easier to travel with when they can all walk around on their own.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h1 id="work--professional"&gt;Work / Professional&lt;/h1&gt;
&lt;p&gt;2024 brought some changes to my career.&lt;/p&gt;
&lt;h2 id="staff-engineer"&gt;Staff Engineer&lt;/h2&gt;
&lt;p&gt;At Rocket.Chat over the course of almost 10 years, I held various roles. Engineering Manager, Tech Lead, Team Lead, etc. From building a team, to taking our scope and spliting it up into 3 seperate teams. But Staff Engineer as a level I didn&amp;rsquo;t really know what it was or what I was supposed to do. So this year I tried to settle in and figure out what the industry considers a Staff Engineer and try to learn what I could.&lt;/p&gt;
&lt;p&gt;This article and book with the same title I really recommend reading if you&amp;rsquo;d like to learn: &lt;a href="https://staffeng.com/guides/what-do-staff-engineers-actually-do/"&gt;https://staffeng.com/guides/what-do-staff-engineers-actually-do/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I tried to also spread our support of Staff Engineers so others coming into that role would have more direction. Its a role I really enjoy and realize I do even more so in retrospect.&lt;/p&gt;
&lt;h2 id="production-readiness"&gt;Production Readiness&lt;/h2&gt;
&lt;p&gt;In the year’s first half, I focused on a cross team initiative: Production Readiness. I might be missing some great sources of information out there. But I felt like this was a subject very under documented on the web.&lt;/p&gt;
&lt;p&gt;This process was a lot of talking to stakeholders and together:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Defining SLAs/SLOs&lt;/li&gt;
&lt;li&gt;Identifying critical user experience factors&lt;/li&gt;
&lt;li&gt;Api response time&lt;/li&gt;
&lt;li&gt;Error rates&lt;/li&gt;
&lt;li&gt;Error budgets&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Then working backwards from there with the engineering team to identify the risks to being able to fullfill these targets.&lt;/p&gt;
&lt;p&gt;Things like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Building and participating in an on call team to actually be responsible for delivering targets&lt;/li&gt;
&lt;li&gt;Implementing new metrics to gain visibilty into something critical&lt;/li&gt;
&lt;li&gt;Removing code complexity from endpoints to speed up response times&lt;/li&gt;
&lt;li&gt;Ensuring could dynamically scale to meet load&lt;/li&gt;
&lt;li&gt;Ensuring could handle dependency failures appropriately&lt;/li&gt;
&lt;li&gt;Ensuring alerts were properly set&lt;/li&gt;
&lt;li&gt;Ensuring systems like Mongo, Redis, Nats etc were set to a higher SLA&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If anyone is looking for good things to blog about.. This would be a good topic to see more information out there. If not I hope to get to it at some point.&lt;/p&gt;
&lt;h2 id="technical-writing"&gt;Technical Writing&lt;/h2&gt;
&lt;p&gt;As part of that focus on Staff Engineer it was important to help with technical alignment. This means documenting and writing things down. This has been a passion of mine for a long time, but we seemed to always struggle getting stakeholders to go read our docs written in markdown, keeping the docs together so they were discoverable, and having a common agreed on format and system for these documents.&lt;/p&gt;
&lt;p&gt;For a while I had been eyeing Oxide Computer&amp;rsquo;s Ellusive &lt;a href="https://oxide.computer/blog/rfd-1-requests-for-discussion"&gt;RFD Process&lt;/a&gt;. What really stuck out to me was not just documenting but trying to drive discussions. I really wanted to try it out, but their system at the time was part of a larger CIO toolset they had built.&lt;/p&gt;
&lt;p&gt;So at the end of 2023 I wrote a tool that from what I could tell worked a lot like their tool. I very creatively called: &lt;a href="https://github.com/geekgonecrazy/rfd-tool"&gt;RFD Tool&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Over the course of 2024 I rolled this out. I also took a bunch of documents I and others had written and imported them into the system. From what I hear the final count at the end of this year was 114 RFDs.&lt;/p&gt;
&lt;p&gt;I plan to write more about this system in a future post.&lt;/p&gt;
&lt;h2 id="new-job"&gt;New Job&lt;/h2&gt;
&lt;p&gt;After nearly 10 years at Rocket.Chat, I transitioned to a new role as a Senior Software Engineer at a new company that helps build out fiber networks in communities and then provides software to allow the members of the community to sign up through a marketplace and chose their ISP, voice services and facilitate the provisioning of the CPE&amp;rsquo;s hooking them up to their chosen services. This change was important to allow me to reset and perform a rebalance of work/life. But also a good opportunity to learn something new, particularly in the ISP space which i&amp;rsquo;ve always found interesting.&lt;/p&gt;
&lt;p&gt;Some times a change is required to help us realize what we value. I realize I find fulfillment in participating in architecture and direction, not just coding. This is something I&amp;rsquo;ll be focusing on in the new year.&lt;/p&gt;
&lt;h3 id="technology"&gt;Technology&lt;/h3&gt;
&lt;p&gt;Joining a new team meant working with new technologies:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Microservices&lt;/strong&gt;: I&amp;rsquo;ve worked with microservices before typically by breaking part of a monolith off to enable more dynamic scaling. I&amp;rsquo;ve never worked with a microservice first architecture. While microservices can enable scaling and team parallelism, the complexity isn’t always worth it for smaller teams.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GraphQL&lt;/strong&gt;: Although I see its appeal, GraphQL introduces challenges with network traffic, authorization, and increased boilerplate code necessary. I still prefer well-crafted RESTful APIs. &lt;a href="https://bessey.dev/blog/2024/05/24/why-im-over-graphql/"&gt;A good article on this&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;gRPC and Protobufs&lt;/strong&gt;: Defining services with Protobufs and generating REST APIs, openapi documentation, and gRPC Gateway code is really cool. I plan to explore this more.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This article by tailscale is a good read that has been top of mind: &lt;a href="https://tailscale.com/blog/new-internet"&gt;https://tailscale.com/blog/new-internet&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="daily-tech-stack"&gt;Daily Tech Stack&lt;/h2&gt;
&lt;p&gt;This year my primary daily stack was:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://fedoraproject.org/atomic-desktops/silverblue/"&gt;Silverblue&lt;/a&gt;, an immutable OSTree OS,&lt;/li&gt;
&lt;li&gt;A custom OSTree branch, &lt;a href="https://github.com/geekgonecrazy/triiodide"&gt;Triiodide&lt;/a&gt; (i3 - 3 iodine atoms is a &lt;a href="https://en.wikipedia.org/wiki/Triiodide"&gt;triiodide&lt;/a&gt; ion) that brings i3wm instead of gnome&lt;/li&gt;
&lt;li&gt;Dev Containers&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ghostty.org"&gt;Ghostty&lt;/a&gt; for a performant terminal experience&lt;/li&gt;
&lt;li&gt;A single 32&amp;quot; curved monitor plus a smaller secondary display for chat, video conferencing and music&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Plan to write more about my immutable/Container based flow at some point soon.&lt;/p&gt;
&lt;h1 id="2025"&gt;2025&lt;/h1&gt;
&lt;p&gt;I don&amp;rsquo;t really do new year&amp;rsquo;s resolutions any more. I feel like uou don&amp;rsquo;t need to wait for a new year to make a change. Plus most people I see that only do resolutions one time a year.. Usually set themselves up for failure by trying to do too many at the same time. How many times did you set a goal to workout and buy a gym membership only to stop going after 2-3 months? I have.. several times.&lt;/p&gt;
&lt;p&gt;But, I do plan to continue to focus on health, doing more writing, and focus on work I find fullfilling.&lt;/p&gt;
&lt;p&gt;Here’s to another year of growth!&lt;/p&gt;</description></item><item><title>Fedora Iot, Greenboot, Systemd and of course DNS</title><link>https://aaronogle.dev/2023/09/24/fedora-iot-greenboot-systemd-and-of-course-dns/</link><pubDate>Sun, 24 Sep 2023 00:00:00 +0000</pubDate><guid>https://aaronogle.dev/2023/09/24/fedora-iot-greenboot-systemd-and-of-course-dns/</guid><description>
&lt;p&gt;This post is mostly as a resource for future me. But maybe it&amp;rsquo;ll come in useful to someone else.&lt;/p&gt;
&lt;p&gt;This weekend I was working on provisioning a new NAS/Media box setup after having to do a bit of hardware shuffling. Long story.&lt;/p&gt;
&lt;p&gt;I decided to try &lt;a href="https://fedoraproject.org/iot/"&gt;Fedora iot&lt;/a&gt; on a whim. Fedora iot has an interesting project called &lt;a href="https://github.com/fedora-iot/greenboot"&gt;greenboot&lt;/a&gt;. The objective of the project is to define some checks for the state of the machine. When the machine is booting and the machine isn&amp;rsquo;t configured or working as expected it reboots and tries to correct. From what I understand it does this several times and then if unsuccessful it rolls back to the previous ostree commit. In an edge deployment scenario where you can&amp;rsquo;t always have your hands on the device and it almost assuredly will break&amp;hellip; I can see ostree commits + this to being great to rollback when something gets broken. Much easier than in my previous post:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://geekgonecrazy.com/2022/06/16/adventures-of-the-geek-remote-password-reset/"&gt;Adventures of the geek: Remote Password Reset&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Anyways.. In this particular case i&amp;rsquo;m also installing &lt;a href="https://pi-hole.net/"&gt;pi-hole&lt;/a&gt; on it. This will act as the DNS server in my house. Blocking domains related to tracking, ads etc. But also lets me do other typical internal dns stuff, block list of inappropriate domains etc.&lt;/p&gt;
&lt;p&gt;So I started off by just tying to run pi-hole:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo podman run -d \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --name=pihole \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -e TZ=America/Chicago \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -e DNSMASQ_LISTENING=all \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -e WEBPASSWORD=password \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -v ./etc-pihole:/etc/pihole:Z \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -v ./etc-dnsmasq.d:/etc/dnsmasq.d:Z \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -p 53:53/tcp \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -p 53:53/udp \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -p 80:80/tcp \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --restart=unless-stopped \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; docker.io/pihole/pihole:latest
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This started throwing erorrs about :53 already being used.&lt;/p&gt;
&lt;p&gt;Turns out that systemd-resolved listens on :53 with a stub-listener and by default all queries goto 127.0.0.1:53 and then through systemd-resolved to upstream dns resolvers.&lt;/p&gt;
&lt;p&gt;To disable I had to create: &lt;code&gt;/etc/systemd/resolvd.conf.d/stub-listener.conf&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;With contents:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[Resolve]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;DNSStubListener=no
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then of course restart systemd-resolved:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo systemctl restart systemd-resolved
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This let me start up pi-hole and I went on about my business setting up volumes, moving data around etc.&lt;/p&gt;
&lt;p&gt;As part of it a reboot was finally needed. Oops&amp;hellip; It wouldn&amp;rsquo;t boot.. get to login screen and then promptly reboot again. I realized this was greenboot. I let it go a few times but it never recovered.&lt;/p&gt;
&lt;p&gt;So I finally intervened and modified the boot arguments from grub and added:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;init=/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To drop into single user mode.&lt;/p&gt;
&lt;p&gt;I poked around and finally found: &lt;code&gt;/usr/lib/greenboot/check/required.d/01_repository_dns_check.sh&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This made me realize what had happened. pi-hole wasn&amp;rsquo;t up at this point and systemd-resolved is no longer running the stub. So this check was failing.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[aaron@super-terribly-named-box ~]$ dig google.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;;; communications error to ::1#53: connection refused
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;;; communications error to ::1#53: connection refused
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;;; communications error to ::1#53: connection refused
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;;; communications error to 127.0.0.1#53: connection refused
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.18.17 &amp;lt;&amp;lt;&amp;gt;&amp;gt; google.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;;; global options: +cmd
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;;; no servers could be reached
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I found this issue: &lt;a href="https://github.com/fedora-iot/greenboot/issues/113#issuecomment-1689929196"&gt;https://github.com/fedora-iot/greenboot/issues/113#issuecomment-1689929196&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The suggestion is simple. Disable the service. Problem was I couldn&amp;rsquo;t even get logged in fast enough over ssh or console access to do this.&lt;/p&gt;
&lt;p&gt;In single user mode systemd isn&amp;rsquo;t running of course so finding the unit file to quickly mask it didn&amp;rsquo;t work. And at the time I didn&amp;rsquo;t remember how to do it manually with ostree involved anyways.&lt;/p&gt;
&lt;p&gt;For the record: &lt;code&gt;/usr/lib/systemd/system/greenboot-healthcheck.service&lt;/code&gt; but still the problem of it being read only because of ostree and being in single user mode where rpm-ostree did not seem to work like I was used to. This is a subject i&amp;rsquo;ll be diving into at a later date.&lt;/p&gt;
&lt;p&gt;I looked for a way via boot args to turn off greenboot. They don&amp;rsquo;t have any. But then I found:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;systemd.mask=greenboot-healthcheck.service
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Can read a bit more &lt;a href="https://man.archlinux.org/man/systemd-debug-generator.8.en"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;By adding this to the boot args it will mask that service from starting during that session.&lt;/p&gt;
&lt;p&gt;From here then it was as simple as:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo systemctl mask greenboot-healthcheck.service
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now to go on to evaluate greenboot further. Seems like a cool idea.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;systemd.mask&lt;/code&gt; bootarg saved the day!&lt;/p&gt;</description></item><item><title>How to Set Up Client SSL Certificate Authentication for Rocket.Chat</title><link>https://aaronogle.dev/2023/05/23/how-to-set-up-client-ssl-certificate-authentication-for-rocket.chat/</link><pubDate>Tue, 23 May 2023 00:00:00 +0000</pubDate><guid>https://aaronogle.dev/2023/05/23/how-to-set-up-client-ssl-certificate-authentication-for-rocket.chat/</guid><description>
&lt;p&gt;Are you looking to add an extra layer of security to access Rocket.Chat? One way to do this is by implementing client SSL certificate authentication. This authentication method requires clients to present a valid SSL certificate to authenticate themselves to the server.&lt;/p&gt;
&lt;p&gt;In this post, we will walk through the steps to set up client SSL certificate authentication using Nginx.&lt;/p&gt;
&lt;h2 id="prerequisites"&gt;Prerequisites&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;A server running Ubuntu
&lt;ul&gt;
&lt;li&gt;Allow HTTP/HTTPS/ssh in security group&lt;/li&gt;
&lt;li&gt;Create a public IP and associate it.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;A domain&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Domain pointed to the server&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="step-1-install-docker"&gt;Step 1: Install Docker&lt;/h2&gt;
&lt;p&gt;Lets do a quick and easy install of Docker if you haven&amp;rsquo;t already.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -L https://get.docker.com | sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now Lets add your user to the docker group so you don&amp;rsquo;t have to use &lt;code&gt;sudo&lt;/code&gt; before every docker command.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo usermod -aG docker $USER
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Normally here we&amp;rsquo;d say logout and back in.. but I don&amp;rsquo;t want to mess with it so I use:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;newgrp docker
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="step-2-install-rocketchat"&gt;Step 2: Install Rocket.Chat&lt;/h2&gt;
&lt;p&gt;Now that we have Docker installed lets get Rocket.Chat up and running.&lt;/p&gt;
&lt;p&gt;Start off with creating a rocketchat directory and grabbing the docker-compose file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mkdir rocketchat &amp;amp;&amp;amp; cd &amp;#34;$_&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -L https://go.rocket.chat/i/docker-compose.yml -O
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next lets fire it up.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker compose up -d
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If impatient or only came here to install Rocket.Chat you could access on port 3000 if your firewall is open. But I suspect you came here for seeing how to do client SSL. So lets carry on!&lt;/p&gt;
&lt;h2 id="step-3-install-nginx"&gt;Step 3: Install Nginx&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt install -y nginx
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="step-4-install-certbot"&gt;Step 4: Install Certbot&lt;/h2&gt;
&lt;p&gt;To help us get a valid certificate we are going to use letsencrypt but using a tool called certbot. This will help us make sure to keep the certificate valid as well.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo snap install --classic certbot
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now use certbot to generate and plug everything up for letsencrypt and nginx:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo certbot --nginx
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You’ll be asked to provide a valid email and the domain set.&lt;/p&gt;
&lt;h2 id="step-5-generate-certificate-authority-ca-certificates"&gt;Step 5: Generate Certificate Authority (CA) Certificates&lt;/h2&gt;
&lt;p&gt;In order to do client SSL Authentication we’re going to need a CA.&lt;/p&gt;
&lt;h3 id="generate-a-key-for-your-ca"&gt;Generate a key for your CA:&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;openssl genrsa -des3 -out ca.key 4096
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="generate-a-certificate-for-your-ca"&gt;Generate a certificate for your CA:&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;openssl req -new -x509 -days 365 -key ca.key -out ca.crt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;Note what you’ve entered for Country, State, Locality, and Organization; you’ll want these to match later when you renew the certificate.&lt;/li&gt;
&lt;li&gt;Do not enter a common name (CN) for the certificate.&lt;/li&gt;
&lt;li&gt;Email can be omitted.&lt;/li&gt;
&lt;li&gt;Note renewing certificate involves running the same command. If you need to remember what options you chose you can run:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;openssl x509 -in ca.crt -noout -text
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="move-ca-cert"&gt;Move CA cert&lt;/h3&gt;
&lt;p&gt;To: &lt;code&gt;/etc/ssl/private/client-cert-ca.crt&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="update-nginx-config"&gt;Update Nginx config&lt;/h3&gt;
&lt;p&gt;We need to add CA cert, turn on client ssl authentication and add location block:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ssl_client_certificate /etc/ssl/private/client-cert-ca.crt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ssl_verify_client optional;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;location / {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; if ($ssl_client_verify != SUCCESS) {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; return 403;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; proxy_pass http://localhost:3000;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; proxy_http_version 1.1;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; proxy_set_header Upgrade $http_upgrade;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; proxy_set_header Connection &amp;#34;upgrade&amp;#34;;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; proxy_set_header Host $http_host;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; proxy_set_header X-Real-IP $remote_addr;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; proxy_set_header X-Forwarded-Proto https;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; proxy_set_header X-Nginx-Proxy true;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; proxy_redirect off;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="step-6-issue-client-ssl-certificates-for-users"&gt;Step 6: Issue Client SSL Certificates for users&lt;/h2&gt;
&lt;p&gt;You can have your users perform most of these steps if you want. But the following are the steps needed to create a certificate to present as client authentication.&lt;/p&gt;
&lt;h3 id="generate-key-for-user"&gt;Generate key for user&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;openssl genrsa -des3 -out user.key 4096
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="generate-a-csr"&gt;Generate a CSR&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;openssl req -new -key user.key -out user.csr
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;A number of questions will be asked; answer each one, including the Common Name (CN) and email address. The CSR needs to be sent to the admin (or you if you are doing this for the user).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="sign-csr-with-ca"&gt;Sign CSR with CA&lt;/h3&gt;
&lt;p&gt;As the admin, take the CSR given to you or generated by you and sign the CSR and create valid certificate:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;openssl x509 -req -days 365 -in user.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out user.crt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;You’ll want to increment the serial number with each signing. Once the certificate expires, a new CSR doesn’t need to be recreated; the same one can be signed, which will create a new certificate tied to that public key.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="return-certificate"&gt;Return Certificate&lt;/h3&gt;
&lt;p&gt;The signed certificate (user.crt) can now be sent back to the user along with the CA cert(ca.crt).&lt;/p&gt;
&lt;p&gt;To be able to use in browsers and mobile generate a pkcs #12 using the user cert and key along with the Ca:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;openssl&lt;/span&gt; &lt;span class="n"&gt;pkcs12&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pfx&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;inkey&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;crt&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;certfile&lt;/span&gt; &lt;span class="n"&gt;ca&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;crt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Beware if you intend to install on Mac or iOS, you may need to use an older version of OpenSSL. More info here: &lt;a href="https://developer.apple.com/forums/thread/697030?answerId=710429022#710429022"&gt;https://developer.apple.com/forums/thread/697030?answerId=710429022#710429022&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="step-7-access-rocketchat-using-client-ssl-certificate"&gt;Step 7: Access Rocket.Chat using Client SSL Certificate&lt;/h2&gt;
&lt;p&gt;To access your application with client certificate authentication:&lt;/p&gt;
&lt;h3 id="on-ios"&gt;On iOS:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Add the file on Files app (depending on what you do, iOS will try to install it on the whole OS. e.g. copying from airdrop)&lt;/li&gt;
&lt;li&gt;Go to new server screen and try the server URL just to confirm (an error message should show because you haven&amp;rsquo;t applied the cert yet)&lt;/li&gt;
&lt;li&gt;Tap &lt;code&gt;apply your certificate&lt;/code&gt; on the bottom of the screen and select it from the Files app&lt;/li&gt;
&lt;li&gt;Try again, and it should navigate to the workspace info&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="on-android"&gt;On Android:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Install the certificate&lt;/li&gt;
&lt;li&gt;Go to new server screen and try the server URL just to confirm (an error message should show because you haven&amp;rsquo;t applied the cert yet)&lt;/li&gt;
&lt;li&gt;Tap &lt;code&gt;apply your certificate&lt;/code&gt;, and the OS should prompt you to select a cert&lt;/li&gt;
&lt;li&gt;Select it&lt;/li&gt;
&lt;li&gt;Tap connect, and it should navigate to the workspace info&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="on-firefox"&gt;On Firefox:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Open Firefox and click on the three horizontal lines in the top-right corner of the window.&lt;/li&gt;
&lt;li&gt;Select &amp;ldquo;Preferences&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;In the left-hand menu, click on &amp;ldquo;Privacy &amp;amp; Security&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;Scroll down to the &amp;ldquo;Certificates&amp;rdquo; section and click on &amp;ldquo;View Certificates&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;Click on the &amp;ldquo;Your Certificates&amp;rdquo; tab.&lt;/li&gt;
&lt;li&gt;Click on &amp;ldquo;Import&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;Browse to the location of your client certificate file and select it.&lt;/li&gt;
&lt;li&gt;Enter the password for the certificate if prompted.&lt;/li&gt;
&lt;li&gt;Click &amp;ldquo;OK&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;Your client certificate should now be imported and ready to use in Firefox.&lt;/li&gt;
&lt;li&gt;Visit the address and you should be prompted to select the certificate.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Congratulations! You have successfully set up client SSL certificate authentication for &lt;a href="http://Rocket.Chat"&gt;Rocket.Chat&lt;/a&gt; using Nginx.&lt;/p&gt;
&lt;p&gt;Extremely useful Reference: &lt;a href="https://fardog.io/blog/2017/12/30/client-side-certificate-authentication-with-nginx/"&gt;https://fardog.io/blog/2017/12/30/client-side-certificate-authentication-with-nginx/&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Adventures of the Geek: Remote Password Reset</title><link>https://aaronogle.dev/2022/06/16/adventures-of-the-geek-remote-password-reset/</link><pubDate>Thu, 16 Jun 2022 00:00:00 +0000</pubDate><guid>https://aaronogle.dev/2022/06/16/adventures-of-the-geek-remote-password-reset/</guid><description>
&lt;p&gt;Our adventure begins on a Monday evening. I received a call from a family member that lives a bit over 8 hours away.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I powered on my laptop today and it won&amp;rsquo;t take my password&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Unfortunately the laptop runs Windows 10. I have made it a point to not use windows and haven&amp;rsquo;t for last several years. Primarily using linux or osx. Leaving me at a bit of a disadvantage.&lt;/p&gt;
&lt;p&gt;So then I did what any self respecting computer guy does when need to find out the options. I duckduckgo&amp;rsquo;d it!&lt;/p&gt;
&lt;h2 id="options-to-do-password-reset"&gt;Options to do Password Reset&lt;/h2&gt;
&lt;p&gt;Found a few options&lt;/p&gt;
&lt;h3 id="password-reset-via-security-questions"&gt;Password Reset via Security Questions&lt;/h3&gt;
&lt;p&gt;Apparently these weren&amp;rsquo;t set. Looks like it was introduced on Windows 10 Version 1803. Not sure if we originally installed before then or exactly what happened.. but didn&amp;rsquo;t have this.. so wasn&amp;rsquo;t an option.&lt;/p&gt;
&lt;h3 id="password-reset-via-password-reset-disk-or-usb"&gt;Password Reset via Password Reset Disk or USB&lt;/h3&gt;
&lt;p&gt;We hadn&amp;rsquo;t prepared one. Awesome&amp;hellip; After this is solved, making one is a must.&lt;/p&gt;
&lt;h3 id="password-reset-via-microsoft-account"&gt;Password Reset via Microsoft Account&lt;/h3&gt;
&lt;p&gt;This was a local account.. not an option.&lt;/p&gt;
&lt;h3 id="password-reset-via-safe-mode"&gt;Password Reset via Safe Mode&lt;/h3&gt;
&lt;p&gt;Tried this..&lt;/p&gt;
&lt;p&gt;I honestly don&amp;rsquo;t know what happened here. I tried to navigate doing this based on screenshots on the internet. Relying on my remote eyes and hands to describe what was happening.&lt;/p&gt;
&lt;p&gt;It didn&amp;rsquo;t work.&lt;/p&gt;
&lt;h3 id="password-reset-via-offline-windows-password--registry-editor"&gt;Password Reset via Offline Windows Password &amp;amp; Registry Editor&lt;/h3&gt;
&lt;p&gt;More info about it can be found here: &lt;a href="https://pogostick.net/~pnh/ntpasswd/"&gt;https://pogostick.net/~pnh/ntpasswd/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This one had a lot of potential. Looked like it would do exactly what I needed.&lt;/p&gt;
&lt;p&gt;Requested my helpful remote hands find a flash drive and put in an older laptop in the house. Used teamviewer to connect. It was already installed this isn&amp;rsquo;t the first time i&amp;rsquo;ve needed to help out with something.&lt;/p&gt;
&lt;p&gt;From there I downloaded a super lightweight tool called &lt;a href="https://rufus.ie/"&gt;Rufus&lt;/a&gt; and put the ISO on the flash drive.&lt;/p&gt;
&lt;p&gt;With a little luck and a little trial and error. We managed to boot from the USB. But kept getting &amp;ldquo;&lt;a href="https://www.reddit.com/r/techsupport/comments/7j4z5t/pogostick_ntpasswd_error_kernel_panic_not_syncing/"&gt;Kernel panic not syncing&lt;/a&gt;&amp;rdquo;. Even after trying all suggested work arounds.&lt;/p&gt;
&lt;p&gt;This took several hours of verbally instructing these options to try, rebooting trying again.. Flashing an older version.&lt;/p&gt;
&lt;p&gt;All with the same results.&lt;/p&gt;
&lt;p&gt;We had spent several hours by this point. The idea was even suggested that would make unscheduled trip to visit us. Given the price of gas though and how rough it was for them to travel.. I really didn&amp;rsquo;t want it to come to this.&lt;/p&gt;
&lt;p&gt;We decided to call it a night. Went to bed thinking how much easier it would be if I could just use my own eyes and hands. I&amp;rsquo;m a problem solver. I knew that if I was able to see it with my own eyes and use my own hands.. The whole try, process and iterate can happen &lt;strong&gt;a lot faster&lt;/strong&gt;!&lt;/p&gt;
&lt;h2 id="being-able-to-use-my-own-eyes-and-hands"&gt;Being able to use my own eyes and hands&lt;/h2&gt;
&lt;p&gt;Sounds a bit cliché.. But it hit me in the shower Tuesday morning.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve made livecd&amp;rsquo;s before&amp;hellip; What if I could have a livecd like the one we had tried.. but based on a more versital distro like Ubuntu. Ubuntu typically boots up on just works about any hardware.&lt;/p&gt;
&lt;p&gt;While i&amp;rsquo;m at it, what if it connected back to me so I could run commands my self? With linux at my hands.. I knew we could get it resolved.&lt;/p&gt;
&lt;h3 id="connect-back-to-me"&gt;Connect back to me?&lt;/h3&gt;
&lt;p&gt;Turns out this is actually extremely easy.&lt;/p&gt;
&lt;p&gt;With ssh you can expose a local port remotely with a command like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ssh -i ~/path-to-ssh-key -R 4022:localhost:22 -N user@my-vps
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It uses an ssh key and expose port 22 on the remote host on port 4022.&lt;/p&gt;
&lt;h3 id="creating-your-own-livecd"&gt;Creating your own livecd?&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;ll save you from some of the discovery. There are many ways to create linux livecds. A few of even with a GUI.&lt;/p&gt;
&lt;p&gt;But, I wanted a way to do it quickly and repeatable with out having to use a GUI.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve made some before manually but not very repeatable as it was always manually editing the squashfs and chrooting in and poking around.&lt;/p&gt;
&lt;p&gt;I found this guide great example of loading a livecd as a docker image and then using docker to modify it&lt;/p&gt;
&lt;p&gt;&lt;a href="https://slai.github.io/posts/customising-ubuntu-live-isos-with-docker/"&gt;https://slai.github.io/posts/customising-ubuntu-live-isos-with-docker/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Perfect!&lt;/p&gt;
&lt;h3 id="lets-make-it"&gt;Lets make it!&lt;/h3&gt;
&lt;p&gt;The important aspects of the livecd would be:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Lighter weight - Ubuntu Server would be the base.&lt;/li&gt;
&lt;li&gt;Automatically connect to the internet&lt;/li&gt;
&lt;li&gt;Automatically run the ssh tunnel back to me&lt;/li&gt;
&lt;li&gt;Automatically reconnect the ssh tunnel if disconnected&lt;/li&gt;
&lt;li&gt;Have some preinstalled tools
&lt;ul&gt;
&lt;li&gt;ntfs - i&amp;rsquo;d need to mount that partition&lt;/li&gt;
&lt;li&gt;ssh server - of course&lt;/li&gt;
&lt;li&gt;chntpw - most importantly in this case the tool we discovered thanks to the previous day that could modify the registry&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Baked ssh keys for bi-directional communciation&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Nice to have:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Don&amp;rsquo;t start up the installer it would be confusing&lt;/li&gt;
&lt;li&gt;Customize boot menu so it doesn&amp;rsquo;t say &amp;ldquo;Install Ubuntu Server&amp;rdquo;&lt;/li&gt;
&lt;li&gt;Include some text above the login prompt to communicate to the user&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For more technical details see this github repo: &lt;a href="https://github.com/geekgonecrazy/remote-recover-livecd"&gt;https://github.com/geekgonecrazy/remote-recover-livecd&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I set about building after my work day ended.&lt;/p&gt;
&lt;h3 id="attack-of-the-remote-desktop-tooling"&gt;Attack of the remote desktop tooling&lt;/h3&gt;
&lt;p&gt;It came time to load the iso up on the USB drive.&lt;/p&gt;
&lt;p&gt;Teamviewer showed its true colors.&lt;/p&gt;
&lt;p&gt;They apparently decided since I needed to remote in two days in a row.. that I was exhibiting signs of commercial use.&lt;/p&gt;
&lt;p&gt;Meaning apparently they start being extremely aggressive. My first session of the evening was barely open and then abruptly ended. I tried connecting again and it said something like: You can&amp;rsquo;t reconnect again so soon try again at: 17:55.&lt;/p&gt;
&lt;p&gt;I waited until then and it showed another saying try again at 17:56. I guess a clock is off somewhere or the error time frame was wrong? It ended up being at least 5 minutes before could connect.&lt;/p&gt;
&lt;p&gt;Here begun that pattern of wait 5 minutes.. Scramble to work for 1 minute before getting the session ripped away from me.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Extremely frustrating!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I did debate paying them. But appears they don&amp;rsquo;t sell monthly.. so I&amp;rsquo;d have to shell out $400+ just to ocassionally use it to help out family. Nope.. Sorry.&lt;/p&gt;
&lt;p&gt;I went shopping for another tool. Even if I had to pay for it surely there is something better out there.&lt;/p&gt;
&lt;p&gt;I &lt;a href="https://fosstodon.org/@geekgonecrazy/108478535293237696"&gt;posted about this frustration on mastodon&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Big thanks to @amolith@nixnet.social for the suggestion&lt;/p&gt;
&lt;p&gt;&lt;img src="https://user-images.githubusercontent.com/51996/174218187-0463babe-38af-4f3f-bf24-5eea9cfd5b30.png" alt="" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://rustdesk.com"&gt;Rustdesk&lt;/a&gt; was perfect!&lt;/p&gt;
&lt;p&gt;30 minutes or so later&amp;hellip; Thanks teamviewer.. I had rustdesk installed and was able to move forward.&lt;/p&gt;
&lt;p&gt;If you are using teamviewer I highly recommend switching to RustDesk. You can even self host the server portion if you want.&lt;/p&gt;
&lt;p&gt;From there used Rufus to put on the USB and then had them plug ethernet into laptop along with the fresh USB.&lt;/p&gt;
&lt;p&gt;We booted.. and it didn&amp;rsquo;t connect back up.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://media.giphy.com/media/xT5LMzIK1AdZJ4cYW4/giphy.gif" alt="" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;We had to call it a night. This ended night 2.&lt;/p&gt;
&lt;h2 id="one-more-try"&gt;One more try&lt;/h2&gt;
&lt;p&gt;Wednesday came and I quickly realized it was netplan.. I think because I had removed the installer squashfs not thinking much about it.. It must have been initalizing a netplan file.&lt;/p&gt;
&lt;p&gt;At the end of the work day I made some changes and built the iso again. Quick rustdesk and rufus later&amp;hellip;&lt;/p&gt;
&lt;p&gt;USB inserted and there it was!&lt;/p&gt;
&lt;p&gt;I finally had access and the process could finally begin of resetting the password!&lt;/p&gt;
&lt;p&gt;10 minutes later the password was reset.&lt;/p&gt;
&lt;h2 id="that-was-a-lot"&gt;That was a lot&lt;/h2&gt;
&lt;p&gt;Yes it was! 3 days to reset a password. Just a bit crazy..&lt;/p&gt;
&lt;p&gt;But now I have a flash drive on site that if this ever happens again.. I can spin up my vps and have them insert the flash drive.&lt;/p&gt;
&lt;p&gt;So all in all.. Another tool for the tool belt. Definitely might be closer to earning the Crazy in Geek Gone Crazy. :smile:&lt;/p&gt;
&lt;h2 id="you-left-me-hanging-how-did-you-reset"&gt;You left me hanging how did you reset?&lt;/h2&gt;
&lt;p&gt;Ok if you want the last 10 minutes.. they went something like this.&lt;/p&gt;
&lt;p&gt;I mounted the hard drive with a quick:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mkdir /mnt/laptop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mount /dev/sda2 /mnt/laptop
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Using &lt;code&gt;fdisk -l&lt;/code&gt; to determine the drive and partition.&lt;/p&gt;
&lt;p&gt;Then:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cd /mnt/laptop/Windows/System32/config
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here is where all of the registry hive files are for windows.&lt;/p&gt;
&lt;p&gt;Now we use the chntpwd util we pre-installed&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chntpw –l SAM
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;From here you follow the prompts to reset the password. Or in my case I went the path of just blanking the password out.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://media.giphy.com/media/PqjTdvXImZQfcmTYEO/giphy.gif" alt="" loading="lazy"&gt;&lt;/p&gt;</description></item><item><title>Rocket.Chat and the Matrix Protocol</title><link>https://aaronogle.dev/2022/05/30/rocketchat-and-the-matrix-protocol/</link><pubDate>Mon, 30 May 2022 00:00:00 +0000</pubDate><guid>https://aaronogle.dev/2022/05/30/rocketchat-and-the-matrix-protocol/</guid><description>
&lt;p&gt;Rocket.Chat &lt;a href="https://rocket.chat/press-releases/rocket-chat-leverages-matrix-protocol-for-decentralized-and-interoperable-communications"&gt;now has federation support via the Matrix protocol&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This announcement is an exciting one to me. I&amp;rsquo;ve been working with Rocket.Chat since I found it almost 7 years ago. One of the things I recall from early on is the vision of being as ubiquitious as email. One of the beauties of email is not everyone is on the same domain or let alone even the same kind of mail server. Just all speaking the same language.&lt;/p&gt;
&lt;p&gt;Rocket.Chat being able to talk the Matrix Protocol to me is a start of it achieving that.&lt;/p&gt;
&lt;p&gt;It does this by registering as an AppService with a Matrix homeserver. This means Rocket.Chat is able to create users on the homeserver and then manage them. So when you opt to federate a room and invite a remote user using Matrix. Rocket.Chat creates your user on the homeserver and controls it as if they are one and the same user.&lt;/p&gt;
&lt;p&gt;tl;dr You can now talk to anyone speaking the Matrix Protocol from Rocket.Chat.&lt;/p&gt;
&lt;h1 id="how-to-setup-rocketchat-with-a-matrix-homeserver"&gt;How to setup Rocket.Chat with a Matrix homeserver&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Matrix support in Rocket.Chat is currently considered alpha. Expect things to break&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;This guide also uses Dendrite which is beta&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Video guide should you prefer that format:
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/oQhIH8kql9I?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;h2 id="compute-requirements"&gt;Compute Requirements&lt;/h2&gt;
&lt;p&gt;If your Rocket.Chat workspace will only support a few users you can generally get away with a machine like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;2GB of RAM&lt;/li&gt;
&lt;li&gt;2CPU&lt;/li&gt;
&lt;li&gt;20GB of Storage&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you start using it more heavily you&amp;rsquo;ll probably want to increase to a couple of CPU and more ram. See the &lt;a href="https://docs.rocket.chat"&gt;Rocket.Chat Documentation&lt;/a&gt; for more details.&lt;/p&gt;
&lt;p&gt;In this case i&amp;rsquo;ve selected this digitalocean droplet:
&lt;!-- raw HTML omitted --&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve also selected Ubuntu 20.04 as the distro.&lt;/p&gt;
&lt;h2 id="domain-requirements"&gt;Domain Requirements&lt;/h2&gt;
&lt;p&gt;You&amp;rsquo;ll need a domain you control. In this case i&amp;rsquo;m going to use geekgone.dev.&lt;/p&gt;
&lt;p&gt;For federation generally the idea is that you are accessed much like you are by email.&lt;br&gt;
So if I was to be reached at aaron [at] geekgone.dev then I would also be reached at @aaron:geekgone.dev.&lt;/p&gt;
&lt;p&gt;Either way you need to decide what domain will you be reached at? We&amp;rsquo;ll call this the federated domain. Then you&amp;rsquo;ll also need to expose matrix and Rocket.Chat on their perspective domains.&lt;/p&gt;
&lt;p&gt;In my case i&amp;rsquo;m going to use:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Federated Domain: geekgone.dev&lt;/li&gt;
&lt;li&gt;Rocket.Chat Domain: chat.geekgone.dev&lt;/li&gt;
&lt;li&gt;Matrix Domain: matrix.geekgone.dev&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Go ahead and point those all at the machine you&amp;rsquo;ve provisioned.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://user-images.githubusercontent.com/51996/170783824-d8afd20a-2aae-4dd2-8ce6-9b1173eb45d8.png" alt="image" loading="lazy"&gt;&lt;/p&gt;
&lt;h2 id="install-some-pre-reqs"&gt;Install some pre-reqs&lt;/h2&gt;
&lt;p&gt;We need a reverse proxy. I&amp;rsquo;m going to use nginx:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt update &amp;amp;&amp;amp; sudo apt install -y nginx
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we need docker:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -fsSL https://get.docker.com -o get-docker.sh
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sh get-docker.sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now for ease we&amp;rsquo;ll add our self to the docker group and assume it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo usermod -a -G docker ubuntu
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;newgrp docker
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Finally we need certbot. This is one of the quickest and easiest way to install it currently:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo snap install --classic certbot
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="configure-lets-encrypt-certificates"&gt;Configure Lets Encrypt Certificates&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;certbot certonly --nginx -d geekgone.dev,chat.geekgone.dev,matrix.geekgone.dev
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="setup-nginx-rules"&gt;Setup Nginx Rules&lt;/h2&gt;
&lt;p&gt;Edit /etc/nginx/sites-available/default&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;listen&lt;/span&gt; &lt;span class="p"&gt;[::]:&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;geekgone&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//$&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;request_uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;geekgone&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//$&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;request_uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;matrix&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;geekgone&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//$&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;request_uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;server_name&lt;/span&gt; &lt;span class="n"&gt;matrix&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;geekgone&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; &lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;geekgone&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; &lt;span class="n"&gt;geekgone&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="n"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ssl_certificate&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;letsencrypt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;live&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;geekgone&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;fullchain&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ssl_certificate_key&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;letsencrypt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;live&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;geekgone&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;privkey&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;include&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;letsencrypt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ssl&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;nginx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ssl_dhparam&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;letsencrypt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ssl&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dhparams&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;www&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;server_name&lt;/span&gt; &lt;span class="n"&gt;geekgone&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;location&lt;/span&gt; &lt;span class="o"&gt;/.&lt;/span&gt;&lt;span class="n"&gt;well&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;known&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;matrix&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_set_header&lt;/span&gt; &lt;span class="n"&gt;Host&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_set_header&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Real&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ne"&gt;IP&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_set_header&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Forwarded&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;For&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_set_header&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Forwarded&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Proto&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;scheme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_pass&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;localhost&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8008&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_read_timeout&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="n"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ssl_certificate&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;letsencrypt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;live&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;geekgone&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;fullchain&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ssl_certificate_key&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;letsencrypt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;live&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;geekgone&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;privkey&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;include&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;letsencrypt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ssl&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;nginx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ssl_dhparam&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;letsencrypt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ssl&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dhparams&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;www&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;server_name&lt;/span&gt; &lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;geekgone&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;location&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_set_header&lt;/span&gt; &lt;span class="n"&gt;Host&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_set_header&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Real&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ne"&gt;IP&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_set_header&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Forwarded&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;For&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_set_header&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Forwarded&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Proto&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;scheme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_pass&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;localhost&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_read_timeout&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="n"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ssl_certificate&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;letsencrypt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;live&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;geekgone&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;fullchain&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ssl_certificate_key&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;letsencrypt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;live&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;geekgone&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;privkey&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;include&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;letsencrypt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ssl&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;nginx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ssl_dhparam&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;letsencrypt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ssl&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dhparams&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;www&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;server_name&lt;/span&gt; &lt;span class="n"&gt;matrix&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;geekgone&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;location&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_set_header&lt;/span&gt; &lt;span class="n"&gt;Host&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_set_header&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Real&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ne"&gt;IP&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_set_header&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Forwarded&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;For&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_set_header&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Forwarded&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Proto&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;scheme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_pass&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;localhost&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8008&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_read_timeout&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Do a &lt;code&gt;nginx -t&lt;/code&gt; just to make sure everything is ok.&lt;/p&gt;
&lt;p&gt;Then:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;systemctl&lt;/span&gt; &lt;span class="n"&gt;reload&lt;/span&gt; &lt;span class="n"&gt;nginx&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="install-rocketchat-and-dendrite"&gt;Install Rocket.Chat and Dendrite&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve commited a docker-compose and config file in a public repo. So will start off with grabbing that:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git clone https://github.com/geekgonecrazy/rocketchat-matrix-federation-example.git matrix
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cd matrix
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Lets bring Rocket.Chat up:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker compose up -d rocketchat mongo mongo-init-replica
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Goto your Rocket.Chat install and finish the initial setup. In my case it was available at &lt;a href="https://chat.geekgone.dev"&gt;https://chat.geekgone.dev&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now goto: Admin-&amp;gt;Settings-&amp;gt;Federation and expand the Matrix Bridge section&lt;/p&gt;
&lt;p&gt;In the Homeserver URL section use:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;http://dendrite:8008
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the Homeserver Domain use your federation domain. In my case:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;geekgone.dev
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now flip to enabled and click save changes.&lt;/p&gt;
&lt;p&gt;Grab the Homeserver Token and the AppService Token and put them some place safe for a moment.&lt;/p&gt;
&lt;p&gt;Rocket.Chat is ready. Now lets go back to the terminal and look at dendrite.&lt;/p&gt;
&lt;p&gt;We need to edit the dendrite config file. Edit: &lt;code&gt;config/dendrite.yaml&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Replace geekgone.dev in this section with your federation domain:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;global:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # The domain name of this homeserver.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; server_name: geekgone.dev
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Replace matrix.geekgone.dev in this section with your matrix domain:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # The server name to delegate server-server communications to, with optional port
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # e.g. localhost:443
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; well_known_server_name: &amp;#34;matrix.geekgone.dev:443&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we need to edit: &lt;code&gt;config/rocketchat-registration.yaml&lt;/code&gt;
Replace: &lt;code&gt;hs_token&lt;/code&gt; value with the Homeserver Token you got from Rocket.Chat
Replace: &lt;code&gt;as_token&lt;/code&gt; value with the AppService Token you got from Rocket.Chat&lt;/p&gt;
&lt;p&gt;Finally now we can start matrix up:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker compose up -d dendrite
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="lets-try-talking-to-another-matrix-homeserver"&gt;Lets try talking to another Matrix Homeserver&lt;/h2&gt;
&lt;p&gt;Now that we have dendrite up and Rocket.Chat up. Lets go into Rocket.Chat and try sending a message out to a user on another server out there speaking the Matrix Protocol. Can be another Rocket.Chat server, dendrite, synapse etc.&lt;/p&gt;
&lt;p&gt;In this case i&amp;rsquo;m going to use an account from matrix.org &lt;a href="https://matrix.to/#/@geekgonedev-demo:matrix.org"&gt;@geekgonedev-demo:matrix.org&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Create a channel in Rocket.Chat and then do: &lt;code&gt;/bridge invite @geekgonedev-demo:matrix.org&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The client you have connected on the other server you will receive an invite. Once accepted you can now type a message on either side and if all went well you should receive the message on the other side!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note: if you invite another Rocket.Chat server it currently will auto accept&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll leave the server up for a couple of weeks if you want to try reaching me at &lt;a href="https://matrix.to/#/@aaron:geekgone.dev"&gt;@aaron:geekgone.dev&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Happy chatting!&lt;/p&gt;</description></item><item><title>Rover Project: Update 3</title><link>https://aaronogle.dev/2021/07/04/rover-project-update-3/</link><pubDate>Sun, 04 Jul 2021 00:03:00 +0000</pubDate><guid>https://aaronogle.dev/2021/07/04/rover-project-update-3/</guid><description>
&lt;p&gt;Finally a more eventful update!&lt;/p&gt;
&lt;p&gt;Last time I worked with building parts in CAD I was using solidworks or AutoCAD. I have no desire to buy either one of those right now plus I need something that will run on linux. So started investing some time into learning my way around FreeCAD.&lt;/p&gt;
&lt;p&gt;Creating first iteration of the wheel
&lt;img src="/images/2021-07-04/wheel-1-freecad.png" alt="" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;50mm radius for a 10cm/100mm diameter wheel&lt;/p&gt;
&lt;p&gt;3mm thick&lt;/p&gt;
&lt;p&gt;Based on the specs of the motor:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Features:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Rated voltage: DC 3V
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Rated speed: 15000 RPM
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Motor size: 38 x 20 x 15 mm/1.5&amp;#34; x 0.8&amp;#34; x 0.6&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Shaft diameter: 2 mm/0.08&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Shaft length: 10 mm/0.4&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Material: metal
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The hole is 1mm radius for a 2mm diameter hole&lt;/p&gt;
&lt;p&gt;Print time was going to take 2 hours and 9 minutes. So time to reduce some material because we don&amp;rsquo;t want to wait that long&lt;/p&gt;
&lt;p&gt;&lt;img src="/images/2021-07-04/wheel-2-freecad.png" alt="" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;This takes it down to 1 hour 21 minutes&lt;/p&gt;
&lt;p&gt;After lots of wrestling with bed leveling and things not sticking..
&lt;img src="/images/2021-07-04/wheel-2-printing.jpg" alt="" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;While this printed we started looking at how we want the body to look. Designing a caster for the 3 wheeled robot we realized was a little harder then we really wanted. Plus we were inspired by a rover&amp;hellip; so we are leaning towards a 4 wheel design with a box to house the brain in&amp;hellip; and surface area on top for mounting things in the future&lt;/p&gt;
&lt;p&gt;&lt;img src="https://i.imgur.com/rz8tl0g.png" alt="" loading="lazy"&gt;
&lt;a href="https://www.google.com/url?sa=i&amp;amp;url=https%3A%2F%2Fwww.iconfinder.com%2Ficons%2F3319875%2Fisolated_robot_robotic_rover_space_icon&amp;amp;psig=AOvVaw2DQonss07C0LenXgaGbjZn&amp;amp;ust=1619650814026000&amp;amp;source=images&amp;amp;cd=vfe&amp;amp;ved=0CAIQjRxqFwoTCMjnvs3Dn_ACFQAAAAAdAAAAABAN"&gt;source&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The wheel finished printing!&lt;/p&gt;
&lt;p&gt;&lt;img src="/images/2021-07-04/wheel-2-finished.jpg" alt="" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;So&amp;hellip; we had to try it!&lt;/p&gt;
&lt;p&gt;&lt;img src="/images/2021-07-04/wheel-spinning.gif" alt="" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;Woot!&lt;/p&gt;
&lt;p&gt;Queue the other wheels!&lt;/p&gt;
&lt;p&gt;While we waited did a bit of soldering and put antennas on the 433mhz chips&lt;/p&gt;
&lt;p&gt;&lt;img src="/images/2021-07-04/soldering-433-antenna.jpg" alt="" loading="lazy"&gt;
&lt;img src="/images/2021-07-04/433-soldered.jpg" alt="" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;Then set about figuring out basic programs and getting everything hooked up to breadboards.&lt;/p&gt;
&lt;p&gt;Got the L239D H-Bridge working doing speed control.&lt;/p&gt;
&lt;p&gt;Then after a long period of debugging&amp;hellip; finally got the 433mhz transmitter and receiver talking. Ended up getting it working with the virtualwire library.&lt;/p&gt;
&lt;p&gt;&lt;img src="/images/2021-07-04/workbench-with-basic-electronics-working.jpg" alt="" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;Next step get the chassis designed and printed!&lt;/p&gt;</description></item><item><title>Rover Project: Update 2</title><link>https://aaronogle.dev/2021/07/04/rover-project-update-2/</link><pubDate>Sun, 04 Jul 2021 00:02:00 +0000</pubDate><guid>https://aaronogle.dev/2021/07/04/rover-project-update-2/</guid><description>
&lt;p&gt;So the robot parts sat in my closet for a few months. I kind of forgot to order the parts.&lt;/p&gt;
&lt;p&gt;Recently realized I really need to disconnect more fully from work in my off hours. When your hobby includes coding and in same language as you write for work.. Its a bit harder to keep your brain from making that jump to thinking about work.&lt;/p&gt;
&lt;p&gt;So i&amp;rsquo;ve been on the look out for new hobbies.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t recall where, but I saw someone making something with a 3D printer. Made me wonder how much they were now days. After some research I realized some where actually extremely affordable. After even more research.. I was able to determine that at least a couple of those affordable printers actually were decent.&lt;/p&gt;
&lt;p&gt;The possibilities to prototype things seem endless. Not to mention.. I actually spent the first 2 years of my post highschool schooling at a VoTech school learning CAD. So this is perfect! Those 12+ year old skill can actually be put to use. I say that. But really i&amp;rsquo;ve identified lots of areas that those skills actually have helped me out in how I approach problems. But still.. To actually to use CAD.&lt;/p&gt;
&lt;p&gt;So I bought a 3d printer.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve already printed kids items and been praised as it being a great decision by my kids. Even my wife had me print several things for her baking projects.&lt;/p&gt;
&lt;p&gt;The purchase of the 3D printer has me inspired to push forward with the robot project. Being able to draw up in CAD and print the wheels and chassis will help greatly in moving this foward.&lt;/p&gt;
&lt;p&gt;Time to pick up where we left off.&lt;/p&gt;
&lt;p&gt;When it got shelved we had realized we had the wrong motors and controllers. So first we need to correct that.&lt;/p&gt;
&lt;p&gt;We needed a controller. From reading around looks like this is called an H-Bridge.&lt;/p&gt;
&lt;p&gt;I found a couple of examples using the &lt;code&gt;L293D&lt;/code&gt; seemed like a low cost chip that didn&amp;rsquo;t need a lot of additional components to work with. Also found this great write up about the chip set:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://maker.pro/custom/projects/all-you-need-to-know-about-l293d"&gt;https://maker.pro/custom/projects/all-you-need-to-know-about-l293d&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;So picked up a few of those from Amazon.&lt;/p&gt;
&lt;p&gt;Now we&amp;rsquo;ve got to find some DC motors. This might be a point i&amp;rsquo;ll have to iterate on. But as long as I can power them and they will move I think we will be good. Ordered a pack of DC Motor 1.5V-3V 15000RPM.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/gp/product/B07JYM8H18/ref=ppx_yo_dt_b_asin_title_o01_s01?ie=UTF8&amp;amp;psc=1"&gt;https://www.amazon.com/gp/product/B07JYM8H18/ref=ppx_yo_dt_b_asin_title_o01_s01?ie=UTF8&amp;amp;psc=1&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not 100% positive on these.. But looks like operates between 1.5-6V. Also claims 3 hours running on 2 x 1.5V AA batteries. So with 4 and other components maybe we can get at least 30 minutes?&lt;/p&gt;
&lt;p&gt;A couple of articles I found on working with this H-Bridge:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dumblebots.com/2019/09/29/controlling-motors-with-arduino-and-h-bridges/"&gt;https://dumblebots.com/2019/09/29/controlling-motors-with-arduino-and-h-bridges/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bc-robotics.com/tutorials/controlling-dc-motor-arduino/"&gt;https://bc-robotics.com/tutorials/controlling-dc-motor-arduino/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://maker.pro/custom/projects/all-you-need-to-know-about-l293d"&gt;https://maker.pro/custom/projects/all-you-need-to-know-about-l293d&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now to wait on these parts to arrive. Plus some tools needed to build out my electronics work area. Has been pretty barebones since Harvey. Time to fix that :)&lt;/p&gt;</description></item><item><title>Rover Project: Update 1</title><link>https://aaronogle.dev/2021/07/04/rover-project-update-1/</link><pubDate>Sun, 04 Jul 2021 00:01:00 +0000</pubDate><guid>https://aaronogle.dev/2021/07/04/rover-project-update-1/</guid><description>
&lt;p&gt;Parts came in!&lt;/p&gt;
&lt;p&gt;&lt;img src="/images/2021-07-04/parts-1.jpg" alt="" loading="lazy"&gt;
&lt;img src="/images/2021-07-04/parts-2.jpg" alt="" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;Finally got time to work on it again. We wired everything up.&lt;/p&gt;
&lt;p&gt;&lt;img src="/images/2021-07-04/parts-hookup-1.jpg" alt="" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;We gathered up some cardboard. We found something to trace and cut out 4 wheels. (you&amp;rsquo;ll notice this is defintely a deviation from the original sketch. But this was insisted on once the additional motors were spotted).&lt;/p&gt;
&lt;p&gt;&lt;img src="/images/2021-07-04/parts-hookup-2.jpg" alt="" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;We also put together the transmitter on another breadboard&lt;/p&gt;
&lt;p&gt;&lt;img src="/images/2021-07-04/parts-hookup-3.jpg" alt="" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;Now if you do electronics seriously at all you&amp;rsquo;ll probably notice straight away two different issues. I was tempted to omit it and just have the build log with final parts.. But this is part of the journey. I think it was important for kids to go through as well. Not everything works first time around. In fact probably doesn&amp;rsquo;t most of the time.&lt;/p&gt;
&lt;p&gt;Issue 1: Those are stepper motors and drivers. 🙈 Yeah.. I don&amp;rsquo;t even know how I did that. I did place the order late.. but I even have some articles stashed away specifically for working with those drivers. So its not like I didn&amp;rsquo;t research the parts. We&amp;rsquo;ll chock it up to lesson learned though.&lt;/p&gt;
&lt;p&gt;Issue 2: Those 433Mhz Transmitter / Receivers don&amp;rsquo;t have even their basic included antenna&amp;rsquo;s soldered on. Reading later.. with out an antenna range is like a few centemeters.&lt;/p&gt;
&lt;p&gt;Needless to say we discovered both of these issues after several hours. I pretty quickly wrote up the arduino code for both. I wrote the code that would send a simple signal that would include a signal for both the left and the right side tank style.&lt;/p&gt;
&lt;p&gt;My Plan was:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Forward: 01 FF 01FF&lt;/li&gt;
&lt;li&gt;Backward: 02 FF 02 FF&lt;/li&gt;
&lt;li&gt;Forward Left: 01 FF 01 99&lt;/li&gt;
&lt;li&gt;Forward Right: 01 99 01 FF&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pattern being: {Left Motor Polarity} {Left Motor Speed} {Right Motor Polarity} {Right Motor Speed}&lt;/p&gt;
&lt;p&gt;With the speed being 0-255 represented in hex. No CRC or anything at first.&lt;/p&gt;
&lt;p&gt;This didn&amp;rsquo;t work.&lt;/p&gt;
&lt;p&gt;So figured maybe I was being too clever and switch to transmitting strings and probably 10x variations.&lt;/p&gt;
&lt;p&gt;So after still not even a hum from the motors.. I figured it must be just something wrong with the 433Mhz pair. I wanted to at least validate the motors worked. So I found an example program for those motors show them working. It was here and getting this to work&amp;hellip; I realized these aren&amp;rsquo;t really the right motors for the wheels.&lt;/p&gt;
&lt;p&gt;So we shelved it until I could go and order the right motors.&lt;/p&gt;
&lt;p&gt;It wasn&amp;rsquo;t until later I actually realized I some how completely spazzed on putting antenna&amp;rsquo;s on and their range was only centimeters with out one.&lt;/p&gt;</description></item><item><title>Rover Project</title><link>https://aaronogle.dev/2021/07/04/rover-project/</link><pubDate>Sun, 04 Jul 2021 00:00:00 +0000</pubDate><guid>https://aaronogle.dev/2021/07/04/rover-project/</guid><description>
&lt;p&gt;My family is very STEM oriented. I grew up learning hands on at home. Taking things apart. Questioning how things worked and eventually learning how to actually fix those things I took apart. As much as possible we&amp;rsquo;re trying to encourage this for our kids.&lt;/p&gt;
&lt;p&gt;They are pretty fortunate as they have good examples of this on both sides of the family. So they come by their curiousity about the world around them very naturally. Now days its not surprising to get asked questions about things even we don&amp;rsquo;t know or remember the answer to.&lt;/p&gt;
&lt;p&gt;Not going to pretend some times the constant questions doesn&amp;rsquo;t get a little annoying. But just have to stop and appreciate the curiousity and help them learn more about the things they are actually curious about.&lt;/p&gt;
&lt;p&gt;Anyways we often watch Rocket Launches together. Now days thanks to the likes of SpaceX, Rocket Labs and even the old school ULA and others.. we frequently get to watch something launch.&lt;/p&gt;
&lt;p&gt;About a year ago on 07/30/2020 we watched the Mars Perseverance mission take off. This kicked off a flurry of questions.&lt;/p&gt;
&lt;p&gt;What is it launching? What is the rover? What does it do? How will it land? How does it work?&lt;/p&gt;
&lt;p&gt;Then after spending some time showing them and answering. I was left with one statement:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I wish kids like us could make robots&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I like making things.. and I used to help a highschool robotics team build their robot for competition every year. I really missed it. So really this was a win-win-win:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I get to teach my kids how to approach engineering problems as best I know how.&lt;/li&gt;
&lt;li&gt;They are really excited&lt;/li&gt;
&lt;li&gt;I get to work on building something too&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So off began the process!&lt;/p&gt;
&lt;h2 id="brainstorming"&gt;Brainstorming&lt;/h2&gt;
&lt;p&gt;So we started right off with brainstorming. During brainstorming we came up with a quick sketch of some that it could look like:&lt;/p&gt;
&lt;p&gt;&lt;img src="/images/2021-07-04/rover-sketch-1.png" alt="" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;A couple of things to note:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;There is an arm&lt;/li&gt;
&lt;li&gt;In the left corner there is a tablet controlling&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We&amp;rsquo;re considering these stretch goals. We agreed that the first priority was getting a basic robot built.&lt;/p&gt;
&lt;p&gt;But through brainstorming we identified the main pieces that will be needed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;2 motors to drive the wheels&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;2 wheels&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A base to act as chassis and to put the electronics on&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Transmitter / Receiver&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Bread boards - I didn’t have any more.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Batteries&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A brain - some sort of microcontroller&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We also identified that we would need some buttons and a way to control. So we needed some buttons.&lt;/p&gt;
&lt;p&gt;We weren’t too certain on the construction of it. We figured maybe CD’s would make ok wheels. We’ve seen robots with CD wheels. Also we have plenty of cardboard. Might work as a prototype.&lt;/p&gt;
&lt;p&gt;I tried to involve the kids as much as possible on the research behind the parts to choose. But this part quickly bored them. So I went off and spent a few hours that evening locating all of the parts.&lt;/p&gt;
&lt;p&gt;Landed on using the Ardunio Nano. This is mostly because info for arduino is a lot easier to come by. I don’t want to waste too much time on the code portion. I want to be able to explain and the kids be able to follow along with the code and how it works.&lt;/p&gt;
&lt;p&gt;For the batteries I’m a noob on batteries. I didn’t want to go off and order some rechargable battery and it be wrong for our circuit. From what I could tell for the Arduino nano everything seemed to be 1.5V compatible so just picked up battery pack to put AA batteries in.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Motors… I’m writing this in retrospect… so I don’t really know why I ended up purchasing stepper motors and the controllers. Its of course not a waste… But it did delay the project.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Parts Ordered:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/gp/product/B087B5NWY4/ref=ppx_yo_dt_b_asin_title_o03_s03?ie=UTF8&amp;amp;psc=1"&gt;Motors&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/gp/product/B07G99NNXL/ref=ppx_yo_dt_b_asin_title_o03_s01?ie=UTF8&amp;amp;psc=1"&gt;Arduino Nano&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/gp/product/B086ZL8W1W/ref=ppx_yo_dt_b_asin_title_o03_s00?ie=UTF8&amp;amp;psc=1"&gt;433Mhz Transmitter / Receivers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/gp/product/B07C6T6YCZ/ref=ppx_yo_dt_b_asin_title_o03_s00?ie=UTF8&amp;amp;psc=1"&gt;AA Battery box&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now we waited on the parts to arrive.&lt;/p&gt;</description></item><item><title>OVH Serial over LAN (SOL)</title><link>https://aaronogle.dev/2020/09/07/ovh-serial-over-lan-sol/</link><pubDate>Mon, 07 Sep 2020 00:00:00 +0000</pubDate><guid>https://aaronogle.dev/2020/09/07/ovh-serial-over-lan-sol/</guid><description>
&lt;p&gt;Its been a while since I&amp;rsquo;ve worked with physical servers and typically when something happened I could pretty quickly get physical access to the box if things went pear shaped.&lt;/p&gt;
&lt;p&gt;But when you buy or lease servers from a provider like OVH. Those servers might be sitting half way around the world. So if something goes wrong you need to some how virtually be in front of the keyboard.&lt;/p&gt;
&lt;p&gt;OVH has a few different ways to access your servers console to interact with the machine directly.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;From a Java applet (KVM)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This way while works across all of the servers.. requires Java Runtime.. Yuck. Not to mention it isn&amp;rsquo;t necessarily going to work on every machine.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Via your web browser (KVM)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This way is by far the best. But seems for some reason, i&amp;rsquo;m not completely sure why.. its not available for all of their servers. So its not really a consistent option&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Serial over LAN (SOL)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This way is probably the most easy to work with. Can access over ssh from any device that can ssh. Which is pretty much anywhere, so very appealing.&lt;/p&gt;
&lt;p&gt;So I really wanted to be able to get Serial over LAN working.&lt;/p&gt;
&lt;h2 id="the-problem"&gt;The Problem&lt;/h2&gt;
&lt;hr&gt;
&lt;p&gt;Out of the box when you connect all you get is:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; Could not chdir to home directory /home/ipmi: No such file or directory
OVH
IPMI Serial Over Lan gateway
IPMI SOL on [Omitted ;-)].us
ipmiutil ver 2.93
isol ver 2.93
Opening lan connection to node 10.245.29.163 ...
Connecting to node 10.245.29.163
-- BMC version 2.00, IPMI version 2.0
Opening lanplus connection to node 10.245.29.163 ...
[SOL session is running, use '~.' to end, '~?' for help.]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hitting enter here should drop you to a login prompt to login to the console. But nothing happens. Turns out this is because out of the box on OVH the linux kernel isn&amp;rsquo;t outputting or opening a tty on the serial port.&lt;/p&gt;
&lt;h2 id="solution"&gt;Solution&lt;/h2&gt;
&lt;p&gt;To make the linux kernel output console output and open a tty on the serial port as needed by Serial Over Lan you need to ssh into your server and modify your grub settings to instruct the kernel to open a tty on that serial port. Also to tell it the baud rate to use. The &lt;a href="https://wiki.archlinux.org/index.php/Working_with_the_serial_console"&gt;arch wiki&lt;/a&gt; is useful here.&lt;/p&gt;
&lt;p&gt;From what I can tell this is typically /dev/ttyS1. But if it doesn&amp;rsquo;t work for you try /dev/ttyS0.&lt;/p&gt;
&lt;p&gt;In the bios you can confirm the baud/bit rate. But in my case it was: 115200 and looking around that seems to be the most common.&lt;/p&gt;
&lt;p&gt;First hop into: /etc/default/grub&lt;/p&gt;
&lt;p&gt;and add:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; GRUB_CMDLINE_LINUX_DEFAULT=&amp;quot;nomodeset console=tty0 console=ttyS1,115200&amp;quot;
GRUB_TERMINAL=&amp;quot;console serial&amp;quot;
GRUB_SERIAL_COMMAND=&amp;quot;serial --unit=1 --speed=115200 --word=8 --parity=no --stop=1&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will both set the default linux command args, but also will let you interract with grub over the serial console as well.&lt;/p&gt;
&lt;p&gt;To make sure takes effect:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; sudo update-grub
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you want to verify take a peak in /boot/grub/grub.cfg and see if the kernel options are there.&lt;/p&gt;
&lt;p&gt;If you would like to also be able to interact with bios and everything after POST you can also hop into bios via one of the KVM solutions and set this setting to enabled:&lt;/p&gt;
&lt;p&gt;&lt;img src="/images/2020-09-07/screen-shot-2020-09-07-at-14-28-07.png" alt="" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="/images/2020-09-07/screen-shot-2020-09-07-at-14-29-20.png" alt="" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;I want to thank the author of this blog post for setting me on the right track: &lt;a href="http://divideoverflow.com/2016/07/Configuring_IPMI_on_OVH_server/"&gt;http://divideoverflow.com/2016/07/Configuring_IPMI_on_OVH_server/&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Tinkerbell or iPXE boot on OVH</title><link>https://aaronogle.dev/2020/09/07/tinkerbell-or-ipxe-boot-on-ovh/</link><pubDate>Mon, 07 Sep 2020 00:00:00 +0000</pubDate><guid>https://aaronogle.dev/2020/09/07/tinkerbell-or-ipxe-boot-on-ovh/</guid><description>
&lt;p&gt;Recently have had to work with a number of physical servers that need to be treated more cattle like than a bunch of pets. I need to be able to quickly and easily provision servers to fit a specific role with out having to go through a complicated setup process.&lt;/p&gt;
&lt;p&gt;For this type of thing PXE or iPXE comes to the rescue. Allowing you to boot over the network. Simply rebooting the machine and then having it pick up its instructions and be provisioned like needed.&lt;/p&gt;
&lt;h2 id="tinkerbell"&gt;Tinkerbell&lt;/h2&gt;
&lt;p&gt;Because of this need a project called tinkerbell has come to my attention. Project website is: &lt;a href="https://tinkerbell.org"&gt;https://tinkerbell.org&lt;/a&gt;. Seems packet uses this or a variation of this inside of their infrastructure.&lt;/p&gt;
&lt;p&gt;Tinkerbell is made up of a few components:&lt;/p&gt;
&lt;h3 id="tink-server"&gt;tink-server&lt;/h3&gt;
&lt;p&gt;This provides the state. It is made up of:&lt;/p&gt;
&lt;h4 id="templates"&gt;templates&lt;/h4&gt;
&lt;p&gt;Templates have a series of actions that are docker images to be ran.&lt;/p&gt;
&lt;h4 id="hardware"&gt;hardware&lt;/h4&gt;
&lt;p&gt;This is a json representation of the machine, metadata, nics with their interface definition ip/mac address.&lt;/p&gt;
&lt;h4 id="workflows"&gt;workflows&lt;/h4&gt;
&lt;p&gt;Workflows are essentially just a job. A match up of hardware and template for it to run. The state is updated as the job runs.&lt;/p&gt;
&lt;h3 id="boots"&gt;boots&lt;/h3&gt;
&lt;p&gt;This provides dhcp and the ipxe script to the server so it can boot. When it receives a request from the server for an ip, it talks to tink-server to find a record of that hardware. If it finds it then it returns it the ip given to it in the hardware definition and returns the ipxe script based on info from that hardware template.&lt;/p&gt;
&lt;h3 id="osie"&gt;osie&lt;/h3&gt;
&lt;p&gt;When boots gives the server an image to boot it gives it the osie image. When this image boots up. It has tink-worker. Tink worker talks back to tink-server to fetch any workflows meant for this device. It then runs these workflows in series of docker containers. So you can package all of your scripts/dependencies in a nice neat docker container.&lt;/p&gt;
&lt;h3 id="hegel"&gt;hegel&lt;/h3&gt;
&lt;p&gt;Hegel seems to mostly just be a tiny little service sitting over tink-server to return to the server its metadata. Pretty much like you are probably familar with if you&amp;rsquo;ve used AWS. The metadata service.&lt;/p&gt;
&lt;h2 id="setting-up-tinkerbell"&gt;Setting up tinkerbell&lt;/h2&gt;
&lt;p&gt;The easiest way to get started on your local machine is to goto: &lt;a href="https://tinkerbell.org/docs/setup/local-with-vagrant/" title="https://tinkerbell.org/docs/setup/local-with-vagrant/"&gt;https://tinkerbell.org/docs/setup/local-with-vagrant/&lt;/a&gt; and get started with their vagrant stack.&lt;/p&gt;
&lt;p&gt;Of course if you are going to be running in OVH.. This won&amp;rsquo;t really be an option.&lt;/p&gt;
&lt;h3 id="pre-reqs"&gt;Pre-reqs&lt;/h3&gt;
&lt;p&gt;So first off you need a couple of things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A place to run tinkerbell. I personally had a proxmox setup for little VM&amp;rsquo;s on a couple of baremetal machines. But if I didn&amp;rsquo;t I would run a sandbox VM on the public cloud.&lt;/li&gt;
&lt;li&gt;A machine you want to boot over the network&lt;/li&gt;
&lt;li&gt;A vRack. You&amp;rsquo;re going to want a private network to conduct your experiment on.&lt;/li&gt;
&lt;li&gt;Your machines connected to that vRack. Make sure you don&amp;rsquo;t turn on dhcp on that vRack doing public cloud.&lt;/li&gt;
&lt;li&gt;An ip range selected. Personally I tend to over provision: 10.1.0.0/16&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="install-tinkerbell-machine"&gt;Install tinkerbell machine&lt;/h3&gt;
&lt;p&gt;Their examples use ubuntu 18.04 so I also chose ubuntu 18.04. 20.04 seems to also work just fine.&lt;/p&gt;
&lt;p&gt;Once you have that we need to ssh in and start configuring tinkerbell.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; git clone https://github.com/tinkerbell/sandbox.git
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we need to hop in to the sandbox folder to start configuring:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; cd sandbox
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we need to generate the environment variables used for all of the rest of the configuration.&lt;/p&gt;
&lt;p&gt;Identify the interface attached to the private interface. You can use &lt;code&gt;ip addr&lt;/code&gt; and find the interface with no ip. Mine was ens18&lt;/p&gt;
&lt;p&gt;Then you need to run:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; ./generate-envrc.sh ens18 &amp;gt; envrc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then you need to edit the file output unless your network choice is 192.168.1.1/24 in which case you can leave alone&lt;/p&gt;
&lt;p&gt;If not you&amp;rsquo;ll need to change the following lines to two ips you wish to use:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; # Decide on a subnet for provisioning. Tinkerbell should &amp;quot;own&amp;quot; this
# network space. Its subnet should be just large enough to be able
# to provision your hardware.
export TINKERBELL_CIDR=16
# Host IP is used by provisioner to expose different services such as
# tink, boots, etc.
#
# The host IP should the first IP in the range, and the Nginx IP
# should be the second address.
export TINKERBELL_HOST_IP=10.0.5.1
# NGINX IP is used by provisioner to serve files required for iPXE boot
export TINKERBELL_NGINX_IP=10.0.5.2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now you need to load the environment variables into the current shell so we can continue executing.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; source ./envrc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now you need to run:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; ./setup.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once that finishes you will then be able to startup the components needed:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; cd deploy
docker-compose up -d
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you happen to come back and want to interact with the docker-compose in the future make sure to first load the &lt;code&gt;envrc&lt;/code&gt; file. If in the deploy folder can just do: &lt;code&gt;source ../envrc&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Wala the stack is up and running!&lt;/p&gt;
&lt;h3 id="tweak-boots-service"&gt;Tweak boots service&lt;/h3&gt;
&lt;p&gt;I hope to be able to replace this section. But at the time of this writing.. the boots service uses a command in the ipxe script called &amp;ldquo;params&amp;rdquo; which can be found here: &lt;a href="https://github.com/tinkerbell/boots/blob/1e1d60ac32bac18d9b3f1c07611cd3b3613ecec7/ipxe/script.go#L34"&gt;https://github.com/tinkerbell/boots/blob/1e1d60ac32bac18d9b3f1c07611cd3b3613ecec7/ipxe/script.go#L34&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In the version of ipxe my servers are running the param command causes things to error out. From what I can tell this just means that ipxe was built with out &lt;a href="https://ipxe.org/buildcfg/param_cmd"&gt;PARAM_CMD&lt;/a&gt; build option. But since these are OVH servers there isn&amp;rsquo;t really anything I can do to ensure its added.&lt;/p&gt;
&lt;p&gt;You can track this issue here: &lt;a href="https://github.com/tinkerbell/boots/issues/78"&gt;https://github.com/tinkerbell/boots/issues/78&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To make it work on OVH first follow pre-reqs listed here: &lt;a href="https://github.com/tinkerbell/boots/tree/1e1d60ac32bac18d9b3f1c07611cd3b3613ecec7#local-setup"&gt;https://github.com/tinkerbell/boots/tree/1e1d60ac32bac18d9b3f1c07611cd3b3613ecec7#local-setup&lt;/a&gt; you&amp;rsquo;ll need go installed from package manager as well.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cd ~
git clone https://github.com/tinkerbell/boots.git
curl https://clbin.com/12XhH -o /tmp/ovh-boots-ipxe.patch
make
docker build -t quay.io/tinkerbell/boots:local-ovh-params-fix .
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then modify: docker-compose.yaml in sandbox/deploy/docker-compose.yaml and change tag to &lt;code&gt;local-ovh-params-fix&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Then in the sandbox/deploy folder run: &lt;code&gt;source ../envrc; docker-compose up -d&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="prepare-ovh-machine"&gt;Prepare OVH machine&lt;/h3&gt;
&lt;p&gt;In OVH by default they have an ipxe server listening on the public interface, and intercept all requests. So we need to setup a script through them to bootstrap things so we can boot from our LAN.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ll need API access from here: &lt;a href="https://api.us.ovhcloud.com/console"&gt;https://api.us.ovhcloud.com/console&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Go down to: &lt;code&gt;POST /me/ipxeScript&lt;/code&gt; and insert:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!ipxe
ifclose net0
dhcp net1
set iface net1
chain --autofree http://10.0.5.1/auto.ipxe || exit
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src="/images/2020-09-07/screen-shot-2020-09-07-at-22-18-28.png" alt="" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;This script will:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;close net0 the public interface.&lt;/li&gt;
&lt;li&gt;get dhcp on net1&lt;/li&gt;
&lt;li&gt;set net1 as the iface&lt;/li&gt;
&lt;li&gt;chain and try to boot the ipxe script from boots. If it gives 404 then exit.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Then grab the name of machine you wish to use and goto &lt;code&gt;GET&lt;/code&gt;&lt;a href="https://api.us.ovhcloud.com/console/#/dedicated/server/%7BserviceName%7D/boot#GET"&gt;&lt;code&gt;/dedicated/server/{serviceName}/boot&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Set bootType=ipxeCustomerScript&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ll get an array back. If you aren&amp;rsquo;t sure which one is which you can call: &lt;code&gt;GET&lt;/code&gt;&lt;a href="https://api.us.ovhcloud.com/console/#/dedicated/server/%7BserviceName%7D/boot/%7BbootId%7D#GET"&gt;&lt;code&gt;/dedicated/server/{serviceName}/boot/{bootId}&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This will tell you the name of the script so you can make sure it matches&lt;/p&gt;
&lt;p&gt;Now we need to set our server up to boot this script: &lt;code&gt;PUT /dedicated/server/{serviceName}&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="/images/2020-09-07/screen-shot-2020-09-07-at-22-27-32.png" alt="" loading="lazy"&gt;&lt;/p&gt;
&lt;h3 id="add-info-to-tinkerbell"&gt;Add info to tinkerbell&lt;/h3&gt;
&lt;p&gt;Go back to your sandbox/deploy folder and run: &lt;code&gt;source ../envrc; docker-compose exec tink-cli sh&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Now you have the tink cli available to you.&lt;/p&gt;
&lt;p&gt;You need to create and inject a couple of files&lt;/p&gt;
&lt;h4 id="hardwarejson"&gt;hardware.json&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;{ &amp;quot;id&amp;quot;:&amp;quot;0fba0bf8-3772-4b4a-ab9f-6ebe93b90a94&amp;quot;,
&amp;quot;metadata&amp;quot;:{
&amp;quot;facility&amp;quot;:{
&amp;quot;facility_code&amp;quot;:&amp;quot;ewr1&amp;quot;,
&amp;quot;plan_slug&amp;quot;:&amp;quot;c2.medium.x86&amp;quot;,
&amp;quot;plan_version_slug&amp;quot;:&amp;quot;&amp;quot;
},
&amp;quot;instance&amp;quot;:{},
&amp;quot;state&amp;quot;:&amp;quot;provisioning&amp;quot;
},
&amp;quot;network&amp;quot;:{
&amp;quot;interfaces&amp;quot;:[
{
&amp;quot;dhcp&amp;quot;:{
&amp;quot;arch&amp;quot;:&amp;quot;x86_64&amp;quot;,
&amp;quot;ip&amp;quot;:{
&amp;quot;address&amp;quot;:&amp;quot;10.0.6.3&amp;quot;,
&amp;quot;gateway&amp;quot;:&amp;quot;10.0.0.1&amp;quot;,
&amp;quot;netmask&amp;quot;:&amp;quot;255.255.0.0&amp;quot;
},
&amp;quot;mac&amp;quot;:&amp;quot;d0:50:99:d7:63:20&amp;quot;,
&amp;quot;uefi&amp;quot;:true
},
&amp;quot;netboot&amp;quot;:{
&amp;quot;allow_pxe&amp;quot;:true,
&amp;quot;allow_workflow&amp;quot;:true
}
}
]
}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You&amp;rsquo;ll need to swap out the ip and mac address.&lt;/p&gt;
&lt;p&gt;Add this hardware with: &lt;code&gt;tink hardware push --file hardware.json&lt;/code&gt;&lt;/p&gt;
&lt;h4 id="hello-worldtmpl"&gt;hello-world.tmpl&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;version: &amp;quot;0.1&amp;quot;
name: hello_world_workflow
global_timeout: 600
tasks:
- name: &amp;quot;hello world&amp;quot;
worker: &amp;quot;{{.device_1}}&amp;quot;
actions:
- name: &amp;quot;hello_world&amp;quot;
image: hello-world
timeout: 60
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Add the template with: &lt;code&gt;tink template create -n hello-world -p hello-world.tmpl&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;ll spit out an id.&lt;/p&gt;
&lt;p&gt;Now we need to create a job to run this template. So we need to create a workflow: &lt;code&gt;tink workflow create -t {template_id} -r '{&amp;quot;device_1&amp;quot;:&amp;quot;d0:50:99:d7:63:20&amp;quot;}'&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Swap out the mac address for the same address used in your hardware.json above.&lt;/p&gt;
&lt;h3 id="try-it"&gt;Try it&lt;/h3&gt;
&lt;p&gt;Now for the fun part. Connect to KVM console for your machine and then reboot it.&lt;/p&gt;
&lt;p&gt;If all went well you should see it boot up&lt;/p&gt;</description></item><item><title>Decision Fatigue in 2020</title><link>https://aaronogle.dev/2020/08/28/decision-fatigue-in-2020/</link><pubDate>Fri, 28 Aug 2020 00:00:00 +0000</pubDate><guid>https://aaronogle.dev/2020/08/28/decision-fatigue-in-2020/</guid><description>
&lt;p&gt;This last couple of weeks I finally took some time off of work to try and reset. I’m not always the greatest at taking time off. I take an extra day or two combined with the weekend for a mini-vacation around the Holidays to see family and it’s often the minimum time needed. This year with everything going on really had to force my self to step back and try to reset with a staycation.&lt;/p&gt;
&lt;p&gt;It’s all too easy now days to get overwhelmed and stressed out. A couple of key contributors now days:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Decision Fatigue&lt;/li&gt;
&lt;li&gt;World Circumstances&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="decision-fatigue"&gt;Decision Fatigue&lt;/h2&gt;
&lt;p&gt;There are many articles written about this topic that do a much better job than I could to describe this. A couple that &lt;a href="https://duckduckgo.com/?q=decision+fatigue"&gt;a quick DuckDuckGo uncovered&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.healthline.com/health/decision-fatigue" title="https://www.healthline.com/health/decision-fatigue"&gt;https://www.healthline.com/health/decision-fatigue&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.rescuetime.com/decision-fatigue/" title="https://blog.rescuetime.com/decision-fatigue/"&gt;https://blog.rescuetime.com/decision-fatigue/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;But in short.. if you are constantly having to make decision after decision. There is a point when it just gets mentally taxing to have to keep making decisions.&lt;/p&gt;
&lt;p&gt;I personally loop into this what I guess you would call Context Switching Fatigue. It boils down to some of the same things. But basically if you are constantly having to switch between tasks it can also lead to fatigue.&lt;/p&gt;
&lt;h2 id="world-circumstances"&gt;World Circumstances&lt;/h2&gt;
&lt;p&gt;It’s super easy to look at everything happening in the world and worry about things you can’t control.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Covid19 - We watch as the number of reported cases climb.. people can’t agree on how it’s reported and it’s politicized. With so much conflicting reporting&amp;hellip; We are faced with more of decision fatigue. What info is correct?&lt;/li&gt;
&lt;li&gt;Protesting and Riots - same thing.. mixed reporting. While the initial reason for protesting feels like a no brainer&amp;hellip; everyone is taking extreme views on how to solve it. We see a lot of reports on who is doing what&amp;hellip; and here we are stuck with making sense of everything.&lt;/li&gt;
&lt;li&gt;Social Media chaos and unrest - a longer topic.. but everyone seems to be looking for a cause. They just pick a side in a fight with little to no research and shame anyone with an opposing view. You don’t have to scroll far in your feed to see someone post something political.. then in the comments you see anyone that opposes the view point or even question it.. dog piled on. Peaceful debating is long gone.&lt;/li&gt;
&lt;li&gt;Deaths - as if it’s not a hard enough year.. people still get older and still die from varying causes&lt;/li&gt;
&lt;li&gt;Hurricanes - In my part of the world it’s in the middle of hurricane season.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="resetting-and-handling"&gt;Resetting and Handling&lt;/h2&gt;
&lt;p&gt;Reducing decision fatigue doesn’t have a silver bullet. But one way I’m handling it on my staycation is taking it easy and making as little decisions as possible. Spent the first week blasting through my honey-do-list and generally cleaning. Then just taking it easy, avoiding news and social media(except Hurricane Laura updates).&lt;/p&gt;
&lt;p&gt;But long term my approach:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cut down / Cut out Social Media - it’s filled with a lot of toxicity.&lt;/li&gt;
&lt;li&gt;Avoid too much News - I admit I don’t do this as well as I’d like. If you spend too much time reading news, you will be forced to spend more time reading both sides and making a decision.&lt;/li&gt;
&lt;li&gt;Simple and structured morning routine - for me this includes Bullet Journaling.&lt;/li&gt;
&lt;li&gt;Organization - being organized helps decision fatigue a lot.&lt;/li&gt;
&lt;li&gt;Value your own time. Just because someone DM’s you asking for something doesn’t mean you need to stop what you are doing now and respond. In fact busy mode / do not disturb is your best friend here. Not even seeing it prevents you from having to make a decision.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Don’t be afraid to take time off to reset! It’s hard to take time off. But it’s important to take care of your self!&lt;/p&gt;</description></item><item><title>A k8s Migration Concept</title><link>https://aaronogle.dev/2020/05/01/a-k8s-migration-concept/</link><pubDate>Fri, 01 May 2020 00:00:00 +0000</pubDate><guid>https://aaronogle.dev/2020/05/01/a-k8s-migration-concept/</guid><description>
&lt;p&gt;Surprisingly I don’t have a lot of kubernetes related content on my blog yet. This might just because I’m too busy using it to talk about it. But i’m a heavy user of it. To me it just makes orchestrating work loads easier.&lt;/p&gt;
&lt;p&gt;One thing in general I don’t see a lot of talk about is migrating between infrastructure. Especially don’t see much for kubernetes.&lt;/p&gt;
&lt;p&gt;So I wanted to share a high level concept set of steps that i’ve followed a couple of times to migrate between a couple of kubernetes clusters with minimal to no downtime.&lt;/p&gt;
&lt;h3 id="establishing-a-link-between-environments"&gt;Establishing a link between environments&lt;/h3&gt;
&lt;p&gt;The first step in this process was establishing a link between the old environment and the new environment. Most major cloud providers have VPC peering so can set this up pretty easily. So far all have been IPSEC. A few tweaks to the firewall later you can talk across.&lt;/p&gt;
&lt;h3 id="spin-up-new-db-nodes"&gt;Spin up new DB nodes&lt;/h3&gt;
&lt;p&gt;In my case it was some mongo nodes. Once they were up, joined them to the replicaset on the other side. One important thing here is they were set with 0 priority to prevent them from some how becoming a primary before we were ready&lt;/p&gt;
&lt;h3 id="proxy-endpoint"&gt;Proxy Endpoint&lt;/h3&gt;
&lt;p&gt;Once the DB is ready and ready to migrate. Established an endpoint from the new environment across to the old environments ingress provider. On caveat here is did actually have to spin up a second internal ingress provider that would handle proxying to load inside the cluster. But did not handle TLS termination. This is what we pointed the endpoint to.&lt;/p&gt;
&lt;h3 id="create-ingress-records"&gt;Create ingress records&lt;/h3&gt;
&lt;p&gt;Now that the other side is ready to accept traffic over the peering and route the traffic to the appropriate place… Need to actually tell the new environment what routes to listen for and where to send them. So all of them just point to the proxy endpoint.&lt;/p&gt;
&lt;p&gt;At this point you can make a request like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl --verbose --header &amp;#39;Host: www.example.com&amp;#39; &amp;#39;http://10.1.1.36:8080/url&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="dns"&gt;DNS&lt;/h3&gt;
&lt;p&gt;Now that requests are verified to go across you can swap over the DNS from old environment to the new environment. Making sure to take note of the TTL on the record. I actually decreased the TTL a couple of days prior to prevent having to wait as long.&lt;/p&gt;
&lt;p&gt;So the traffic will flow into new environment and the proxy over to old environment&lt;/p&gt;
&lt;h3 id="migrate"&gt;Migrate&lt;/h3&gt;
&lt;p&gt;Once give the time for the TTL time to have fully ran out. Could start migrating.&lt;/p&gt;
&lt;p&gt;For us this process looked like:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Deploy Deployment&lt;/li&gt;
&lt;li&gt;Deploy SVC&lt;/li&gt;
&lt;li&gt;Swap ingress to point to service&lt;/li&gt;
&lt;li&gt;Verify traffic hits&lt;/li&gt;
&lt;li&gt;Spin down resource in old environment&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="db-primary-switch"&gt;DB Primary Switch&lt;/h3&gt;
&lt;p&gt;We waited until about half of the deployments had switched and then adjusted priority in our DB cluster so that only nodes in the new environment had priority and now all in old environment had none and then made our primary in the old environment step down.&lt;/p&gt;
&lt;p&gt;Important to make sure your application can actually detect and handle this. Otherwise it won’t work.&lt;/p&gt;
&lt;h3 id="finishing-up"&gt;Finishing up&lt;/h3&gt;
&lt;p&gt;Once it was all over only thing left to do was to clean up.&lt;/p&gt;
&lt;p&gt;To me the magic here is in being able to change the DNS and traffic still be working with some minimal latency increase.&lt;/p&gt;
&lt;p&gt;Things can definitely go wrong. You have to plan for them. This is also why giving your self a maintenance window is also extremely important.&lt;/p&gt;
&lt;p&gt;Also if you know anything about working with the kubernetes api.. consider writing something to do this.&lt;/p&gt;</description></item><item><title>Quarantainment</title><link>https://aaronogle.dev/2020/05/01/quarantainment/</link><pubDate>Fri, 01 May 2020 00:00:00 +0000</pubDate><guid>https://aaronogle.dev/2020/05/01/quarantainment/</guid><description>
&lt;p&gt;I don’t think its likely a surprise to anyone if I say I’m typically an introvert. I stay at and around home a lot in general. But when its no longer by choice.. kinda takes the fun out of it.&lt;/p&gt;
&lt;p&gt;We identified early on that we needed to keep our selves busy and entertained.&lt;/p&gt;
&lt;p&gt;Started out the quarantine with me teaching my wife to play chess. So pulled out the ‘ol &lt;a href="https://www.amazon.com/USAopoly-CH005-191-Chess-Super-Mario/dp/B00168PI9S"&gt;Mario chess set&lt;/a&gt;. Yes its awesome!&lt;/p&gt;
&lt;p&gt;&lt;img src="https://paper-attachments.dropbox.com/s_5B8DDF11035244A7AC92669A93E624BCD7D0866F945EF2DF2F75C708AABAABDC_1588363799655_file.jpeg" alt="" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://paper-attachments.dropbox.com/s_5B8DDF11035244A7AC92669A93E624BCD7D0866F945EF2DF2F75C708AABAABDC_1588363821571_file.jpeg" alt="" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;I’ve wanted to learn to play go for a long time. Pretty much ever since seeing AlphaGo compete against the top players. So I figured what better time to learn? Picked &lt;a href="https://en.wikipedia.org/wiki/Go_equipment#Board"&gt;Goban&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Go_equipment#Stones"&gt;stones&lt;/a&gt; or &lt;a href="https://en.wikipedia.org/wiki/Yunzi"&gt;Yunzi&lt;/a&gt; as they are apparently called.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://paper-attachments.dropbox.com/s_5B8DDF11035244A7AC92669A93E624BCD7D0866F945EF2DF2F75C708AABAABDC_1588364259006_file.jpeg" alt="" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;Proceeded to play a couple of very noob games of go.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://paper-attachments.dropbox.com/s_5B8DDF11035244A7AC92669A93E624BCD7D0866F945EF2DF2F75C708AABAABDC_1588364332277_file.jpeg" alt="" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;The same board doubles as a chess board on the other side so have been alternating between this board and the other for playing chess.&lt;/p&gt;
&lt;p&gt;Even taught my kids. They now can all correctly identify the pieces and how the pieces can move.&lt;/p&gt;
&lt;p&gt;Picked up a few more various card games and board games to add to our collection. We already regularly enjoy family game nights.&lt;/p&gt;
&lt;p&gt;Have spent a fair amount of time in my backyard. Got some patio furniture and a Hammock.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://paper-attachments.dropbox.com/s_5B8DDF11035244A7AC92669A93E624BCD7D0866F945EF2DF2F75C708AABAABDC_1588365007947_file.jpeg" alt="" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m pretty sure amazon and UPS hate us.&lt;/p&gt;
&lt;p&gt;I also bought some controllers and loaded a raspberry pi up with &lt;a href="https://retropie.org.uk/"&gt;retropie&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://paper-attachments.dropbox.com/s_5B8DDF11035244A7AC92669A93E624BCD7D0866F945EF2DF2F75C708AABAABDC_1588365556279_file.jpeg" alt="" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;So far its working. We have stayed fairly sane and we are coming out the other side a bit better then we went in.&lt;/p&gt;</description></item><item><title>Respecting Privacy in Analytics</title><link>https://aaronogle.dev/2020/04/29/respecting-privacy-in-analytics/</link><pubDate>Wed, 29 Apr 2020 00:00:00 +0000</pubDate><guid>https://aaronogle.dev/2020/04/29/respecting-privacy-in-analytics/</guid><description>
&lt;p&gt;There is a reason why people tend to add analytics to sites. I&amp;rsquo;d say most people add for completely honest reasoning. They just want to be able to see how their site is doing and if anyone actually shows up.&lt;/p&gt;
&lt;p&gt;But its really important to go down the path with caution. If you dont carefully select and think through your analytics… You end up spying on your users likely without even realizing it.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s imagine you read the exciting sales pitch from AssociatedIn on how adding their analytics will let you see the types of users or businesses visit your site. Seems innocent enough right?&lt;/p&gt;
&lt;p&gt;Lets put on our privacy detective hat!&lt;/p&gt;
&lt;p&gt;So you turn it on and they start giving you this data.. How are they able to give you this info? The only way they would know anything about your users if they send something to them selves right? So of course they do this. But the only way them sending the page to themselves would be useful if they included something about the user. So they have to some how identify you or to see if unique.&lt;/p&gt;
&lt;p&gt;Maybe they see you are logged in to their service? Ouch.. But ok ones easy.&lt;/p&gt;
&lt;p&gt;Maybe they fingerprint you by grabbing an assortment of clues the browser gives away? Could be.. To make it even easier on themselves maybe they drop a cookie in the browser so next time that user visits a page they will know it&amp;rsquo;d the same user. Oh it happens to also send to any other site using their analytics?&lt;/p&gt;
&lt;p&gt;This just went from analytics straight on over in to tracking territory. Now by getting some analytics about the type of business your users run.. You have traded it for your user being tracked.&lt;/p&gt;
&lt;p&gt;The tracking company is then aggregating this data, building models about users, maybe selling it? Or maybe they aren&amp;rsquo;t so blatenly nefarious.. maybe they are just offering a paid plan offering advanced abilities. Your users data that you are giving them now let&amp;rsquo;s them make money.&lt;/p&gt;
&lt;p&gt;Seemed innocent though right?&lt;/p&gt;
&lt;p&gt;Super important to think about the type of information we collect about our users. Is that bit of data worth allowing a tracker to invade your users privacy?&lt;/p&gt;
&lt;h1 id="ok-so-what-should-i-use"&gt;Ok so what should I use?&lt;/h1&gt;
&lt;p&gt;Great question! First off self hosting an open source analytics tool can be a great way to know exactly what data you collect and how its collected. Also you ensure that data isn&amp;rsquo;t then being aggregated to track your users across the web.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m still on the hunt for good options but will update this list as I find out about them. But here are a couple:&lt;/p&gt;
&lt;h2 id="matomo"&gt;Matomo&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://matomo.org"&gt;https://matomo.org&lt;/a&gt; is one recommended by many people in the open source community. Full featured alternative to the likes of Google Analytics.&lt;/p&gt;
&lt;h2 id="fatham"&gt;Fatham&lt;/h2&gt;
&lt;p&gt;Recently came across this one. I&amp;rsquo;m actually using it for my site and inspired this topic. Feels great for use cases like mine.&lt;/p&gt;
&lt;p&gt;Its kind of confusing.. But apparently their first version is/was open source. Then they rewrote it and this version is not open source but available on their SaaS offering.&lt;/p&gt;
&lt;p&gt;But the open source version can be found here: &lt;a href="https://github.com/usefathom/fathom"&gt;https://github.com/usefathom/fathom&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;What I like about this is I can see exactly what is transmitted and what is stored.&lt;/p&gt;
&lt;p&gt;Transmitted: &lt;a href="https://github.com/usefathom/fathom/blob/8f7c6d2e45ebb28651208e2a7320e29948ecdb2c/assets/src/js/tracker.js#L162"&gt;here&lt;/a&gt;
Saved: &lt;a href="https://github.com/usefathom/fathom/blob/8f7c6d2e45ebb28651208e2a7320e29948ecdb2c/pkg/api/collect.go#L54"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here is a sample of my brief moment on hackernews yesterday. But what you see there is it. Super simple, but does the job.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://paper-attachments.dropbox.com/s_3A770CD59D00AB3A931B3BF5D654149EDE7875E5917677E7CC0A064B28BBDD07_1588216208662_file.jpeg" alt="" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;Think about privacy the next time you start adding analytics to your website. Think about what you are making your users give up in exchange. Do the right thing 🙂&lt;/p&gt;</description></item><item><title>De-Googling: My Progress</title><link>https://aaronogle.dev/2020/04/28/de-googling-my-progress/</link><pubDate>Tue, 28 Apr 2020 00:00:00 +0000</pubDate><guid>https://aaronogle.dev/2020/04/28/de-googling-my-progress/</guid><description>
&lt;p&gt;I wrote a bit about my reasoning to De-Google &lt;a href="https://geekgonecrazy.com/2020/04/27/de-googling/"&gt;here&lt;/a&gt;. Now I want to write a bit about my progress, the struggles and what I ended up with.&lt;/p&gt;
&lt;h1 id="search"&gt;Search&lt;/h1&gt;
&lt;p&gt;Or Google as many think of it. This one I have toyed with off and on with over the years. But a while back probably around a year ago.. I was listening to a podcast. I think either Ask Noah Show or one of the Jupiter Broadcast Linux podcasts and was inspired to challenge my self to switch and see how it went.&lt;/p&gt;
&lt;p&gt;I switched to:&lt;/p&gt;
&lt;h4 id="duckduckgo"&gt;Duckduckgo&lt;/h4&gt;
&lt;p&gt;It was one that I had tried direct comparison searches with before.. Every time I would feel it wasn&amp;rsquo;t as good. But I went ahead and switched it as my default on my phone.&lt;/p&gt;
&lt;p&gt;At first I noticed what felt like results not showing. Felt like I was digging a lot. The same sort of thing I see everyone else complain about and turn away. But I decided to stick it out.&lt;/p&gt;
&lt;p&gt;Before long I stopped noticing. I also almost always find the result on the first page. No different than Google.&lt;/p&gt;
&lt;p&gt;What I&amp;rsquo;ve come to realize is I&amp;rsquo;m no longer depending on what Google knows about me to help me find what I want and instead I have become better at searching.&lt;/p&gt;
&lt;p&gt;Google knows you, it knows the typed of things you would look for. It farms data on lots of people just like you. So of course its able to fill in the gap.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll take training my brain my privacy any day!&lt;/p&gt;
&lt;h1 id="browser"&gt;Browser&lt;/h1&gt;
&lt;p&gt;I almost forgot to add. I actually feel kind of bad.. I help move a lot of people to Chrome from other browsers. 😔&lt;/p&gt;
&lt;p&gt;I have to give Google major props for Chrome. The web was getting a bit stagnant. With Chrome it feels like they gave the web the kick in the pants we needed to evolve.&lt;/p&gt;
&lt;p&gt;But it&amp;rsquo;s still Google and my browsing habits is my data. So I switched to:&lt;/p&gt;
&lt;h4 id="firefox"&gt;Firefox&lt;/h4&gt;
&lt;p&gt;Firefox has gotten a lot better! Like night and day difference. Its fast, lighter on memory, looks a bit better and perhaps most importantly…&lt;/p&gt;
&lt;p&gt;Its maintaining some diversity. Most browsers now use chromium or at least blink under the hood. Competition is good. Firefox&amp;rsquo;s phenoix like rise from the the ashes is proof enough of this.&lt;/p&gt;
&lt;p&gt;I keep chromium and brave around as a backup for times when Firefox doesn&amp;rsquo;t cut it.&lt;/p&gt;
&lt;h1 id="email"&gt;Email&lt;/h1&gt;
&lt;p&gt;I drug my feet for the longest time on this. I had a grandfathered in Google apps free account for my domains email. So I&amp;rsquo;m already in better shape then most.&lt;/p&gt;
&lt;p&gt;I started off in a similar way to search. I first started using a non-gmail account on my phone. Desktop I used Thunderbird or Mail.app on osx. This started to train my self to not really care about the gmail features.&lt;/p&gt;
&lt;p&gt;Then after really dragging my feet some more… I eyed protonmail.. But didn&amp;rsquo;t really feel like the encryption they provided and plan options ever really was that great of a deal.&lt;/p&gt;
&lt;p&gt;I switched to:&lt;/p&gt;
&lt;h4 id="self-hosted-with-mail-in-a-box"&gt;Self-hosted with &lt;a href="https://mailinabox.email"&gt;mail-in-a-box&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;This made it so simple! Simple enough for me to spend half an hour to set it up a $5 droplet on DigitalOcean and have it receiving email for several domains and a couple of new ones 🙂&lt;/p&gt;
&lt;p&gt;Took another few hours to fail miserably with the terrible Google Takeout export of my email. Then force Thunderbird to fully download all of my mail and then push it all back up. Moral of story just use IMAP and you can move your mail anywhere.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not 100% satisfied with this. I think in the future I will use some sort of docker based solution or roll my own. So I can self host a few more things a bit easier. But I got through the hardest part… I got my data back.&lt;/p&gt;
&lt;h1 id="phone"&gt;Phone&lt;/h1&gt;
&lt;p&gt;One of my biggest tie-ins to Google has actually been mobile. I&amp;rsquo;ve had a nexus or pixel for as long as I can remember. I tried Samsung and absolutely hated the skin they threw on it.&lt;/p&gt;
&lt;p&gt;I tried ROMs like Cyanogenmod but it was always so buggy.. My phone is the one device I need to just work.&lt;/p&gt;
&lt;p&gt;I tried just switching apps but I&amp;rsquo;d find my self right back into Google Assistant, Google Now etc…&lt;/p&gt;
&lt;p&gt;So I switched to what only an insane person would:&lt;/p&gt;
&lt;h4 id="iphone"&gt;iPhone&lt;/h4&gt;
&lt;p&gt;I probably just lost 99% of you 🙈&lt;/p&gt;
&lt;p&gt;But doing this in one fell swoop I cut off a lot of temptation and random little Google apps.&lt;/p&gt;
&lt;p&gt;This also let me see how the other side is. To be honest not that different.. I haven&amp;rsquo;t really missed anything.&lt;/p&gt;
&lt;p&gt;But I think this really helped cut my reliance on Google and I feel a lot less reliant on any particular phone OS.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m keeping my eye on pinephone. Very exciting work being done. I&amp;rsquo;ll be buying one to play with before too long.&lt;/p&gt;
&lt;h1 id="photos"&gt;Photos&lt;/h1&gt;
&lt;p&gt;All photos used to backup automatically in full resolution to Google Photos. By having original pixel I got this for free.&lt;/p&gt;
&lt;p&gt;Switched to:&lt;/p&gt;
&lt;h4 id="icloud"&gt;iCloud&lt;/h4&gt;
&lt;p&gt;Yeah… I&amp;rsquo;m still looking for a good place to store this. But at least I&amp;rsquo;m paying for this service and am not the product.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m open to suggestions on self hosted. I&amp;rsquo;ve already pulled down my 2-300GB Google Photos archive.&lt;/p&gt;
&lt;h1 id="contactscalendar"&gt;Contacts/Calendar&lt;/h1&gt;
&lt;p&gt;Another byproduct of using Android my Google account was default.&lt;/p&gt;
&lt;p&gt;Switched to:&lt;/p&gt;
&lt;h4 id="icloud-1"&gt;iCloud&lt;/h4&gt;
&lt;p&gt;I&amp;rsquo;m thinking about using nextcloud.&lt;/p&gt;
&lt;h1 id="docs"&gt;Docs&lt;/h1&gt;
&lt;p&gt;I never really used Google Drive or any of the gsuite.&lt;/p&gt;
&lt;p&gt;Switched to:&lt;/p&gt;
&lt;h4 id="hackmd"&gt;Hackmd&lt;/h4&gt;
&lt;p&gt;I like writing markdown. Downside… typing on mobile doesn&amp;rsquo;t work very well. Especially copy and pasting or moving cursor.&lt;/p&gt;
&lt;p&gt;Nextcloud might fill this gap. But I don&amp;rsquo;t feel a void to fill right now.&lt;/p&gt;
&lt;h1 id="google-hangouts"&gt;Google Hangouts&lt;/h1&gt;
&lt;p&gt;I think I&amp;rsquo;ve used every incarnation of messenger Google has had and killed off. I had all of my family on Google Hangouts in group conversations.&lt;/p&gt;
&lt;p&gt;Switched to:&lt;/p&gt;
&lt;h4 id="whatsapp"&gt;Whatsapp&lt;/h4&gt;
&lt;p&gt;Yeah I know.. One evil for another. I was traveling and one of the services I could use for free and worked best in Brazil was WhatsApp. Moving my family, in-laws, etc off is battle for another day.&lt;/p&gt;
&lt;p&gt;I would like to get them all using a self hosted Rocket.Chat workspace. One day!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Edit to clarify:&lt;/strong&gt;&lt;/em&gt; This was replacing my need for extended family communication groups. My wife&amp;rsquo;s family my family and extended family thats pretty much it. For other communications I use Rocket.Chat for team collab, signal, keybase chat or sms(which if they do happen to have iMessage does convert). I definitely do not trust facebook any more than Google.&lt;/p&gt;
&lt;h1 id="music"&gt;Music&lt;/h1&gt;
&lt;p&gt;Used Google Music a lot and actually really liked its recommendations. But even before my De-Googling exercise I noticed that they started pushing YouTube Music. Rumor is it will be replace with YouTube Music. My guess is to leverage all of the music brought on by artists with vevo.&lt;/p&gt;
&lt;p&gt;Switched to:&lt;/p&gt;
&lt;h4 id="spotify"&gt;Spotify&lt;/h4&gt;
&lt;p&gt;Its one of the few services I don&amp;rsquo;t mind paying for. It does an okay job at playing music I might be interested in.&lt;/p&gt;
&lt;h1 id="todo"&gt;Todo&lt;/h1&gt;
&lt;p&gt;Looking through my phone at the Google Apps installed.&lt;/p&gt;
&lt;p&gt;Youtube is the only app/service I visit any more for personal use. I&amp;rsquo;ve tried using invidious.. But I don&amp;rsquo;t know how much this really helps. Also if I self host then the data is then tied to me… so kinda defeats the purposes.&lt;/p&gt;
&lt;p&gt;When ever I do find my self having to access Google I do so in a separate Firefox Container.&lt;/p&gt;
&lt;p&gt;Overall I feel like I&amp;rsquo;ve done a great job removing my reliance on Google! I have a feeling I will be self hosting a lot more in the future. Maybe more on that another time. 😉&lt;/p&gt;</description></item><item><title>De-Googling</title><link>https://aaronogle.dev/2020/04/27/de-googling/</link><pubDate>Mon, 27 Apr 2020 00:00:00 +0000</pubDate><guid>https://aaronogle.dev/2020/04/27/de-googling/</guid><description>
&lt;p&gt;This is not by any means a new idea. A quick search around the web will return many results of people doing this. My reasons are likely similar to many others. Privacy being the most common shared reason.&lt;/p&gt;
&lt;p&gt;Ok that&amp;rsquo;s it I spoiled it! Now you don&amp;rsquo;t need to read on 😜 But I&amp;rsquo;ll explain anyways.&lt;/p&gt;
&lt;h1 id="privacy"&gt;Privacy&lt;/h1&gt;
&lt;p&gt;Google gives their applications and services away for free. This is extreeemly attractive! We humans are cheap! That&amp;rsquo;s not totally fair.. But I think in regard to software it holds true.&lt;/p&gt;
&lt;p&gt;We will buy the best hardware in the world and then we hunt for the cheapest software we can find. But this is a rabbit hole.. I won&amp;rsquo;t go down today.&lt;/p&gt;
&lt;p&gt;What we often forget(my self included) is to stop and ask your self a question:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;How are they able to pay people to make this if they are giving it away for free?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Don&amp;rsquo;t know? Let me help you out. You are paying with your data!&lt;/p&gt;
&lt;p&gt;Of course there are exceptions that I won&amp;rsquo;t go into here. But for the most part this holds true.&lt;/p&gt;
&lt;p&gt;Google specifically is an ad company. This is how they make money. &amp;ldquo;But I thought Google was just a search engine?&amp;rdquo; Nope they historically make most money on ads. &lt;a href="https://www.investopedia.com/articles/investing/020515/business-google.asp"&gt;Here is one example&lt;/a&gt; of many out there talking about this. So your data feeds their ad machine.&lt;/p&gt;
&lt;p&gt;Creeped out yet? Me too..&lt;/p&gt;
&lt;h1 id="google-grave-yard"&gt;Google Grave yard&lt;/h1&gt;
&lt;p&gt;A less common reason.. I&amp;rsquo;ll try not to sound too bitter here. Bear with me. But Google has left in its wake a trail of bodies.&lt;/p&gt;
&lt;p&gt;A few that I used to use:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Google Wave - so cool&lt;/li&gt;
&lt;li&gt;Google Reader - still don&amp;rsquo;t have one I like as much&lt;/li&gt;
&lt;li&gt;100 different messaging products - I&amp;rsquo;m exaggerating… but only slightly&lt;/li&gt;
&lt;li&gt;Many more&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Its enough that there is a dedicated website just to products Google has killed:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://killedbygoogle.com"&gt;https://killedbygoogle.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If they can&amp;rsquo;t figure out how to get their ad clicks or get bored (seems to be the case of messengers) to the chopping block they go!&lt;/p&gt;
&lt;h1 id="diversity"&gt;Diversity&lt;/h1&gt;
&lt;p&gt;It goes a bit beyond Google for me. Its more like a way of life. As the old saying goes:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Dont put all of your eggs in one basket&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;What if a company went out of business and took all of your data with them? This has happened.&lt;/p&gt;
&lt;p&gt;Diversifying the companies you use for services you can&amp;rsquo;t host your self is like hedging your bets.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Thats it folks! Hopefully my perspective is different enough to be interesting. 😜 I might follow this up with how I have de-googled.&lt;/p&gt;</description></item><item><title>Hacking in the Physical World</title><link>https://aaronogle.dev/2020/04/26/hacking-in-the-physical-world/</link><pubDate>Sun, 26 Apr 2020 00:00:00 +0000</pubDate><guid>https://aaronogle.dev/2020/04/26/hacking-in-the-physical-world/</guid><description>
&lt;p&gt;Hacking is often a term used to mean malicious behavior. But I believe hacking is a mindset. It&amp;rsquo;s about trying to be creative.. Taking things and making them work in a different way. It&amp;rsquo;s about not letting your self be your own limiter. Just because you&amp;rsquo;ve never done something before… doesn&amp;rsquo;t mean you shouldn&amp;rsquo;t try.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t consider my self good at carpentry. Or using screws, hammers, power tools etc.. I&amp;rsquo;m also sure &lt;del&gt;some&lt;/del&gt; most of the work makes professionals cringe just like I do at code by a novice.&lt;/p&gt;
&lt;p&gt;But when a project comes around that needs done.. I think the only way to learn is to do.&lt;/p&gt;
&lt;p&gt;When ever I can I like to help on projects where someone knows what they are doing. This way I can slowly build up some tips and tricks.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve always been a tinkerer with a very curious mind. My parents love to tell the story of me as a young kid ripping the thermostat off of the wall so that I could see how it worked.&lt;/p&gt;
&lt;p&gt;Over the last few years I feel I&amp;rsquo;ve gotten a bit more comfortable with power tools. Hurricane Harvey hit me and my in-laws houses. Fortunately for us we were renting. But my in-laws have spent the last few years gutting and remodeling their house. A lot of opportunities to learn there and they have gotten to make the house like they want it. Look for the silver linings right?&lt;/p&gt;
&lt;p&gt;Anyways.. Few years back we bought a house and I inherited an amazing fence &lt;!-- raw HTML omitted --&gt;. I&amp;rsquo;ve done repairs in the past replacing pieces that butt up against my neighbors yard. It was an urgent repair to keep the neighbors aggressive acting dog from barging through the very weak pieces. The side has always leaned out a bit towards the road.&lt;/p&gt;
&lt;p&gt;What needs to happen is I need to pull all planks off and fix it properly. But until I have resources to do so I have attempted to straighten some and strengthen it.&lt;/p&gt;
&lt;p&gt;First thing was obvious.. some of the bottom 2x4s weren&amp;rsquo;t even connected. 🙈&lt;/p&gt;
&lt;p&gt;The second major issue is the top 2x4s were layed flat and super bowed.&lt;/p&gt;
&lt;p&gt;I loosened some pieces around the beam leaving the section unhooked from the post and then since mostly doing by my self made a make shift pulley out of rope and stake in the ground.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://paper-attachments.dropbox.com/s_316E9D8BF50C70E0D031ECDBEA216C11C9895ACBF532434B292654CB7AD99E07_1587947823306_file.jpeg" alt="" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://paper-attachments.dropbox.com/s_316E9D8BF50C70E0D031ECDBEA216C11C9895ACBF532434B292654CB7AD99E07_1587947837444_file.jpeg" alt="" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://paper-attachments.dropbox.com/s_316E9D8BF50C70E0D031ECDBEA216C11C9895ACBF532434B292654CB7AD99E07_1587947858948_file.jpeg" alt="" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://paper-attachments.dropbox.com/s_316E9D8BF50C70E0D031ECDBEA216C11C9895ACBF532434B292654CB7AD99E07_1587947877962_file.jpeg" alt="" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://paper-attachments.dropbox.com/s_316E9D8BF50C70E0D031ECDBEA216C11C9895ACBF532434B292654CB7AD99E07_1587947890351_file.jpeg" alt="" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://paper-attachments.dropbox.com/s_316E9D8BF50C70E0D031ECDBEA216C11C9895ACBF532434B292654CB7AD99E07_1587947906948_file.jpeg" alt="" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://paper-attachments.dropbox.com/s_316E9D8BF50C70E0D031ECDBEA216C11C9895ACBF532434B292654CB7AD99E07_1587947924886_file.jpeg" alt="" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://paper-attachments.dropbox.com/s_316E9D8BF50C70E0D031ECDBEA216C11C9895ACBF532434B292654CB7AD99E07_1587947938717_file.jpeg" alt="" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;Once they were as straight as I could.. cut a few spare 2x4s put them in as square as I could and then removed the bowed pieces.&lt;/p&gt;
&lt;p&gt;Anyways… it&amp;rsquo;s not pretty. But it will last a little longer until I can do it right.&lt;/p&gt;
&lt;p&gt;Hopefully interesting in some way! If not we’ll try again. I&amp;rsquo;ve got several more projects needing done 🙂&lt;/p&gt;</description></item><item><title>100 Day writing challenge</title><link>https://aaronogle.dev/2020/04/25/100-day-writing-challenge/</link><pubDate>Sat, 25 Apr 2020 00:00:00 +0000</pubDate><guid>https://aaronogle.dev/2020/04/25/100-day-writing-challenge/</guid><description>
&lt;p&gt;Hello its me again your friendly neighborhood Geek Gone Crazy.😜 Its been a bit less time since my last post than normal. Recently I came across a challenge on mastodon to do a 100 day writing challenge. Inspired by the 100 days of code.&lt;/p&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;p&gt;The idea being much like 100 days of code it encourages a person to sit down to write more often. Of course by doing this you get better at it.&lt;/p&gt;
&lt;p&gt;As you can see from my posting history here.. I don&amp;rsquo;t post a lot. But I do enjoy writing, I do a fair amount of writing for work and have always wanted to post a bit more. So.. here goes nothing!&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s to hopefully a few more posts!&lt;/p&gt;</description></item></channel></rss>