<?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[Cloud Infrastructure]]></title><description><![CDATA[Cloud Infrastructure]]></description><link>https://blog.aliasgar.cloud</link><generator>RSS for Node</generator><lastBuildDate>Mon, 13 Apr 2026 23:23:56 GMT</lastBuildDate><atom:link href="https://blog.aliasgar.cloud/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Deploying a Secure Contact Form Application with Kubernetes and Cloudflare Tunnel]]></title><description><![CDATA[Introduction
In this comprehensive guide, we'll walk through setting up and deploying a secure, scalable contact-form backend using Python Flask and Kubernetes and exposing it securely to the Internet using Cloudflare Tunnel. By the end of this tutor...]]></description><link>https://blog.aliasgar.cloud/deploying-a-secure-contact-form-application-with-kubernetes-and-cloudflare-tunnel</link><guid isPermaLink="true">https://blog.aliasgar.cloud/deploying-a-secure-contact-form-application-with-kubernetes-and-cloudflare-tunnel</guid><category><![CDATA[cloudflare]]></category><category><![CDATA[APIs]]></category><category><![CDATA[contact form]]></category><category><![CDATA[Flask Framework]]></category><category><![CDATA[Python]]></category><category><![CDATA[#kubernetes #container ]]></category><category><![CDATA[cloudflare-pages]]></category><category><![CDATA[tunneling]]></category><category><![CDATA[Cloud Computing]]></category><category><![CDATA[cloud security]]></category><category><![CDATA[cloud native]]></category><dc:creator><![CDATA[Aliasgar Husain]]></dc:creator><pubDate>Tue, 18 Mar 2025 02:20:21 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>In this comprehensive guide, we'll walk through setting up and deploying a secure, scalable contact-form backend using Python Flask and Kubernetes and exposing it securely to the Internet using Cloudflare Tunnel. By the end of this tutorial, you'll have a fully working backend service accessible globally, ideal for integrating with any front-end application.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ul>
<li><p>Basic knowledge of Kubernetes, Docker, and Python</p>
</li>
<li><p>Cloudflare account and a registered domain</p>
</li>
<li><p>Docker and Kubernetes installed locally or on your server</p>
</li>
<li><p>setup a SendGrid account and get the API key</p>
</li>
</ul>
<h2 id="heading-step-1-create-your-flask-contact-form-application">Step 1: Create Your Flask Contact Form Application</h2>
<p>Create a Flask app named <code>app.py</code> with email integration using SendGrid.</p>
<p><code>app.py:</code></p>
<pre><code class="lang-bash">from flask import Flask, request, jsonify
from flask_cors import CORS
import os
import logging
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail

app = Flask(__name__)
CORS(app)

@app.route(<span class="hljs-string">'/contact-form'</span>, methods=[<span class="hljs-string">'POST'</span>, <span class="hljs-string">'OPTIONS'</span>])
def contact_form():
    <span class="hljs-keyword">if</span> request.method == <span class="hljs-string">"OPTIONS"</span>:
        response = jsonify({<span class="hljs-string">"message"</span>: <span class="hljs-string">"CORS Preflight OK"</span>})
        response.headers.add(<span class="hljs-string">"Access-Control-Allow-Origin"</span>, <span class="hljs-string">"*"</span>)
        response.headers.add(<span class="hljs-string">"Access-Control-Allow-Methods"</span>, <span class="hljs-string">"POST, OPTIONS"</span>)
        response.headers.add(<span class="hljs-string">"Access-Control-Allow-Headers"</span>, <span class="hljs-string">"Content-Type, Authorization"</span>)
        <span class="hljs-built_in">return</span> response, 200

    data = request.get_json()
    required_fields = [<span class="hljs-string">'name'</span>, <span class="hljs-string">'email'</span>, <span class="hljs-string">'subject'</span>, <span class="hljs-string">'message'</span>]
    <span class="hljs-keyword">if</span> not all(field <span class="hljs-keyword">in</span> data <span class="hljs-keyword">for</span> field <span class="hljs-keyword">in</span> required_fields):
        <span class="hljs-built_in">return</span> jsonify({<span class="hljs-string">"error"</span>: <span class="hljs-string">"Missing fields"</span>}), 400

    sender_email = os.getenv(<span class="hljs-string">"SENDER_EMAIL"</span>)
    receiver_email = os.getenv(<span class="hljs-string">"RECEIVER_EMAIL"</span>)

    email_body = f<span class="hljs-string">""</span><span class="hljs-string">"
    &lt;p&gt;&lt;strong&gt;Name:&lt;/strong&gt; {data['name']}&lt;/p&gt;
    &lt;p&gt;&lt;strong&gt;Email:&lt;/strong&gt; {data['email']}&lt;/p&gt;
    &lt;p&gt;&lt;strong&gt;Subject:&lt;/strong&gt; {data['subject']}&lt;/p&gt;
    &lt;p&gt;&lt;strong&gt;Message:&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;{data['message']}&lt;/p&gt;
    "</span><span class="hljs-string">""</span>

    sg = SendGridAPIClient(os.getenv(<span class="hljs-string">"SENDGRID_API_KEY"</span>))
    email = Mail(from_email=sender_email, to_emails=receiver_email,
                 subject=data[<span class="hljs-string">'subject'</span>], html_content=email_body)
    sg.send(email)

    <span class="hljs-built_in">return</span> jsonify({<span class="hljs-string">"message"</span>: <span class="hljs-string">"Form submitted successfully"</span>}), 200

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">'__main__'</span>:
    app.run(host=<span class="hljs-string">'0.0.0.0'</span>, port=5000)
