<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[ArnavDocs]]></title><description><![CDATA[ArnavDocs]]></description><link>https://docs.arnav.uk</link><image><url>https://cdn.hashnode.com/uploads/logos/6767e8fe0ddd601305c860a0/53c71811-f582-41ea-9ec8-2c48f8add2e1.png</url><title>ArnavDocs</title><link>https://docs.arnav.uk</link></image><generator>RSS for Node</generator><lastBuildDate>Wed, 07 Oct 2026 10:17:19 GMT</lastBuildDate><atom:link href="https://docs.arnav.uk/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[VMware Network Adapters Explained: NAT, Host‑Only, and Bridged Modes]]></title><description><![CDATA[Introduction
I recently ran into a problem while I was working on a home lab that I thought was worth sharing. I wanted to run a virtual machine, but my main PC didn’t have enough free storage space, ]]></description><link>https://docs.arnav.uk/vmware-network-adapters-explained</link><guid isPermaLink="true">https://docs.arnav.uk/vmware-network-adapters-explained</guid><category><![CDATA[vmware]]></category><category><![CDATA[networking]]></category><category><![CDATA[virtual machine]]></category><category><![CDATA[VirtualBox ]]></category><category><![CDATA[hyper-v]]></category><category><![CDATA[hypervisor]]></category><dc:creator><![CDATA[Arnav Salian]]></dc:creator><pubDate>Sat, 29 Aug 2026 19:26:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6767e8fe0ddd601305c860a0/c42fc3c2-0888-476c-996a-8e27f22a4b35.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2>
<p>I recently ran into a problem while I was working on a home lab that I thought was worth sharing. I wanted to run a virtual machine, but my main PC didn’t have enough free storage space, so I decided to install VMware on a different machine on the same local network and set up a Windows 11 Pro virtual machine there.</p>
<p>My plan was to enable Remote Desktop inside the guest OS so I could RDP into the VM from my main computer instead of using the second machine directly. When I attempted to connect using RDP, the connection kept failing. I checked the usual settings: Remote Desktop was turned on in the guest OS, the firewall allowed RDP traffic, and the VM was running with a valid IP address. Since everything inside the guest OS appeared correct, the issue had to lie in the network path between my main PC and the VM.</p>
<p>That led me to research the issue, and I learned about VMware’s network adapter modes: NAT, Host-Only, and Bridged. The VM was using the default NAT adapter. This meant that the VM could reach the internet, but it lived in a private network, so my main computer couldn’t initiate a connection with it. Switching the adapter to Bridged mode fixed the problem immediately.</p>
<p>The diagrams below show how each network mode works, along with explanations as to why the network mode choice matters more than it first appears.</p>
<h2>How VMware connects a VM to a network</h2>
<p>A VM's network adapter is a software device, but VMware presents it to the guest OS like a physical NIC. That virtual adapter still needs to connect to a network on the host, and VMware does this with virtual switches.</p>
<p>In a typical VMware Workstation install, three virtual networks are created automatically:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6767e8fe0ddd601305c860a0/e26c55f9-2af9-4fb9-8218-252b6cb56477.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li><p><strong>VMnet0</strong> - used for Bridged mode</p>
</li>
<li><p><strong>VMnet1</strong> - used for Host-Only mode</p>
</li>
<li><p><strong>VMnet8</strong> - used for NAT mode</p>
</li>
</ul>
<p>Your VM connects to one of these virtual switches (or a custom network you create). The network mode choice decides which systems the VM can talk to and whether the VM behaves like another device on your LAN or stays isolated behind the host.</p>
<h2>NAT: internet access through the host</h2>
<img src="https://cdn.hashnode.com/uploads/covers/6767e8fe0ddd601305c860a0/ee8ae6aa-ff14-4c48-873d-e08447723ccf.png" alt="" style="display:block;margin:0 auto" />

<p>NAT is the default for new VMs. It's a good fit when the guest needs outbound internet access but doesn't need to be directly reachable from other devices on your physical network.</p>
<p>In NAT mode, VMware connects the VM to a private virtual switch, usually <strong>VMnet8</strong>. In my setup, the physical home network is <code>192.168.1.0/24</code> and the host has <code>192.168.1.10</code>. VMware creates a separate subnet for the NAT network, <code>192.168.150.0/24</code>, and hands out addresses in that range via a virtual DHCP server. A virtual NAT device sits between the VM network and the host's physical connection.</p>
<p>When the VM sends traffic to the internet, the NAT device rewrites the source address so the traffic looks like it's coming from the host. It's the same idea as a home router letting multiple devices share one public IP. This allows the guest OS to have internet access with almost no configuration.</p>
<p>The catch is that devices on your physical LAN can't normally initiate connections to the VM. The VM's <code>192.168.150.x</code> address lives on VMware's private network and isn't routed across your LAN. So another computer on <code>192.168.1.0/24</code> can't just RDP to that address. That's exactly why my Remote Desktop attempt from the main PC failed.</p>
<h2>Host-Only: private communication with the host</h2>
<img src="https://cdn.hashnode.com/uploads/covers/6767e8fe0ddd601305c860a0/1e4c2684-a25a-41a1-9699-351c85e48247.png" alt="" style="display:block;margin:0 auto" />

<p>Host-Only mode also uses a private virtual network, but without a NAT path to the physical network or the internet. VMware creates a virtual switch, typically <strong>VMnet1</strong>, with its own subnet. In the diagram this is <code>192.168.100.0/24</code>. The host gets a virtual adapter on the same network, <code>192.168.100.1</code>, so the host and its VMs can talk directly.</p>
<p>This network mode is useful when VMs need to communicate with the host, or with other VMs on the same Host-Only network, while staying isolated from the physical LAN. It can be used for test environments, security labs, or any scenario where you want to block internet access on purpose.</p>
<p>Host-Only wouldn't have solved my RDP problem. It would have let the VM talk to the machine running VMware, but not to my separate main computer. Since my main PC was another device on the physical LAN, it still wouldn't have had a route into the Host-Only subnet.</p>
<p>A VM with only a Host-Only adapter can't reach the internet, because that network has no route to your physical router or beyond. If you also need internet access, you can add a second virtual network adapter in NAT mode.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6767e8fe0ddd601305c860a0/f41aacec-f338-4608-93b2-7742a5c602a4.png" alt="" style="display:block;margin:0 auto" />

<p>The Host-Only adapter handles isolated host‑to‑VM traffic, while the NAT adapter provides outbound internet through the host's physical connection. VMware supports multiple virtual NICs per VM, so this is a common setup for labs and testing.</p>
<h2>Bridged: direct access to the local network</h2>
<img src="https://cdn.hashnode.com/uploads/covers/6767e8fe0ddd601305c860a0/718f887c-4ad2-4696-9193-3f77dcc78fd3.png" alt="" style="display:block;margin:0 auto" />

