<?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[DevOps Insight with Irene]]></title><description><![CDATA[DevOps Insight shares practical tips on DevOps, Linux, automation, and cloud. You'll find actionable takeaways to build smarter and more reliable systems.]]></description><link>https://blog.devopsinsight.co</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1742368911241/72b54ab4-3722-485b-a7f6-3b488de89643.png</url><title>DevOps Insight with Irene</title><link>https://blog.devopsinsight.co</link></image><generator>RSS for Node</generator><lastBuildDate>Fri, 05 Jun 2026 20:09:50 GMT</lastBuildDate><atom:link href="https://blog.devopsinsight.co/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Effective Strategies for Scaling Cloud Infrastructure and Reducing Costs]]></title><description><![CDATA[A few years ago, a small SaaS startup launched with a great idea — an AI-powered personal finance assistant. The founders were excited, and their first instinct was to build for scale. They provisioned redundant cloud resources, assuming they would n...]]></description><link>https://blog.devopsinsight.co/effective-strategies-for-scaling-cloud-infrastructure-and-reducing-costs</link><guid isPermaLink="true">https://blog.devopsinsight.co/effective-strategies-for-scaling-cloud-infrastructure-and-reducing-costs</guid><category><![CDATA[Startups]]></category><category><![CDATA[Cloud]]></category><category><![CDATA[Cloud infrastructure]]></category><category><![CDATA[Devops]]></category><category><![CDATA[finops]]></category><dc:creator><![CDATA[DevOps Insight with Irene]]></dc:creator><pubDate>Wed, 19 Mar 2025 08:48:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1742370872370/cfcc8daa-2b85-4016-a277-7a8bbb331842.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A few years ago, a small SaaS startup launched with a great idea — an AI-powered personal finance assistant. The founders were excited, and their first instinct was to build for scale. They provisioned redundant cloud resources, assuming they would need them soon. They were ready for millions of users.</p>
<p>By the end of their first quarter, they had spent more on infrastructure than they had earned in revenue. Except, they didn’t have millions of users. They had a few hundred. Yet their cloud bill was climbing north of $1,000 per month. Before they had a chance to iterate on their product-market fit, they were drowning in infrastructure costs. Within a year, they shut down.</p>
<p>This is a common story — that plays out in different variations across the startup world. Founders and engineers often over-engineer their infrastructure based on hypothetical future needs, rather than present realities.</p>
<p>As a DevOps and infrastructure engineer, I have repeatedly seen this mistake: teams spend excessive time and resources designing for massive scalability when they haven’t even validated their core business model. In this article, I will share important lessons I’ve learned throughout my journey and how to strike the right balance between scalability and efficiency.</p>
<blockquote>
<p><strong>The truth is, you don’t need to scale until your business demands it.</strong></p>
</blockquote>
<h2 id="heading-the-high-cost-of-premature-scaling">The High Cost of Premature Scaling</h2>
<p>AWS, GCP, and Azure provide powerful infrastructure solutions, but they come at a steep price. When teams configure auto-scaling groups, distribute workloads across multiple availability zones, and implement advanced caching strategies before their traffic justifies it, they introduce unnecessary complexity and cost.</p>
<h3 id="heading-where-the-costs-add-up"><strong>Where the Costs Add Up</strong></h3>
<ol>
<li><p><strong>Cloud Providers Are Expensive:</strong> Distributed architectures come with increased networking, storage, and data transfer costs.</p>
</li>
<li><p><strong>Overprovisioned Resources Drain Budget:</strong> Teams often allocate excessive computing power without fully utilizing it, leading to wasted spend.</p>
</li>
<li><p><strong>Operational Complexity Kills Agility:</strong> Managing a multi-cloud, multi-region setup requires dedicated DevOps expertise, adding overhead.</p>
</li>
</ol>
<h2 id="heading-scaling-strategies">Scaling Strategies</h2>
<p><strong>Picking the Right Approach</strong></p>
<p>Scaling is a fundamental concept in software architecture, referring to a system’s ability to handle increased load. Scaling isn’t one-size-fits-all. Businesses need to choose the right strategy based on demand — application specific needs and growth patterns. Here are the three main approaches:</p>
<ul>
<li><p><strong>Vertical Scaling (Scaling Up):</strong> Enhancing the capacity of a single server by adding more resources, such as CPU or RAM. It’s like upgrading a computer to make it more powerful.</p>
</li>
<li><p><strong>Horizontal Scaling (Scaling Out):</strong> Adding more servers to distribute the load. This approach increases capacity by expanding the number of machines working together.</p>
</li>
<li><p><strong>Diagonal Scaling (A Balanced Approach):</strong> Diagonal scaling is a flexible approach that combines both vertical and horizontal scaling, adjusting dynamically based on current demand. Instead of choosing one strategy upfront, it starts with vertical scaling — adding more CPU, memory, or storage to a single machine until it reaches its limit. Once further growth is needed, it shifts to horizontal scaling by distributing workloads across multiple instances. For example, a business might begin by upgrading its database server, but as traffic grows, it can introduce read replicas and load balancing to manage increasing queries efficiently.</p>
</li>
</ul>
<blockquote>
<p>The key advantage of diagonal scaling is adaptability — it allows infrastructure to grow when demand rises and scale down when demand drops, ensuring cost-efficiency without unnecessary complexity.</p>
</blockquote>
<h2 id="heading-a-smarter-approach">A Smarter Approach</h2>
<p><strong>When to Use the Right Scaling Strategy</strong></p>
<p>Instead of over-engineering infrastructure and blindly deploying a distributed system from the beginning, companies should start simple and scale incrementally, teams should optimize their architecture based on actual usage patterns:</p>
<ol>
<li><p><strong>Use Vertical Scaling First:</strong> If your application is CPU/memory-bound and traffic is predictable, upgrading to a larger instance is usually the simplest and most cost-effective solution.</p>
</li>
<li><p><strong>Introduce Horizontal Scaling When Needed:</strong> If you’re hitting consistent performance bottlenecks due to concurrent traffic spikes, then adding more instances makes sense.</p>
</li>
<li><p><strong>Monitor Before Scaling:</strong> Performance bottlenecks should be analyzed first — sometimes caching, query optimization, or asynchronous processing can eliminate the need for immediate scaling.</p>
</li>
</ol>
<blockquote>
<p><strong><em>For applications with fewer than 1,000 monthly users, a monolithic architecture with vertical scaling is often one of the best approach.</em></strong></p>
</blockquote>
<h2 id="heading-why-monoliths-work-better-at-early-stages">Why Monoliths Work Better at Early Stages</h2>
<p>Many startups jump straight into microservices, thinking it’s the modern way to build software. However, microservices introduce communication overhead, deployment complexity, and operational challenges. A well-structured monolith is often easier and cheaper to maintain early on as it provides:</p>
<ol>
<li><p><strong>Lower Infrastructure Cost:</strong> A single well-optimized instance is cheaper than running multiple small instances with distributed overhead.</p>
</li>
<li><p><strong>Simplified Debugging &amp; Maintenance</strong>: Fewer moving parts mean fewer things breaking at scale.</p>
</li>
<li><p><strong>Easier to Iterate:</strong> Early-stage applications require rapid development cycles, not excessive infrastructure.</p>
</li>
</ol>
<h2 id="heading-practical-steps-to-scale-the-right-way">Practical Steps to Scale the Right Way</h2>
<ol>
<li><p><strong>Keep it Monolithic Initially:</strong> Until you hit scale bottlenecks, avoid microservices and distributed patterns.</p>
</li>
<li><p><strong>Optimize Before Scaling:</strong> Improve database queries, implement caching (Redis, Memcached), and optimize code efficiency before provisioning more resources.</p>
</li>
<li><p><strong>Benchmark Your Limits:</strong> Use load testing to define at what threshold your infrastructure needs to scale.</p>
</li>
</ol>
<h2 id="heading-but-i-dont-want-to-configure-things-twice">“But I Don’t Want to Configure Things Twice!”</h2>
<p>A common argument against starting small is that reconfiguring for scale later requires extra work. However, this thinking ignores two critical realities:</p>
<ol>
<li><p><strong>Your Scaling Needs Will Evolve Unpredictably:</strong> Designing prematurely for a million users results in unnecessary complexity.</p>
</li>
<li><p><strong>Modern Migration Is Easier Than Ever:</strong> Tools like Terraform, Kubernetes, and cloud-native databases simplify infrastructure changes.</p>
</li>
</ol>
<blockquote>
<p><strong><em>Investing in massive scalability before demand exists is like renting a stadium before you’ve formed a local football team.</em></strong></p>
</blockquote>
<h2 id="heading-is-serverless-really-cost-effective">Is Serverless Really Cost-Effective?</h2>
<p>Serverless computing is often marketed as an affordable way to scale, but poor configurations can lead to unexpected costs. Misconfigured AWS Lambda, Firebase, or Vercel functions have resulted in five-figure invoices due to:</p>
<ul>
<li><p><strong>Execution Duration Costs:</strong> Poorly optimized functions that run longer than necessary drive up costs.</p>
</li>
<li><p><strong>Concurrency Limits and Scaling Behavior:</strong> Auto-scaling adds more instances, each incurring additional costs.</p>
</li>
<li><p><strong>Networking Costs:</strong> Frequent external database calls lead to excessive cross-region networking charges.</p>
</li>
</ul>
<blockquote>
<p>Serverless isn’t inherently bad, but it requires careful tuning. It’s not always the cheapest solution, especially when running continuously.</p>
</blockquote>
<h2 id="heading-the-importance-of-building-for-scalability-without-prematurely-scaling">The Importance of Building for Scalability — Without Prematurely Scaling</h2>
<p>While premature scaling is a mistake, engineers should still design applications for future scalability without introducing unnecessary overhead.</p>
<h3 id="heading-how-to-design-for-future-scaling">How to Design for Future Scaling</h3>
<ul>
<li><p><strong>Decouple Core Logic:</strong> Structuring business logic modularly makes migrating to microservices easier.</p>
</li>
<li><p><strong>Choose Databases That Scale:</strong> PostgreSQL, MySQL, and other relational databases can handle significant scale if architected properly with indexing, replication, and partitioning strategies.</p>
</li>
<li><p><strong>Implement Caching from Day One:</strong> Using a caching layer like Redis significantly reduces the need for excessive scaling by offloading repeated queries.</p>
</li>
<li><p><strong>Use Feature Flags and Modular Deployment:</strong> This enables incremental migrations without massive rework.</p>
</li>
<li><p><strong>Avoid Cloud Vendor Lock-in:</strong> Open standards for databases, messaging queues, and storage provide long-term flexibility.</p>
</li>
</ul>
<h2 id="heading-when-to-actually-scale">When to Actually Scale</h2>
<p>There is a right time to move beyond vertical scaling and invest in horizontal scaling, distributed databases, and containerized workloads.</p>
<p>That time comes when:</p>
<ul>
<li><p><strong>Traffic consistently exceeds 10,000+ monthly users, and performance bottlenecks arise despite optimizations.</strong></p>
</li>
<li><p><strong>A single server is no longer enough due to CPU/memory constraints, even after vertical scaling.</strong></p>
</li>
<li><p><strong>Your team requires independent deployments, and the monolith slows down development velocity.</strong></p>
</li>
<li><p><strong>Your business model is validated, and you need high availability guarantees for paying customers.</strong></p>
</li>
</ul>
<h2 id="heading-conclusion-scale-when-your-business-scales">Conclusion: Scale When Your Business Scales</h2>
<p>Before designing for millions of users, ask yourself: <strong>Do I even have a thousand yet?</strong></p>
<p><strong>Many startups fail because they focus on enterprise-scale infrastructure before validating their business model.</strong></p>
<blockquote>
<p><em><mark>So, as a business, what is the best infrastructure that won’t cost a lot but can scale when demand rises or falls?</mark></em></p>
</blockquote>
<p>The answer lies in <strong>diagonal scaling</strong> because the <strong>best infrastructure balances cost</strong> <strong>and</strong> <strong>scalability</strong>:</p>
<ul>
<li><p>Start lean with minimal but efficient resources.</p>
</li>
<li><p>Optimize vertically first — improve performance before adding more machines.</p>
</li>
<li><p>Scale horizontally only when necessary.</p>
</li>
<li><p>Use automation to scale dynamically, avoiding unnecessary costs.</p>
</li>
</ul>
<p>Scaling should be a response to growth, not a prediction of it. Businesses that scale too soon waste money and slow down development. The key is to build infrastructure based on real demand, not future assumptions.</p>
<p>By <strong>balancing lean infrastructure</strong> with <strong>scalable software design</strong> and <strong>actual business growth</strong>, engineers and startups can <strong>manage costs effectively</strong> while positioning themselves for future success.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">🔗</div>
<div data-node-type="callout-text"><strong><em>Irene Ufia is a software engineer specializing in DevOps and Infrastructure Security Management. Have you experienced infrastructure scaling challenges? Let’s connect and discuss: </em></strong><a target="_self" href="https://www.linkedin.com/in/covenantireneufia"><strong><em>LinkedIn</em></strong></a><strong><em> | </em></strong><a target="_self" href="https://github.com/UfiairENE"><strong><em>Github</em></strong></a></div>
</div>]]></content:encoded></item><item><title><![CDATA[How to Configure Caddy with an External SSL Certificate Using Ansible]]></title><description><![CDATA[In this article, we’ll walk you through configuring Caddy (A powerful, easy-to-use web server that automatically handles SSL certificates and reverse proxying ) to use an external SSL/TLS certificate from a commercial Certificate Authority (CA).
Whil...]]></description><link>https://blog.devopsinsight.co/how-to-configure-caddy-with-an-external-ssl-certificate-using-ansible</link><guid isPermaLink="true">https://blog.devopsinsight.co/how-to-configure-caddy-with-an-external-ssl-certificate-using-ansible</guid><category><![CDATA[Caddy]]></category><category><![CDATA[Linux]]></category><category><![CDATA[ansible]]></category><category><![CDATA[SSL Certificate]]></category><dc:creator><![CDATA[DevOps Insight with Irene]]></dc:creator><pubDate>Fri, 29 Nov 2024 23:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1742898292359/22c7e97d-6cba-4c66-92c1-d005cc801053.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this article, we’ll walk you through configuring <a target="_blank" href="https://caddyserver.com/docs/">Caddy</a> (A powerful, easy-to-use web server that automatically handles SSL certificates and reverse proxying ) to use an external SSL/TLS certificate from a commercial Certificate Authority (CA).</p>
<p>While Caddy can handle automatic certificate management with Let’s Encrypt, there are situations where you may need to use a certificate provided by a third-party CA.</p>
<p>We’ll demonstrate how to deploy and configure this type of certificate with Caddy, including the necessary steps to ensure it works correctly.</p>
<p>We’ll automate the setup using <a target="_blank" href="https://docs.ansible.com/">Ansible</a> ( A popular automation tool for configuring systems and deploying applications with simple, human-readable YAML files ) to simplify and streamline the process for production environments.</p>
<h2 id="heading-prerequisites"><strong>Prerequisites</strong></h2>
<p>Before you begin, ensure that you have:</p>
<ol>
<li><p>A valid SSL/TLS certificate and corresponding private key from your CA.</p>
</li>
<li><p>Ansible installed for automation.</p>
</li>
<li><p>Root or sudo privileges on the server to install packages and modify system configurations.</p>
</li>
</ol>
<h2 id="heading-step-1-preparing-your-certificate-files"><strong>Step 1: Preparing Your Certificate Files</strong></h2>
<p>When you receive an SSL certificate from a commercial Certificate Authority, it often consists of multiple files, such as:</p>
<ol>
<li><p>The leaf certificate (your server’s certificate) — usually ends with .crt or .pem</p>
</li>
<li><p>The intermediate certificate (which bridges the trust between your leaf certificate and the root certificate) — ends with .crt or .pem</p>
</li>
<li><p>The private key associated with the leaf certificate — usually ends with .key</p>
</li>
</ol>
<p>Sometimes these certificates are provided separately, and sometimes in a single file (full chain). In most cases, the leaf certificate needs to be combined with the intermediate certificate to form the full certificate chain. This ensures that browsers and other clients can validate the entire trust path, from the root CA to your leaf certificate.</p>
<h2 id="heading-step-2-setting-up-ansible-to-automate-the-configuration"><strong>Step 2: Setting Up Ansible to Automate the Configuration</strong></h2>
<p>For this guide, we’ll use Ansible to automate the deployment of your SSL certificate onto the Caddy server. The Ansible playbook will copy your certificate files, concatenate the leaf and intermediate certificates (if needed), and configure Caddy to use them.</p>
<p>Here is an example Ansible Playbook that automates the process of installing dependencies, configuring Caddy, and deploying the certificate:</p>
<pre><code class="lang-yaml"><span class="hljs-bullet">-</span> <span class="hljs-attr">hosts:</span> <span class="hljs-string">all</span>
  <span class="hljs-attr">become:</span> <span class="hljs-literal">yes</span>
  <span class="hljs-attr">tasks:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Update</span> <span class="hljs-string">apt</span> <span class="hljs-string">packages</span>
      <span class="hljs-attr">become:</span> <span class="hljs-literal">true</span>
      <span class="hljs-attr">apt:</span>
        <span class="hljs-attr">update_cache:</span> <span class="hljs-literal">yes</span>

    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Install</span> <span class="hljs-string">Caddy</span> <span class="hljs-string">and</span> <span class="hljs-string">fail2ban</span>
      <span class="hljs-attr">become:</span> <span class="hljs-literal">true</span>
      <span class="hljs-attr">apt:</span>
        <span class="hljs-attr">pkg:</span>
          <span class="hljs-bullet">-</span> <span class="hljs-string">caddy</span>
          <span class="hljs-bullet">-</span> <span class="hljs-string">fail2ban</span>

    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Copy</span> <span class="hljs-string">server</span> <span class="hljs-string">certificate</span> <span class="hljs-string">file</span> <span class="hljs-string">(example.com.crt)</span>
      <span class="hljs-attr">copy:</span>
        <span class="hljs-attr">src:</span> <span class="hljs-string">../templates/example.com.crt</span>
        <span class="hljs-attr">dest:</span> <span class="hljs-string">/etc/ssl/certs/example.com.crt</span>
        <span class="hljs-attr">mode:</span> <span class="hljs-string">‘0644'</span>

    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Set</span> <span class="hljs-string">correct</span> <span class="hljs-string">ownership</span> <span class="hljs-string">for</span> <span class="hljs-string">the</span> <span class="hljs-string">certificate</span> <span class="hljs-string">file</span>
      <span class="hljs-attr">file:</span>
        <span class="hljs-attr">path:</span> <span class="hljs-string">/etc/ssl/certs/example.com.crt</span>
        <span class="hljs-attr">owner:</span> <span class="hljs-string">caddy</span>
        <span class="hljs-attr">group:</span> <span class="hljs-string">caddy</span>
        <span class="hljs-attr">mode:</span> <span class="hljs-string">‘0644'</span>

    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Copy</span> <span class="hljs-string">intermediate</span> <span class="hljs-string">certificate</span> <span class="hljs-string">(DigiCertCA.crt)</span>
      <span class="hljs-attr">copy:</span>
        <span class="hljs-attr">src:</span> <span class="hljs-string">../templates/DigiCertCA.crt</span>
        <span class="hljs-attr">dest:</span> <span class="hljs-string">/etc/ssl/certs/DigiCertCA.crt</span>
        <span class="hljs-attr">mode:</span> <span class="hljs-string">‘0644'</span>

    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Set</span> <span class="hljs-string">correct</span> <span class="hljs-string">ownership</span> <span class="hljs-string">for</span> <span class="hljs-string">the</span> <span class="hljs-string">intermediate</span> <span class="hljs-string">certificate</span>
      <span class="hljs-attr">file:</span>
        <span class="hljs-attr">path:</span> <span class="hljs-string">/etc/ssl/certs/DigiCertCA.crt</span>
        <span class="hljs-attr">owner:</span> <span class="hljs-string">caddy</span>
        <span class="hljs-attr">group:</span> <span class="hljs-string">caddy</span>
        <span class="hljs-attr">mode:</span> <span class="hljs-string">‘0644'</span>

    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Concatenate</span> <span class="hljs-string">server</span> <span class="hljs-string">certificate</span> <span class="hljs-string">and</span> <span class="hljs-string">intermediate</span> <span class="hljs-string">certificate</span> <span class="hljs-string">to</span> <span class="hljs-string">form</span> <span class="hljs-string">a</span> <span class="hljs-string">full</span> <span class="hljs-string">chain</span>
      <span class="hljs-attr">shell:</span> <span class="hljs-string">"cat /etc/ssl/certs/example.com.crt /etc/ssl/certs/DigiCertCA.crt &gt; /etc/ssl/certs/example.com_fullchain.crt"</span>
      <span class="hljs-attr">args:</span>
        <span class="hljs-attr">creates:</span> <span class="hljs-string">/etc/ssl/certs/example.com_fullchain.crt</span>

    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Copy</span> <span class="hljs-string">private</span> <span class="hljs-string">key</span> <span class="hljs-string">file</span> <span class="hljs-string">(example.com.key)</span>
      <span class="hljs-attr">copy:</span>
        <span class="hljs-attr">src:</span> <span class="hljs-string">../templates/example.com.key</span>
        <span class="hljs-attr">dest:</span> <span class="hljs-string">/etc/ssl/private/example.com.key</span>
        <span class="hljs-attr">mode:</span> <span class="hljs-string">‘0600'</span>

    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Set</span> <span class="hljs-string">correct</span> <span class="hljs-string">ownership</span> <span class="hljs-string">for</span> <span class="hljs-string">the</span> <span class="hljs-string">private</span> <span class="hljs-string">key</span> <span class="hljs-string">file</span>
      <span class="hljs-attr">file:</span>
        <span class="hljs-attr">path:</span> <span class="hljs-string">/etc/ssl/private/example.com.key</span>
        <span class="hljs-attr">owner:</span> <span class="hljs-string">caddy</span>
        <span class="hljs-attr">group:</span> <span class="hljs-string">caddy</span>
        <span class="hljs-attr">mode:</span> <span class="hljs-string">‘0600'</span>

    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Set</span> <span class="hljs-string">correct</span> <span class="hljs-string">permissions</span> <span class="hljs-string">for</span> <span class="hljs-string">the</span> <span class="hljs-string">/etc/ssl/private</span> <span class="hljs-string">directory</span>
      <span class="hljs-attr">file:</span>
        <span class="hljs-attr">path:</span> <span class="hljs-string">/etc/ssl/private</span>
        <span class="hljs-attr">owner:</span> <span class="hljs-string">caddy</span>
        <span class="hljs-attr">group:</span> <span class="hljs-string">caddy</span>
        <span class="hljs-attr">mode:</span> <span class="hljs-string">‘0750'</span>

    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Copy</span> <span class="hljs-string">Caddy</span> <span class="hljs-string">configuration</span> <span class="hljs-string">file</span>
      <span class="hljs-attr">template:</span>
        <span class="hljs-attr">src:</span> <span class="hljs-string">../templates/Caddyfile</span>
        <span class="hljs-attr">dest:</span> <span class="hljs-string">/etc/caddy/Caddyfile</span>

    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Format</span> <span class="hljs-string">Caddyfile</span>
      <span class="hljs-attr">ansible.builtin.shell:</span> <span class="hljs-string">/usr/bin/caddy</span> <span class="hljs-string">fmt</span> <span class="hljs-string">--overwrite</span> <span class="hljs-string">/etc/caddy/Caddyfile</span>

    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Reload</span> <span class="hljs-string">Caddy</span> <span class="hljs-string">service</span> <span class="hljs-string">to</span> <span class="hljs-string">apply</span> <span class="hljs-string">changes</span>
      <span class="hljs-attr">systemd:</span>
        <span class="hljs-attr">name:</span> <span class="hljs-string">caddy</span>
        <span class="hljs-attr">state:</span> <span class="hljs-string">reloaded</span>