</code></pre>
<p><code>requirements.txt:</code></p>
<pre><code class="lang-bash">flask
flask_cors
gunicorn
sendgrid
</code></pre>
<h2 id="heading-step-2-dockerizing-your-application">Step 2: Dockerizing Your Application</h2>
<p>Create a <code>Dockerfile</code> in the root directory:</p>
<pre><code class="lang-bash">FROM python:3.9
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
EXPOSE 5000
CMD [<span class="hljs-string">"gunicorn"</span>, <span class="hljs-string">"-w"</span>, <span class="hljs-string">"2"</span>, <span class="hljs-string">"-b"</span>, <span class="hljs-string">"0.0.0.0:5000"</span>, <span class="hljs-string">"app:app"</span>]
</code></pre>
<p>Build and push your Docker image:</p>
<pre><code class="lang-bash">docker build -t yourdockerhubusername/contact-form-app:latest .
docker push yourdockerhubusername/contact-form-app:latest
</code></pre>
<hr />
<h2 id="heading-step-3-deploying-application-to-kubernetes">Step 3: Deploying Application to Kubernetes</h2>
<p>Create Kubernetes Deployment and Service files:</p>
<p><code>deployment.yaml:</code></p>
<pre><code class="lang-bash">apiVersion: apps/v1
kind: Deployment
metadata:
  name: contact-form-app
  namespace: contact-form
spec:
  replicas: 1
  selector:
    matchLabels:
      app: contact-form-app
  template:
    metadata:
      labels:
        app: contact-form-app
    spec:
      containers:
        - name: contact-form
          image: yourdockerhubusername/contact-form-app:latest
          ports:
            - containerPort: 5000
          env:
            - name: SENDGRID_API_KEY
              valueFrom:
                secretKeyRef:
                  name: sendgrid-secret
                  key: sendgrid_api_key
            - name: SENDER_EMAIL
              value: <span class="hljs-string">"your-sender-email@example.com"</span>
            - name: RECEIVER_EMAIL
              value: <span class="hljs-string">"your-receiver-email@example.com"</span>
</code></pre>
<p><code>service.yaml:</code></p>
<pre><code class="lang-bash">apiVersion: v1
kind: Service
metadata:
  name: contact-form-service
  namespace: contact-form
spec:
  selector:
    app: contact-form-app
  ports:
    - protocol: TCP
      port: 3344
      targetPort: 5000
  <span class="hljs-built_in">type</span>: ClusterIP