<p>Bridged mode was the right choice for my situation. Instead of creating a separate private subnet, VMware uses <strong>VMnet0</strong> to bridge the VM's virtual adapter to the host's physical network adapter. The VM then talks directly to the same router the host uses.</p>
<p>In the example shown, the VM asks the router's DHCP server for an IP address and gets one on the <code>192.168.1.0/24</code> network. It now sits on the LAN alongside the host and other devices. The VM has its own MAC address and IP address, and other machines treat it like any other physical device.</p>
<p>That’s why Remote Desktop worked once I switched to Bridged mode. My main computer could open an RDP session straight to the VM's LAN address, just as it would connect to any other machine on the same network.</p>
<h2>Comparison of the three network modes</h2>
<table>
<thead>
<tr>
<th>Feature</th>
<th>NAT (VMnet8)</th>
<th>Host-Only (VMnet1)</th>
<th>Bridged (VMnet0)</th>
</tr>
</thead>
<tbody><tr>
<td>VM can access the internet</td>
<td>Yes</td>
<td>No, unless a second NAT adapter is added</td>
<td>Yes</td>
</tr>
<tr>
<td>VMware host can reach the VM</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td>Other LAN devices can reach the VM directly</td>
<td>No, not by default</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr>
<td>VM receives an address from the physical router's DHCP service</td>
<td>No</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr>
<td>VM is directly visible on the physical network</td>
<td>No</td>
<td>No</td>
<td>Yes</td>
</tr>
</tbody></table>
<h2>Resolving the RDP issue</h2>
<p>Once the network modes made sense, fixing the issue was straightforward. I opened the VM's network settings and switched the adapter from NAT to Bridged. The VM picked up a new IP address from the router's DHCP pool and became visible to the rest of the local network. After entering that new IP address into Remote Desktop on my main PC, the connection was successful.</p>
<p>Nothing was broken in VMware or Remote Desktop. NAT was doing exactly what it's supposed to do: provide outbound connectivity while keeping the guest OS on a separate private network. The issue was my use case. I needed another device on the LAN to initiate a connection to the VM, and Bridged mode was the right choice because it made the VM directly reachable as a device on the same physical network.</p>
<h2>Conclusion</h2>
<p>It is important to choose the right network mode for your use case. Here is a brief description of when to use which network mode:</p>
<ul>
<li><p><strong>Use NAT</strong> when the VM mainly needs internet access (updates, browsing, downloads) and no other device needs to connect to it directly.</p>
</li>
<li><p><strong>Use Host-Only</strong> when you want an isolated environment where communication is limited to the VMware host and other VMs on the same private network. Add a second NAT adapter if the VM also needs internet access.</p>
</li>
<li><p><strong>Use Bridged</strong> when other devices on the physical LAN need to access the VM directly. Think Remote Desktop, hosting a service, or testing a machine that should behave like an independent device on the network.</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Final Year Project: University Accommodation Allocation System]]></title><description><![CDATA[Introduction
The full project, including the source code, screenshots, and the two documents referenced below, is available on GitLab: gitlab.com/Arnav-Salian/CO3201
Two documents in that repository a]]></description><link>https://docs.arnav.uk/university-accommodation-allocation-system</link><guid isPermaLink="true">https://docs.arnav.uk/university-accommodation-allocation-system</guid><category><![CDATA[AWS]]></category><category><![CDATA[React]]></category><dc:creator><![CDATA[Arnav Salian]]></dc:creator><pubDate>Tue, 18 Aug 2026 11:42:29 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6767e8fe0ddd601305c860a0/37d521c0-8bc5-4c01-9eeb-aae0bc516a6a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2>
<p>The full project, including the source code, screenshots, and the two documents referenced below, is available on GitLab: <a href="https://gitlab.com/Arnav-Salian/CO3201"><strong>gitlab.com/Arnav-Salian/CO3201</strong></a></p>
<p>Two documents in that repository are worth linking directly, in case you want more detail than this post covers:</p>
<ul>
<li><p><a href="https://gitlab.com/Arnav-Salian/CO3201/-/raw/main/Documents%20(Public%20Release%20Version)/3.%20Dissertation.pdf"><strong>Dissertation (PDF)</strong></a> - the full write-up, around 85 pages, covering everything from background research to final results.</p>
</li>
<li><p><a href="https://gitlab.com/Arnav-Salian/CO3201/-/raw/main/Documents%20(Public%20Release%20Version)/4.%20Re-Evaluation%20Report.pdf"><strong>Re-Evaluation Report (PDF)</strong></a> - a follow-up report covering a correction made to the test data after submission, discussed further below.</p>
</li>
</ul>
<p>This post summarises what the project was, what I built, and what I took away from it, without the length or formality of the dissertation itself.</p>
<h2>The problem</h2>
<p>For my CO3201 Computer Science Project at the University of Leicester, I built a system to automate university accommodation allocation. At most universities, this process is still handled manually: staff work through applications by hand, matching students to rooms based on preferences and policy rules. During peak admission periods, when hundreds of applications are submitted at once, this becomes slow and error-prone, and students are often left with little visibility into the status of their application.</p>
<p>The aim was to replace that process with an automated, rules-based system that remains fair and auditable, rather than a black-box algorithm that can't be explained or reviewed.</p>
<h2>What I built</h2>
<p>The system, which I called LeicesterHalls, is a full-stack, cloud-hosted web application consisting of two separate React applications and a serverless backend running entirely on AWS.</p>
<ul>
<li><p><strong>Client application</strong>: the student-facing side. Students can register, browse accommodation, submit an application with ranked preferences, track their application status, accept or decline room offers, make payments through PayPal, and view their contract.</p>
</li>
<li><p><strong>Admin application</strong>: the interface for accommodation staff. Admins can manage room inventory, trigger allocation runs, override allocation decisions, handle room change and termination requests, and monitor occupancy and revenue through dashboards.</p>
</li>
</ul>
<p>Both applications call the same backend API, but each has its own authentication and authorization setup, so they had to be designed and secured largely independently despite sharing infrastructure.</p>
<p>The stack, briefly:</p>
<ul>
<li><p><strong>Frontend:</strong> React.js with Vite, MUI Joy UI, Axios, AWS Amplify for authentication, and PayPal's Checkout SDK for payments.</p>
</li>
<li><p><strong>Backend:</strong> Node.js Lambda functions behind a single API Gateway REST API, with shared dependencies packaged as Lambda Layers.</p>
</li>
<li><p><strong>Data:</strong> DynamoDB with on-demand capacity, so the database scales without needing traffic to be estimated in advance.</p>
</li>
<li><p><strong>Auth:</strong> Two separate Cognito User Pools, one for students and one for admins.</p>
</li>
<li><p><strong>Infrastructure:</strong> A custom VPC, EC2 instances in Auto Scaling Groups behind Application Load Balancers, Route 53 for DNS, and ACM certificates so both applications run over HTTPS.</p>
</li>
</ul>
<h2>How traffic flows through the system</h2>
<p>This was the part of the project that took the most iteration, since it involved getting a number of AWS services to work together correctly. The diagram below is the architecture diagram from the dissertation:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6767e8fe0ddd601305c860a0/bfb7a473-87bc-481a-a578-7e73985ddf06.svg" alt="" style="display:block;margin:0 auto" />

