<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Ansible on DevOps Engineer &amp; CloudAdmin</title><link>https://ruadmin.root.sx/tags/ansible/</link><description>Recent content in Ansible on DevOps Engineer &amp; CloudAdmin</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><atom:link href="https://ruadmin.root.sx/tags/ansible/index.xml" rel="self" type="application/rss+xml"/><item><title>CI/CD &amp; Production Infrastructure for a Social App</title><link>https://ruadmin.root.sx/posts/cicd/ci-cd-dating/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://ruadmin.root.sx/posts/cicd/ci-cd-dating/</guid><description>&lt;h2 id="production-infrastructure--cicd-for-a-social-app-launch"&gt;Production Infrastructure &amp;amp; CI/CD for a Social App Launch&lt;/h2&gt;
&lt;hr&gt;
&lt;h4 id="client"&gt;Client&lt;/h4&gt;
&lt;p&gt;Puzzle Master — a social matching platform&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id="challenge"&gt;Challenge&lt;/h4&gt;
&lt;p&gt;The startup had a production-ready Nest.js backend and Angular frontend, but zero infrastructure: deployments were manual, there was no CI/CD, no monitoring, no backups, and no separation between dev and prod environments. The goal was to build a complete DevOps stack from scratch before the public launch.&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id="solution"&gt;Solution&lt;/h4&gt;
&lt;h6 id="1-application-containerization"&gt;1. Application Containerization&lt;/h6&gt;
&lt;ul&gt;
&lt;li&gt;Multi-stage Dockerfile for backend (Nest.js + Prisma, non-root user)&lt;/li&gt;
&lt;li&gt;Multi-stage Dockerfile for frontend (Angular 12, legacy OpenSSL, Nginx for static assets)&lt;/li&gt;
&lt;li&gt;Docker Compose full stack: PostgreSQL 15, Redis 7, imgproxy, Nginx&lt;/li&gt;
&lt;li&gt;Healthchecks and &lt;code&gt;depends_on&lt;/code&gt; for correct startup ordering&lt;/li&gt;
&lt;li&gt;Isolated dev and prod environments in &lt;code&gt;/opt/dev&lt;/code&gt; and &lt;code&gt;/opt/prod&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h6 id="2-gitlab-cicd"&gt;2. GitLab CI/CD&lt;/h6&gt;
&lt;ul&gt;
&lt;li&gt;Migration of repository from Bitbucket to GitLab&lt;/li&gt;
&lt;li&gt;Pipeline for backend and frontend: build → push → deploy&lt;/li&gt;
&lt;li&gt;GitLab Container Registry for Docker image storage&lt;/li&gt;
&lt;li&gt;Automatic deploy to dev on every push; manual trigger for prod&lt;/li&gt;
&lt;li&gt;SSH deployment to VPS via &lt;code&gt;SSH_PRIVATE_KEY&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h6 id="3-nginx-reverse-proxy"&gt;3. Nginx Reverse Proxy&lt;/h6&gt;
&lt;ul&gt;
&lt;li&gt;Environment-agnostic config via &lt;code&gt;envsubst&lt;/code&gt; for dev/prod parity&lt;/li&gt;
&lt;li&gt;SSL/TLS (TLSv1.2, TLSv1.3) with Cloudflare certificates&lt;/li&gt;
&lt;li&gt;Routing: &lt;code&gt;/api/*&lt;/code&gt; → backend:4000, &lt;code&gt;/*&lt;/code&gt; → frontend:80&lt;/li&gt;
&lt;li&gt;www → root domain redirect (301)&lt;/li&gt;
&lt;li&gt;Separate imgproxy stack with SSL termination&lt;/li&gt;
&lt;/ul&gt;
&lt;h6 id="4-security-ansible"&gt;4. Security (Ansible)&lt;/h6&gt;
&lt;ul&gt;
&lt;li&gt;Server hardening via Ansible: SSH key-only auth, root login disabled&lt;/li&gt;
&lt;li&gt;UFW Firewall: only ports 80, 443, and custom SSH open&lt;/li&gt;
&lt;li&gt;Database accessible only via SSH tunnel&lt;/li&gt;
&lt;li&gt;All secrets stored in GitLab CI/CD variables&lt;/li&gt;
&lt;/ul&gt;
&lt;h6 id="5-monitoring"&gt;5. Monitoring&lt;/h6&gt;
&lt;ul&gt;
&lt;li&gt;Prometheus + Grafana with automated dashboard provisioning&lt;/li&gt;
&lt;li&gt;Exporters: Node, cAdvisor, Postgres, Redis, Nginx, Blackbox&lt;/li&gt;
&lt;li&gt;5 Grafana dashboards: server, Docker containers, PostgreSQL, Redis, Nginx&lt;/li&gt;
&lt;li&gt;Alertmanager with Slack/webhook integration; alerts on CPU/RAM/Disk/API/SSL&lt;/li&gt;
&lt;/ul&gt;
&lt;h6 id="6-database-backups"&gt;6. Database Backups&lt;/h6&gt;
&lt;ul&gt;
&lt;li&gt;Automated &lt;code&gt;pg_dump&lt;/code&gt; every hour&lt;/li&gt;
&lt;li&gt;gzip compression and upload to S3-compatible object storage (Cloudflare R2)&lt;/li&gt;
&lt;li&gt;Prometheus backup metrics: success status, size, timestamp&lt;/li&gt;
&lt;li&gt;Alerts: &lt;code&gt;DatabaseBackupMissing&lt;/code&gt;, &lt;code&gt;DatabaseBackupFailed&lt;/code&gt;, &lt;code&gt;DatabaseBackupSizeAnomaly&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h4 id="technologies"&gt;Technologies&lt;/h4&gt;
&lt;div class="row"&gt;
&lt;div class="col-4 col-lg-2 pt-2" style="text-align: center;"&gt;&lt;img src="https://ruadmin.root.sx/icons/gitlab-original.svg" alt="GitLab"&gt;&lt;div&gt;GitLab CI&lt;/div&gt;&lt;/div&gt;
&lt;div class="col-4 col-lg-2 pt-2" style="text-align: center;"&gt;&lt;img src="https://ruadmin.root.sx/icons/docker-original.svg" alt="Docker"&gt;&lt;div&gt;Docker&lt;/div&gt;&lt;/div&gt;
&lt;div class="col-4 col-lg-2 pt-2" style="text-align: center;"&gt;&lt;img src="https://ruadmin.root.sx/icons/ansible-original.svg" alt="Ansible"&gt;&lt;div&gt;Ansible&lt;/div&gt;&lt;/div&gt;
&lt;div class="col-4 col-lg-2 pt-2" style="text-align: center;"&gt;&lt;img src="https://ruadmin.root.sx/icons/prometheus-original.svg" alt="Prometheus"&gt;&lt;div&gt;Prometheus&lt;/div&gt;&lt;/div&gt;
&lt;div class="col-4 col-lg-2 pt-2" style="text-align: center;"&gt;&lt;img src="https://ruadmin.root.sx/icons/nginx.svg" alt="Nginx"&gt;&lt;div&gt;Nginx&lt;/div&gt;&lt;/div&gt;
&lt;div class="col-4 col-lg-2 pt-2" style="text-align: center;"&gt;&lt;img src="https://ruadmin.root.sx/icons/postgresql.svg" alt="PostgreSQL"&gt;&lt;div&gt;PostgreSQL&lt;/div&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h4 id="results"&gt;Results&lt;/h4&gt;
&lt;p&gt;✅ &lt;strong&gt;Deploy:&lt;/strong&gt; git push to main → automatic build and deploy to server&lt;br&gt;
✅ &lt;strong&gt;Environments:&lt;/strong&gt; full dev/prod isolation on a single VPS&lt;br&gt;
✅ &lt;strong&gt;Monitoring:&lt;/strong&gt; 5 dashboards, alerts across 6 categories&lt;br&gt;
✅ &lt;strong&gt;Backups:&lt;/strong&gt; automated hourly &lt;code&gt;pg_dump&lt;/code&gt; to Cloudflare R2&lt;br&gt;
✅ &lt;strong&gt;Security:&lt;/strong&gt; UFW, key-based SSH, database inaccessible from outside&lt;br&gt;
✅ &lt;strong&gt;Scalability:&lt;/strong&gt; architecture ready for database extraction to a dedicated server&lt;/p&gt;</description></item><item><title>WireGuard VPN Infrastructure</title><link>https://ruadmin.root.sx/posts/network-security/vpn-services/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://ruadmin.root.sx/posts/network-security/vpn-services/</guid><description>&lt;h2 id="wireguard-vpn-infrastructure"&gt;WireGuard VPN Infrastructure&lt;/h2&gt;
&lt;hr&gt;
&lt;h4 id="challenge"&gt;Challenge&lt;/h4&gt;
&lt;p&gt;A distributed team of 15+ engineers working across multiple locations needed secure, low-latency access to internal corporate infrastructure — without relying on heavyweight legacy VPN appliances. The existing setup introduced significant overhead, was difficult to maintain, and caused frequent connectivity issues for remote employees. The goal was to replace it with a lightweight, self-hosted solution that is fast, auditable, and easy to scale.&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id="solution"&gt;Solution&lt;/h4&gt;
&lt;h6 id="1-technology-selection"&gt;1. Technology Selection&lt;/h6&gt;
&lt;ul&gt;
&lt;li&gt;Protocol evaluation: OpenVPN, WireGuard, Outline&lt;/li&gt;
&lt;li&gt;WireGuard chosen for its speed, simplicity, and modern cryptography&lt;/li&gt;
&lt;li&gt;Docker for isolation and portability&lt;/li&gt;
&lt;li&gt;Ansible for automated provisioning&lt;/li&gt;
&lt;/ul&gt;
&lt;h6 id="2-infrastructure"&gt;2. Infrastructure&lt;/h6&gt;
&lt;ul&gt;
&lt;li&gt;VPS hosted in a neutral jurisdiction (Netherlands)&lt;/li&gt;
&lt;li&gt;Docker Compose for service orchestration&lt;/li&gt;
&lt;li&gt;WireGuard running in a container&lt;/li&gt;
&lt;li&gt;Nginx for the web management panel&lt;/li&gt;
&lt;li&gt;Prometheus + Grafana for monitoring&lt;/li&gt;
&lt;/ul&gt;
&lt;h6 id="3-automation"&gt;3. Automation&lt;/h6&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Ansible playbook for deployment&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Deploy WireGuard VPN&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;hosts&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;vpn_servers&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;roles&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;docker&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;wireguard&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;monitoring&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;backup&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h6 id="4-security"&gt;4. Security&lt;/h6&gt;
&lt;ul&gt;
&lt;li&gt;Automatic key rotation&lt;/li&gt;
&lt;li&gt;Firewall rules (UFW)&lt;/li&gt;
&lt;li&gt;Fail2ban for brute-force protection&lt;/li&gt;
&lt;li&gt;ChaCha20-Poly1305 traffic encryption&lt;/li&gt;
&lt;/ul&gt;
&lt;h6 id="5-monitoring"&gt;5. Monitoring&lt;/h6&gt;
&lt;ul&gt;
&lt;li&gt;Bandwidth and throughput metrics&lt;/li&gt;
&lt;li&gt;Downtime alerts&lt;/li&gt;
&lt;li&gt;Connection logging&lt;/li&gt;
&lt;li&gt;Automatic restart on failure&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h4 id="technologies"&gt;Technologies&lt;/h4&gt;
&lt;div class="row"&gt;
&lt;div class="col-4 col-lg-2 pt-2" style="text-align: center;"&gt;&lt;img src="https://ruadmin.root.sx/icons/wireguard.svg" alt="WireGuard"&gt;&lt;div&gt;WireGuard&lt;/div&gt;&lt;/div&gt;
&lt;div class="col-4 col-lg-2 pt-2" style="text-align: center;"&gt;&lt;img src="https://ruadmin.root.sx/icons/docker-original.svg" alt="Docker"&gt;&lt;div&gt;Docker&lt;/div&gt;&lt;/div&gt;
&lt;div class="col-4 col-lg-2 pt-2" style="text-align: center;"&gt;&lt;img src="https://ruadmin.root.sx/icons/ansible-original.svg" alt="Ansible"&gt;&lt;div&gt;Ansible&lt;/div&gt;&lt;/div&gt;
&lt;div class="col-4 col-lg-2 pt-2" style="text-align: center;"&gt;&lt;img src="https://ruadmin.root.sx/icons/prometheus-original.svg" alt="Prometheus"&gt;&lt;div&gt;Prometheus&lt;/div&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h4 id="results"&gt;Results&lt;/h4&gt;
&lt;p&gt;✅ &lt;strong&gt;Uptime:&lt;/strong&gt; 99.8% over 6+ months of operation&lt;br&gt;
✅ &lt;strong&gt;Speed:&lt;/strong&gt; stable 100+ Mbps&lt;br&gt;
✅ &lt;strong&gt;Access:&lt;/strong&gt; OpenAI API, ChatGPT, GitHub Copilot, npm registry&lt;br&gt;
✅ &lt;strong&gt;Deployment time:&lt;/strong&gt; ~20 minutes per new server&lt;br&gt;
✅ &lt;strong&gt;Users:&lt;/strong&gt; 15+ developers with zero connectivity issues&lt;/p&gt;</description></item></channel></rss>