</code></pre>
<h3 id="heading-kubernetes-secret">Kubernetes Secret</h3>
<p>Create Kubernetes secret for SendGrid API:</p>
<pre><code class="lang-bash">kubectl create secret generic sendgrid-secret -n contact-form --from-literal=sendgrid_api_key=<span class="hljs-string">'your-sendgrid-api-key'</span>
</code></pre>
<p>Deploy:</p>
<pre><code class="lang-bash">kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
</code></pre>
<hr />
<h2 id="heading-step-4-test-application-using-clusterip-local-test">Step 4: Test Application using ClusterIP (Local Test)</h2>
<p>Create a temporary debug pod:</p>
<pre><code class="lang-bash">kubectl run testcurl -n contact-form --image=radial/busyboxplus:curl -i --tty --rm
</code></pre>
<p>Inside pod run:</p>
<pre><code class="lang-bash">curl -X POST http://contact-form-service:3344/contact-form -H <span class="hljs-string">'Content-Type: application/json'</span> -d <span class="hljs-string">'{"name":"test","email":"test@test.com","subject":"test","message":"hello"}'</span>
</code></pre>
<hr />
<h2 id="heading-step-5-setting-up-cloudflare-tunnel">Step 5: Setting Up Cloudflare Tunnel</h2>
<ol>
<li>Install Cloudflared:</li>
</ol>
<pre><code class="lang-bash">sudo apt install cloudflared
</code></pre>
<ol start="2">
<li>Authenticate Cloudflare:</li>
</ol>
<pre><code class="lang-bash">cloudflared tunnel login
</code></pre>
<ol start="3">
<li>Create a Tunnel:</li>
</ol>
<pre><code class="lang-bash">cloudflared tunnel create contact-form-tunnel
</code></pre>
<ol start="4">
<li><p>Configure DNS via Cloudflare Dashboard:</p>
<ul>
<li><p>Log into Cloudflare &gt; select domain &gt; DNS tab</p>
</li>
<li><p>Add a CNAME record:</p>
<ul>
<li><p>Name: <code>contact</code> (your subdomain)</p>
</li>
<li><p>Target: <code>&lt;tunnel-uuid&gt;.cfargotunnel.com</code></p>
</li>
</ul>
</li>
</ul>
</li>
</ol>
<hr />
<h2 id="heading-step-6-cloudflare-kubernetes-deployment">Step 6: Cloudflare Kubernetes Deployment</h2>
<p><code>cloudflared-deployment.yaml</code>:</p>
<pre><code class="lang-bash">apiVersion: apps/v1
kind: Deployment
metadata:
  name: cloudflare-tunnel
  namespace: contact-form
spec:
  replicas: 1
  selector:
    matchLabels:
      app: cloudflare-tunnel
  template:
    metadata:
      labels:
        app: cloudflare-tunnel
    spec:
      containers:
        - name: cloudflare-tunnel
          image: cloudflare/cloudflared:latest
          args:
            - <span class="hljs-string">"tunnel"</span>
            - <span class="hljs-string">"--no-autoupdate"</span>
            - <span class="hljs-string">"run"</span>
            - <span class="hljs-string">"--token"</span>
            - <span class="hljs-string">"<span class="hljs-subst">$(TUNNEL_TOKEN)</span>"</span>
          env:
            - name: TUNNEL_TOKEN
              valueFrom:
                secretKeyRef:
                  name: cloudflare-tunnel-secret
                  key: token
          volumeMounts:
            - name: config-volume
              mountPath: /etc/cloudflared
      volumes:
        - name: config-volume
          configMap:
            name: cloudflare-config
</code></pre>
<p><code>cloudflared-config.yaml:</code></p>
<pre><code class="lang-bash">apiVersion: v1
kind: ConfigMap
metadata:
  name: cloudflared-config
  namespace: contact-form
data:
  config.yml: |
    ingress:
      - hostname: contact.yourdomain.com
        service: http://contact-form-service.contact-form.svc.cluster.local:3344
      - service: http_status:404