<p><strong>Loading the page.</strong> A request to the client app or the admin app reaches Route 53 first, which resolves the domain and routes it to the correct Application Load Balancer, since each application has its own. The ALB terminates TLS using the relevant ACM certificate, then forwards the request over HTTP to a healthy EC2 instance in its Auto Scaling Group. Both Auto Scaling Groups span two Availability Zones, <code>eu-west-2a</code> and <code>eu-west-2b</code>, so the system continues to operate if one zone becomes unavailable. Each EC2 instance runs nginx and serves the static React build, which is pulled from an S3 bucket by a user data script when the instance launches.</p>
<p><strong>Making API calls.</strong> Once the application has loaded, any user action, whether that's logging in, submitting an application, or loading a dashboard, is sent to API Gateway. Protected routes require a JWT access token in the request header, which API Gateway validates against one of three Cognito authorizers: one for students, one for admins, and a shared authorizer for endpoints both roles can access. Requests with an invalid or missing token are rejected before they reach any backend logic.</p>
<p><strong>Processing the request.</strong> Once a request passes the authorizer, API Gateway forwards it to the relevant Lambda function using proxy integration. That function executes the business logic, whether that's reading room data, running the allocation algorithm, or writing a new application, and interacts with DynamoDB using IAM permissions scoped to exactly what it needs. The response is returned through API Gateway to the browser, and each function writes its logs to its own CloudWatch log group, which proved useful throughout development when debugging permission issues.</p>
<p>Authentication follows a similar but separate flow. Registration triggers a <code>PreSignUp</code> Lambda function that checks the student ID and date of birth against a Students table before Cognito creates the account, which prevents unauthorised sign-ups. After email verification, a <code>PostConfirm</code> Lambda writes the corresponding user record to DynamoDB. On login, Cognito returns ID, access, and refresh tokens, which are stored client-side and used to authenticate subsequent requests.</p>
<h2>The allocation algorithm</h2>
<p>This was the core of the project; everything else exists to support it. When an admin triggers an allocation run for an academic year, a Lambda function retrieves every submitted application and every available room, then runs a policy-constrained greedy assignment algorithm.</p>
<p>Students are processed in priority order: accessibility requirements first, then course type, then submission timestamp. For each student, the algorithm attempts to match them to their highest-ranked accommodation and room choice, out of up to four ranked preferences, provided it satisfies hard constraints such as gender policy, budget, and accessibility requirements. If none of their ranked choices are available, a fallback allocation is made based on the student's stated secondary priorities. Students who cannot be matched under any condition are recorded as unallocated for manual review. Every allocation, offer, occupancy update, and notification is written atomically using DynamoDB transactions, so no partial updates occur.</p>
<p>I chose a greedy, priority-respecting approach over something like Gale-Shapley stable matching, because stable matching doesn't handle hard eligibility constraints well: a room that fails a student's accessibility requirement isn't a valid match regardless of ranking. The definition of fairness I used instead was more direct: no student should be able to point to a room they preferred and were eligible for that was given to a lower-priority student.</p>
<h2>Testing it</h2>
<p>To evaluate the allocation logic, I built a synthetic dataset of 51 student applications against 234 available rooms for the 2026/2027 academic year, written manually rather than generated randomly, to keep the mix of preferences, budgets, and accessibility needs realistic. Running this through the system produced:</p>
<ul>
<li><p><strong>94.1% allocation rate</strong> (48 of 51 students successfully allocated)</p>
</li>
<li><p><strong>87.5%</strong> of allocated students received one of their ranked preferences</p>
</li>
<li><p><strong>54.2%</strong> received their first choice</p>
</li>
</ul>
<p>Running the same dataset through the allocation process twice produced identical results, which mattered given the intent of the system: consistency, not variability, is a requirement for a fairness-sensitive process.</p>
<p>I also stress-tested the infrastructure directly. After SSHing into the EC2 instances, I installed the <code>stress</code> tool and ran <code>stress --cpu 2</code> to push CPU utilisation to 100%. Once utilisation crossed the 60% threshold configured on the scaling policy, both Auto Scaling Groups provisioned an additional instance each, and the load balancer correctly distributed traffic between the original and new instances.</p>
<h2>Finding a bug after submission</h2>
<p>After submitting the dissertation, I reviewed the test data again and found an error in the synthetic room dataset that had affected the allocation results reported above.</p>
<p>Each room record includes a <code>RoomInfoID</code> field linking it to an entry in its accommodation's list of room types, such as Single Ensuite, Studio Room, or Adapted Single Ensuite. In the seed data I had built, every room in every flat had been assigned the first <code>RoomInfoID</code> in that list rather than the one matching its actual room type. Because Adapted Single Ensuite happened to be listed first for several accommodations, most of the 234 rooms in the dataset were effectively mislabelled as accessible rooms, regardless of what they actually were.</p>
<p>This produced two failure modes. Because the algorithm correctly restricts accessible rooms to students who have declared an accessibility requirement, the majority of the room pool was incorrectly excluded from non-accessible students, forcing fallback allocations. Separately, students who had ranked a specific room type, a Studio Room, for example, could never be matched to it, because the system had recorded that room under the wrong type. Neither issue was a fault in the algorithm; it behaved exactly as designed against incorrect input data.</p>
<p>I corrected the room type labels in a new dataset (<code>Rooms_Patched.json</code>), without modifying the algorithm or any backend code, and reran the same 51 applications against the same 234 rooms:</p>
<table>
<thead>
<tr>
<th>Metric</th>
<th>Original dataset</th>
<th>Corrected dataset</th>
</tr>
</thead>
<tbody><tr>
<td>Successfully allocated</td>
<td>48 / 51 (94.1%)</td>
<td>51 / 51 (100%)</td>
</tr>
<tr>
<td>Unallocated</td>
<td>3 (5.9%)</td>
<td>0 (0%)</td>
</tr>
<tr>
<td>First choice matches</td>
<td>26 (54.2%)</td>
<td>45 (88.2%)</td>
</tr>
<tr>
<td>Second choice matches</td>
<td>7 (14.6%)</td>
<td>6 (11.8%)</td>
</tr>
<tr>
<td>Fallback allocations</td>
<td>6 (12.5%)</td>
<td>0 (0%)</td>
</tr>
<tr>
<td>Preference match rate</td>
<td>87.5%</td>
<td>100%</td>
</tr>
</tbody></table>
<p>With correct room type data, every student was successfully allocated, no fallback allocations were required, and 88.2% received their first choice. Re-running the corrected dataset produced identical results again, consistent with the determinism claimed in the dissertation.</p>
<p>I wrote this up as a formal re-evaluation report to make sure the correction and its impact on the results were clearly documented. It's also a useful reminder that a single incorrect field in seed data can affect an entire set of results without being obvious from the output alone.</p>
<h2>What I would do differently</h2>
<p>A few limitations are worth acknowledging. 51 applications is enough to demonstrate that the logic functions correctly, but it is far smaller than a real university deployment; the University of Leicester alone manages around 4,600 rooms, so a more representative test would need a substantially larger dataset, ideally generated programmatically rather than by hand. Contracts and invoices are currently generated client-side as PDFs on demand, which reduces storage costs but means no server-side copy exists unless the student downloads it. The PayPal client ID and secret are also currently stored as Lambda environment variables rather than in a dedicated secrets manager, which would be the more appropriate approach for a production deployment.</p>
<p>Given the chance to start over, I would build automated test data generation in from the outset rather than adding it later, which would likely have caught the <code>RoomInfoID</code> error before it reached a submitted result. I would also spend more time analysing DynamoDB access patterns before finalising the schema; the denormalised structure was adequate for a project of this scope but became harder to manage as more tables and relationships were introduced.</p>
<p>Beyond the technical work, this project extended further than anything I had built in previous coursework. I had some prior experience with React and a general familiarity with AWS, but had not previously combined Cognito, Amplify, Lambda, DynamoDB, PayPal integration, and auto-scaling infrastructure into a single system. Most of what I learned came from debugging integration issues rather than from building new features; getting IAM roles and Cognito authorizers configured consistently across different endpoints took considerably longer than expected, and was also where I gained the most practical understanding of how cloud security is actually implemented.</p>
<h2>Conclusion</h2>
<p>The project achieved what it set out to do. It is a working, deployed system that takes students through the full accommodation process, from application through to allocation, contract signing, and payment, running on cloud infrastructure that scales as intended. The version submitted for assessment reported a 94.1% allocation rate; after identifying and correcting the room data error, the corrected figures show a 100% allocation rate with 88.2% of students receiving their first choice, a more accurate reflection of the algorithm's actual performance. Infrastructure testing also confirmed that the scaling configuration behaves correctly under load.</p>
<p>A few things would need to happen before this system could realistically go into production: testing at a larger scale with a properly validated dataset, and possibly letting students rank more than four preferences to improve preference match rates in a larger deployment. As a final year project, however, it met its original aims: a system that is fair, scalable, and usable by both students and staff, rather than a proof of concept alone.</p>
<p>The full project is available on GitLab: <a href="https://gitlab.com/Arnav-Salian/CO3201"><strong>gitlab.com/Arnav-Salian/CO3201</strong></a></p>
]]></content:encoded></item><item><title><![CDATA[Evaluating Brave Origin as a Privacy-Focused Alternative to Chrome]]></title><description><![CDATA[Like most people, Chrome was my default browser for years. It just worked, fast, compatible, and backed by a familiar ecosystem of extensions. But as I started getting deeper into open-source software]]></description><link>https://docs.arnav.uk/evaluating-brave-origin-as-a-privacy-focused-alternative-to-chrome</link><guid isPermaLink="true">https://docs.arnav.uk/evaluating-brave-origin-as-a-privacy-focused-alternative-to-chrome</guid><category><![CDATA[Google Chrome]]></category><category><![CDATA[Brave Browser]]></category><category><![CDATA[brave origin]]></category><category><![CDATA[brave shield]]></category><category><![CDATA[ublock origin]]></category><category><![CDATA[waterfox]]></category><category><![CDATA[privacy]]></category><dc:creator><![CDATA[Arnav Salian]]></dc:creator><pubDate>Mon, 01 Jun 2026 14:34:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6767e8fe0ddd601305c860a0/f49130de-0e40-4ce0-9856-a42e1a2f0ae4.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Like most people, Chrome was my default browser for years. It just worked, fast, compatible, and backed by a familiar ecosystem of extensions. But as I started getting deeper into open-source software and privacy-respecting tools, I began to think more about how much of my data was being collected and used to support Google's advertising business.</p>
<p>Google Chrome is not just a browser, it is also deeply tied into Google's wider data collection and advertising ecosystem. So I started looking for something that kept the usability of Chrome without all of Google's proprietary services, background data collection, and tight integration with its advertising platform.</p>
<p>The obvious first stop was <strong>Firefox</strong>. It is the browser most people have heard of first, largely because it has been around for a long time and has consistently positioned itself as an alternative to Chrome. On paper, it makes sense as a recommendation because it is open source, developed by a non-profit organisation, and explicitly focused on user privacy and transparency.</p>
<p>But after actually using it day to day, a few things put me off. A fresh Firefox install comes with sponsored content on the new tab page, which already feels like the wrong direction for a privacy-focused browser. On top of that, Mozilla's 2024 policy changes caused a lot of backlash and raised trust concerns for many users. Then there is the practical side: some sites still work better on Chromium, and a lot of the extensions I relied on simply were not available in the Firefox add-on ecosystem.</p>
<p>That led me toward <strong>Chromium-based</strong> alternatives. Chromium, unlike Google Chrome, is the open-source project underneath the browser. It gives you the compatibility, extension support, and site reliability of Chrome, but without Google's telemetry, account integration, and ad-targeting infrastructure layered on top.</p>
<h2>The Privacy Browser Landscape</h2>
<p>After looking through privacy-focused browsers, two options stood out as bloat-free and worth paying attention to:</p>
<ul>
<li><p><a href="https://brave.com/origin/"><strong>Brave Origin</strong></a>, a stripped-down version of Brave built around privacy and minimalism.</p>
</li>
<li><p><a href="https://www.waterfox.com/"><strong>Waterfox</strong></a>, a Firefox-based browser for people who still want the Gecko engine without depending on Mozilla's standard build.</p>
</li>
</ul>
<p>This post focuses mainly on <strong>Brave Origin</strong>, with a detailed comparison against <strong>Waterfox</strong>, since Waterfox has become a genuinely serious privacy option in its own right rather than just a Firefox fork with the telemetry stripped out.</p>
<h2>What Brave Origin Is</h2>
<p>Brave Origin is a more minimal, privacy-first version of Brave. It keeps the parts of Brave that are actually useful for privacy and browsing, then remove the extras that make the standard Brave browser feel cluttered.</p>
<p>Standard Brave is not bad, but it does come with a lot of stuff I do not want in a browser. That includes Brave Rewards, Brave Wallet, Brave News, Brave Leo, Brave Talk, VPN features, and a handful of other built-in services. A lot of that can be turned off, but I would rather use a browser that does not ship with it in the first place.</p>
<p>Brave Origin removes that extra layer and keeps the core experience. What is left is a cleaner Chromium browser with strong built-in privacy features, Chrome extension support, and avoids unnecessary distractions.</p>
<h3>What Brave Origin Keeps</h3>
<ul>
<li><p><strong>Brave Shields</strong>, Brave's built-in ad and tracker blocker written natively into the browser.</p>
</li>
<li><p><strong>Fingerprint protections</strong>, including Brave's anonymised approach to making browser fingerprinting less reliable.</p>
</li>
<li><p><strong>Chromium extension support</strong>, including the Chrome Web Store.</p>
</li>
<li><p><strong>Widevine DRM support</strong>, which matters if you watch Netflix and other DRM-protected services in the browser.</p>
</li>
<li><p><strong>Native translation</strong>, which is genuinely useful and one of those features you miss once it is gone.</p>
</li>
<li><p><strong>Split View</strong>, for side-by-side browsing in the same window.</p>
</li>
<li><p><strong>Container support</strong>, which is a Firefox-style tab isolation feature for separating sessions, cookies, and storage.</p>
</li>
</ul>
<p>That last point is one of the things I like most about where Brave is heading. Containers are one of the most useful features Firefox has, and seeing Brave bring a similar concept to a Chromium browser is a big plus.</p>
<h3>Pricing and Availability</h3>
<p>Brave Origin launched as a stable, standalone product in June 2026, separate from the standard Brave browser, with Linux users getting it for free while Windows, macOS, Android, and iOS users pay a one-time $60 fee that covers up to 10 device activations. That pricing model makes sense in context because Brave Origin is being positioned as a stripped-down browser with no ads, no rewards system, and no extra monetisation layer.</p>
<p>On Linux, that makes Brave Origin especially appealing. You get the cleaner Brave experience without paying anything, which is a very strong deal for a browser that is trying to do privacy properly.</p>
<h2>Waterfox</h2>
<p><a href="https://www.waterfox.com/">Waterfox</a> is an independently developed, Firefox-based browser built entirely around privacy. It runs on Gecko rather than Chromium, strips out Mozilla's telemetry, sponsored content, and Pocket integration, and has recently started shipping meaningful privacy upgrades of its own rather than just trimming what Firefox already ships.</p>
<h3>What Waterfox Gets Right</h3>
<ul>
<li><p><strong>Zero telemetry by default</strong>, with all data collection, crash reporting, and remote experiments disabled and locked at build time.</p>
</li>
<li><p><strong>Oblivious DNS over HTTPS</strong>, which routes DNS queries through a relay so no single party can see both who you are and what you are looking up, a feature most mainstream browsers do not offer out of the box.</p>
</li>
<li><p><strong>Container tabs enabled by default</strong>, unlike Firefox, where the same feature needs an extension.</p>
</li>
<li><p><strong>Native ad blocking</strong>, now built directly into the browser using Brave's open-source adblock-rust engine rather than relying purely on an extension.</p>
</li>
<li><p><strong>Full Firefox extension support</strong>, including access to Mozilla's add-on store.</p>
</li>
<li><p><strong>Built-in sync and password manager</strong>, so tabs, history, bookmarks, and logins carry across devices without a separate tool.</p>
</li>
<li><p><strong>Native translation</strong>, built in for translating pages without needing an extension.</p>
</li>
<li><p><strong>Split view</strong>, for side-by-side browsing in the same window.</p>
</li>
<li><p><strong>Extension support on Android</strong>, which is rare among mobile browsers and lets you run the same privacy extensions you use on desktop.</p>
</li>
</ul>
<p>Waterfox genuinely holds its own against Brave Origin on features. The main practical difference is the underlying engine, Gecko instead of Chromium, which means a handful of sites optimised specifically for Chromium can occasionally behave slightly differently.</p>
<h2>Brave Shields vs uBlock Origin</h2>
<p>The most important comparison is between <strong>Brave Shields</strong> (Brave's built-in privacy protection) and <strong>uBlock Origin</strong> (a powerful ad-blocking extension), since each is the core privacy tool people reach for by default.</p>
<table>
<thead>
<tr>
<th>Feature</th>
<th>Brave Shields</th>
<th>uBlock Origin</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Integration</strong></td>
<td>Built directly into the browser</td>
<td>Runs as an extension</td>
</tr>
<tr>
<td><strong>Ad and tracker blocking</strong></td>
<td>Strong blocking with customisation through developer settings</td>
<td>Extremely strong blocking with deeper customisation</td>
</tr>
<tr>
<td><strong>Fingerprinting protection</strong></td>
<td>Includes Brave's own fingerprinting protections</td>
<td>More limited on its own without extra browser-level help</td>
</tr>
<tr>
<td><strong>Ease of use</strong></td>
<td>Better for people who want privacy without tweaking</td>
<td>Better for people who like custom filters and fine control</td>
</tr>
<tr>
<td><strong>Portability</strong></td>
<td>Brave only</td>
<td>Works across multiple browsers</td>
</tr>
</tbody></table>
<p>The short version is that both are good. Brave Shields is better if you want privacy protections deeply integrated into the browser with almost no setup. uBlock Origin is better if you want maximum control and the flexibility to tune exactly how blocking works.</p>
<p>Brave Origin also supports the uBlock Origin extension, so if you would rather have its filter lists and customisation, you can simply disable Brave Shields and run uBlock Origin instead. The same applies to Waterfox, which ships its own native ad blocker built on Brave's adblock-rust engine, but that can be disabled in settings in favour of uBlock Origin, since Waterfox still supports the full MV2 extension. In practice, both are excellent, and for most people the difference is negligible.</p>
<h2>Brave Origin vs Waterfox</h2>
<table>
<thead>
<tr>
<th>Feature</th>
<th>Brave Origin</th>
<th>Waterfox</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Engine</strong></td>
<td>Chromium-based</td>
<td>Gecko-based (Firefox fork)</td>
</tr>
<tr>
<td><strong>Price</strong></td>
<td>Free on Linux, $60 on Windows, macOS, Android, and iOS</td>
<td>Free</td>
</tr>
<tr>
<td><strong>Ad blocking</strong></td>
<td>Brave Shields, or uBlock Origin</td>
<td>Native ad blocker (Brave's adblock-rust engine), or uBlock Origin</td>
</tr>
<tr>
<td><strong>Fingerprinting protection</strong></td>
<td>Strong browser-level protections</td>
<td>Firefox-style anti-fingerprinting protections</td>
</tr>
<tr>
<td><strong>DRM support</strong></td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td><strong>Native translation</strong></td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td><strong>Split view</strong></td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td><strong>Containers</strong></td>
<td>Yes</td>
<td>Yes, enabled by default</td>
</tr>
<tr>
<td><strong>Sync</strong></td>
<td>Available in Brave's browser ecosystem</td>
<td>Built in</td>
</tr>
<tr>
<td><strong>Password manager</strong></td>
<td>Yes</td>
<td>Built in</td>
</tr>
<tr>
<td><strong>Oblivious DNS</strong></td>
<td>No</td>
<td>Yes, on by default</td>
</tr>
<tr>
<td><strong>Extension ecosystem</strong></td>
<td>Chrome Web Store</td>
<td>Firefox Add-ons</td>
</tr>
<tr>
<td><strong>Project backing</strong></td>
<td>Independent company</td>
<td>Small independent team</td>
</tr>
</tbody></table>
<p>This is where the decision becomes pretty simple. Waterfox is the clear pick if you want a fully free, cross-platform browser and you do not mind trading Chromium compatibility for the Gecko engine. Brave Origin is the better all-rounder if you want Chromium compatibility and Brave's specific fingerprinting model, and you either use Linux or are willing to pay for other platforms.</p>
<h2>Highly Recommended Extensions</h2>
<p>These extensions are available on both Chromium-based and Firefox-based browsers.</p>
<ul>
<li><p><a href="https://github.com/gorhill/uBlock"><strong>uBlock Origin</strong></a>: An open source ad blocker. On Brave Origin and Waterfox, both of which run their own native ad blocker by default, you can disable that built-in blocker and install uBlock Origin instead if you prefer its filter lists and customisation, since both browsers still support the full extension. On Chromium-based browsers, the full MV2 version is limited to a shrinking set of browsers, while Chrome and other MV3-only browsers are limited to <a href="https://github.com/uBlockOrigin/uBOL-home">uBlock Origin Lite</a>. On Firefox-based browsers, including Waterfox, the full MV2 version works without any restrictions.</p>
</li>
<li><p><a href="https://github.com/schomery/popup-blocker/"><strong>Popup Blocker (strict)</strong></a>: An open source lightweight extension that intercepts and blocks popup windows before they even open, rather than waiting for them to appear. It halts all requests for new windows and lets you permit or deny each one, with multiple requests presented in a list.</p>
</li>
</ul>
<h3>YouTube Only</h3>
<ul>
<li><p><a href="https://github.com/ajayyy/SponsorBlock"><strong>SponsorBlock</strong></a>: An open source crowdsourced extension that automatically skips sponsor segments in YouTube videos based on community submitted timestamps. It also supports skipping intros, outros, and subscribe reminders.</p>
</li>
<li><p><a href="https://github.com/Anarios/return-youtube-dislike"><strong>Return YouTube Dislike</strong></a>: An open-source extension that returns the YouTube dislike count. After Google removed the public dislike count from YouTube in November 2021, this extension restores it using a combination of scraped dislike stats and estimates extrapolated from extension user data, so you can judge content quality before watching.</p>
</li>
</ul>
<h2>Which Browser I Would Use</h2>
<p>On <strong>Linux</strong>, Brave Origin would be the primary browser and Waterfox would be the secondary one. Brave Origin gets the edge mainly because of its Chromium compatibility over Waterfox's Gecko engine, since I still run into the occasional site that behaves better or only works properly on Chromium. Brave Origin left beta and became a stable product in June 2026, so it is now a solid long-term option rather than something to wait on, and it is free on Linux too. I still use Waterfox as my secondary browser because it is fast, respects privacy by default.</p>
<p>On <strong>Windows</strong>, Waterfox makes more sense as the main browser for most people because Brave Origin costs $60 there while Waterfox is free and comes with almost all the features that Brave Origin has. The main exception is if Chromium-specific site compatibility or Brave's browser-level fingerprinting model matter enough to justify paying for Brave Origin.</p>
<p>On <strong>Android</strong>, I use Waterfox as my mobile browser of choice because it supports installing extensions on mobile, which is really useful. This means you can run the same extensions listed above, including uBlock Origin and Popup Blocker (strict), directly on your phone. This makes a significant difference to the browsing experience compared to most mobile browsers that offer no extension support at all.</p>
<h2>Conclusion</h2>
<p>For a long time, Chrome stayed on top because it was the easiest option. That is still true in a narrow sense, but it is no longer true if you care about privacy, open source, and reducing dependence on big tech browsers.</p>
<p>Brave Origin is one of the best Chromium-based options I have found if the goal is to get Chrome-like compatibility without Chrome's downsides, especially on Linux where it is free. Waterfox is also great, and on Windows it is probably the easier recommendation for most people unless Chromium-level compatibility matters to you. Between the two, there is now a very real case for leaving Chrome behind without sacrificing the browsing experience that made people stick with it in the first place.</p>
]]></content:encoded></item><item><title><![CDATA[Migrating from Windows 11 to Linux: A Practical Guide]]></title><description><![CDATA[So I finally did it. After two years of dual-booting, I made the full switch to Fedora KDE Plasma as my daily driver and I have not looked back. This post covers why I left Windows 11, why I chose Fed]]></description><link>https://docs.arnav.uk/migrating-from-windows-11-to-linux</link><guid isPermaLink="true">https://docs.arnav.uk/migrating-from-windows-11-to-linux</guid><category><![CDATA[Linux]]></category><category><![CDATA[Fedora]]></category><category><![CDATA[kde]]></category><category><![CDATA[Windows]]></category><dc:creator><![CDATA[Arnav Salian]]></dc:creator><pubDate>Mon, 01 Jun 2026 10:34:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6767e8fe0ddd601305c860a0/2c581d82-d08d-4268-ac48-c6d9706e727f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>So I finally did it. After two years of dual-booting, I made the full switch to Fedora KDE Plasma as my daily driver and I have not looked back. This post covers why I left Windows 11, why I chose Fedora, how I set everything up, and what my experience has been like since.</p>
<p>My machine is nothing special: an 11th Gen Intel Core i5-1135G7, Intel Iris Xe integrated graphics, 8 GB of RAM, and a 512 GB SSD. Not exactly high-end, which made Windows 11’s resource demands feel especially noticeable.</p>
<h2>Why I Left Windows 11</h2>
<h3>The Performance Problem</h3>
<p>The most immediate and frustrating issue was RAM usage. On idle, Windows 11 was consuming up to 7 GB of my 8 GB of RAM. On a machine with only 8 GB, that left virtually nothing for actual work. Having a few Chrome tabs open alongside Visual Studio Code was a genuine struggle. Multitasking felt like asking too much of a system that should, by all accounts, be able to handle it.</p>
<h3>A Buggy, Fragmented OS</h3>
<p>The early 2026 Windows updates made things significantly worse. The January and February 2026 updates introduced a wave of bugs that were widely reported and left unaddressed for far too long. Among the most common were telling Windows to shut down after an update only for it to restart instead, Wi-Fi adapters going missing entirely, black screens during boot, and Notepad failing to open. These problems reflect deeper stability concerns, surfacing across core components in ways that disrupt everyday use.</p>
<p>Beyond the bugs, Windows 11 has a deeper identity crisis with its UI. It is a patchwork of different design languages stitched together across decades. The modern Settings app sits alongside the classic Control Panel from older versions of Windows. The right-click context menu is a prime example of this regression. Microsoft buried the most-used options behind a "Show more options" click, adding an extra step to something you do dozens of times a day. Windows 11 also uses React for parts of its shell UI, and the result is a noticeably sluggish interface that feels resource-heavy for what it is actually doing.</p>
<h3>Forced AI Everywhere</h3>
<p>Microsoft's aggressive push of Copilot has become impossible to ignore. AI features have been pushed into Notepad, Paint, OneDrive in File Explorer, and seemingly every other corner of the OS whether you want them or not. The introduction of Microsoft Recall, a feature that continuously screenshots your activity, made it clear that Microsoft's priorities lie somewhere other than user privacy.</p>
<p>File Explorer also became increasingly unreliable. Search, one of the most basic OS features, is practically unusable. And if you uninstalled Copilot or OneDrive, neither of which you consented to installing in the first place, there was a real chance a future update would quietly reinstall them. For an OS you pay a licence fee for, shipping it with ads on the installation screen is hard to justify.</p>
<h3>Privacy, Telemetry, and Local Accounts</h3>
<p>Windows 11 is not open source. You have no visibility into what data is being collected or sent to Microsoft. The gradual removal of the local account option during setup makes this worse. Microsoft wants your account linked, which creates a persistent identity that can be tracked and fingerprinted. Telemetry is on by default and difficult to fully disable. For anyone who cares about privacy and data ownership, this is a dealbreaker.</p>
<h3>Lack of Customisation and Character</h3>
<p>Windows 11 has a corporate and generic feel to it. It has drifted far from what made Windows enjoyable, the personality it had in the Windows 7 and even Windows 10 era. Yes, there are third-party tools to work around most of these issues, but the fact that this is the default state of a modern operating system is telling. Windows has lost its way.</p>
<h2>Why Linux and Why Fedora KDE Plasma</h2>
<h3>The Case for Linux</h3>
<p>When it came to picking an alternative, the choice was between macOS and Linux. For me, it was not a hard decision. I care deeply about open source software: the transparency, the community, the philosophy. Linux ticks every box. No telemetry, no big tech tracking, better privacy by default, and you are in complete control of your system.</p>
<p>Linux also has a dramatically lower memory footprint. The OS itself idles at a fraction of what Windows uses, meaning the majority of your RAM is free for the applications you are actually running. On an 8 GB machine, this difference is significant.</p>
<h3>Choosing a Linux Distribution</h3>
<p>I had previous experience with Ubuntu, both in a dual-boot setup and at university. But Ubuntu has been drifting in a direction I am not comfortable with, especially with Snap packages being pushed over user preference and a general trajectory that feels too close to Microsoft's approach. I also have issues with GNOME, Ubuntu's default desktop environment. It has a macOS-like user interface that I do not enjoy, and it is less customisable than I would like.</p>
<p>What I wanted was a desktop that felt familiar, something closer to a Windows 10 layout, but with the flexibility to make it truly my own. KDE Plasma was the obvious answer. It is fast, highly customisable, and has a clean, intuitive layout that does not try to reinvent how a desktop should work.</p>
<p>For the distro itself, I wanted something that is bleeding edge but stable, shipping modern software quickly, but not at the cost of reliability. Fedora is exactly that. It ships newer kernels and software than many other distros while still feeling polished and dependable. Fedora also offers an official KDE Plasma spin, which made it a straightforward choice.</p>
<h2>Installation</h2>
<h3>Creating the Bootable USB</h3>
<p>Download the Fedora KDE Plasma ISO from the official Fedora website. Use Rufus on Windows to flash it to a USB drive. It is fast, simple, and reliable.</p>
<h3>BIOS Configuration</h3>
<p>Restart your machine and enter the BIOS, typically by pressing F2, F12, or Delete on boot depending on the manufacturer, or on Windows you can hold Shift while selecting Restart to access the advanced startup menu. Then you need to:</p>
<ul>
<li><p>Disable Secure Boot (Fedora supports it, but turning it off can help avoid potential compatibility issues).</p>
</li>
<li><p>Move the USB drive to the top of the boot order.</p>
</li>
</ul>
<p>Save and exit. Your machine should then boot from the USB into the Fedora live environment.</p>
<h3>Installing to Disk</h3>
<p>From the live environment, launch the installer. I chose to install Fedora to the full disk. After two years of dual-booting, I was ready to commit. Select your disk, confirm the partition layout, and proceed. You can also enable disk encryption during this step for added security. During setup, you create a local account, which is a refreshing change from being pushed into an online account.</p>
<p>Once the installation completes, shut down, remove the USB, and boot into your new Fedora installation.</p>
<h2>Post-Installation Setup</h2>
<p>The first thing to understand is that Linux is not a drop-in replacement for Windows. It is a different operating system with a different ecosystem, just as you would not expect macOS and Windows to be interchangeable. What follows is what I set up to make Fedora work the way I want it to.</p>
<h3>System Update</h3>
<p>Before anything else, update the system:</p>
<pre><code class="language-bash">sudo dnf upgrade
</code></pre>
<p>This pulls in the latest packages, kernel updates, and security patches. It is the first thing worth doing on a fresh install.</p>
<h3>Flatpak and Flathub</h3>
<p>Fedora supports Flatpak out of the box, but adding Flathub gives you access to a much larger app catalogue:</p>
<pre><code class="language-bash">flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
</code></pre>
<p>This makes it much easier to install desktop apps in a clean and simple way.</p>
<h3>Browser: Brave Origin</h3>
<p>I switched to Brave Origin, the privacy-focused browser from Brave. It has been great so far, and I plan to write a comparison of Chrome vs Brave Origin in a future post.</p>
<pre><code class="language-bash">curl -fsS https://dl.brave.com/install.sh | FLAVOR=origin CHANNEL=beta sh
</code></pre>
<h3>Office Suite: OnlyOffice</h3>
<p>Microsoft Office does not run natively on Linux, so I installed OnlyOffice as the closest open source alternative for Word, PowerPoint, and Excel-style work.</p>
<pre><code class="language-bash">flatpak install flathub org.onlyoffice.desktopeditors
</code></pre>
<p>It handles Microsoft file formats well and feels familiar enough for day-to-day work.</p>
<h3>Email Client: Thunderbird</h3>
<p>For email, I installed Thunderbird. It is open source, reliable, and a better replacement for Outlook if you want a desktop email client without the extra Microsoft features and services.</p>
<pre><code class="language-bash">flatpak install flathub org.mozilla.thunderbird_esr
</code></pre>
<h3>LaTeX: TeX Live Full</h3>
<p>Since I like using LaTeX for write-ups, academic writing, and similar work, having a full LaTeX setup was essential. Installing the full TeX Live scheme saves time later because you are much less likely to run into missing package issues when working on documents.</p>
<pre><code class="language-bash">sudo dnf install texlive-scheme-full
</code></pre>
<h3>Theming: Catppuccin Mocha</h3>
<p>One of KDE Plasma's biggest strengths is how deeply you can customise it. I installed the Catppuccin Mocha theme because it looks clean, modern, and gives the desktop more personality.</p>
<pre><code class="language-bash">git clone --depth=1 https://github.com/catppuccin/kde catppuccin-kde &amp;&amp; cd catppuccin-kde
./install.sh
</code></pre>
<p>Follow the prompts in the install script to apply it to the KDE Plasma desktop.</p>
<h3>Code Editor: Zed</h3>
<p>I have been using Zed as my primary code editor. It is open source, written in Rust, and feels extremely fast. Startup time is near-instant, it handles files smoothly, and the editing experience feels more lightweight than VS Code. That said, VS Code is still very good and I still use it because of its extension ecosystem. Both are good tools, just with different strengths.</p>
<pre><code class="language-bash">curl -f https://zed.dev/install.sh | sh
</code></pre>
<h3>Notes: Obsidian</h3>
<p>For notes and knowledge management, I installed Obsidian. Obsidian stores everything locally in Markdown files, which fits perfectly with the privacy-first direction of moving to Linux.</p>
<pre><code class="language-bash">flatpak install flathub md.obsidian.Obsidian
</code></pre>
<h3>Password Manager: Bitwarden</h3>
<p>Bitwarden is my password manager of choice. It is open source, cross-platform, and works well across desktop and browser environments.</p>
<pre><code class="language-bash">flatpak install flathub com.bitwarden.desktop
</code></pre>
<h3>Media Codecs, FFmpeg, and VLC</h3>
<p>Fedora does not ship with some proprietary media codecs by default because of licensing reasons. To get proper multimedia support, I enabled RPM Fusion and installed VLC:</p>
<pre><code class="language-bash">su -
dnf install https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm
dnf install https://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm
dnf install vlc
dnf install python-vlc
</code></pre>
<p>Once RPM Fusion is enabled, you can also install FFmpeg and other useful multimedia packages.</p>
<h2>After the Switch</h2>
<p>The difference has been significant. Fedora KDE Plasma has solved most of the problems I was facing with Windows 11.</p>
<ul>
<li><p>RAM usage is dramatically lower, which means there is finally room for actual applications and proper multitasking.</p>
</li>
<li><p>Everything feels faster and more responsive, from opening apps to browsing files.</p>
</li>
<li><p>Dolphin, the KDE file manager, is quick and search actually works.</p>
</li>
<li><p>There is no bloat on install, so the system feels clean from the start.</p>
</li>
<li><p>Wi-Fi works reliably.</p>
</li>
<li><p>There is no forced Copilot integration or AI being pushed into basic apps.</p>
</li>
<li><p>Most updates are straightforward with <code>sudo dnf upgrade &amp;&amp; flatpak update</code>, and they rarely require a restart.</p>
</li>
<li><p>I get a local account, more privacy, no telemetry, and no cloud storage tied directly into the file system.</p>
</li>
<li><p>Linux takes up less storage space, which leaves more room for applications and personal files.</p>
</li>
<li><p>KDE Plasma is highly customisable and gives the desktop actual personality.</p>
</li>
</ul>
<p>The switch does require some adjustment. Not every Windows application runs on Linux, and there is a learning curve around package managers, desktop environments, and terminal commands. But for the way I work, which is mostly coding, writing, research, and general productivity, Fedora KDE Plasma handles everything I need without getting in the way.</p>
<p>If you are on a mid-range or older machine being dragged down by Windows 11, Linux is worth serious consideration. Fedora KDE Plasma has been a great fit for me because it feels modern, stable, lightweight, and genuinely enjoyable to use.</p>
]]></content:encoded></item><item><title><![CDATA[Cloud to Self-Hosted: Switching from Google Photos to Immich]]></title><description><![CDATA[Introduction
Why switch from Google Photos to a self-hosted solution?
Google Photos has long been a convenient solution for storing and managing personal photos and videos. Its seamless integration wi]]></description><link>https://docs.arnav.uk/cloud-to-self-hosted-switching-from-google-photos-to-immich</link><guid isPermaLink="true">https://docs.arnav.uk/cloud-to-self-hosted-switching-from-google-photos-to-immich</guid><category><![CDATA[self-hosted]]></category><category><![CDATA[Immich]]></category><category><![CDATA[Google Photos]]></category><category><![CDATA[homeserver]]></category><category><![CDATA[Docker]]></category><category><![CDATA[nginx proxy manager]]></category><category><![CDATA[Photo Management]]></category><dc:creator><![CDATA[Arnav Salian]]></dc:creator><pubDate>Sun, 08 Jun 2025 05:03:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1749281797201/1d5a4d73-d8cd-4f72-8fb8-b9c5452f5e20.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1>Introduction</h1>
<h3>Why switch from Google Photos to a self-hosted solution?</h3>
<p>Google Photos has long been a convenient solution for storing and managing personal photos and videos. Its seamless integration with the broader Google ecosystem made it difficult for many users to consider alternatives. However, the transition from offering unlimited free storage to adopting a subscription-based model under Google One prompted many - including myself - to reconsider our reliance on traditional cloud storage. With an increasing number of services moving to subscription models, I find this trend inconvenient and unsustainable for long-term use.</p>
<p>Previously, <a href="https://support.google.com/photos/thread/111049414/google-photos-storage-policy-changes?hl=en">Google Photos offered free unlimited storage for certain formats, but this policy changed with the announcement in November 2020 that unlimited storage would end on June 1, 2021</a>. Since then, concerns have grown over long-term costs, data privacy, and the lack of control over personal media stored on big tech platforms.</p>
<p>While using the Google One plan - 200GB for £2.49/month - is pretty cheap, my decision to leave the service was not driven by cost. It was about regaining control over my data. I no longer believe entrusting my personal photo collection to a large corporation. In my view, our personal media should not be managed by tech giants whose priorities may not always align with user privacy.</p>
<p>So I decided to cancel the Google One subscription and switch to a self-hosted solution. This way, I have full control over my photos and videos, and I can manage the security and privacy myself.</p>
<h3>What is Immich and why I chose it over LibrePhotos or PhotoPrism?</h3>
<p><a href="https://immich.app/">Immich</a> is an open source self-hosted photo and video management solution. It lets users easily back up, organize, and manage their photos on their own server. Immich helps users browse, search and organize their photos and videos with ease, without sacrificing their privacy. Explore the live demo [<a href="https://demo.immich.app/">Open Demo</a>].</p>
<p>One of the main reasons I chose Immich was its modern user interface, which the developer intentionally designed to be similar to Google Photos, making it easy for users to get accustomed to. Unlike older alternatives like <a href="https://docs.librephotos.com/">LibrePhotos</a> or <a href="https://www.photoprism.app/">PhotoPrism</a>, Immich focuses on delivering a polished UI, mobile-first syncing, and smooth timeline organization. After testing all three photo management solutions, I found Immich faster and more polished. The mobile app and commitment to active development made it the clear choice for my home lab.</p>
<h3>Overview of the switching process</h3>
<p>The rest of the article covers the process I followed from planning to completion: preparing my self-hosted environment and setting up Immich. I configured secure local access using Nginx Proxy Manager with SSL for HTTPS, and I plan to enable remote access with secure VPN connection or Tailscale. I also compare the cost, scalability, and privacy of both platforms and share key lessons I learned along the way.</p>
<h1>Planning the Switch</h1>
<h3>Requirements for Hosting Immich</h3>
<p>Hosting Immich is quite straightforward - all you need is a server, which is essentially a computer that's always on and provides services, data, and resources to other devices over a network. This server can even be an old laptop you no longer use. For example, if you have a Windows laptop that became slow over time and you replaced it with a new one, you can repurpose the old laptop as a server by installing Ubuntu to improve its performance.</p>
<p>To store your photos and videos, make sure you have sufficient storage capacity; in my case, I use 2 TB of storage. Here are the basic requirements for hosting Immich:</p>
<ul>
<li><p>RAM: Minimum 4GB, recommended 6GB.</p>
</li>
<li><p>CPU: Minimum 2 cores, recommended 4 cores.</p>
</li>
<li><p>Persistent storage large enough to hold your entire photo and video library.</p>
</li>
<li><p>Docker support</p>
</li>
<li><p>Recommended: A domain name for setting up a reverse proxy with HTTPS.</p>
</li>
<li><p>Optional: Remote access configured via Tailscale or WireGuard for secure external connections.</p>
</li>
</ul>
<h3>Choosing the Right Hardware: NAS or Home Server?</h3>
<p>I had two hosting options:</p>
<ol>
<li><p><strong>NAS (Synology)</strong>: user-friendly and requires minimal setup, making it ideal for people who want a more hands-off experience. However, it comes with some limitations - if I used Synology, I would be tied to their software ecosystem. While it's possible to install third-party apps, it's not as flexible, and you don't have full control over the system. Switching away from their platform in the future or doing deep customisation can be difficult or even unsupported.</p>
</li>
<li><p><strong>Home Server</strong>: offers full control and flexibility. I can choose the operating system (like Ubuntu), configure services exactly the way I want, and switch platforms any time. This approach gives me complete freedom to run applications like Immich with Docker, fine-tune performance, and scale or change things as my needs grow.</p>
</li>
</ol>
<p>Ultimately, I chose a home server because it gives me full control over how I host and manage my media.</p>
<h1>Setting Up Immich (Linux)</h1>
<h3>Installing Immich on Docker</h3>
<p>The recommended way to install Immich is using Docker and Docker Compose. [<a href="https://immich.app/docs/install/docker-compose">Learn More</a>]</p>
<ol>
<li><p>Create a directory <code>./immich-app</code> to save the <code>docker-compose.yml</code> and <code>.env</code> files.</p>
<pre><code class="language-bash">mkdir ./immich-app
cd ./immich-app
</code></pre>
</li>
<li><p>Download these two files <a href="https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml"><code>docker-compose.yml</code></a> and <a href="https://github.com/immich-app/immich/releases/latest/download/example.env"><code>example.env</code></a> from your browser and move them to the directory that you created, in which case ensure that you rename <code>example.env</code> to <code>.env</code>. (<a href="https://github.com/immich-app/immich/releases">Find latest releases on Immich's GitHub</a>)</p>
</li>
<li><p>You can also choose to create the <code>.env</code> file and populate it with custom values.</p>
<pre><code class="language-bash"># You can find documentation for all the supported env variables at https://immich.app/docs/install/environment-variables

# The location where your uploaded files are stored
UPLOAD_LOCATION=./library

# The location where your database files are stored. Network shares are not supported for the database
DB_DATA_LOCATION=./postgres

# To set a timezone, uncomment the next line and change Etc/UTC to a TZ identifier from this list: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List
# TZ=Etc/UTC

# The Immich version to use. You can pin this to a specific version like "v1.71.0"
IMMICH_VERSION=release

# Connection secret for postgres. You should change it to a random password
# Please use only the characters `A-Za-z0-9`, without special characters or spaces
DB_PASSWORD=postgres

# The values below this line do not need to be changed
###################################################################################
DB_USERNAME=postgres
DB_DATABASE_NAME=immich
</code></pre>
<ul>
<li><p>Consider changing <code>DB_PASSWORD</code> to a custom value. Postgres is not publicly exposed, so this password is only used for local authentication. To avoid issues with Docker parsing this value, it is best to use only the characters <code>A-Za-z0-9</code>. <code>pwgen</code> is a handy utility for this.</p>
</li>
<li><p>Set your timezone by uncommenting the <code>TZ=</code> line.</p>
</li>
</ul>
</li>
<li><p>Edit your <code>docker-compose.yml</code> file to bind the Immich web port to localhost only. Locate the <code>ports</code> section for the <code>immich-server</code> service and change the line from <code>- '2283:2283'</code> to <code>- '127.0.0.1:2283:2283'</code></p>
<pre><code class="language-yaml">name: immich

services:
  immich-server:
    container_name: immich_server
    image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
    # extends:
    #   file: hwaccel.transcoding.yml
    #   service: cpu # set to one of [nvenc, quicksync, rkmpp, vaapi, vaapi-wsl] for accelerated transcoding
    volumes:
      # Do not edit the next line. If you want to change the media storage location on your system, edit the value of UPLOAD_LOCATION in the .env file
      - ${UPLOAD_LOCATION}:/usr/src/app/upload
      - /etc/localtime:/etc/localtime:ro
    env_file:
      - .env
    ports:
      - '127.0.0.1:2283:2283'
    depends_on:
      - redis
      - database
    restart: always
    healthcheck:
      disable: false

# REST OF FILE
</code></pre>
<p>This binds <code>127.0.0.1:2283:2283</code> in the Docker Compose file, which means the Immich server only listens on the local machine's loopback interface. As a result, it's not accessible directly from other devices on the network. Instead, the Nginx Proxy Manager handles external HTTPS requests to <a href="https://photos.local.domain.uk">https://photos.local.domain.uk</a> and securely forwards them to Immich on localhost, keeping the server protected behind the reverse proxy while managing SSL and external access.</p>
</li>
<li><p>From the directory you created in Step 1 run the following command to start Immich as a background service:</p>
<pre><code class="language-bash">docker compose up -d
</code></pre>
</li>
</ol>
<h3>Using a Reverse Proxy (Nginx Proxy Manager) with SSL for Local HTTPS</h3>
<ol>
<li><p>Create a directory <code>./nginx-proxy-manager</code> and inside it, create a <code>docker-compose.yml</code> file with the following configuration. [<a href="https://nginxproxymanager.com/guide/#quick-setup">Learn More</a>]</p>
<pre><code class="language-bash">services:
  app:
    image: 'jc21/nginx-proxy-manager:latest'
    restart: unless-stopped
    network_mode: "host"
    ports:
      - '80:80'
      - '81:81'
      - '443:443'
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt
</code></pre>
</li>
<li><p>Run the following command to start Nginx Proxy Manager as a background service:</p>
<pre><code class="language-bash">docker compose up -d
</code></pre>
</li>
<li><p>When your docker container is running, navigate to <code>http://&lt;your-machine-ip&gt;:81</code> for the admin interface.</p>
</li>
<li><p>Default Admin User:</p>
<pre><code class="language-plaintext">Email:    admin@example.com
Password: changeme
</code></pre>
<p>Immediately after logging in with this default user you will be asked to change your details and credentials.</p>
</li>
<li><p>Click on <strong>Hosts</strong>, then select <strong>Proxy Hosts</strong>, and click the <strong>New Proxy Host</strong> button. Enter your domain names - you can add multiple if needed. I chose a <code>.local</code> domain because it's only accessible within my local network; for example, I used <a href="https://photos.local.arnav.uk">https://photos.local.arnav.uk</a>. Next, set the <strong>Forward Hostname/IP</strong> to <code>127.0.0.1</code> and the <strong>Forward Port</strong> to <code>2283</code>.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749305962667/13cd4d3e-d4a8-4d3d-a65c-f95ab326e1fa.png" alt="" style="display:block;margin:0 auto" />
</li>
<li><p>Click on the <strong>SSL</strong> tab, then enable <strong>Force SSL</strong> and <strong>Use a DNS Challenge</strong>. For the DNS provider, choose <strong>Cloudflare</strong>, and finally, click to <strong>agree to the Let's Encrypt Terms of Service</strong>.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749306283722/4a588f5f-e4f5-41d3-a557-a8590b5cd63b.png" alt="" style="display:block;margin:0 auto" />
</li>
<li><p>In a New Tab go to Cloudflare and Search for <strong>API Tokens</strong> in the Cloudflare search bar or go directly to <a href="https://dash.cloudflare.com/profile/api-tokens">dash.cloudflare.com/profile/api-tokens</a>, then click on <strong>Create Token</strong>.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749306514338/cecfbf6f-f083-48f0-94f3-9dc67418d68a.png" alt="" style="display:block;margin:0 auto" />
</li>
<li><p>Then click on <strong>Use Template</strong> for <strong>Edit zone DNS</strong>.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749306641982/1e9da05e-90dc-4a4c-a8f1-19ba71babe4b.png" alt="" style="display:block;margin:0 auto" />
</li>
<li><p>Then select your domain name from the dropdown.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749306727830/2779605e-c41f-4ec5-a2ae-10fd0de59033.png" alt="" style="display:block;margin:0 auto" />
</li>
<li><p>Click <strong>Create Token</strong></p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749306784523/da9ecec4-939f-4427-b4de-42dc8805d4f2.png" alt="" style="display:block;margin:0 auto" />
</li>
<li><p>Copy your API token and save it securely in a safe place for future use.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749306868614/5772b912-e2dc-4a78-9850-3b4c357cf26b.png" alt="" style="display:block;margin:0 auto" />
</li>
<li><p>Replace the existing API Token with the one you copied from Cloudflare then click <strong>Save</strong>.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749306934322/9c757f6b-8cc8-4923-bc84-22fee204d284.png" alt="" style="display:block;margin:0 auto" />
</li>
<li><p>You should now see Online Status in the Proxy Hosts list.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749307034146/89ef492b-156d-4b47-a298-e2f0aac3664a.png" alt="" style="display:block;margin:0 auto" />
</li>
<li><p>Go to DNS Records and click <strong>Create New Record</strong>. Choose <code>A Record</code>, set the Name to <code>*.local</code> (to cover all subdomains), and enter your machine's IPv4 address as the value. Make sure to set it as DNS only (disable the proxy). To find your machine's IP address, you can run <code>ipconfig</code> on Windows or <code>ip a</code> on Linux/macOS in the terminal. Then click <strong>Save</strong>.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749307506804/8c42a39b-242b-47e2-b29f-c5ea88fd5344.png" alt="" style="display:block;margin:0 auto" />
</li>
<li><p>You can now access Immich using the domain name you set up - in my case it's <a href="https://photos.local.arnav.uk">https://photos.local.arnav.uk</a> - from any device within your local network, but it won't be accessible from outside your network.</p>
</li>
</ol>
<h3>Configuring Users, Partner Sharing, and Mobile App</h3>
<ol>
<li><p>If you have friends or family members who want to use the application as well, you can create additional accounts for them. [<a href="https://immich.app/docs/administration/user-management/">Learn More</a>]</p>
</li>
<li><p>Immich allows you to share your library with other users. They can then view your library and download the assets. You can manage Partner Sharing from the User Settings page on the web. [<a href="https://immich.app/docs/features/partner-sharing">Learn More</a>]</p>
</li>
<li><p>The mobile app can be downloaded from the following platforms: <a href="https://play.google.com/store/apps/details?id=app.alextran.immich">Google Play Store</a> / <a href="https://apps.apple.com/us/app/immich/id1613945652">Apple App Store</a> / <a href="https://github.com/immich-app/immich/releases">GitHub Releases (APK)</a>. [<a href="https://immich.app/docs/features/mobile-app/">Learn More</a>]</p>
<ol>
<li><p>Login to the mobile app using your server's endpoint URL at <code>https://photos.local.domain.uk</code> (replace this with your own domain name).</p>
</li>
<li><p>Navigate to the backup screen and select which album(s) you want to back up to the Immich server.</p>
<img src="https://immich.app/assets/images/album-selection-fbf8bc25cd8a8d504f4fbb48ed317a53.webp" alt="" />
</li>
<li><p>Scroll down to the bottom and press "Start Backup" to start the backup process. This will upload all the assets in the selected albums.</p>
</li>
</ol>
</li>
</ol>
<h3>Optional: Setting Up Immich with Tailscale or WireGuard to Access Immich Remotely</h3>
<p>[Implementation Pending]</p>
<h1>Cost, Privacy, and Scalability</h1>
<h3>Trade-Offs Between Self-Hosting and Google One Subscription</h3>
<table>
<thead>
<tr>
<th><strong>Category</strong></th>
<th><strong>Self-Hosting (Home Server / NAS)</strong></th>
<th><strong>Google One</strong></th>
</tr>
</thead>
<tbody><tr>
<td><strong>Initial Setup Cost</strong></td>
<td>Depends on existing hardware (<em>NAS or Home Server required</em>)</td>
<td>£0</td>
</tr>
<tr>
<td><strong>Monthly Storage Cost</strong></td>
<td>£0 (<em>uses local disks</em>)</td>
<td>£7.99</td>
</tr>
<tr>
<td><strong>Annual Cost (Est.)</strong></td>
<td>Effectively £0 <em>(only minor electricity cost)</em></td>
<td>£95.88/year</td>
</tr>
<tr>
<td><strong>Current Storage Capacity</strong></td>
<td>2TB (<em>current setup</em>)</td>
<td>2TB</td>
</tr>
<tr>
<td><strong>Upgrade Path</strong></td>
<td>Add/replace drives (<em>e.g. add another HDD or SSD</em>)</td>
<td>Upgrade to 5TB plan at £19.99/month</td>
</tr>
<tr>
<td><strong>Backup</strong></td>
<td>✅ Optional – external SSD/HDD backup</td>
<td>✅ Included</td>
</tr>
<tr>
<td><strong>Data Ownership</strong></td>
<td>✅ Full control, private and secure</td>
<td>❌ Google manages and accesses metadata</td>
</tr>
<tr>
<td><strong>Access from Anywhere</strong></td>
<td>✅ Possible via VPN or Tailscale</td>
<td>✅ Available by default</td>
</tr>
<tr>
<td><strong>Maintenance</strong></td>
<td>⚠️ Requires manual updates and system upkeep</td>
<td>✅ No maintenance required</td>
</tr>
<tr>
<td><strong>Customization</strong></td>
<td>✅ Highly customizable (<em>features, interface, add-ons</em>)</td>
<td>❌ Limited to Google's options</td>
</tr>
<tr>
<td><strong>Privacy</strong></td>
<td>✅ 100% local – no third-party access</td>
<td>❌ Data resides in Google's Cloud</td>
</tr>
</tbody></table>
<p>Google One Subscription Plans: <a href="https://one.google.com/about/plans">https://one.google.com/about/plans</a></p>
<h1>Review and Conclusion</h1>
<h3>Understanding Ports, Networking, and Remote Access</h3>
<img src="https://cdn.hashnode.com/uploads/covers/6767e8fe0ddd601305c860a0/8df08d2e-ec85-4208-a76e-dbeaeb2364cf.png" alt="" style="display:block;margin:0 auto" />

<h3>Why Self-Hosting Is Worth It for Photos</h3>
<p>Despite a few initial challenges, the result is a fully self-hosted, fast, and modern photo management solution. Immich performs as well as - or even better than - Google Photos in many ways. Now that I've successfully set up a self-hosted photo management service, I am ready to explore hosting more services in the future, particularly <a href="https://nextcloud.com/">Nextcloud</a> for file syncing and collaboration and automatic SSD backups for cold storage. Knowing that all my media is fully owned and controlled by me makes the effort completely worthwhile.</p>
<h1>Acknowledgement</h1>
<p>Some of the content and instructions in this article have been adapted from the official <strong>Immich</strong> and <strong>Nginx Proxy Manager</strong> documentation to provide an easy-to-follow explanation and streamline the setup process. Full credit goes to the development teams of both projects for their thorough and helpful resources.</p>
<ul>
<li><p><strong>Immich</strong> – for providing an open-source self-hosted photo and video management solution. <a href="https://immich.app/">https://immich.app/</a></p>
</li>
<li><p><strong>Nginx Proxy Manager</strong> - for reverse proxy with SSL for HTTPS. <a href="https://nginxproxymanager.com/">https://nginxproxymanager.com/</a></p>
</li>
<li><p><strong>Docker and Docker Compose</strong> - for containerizing and managing the application setup. <a href="https://www.docker.com/">https://www.docker.com/</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Basic AWS Network Architecture Deployment]]></title><description><![CDATA[AWS Network Diagram


The AWS network diagram illustrates the setup of a Virtual Private Cloud (VPC) with public and private subnets in a single Availability Zone (AZ). It includes the creation of EC2]]></description><link>https://docs.arnav.uk/basics-of-aws-networking</link><guid isPermaLink="true">https://docs.arnav.uk/basics-of-aws-networking</guid><category><![CDATA[AWS]]></category><category><![CDATA[ec2]]></category><category><![CDATA[architecture]]></category><category><![CDATA[networking]]></category><category><![CDATA[arnav.uk]]></category><category><![CDATA[arnavdocs]]></category><dc:creator><![CDATA[Arnav Salian]]></dc:creator><pubDate>Mon, 23 Dec 2024 18:34:02 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6767e8fe0ddd601305c860a0/d14519a0-ac9e-406e-99b1-e6700dec39ba.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>AWS Network Diagram</h2>
<img src="https://cdn.hashnode.com/uploads/covers/6767e8fe0ddd601305c860a0/7f193937-f7dc-466d-a49d-7edf3542824b.png" alt="" style="display:block;margin:0 auto" />