</code></pre>
<h2 id="heading-step-3-explanation-of-key-steps"><strong>Step 3: Explanation of Key Steps</strong></h2>
<p>1. Copying Certificate Files<br />After the installation, we begin by copying the necessary certificate files to their proper locations. These files typically include:</p>
<ul>
<li><p>Leaf Certificate (example.com.crt): This is the public certificate issued for your domain.</p>
</li>
<li><p>Intermediate Certificate (DigiCertCA.crt): This bridges the trust between your leaf certificate and the root certificate.</p>
</li>
<li><p>Private Key (example.com.key): This is the private key that matches your leaf certificate.</p>
</li>
</ul>
<p>These files are placed in the appropriate directories (/etc/ssl/certs and /etc/ssl/private) with correct file permissions to ensure proper access control. The playbook will set ownership to the caddy user, which is important for security.</p>
<p>2. Concatenating the Full Chain<br />In most cases, the leaf certificate needs to be combined with the intermediate certificate to form a full certificate chain. This ensures that clients can trace the certificate back to a trusted root authority.</p>
<p>Here’s the command used to concatenate the certificates:</p>
<pre><code class="lang-json">cat /etc/ssl/certs/example.com.crt /etc/ssl/certs/DigiCertCA.crt &gt; /etc/ssl/certs/example.com_fullchain.crt
</code></pre>
<blockquote>
<p><strong><em>The full chain includes the leaf certificate first, followed by the intermediate certificate. This order is important because it ensures the correct certificate trust path.</em></strong></p>
</blockquote>
<p>3. Configuring Caddy with the Certificates<br />Next, the template Caddyfile is configured to use the full certificate chain and the private key. The Caddyfile is a simple configuration file where we specify the certificate locations.</p>
<p>Here’s the relevant section in the Caddyfile:</p>
<pre><code class="lang-plaintext">example.com {
    tls /etc/ssl/certs/example.com_fullchain.crt /etc/ssl/private/example.com.key
    reverse_proxy localhost:8080
}
</code></pre>
<p>The tls directive tells Caddy to use the full chain certificate and the private key for SSL/TLS encryption. The reverse_proxy directive forwards traffic to your application running on localhost:8080.</p>
<p>4. Reloading Caddy</p>
<p>Finally, the playbook reloads the Caddy service using systemd to apply the new configuration and certificate changes:</p>
<pre><code class="lang-bash">- name: Reload Caddy service to apply changes
  systemd:
    name: caddy
    state: reloaded