</code></pre>
<p><strong>Cloudflare secret</strong>:</p>
<pre><code class="lang-bash">kubectl create secret generic cloudflare-tunnel-secret --from-literal=token=<span class="hljs-string">'your-tunnel-token'</span> -n contact-form
</code></pre>
<p>Deploy Cloudflared:</p>
<pre><code class="lang-bash">kubectl apply -f cloudflared-config.yaml -f cloudflared-deployment.yaml
</code></pre>
<hr />
<h2 id="heading-step-7-final-test">Step 7: Final Test</h2>
<pre><code class="lang-bash">curl -X POST https://contact.yourdomain.com/contact-form -H <span class="hljs-string">'Content-Type: application/json'</span> -d <span class="hljs-string">'{"name":"test","email":"test@test.com","subject":"hello","message":"world"}'</span>
</code></pre>
<hr />
<h2 id="heading-frontend-integration">Frontend Integration</h2>
<p>Use the above URL as an API endpoint for form submissions from your front end.</p>
<h2 id="heading-future-scope">Future Scope</h2>
<ul>
<li><p>Integrate a database to store submissions.</p>
</li>
<li><p>Set up analytics and monitoring.</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>You now have a secure, scalable contact form backend ready for production use.</p>
]]></content:encoded></item><item><title><![CDATA[How I Built My Home Server and Made It Accessible from Anywhere]]></title><description><![CDATA[Introduction
Setting up a personal home server can be a game-changer for those who want to self-host applications, manage cloud services, or create a test environment. In this guide, I will walk you through how I set up my server using a Lenovo Think...]]></description><link>https://blog.aliasgar.cloud/home-server-setup</link><guid isPermaLink="true">https://blog.aliasgar.cloud/home-server-setup</guid><category><![CDATA[ssh access from anywhere]]></category><category><![CDATA[Thinkcentre m93p]]></category><category><![CDATA[homeserver]]></category><category><![CDATA[ssh]]></category><category><![CDATA[cloudflare]]></category><category><![CDATA[cloudflare-tunnel]]></category><category><![CDATA[centos]]></category><dc:creator><![CDATA[Aliasgar Husain]]></dc:creator><pubDate>Fri, 14 Mar 2025 22:12:08 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>Setting up a personal home server can be a game-changer for those who want to self-host applications, manage cloud services, or create a test environment. In this guide, I will walk you through how I set up my server using a Lenovo ThinkCentre M93p, featuring:</p>
<ul>
<li><p>CentOS Server Installation</p>
</li>
<li><p>Strict networking configuration</p>
</li>
<li><p>Cloudflare Tunnel for secure remote SSH access</p>
</li>
<li><p>Installing and configuring Kubernetes and Docker</p>
</li>
<li><p>Setting up Prometheus and Grafana for monitoring</p>
</li>
<li><p>Hosting applications and jobs efficiently</p>
</li>
</ul>
<p>Let’s dive into the details of how I built this home server and made it accessible from anywhere securely.</p>
<h2 id="heading-1-hardware-and-initial-setup"><strong>1. Hardware and Initial Setup</strong></h2>
<h3 id="heading-11-choosing-the-hardware"><strong>1.1 Choosing the Hardware</strong></h3>
<p>I used a <strong>Lenovo ThinkCentre M93p</strong> with the following specifications:</p>
<ul>
<li><p><strong>CPU</strong>: Intel Core i5-4570</p>
</li>
<li><p><strong>RAM</strong>: 24GB</p>
</li>
<li><p><strong>Storage</strong>:</p>
<ul>
<li><p><strong>1TB HDD</strong> for general storage</p>
</li>
<li><p><strong>256GB SSD</strong> for the operating system</p>
</li>
</ul>
</li>
</ul>
<p>This setup is powerful enough for running multiple containers and handling monitoring tasks efficiently.</p>
<h3 id="heading-12-installing-centos-server"><strong>1.2 Installing CentOS Server</strong></h3>
<p>To keep things lightweight and secure, I installed <strong>CentOS Stream 9</strong> as the operating system.</p>
<h4 id="heading-steps-to-install-centos-server"><strong>Steps to Install CentOS Server</strong></h4>
<ol>
<li><p>Download the <strong>CentOS Stream 9 ISO</strong> from the official website.</p>
</li>
<li><p>Create a bootable USB using <code>dd</code> on Linux or use <code>Rufus</code> Software.</p>
</li>
<li><p>Boot from the USB and follow the installation wizard.</p>
</li>
<li><p>Choose <strong>Minimal Installation</strong> to keep the system lightweight.</p>
</li>
<li><p>Configure a <strong>root password</strong> and create a <strong>new user account</strong>.</p>
</li>
<li><p>Complete the installation and reboot the system.</p>
</li>
</ol>
<h2 id="heading-2-configuring-strict-networking"><strong>2. Configuring Strict Networking</strong></h2>
<h3 id="heading-21-disabling-unused-services"><strong>2.1 Disabling Unused Services</strong></h3>
<p>To enhance security, enable <code>firewalld</code> if not:</p>
<pre><code class="lang-bash">sudo systemctl start firewalld
sudo systemctl <span class="hljs-built_in">enable</span> firewalld
sudo systemctl status firewalld
</code></pre>
<h3 id="heading-22-configuring-firewall-rules"><strong>2.2 Configuring Firewall Rules</strong></h3>
<p>To allow only essential traffic:</p>
<pre><code class="lang-bash">sudo firewall-cmd --permanent --add-port=22/tcp  <span class="hljs-comment"># SSH Access</span>
sudo firewall-cmd --permanent --add-port=6443/tcp <span class="hljs-comment"># Kubernetes API Server</span>
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
</code></pre>
<h2 id="heading-3-setting-up-cloudflare-tunnel-for-remote-ssh-access"><strong>3. Setting Up Cloudflare Tunnel for Remote SSH Access</strong></h2>
<p>Cloudflare Tunnel allows you to access your home server from anywhere securely.</p>
<h3 id="heading-31-installing-cloudflared"><strong>3.1 Installing Cloudflared</strong></h3>
<pre><code class="lang-bash">sudo yum install -y cloudflared
</code></pre>
<h3 id="heading-32-authenticating-with-cloudflare"><strong>3.2 Authenticating with Cloudflare</strong></h3>
<pre><code class="lang-bash">cloudflared tunnel login
</code></pre>
<p>This command opens a browser to authenticate with Cloudflare.</p>
<h3 id="heading-33-creating-the-tunnel"><strong>3.3 Creating the Tunnel</strong></h3>
<pre><code class="lang-bash">cloudflared tunnel create my-home-server
</code></pre>
<h3 id="heading-34-configuring-the-tunnel"><strong>3.4 Configuring the Tunnel</strong></h3>
<pre><code class="lang-bash">cloudflared tunnel route dns my-home-server myserver.example.com
</code></pre>
<h3 id="heading-35-running-the-tunnel-as-a-service"><strong>3.5 Running the Tunnel as a Service</strong></h3>
<pre><code class="lang-bash">sudo cloudflared service install
</code></pre>
<p>Now, you can SSH securely into your server using:</p>
<pre><code class="lang-bash">ssh -o ProxyCommand=<span class="hljs-string">"cloudflared access ssh --hostname myserver.example.com"</span> user@myserver.example.com
</code></pre>
<h2 id="heading-4-installing-kubernetes-and-docker"><strong>4. Installing Kubernetes and Docker</strong></h2>
<h3 id="heading-41-installing-containerd-and-kubernetes"><strong>4.1 Installing Containerd and Kubernetes</strong></h3>
<pre><code class="lang-bash">sudo yum install -y containerd kubelet kubeadm kubectl
</code></pre>
<h3 id="heading-42-initializing-kubernetes"><strong>4.2 Initializing Kubernetes</strong></h3>
<pre><code class="lang-bash">sudo kubeadm init --pod-network-cidr=10.244.0.0/16
</code></pre>
<h3 id="heading-43-configuring-kubeconfig"><strong>4.3 Configuring Kubeconfig</strong></h3>
<pre><code class="lang-bash">mkdir -p <span class="hljs-variable">$HOME</span>/.kube
sudo cp -i /etc/kubernetes/admin.conf <span class="hljs-variable">$HOME</span>/.kube/config
sudo chown $(id -u):$(id -g) <span class="hljs-variable">$HOME</span>/.kube/config
</code></pre>
<h3 id="heading-44-installing-flannel-for-networking"><strong>4.4 Installing Flannel for Networking</strong></h3>
<pre><code class="lang-bash">kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
</code></pre>
<h2 id="heading-5-setting-up-prometheus-and-grafana-for-monitoring"><strong>5. Setting Up Prometheus and Grafana for Monitoring</strong></h2>
<h3 id="heading-51-deploying-prometheus"><strong>5.1 Deploying Prometheus</strong></h3>
<pre><code class="lang-bash">apiVersion: apps/v1
kind: Deployment
metadata:
  name: prometheus
  namespace: monitoring