<p>The AWS network diagram illustrates the setup of a Virtual Private Cloud (VPC) with public and private subnets in a single Availability Zone (AZ). It includes the creation of EC2 instances, route tables, an Internet Gateway, and a NAT Gateway, ensuring secure communication between the instances within the VPC and external services.</p>
<h2>Converting Diagram into AWS Network</h2>
<h3>Creating Virtual Private Cloud</h3>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734970981690/9217aee5-a390-48e0-9661-13580856de23.png" alt="" style="display:block;margin:0 auto" />

<p>The IPv4 CIDR block for the VPC was configured as <code>10.0.0.0/16</code>, which provides 65,536 IP addresses to accommodate the network.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734972659598/67ccc789-f3fc-44b7-8a7b-d440e079722e.png" alt="" style="display:block;margin:0 auto" />

<p>The first VPC shown is the default VPC.</p>
<h3>Creating Subnets</h3>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734972159468/772e3df7-76b0-4c71-a152-4f7e1f8159f4.png" alt="" style="display:block;margin:0 auto" />

<p>The newly created VPC (<code>new-vpc</code>) was selected for subnet creation.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734972200337/2498d8d9-47d8-4f8e-a15f-68c7dff07c39.png" alt="" style="display:block;margin:0 auto" />

<p>For the first subnet, a <code>PublicSubnet</code> was created in Availability Zone <code>eu-west-2a</code>, with an IPv4 CIDR block of <code>10.0.0.0/24</code> (within the VPC CIDR block).</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734972282980/7ef8b122-0998-48e0-91c8-17367c035889.png" alt="" style="display:block;margin:0 auto" />