</code></pre>
<h2 id="heading-step-4-running-the-playbook"><strong>Step 4: Running the Playbook</strong></h2>
<p>To apply the changes, you’ll run the Ansible playbook on your server with the following command:</p>
<pre><code class="lang-bash">ansible-playbook -i your_inventory_file configure_caddy.yml
</code></pre>
<p>This will automate the entire process, including copying the certificate files, setting up Caddy, and reloading the service.</p>
<h2 id="heading-step-5-validation-via-command-line"><strong>Step 5: Validation via Command Line</strong></h2>
<p>After deploying the certificate using Ansible, you can use the openssl command to validate the expiration of the SSL certificate from your local machine or a remote server:</p>
<p>1. Using openssl to Check SSL Expiration:</p>
<p>This command will connect to your server and display the expiration date of the SSL certificate:</p>
<pre><code class="lang-bash">openssl s_client -connect yourdomain.com:443 -servername yourdomain.com &lt;/dev/null 2&gt;/dev/null | openssl x509 -noout -enddate
</code></pre>
<p>Output: The command will return a line like this:</p>
<pre><code class="lang-bash">notAfter=Dec 31 23:59:59 2024 GMT
</code></pre>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>In this article, we’ve demonstrated how to configure Caddy with an external SSL/TLS certificate from a commercial Certificate Authority. Using Ansible, we’ve automated copying the certificate files, concatenating the full chain, and configuring Caddy to use the certificate for encrypted communication. By following this guide, you can ensure that your Caddy server is securely configured with external certificates, making it ready for production with minimal manual intervention.</p>
<p>By automating this process, you can easily scale and maintain secure configurations for multiple servers, saving you time and reducing the chance of errors.</p>
<p><em>Irene Ufia is a software engineer specializing in DevSecOps (Blockchain Infrastructure).</em></p>
<p><em>Follow me for insights and technical tips:</em> <a target="_blank" href="https://www.linkedin.com/in/covenantireneufia"><em>LinkedIn</em></a> <em>|</em> <a target="_blank" href="https://github.com/UfiairENE"><em>Github</em></a></p>
]]></content:encoded></item><item><title><![CDATA[Step-by-Step Guide to Setting Up a Hashnode Blog in Nigeria and Solving Accessibility Problems]]></title><description><![CDATA[If you’ve set up a Hashnode blog and noticed it doesn’t load on Nigerian ISPs, you’re not alone. Many users resort to VPNs, but there’s a better solution—using Cloudflare’s proxy (orange cloud) instead of DNS-only (gray cloud).
However, there’s one i...]]></description><link>https://blog.devopsinsight.co/how-to-access-your-hashnode-blog-in-nigeria-without-a-vpn</link><guid isPermaLink="true">https://blog.devopsinsight.co/how-to-access-your-hashnode-blog-in-nigeria-without-a-vpn</guid><category><![CDATA[Hashnode]]></category><category><![CDATA[Custom Domain]]></category><dc:creator><![CDATA[DevOps Insight with Irene]]></dc:creator><pubDate>Sun, 24 Nov 2024 23:00:00 GMT</pubDate><content:encoded><![CDATA[<p>If you’ve set up a Hashnode blog and noticed it doesn’t load on Nigerian ISPs, you’re not alone. Many users resort to VPNs, but there’s a better solution—<strong>using Cloudflare’s proxy (orange cloud) instead of DNS-only (gray cloud)</strong>.</p>
<p>However, there’s one issue: <strong>Hashnode won’t verify your domain if Cloudflare’s proxy is enabled</strong>. In this guide, I’ll show you how to <strong>successfully verify your subdomain</strong> and still <strong>make your blog accessible without a VPN</strong>.</p>
<hr />
<h2 id="heading-the-problem-hashnode-blogs-not-resolving-on-nigerian-isps"><strong>The Problem: Hashnode Blogs Not Resolving on Nigerian ISPs</strong></h2>
<p>Hashnode requires you to set your DNS records to <strong>DNS-only</strong> (gray cloud) in Cloudflare for verification. But even after doing this, many Nigerian ISPs fail to resolve custom domains, leaving users locked out of their own blogs.</p>
<p>Since Hashnode won’t verify your domain if Cloudflare’s proxy is enabled, the trick is to temporarily disable the proxy, complete the verification, and then turn it back on.</p>
<hr />
<h2 id="heading-the-fix-verify-your-domain-then-enable-cloudflare-proxy"><strong>The Fix: Verify Your Domain, Then Enable Cloudflare Proxy</strong></h2>
<p>Instead of struggling with VPNs, follow these steps to <strong>verify your Hashnode domain and make your blog accessible</strong>.</p>
<h3 id="heading-step-1-add-your-domain-to-cloudflare"><strong>Step 1: Add Your Domain to Cloudflare</strong></h3>
<ol>
<li><p>Sign up at <a target="_blank" href="https://www.cloudflare.com/">Cloudflare</a> and add your domain.</p>
</li>
<li><p>Let Cloudflare scan and import your DNS records.</p>
</li>
</ol>
<h3 id="heading-step-2-verify-your-hashnode-domain"><strong>Step 2: Verify Your Hashnode Domain</strong></h3>
<ol>
<li><p><strong>Go to Cloudflare’s DNS settings</strong>.</p>
</li>
<li><p><strong>Add a CNAME record</strong>:</p>
<ul>
<li><p><strong>Name</strong>: <code>blog</code> (or whatever subdomain you’re using).</p>
</li>
<li><p><strong>Target</strong>: <code>hashnode.network</code>.</p>
</li>
<li><p><strong>Proxy Status</strong>: Set to <strong>DNS-only (gray cloud)</strong>.</p>
</li>
</ul>
</li>
<li><p><strong>Go to Hashnode</strong> and verify your custom domain.</p>
</li>
<li><p>Once verification is complete, your blog is connected, but it still might not resolve on Nigerian ISPs.</p>
</li>
</ol>
<h3 id="heading-step-3-enable-cloudflare-proxy"><strong>Step 3: Enable Cloudflare Proxy</strong></h3>
<ol>
<li><p>Go back to Cloudflare’s <strong>DNS settings</strong>.</p>
</li>
<li><p>Change the <strong>Proxy Status</strong> of your CNAME record to <strong>Proxied (orange cloud ON)</strong>.</p>
</li>
<li><p>Wait a few minutes for the changes to propagate.</p>
</li>
</ol>
<p>Your blog should now be accessible across Nigerian ISPs without needing a VPN!</p>
<hr />
<h2 id="heading-why-this-works"><strong>Why This Works</strong></h2>
<p>Hashnode requires <strong>DNS-only mode</strong> for verification, but Nigerian ISPs often fail to resolve <code>hashnode.network</code>. When you enable Cloudflare’s proxy <strong>after verification</strong>, Cloudflare routes your traffic through its global network, bypassing these ISP restrictions.</p>
<h3 id="heading-common-questions"><strong>Common Questions</strong></h3>
<p><strong>1. Why does Hashnode recommend DNS-only mode?</strong><br />Hashnode prefers a direct connection to their servers for simplicity and verification purposes. However, this doesn’t work well with some Nigerian ISPs, which is why enabling Cloudflare’s proxy after verification helps.</p>
<p><strong>2. Won’t enabling Cloudflare’s proxy break my Hashnode setup?</strong><br />No. Once verification is complete, Hashnode doesn’t need DNS-only mode to keep your blog active. Proxying the traffic through Cloudflare makes it accessible.</p>
<hr />
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>If your Hashnode blog isn’t loading in Nigeria, follow this method:</p>
<ol>
<li><p>Verify your subdomain with DNS-only mode.</p>
</li>
<li><p>Enable Cloudflare’s proxy afterward.</p>
</li>
<li><p>Enjoy seamless access to your blog.</p>
</li>
</ol>
<p>This fix worked for me, and I hope it helps you too! Let me know if you have any questions.</p>
]]></content:encoded></item></channel></rss>