<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Security on MangoDriod</title><link>https://md.eknath.dev/tags/security/</link><description>Recent content in Security on MangoDriod</description><generator>Hugo -- 0.141.0</generator><language>en-us</language><lastBuildDate>Sat, 13 Sep 2025 11:00:00 +0530</lastBuildDate><atom:link href="https://md.eknath.dev/tags/security/index.xml" rel="self" type="application/rss+xml"/><item><title>A Beginner's Guide to Your First Hour on a Linux VPS</title><link>https://md.eknath.dev/posts/software-development/beginners-guide-to-vps-setup/</link><pubDate>Sat, 13 Sep 2025 11:00:00 +0530</pubDate><guid>https://md.eknath.dev/posts/software-development/beginners-guide-to-vps-setup/</guid><description>&lt;p>Congratulations on your new Virtual Private Server (VPS)! This is your own private space on the internet, a blank canvas ready for your projects. That freedom can also be a bit intimidating. What should you do first?&lt;/p>
&lt;p>This guide is designed for the absolute beginner. We will walk through the first essential steps to secure your server, get it ready for projects, and host your first website securely with Nginx and a free SSL certificate.&lt;/p></description><content:encoded><![CDATA[<p>Congratulations on your new Virtual Private Server (VPS)! This is your own private space on the internet, a blank canvas ready for your projects. That freedom can also be a bit intimidating. What should you do first?</p>
<p>This guide is designed for the absolute beginner. We will walk through the first essential steps to secure your server, get it ready for projects, and host your first website securely with Nginx and a free SSL certificate.</p>
<h2 id="1-your-first-login-the-root-user">1. Your First Login: The Root User</h2>
<p>Your hosting provider will give you an IP address (e.g., <code>123.45.67.89</code>) and a password for the <code>root</code> user. The <code>root</code> user is the super-administrator with unlimited power. It&rsquo;s powerful, but also risky to use for everyday tasks.</p>
<h3 id="step-1-connect-to-the-server">Step 1: Connect to the Server</h3>
<p>Open a terminal on your computer and connect to your server using the <code>ssh</code> command.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>ssh root@YOUR_SERVER_IP
</span></span></code></pre></div><h3 id="step-2-change-the-root-password">Step 2: Change the Root Password</h3>
<p>If your provider gave you a temporary password, your first action should be to change it to something strong and unique.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>passwd
</span></span></code></pre></div><h2 id="2-create-your-own-user-account">2. Create Your Own User Account</h2>
<p>This is the single most important security step. We will create a standard user account and give it administrative privileges using the <code>sudo</code> command.</p>
<h3 id="step-1-create-the-new-user">Step 1: Create the New User</h3>
<p>Replace <code>devuser</code> with a username you like.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>adduser devuser
</span></span></code></pre></div><h3 id="step-2-grant-administrative-privileges">Step 2: Grant Administrative Privileges</h3>
<p>Add your new user to the <code>sudo</code> group, which allows it to run commands as the administrator.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>usermod -aG sudo devuser
</span></span></code></pre></div><h3 id="step-3-log-in-as-your-new-user">Step 3: Log in as Your New User</h3>
<p>Log out of the root account (<code>exit</code>) and log back in with your new credentials.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>ssh devuser@YOUR_SERVER_IP
</span></span></code></pre></div><p>From now on, you should <strong>always</strong> log in with this user.</p>
<h2 id="3-update-system-and-install-essential-tools">3. Update System and Install Essential Tools</h2>
<p>Now that you are logged in as your new <code>sudo</code> user, the first actions are to update the server and install some essential tools.</p>
<h3 id="step-1-update-the-system">Step 1: Update the System</h3>
<p>This command downloads the latest list of available software (<code>update</code>) and then installs those updates (<code>upgrade</code>).</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo apt update <span style="color:#f92672">&amp;&amp;</span> sudo apt upgrade -y
</span></span></code></pre></div><h3 id="step-2-install-basic-tools">Step 2: Install Basic Tools</h3>
<p>Next, install a few common and useful tools.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo apt install curl git vim htop unzip nginx -y
</span></span></code></pre></div><p>We include <strong>Nginx</strong> here as it is a lightweight, high-performance web server we will configure later.</p>
<h2 id="4-set-your-timezone">4. Set Your Timezone</h2>
<p>Correct server time is important for logs and many applications. Find your timezone from the list and set it.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e"># Find your timezone (press &#39;q&#39; to quit the list)</span>
</span></span><span style="display:flex;"><span>timedatectl list-timezones
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Set your timezone (replace with your own)</span>
</span></span><span style="display:flex;"><span>sudo timedatectl set-timezone Asia/Kolkata
</span></span></code></pre></div><h2 id="5-basic-firewall-setup">5. Basic Firewall Setup</h2>
<p>A firewall is a digital security guard. We will use <code>ufw</code> (Uncomplicated Firewall) to block unwanted traffic.</p>
<h3 id="step-1-allow-essential-traffic">Step 1: Allow Essential Traffic</h3>
<p><strong>This is critical:</strong> You must allow SSH traffic, otherwise the firewall will lock you out. We will also allow Nginx traffic.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo ufw allow OpenSSH
</span></span><span style="display:flex;"><span>sudo ufw allow <span style="color:#e6db74">&#39;Nginx Full&#39;</span>
</span></span></code></pre></div><p>&lsquo;Nginx Full&rsquo; allows traffic on both HTTP (port 80) and HTTPS (port 443).</p>
<h3 id="step-2-enable-the-firewall">Step 2: Enable the Firewall</h3>
<p>Now, turn the firewall on.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo ufw enable
</span></span></code></pre></div><h2 id="6-host-a-website-with-nginx">6. Host a Website with Nginx</h2>
<p>Now we will configure Nginx to serve a website for a domain you own.</p>
<h3 id="step-0-point-your-domain-to-the-server-dns">Step 0: Point Your Domain to the Server (DNS)</h3>
<p>Before Nginx can work, you have to tell the internet that your domain should point to your server&rsquo;s IP address. You do this at your <strong>domain registrar</strong> (the company where you bought your domain, like GoDaddy, Namecheap, Google Domains, etc.).</p>
<ol>
<li>Log in to your domain registrar&rsquo;s website.</li>
<li>Find the DNS management page for your domain.</li>
<li>You need to create two <strong>&lsquo;A&rsquo; records</strong>:
<ul>
<li><strong>Record 1 (Root Domain):</strong>
<ul>
<li><strong>Type:</strong> <code>A</code></li>
<li><strong>Host/Name:</strong> <code>@</code> (this symbol represents the root domain itself)</li>
<li><strong>Value/Points to:</strong> Your server&rsquo;s IP address (e.g., <code>123.45.67.89</code>)</li>
<li><strong>TTL (Time to Live):</strong> Leave as default (often 1 hour).</li>
</ul>
</li>
<li><strong>Record 2 (www subdomain):</strong>
<ul>
<li><strong>Type:</strong> <code>A</code></li>
<li><strong>Host/Name:</strong> <code>www</code></li>
<li><strong>Value/Points to:</strong> Your server&rsquo;s IP address (the same one)</li>
<li><strong>TTL:</strong> Leave as default.</li>
</ul>
</li>
</ul>
</li>
</ol>
<p>DNS changes can take anywhere from a few minutes to a few hours to update across the internet.</p>
<h3 id="step-1-create-a-directory-for-your-site">Step 1: Create a Directory for Your Site</h3>
<p>We&rsquo;ll store our website&rsquo;s files in the <code>/var/www</code> directory.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e"># Create a directory for your domain</span>
</span></span><span style="display:flex;"><span>sudo mkdir -p /var/www/your-domain.com/html
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Assign ownership to your user</span>
</span></span><span style="display:flex;"><span>sudo chown -R $USER:$USER /var/www/your-domain.com/html
</span></span></code></pre></div><h3 id="step-2-create-a-sample-page">Step 2: Create a Sample Page</h3>
<p>Let&rsquo;s create a simple <code>index.html</code> file for testing.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;&lt;h1&gt;Hello from my Nginx Site!&lt;/h1&gt;&#34;</span> | sudo tee /var/www/your-domain.com/html/index.html
</span></span></code></pre></div><h3 id="step-3-create-an-nginx-server-block">Step 3: Create an Nginx Server Block</h3>
<p>Nginx uses &ldquo;server block&rdquo; files to know how to handle incoming domains. We&rsquo;ll create one for our domain.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo nano /etc/nginx/sites-available/your-domain.com
</span></span></code></pre></div><p>Paste the following configuration into the file:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-nginx" data-lang="nginx"><span style="display:flex;"><span><span style="color:#66d9ef">server</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">listen</span> <span style="color:#ae81ff">80</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">listen</span> <span style="color:#e6db74">[::]:80</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">root</span> <span style="color:#e6db74">/var/www/your-domain.com/html</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">index</span> <span style="color:#e6db74">index.html</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">server_name</span> <span style="color:#e6db74">your-domain.com</span> <span style="color:#e6db74">www.your-domain.com</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">location</span> <span style="color:#e6db74">/</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">try_files</span> $uri $uri/ =<span style="color:#ae81ff">404</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h3 id="step-4-enable-the-server-block">Step 4: Enable the Server Block</h3>
<p>We enable the site by creating a symbolic link from this file into the <code>sites-enabled</code> directory.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo ln -s /etc/nginx/sites-available/your-domain.com /etc/nginx/sites-enabled/
</span></span></code></pre></div><p>Now, test your Nginx configuration for errors and restart it.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo nginx -t
</span></span><span style="display:flex;"><span>sudo systemctl restart nginx
</span></span></code></pre></div><p>Once your DNS has updated, if you visit <code>http://your-domain.com</code> in a browser, you should see your &ldquo;Hello World&rdquo; message.</p>
<h2 id="7-secure-your-site-with-ssl-https">7. Secure Your Site with SSL (HTTPS)</h2>
<p>To secure your site, we&rsquo;ll get a free SSL certificate from Let&rsquo;s Encrypt using a tool called Certbot.</p>
<h3 id="step-1-install-certbot">Step 1: Install Certbot</h3>
<p>Certbot has a dedicated Nginx plugin that makes the process simple.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo apt install certbot python3-certbot-nginx -y
</span></span></code></pre></div><h3 id="step-2-obtain-the-ssl-certificate">Step 2: Obtain the SSL Certificate</h3>
<p>Run Certbot. It will read your Nginx configuration, see the domain you just set up, and guide you through obtaining the certificate.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo certbot --nginx
</span></span></code></pre></div><p>Certbot will ask for your email, for you to agree to the terms of service, and if you want to redirect all HTTP traffic to HTTPS. It is highly recommended to choose the redirect option.</p>
<h3 id="step-3-verify-auto-renewal">Step 3: Verify Auto-Renewal</h3>
<p>Let&rsquo;s Encrypt certificates are valid for 90 days. Certbot automatically sets up a task to renew them for you. You can test the renewal process with a dry run.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo certbot renew --dry-run
</span></span></code></pre></div><p>If this runs without errors, you are all set. Your site is now secure and accessible via <code>https://your-domain.com</code>.</p>
<p><strong>To add a subdomain</strong> (e.g., <code>blog.your-domain.com</code>), you simply repeat the process: create a new directory in <code>/var/www</code>, create a new server block file in <code>sites-available</code>, enable it, and then run <code>sudo certbot --nginx</code> again.</p>
<h2 id="8-quick-tips-and-best-practices">8. Quick Tips and Best Practices</h2>
<ul>
<li>
<p><strong>Use SSH Keys:</strong> Passwords can be cracked. SSH keys are a much more secure way to log in. This is a highly recommended next security step.</p>
</li>
<li>
<p><strong>Keep Your System Updated:</strong> Get in the habit of running <code>sudo apt update &amp;&amp; sudo apt upgrade -y</code> at least once a week.</p>
</li>
<li>
<p><strong>Be Careful with Commands:</strong> Don&rsquo;t run scripts or commands from the internet without understanding what they do.</p>
</li>
<li>
<p><strong>Use Strong Passwords:</strong> The password for your <code>sudo</code> user should be strong and unique.</p>
</li>
</ul>
]]></content:encoded></item><item><title>How to Set Up Telegram Alerts for SSH Logins on Debian</title><link>https://md.eknath.dev/posts/software-development/telegram-ssh-login-alerts/</link><pubDate>Sat, 13 Sep 2025 10:00:00 +0530</pubDate><guid>https://md.eknath.dev/posts/software-development/telegram-ssh-login-alerts/</guid><description>&lt;p>Securing your Virtual Private Server (VPS) is critical. A simple and effective way to monitor access is to receive real-time notifications for every successful SSH login. This guide provides a step-by-step walkthrough for setting up instant Telegram alerts on a Debian-based server, giving you immediate awareness of all shell access.&lt;/p>
&lt;h2 id="1-prerequisites">1. Prerequisites&lt;/h2>
&lt;p>Before you begin, ensure you have the following:&lt;/p>
&lt;ul>
&lt;li>A server running a Debian-based Linux distribution.&lt;/li>
&lt;li>&lt;code>sudo&lt;/code> or &lt;code>root&lt;/code> access to the server.&lt;/li>
&lt;li>A Telegram account.&lt;/li>
&lt;li>&lt;code>curl&lt;/code> and &lt;code>jq&lt;/code> installed on your server. If you don&amp;rsquo;t have them, install them now:
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>sudo apt-get update &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> sudo apt-get install -y curl jq
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ul>
&lt;h2 id="2-create-a-telegram-bot">2. Create a Telegram Bot&lt;/h2>
&lt;p>Your alerts will be sent by a Telegram Bot.&lt;/p></description><content:encoded><![CDATA[<p>Securing your Virtual Private Server (VPS) is critical. A simple and effective way to monitor access is to receive real-time notifications for every successful SSH login. This guide provides a step-by-step walkthrough for setting up instant Telegram alerts on a Debian-based server, giving you immediate awareness of all shell access.</p>
<h2 id="1-prerequisites">1. Prerequisites</h2>
<p>Before you begin, ensure you have the following:</p>
<ul>
<li>A server running a Debian-based Linux distribution.</li>
<li><code>sudo</code> or <code>root</code> access to the server.</li>
<li>A Telegram account.</li>
<li><code>curl</code> and <code>jq</code> installed on your server. If you don&rsquo;t have them, install them now:
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo apt-get update <span style="color:#f92672">&amp;&amp;</span> sudo apt-get install -y curl jq
</span></span></code></pre></div></li>
</ul>
<h2 id="2-create-a-telegram-bot">2. Create a Telegram Bot</h2>
<p>Your alerts will be sent by a Telegram Bot.</p>
<h3 id="step-1-talk-to-botfather">Step 1: Talk to BotFather</h3>
<p>In your Telegram app, search for the verified <strong>BotFather</strong> account and start a chat.</p>
<h3 id="step-2-create-the-bot">Step 2: Create the Bot</h3>
<p>Send the <code>/newbot</code> command. Follow the prompts to give your bot a display name and a unique username, which must end in <code>bot</code>.</p>
<h3 id="step-3-save-the-api-token">Step 3: Save the API Token</h3>
<p>Once created, BotFather will provide a secret <strong>API token</strong>. Copy this token and keep it secure; you will need it in the next steps.</p>
<h2 id="3-get-your-personal-chat-id">3. Get Your Personal Chat ID</h2>
<p>The bot needs to know where to send the alerts. This will be your personal Telegram chat.</p>
<h3 id="step-1-start-a-chat-with-your-bot">Step 1: Start a Chat with Your Bot</h3>
<p>Search for your new bot in Telegram and send it any message (e.g., <code>/start</code>). This initializes the chat.</p>
<h3 id="step-2-retrieve-the-chat-id">Step 2: Retrieve the Chat ID</h3>
<p>In your server&rsquo;s terminal, run the following command. Replace <code>&lt;YOUR_BOT_TOKEN&gt;</code> with the token you saved from BotFather.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>curl -s <span style="color:#e6db74">&#34;https://api.telegram.org/bot&lt;YOUR_BOT_TOKEN&gt;/getUpdates&#34;</span> | jq <span style="color:#e6db74">&#39;.result[0].message.chat.id&#39;</span>
</span></span></code></pre></div><p>This command will output a long number, which is your <strong>Chat ID</strong>. Copy it.</p>
<h2 id="4-create-the-notification-script">4. Create the Notification Script</h2>
<p>This shell script will be triggered on login, gather information, and send the alert.</p>
<h3 id="step-1-create-the-script-file">Step 1: Create the Script File</h3>
<p>Using a text editor, create a new file for the script:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo nano /usr/local/bin/ssh-login-alert.sh
</span></span></code></pre></div><h3 id="step-2-add-the-script-content">Step 2: Add the Script Content</h3>
<p>Paste the following code into the file. <strong>Remember to replace the placeholder values for <code>BOT_TOKEN</code> and <code>CHAT_ID</code> with your actual credentials.</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e">#!/bin/bash
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># --- Replace with your details ---</span>
</span></span><span style="display:flex;"><span>BOT_TOKEN<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;&lt;YOUR_BOT_TOKEN&gt;&#34;</span>
</span></span><span style="display:flex;"><span>CHAT_ID<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;&lt;YOUR_CHAT_ID&gt;&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#----------------------------------</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Do nothing if not an interactive session</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> -z <span style="color:#e6db74">&#34;</span>$PAM_TYPE<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">]</span> <span style="color:#f92672">||</span> <span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$PAM_TYPE<span style="color:#e6db74">&#34;</span> !<span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;open_session&#34;</span> <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>    exit <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Gather login information</span>
</span></span><span style="display:flex;"><span>HOSTNAME<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>hostname<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>USER<span style="color:#f92672">=</span>$PAM_USER
</span></span><span style="display:flex;"><span>IP_ADDRESS<span style="color:#f92672">=</span>$PAM_RHOST
</span></span><span style="display:flex;"><span>TIMESTAMP<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>date +<span style="color:#e6db74">&#34;%Y-%m-%d %H:%M:%S&#34;</span><span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Format the message using Markdown</span>
</span></span><span style="display:flex;"><span>MESSAGE<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>cat <span style="color:#e6db74">&lt;&lt;EOF
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">🔔 *New SSH Login Detected* 🔔
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">*Server:* \`$HOSTNAME\`
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">*User:* \`$USER\`
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">*From IP:* \`$IP_ADDRESS\`
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">*Time:* \`$TIMESTAMP\`
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">EOF</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Send the message via the Telegram API</span>
</span></span><span style="display:flex;"><span>curl -s --max-time <span style="color:#ae81ff">10</span> -X POST <span style="color:#e6db74">&#34;https://api.telegram.org/bot</span>$BOT_TOKEN<span style="color:#e6db74">/sendMessage&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>     -d chat_id<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$CHAT_ID<span style="color:#e6db74">&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>     -d text<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$MESSAGE<span style="color:#e6db74">&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>     -d parse_mode<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;Markdown&#34;</span> &gt; /dev/null
</span></span></code></pre></div><h3 id="step-3-make-the-script-executable">Step 3: Make the Script Executable</h3>
<p>Save the file and make it executable so the system can run it.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo chmod +x /usr/local/bin/ssh-login-alert.sh
</span></span></code></pre></div><h2 id="5-configure-pam-to-trigger-the-script">5. Configure PAM to Trigger the Script</h2>
<p>We&rsquo;ll use the Pluggable Authentication Module (PAM) framework to execute our script whenever a user opens a new SSH session.</p>
<h3 id="step-1-edit-the-sshd-pam-configuration">Step 1: Edit the SSHD PAM Configuration</h3>
<p>Open the PAM configuration file for the SSH daemon:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo nano /etc/pam.d/sshd
</span></span></code></pre></div><h3 id="step-2-add-the-execution-rule">Step 2: Add the Execution Rule</h3>
<p>Add the following line at the very <strong>end</strong> of the file. This tells PAM to run our script for every session, but our script is smart enough to only act on SSH logins.</p>
<pre tabindex="0"><code># Run script for SSH login notification
session optional pam_exec.so /usr/local/bin/ssh-login-alert.sh
</code></pre><p>Save and close the file.</p>
<h2 id="6-test-the-setup">6. Test the Setup</h2>
<p>You&rsquo;re all set! To test the notification, log out of your server and log back in via SSH.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>exit
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>ssh your_user@your_server_ip
</span></span></code></pre></div><p>Within seconds, you should receive a neatly formatted notification on Telegram from your bot. If you don&rsquo;t, double-check that the <code>BOT_TOKEN</code> and <code>CHAT_ID</code> in your script are correct and that the script is executable.</p>
<pre tabindex="0"><code></code></pre>]]></content:encoded></item><item><title>Advanced VPS Guide: Mastering Nginx, Subdomains, and Reverse Proxies</title><link>https://md.eknath.dev/posts/software-development/vps-setup-guide/</link><pubDate>Sun, 07 Sep 2025 12:00:00 +0530</pubDate><guid>https://md.eknath.dev/posts/software-development/vps-setup-guide/</guid><description>&lt;p>A Virtual Private Server (VPS) is your personal canvas on the internet. While basic setup is straightforward, unlocking its true potential requires mastering the web server. This guide dives deep into using Nginx to host multiple projects, manage subdomains, and route traffic to different services, transforming your single server into a multi-functional powerhouse.&lt;/p>
&lt;h2 id="1-initial-server-setup">1. Initial Server Setup&lt;/h2>
&lt;p>After acquiring a VPS, you&amp;rsquo;ll get an IP address and root access. Your first steps are to secure the server and create a non-root user for daily operations.&lt;/p></description><content:encoded><![CDATA[<p>A Virtual Private Server (VPS) is your personal canvas on the internet. While basic setup is straightforward, unlocking its true potential requires mastering the web server. This guide dives deep into using Nginx to host multiple projects, manage subdomains, and route traffic to different services, transforming your single server into a multi-functional powerhouse.</p>
<h2 id="1-initial-server-setup">1. Initial Server Setup</h2>
<p>After acquiring a VPS, you&rsquo;ll get an IP address and root access. Your first steps are to secure the server and create a non-root user for daily operations.</p>
<p>Connect to your server via SSH:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>ssh root@YOUR_SERVER_IP
</span></span></code></pre></div><h3 id="create-a-sudo-user">Create a Sudo User</h3>
<p>Operating as <code>root</code> is risky. Create a new user and grant administrative privileges.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e"># Create the new user (replace &#39;devuser&#39; with your username)</span>
</span></span><span style="display:flex;"><span>adduser devuser
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Add the user to the &#39;sudo&#39; group</span>
</span></span><span style="display:flex;"><span>usermod -aG sudo devuser
</span></span></code></pre></div><p>Now, set up SSH key authentication for your new user for enhanced security and convenience, then log in as that user.</p>
<h2 id="2-essential-security-and-updates">2. Essential Security and Updates</h2>
<p>A public server is a constant target. Secure it immediately.</p>
<h3 id="configure-the-firewall">Configure the Firewall</h3>
<p><code>ufw</code> (Uncomplicated Firewall) makes this easy. We&rsquo;ll allow SSH, HTTP, and HTTPS traffic.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e"># Allow OpenSSH (so you don&#39;t lock yourself out)</span>
</span></span><span style="display:flex;"><span>sudo ufw allow OpenSSH
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Allow Nginx to handle web traffic on ports 80 and 443</span>
</span></span><span style="display:flex;"><span>sudo ufw allow <span style="color:#e6db74">&#39;Nginx Full&#39;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Enable the firewall</span>
</span></span><span style="display:flex;"><span>sudo ufw enable
</span></span></code></pre></div><p>After enabling, check its status to ensure it&rsquo;s active and your rules are loaded.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo ufw status
</span></span></code></pre></div><h3 id="update-your-server">Update Your Server</h3>
<p>Keep your system&rsquo;s packages current to patch security vulnerabilities.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo apt update <span style="color:#f92672">&amp;&amp;</span> sudo apt upgrade -y
</span></span></code></pre></div><h2 id="3-installing-and-understanding-nginx">3. Installing and Understanding Nginx</h2>
<p>Nginx is the heart of our setup. It&rsquo;s a high-performance web server that can also act as a reverse proxy, load balancer, and more.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e"># Install Nginx</span>
</span></span><span style="display:flex;"><span>sudo apt install nginx -y
</span></span></code></pre></div><p>While the package should start and enable Nginx automatically, it&rsquo;s good practice to run the commands explicitly to be sure.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e"># Start the Nginx service</span>
</span></span><span style="display:flex;"><span>sudo systemctl start nginx
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Enable Nginx to start automatically on boot</span>
</span></span><span style="display:flex;"><span>sudo systemctl enable nginx
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Now, check that it&#39;s running and enabled</span>
</span></span><span style="display:flex;"><span>sudo systemctl status nginx
</span></span></code></pre></div><p>You should see <code>active (running)</code> in the output. Visiting your server&rsquo;s IP in a browser should also show the Nginx welcome page.</p>
<h3 id="nginx-configuration-structure">Nginx Configuration Structure</h3>
<p>Nginx&rsquo;s configuration lives in <code>/etc/nginx</code>. The <code>-p</code> flag in the commands below ensures that the command does nothing if the directories already exist.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo mkdir -p /etc/nginx/sites-available
</span></span><span style="display:flex;"><span>sudo mkdir -p /etc/nginx/sites-enabled
</span></span></code></pre></div><p>The key directories are:</p>
<ul>
<li><code>/etc/nginx/nginx.conf</code>: The main configuration file. You rarely edit this.</li>
<li><code>/etc/nginx/sites-available/</code>: Where you store the configuration files for each of your sites (called &ldquo;server blocks&rdquo;).</li>
<li><code>/etc/nginx/sites-enabled/</code>: Where you create symbolic links to the configurations in <code>sites-available</code> that you want to be active.</li>
</ul>
<p>This structure lets you easily enable or disable sites without deleting their configuration files.</p>
<h2 id="4-advanced-hosting-subdomains-and-reverse-proxies">4. Advanced Hosting: Subdomains and Reverse Proxies</h2>
<p>This is where the magic happens. A single server can host a blog, a portfolio website, a web app, and several APIs, all neatly organized using subdomains.</p>
<p>The core concept is the <strong>Reverse Proxy</strong>. Your Nginx server listens on the standard web ports (80 for HTTP, 443 for HTTPS) and intelligently forwards incoming requests to the correct internal service based on the requested domain or subdomain.</p>
<h3 id="scenario">Scenario:</h3>
<p>Let&rsquo;s say we want to set up the following on our server:</p>
<ol>
<li><code>eknath.dev</code>: A static HTML/CSS website.</li>
<li><code>blog.eknath.dev</code>: A separate project, maybe a Hugo or Jekyll site.</li>
<li><code>api.eknath.dev</code>: A Node.js application running on port <code>3000</code>.</li>
</ol>
<h3 id="step-1-create-project-directories">Step 1: Create Project Directories</h3>
<p>Organize your projects in the <code>/var/www</code> directory.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e"># Create directories for the main site and blog</span>
</span></span><span style="display:flex;"><span>sudo mkdir -p /var/www/eknath.dev/html
</span></span><span style="display:flex;"><span>sudo mkdir -p /var/www/blog.eknath.dev/html
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Set correct permissions</span>
</span></span><span style="display:flex;"><span>sudo chown -R $USER:$USER /var/www/eknath.dev
</span></span><span style="display:flex;"><span>sudo chown -R $USER:$USER /var/www/blog.eknath.dev
</span></span></code></pre></div><p>Verify that the directories were created with the correct ownership.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>ls -ld /var/www/eknath.dev/
</span></span><span style="display:flex;"><span>ls -ld /var/www/blog.eknath.dev/
</span></span></code></pre></div><p>Now, place some placeholder files.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;&lt;h1&gt;Welcome to Eknath&#39;s Site&lt;/h1&gt;&#34;</span> | sudo tee /var/www/eknath.dev/html/index.html
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;&lt;h1&gt;Welcome to Eknath&#39;s Blog&lt;/h1&gt;&#34;</span> | sudo tee /var/www/blog.eknath.dev/html/index.html
</span></span></code></pre></div><h3 id="step-2-create-nginx-server-blocks">Step 2: Create Nginx Server Blocks</h3>
<p>Now, we create a configuration file for each site in <code>sites-available</code>.</p>
<p><strong>For the main domain (<code>eknath.dev</code>):</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo nano /etc/nginx/sites-available/eknath.dev
</span></span></code></pre></div><p>Add the following server block:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-nginx" data-lang="nginx"><span style="display:flex;"><span><span style="color:#66d9ef">server</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">listen</span> <span style="color:#ae81ff">80</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">listen</span> <span style="color:#e6db74">[::]:80</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">server_name</span> <span style="color:#e6db74">eknath.dev</span> <span style="color:#e6db74">www.eknath.dev</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">root</span> <span style="color:#e6db74">/var/www/eknath.dev/html</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">index</span> <span style="color:#e6db74">index.html</span> <span style="color:#e6db74">index.php</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">location</span> <span style="color:#e6db74">/</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">try_files</span> $uri $uri/ =<span style="color:#ae81ff">404</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p><strong>For the blog subdomain (<code>blog.eknath.dev</code>):</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo nano /etc/nginx/sites-available/blog.eknath.dev
</span></span></code></pre></div><p>Add this configuration:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-nginx" data-lang="nginx"><span style="display:flex;"><span><span style="color:#66d9ef">server</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">listen</span> <span style="color:#ae81ff">80</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">listen</span> <span style="color:#e6db74">[::]:80</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">server_name</span> <span style="color:#e6db74">blog.eknath.dev</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">root</span> <span style="color:#e6db74">/var/www/blog.eknath.dev/html</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">index</span> <span style="color:#e6db74">index.html</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">location</span> <span style="color:#e6db74">/</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">try_files</span> $uri $uri/ =<span style="color:#ae81ff">404</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h3 id="step-3-configure-the-reverse-proxy-for-the-api">Step 3: Configure the Reverse Proxy for the API</h3>
<p>For <code>api.eknath.dev</code>, we&rsquo;ll proxy requests to our Node.js app, which we assume is running on <code>http://127.0.0.1:3000</code>.</p>
<p>Create the configuration file:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo nano /etc/nginx/sites-available/api.eknath.dev
</span></span></code></pre></div><p>Add the reverse proxy configuration:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-nginx" data-lang="nginx"><span style="display:flex;"><span><span style="color:#66d9ef">server</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">listen</span> <span style="color:#ae81ff">80</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">listen</span> <span style="color:#e6db74">[::]:80</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">server_name</span> <span style="color:#e6db74">api.eknath.dev</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">location</span> <span style="color:#e6db74">/</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">proxy_pass</span> <span style="color:#e6db74">http://127.0.0.1:3000</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">proxy_set_header</span> <span style="color:#e6db74">Host</span> $host;
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">proxy_set_header</span> <span style="color:#e6db74">X-Real-IP</span> $remote_addr;
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">proxy_set_header</span> <span style="color:#e6db74">X-Forwarded-For</span> $proxy_add_x_forwarded_for;
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">proxy_set_header</span> <span style="color:#e6db74">X-Forwarded-Proto</span> $scheme;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h3 id="step-4-enable-the-sites-and-test">Step 4: Enable the Sites and Test</h3>
<p>Now, link these configurations into <code>sites-enabled</code> to activate them.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo ln -s /etc/nginx/sites-available/eknath.dev /etc/nginx/sites-enabled/
</span></span><span style="display:flex;"><span>sudo ln -s /etc/nginx/sites-available/blog.eknath.dev /etc/nginx/sites-enabled/
</span></span><span style="display:flex;"><span>sudo ln -s /etc/nginx/sites-available/api.eknath.dev /etc/nginx/sites-enabled/
</span></span></code></pre></div><p>Test the Nginx configuration for syntax errors:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo nginx -t
</span></span></code></pre></div><p>If it&rsquo;s successful, restart Nginx to apply the changes:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo systemctl restart nginx
</span></span></code></pre></div><p>Check the status to ensure it restarted correctly.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo systemctl status nginx
</span></span></code></pre></div><p>After setting up your DNS records, you&rsquo;ll be able to access each service through its unique subdomain.</p>
<h2 id="5-securing-your-sites-with-ssl-https">5. Securing Your Sites with SSL (HTTPS)</h2>
<p>We&rsquo;ll use <strong>Let&rsquo;s Encrypt</strong>, a free and automated Certificate Authority, and <strong>Certbot</strong>, a tool that makes managing SSL/TLS certificates effortless.</p>
<h3 id="step-1-install-certbot">Step 1: Install Certbot</h3>
<p>Certbot has a dedicated Nginx plugin that automates the process.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e"># Install Certbot and its Nginx plugin</span>
</span></span><span style="display:flex;"><span>sudo apt install certbot python3-certbot-nginx -y
</span></span></code></pre></div><h3 id="step-2-obtain-and-install-the-ssl-certificates">Step 2: Obtain and Install the SSL Certificates</h3>
<p>With your server blocks already configured, running Certbot is incredibly simple.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e"># Run Certbot to get certificates for all configured domains</span>
</span></span><span style="display:flex;"><span>sudo certbot --nginx
</span></span></code></pre></div><p>Certbot will guide you through a few simple steps:</p>
<ol>
<li><strong>Enter your email address.</strong></li>
<li><strong>Agree to the Terms of Service.</strong></li>
<li><strong>Choose domains</strong> from the list Certbot finds.</li>
<li><strong>Choose to redirect HTTP to HTTPS.</strong> This is highly recommended.</li>
</ol>
<h3 id="step-3-verify-the-new-configuration">Step 3: Verify the New Configuration</h3>
<p>Certbot automatically modifies your Nginx files to enable HTTPS. You can check the new configuration by running <code>sudo nginx -t</code> and then reloading Nginx with <code>sudo systemctl reload nginx</code>.</p>
<h3 id="step-4-understanding-automatic-renewal">Step 4: Understanding Automatic Renewal</h3>
<p>Let&rsquo;s Encrypt certificates are valid for 90 days. The Certbot package automatically sets up a task to renew them. You can test the renewal process with a dry run:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo certbot renew --dry-run
</span></span></code></pre></div><p>If this command runs without errors, your auto-renewal is set up correctly.</p>
<h2 id="conclusion">Conclusion</h2>
<p>You have now transformed a basic VPS into a sophisticated, multi-tenant hosting platform. By leveraging Nginx&rsquo;s server blocks and reverse proxy capabilities, you can host and manage numerous projects, each on its own subdomain, from a single server. Happy hosting!</p>
]]></content:encoded></item></channel></rss>