<p>A <strong>PrivateSubnet</strong> was created in the same Availability Zone (AZ) of <code>eu-west-2a</code>. While it's typically recommended to distribute public and private subnets across different AZs for high availability, a single AZ was used here for simplicity. Since the <code>10.0.0.0/24</code> block was already assigned to the <strong>PublicSubnet</strong>, <code>10.0.1.0/24</code> was used for the <strong>PrivateSubnet</strong>, which still falls within the VPC's CIDR block.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734972627818/ad78e8c6-557a-47eb-bf09-e6ee4310e4c2.png" alt="" style="display:block;margin:0 auto" />

<h3>Launching a Public EC2 Instance</h3>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734972878775/b8e5788c-03c1-47f0-9bbc-5bb010678c82.png" alt="" style="display:block;margin:0 auto" />

<p>A new EC2 instance called <code>PublicInstance</code> was launched, using the default AMI and the <code>t2.micro</code> instance type, which is free-tier eligible.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734972982689/a79536ff-7bc3-4e65-b6e6-6ce96c0e3fd6.png" alt="" style="display:block;margin:0 auto" />

<p>A new key pair, <code>my-key-pair</code>, was created to allow SSH access to the instance.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6767e8fe0ddd601305c860a0/dd42c369-347a-4be5-ad87-8aae807596ed.png" alt="" style="display:block;margin:0 auto" />