spec:
  replicas: 1
  selector:
    matchLabels:
      app: prometheus
  template:
    metadata:
      labels:
        app: prometheus
    spec:
      containers:
        - name: prometheus
          image: prom/prometheus:latest
          ports:
            - containerPort: 9090
</code></pre>
<h3 id="heading-52-deploying-grafana"><strong>5.2 Deploying Grafana</strong></h3>
<pre><code class="lang-bash">apiVersion: apps/v1
kind: Deployment
metadata:
  name: grafana
  namespace: monitoring
spec:
  replicas: 1
  selector:
    matchLabels:
      app: grafana
  template:
    metadata:
      labels:
        app: grafana
    spec:
      containers:
        - name: grafana
          image: grafana/grafana:latest
          ports:
            - containerPort: 3000
</code></pre>
<p>After applying these configurations, you can access:</p>
<ul>
<li><p><strong>Prometheus</strong>: <code>http://&lt;server-ip&gt;:9090</code></p>
</li>
<li><p><strong>Grafana</strong>: <code>http://&lt;server-ip&gt;:3000</code></p>
</li>
</ul>
<h2 id="heading-6-conclusion"><strong>6. Conclusion</strong></h2>
<p>By following this guide, you now have a fully functional home server running Kubernetes, Docker, and a monitoring stack. <strong>With Cloudflare Tunnel, you can securely access your server from anywhere.</strong></p>
<h3 id="heading-whats-next"><strong>What’s Next?</strong></h3>
<ul>
<li><p>Deploy self-hosted apps using Helm charts.</p>
</li>
<li><p>Set up automatic backups.</p>
</li>
<li><p>Experiment with CI/CD pipelines on your home server.</p>
</li>
</ul>
<p>Let me know your thoughts, and happy self-hosting! 🚀</p>
]]></content:encoded></item></channel></rss>