<?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><generator>RSS for Node</generator><lastBuildDate>Fri, 15 May 2026 05:03:13 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[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 with the broader Google ecosystem made it difficult ...]]></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 id="heading-introduction">Introduction</h1>
<h3 id="heading-why-switch-from-google-photos-to-a-self-hosted-solution">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 target="_blank" 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 id="heading-what-is-immich-and-why-i-chose-it-over-librephotos-or-photoprism">What is Immich and why I chose it over LibrePhotos or PhotoPrism?</h3>
<p><a target="_blank" 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 target="_blank" 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 target="_blank" href="https://docs.librephotos.com/">LibrePhotos</a> or <a target="_blank" 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 id="heading-overview-of-the-switching-process">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 id="heading-planning-the-switch">Planning the Switch</h1>
<h3 id="heading-requirements-for-hosting-immich">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 id="heading-choosing-the-right-hardware-nas-or-home-server">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 id="heading-setting-up-immich-linux">Setting Up Immich (Linux)</h1>
<h3 id="heading-installing-immich-on-docker">Installing Immich on Docker</h3>
<p>The recommended way to install Immich is using Docker and Docker Compose. [<a target="_blank" href="https://immich.app/docs/install/docker-compose">Learn More</a>]</p>
<ol>
<li>Create a directory <code>./immich-app</code> to save the <code>docker-compose.yml</code> and <code>.env</code> files.</li>
</ol>
<pre><code class="lang-bash">mkdir ./immich-app
<span class="hljs-built_in">cd</span> ./immich-app
</code></pre>
<ol start="2">
<li><p>Download these two files <a target="_blank" href="https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml"><code>docker-compose.yml</code></a> and <a target="_blank" 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 target="_blank" 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>
</li>
</ol>
<pre><code class="lang-bash"><span class="hljs-comment"># You can find documentation for all the supported env variables at https://immich.app/docs/install/environment-variables</span>

<span class="hljs-comment"># The location where your uploaded files are stored</span>
UPLOAD_LOCATION=./library

<span class="hljs-comment"># The location where your database files are stored. Network shares are not supported for the database</span>
DB_DATA_LOCATION=./postgres

<span class="hljs-comment"># 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</span>
<span class="hljs-comment"># TZ=Etc/UTC</span>

<span class="hljs-comment"># The Immich version to use. You can pin this to a specific version like "v1.71.0"</span>
IMMICH_VERSION=release

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

<span class="hljs-comment"># The values below this line do not need to be changed</span>
<span class="hljs-comment">###################################################################################</span>
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>
<ol start="4">
<li>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></li>
</ol>
<pre><code class="lang-yaml"><span class="hljs-attr">name:</span> <span class="hljs-string">immich</span>

<span class="hljs-attr">services:</span>
  <span class="hljs-attr">immich-server:</span>
    <span class="hljs-attr">container_name:</span> <span class="hljs-string">immich_server</span>
    <span class="hljs-attr">image:</span> <span class="hljs-string">ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}</span>
    <span class="hljs-comment"># extends:</span>
    <span class="hljs-comment">#   file: hwaccel.transcoding.yml</span>
    <span class="hljs-comment">#   service: cpu # set to one of [nvenc, quicksync, rkmpp, vaapi, vaapi-wsl] for accelerated transcoding</span>
    <span class="hljs-attr">volumes:</span>
      <span class="hljs-comment"># 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</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">${UPLOAD_LOCATION}:/usr/src/app/upload</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">/etc/localtime:/etc/localtime:ro</span>
    <span class="hljs-attr">env_file:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">.env</span>
    <span class="hljs-attr">ports:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">'127.0.0.1:2283:2283'</span>
    <span class="hljs-attr">depends_on:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">redis</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">database</span>
    <span class="hljs-attr">restart:</span> <span class="hljs-string">always</span>
    <span class="hljs-attr">healthcheck:</span>
      <span class="hljs-attr">disable:</span> <span class="hljs-literal">false</span>