<p>The network settings were edited to deploy <code>PublicInstance</code> in the <code>PublicSubnet</code>, assign a public IP, and use the default security group (<code>PublicSecurityGroup</code>).</p>
<h3>Creating an Internet Gateway</h3>
<img src="https://cdn.hashnode.com/uploads/covers/6767e8fe0ddd601305c860a0/10d8229d-486f-4d84-8ca4-d0d16d032aa6.png" alt="" style="display:block;margin:0 auto" />

<p>An Internet Gateway was created and attached to the VPC to enable internet access for public instances.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6767e8fe0ddd601305c860a0/098103cc-6870-4d9e-a50d-c7752a24cbae.png" alt="" style="display:block;margin:0 auto" />

<h3>Creating Route Tables</h3>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734973626184/da9b8f0e-8707-4fa0-b59b-0460661a219f.png" alt="" style="display:block;margin:0 auto" />

<p>The default route table allows communication between <code>Public</code> and <code>Private</code> subnets by default, as indicated by the <code>local</code> route.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734973847316/5a4cb304-d2cc-4b5d-bad9-a95e1ee35813.png" alt="" style="display:block;margin:0 auto" />

<p>Explicit subnet associations are required for both the Public and Private Route Tables.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734973919926/d3fb8258-9cab-40df-a278-284fb45ae7cf.png" alt="" style="display:block;margin:0 auto" />

<p>Here, the <code>PublicSubnet</code> was associated with the <code>PublicRouteTable</code>.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734973959491/3618b553-c1c5-454b-9031-b51e20b100a8.png" alt="" style="display:block;margin:0 auto" />

<p>Next, the <code>PrivateSubnet</code> was associated with the <code>PrivateRouteTable</code>.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734974002897/223bd51f-52b4-422a-801e-03e75d490306.png" alt="" style="display:block;margin:0 auto" />

<p>The route tables have been successfully associated with the respective subnets.</p>
<h3>Allowing Route to Internet Gateway</h3>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734974152835/4de4a28b-dfef-44de-b0ee-aebfb57ee6eb.png" alt="" style="display:block;margin:0 auto" />

<p>A route was added to the <code>PublicRouteTable</code> with <code>0.0.0.0/0</code> targeting the Internet Gateway. This allows <code>PublicInstance</code> to connect to the internet.</p>
<h3>Connecting via EC2 Instance Connect</h3>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734974340991/3354ba0e-c36e-43c0-a51d-2c71325543b2.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734974470977/81fc804b-efe0-475d-b814-322d24edb02a.png" alt="" style="display:block;margin:0 auto" />

<p>The internet connection was tested by running <code>sudo yum update -y</code>, which succeeded, confirming the internet route was working.</p>
<h3>Launching a Private EC2 Instance</h3>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734974641863/d42bb376-22ab-452a-9c3c-80649cf7ee49.png" alt="" style="display:block;margin:0 auto" />