<span class="hljs-comment"># REST OF FILE</span>
</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 target="_blank" 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>
<ol start="4">
<li>From the directory you created in Step 1 run the following command to start Immich as a background service:</li>
</ol>
<pre><code class="lang-bash">docker compose up -d
</code></pre>
<h3 id="heading-using-a-reverse-proxy-nginx-proxy-manager-with-ssl-for-local-https">Using a Reverse Proxy (Nginx Proxy Manager) with SSL for Local HTTPS</h3>
<ol>
<li>Create a directory <code>./nginx-proxy-manager</code> and inside it, create a <code>docker-compose.yml</code> file with the following configuration. [<a target="_blank" href="https://nginxproxymanager.com/guide/#quick-setup">Learn More</a>]</li>
</ol>
<pre><code class="lang-bash">services:
  app:
    image: <span class="hljs-string">'jc21/nginx-proxy-manager:latest'</span>
    restart: unless-stopped
    network_mode: <span class="hljs-string">"host"</span>
    ports:
      - <span class="hljs-string">'80:80'</span>
      - <span class="hljs-string">'81:81'</span>
      - <span class="hljs-string">'443:443'</span>
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt
</code></pre>
<ol start="2">
<li>Run the following command to start Nginx Proxy Manager as a background service:</li>
</ol>
<pre><code class="lang-bash">docker compose up -d
</code></pre>
<ol start="3">
<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>
</li>
</ol>
<pre><code class="lang-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>
<ol start="5">
<li>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 target="_blank" 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>.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749305962667/13cd4d3e-d4a8-4d3d-a65c-f95ab326e1fa.png" alt class="image--center mx-auto" /></p>
<ol start="6">
<li>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>.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749306283722/4a588f5f-e4f5-41d3-a557-a8590b5cd63b.png" alt class="image--center mx-auto" /></p>
<ol start="7">
<li>In a New Tab go to Cloudflare and Search for <strong>API Tokens</strong> in the Cloudflare search bar or go directly to <a target="_blank" href="https://dash.cloudflare.com/profile/api-tokens">dash.cloudflare.com/profile/api-tokens</a>, then click on <strong>Create Token</strong>.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749306514338/cecfbf6f-f083-48f0-94f3-9dc67418d68a.png" alt class="image--center mx-auto" /></p>
<ol start="8">
<li>Then click on <strong>Use Template</strong> for <strong>Edit zone DNS</strong>.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749306641982/1e9da05e-90dc-4a4c-a8f1-19ba71babe4b.png" alt class="image--center mx-auto" /></p>
<ol start="9">
<li>Then select your domain name from the dropdown.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749306727830/2779605e-c41f-4ec5-a2ae-10fd0de59033.png" alt class="image--center mx-auto" /></p>
<ol start="10">
<li>Click <strong>Create Token</strong></li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749306784523/da9ecec4-939f-4427-b4de-42dc8805d4f2.png" alt class="image--center mx-auto" /></p>
<ol start="11">
<li>Copy your API token and save it securely in a safe place for future use.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749306868614/5772b912-e2dc-4a78-9850-3b4c357cf26b.png" alt class="image--center mx-auto" /></p>
<ol start="12">
<li>Replace the existing API Token with the one you copied from Cloudflare then click <strong>Save</strong>.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749306934322/9c757f6b-8cc8-4923-bc84-22fee204d284.png" alt class="image--center mx-auto" /></p>
<ol start="13">
<li>You should now see Online Status in the Proxy Hosts list.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749307034146/89ef492b-156d-4b47-a298-e2f0aac3664a.png" alt class="image--center mx-auto" /></p>
<ol start="14">
<li>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>.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749307506804/8c42a39b-242b-47e2-b29f-c5ea88fd5344.png" alt class="image--center mx-auto" /></p>
<ol start="15">
<li>You can now access Immich using the domain name you set up - in my case it’s <a target="_blank" 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.</li>
</ol>
<h3 id="heading-configuring-users-partner-sharing-and-mobile-app">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 target="_blank" 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 target="_blank" 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 target="_blank" href="https://play.google.com/store/apps/details?id=app.alextran.immich">Google Play Store</a> / <a target="_blank" href="https://apps.apple.com/us/app/immich/id1613945652">Apple App Store</a> / <a target="_blank" href="https://github.com/immich-app/immich/releases">GitHub Releases (APK)</a>. [<a target="_blank" 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>
<p> <img src="https://immich.app/assets/images/album-selection-fbf8bc25cd8a8d504f4fbb48ed317a53.webp" alt /></p>
</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 id="heading-optional-setting-up-immich-with-tailscale-or-wireguard-to-access-immich-remotely">Optional: Setting Up Immich with Tailscale or WireGuard to Access Immich Remotely</h3>
<p>[Implementation Pending]</p>
<h1 id="heading-cost-privacy-and-scalability">Cost, Privacy, and Scalability</h1>
<h3 id="heading-trade-offs-between-self-hosting-and-google-one-subscription">Trade-Offs Between Self-Hosting and Google One Subscription</h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Category</strong></td><td><strong>Self-Hosting (Home Server / NAS)</strong></td><td><strong>Google One</strong></td></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>
</div><p>Google One Subscription Plans: <a target="_blank" href="https://one.google.com/about/plans">https://one.google.com/about/plans</a></p>
<h1 id="heading-review-and-conclusion">Review and Conclusion</h1>
<h3 id="heading-understanding-ports-networking-and-remote-access">Understanding Ports, Networking, and Remote Access</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749357956881/78b104a0-8e23-4adc-9929-3636e7b586c4.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-why-self-hosting-is-worth-it-for-photos">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 target="_blank" 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 id="heading-acknowledgement">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 target="_blank" 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 target="_blank" 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 target="_blank" href="https://www.docker.com/">https://www.docker.com/</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[AWS Network Architecture Deployment Documentation]]></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 instances, route tables, an Internet Gateway, and ...]]></description><link>https://docs.arnav.uk/basics-of-aws-networking--deleted</link><guid isPermaLink="true">https://docs.arnav.uk/basics-of-aws-networking--deleted</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/res/hashnode/image/upload/v1734970423618/73283928-3b88-4480-a6e2-11713374595b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-aws-network-diagram">AWS Network Diagram</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734969601389/c007faad-2160-4b16-b3c3-bbf7bd813fc1.png" alt class="image--center mx-auto" /></p>
<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 id="heading-converting-diagram-into-aws-network">Converting Diagram into AWS Network</h2>
<h3 id="heading-creating-virtual-private-cloud">Creating Virtual Private Cloud</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734970981690/9217aee5-a390-48e0-9661-13580856de23.png" alt class="image--center mx-auto" /></p>
<p>I configured the IPv4 CIDR block for the VPC as <code>10.0.0.0/16</code>, which provides 65,536 IP addresses to accommodate the network.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734972659598/67ccc789-f3fc-44b7-8a7b-d440e079722e.png" alt class="image--center mx-auto" /></p>
<p>The first VPC is the default VPC.</p>
<h3 id="heading-creating-subnets">Creating Subnets</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734972159468/772e3df7-76b0-4c71-a152-4f7e1f8159f4.png" alt class="image--center mx-auto" /></p>
<p>I selected the newly created VPC (<code>new-vpc</code>) for subnet creation.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734972200337/2498d8d9-47d8-4f8e-a15f-68c7dff07c39.png" alt class="image--center mx-auto" /></p>
<p>For the first subnet, I created a <code>PublicSubnet</code> 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>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734972282980/7ef8b122-0998-48e0-91c8-17367c035889.png" alt class="image--center mx-auto" /></p>
<p>I will create a <strong>PrivateSubnet</strong> 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, I will use a single AZ for simplicity in this setup. Since the <code>10.0.0.0/24</code> block is already assigned to the <strong>PublicSubnet</strong>, I will use <code>10.0.1.0/24</code> for the <strong>PrivateSubnet</strong>, which still falls within the VPC's CIDR block.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734972627818/ad78e8c6-557a-47eb-bf09-e6ee4310e4c2.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-launching-a-public-ec2-instance">Launching a Public EC2 Instance</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734972878775/b8e5788c-03c1-47f0-9bbc-5bb010678c82.png" alt class="image--center mx-auto" /></p>
<p>I launched a new EC2 instance called <code>PublicInstance</code>, selecting the default AMI and the <code>t2.micro</code> instance type, which is free-tier eligible.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734972982689/a79536ff-7bc3-4e65-b6e6-6ce96c0e3fd6.png" alt class="image--center mx-auto" /></p>
<p>A new key pair, <code>my-key-pair</code>, was created to allow SSH access to the instance.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734973035388/f977325a-66d3-4f9f-8dae-e3c43349ecce.png" alt class="image--center mx-auto" /></p>
<p>I edited the network settings to deploy <code>PublicInstance</code> in the <code>PublicSubnet</code>, assigned a public IP, and used the default security group (<code>PublicSecurityGroup</code>).</p>
<h3 id="heading-creating-an-internet-gateway">Creating an Internet Gateway</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734973394404/c10743c0-7f9b-4e82-9af8-6fde548080db.png" alt class="image--center mx-auto" /></p>
<p>An Internet Gateway was created and attached to the VPC to enable internet access for public instances.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734973460980/5113e74c-82a1-4ae7-881a-f05e0308e52d.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-creating-route-tables">Creating Route Tables</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734973626184/da9b8f0e-8707-4fa0-b59b-0460661a219f.png" alt class="image--center mx-auto" /></p>
<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>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734973847316/5a4cb304-d2cc-4b5d-bad9-a95e1ee35813.png" alt class="image--center mx-auto" /></p>
<p>Explicit subnet associations are required for both the Public and Private Route Tables.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734973919926/d3fb8258-9cab-40df-a278-284fb45ae7cf.png" alt class="image--center mx-auto" /></p>
<p>Here, I associated the <code>PublicSubnet</code> with the <code>PublicRouteTable</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734973959491/3618b553-c1c5-454b-9031-b51e20b100a8.png" alt class="image--center mx-auto" /></p>
<p>Next, I associated the <code>PrivateSubnet</code> with the <code>PrivateRouteTable</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734974002897/223bd51f-52b4-422a-801e-03e75d490306.png" alt class="image--center mx-auto" /></p>
<p>The route tables have been successfully associated with the respective subnets.</p>
<h3 id="heading-allowing-route-to-internet-gateway">Allowing Route to Internet Gateway</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734974152835/4de4a28b-dfef-44de-b0ee-aebfb57ee6eb.png" alt class="image--center mx-auto" /></p>
<p>I added a route 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 id="heading-connecting-via-ec2-instance-connect">Connecting via EC2 Instance Connect</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734974340991/3354ba0e-c36e-43c0-a51d-2c71325543b2.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734974470977/81fc804b-efe0-475d-b814-322d24edb02a.png" alt class="image--center mx-auto" /></p>
<p>I tested the internet connection by running <code>sudo yum update -y</code>, and it successfully connected, confirming the internet route is working.</p>
<h3 id="heading-launching-a-private-ec2-instance">Launching a Private EC2 Instance</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734974641863/d42bb376-22ab-452a-9c3c-80649cf7ee49.png" alt class="image--center mx-auto" /></p>
<p>I launched a new EC2 instance named <code>PrivateInstance</code> with default settings, using the existing <code>my-key-pair</code> key pair for SSH access.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734974696492/0f7c3c16-5f56-4304-9332-035ae10022d7.png" alt class="image--center mx-auto" /></p>
<p>The instance was placed in the <code>PrivateSubnet</code> without a public IP, and the default <code>PrivateSecurityGroup</code> was used.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734975533424/0e0152ec-2089-4990-849e-dac978f0aab8.png" alt class="image--center mx-auto" /></p>
<p>Using SCP, I uploaded the key pair to <code>PublicInstance</code> to enable SSH access to the <code>PrivateInstance</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734975575813/2b59a3e4-e6b3-40ec-8bb0-024fb225b4a3.png" alt class="image--center mx-auto" /></p>
<p>The key pair is successfully uploaded to the <code>PublicInstance</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734975871527/181f022a-d423-446f-bc61-a560a26a39dd.png" alt class="image--center mx-auto" /></p>
<p>I confirmed that I can access <code>PrivateInstance</code> since traffic is allowed between the two subnets by default. However, the <code>PrivateInstance</code> does not have internet access.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734975983328/d8711ecf-0c76-4573-9eef-e8a0d7f9d6c4.png" alt class="image--center mx-auto" /></p>
<p>Attempting to run <code>sudo yum update -y</code> on <code>PrivateInstance</code> failed as there is no internet access.</p>
<h3 id="heading-creating-a-nat-gateway">Creating a NAT Gateway</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734976215951/a0152ebd-37f2-45a5-8808-a856e3a0e726.png" alt class="image--center mx-auto" /></p>
<p>I created a NAT Gateway in the <code>PublicSubnet</code>, which allows 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 data-node-type="callout">
<div data-node-type="callout-emoji">❗</div>
<div data-node-type="callout-text"><strong>Important</strong>: Remember to release Elastic IP addresses once you finish using them, as idle Elastic IP incurs charges.</div>
</div>

<h3 id="heading-adding-route-to-nat-gateway">Adding Route to NAT Gateway</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734976450012/33629570-ba76-48f0-93b9-57d59a359502.png" alt class="image--center mx-auto" /></p>
<p>I added a route 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>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734976609409/808a239c-deb7-4ef6-82df-bf3b6c47ed39.png" alt class="image--center mx-auto" /></p>
<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 id="heading-conclusion">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 organized VPC setup with controlled access to and from the internet for both public and private resources.</p>
]]></content:encoded></item></channel></rss>