<p>A new EC2 instance named <code>PrivateInstance</code> was launched with default settings, using the existing <code>my-key-pair</code> key pair for SSH access.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6767e8fe0ddd601305c860a0/506557a0-687c-4bbf-9f88-1c0357ad9941.png" alt="" style="display:block;margin:0 auto" />

<p>The instance was placed in the <code>PrivateSubnet</code> without a public IP, using the default <code>PrivateSecurityGroup</code>.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734975533424/0e0152ec-2089-4990-849e-dac978f0aab8.png" alt="" style="display:block;margin:0 auto" />

<p>Using SCP, the key pair was uploaded to <code>PublicInstance</code> to enable SSH access to the <code>PrivateInstance</code>.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734975575813/2b59a3e4-e6b3-40ec-8bb0-024fb225b4a3.png" alt="" style="display:block;margin:0 auto" />

<p>The key pair was successfully uploaded to the <code>PublicInstance</code>.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734975871527/181f022a-d423-446f-bc61-a560a26a39dd.png" alt="" style="display:block;margin:0 auto" />

<p>Access to <code>PrivateInstance</code> was confirmed, since traffic is allowed between the two subnets by default. However, the <code>PrivateInstance</code> does not have internet access.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734975983328/d8711ecf-0c76-4573-9eef-e8a0d7f9d6c4.png" alt="" style="display:block;margin:0 auto" />

<p>Attempting to run <code>sudo yum update -y</code> on <code>PrivateInstance</code> failed, since there is no internet access.</p>
<h3>Creating a NAT Gateway</h3>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734976215951/a0152ebd-37f2-45a5-8808-a856e3a0e726.png" alt="" style="display:block;margin:0 auto" />

<p>A NAT Gateway was created in the <code>PublicSubnet</code>, allowing instances in private subnets to access the internet without allowing external services to initiate connections. The NAT Gateway was allocated an Elastic IP.</p>
<div>
<div>❗</div>
<div><strong>Important</strong>: NAT Gateways are billed hourly plus per-GB for data processed, even when idle, and Elastic IP incurs charges too. Remember to delete the NAT Gateway and release its Elastic IP once you're done with the lab.</div>
</div>

<h3>Adding Route to NAT Gateway</h3>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734976450012/33629570-ba76-48f0-93b9-57d59a359502.png" alt="" style="display:block;margin:0 auto" />

<p>A route was added in the <code>PrivateRouteTable</code>, setting <code>0.0.0.0/0</code> as the destination and the newly created NAT Gateway as the target.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734976609409/808a239c-deb7-4ef6-82df-bf3b6c47ed39.png" alt="" style="display:block;margin:0 auto" />

<p>This allows <code>PrivateInstance</code> to access the internet through the NAT Gateway, while external services cannot initiate a connection with it.</p>
<h2>Conclusion</h2>
<p>This AWS setup provides a solid network architecture with proper segmentation between public and private subnets. By leveraging Network Access Control Lists (NACLs), additional security layers are added to restrict or allow traffic at the subnet level, offering more control over inbound and outbound traffic. This ensures a secure and organised VPC setup with controlled access to and from the internet for both public and private resources.</p>
]]></content:encoded></item></channel></rss>