<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Latchu@DevOps</title>
    <description>The latest articles on DEV Community by Latchu@DevOps (@latchudevops).</description>
    <link>https://dev.to/latchudevops</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3038063%2F960b635d-29cf-43a0-be55-5eb0b5469ccd.jpeg</url>
      <title>DEV Community: Latchu@DevOps</title>
      <link>https://dev.to/latchudevops</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/latchudevops"/>
    <language>en</language>
    <item>
      <title>GitHub Actions workflow to deploy the Next.js Application on Vercel Cloud</title>
      <dc:creator>Latchu@DevOps</dc:creator>
      <pubDate>Tue, 24 Feb 2026 18:41:04 +0000</pubDate>
      <link>https://dev.to/latchudevops/github-actions-workflow-to-deploy-the-nextjs-application-on-vercel-cloud-2ooi</link>
      <guid>https://dev.to/latchudevops/github-actions-workflow-to-deploy-the-nextjs-application-on-vercel-cloud-2ooi</guid>
      <description>&lt;p&gt;In this article, I’ll walk you through setting up a GitHub Actions workflow to automatically deploy a Next.js application to Vercel.&lt;br&gt;
Continuous deployment helps streamline development and ensures every push is production-ready.&lt;br&gt;
We’ll configure secrets, create a workflow file, and connect GitHub with Vercel for seamless deployments.&lt;br&gt;
This setup enables automated builds and previews for every commit.&lt;br&gt;
Let’s dive into building a simple CI/CD pipeline for your Next.js app.&lt;/p&gt;


&lt;h2&gt;
  
  
  What We'll Build
&lt;/h2&gt;

&lt;p&gt;A complete Next.js application that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Runs on Ubuntu 24 on port 80 as a background service&lt;/li&gt;
&lt;li&gt;✅ Uses TypeScript and Tailwind CSS&lt;/li&gt;
&lt;li&gt;✅ Has automated testing with Jest&lt;/li&gt;
&lt;li&gt;✅ Auto-deploys to Vercel on every push&lt;/li&gt;
&lt;li&gt;✅ Includes GitHub Actions CI/CD pipeline&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tech Stack&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Next.js 14 (App Router)&lt;/li&gt;
&lt;li&gt;TypeScript&lt;/li&gt;
&lt;li&gt;Tailwind CSS&lt;/li&gt;
&lt;li&gt;PM2 (Process Manager)&lt;/li&gt;
&lt;li&gt;GitHub Actions&lt;/li&gt;
&lt;li&gt;Vercel&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  📋 Prerequisites
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Ubuntu 24.04 server (local or cloud)&lt;/li&gt;
&lt;li&gt;GitHub account&lt;/li&gt;
&lt;li&gt;Vercel account (free)&lt;/li&gt;
&lt;/ol&gt;


&lt;h3&gt;
  
  
  STEP 1: Install Node.js and Required Tools on local machine
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Update system
sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y

# Install Node.js 20.x (LTS)
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs

# Verify installation
node --version   # Should show v20.x.x
npm --version    # Should show 10.x.x

# Install additional tools
sudo apt install -y git curl build-essential

# Install PM2 (process manager for background running)
sudo npm install -g pm2

# Verify PM2
pm2 --version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  STEP 2: Create Next.js Application
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create project directory
mkdir -p ~/nextjs-app
cd ~/nextjs-app

# Create Next.js app structure
# We'll create all files manually for complete control
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  Create Project Structure
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create directories
mkdir -p app/{api/hello,components,lib,styles}
mkdir -p public/images
mkdir -p .github/workflows

# Create files
touch next.config.js
touch package.json
touch tsconfig.json
touch .gitignore
touch .env.local
touch README.md
touch ecosystem.config.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now, let's create each file with content:&lt;/p&gt;


&lt;h4&gt;
  
  
  File 1: package.json
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat &amp;gt; package.json &amp;lt;&amp;lt; 'EOF'
{
  "name": "nextjs-app",
  "version": "1.0.0",
  "description": "Complete Next.js application with CI/CD",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start -p 80",
    "lint": "next lint",
    "test": "jest",
    "test:watch": "jest --watch"
  },
  "dependencies": {
    "next": "14.1.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  },
  "devDependencies": {
    "@testing-library/jest-dom": "^6.1.5",
    "@testing-library/react": "^14.1.2",
    "@types/node": "^20.10.6",
    "@types/react": "^18.2.46",
    "@types/react-dom": "^18.2.18",
    "autoprefixer": "^10.4.16",
    "eslint": "^8.56.0",
    "eslint-config-next": "14.1.0",
    "jest": "^29.7.0",
    "jest-environment-jsdom": "^29.7.0",
    "postcss": "^8.4.32",
    "tailwindcss": "^3.4.0",
    "typescript": "^5.3.3"
  }
}
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  File 2: next.config.js
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat &amp;gt; next.config.js &amp;lt;&amp;lt; 'EOF'
/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  swcMinify: true,
  output: 'standalone',
  poweredByHeader: false,

  // Environment variables
  env: {
    NEXT_PUBLIC_APP_NAME: process.env.NEXT_PUBLIC_APP_NAME || 'Next.js App',
    NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:80',
  },

  // Image optimization
  images: {
    domains: ['localhost'],
    formats: ['image/avif', 'image/webp'],
  },

  // Headers
  async headers() {
    return [
      {
        source: '/(.*)',
        headers: [
          {
            key: 'X-Frame-Options',
            value: 'DENY',
          },
          {
            key: 'X-Content-Type-Options',
            value: 'nosniff',
          },
          {
            key: 'Referrer-Policy',
            value: 'origin-when-cross-origin',
          },
        ],
      },
    ];
  },
};

module.exports = nextConfig;
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  File 3: tsconfig.json
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat &amp;gt; tsconfig.json &amp;lt;&amp;lt; 'EOF'
{
  "compilerOptions": {
    "target": "ES2020",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "bundler",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "incremental": true,
    "plugins": [
      {
        "name": "next"
      }
    ],
    "paths": {
      "@/*": ["./*"]
    }
  },
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
  "exclude": ["node_modules"]
}
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  File 4: .gitignore
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat &amp;gt; .gitignore &amp;lt;&amp;lt; 'EOF'
# Dependencies
node_modules/
/.pnp
.pnp.js

# Testing
/coverage

# Next.js
/.next/
/out/
.next

# Production
/build
dist

# Misc
.DS_Store
*.pem
.vercel

# Debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Local env files
.env*.local
.env.production

# PM2
.pm2

# IDE
.idea/
.vscode/
*.swp
*.swo
*~

# Logs
logs
*.log
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  File 5: .env.local
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat &amp;gt; .env.local &amp;lt;&amp;lt; 'EOF'
# Application
NEXT_PUBLIC_APP_NAME=My Next.js App
NEXT_PUBLIC_API_URL=http://localhost:80

# Environment
NODE_ENV=development
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  File 6: app/layout.tsx
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat &amp;gt; app/layout.tsx &amp;lt;&amp;lt; 'EOF'
import type { Metadata } from 'next'
import './globals.css'

export const metadata: Metadata = {
  title: 'Next.js App',
  description: 'Complete Next.js application with CI/CD',
}

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    &amp;lt;html lang="en"&amp;gt;
      &amp;lt;body&amp;gt;{children}&amp;lt;/body&amp;gt;
    &amp;lt;/html&amp;gt;
  )
}
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  File 7: app/page.tsx
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat &amp;gt; app/page.tsx &amp;lt;&amp;lt; 'EOF'
import Link from 'next/link'

export default function Home() {
  return (
    &amp;lt;main className="min-h-screen flex flex-col items-center justify-center p-24 bg-gradient-to-br from-blue-50 to-indigo-100"&amp;gt;
      &amp;lt;div className="max-w-4xl w-full space-y-8 text-center"&amp;gt;
        &amp;lt;div className="space-y-4"&amp;gt;
          &amp;lt;h1 className="text-6xl font-bold text-gray-900"&amp;gt;
            Welcome to &amp;lt;span className="text-blue-600"&amp;gt;Next.js&amp;lt;/span&amp;gt;
          &amp;lt;/h1&amp;gt;
          &amp;lt;p className="text-xl text-gray-600"&amp;gt;
            A complete Next.js application with CI/CD pipeline
          &amp;lt;/p&amp;gt;
        &amp;lt;/div&amp;gt;

        &amp;lt;div className="grid grid-cols-1 md:grid-cols-3 gap-6 mt-12"&amp;gt;
          &amp;lt;div className="p-6 border border-gray-200 rounded-lg bg-white shadow-sm hover:shadow-md transition-shadow"&amp;gt;
            &amp;lt;h3 className="text-xl font-semibold mb-2"&amp;gt;📦 Features&amp;lt;/h3&amp;gt;
            &amp;lt;p className="text-gray-600"&amp;gt;
              TypeScript, Tailwind CSS, API Routes
            &amp;lt;/p&amp;gt;
          &amp;lt;/div&amp;gt;

          &amp;lt;div className="p-6 border border-gray-200 rounded-lg bg-white shadow-sm hover:shadow-md transition-shadow"&amp;gt;
            &amp;lt;h3 className="text-xl font-semibold mb-2"&amp;gt;🚀 Deploy&amp;lt;/h3&amp;gt;
            &amp;lt;p className="text-gray-600"&amp;gt;
              Automated deployment to Vercel
            &amp;lt;/p&amp;gt;
          &amp;lt;/div&amp;gt;

          &amp;lt;div className="p-6 border border-gray-200 rounded-lg bg-white shadow-sm hover:shadow-md transition-shadow"&amp;gt;
            &amp;lt;h3 className="text-xl font-semibold mb-2"&amp;gt;🔧 CI/CD&amp;lt;/h3&amp;gt;
            &amp;lt;p className="text-gray-600"&amp;gt;
              GitHub Actions workflow included
            &amp;lt;/p&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;

        &amp;lt;div className="mt-12 space-x-4"&amp;gt;
          &amp;lt;Link
            href="/about"
            className="inline-block px-6 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"
          &amp;gt;
            About Page
          &amp;lt;/Link&amp;gt;
          &amp;lt;Link
            href="/api/hello"
            className="inline-block px-6 py-3 bg-gray-800 text-white rounded-lg hover:bg-gray-900 transition-colors"
          &amp;gt;
            Test API
          &amp;lt;/Link&amp;gt;
        &amp;lt;/div&amp;gt;

        &amp;lt;div className="mt-8 text-sm text-gray-500"&amp;gt;
          &amp;lt;p&amp;gt;Running on port 80 • Managed by PM2&amp;lt;/p&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/main&amp;gt;
  )
}
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  File 8: app/about/page.tsx
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir -p app/about
cat &amp;gt; app/about/page.tsx &amp;lt;&amp;lt; 'EOF'
import Link from 'next/link'

export default function About() {
  return (
    &amp;lt;main className="min-h-screen flex flex-col items-center justify-center p-24 bg-gradient-to-br from-purple-50 to-pink-100"&amp;gt;
      &amp;lt;div className="max-w-2xl w-full space-y-8"&amp;gt;
        &amp;lt;h1 className="text-5xl font-bold text-gray-900 text-center"&amp;gt;
          About This App
        &amp;lt;/h1&amp;gt;

        &amp;lt;div className="bg-white p-8 rounded-lg shadow-md space-y-4"&amp;gt;
          &amp;lt;h2 className="text-2xl font-semibold text-gray-800"&amp;gt;Features&amp;lt;/h2&amp;gt;
          &amp;lt;ul className="list-disc list-inside space-y-2 text-gray-600"&amp;gt;
            &amp;lt;li&amp;gt;Next.js 14 with App Router&amp;lt;/li&amp;gt;
            &amp;lt;li&amp;gt;TypeScript for type safety&amp;lt;/li&amp;gt;
            &amp;lt;li&amp;gt;Tailwind CSS for styling&amp;lt;/li&amp;gt;
            &amp;lt;li&amp;gt;API Routes for backend logic&amp;lt;/li&amp;gt;
            &amp;lt;li&amp;gt;PM2 for process management&amp;lt;/li&amp;gt;
            &amp;lt;li&amp;gt;GitHub Actions for CI/CD&amp;lt;/li&amp;gt;
            &amp;lt;li&amp;gt;Vercel deployment ready&amp;lt;/li&amp;gt;
          &amp;lt;/ul&amp;gt;
        &amp;lt;/div&amp;gt;

        &amp;lt;div className="text-center"&amp;gt;
          &amp;lt;Link
            href="/"
            className="inline-block px-6 py-3 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition-colors"
          &amp;gt;
            ← Back to Home
          &amp;lt;/Link&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/main&amp;gt;
  )
}
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  File 9: app/api/hello/route.ts
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat &amp;gt; app/api/hello/route.ts &amp;lt;&amp;lt; 'EOF'
import { NextResponse } from 'next/server'

export async function GET() {
  return NextResponse.json({
    message: 'Hello from Next.js API!',
    timestamp: new Date().toISOString(),
    status: 'success',
    environment: process.env.NODE_ENV,
  })
}

export async function POST(request: Request) {
  const body = await request.json()

  return NextResponse.json({
    message: 'Data received successfully',
    receivedData: body,
    timestamp: new Date().toISOString(),
  })
}
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  File 10: app/globals.css
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat &amp;gt; app/globals.css &amp;lt;&amp;lt; 'EOF'
@tailwind base;
@tailwind components;
@tailwind utilities;

:root {
  --foreground-rgb: 0, 0, 0;
  --background-start-rgb: 214, 219, 220;
  --background-end-rgb: 255, 255, 255;
}

body {
  color: rgb(var(--foreground-rgb));
  background: linear-gradient(
      to bottom,
      transparent,
      rgb(var(--background-end-rgb))
    )
    rgb(var(--background-start-rgb));
}
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  File 11: tailwind.config.ts
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat &amp;gt; tailwind.config.ts &amp;lt;&amp;lt; 'EOF'
import type { Config } from 'tailwindcss'

const config: Config = {
  content: [
    './pages/**/*.{js,ts,jsx,tsx,mdx}',
    './components/**/*.{js,ts,jsx,tsx,mdx}',
    './app/**/*.{js,ts,jsx,tsx,mdx}',
  ],
  theme: {
    extend: {
      backgroundImage: {
        'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))',
        'gradient-conic':
          'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))',
      },
    },
  },
  plugins: [],
}
export default config
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  File 12: postcss.config.js
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat &amp;gt; postcss.config.js &amp;lt;&amp;lt; 'EOF'
module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
}
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  File 13: jest.config.js
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat &amp;gt; jest.config.js &amp;lt;&amp;lt; 'EOF'
const nextJest = require('next/jest')

const createJestConfig = nextJest({
  dir: './',
})

const customJestConfig = {
  setupFilesAfterEnv: ['&amp;lt;rootDir&amp;gt;/jest.setup.js'],
  testEnvironment: 'jest-environment-jsdom',
  moduleNameMapper: {
    '^@/(.*)$': '&amp;lt;rootDir&amp;gt;/$1',
  },
  testMatch: [
    '**/__tests__/**/*.[jt]s?(x)',
    '**/?(*.)+(spec|test).[jt]s?(x)',
  ],
}

module.exports = createJestConfig(customJestConfig)
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  File 14: jest.setup.js
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat &amp;gt; jest.setup.js &amp;lt;&amp;lt; 'EOF'
import '@testing-library/jest-dom'
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  File 15: &lt;strong&gt;tests&lt;/strong&gt;/page.test.tsx
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir -p __tests__
cat &amp;gt; __tests__/page.test.tsx &amp;lt;&amp;lt; 'EOF'
import { render, screen } from '@testing-library/react'
import Home from '@/app/page'

describe('Home Page', () =&amp;gt; {
  it('renders the main heading', () =&amp;gt; {
    render(&amp;lt;Home /&amp;gt;)
    const heading = screen.getByRole('heading', { level: 1 })
    expect(heading).toBeInTheDocument()
  })

  it('contains welcome text', () =&amp;gt; {
    render(&amp;lt;Home /&amp;gt;)
    expect(screen.getByText(/Welcome to/i)).toBeInTheDocument()
  })
})
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  File 16: ecosystem.config.js (PM2 Configuration)
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat &amp;gt; ecosystem.config.js &amp;lt;&amp;lt; 'EOF'
module.exports = {
  apps: [
    {
      name: 'nextjs-app',
      script: 'npm',
      args: 'start',
      cwd: './',
      instances: 1,
      autorestart: true,
      watch: false,
      max_memory_restart: '1G',
      env: {
        NODE_ENV: 'production',
        PORT: 80,
      },
      error_file: './logs/err.log',
      out_file: './logs/out.log',
      log_file: './logs/combined.log',
      time: true,
    },
  ],
}
EOF

# Create logs directory
mkdir -p logs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  File 17: README.md
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat &amp;gt; README.md &amp;lt;&amp;lt; 'EOF'
# Next.js Application

Complete Next.js application with CI/CD pipeline.

## Features

- ✅ Next.js 14 with App Router
- ✅ TypeScript
- ✅ Tailwind CSS
- ✅ API Routes
- ✅ Jest Testing
- ✅ PM2 Process Management
- ✅ GitHub Actions CI/CD
- ✅ Vercel Deployment

## Development

npm install
npm run dev


## Production

npm run build
npm start


## Testing

npm test


## Deployment

Automatically deploys to Vercel on push to main branch.
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  STEP 3: Install Dependencies
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Install all dependencies
npm install

# This will take a few minutes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  STEP 4: Build the Application
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Build for production
npm run build

# Expected output:
# ✓ Compiled successfully
# ✓ Linting and checking validity of types
# ✓ Collecting page data
# ✓ Generating static pages
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  STEP 5: Run on Port 80 (Requires sudo)
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Using PM2
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Build first
npm run build

# Give Node.js permission to bind to port 80
sudo setcap 'cap_net_bind_service=+ep' $(which node)

# Start with PM2
pm2 start ecosystem.config.js

# Check status
pm2 status

# View logs
pm2 logs nextjs-app

# Save PM2 process list
pm2 save

# Setup PM2 to start on system boot
pm2 startup
# Follow the command it outputs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  STEP 6: Test the Application
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Test locally
curl http://localhost:80

# Or open in browser
# http://localhost:80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  STEP 7: Push to GitHub
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Initialize git
git init

# Add all files
git add .

# Commit
git commit -m "Initial commit: Complete Next.js app with CI/CD"

# Add remote (replace with your repo)
git remote add origin git@github.com:YOUR_USERNAME/nextjs-app.git

# Push
git push -u origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  STEP 8: Create GitHub Actions Workflow
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create workflow file
cat &amp;gt; .github/workflows/deploy.yml &amp;lt;&amp;lt; 'EOF'
name: CI/CD Pipeline

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

env:
  NODE_VERSION: '20.x'

jobs:
  test:
    name: Test
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Run linter
        run: npm run lint

      - name: Run tests
        run: npm test

  build:
    name: Build
    runs-on: ubuntu-latest
    needs: test

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Build application
        run: npm run build

      - name: Upload build artifacts
        uses: actions/upload-artifact@v4
        with:
          name: nextjs-build
          path: .next
          retention-days: 7

  deploy:
    name: Deploy to Vercel
    runs-on: ubuntu-latest
    needs: [test, build]
    if: github.ref == 'refs/heads/main' &amp;amp;&amp;amp; github.event_name == 'push'

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Deploy to Vercel
        uses: amondnet/vercel-action@v25
        with:
          vercel-token: ${{ secrets.VERCEL_TOKEN }}
          vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
          vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
          vercel-args: '--prod'
EOF

# Commit and push
git add .github/workflows/deploy.yml
git commit -m "Add GitHub Actions CI/CD workflow"
git push origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  STEP 9: Setup Vercel
&lt;/h3&gt;
&lt;h4&gt;
  
  
  9.1: Install Vercel CLI
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g vercel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  9.2: Login to Vercel
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vercel login

1. Select "Continue with GitHub"
2. Vercel will open a browser window
3. Browser URL: https://vercel.com/auth/github
4. Click "Authorize Vercel"
5. You'll see: "Successfully logged in!"
6. Return to terminal
7. Terminal shows: ✅ Success! GitHub authentication complete
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  9.3: Link Project to Vercel
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vercel link
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;## Follow These Prompts Exactly:


### Prompt 1:

? Set up "~/nextjs-app"? (Y/n)


**Answer:** Type `y` or just press **Enter** (default is Yes)

### Prompt 2

? Which scope should contain your project?
  ❯ yourname (Personal Account)
    your-team (Team Account)


**Answer:** Use arrow keys to select your account, then press **Enter**


### Prompt 3

? Link to existing project? (y/N)


**Answer:** Type `n` or just press **Enter** (we're creating new project)



### Prompt 4

? What's your project's name? (nextjs-app)


**Answer:** Press **Enter** (keep default name) or type a custom name



### Prompt 5

? In which directory is your code located? (./)


**Answer:** Press **Enter** (keep default `./`)



## Expected Success Output

✅ Linked to yourname/nextjs-app (created .vercel and added it to .gitignore)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  9.4: Get Vercel Credentials
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Get Vercel Token
# Go to: https://vercel.com/account/tokens
# Click "Create Token"
# Name: GitHub Actions
# Scope: Full Account
# Copy the token

# Get Project ID and Org ID
cat .vercel/project.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Output will look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "projectId": "prj_abc123xyz",
  "orgId": "team_xyz789abc"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  STEP 10: Add GitHub Secrets
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Go to: &lt;a href="https://github.com/YOUR_USERNAME/nextjs-app" rel="noopener noreferrer"&gt;https://github.com/YOUR_USERNAME/nextjs-app&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click: Settings → Secrets and variables → Actions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click: "New repository secret"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add three secrets:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;| Secret Name        | Value Description            | Where to Get It                              |
|--------------------|-----------------------------|----------------------------------------------|
| VERCEL_TOKEN       | Your Vercel personal token  | https://vercel.com/account/tokens            |
| VERCEL_ORG_ID      | Vercel Organization ID      | From `.vercel/project.json` → `cat .vercel/project.json` |
| VERCEL_PROJECT_ID  | Vercel Project ID           | From `.vercel/project.json` → `cat .vercel/project.json` |

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  STEP 11: Test Full Pipeline
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Make a change
echo "# Test deployment" &amp;gt;&amp;gt; README.md

# Commit and push
git add README.md
git commit -m "Test CI/CD pipeline"
git push origin main

# Watch workflow
# Go to: GitHub → Actions tab
# Watch the pipeline run:
#   ✅ Test
#   ✅ Build  
#   ✅ Deploy to Vercel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  🎨 How to Make Changes and See Automatic Deployment
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Understanding the Workflow
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Local Machine (Ubuntu)
    ↓ (make changes)
    ↓ (git commit)
    ↓ (git push)
    ↓
GitHub Repository
    ↓ (triggers)
    ↓
GitHub Actions (if configured)
    ↓ (or directly)
    ↓
Vercel Deployment
    ↓ (automatic)
    ↓
Live Website Updated ✅
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  🚀 Quick Test: Make Your First Change
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Change Homepage Text (Easiest)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Navigate to project
cd ~/nextjs-app

# Edit the home page
nano app/page.tsx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  📤 Push Changes to GitHub
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Check what changed
git status

# Stage the changes
git add app/page.tsx

# Commit with a message
git commit -m "Update homepage: Changed title and description"

# Push to GitHub
git push origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔍 Watch the Automatic Deployment
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Method 1: Watch on Vercel Dashboard
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Open browser
2. Go to: https://vercel.com/dashboard
3. Click on your project: sowmiya-next-js-app
4. You'll see: "Building..." 
5. Wait 30-60 seconds
6. Status changes to: "Ready" ✅
7. Click "Visit" to see your changes live!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0m87j04gyrrmfz1he6aq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0m87j04gyrrmfz1he6aq.png" alt="1" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  🌐 View Your Changes
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fczh0l814gmu1it50z1eg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fczh0l814gmu1it50z1eg.png" alt="2" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;




</description>
      <category>vercel</category>
      <category>githubactions</category>
      <category>cicd</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>🚀 Build, Push, and Deploy a Python App image to Cloud Run Using Google Cloud Build Triggers</title>
      <dc:creator>Latchu@DevOps</dc:creator>
      <pubDate>Fri, 09 Jan 2026 12:07:35 +0000</pubDate>
      <link>https://dev.to/latchudevops/build-push-and-deploy-a-python-app-image-to-cloud-run-using-google-cloud-build-triggers-2hk6</link>
      <guid>https://dev.to/latchudevops/build-push-and-deploy-a-python-app-image-to-cloud-run-using-google-cloud-build-triggers-2hk6</guid>
      <description>&lt;p&gt;In this guide, we will build a Python Flask application, containerize it using Docker, push the image to Google Artifact Registry, and deploy it automatically to Cloud Run using Google Cloud Build Triggers.&lt;/p&gt;




&lt;h2&gt;
  
  
  1️⃣ Create a Private Repository in GitHub
&lt;/h2&gt;

&lt;p&gt;Create a private GitHub repository and add the following files.&lt;/p&gt;

&lt;p&gt;📄 app.py&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from flask import Flask
import os

app = Flask(__name__)

@app.route("/")
def wish():
    message = "Happy birthday {name}"
    return message.format(name=os.getenv("NAME", "Latchu"))

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=8080)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;📄 Dockerfile&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM python:3.8.0-slim
WORKDIR /app
ADD . /app
RUN pip install --trusted-host pypi.python.org Flask
ENV NAME Mark
CMD ["python", "app.py"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  2️⃣ Create an Artifact Registry Repository
&lt;/h2&gt;

&lt;p&gt;Navigate to:&lt;/p&gt;

&lt;p&gt;Artifact Registry → Repositories → Create Repository&lt;/p&gt;

&lt;p&gt;Configure the repository as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name: pyapprepo-artifact&lt;/li&gt;
&lt;li&gt;Format: Docker&lt;/li&gt;
&lt;li&gt;Mode: Standard&lt;/li&gt;
&lt;li&gt;Location type: Region&lt;/li&gt;
&lt;li&gt;Region: asia-south2 (Delhi)&lt;/li&gt;
&lt;li&gt;Cleanup policies: Dry run&lt;/li&gt;
&lt;li&gt;Vulnerability scanning: Enabled&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Click Create to create the repository.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqbi72fjpca2hyc5sjyaw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqbi72fjpca2hyc5sjyaw.png" alt="1" width="800" height="183"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  3️⃣ Connect GitHub Repository to Cloud Build
&lt;/h2&gt;

&lt;p&gt;Navigate to:&lt;/p&gt;

&lt;p&gt;Cloud Build → Triggers → Connect repository&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr3a9ashzc8qy5ss0ajvl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr3a9ashzc8qy5ss0ajvl.png" alt="2" width="800" height="584"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select Source Code Management Provider&lt;/li&gt;
&lt;li&gt;Choose Region: asia-south2 (Delhi)&lt;/li&gt;
&lt;li&gt;Select GitHub (Cloud Build GitHub App) → Continue&lt;/li&gt;
&lt;li&gt;Authenticate with GitHub&lt;/li&gt;
&lt;li&gt;Select your account and repository&lt;/li&gt;
&lt;li&gt;Click Connect → Done&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your repository should now be connected successfully.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo2xg27ln304duh4v5xti.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo2xg27ln304duh4v5xti.png" alt="3" width="800" height="584"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  4️⃣ Create cloudbuild.yaml
&lt;/h2&gt;

&lt;p&gt;Add the following cloudbuild.yaml file to your repository.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;steps:
- name: 'gcr.io/cloud-builders/docker'
  args: ['build','-t','asia-south2-docker.pkg.dev/latchu/pyapprepo-artifact/pyappimage:latest','.']

- name: 'gcr.io/cloud-builders/docker'
  args: ['push','asia-south2-docker.pkg.dev/latchu/pyapprepo-artifact/pyappimage:latest']

- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
  entrypoint: gcloud
  args:
  - 'run'
  - 'deploy'
  - 'pyflaskapp'
  - '--image'
  - 'asia-south2-docker.pkg.dev/latchu/pyapprepo-artifact/pyappimage:latest'
  - '--region'
  - 'asia-south2'
  - '--allow-unauthenticated'

options:
  defaultLogsBucketBehavior: REGIONAL_USER_OWNED_BUCKET
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  5️⃣ Create a Cloud Build Trigger
&lt;/h2&gt;

&lt;p&gt;Navigate to:&lt;/p&gt;

&lt;p&gt;Cloud Build → Triggers → Create Trigger&lt;/p&gt;

&lt;p&gt;Configure the trigger:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name: mypyapptrigger&lt;/li&gt;
&lt;li&gt;Region: asia-south2 (Delhi)&lt;/li&gt;
&lt;li&gt;Event: Push to a branch&lt;/li&gt;
&lt;li&gt;Source: Repository service → Cloud Build repositories&lt;/li&gt;
&lt;li&gt;Repository generation: 1st gen&lt;/li&gt;
&lt;li&gt;Repository: Select your repo&lt;/li&gt;
&lt;li&gt;Branch: .* (any branch)&lt;/li&gt;
&lt;li&gt;Configuration: Autodetected (cloudbuild.yaml will be detected)&lt;/li&gt;
&lt;li&gt;Location: Repository&lt;/li&gt;
&lt;li&gt;Service account: Choose your service account&lt;/li&gt;
&lt;li&gt;Leave other options as default&lt;/li&gt;
&lt;li&gt;Click Create&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  6️⃣ Commit Code and Trigger the Pipeline
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Make a small change in the code&lt;/li&gt;
&lt;li&gt;Commit and push to GitHub&lt;/li&gt;
&lt;li&gt;Cloud Build trigger will start automatically&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  7️⃣ Verify Deployment
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1yca7al242cb3z3op1k1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1yca7al242cb3z3op1k1.png" alt="4" width="800" height="243"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click on the running build in Cloud Build&lt;/li&gt;
&lt;li&gt;View detailed logs for build, push, and deployment&lt;/li&gt;
&lt;li&gt;Click the Cloud Run service URL&lt;/li&gt;
&lt;li&gt;You should see the deployed Flask application running 🎉&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzbnun7l880swzdb221lg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzbnun7l880swzdb221lg.png" alt="5" width="800" height="537"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd25asz70bdhozdbtdp3w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd25asz70bdhozdbtdp3w.png" alt="6" width="800" height="183"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Summary
&lt;/h2&gt;

&lt;p&gt;This setup enables a complete CI/CD pipeline using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub (source code)&lt;/li&gt;
&lt;li&gt;Cloud Build Triggers (automation)&lt;/li&gt;
&lt;li&gt;Artifact Registry (Docker images)&lt;/li&gt;
&lt;li&gt;Cloud Run (serverless deployment)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every push to the repository automatically builds, pushes, and deploys your application.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>gcp</category>
      <category>cicd</category>
      <category>containers</category>
    </item>
    <item>
      <title>Docker Kanvas Challenges Helm and Kustomize for Kubernetes Dominance</title>
      <dc:creator>Latchu@DevOps</dc:creator>
      <pubDate>Fri, 09 Jan 2026 06:25:56 +0000</pubDate>
      <link>https://dev.to/latchudevops/docker-kanvas-challenges-helm-and-kustomize-for-kubernetes-dominance-2df0</link>
      <guid>https://dev.to/latchudevops/docker-kanvas-challenges-helm-and-kustomize-for-kubernetes-dominance-2df0</guid>
      <description>&lt;h2&gt;
  
  
  🚀 What Is Docker Kanvas and Why Does It Matter for Kubernetes?
&lt;/h2&gt;

&lt;p&gt;Docker recently introduced Docker Kanvas, a new platform aimed at simplifying one of the hardest problems in cloud-native development:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Moving from local development to production Kubernetes — without drowning in YAML.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This move signals a strategic shift for Docker: from being just a container runtime to becoming a deployment and platform orchestration layer.&lt;/p&gt;

&lt;p&gt;Let’s break it down.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧩 The Problem Docker Kanvas Is Solving
&lt;/h2&gt;

&lt;p&gt;Most developers are comfortable with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But production looks very different.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To deploy the same app on Kubernetes, teams usually need to:&lt;/li&gt;
&lt;li&gt;Rewrite the application using Kubernetes manifests&lt;/li&gt;
&lt;li&gt;Learn Helm or Kustomize&lt;/li&gt;
&lt;li&gt;Create Terraform or Pulumi scripts&lt;/li&gt;
&lt;li&gt;Manage clusters, networking, storage, and scaling&lt;/li&gt;
&lt;li&gt;Maintain two sources of truth:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Docker Compose (local)
Kubernetes YAML (production)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This transition is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Slow&lt;/li&gt;
&lt;li&gt;Error-prone&lt;/li&gt;
&lt;li&gt;DevOps-heavy&lt;/li&gt;
&lt;li&gt;A major cognitive burden for developers&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧠 What Is Docker Kanvas?
&lt;/h2&gt;

&lt;p&gt;Docker Kanvas is a Docker Desktop extension that allows developers to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use Docker Compose as the source of truth&lt;/li&gt;
&lt;li&gt;Automatically generate:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Kubernetes deployment artifacts
Infrastructure-as-Code (Terraform / Pulumi)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Deploy applications to:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Managed Kubernetes (GKE, EKS, AKS)
Serverless platforms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Visualize application architecture and service dependencies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All without manually writing Kubernetes YAML.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔁 How Docker Kanvas Works (Conceptually)
&lt;/h2&gt;

&lt;p&gt;Traditional flow&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Docker Compose
     ↓
Manual Kubernetes YAML
     ↓
Helm / Kustomize
     ↓
Terraform
     ↓
Kubernetes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With Docker Kanvas&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Docker Compose
     ↓
Docker Kanvas
     ↓
Cloud-ready Kubernetes deployment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compose remains the single source of truth.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧪 Simple Example
&lt;/h2&gt;

&lt;p&gt;Docker Compose (what developers already write)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;services:
  web:
    image: nginx
    ports:
      - "8080:80"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With Kanvas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This Compose file is interpreted&lt;/li&gt;
&lt;li&gt;Kubernetes Deployments, Services, and networking are generated&lt;/li&gt;
&lt;li&gt;Infrastructure is provisioned automatically&lt;/li&gt;
&lt;li&gt;The app is deployed to the cloud&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Developers never touch Kubernetes YAML directly.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧭 Why Docker Kanvas Challenges Helm and Kustomize
&lt;/h2&gt;

&lt;p&gt;Helm and Kustomize are powerful tools — but they assume:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You already understand Kubernetes&lt;/li&gt;
&lt;li&gt;You’re comfortable managing YAML&lt;/li&gt;
&lt;li&gt;You accept Kubernetes as the primary interface&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Docker Kanvas challenges that assumption.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key differences&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;| Aspect            | Helm / Kustomize        | Docker Kanvas          |
| ----------------- | ----------------------- | ---------------------- |
| Entry point       | Kubernetes YAML         | Docker Compose         |
| Target user       | DevOps / Platform teams | Application developers |
| Learning curve    | High                    | Low                    |
| Source of truth   | YAML manifests          | Compose file           |
| Visualization     | No                      | Yes                    |
| Abstraction level | Low                     | High                   |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Kanvas doesn’t replace Helm in complex enterprises — it bypasses Helm for many teams entirely.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🧠 Why Docker Kanvas Is Needed
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1️⃣ Developers don’t want to learn Kubernetes internals&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most developers want to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build features&lt;/li&gt;
&lt;li&gt;Ship faster&lt;/li&gt;
&lt;li&gt;Avoid infrastructure complexity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Kanvas lets them stay productive without becoming Kubernetes experts.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;2️⃣ Platform engineering is rising&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Modern teams are building:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Internal developer platforms&lt;/li&gt;
&lt;li&gt;Golden paths&lt;/li&gt;
&lt;li&gt;Opinionated workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Docker Kanvas fits naturally into this model by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Standardizing deployments&lt;/li&gt;
&lt;li&gt;Reducing decision fatigue&lt;/li&gt;
&lt;li&gt;Enforcing consistency&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;3️⃣ Visual architecture matters&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Kanvas generates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Service dependency graphs&lt;/li&gt;
&lt;li&gt;Application topology views&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This helps with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Debugging&lt;/li&gt;
&lt;li&gt;Security reviews&lt;/li&gt;
&lt;li&gt;Onboarding&lt;/li&gt;
&lt;li&gt;Architecture discussions&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚠️ What Docker Kanvas Is NOT
&lt;/h2&gt;

&lt;p&gt;❌ Not a replacement for Kubernetes&lt;/p&gt;

&lt;p&gt;❌ Not a replacement for Helm in advanced setups&lt;/p&gt;

&lt;p&gt;❌ Not designed for headless servers (Desktop-only today)&lt;/p&gt;

&lt;p&gt;It’s a developer-experience tool, not a low-level infrastructure engine.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔮 What This Means for the Kubernetes Ecosystem
&lt;/h2&gt;

&lt;p&gt;Docker Kanvas represents a shift toward:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Higher-level abstractions&lt;/li&gt;
&lt;li&gt;Fewer infrastructure tools per team&lt;/li&gt;
&lt;li&gt;Kubernetes becoming an invisible runtime&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Kubernetes still runs everything — developers just don’t have to think about it.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🏁 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Docker Kanvas is not trying to win Kubernetes feature wars.&lt;/p&gt;

&lt;p&gt;It’s trying to win developer mindshare.&lt;/p&gt;

&lt;p&gt;By making Docker Compose a valid path to production, Docker is redefining how applications move from laptops to the cloud — and that’s why tools like Helm and Kustomize are being challenged, not replaced.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>kubernetes</category>
      <category>containers</category>
    </item>
    <item>
      <title>🧱Understanding Artifacts and Artifact Repositories in Google Cloud CI/CD</title>
      <dc:creator>Latchu@DevOps</dc:creator>
      <pubDate>Fri, 12 Dec 2025 07:50:29 +0000</pubDate>
      <link>https://dev.to/latchudevops/understanding-artifacts-and-artifact-repositories-in-google-cloud-cicd-2lbh</link>
      <guid>https://dev.to/latchudevops/understanding-artifacts-and-artifact-repositories-in-google-cloud-cicd-2lbh</guid>
      <description>&lt;p&gt;In every modern CI/CD pipeline, there is one element that quietly powers the entire automation process — artifacts.&lt;br&gt;
They play a crucial role in how software moves from code → build → deployment.&lt;br&gt;
If you’re new to DevOps or Google Cloud, this guide will help you clearly understand:&lt;/p&gt;

&lt;p&gt;✔ What artifacts are&lt;br&gt;
✔ Why they matter in CI/CD&lt;br&gt;
✔ How they are stored and managed&lt;br&gt;
✔ Artifact Repository vs Container Registry&lt;br&gt;
✔ Why Google recommends Artifact Registry&lt;/p&gt;

&lt;p&gt;Let’s break it down in simple terms.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔍 What Are Artifacts?
&lt;/h2&gt;

&lt;p&gt;When your CI pipeline builds code, it produces output files.&lt;br&gt;
These files — called artifacts — are the deliverables used later during deployment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🧩 Artifacts include:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Jar files&lt;/li&gt;
&lt;li&gt;Packages&lt;/li&gt;
&lt;li&gt;Binaries&lt;/li&gt;
&lt;li&gt;Docker images&lt;/li&gt;
&lt;li&gt;Configuration files&lt;/li&gt;
&lt;li&gt;Documents or reports&lt;/li&gt;
&lt;li&gt;Any compiled or generated output&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of artifacts as the results of your build stage (CI), which are then consumed by the deployment stage (CD).&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚙️ Types of Artifacts
&lt;/h2&gt;

&lt;p&gt;Artifacts generally fall into two categories:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1️⃣ Container Artifacts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;These are container images — typically Docker images — used to deploy applications in Kubernetes, Cloud Run, Cloud Functions, etc.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2️⃣ Non-Container Artifacts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;These include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java .jar files&lt;/li&gt;
&lt;li&gt;Node/npm packages&lt;/li&gt;
&lt;li&gt;Python wheels&lt;/li&gt;
&lt;li&gt;Terraform modules&lt;/li&gt;
&lt;li&gt;Helm charts&lt;/li&gt;
&lt;li&gt;Config files&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both types need reliable storage and versioning.&lt;/p&gt;




&lt;h2&gt;
  
  
  📦 Why Do We Need Artifact Management?
&lt;/h2&gt;

&lt;p&gt;Once the CI pipeline generates artifacts, they must be:&lt;/p&gt;

&lt;p&gt;✔ Stored in a central place&lt;br&gt;
✔ Versioned properly&lt;br&gt;
✔ Made accessible to CD pipelines&lt;br&gt;
✔ Secure and scanned for vulnerabilities&lt;br&gt;
✔ Managed consistently&lt;/p&gt;

&lt;p&gt;An Artifact Management System solves these challenges by acting as the single source of truth for all build outputs.&lt;/p&gt;




&lt;h2&gt;
  
  
  🏛 Artifact Repositories Explained
&lt;/h2&gt;

&lt;p&gt;An Artifact Repository is a centralized storage system specifically designed for storing and managing artifacts in CI/CD workflows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key benefits:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Acts as the single source of truth&lt;/li&gt;
&lt;li&gt;Supports version management&lt;/li&gt;
&lt;li&gt;Scans artifacts for vulnerabilities&lt;/li&gt;
&lt;li&gt;Helps apply approval workflows&lt;/li&gt;
&lt;li&gt;Ensures consistency across build and deploy stages&lt;/li&gt;
&lt;li&gt;Enhances DevOps efficiency and organizational performance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Artifact repositories are essential for both monolithic and microservices architectures.&lt;/p&gt;




&lt;h2&gt;
  
  
  🗂 Options for Storing Artifacts in Google Cloud
&lt;/h2&gt;

&lt;p&gt;Google Cloud offers two main services for storing artifacts:&lt;/p&gt;




&lt;h2&gt;
  
  
  🏗️ 1. Artifact Registry (Recommended)
&lt;/h2&gt;

&lt;p&gt;Artifact Registry is the next generation of Google’s artifact storage solution.&lt;br&gt;
It replaces Container Registry and supports more artifact types.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;⭐ Key Features:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stores container and non-container artifacts&lt;/li&gt;
&lt;li&gt;Native support for multiple formats (Docker, npm, Maven, Python, etc.)&lt;/li&gt;
&lt;li&gt;Fully integrated with Google Cloud Build, GKE, Cloud Run&lt;/li&gt;
&lt;li&gt;Allows creation of regional or multi-regional repositories&lt;/li&gt;
&lt;li&gt;Offers vulnerability scanning&lt;/li&gt;
&lt;li&gt;Provides fine-grained IAM control&lt;/li&gt;
&lt;li&gt;Charges based on usage (storage + network egress)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Artifact Registry is now the default and recommended option.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚢 2. Container Registry (Legacy)
&lt;/h2&gt;

&lt;p&gt;Container Registry was Google's original solution for storing Docker images.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;📌 Features:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stores Docker images in private repositories&lt;/li&gt;
&lt;li&gt;Supports Docker Image Manifest V2 &amp;amp; OCI formats&lt;/li&gt;
&lt;li&gt;Vulnerability scanning for early detection&lt;/li&gt;
&lt;li&gt;Compatible with standard Docker CLI (docker push, docker pull)&lt;/li&gt;
&lt;li&gt;Charges for underlying Cloud Storage usage&lt;/li&gt;
&lt;li&gt;Still works — but Google Cloud is migrating users to Artifact Registry&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're starting new, always choose Artifact Registry.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Artifacts form the backbone of any CI/CD pipeline.&lt;br&gt;
They ensure that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Code is transformed into deployable assets&lt;/li&gt;
&lt;li&gt;Build outputs remain consistent and traceable&lt;/li&gt;
&lt;li&gt;Deployment workflows are reliable and secure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Google Cloud’s Artifact Registry provides a modern, unified, secure, and scalable way to manage container and non-container artifacts — making it the ideal choice for DevOps teams.&lt;/p&gt;




&lt;p&gt;🌟 Thanks for reading! If this post added value, a like ❤️, follow, or share would encourage me to keep creating more content.&lt;/p&gt;




&lt;p&gt;— Latchu | Senior DevOps &amp;amp; Cloud Engineer&lt;/p&gt;

&lt;p&gt;☁️ AWS | GCP | ☸️ Kubernetes | 🔐 Security | ⚡ Automation&lt;br&gt;
📌 Sharing hands-on guides, best practices &amp;amp; real-world cloud solutions&lt;/p&gt;

</description>
      <category>devops</category>
      <category>cicd</category>
      <category>gcp</category>
      <category>cloud</category>
    </item>
    <item>
      <title>🚀How to Create Your First GitHub Trigger &amp; Connections in Google Cloud Build</title>
      <dc:creator>Latchu@DevOps</dc:creator>
      <pubDate>Fri, 12 Dec 2025 07:10:32 +0000</pubDate>
      <link>https://dev.to/latchudevops/how-to-create-your-first-github-trigger-connections-in-google-cloud-build-2igd</link>
      <guid>https://dev.to/latchudevops/how-to-create-your-first-github-trigger-connections-in-google-cloud-build-2igd</guid>
      <description>&lt;p&gt;Google Cloud Build makes it incredibly simple to automate your CI/CD pipeline. One of the most common setups is connecting GitHub → Cloud Build so that every commit automatically triggers a build.&lt;br&gt;
If you're new to Cloud Build, follow this step-by-step guide to create your first trigger successfully.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔗 Step 1: Connect GitHub Repository to Cloud Build
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Open Google Cloud Console → Search for Cloud Build.&lt;/li&gt;
&lt;li&gt;Go to the Triggers section.&lt;/li&gt;
&lt;li&gt;Click “Connect Repository”.&lt;/li&gt;
&lt;li&gt;Select your source provider: → GitHub (Cloud Build GitHub App)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffl2jbu8xtthxluk0llg9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffl2jbu8xtthxluk0llg9.png" alt="1" width="800" height="514"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click Continue to Authenticate.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy7knu5mq60yvoiod6l4c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy7knu5mq60yvoiod6l4c.png" alt="2" width="800" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You’ll be redirected to GitHub to install the Cloud Build GitHub App.&lt;/li&gt;
&lt;li&gt;After installation, return to Cloud Build.&lt;/li&gt;
&lt;li&gt;Select the GitHub account and repository you want to connect.&lt;/li&gt;
&lt;li&gt;Click Connect → Done.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your GitHub repo is now officially linked with Google Cloud Build.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚙️ Step 2: Create Your First Cloud Build Trigger
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;In Cloud Build → Go to Triggers → Create Trigger.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fill in the fields:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Basic Settings&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name: first-trigger&lt;/li&gt;
&lt;li&gt;Region: global&lt;/li&gt;
&lt;li&gt;Tags: dev_team&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Event Type&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Event: Push to a branch&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2qxfd2rkw5ufuisjffsv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2qxfd2rkw5ufuisjffsv.png" alt="3" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Source Configuration&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Source: Cloud Build Repositories&lt;/li&gt;
&lt;li&gt;Repository type: 1st generation&lt;/li&gt;
&lt;li&gt;Repository: Select your GitHub repo&lt;/li&gt;
&lt;li&gt;Branch: ^main$
(This ensures the trigger runs only for main branch pushes)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F44oqct4309g8oc461k1b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F44oqct4309g8oc461k1b.png" alt="4" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Build Configuration&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Configuration: Autodetected&lt;/li&gt;
&lt;li&gt;Location: Repository
(Cloud Build will search for your cloudbuild.yaml inside the repo)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Service Account&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select your Cloud Build service account&lt;/li&gt;
&lt;li&gt;Click Create Trigger&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your first CI pipeline is now ready!&lt;/p&gt;




&lt;h2&gt;
  
  
  📝 Step 3: Commit Changes in GitHub
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Open your GitHub repository.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make a small change (add a print statement, update a README, etc.).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Commit and push the changes.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This action will automatically trigger Cloud Build.&lt;/p&gt;




&lt;h2&gt;
  
  
  📊 Step 4: View Build History &amp;amp; Logs
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1x667o2149l2dz0yix3k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1x667o2149l2dz0yix3k.png" alt="5" width="800" height="265"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Go to Cloud Build → History.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You’ll see your recent builds.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click any build to open the Build Summary:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;You can view:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build logs&lt;/li&gt;
&lt;li&gt;Execution details&lt;/li&gt;
&lt;li&gt;Artifact outputs&lt;/li&gt;
&lt;li&gt;Build duration &amp;amp; steps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxp67yythnwfj03x7l53u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxp67yythnwfj03x7l53u.png" alt="6" width="800" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fenik7bgvcz1dcfz1pr7y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fenik7bgvcz1dcfz1pr7y.png" alt="7" width="800" height="474"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  📈 Step 5: Monitor Overall Build Activity
&lt;/h2&gt;

&lt;p&gt;Open the Cloud Build Dashboard to get a high-level view of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Recent build status&lt;/li&gt;
&lt;li&gt;Success/failure rate&lt;/li&gt;
&lt;li&gt;Build durations&lt;/li&gt;
&lt;li&gt;Trigger usage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7kxidff49kmpa15eshhx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7kxidff49kmpa15eshhx.png" alt="8" width="800" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This helps track the health of your CI pipeline easily.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎉 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;You’ve now successfully set up:&lt;/p&gt;

&lt;p&gt;✔ GitHub connected to Cloud Build&lt;br&gt;
✔ A working build trigger&lt;br&gt;
✔ Automated builds on every commit&lt;br&gt;
✔ Build logs and dashboard monitoring&lt;/p&gt;




&lt;p&gt;🌟 Thanks for reading! If this post added value, a like ❤️, follow, or share would encourage me to keep creating more content.&lt;/p&gt;




&lt;p&gt;— Latchu | Senior DevOps &amp;amp; Cloud Engineer&lt;/p&gt;

&lt;p&gt;☁️ AWS | GCP | ☸️ Kubernetes | 🔐 Security | ⚡ Automation&lt;br&gt;
📌 Sharing hands-on guides, best practices &amp;amp; real-world cloud solutions&lt;/p&gt;

</description>
      <category>devops</category>
      <category>cicd</category>
      <category>gcp</category>
      <category>cloud</category>
    </item>
    <item>
      <title>🚀Getting Started With Google Cloud Build</title>
      <dc:creator>Latchu@DevOps</dc:creator>
      <pubDate>Fri, 12 Dec 2025 05:01:30 +0000</pubDate>
      <link>https://dev.to/latchudevops/getting-started-with-google-cloud-build-24o0</link>
      <guid>https://dev.to/latchudevops/getting-started-with-google-cloud-build-24o0</guid>
      <description>&lt;p&gt;Modern applications need fast, reliable, and automated ways to build, test, and deploy code. Google Cloud Build is one such powerful service that helps developers automate their entire CI/CD process — without managing any servers.&lt;/p&gt;

&lt;p&gt;In this article, let’s understand what Cloud Build is, why it’s useful, and how build configuration files work, in the simplest possible way.&lt;/p&gt;




&lt;h2&gt;
  
  
  🌥️ What is Google Cloud Build?
&lt;/h2&gt;

&lt;p&gt;Cloud Build is a serverless CI/CD platform from Google Cloud that automates the process of building, testing, and deploying your applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔥 Key advantages:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;⭐ 1. Serverless&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No need to provision or manage build servers.&lt;br&gt;
Cloud Build handles compute resources automatically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;⭐ 2. Auto-Scaling&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Whether you run 1 build or 100 builds, Cloud Build scales up and down as needed.&lt;br&gt;
You only pay for the build time you use.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;⭐ 3. Single Configuration File&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You define all your build steps (build, test, package, push images, deploy, etc.) inside one YAML or JSON file.&lt;/p&gt;

&lt;p&gt;This file tells Cloud Build exactly what to do.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;⭐ 4. Built-in Vulnerability Scanning&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cloud Build can scan container images for security vulnerabilities as part of the CI/CD workflow.&lt;br&gt;
Security is automated!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;⭐ 5. Supports Multiple Source Code Providers&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cloud Build can fetch your code from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Google Cloud Storage&lt;/li&gt;
&lt;li&gt;Cloud Source Repositories&lt;/li&gt;
&lt;li&gt;GitHub&lt;/li&gt;
&lt;li&gt;Bitbucket&lt;/li&gt;
&lt;li&gt;And more&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can trigger builds automatically when you push code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;⭐ 6. Deploy Anywhere&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cloud Build can deploy your application to multiple environments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;VM instances&lt;/li&gt;
&lt;li&gt;Cloud Run (serverless)&lt;/li&gt;
&lt;li&gt;Google Kubernetes Engine (GKE)&lt;/li&gt;
&lt;li&gt;Firebase&lt;/li&gt;
&lt;li&gt;Or even other clouds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;⭐ 7. Cloud Builders&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cloud Build uses "builders" — pre-built images with common tools (like Docker, Maven, Node, Go, Python, etc.)&lt;br&gt;
They allow you to run commands like docker build, npm install, mvn package, etc.&lt;/p&gt;


&lt;h2&gt;
  
  
  🧩 Build Configuration (cloudbuild.yaml)
&lt;/h2&gt;

&lt;p&gt;The core of Cloud Build is the build configuration file.&lt;/p&gt;

&lt;p&gt;You provide this file along with your source code, and Cloud Build uses it to understand what steps to execute.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;📌 What is it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A YAML/JSON file that defines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The steps of your build&lt;/li&gt;
&lt;li&gt;Which tools or builder images to use&lt;/li&gt;
&lt;li&gt;What commands to run&lt;/li&gt;
&lt;li&gt;What to deploy&lt;/li&gt;
&lt;li&gt;Where to store logs and artifacts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;📌 What does it contain?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;✔️ Instructions for Cloud Build&lt;br&gt;
✔️ Step-by-step tasks&lt;br&gt;
✔️ Runtime environment&lt;br&gt;
✔️ Docker image definitions&lt;br&gt;
✔️ Artifact locations&lt;br&gt;
✔️ Deploy settings&lt;/p&gt;

&lt;p&gt;The file is usually named cloudbuild.yaml.&lt;/p&gt;


&lt;h2&gt;
  
  
  🧱 Example: A Very Simple Cloud Build File
&lt;/h2&gt;

&lt;p&gt;Here’s a basic cloudbuild.yaml that builds a Docker image and pushes it to Google Container Registry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;steps:
  - name: 'gcr.io/cloud-builders/docker'
    args: ['build', '-t', 'gcr.io/$PROJECT_ID/myapp', '.']

  - name: 'gcr.io/cloud-builders/docker'
    args: ['push', 'gcr.io/$PROJECT_ID/myapp']

images:
  - 'gcr.io/$PROJECT_ID/myapp'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;🔍 What this file does:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Uses Docker builder to build an image&lt;/li&gt;
&lt;li&gt;Tags the image&lt;/li&gt;
&lt;li&gt;Pushes it to Google Container Registry&lt;/li&gt;
&lt;li&gt;Marks the image as a final output&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Simple, clean, and fully automated.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 Why Developers Love Cloud Build
&lt;/h2&gt;

&lt;p&gt;✔️ No servers to manage&lt;br&gt;
✔️ Fast and scalable&lt;br&gt;
✔️ Works for both monoliths and microservices&lt;br&gt;
✔️ Supports Docker, Kubernetes, Cloud Run, and more&lt;br&gt;
✔️ Easy integrations with GitHub/GitLab&lt;br&gt;
✔️ Secure by design&lt;/p&gt;

&lt;p&gt;You can go from code → container → deployment in minutes!&lt;/p&gt;




&lt;h2&gt;
  
  
  🏁 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;If you want a low-maintenance, scalable, and secure CI/CD solution, Google Cloud Build is one of the best options available today.&lt;/p&gt;

&lt;p&gt;It works for beginners because it is simple and works for experts because it is powerful.&lt;/p&gt;

&lt;p&gt;All you need is a cloudbuild.yaml file — and Cloud Build takes care of the rest.&lt;/p&gt;




&lt;p&gt;🌟 Thanks for reading! If this post added value, a like ❤️, follow, or share would encourage me to keep creating more content.&lt;/p&gt;




&lt;p&gt;— Latchu | Senior DevOps &amp;amp; Cloud Engineer&lt;/p&gt;

&lt;p&gt;☁️ AWS | GCP | ☸️ Kubernetes | 🔐 Security | ⚡ Automation&lt;br&gt;
📌 Sharing hands-on guides, best practices &amp;amp; real-world cloud solutions&lt;/p&gt;

</description>
      <category>gcp</category>
      <category>devops</category>
      <category>cicd</category>
      <category>cloud</category>
    </item>
    <item>
      <title>🟩How to Route DB Connections to Multiple Database Servers Using HAProxy Port Forwarding</title>
      <dc:creator>Latchu@DevOps</dc:creator>
      <pubDate>Sat, 06 Dec 2025 09:16:57 +0000</pubDate>
      <link>https://dev.to/latchudevops/how-to-route-db-connections-to-multiple-database-servers-using-haproxy-port-forwarding-1332</link>
      <guid>https://dev.to/latchudevops/how-to-route-db-connections-to-multiple-database-servers-using-haproxy-port-forwarding-1332</guid>
      <description>&lt;p&gt;Managing multiple MySQL databases across several servers can be challenging—especially when you want users to connect seamlessly without needing to know which server hosts which database.&lt;/p&gt;

&lt;p&gt;In this guide, I’ll walk you through a clean, production-friendly setup where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have 3 MySQL servers (each hosting one database)&lt;/li&gt;
&lt;li&gt;You have 1 client server&lt;/li&gt;
&lt;li&gt;You install HAProxy on the client server&lt;/li&gt;
&lt;li&gt;Users connect to different ports, and HAProxy forwards them to the correct MySQL server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach is simple, scalable, and ideal for separating workloads or multi-tenant MySQL environments.&lt;/p&gt;




&lt;h2&gt;
  
  
  🟦 What is HAProxy?
&lt;/h2&gt;

&lt;p&gt;HAProxy (High Availability Proxy) is a fast, open-source TCP and HTTP load balancer widely used in production environments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key features:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Load Balancing&lt;/li&gt;
&lt;li&gt;Reverse Proxying&lt;/li&gt;
&lt;li&gt;Health Checks&lt;/li&gt;
&lt;li&gt;High Availability&lt;/li&gt;
&lt;li&gt;SSL Termination&lt;/li&gt;
&lt;li&gt;TCP/UDP routing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For MySQL, HAProxy acts as a TCP proxy, routing database connections based on rules you define.&lt;/p&gt;




&lt;h2&gt;
  
  
  🟦 What is HAProxy Port Forwarding?
&lt;/h2&gt;

&lt;p&gt;HAProxy port forwarding means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You expose different ports on the HAProxy server&lt;/li&gt;
&lt;li&gt;Each port forwards traffic to a specific backend server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In our case:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th&gt;Goes To&lt;/th&gt;
&lt;th&gt;Database&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;3301&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;MySQL Server 1&lt;/td&gt;
&lt;td&gt;db1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;3302&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;MySQL Server 2&lt;/td&gt;
&lt;td&gt;db2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;3303&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;MySQL Server 3&lt;/td&gt;
&lt;td&gt;db3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;So, when a user connects to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql -h haproxy-server -P 3302 -u dbuser -p
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They are transparently forwarded to MySQL Server 2.&lt;/p&gt;

&lt;p&gt;This method keeps things simple and avoids complex routing logic.&lt;/p&gt;




&lt;h2&gt;
  
  
  🟩 Architecture Diagram
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                +---------------------+
                |     Client User     |
                +----------+----------+
                           |
                           | MySQL request on port 3301/3302/3303
                           |
                     +-----+------+
                     |  HAProxy   |
                     |  (10.0.0.14)|
                     +-----+------+
         3301 -----------| |------------- 3302
                         | |
        +----------------+ +----------------+
        |                                   |
+-------+--------+                 +--------+-------+
| MySQL Server 1 |                 | MySQL Server 2 |
|  (10.0.0.11)   |                 |  (10.0.0.12)   |
|     db1        |                 |     db2        |
+----------------+                 +----------------+

                    +-----------------------+
                    |   MySQL Server 3      |
                    |     (10.0.0.13)       |
                    |         db3           |
                    +-----------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🟩 Server Setup Overview
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;| Server Role            | Example IP  |
| ---------------------- | ----------- |
| MySQL Server 1 (db1)   | `10.0.0.11` |
| MySQL Server 2 (db2)   | `10.0.0.12` |
| MySQL Server 3 (db3)   | `10.0.0.13` |
| HAProxy + MySQL client | `10.0.0.14` |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Replace IPs with your own.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🟦 Step 1 — Install MySQL on Each Server
&lt;/h2&gt;

&lt;p&gt;Run on all three MySQL servers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt update
sudo apt install mysql-server -y
sudo systemctl enable mysql
sudo systemctl start mysql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🟦 Step 2 — Secure MySQL Installation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mysql_secure_installation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Recommended answers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Remove anonymous users: Yes&lt;/li&gt;
&lt;li&gt;Disallow remote root login: Yes&lt;/li&gt;
&lt;li&gt;Remove test DB: Yes&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🟦 Step 3 — Create Databases and MySQL User
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;✔ Server 1 (10.0.0.11)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mysql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE DATABASE db1;
CREATE USER 'dbuser'@'%' IDENTIFIED BY 'StrongPass@123';
GRANT ALL PRIVILEGES ON db1.* TO 'dbuser'@'%';
FLUSH PRIVILEGES;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;✔ Server 2 (10.0.0.12)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE DATABASE db2;
CREATE USER 'dbuser'@'%' IDENTIFIED BY 'StrongPass@123';
GRANT ALL PRIVILEGES ON db2.* TO 'dbuser'@'%';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;✔ Server 3 (10.0.0.13)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE DATABASE db3;
CREATE USER 'dbuser'@'%' IDENTIFIED BY 'StrongPass@123';
GRANT ALL PRIVILEGES ON db3.* TO 'dbuser'@'%';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🟦 Step 4 — Allow Remote Connections
&lt;/h2&gt;

&lt;p&gt;Edit MySQL config on each database server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bind-address = 127.0.0.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bind-address = 0.0.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl restart mysql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🟦 Step 5 — Install HAProxy on the Client Server
&lt;/h2&gt;

&lt;p&gt;Run on 10.0.0.14:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt update
sudo apt install haproxy -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🟦 Step 6 — Configure HAProxy for MySQL Port Forwarding
&lt;/h2&gt;

&lt;p&gt;Edit config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;global
    log /dev/log local0
    maxconn 4096
    daemon

defaults
    mode tcp
    option tcplog
    timeout connect 5s
    timeout client  1m
    timeout server  1m

# -----------------
# FRONTENDS
# -----------------

frontend mysql_db1
    bind *:3301
    default_backend backend_db1

frontend mysql_db2
    bind *:3302
    default_backend backend_db2

frontend mysql_db3
    bind *:3303
    default_backend backend_db3

# -----------------
# BACKENDS
# -----------------

backend backend_db1
    server db1 10.0.0.11:3306 check

backend backend_db2
    server db2 10.0.0.12:3306 check

backend backend_db3
    server db3 10.0.0.13:3306 check
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart HAProxy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl restart haproxy
sudo systemctl enable haproxy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🟦 Step 7 — Test HAProxy Routing
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;✔ Test DB1&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql -u dbuser -p -h 127.0.0.1 -P 3301 db1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;✔ Test DB2&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql -u dbuser -p -h 127.0.0.1 -P 3302 db2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;✔ Test DB3&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql -u dbuser -p -h 127.0.0.1 -P 3303 db3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it connects successfully, HAProxy routing works!&lt;/p&gt;




&lt;h2&gt;
  
  
  🟩 How Users Will Connect
&lt;/h2&gt;

&lt;p&gt;Tell users:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;| Database | Port     |
| -------- | -------- |
| db1      | **3301** |
| db2      | **3302** |
| db3      | **3303** |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql -h &amp;lt;haproxy-ip&amp;gt; -P 3302 -u dbuser -p db2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🟩 Why This Architecture Works Well
&lt;/h2&gt;

&lt;p&gt;✔ Simple — no need for DNS tricks or MySQL router&lt;br&gt;
✔ Easy to scale — add more ports/backends anytime&lt;br&gt;
✔ Secure — MySQL servers are never exposed directly&lt;br&gt;
✔ Transparent to users — they just pick a port&lt;br&gt;
✔ Good for multi-tenant setups&lt;/p&gt;




&lt;h2&gt;
  
  
  🟩 Conclusion
&lt;/h2&gt;

&lt;p&gt;Using HAProxy as a port-based MySQL router is one of the cleanest and most maintainable setups for environments where different databases reside on different servers.&lt;/p&gt;

&lt;p&gt;By forwarding unique ports to unique backend servers, you avoid complexity while providing a flexible system that users can easily interact with.&lt;/p&gt;

</description>
      <category>mysql</category>
      <category>haproxy</category>
      <category>devops</category>
      <category>cloud</category>
    </item>
    <item>
      <title>🔐Secure AWS Access Using Client VPN Endpoint — A Step-by-Step Guide (EasyRSA + ACM)</title>
      <dc:creator>Latchu@DevOps</dc:creator>
      <pubDate>Sat, 06 Dec 2025 06:20:32 +0000</pubDate>
      <link>https://dev.to/latchudevops/secure-aws-access-using-client-vpn-endpoint-a-step-by-step-guide-easyrsa-acm-3mh2</link>
      <guid>https://dev.to/latchudevops/secure-aws-access-using-client-vpn-endpoint-a-step-by-step-guide-easyrsa-acm-3mh2</guid>
      <description>&lt;p&gt;Managing secure access to your AWS resources—without juggling IP whitelisting or exposing your infrastructure—is easier than you think. In this guide, you’ll learn how to create your own certificates using EasyRSA, upload them to AWS Certificate Manager (ACM), and configure a fully functional AWS Client VPN Endpoint.&lt;/p&gt;

&lt;p&gt;By the end, you’ll be able to connect securely to your VPC with a simple VPN client.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⭐ What We’ll Cover
&lt;/h2&gt;

&lt;p&gt;Generating server &amp;amp; client certificates using EasyRSA&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uploading certificates to AWS ACM&lt;/li&gt;
&lt;li&gt;Creating and configuring an AWS Client VPN Endpoint&lt;/li&gt;
&lt;li&gt;Associating networks &amp;amp; setting authorization rules&lt;/li&gt;
&lt;li&gt;Downloading the .ovpn file and connecting securely&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s get started!&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ Step 1: Install EasyRSA &amp;amp; Generate Certificates
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Download EasyRSA&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Download the ZIP for your Windows version from:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/OpenVPN/easy-rsa/releases" rel="noopener noreferrer"&gt;👉 Download EasyRSA&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Open EasyRSA Shell&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;C:\Program Files\EasyRSA-3.x&amp;gt; .\EasyRSA-Start.bat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Initialize a New PKI&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./easyrsa init-pki
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Build Your Certificate Authority (CA)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./easyrsa build-ca nopass
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5. Generate Server Certificate &amp;amp; Key&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./easyrsa --san=DNS:server build-server-full server nopass
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;6. Generate Client Certificate &amp;amp; Key&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./easyrsa build-client-full client1.domain.tld nopass
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repeat as needed for additional users.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Exit the EasyRSA Shell&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;exit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  📁 Step 2: Organize Certificates for Upload
&lt;/h2&gt;

&lt;p&gt;Create a custom folder and copy the required files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir C:\custom_folder
copy pki\ca.crt C:\custom_folder
copy pki\issued\server.crt C:\custom_folder
copy pki\private\server.key C:\custom_folder
copy pki\issued\client1.domain.tld.crt C:\custom_folder
copy pki\private\client1.domain.tld.key C:\custom_folder
cd C:\custom_folder
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ☁️ Step 3: Upload Certificates to AWS ACM
&lt;/h2&gt;

&lt;p&gt;Go to AWS Certificate Manager (ACM) and upload:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;server.crt&lt;/li&gt;
&lt;li&gt;ca.crt&lt;/li&gt;
&lt;li&gt;server.key&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once uploaded, your certificates will be ready to attach to the Client VPN Endpoint.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔧 Step 4: Create the AWS Client VPN Endpoint
&lt;/h2&gt;

&lt;p&gt;Navigate to:&lt;/p&gt;

&lt;p&gt;AWS Console → VPC → Client VPN Endpoints → Create Client VPN Endpoint&lt;/p&gt;

&lt;p&gt;Fill in the details:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;| Setting                | Value                             |
| ---------------------- | --------------------------------- |
| Name                   | `my-client`                       |
| Endpoint IP type       | IPv4                              |
| Client IPv4 CIDR       | `20.0.0.0/22`                     |
| Server certificate ARN | select from ACM                   |
| Authentication         | Mutual authentication             |
| Client certificate ARN | select from ACM                   |
| DNS servers            | `10.0.0.2`, `8.8.8.8`             |
| Protocol               | UDP                               |
| VPN Port               | 443                               |
| VPC                    | Select your VPC                   |
| Security Group         | Any SG that allows needed traffic |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Click Create.&lt;/p&gt;




&lt;h2&gt;
  
  
  🌐 Step 5: Associate a Target Network
&lt;/h2&gt;

&lt;p&gt;Go to your Client VPN endpoint:&lt;/p&gt;

&lt;p&gt;Target network associations → Associate network&lt;/p&gt;

&lt;p&gt;Select:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your VPC&lt;/li&gt;
&lt;li&gt;The subnet you want users to access&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔑 Step 6: Add Authorization Rules
&lt;/h2&gt;

&lt;p&gt;Go to Authorization rules → Add new rule:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Destination network: 10.0.0.0/26 (your VPC CIDR)&lt;/li&gt;
&lt;li&gt;Access: Allow access to all users&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Add the rule.&lt;/p&gt;




&lt;h2&gt;
  
  
  📥 Step 7: Download &amp;amp; Update VPN Config
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Download the client configuration (.ovpn) from your Client VPN endpoint.&lt;/li&gt;
&lt;li&gt;Add your client certificate and key inside the .ovpn file:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;cert&amp;gt;
  (contents of client1.domain.tld.crt)
&amp;lt;/cert&amp;gt;

&amp;lt;key&amp;gt;
  (contents of client1.domain.tld.key)
&amp;lt;/key&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  💻 Step 8: Install AWS Client VPN
&lt;/h2&gt;

&lt;p&gt;Download here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/vpn/client-vpn-download/" rel="noopener noreferrer"&gt;👉 Download AWS Client VPN&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Install and open the client.&lt;/p&gt;

&lt;p&gt;Add a new profile using the updated .ovpn file and connect.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎉 You're In!
&lt;/h2&gt;

&lt;p&gt;You are now connected to your AWS VPC securely via Client VPN Endpoint.&lt;br&gt;
No more IP whitelisting. No exposing SSH ports. Just clean, encrypted access.&lt;/p&gt;

&lt;p&gt;You can now SSH into your servers safely from your local machine.&lt;/p&gt;




&lt;h2&gt;
  
  
  💬 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;AWS Client VPN Endpoint is a powerful way to centralize, secure, and simplify access to your private networks. By generating your own certificates, you stay fully in control of your security setup.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>cloud</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>🚀 Task #4 — GitHub Actions with CI + Docker + GitOps ArgoCD + GKE Cluster (CICD)</title>
      <dc:creator>Latchu@DevOps</dc:creator>
      <pubDate>Fri, 28 Nov 2025 06:08:51 +0000</pubDate>
      <link>https://dev.to/latchudevops/task-4-github-actions-with-ci-docker-gitops-argocd-gke-cluster-cicd-2e9c</link>
      <guid>https://dev.to/latchudevops/task-4-github-actions-with-ci-docker-gitops-argocd-gke-cluster-cicd-2e9c</guid>
      <description>&lt;h2&gt;
  
  
  📌 How CI/CD Works
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step-by-Step Flow&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1️⃣ Developer pushes code to GitHub&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Push changes inside app/main.go&lt;/li&gt;
&lt;li&gt;Push new Dockerfile changes&lt;/li&gt;
&lt;li&gt;Push manifest updates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2️⃣ GitHub Actions Runs&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Builds Docker image&lt;/li&gt;
&lt;li&gt;Pushes new image to GHCR&lt;/li&gt;
&lt;li&gt;Updates deployment YAML&lt;/li&gt;
&lt;li&gt;Commits YAML back to the repo&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3️⃣ ArgoCD Observes Git State&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ArgoCD continuously watches repo&lt;/li&gt;
&lt;li&gt;Repo changed ➝ ArgoCD detects new commit&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4️⃣ ArgoCD Performs Deployment&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Applies updated YAML to Kubernetes&lt;/li&gt;
&lt;li&gt;Deploys the new version&lt;/li&gt;
&lt;li&gt;Ensures cluster matches Git (self-heal)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5️⃣ Result&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;✅ Fully automated CI/CD&lt;br&gt;
🔥 No kubectl required&lt;br&gt;
⚡ Zero manual deployments&lt;br&gt;
🎯 Pull-based GitOps workflow (secure + stable)&lt;/p&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk01x4581snve80a8fgg2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk01x4581snve80a8fgg2.png" alt="1" width="800" height="349"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  📁 Project Structure
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;argocd-demo-app/
  ├── app/
  │    └── main.go
  ├── k8s/
  │    └── deployment.yaml
  ├── .github/
  │    └── workflows/
  │         └── ci-cd.yaml
  ├── Dockerfile
  ├── README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ehad19h09183kuoa2s8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ehad19h09183kuoa2s8.png" alt="r1" width="800" height="487"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  📌 Part 1 — Application Code
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;app/main.go&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
    "fmt"
    "net/http"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintln(w, "This is Latchu! Hello from ArgoCD + GitHub Actions + GitOps!")
    })

    fmt.Println("Server running on port 80")
    http.ListenAndServe(":80", nil)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  📌 Part 2 — Dockerfile
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM golang:1.22 AS builder
WORKDIR /app
COPY app/ .
RUN go build -o server main.go

FROM debian:stable-slim
COPY --from=builder /app/server /usr/local/bin/server
CMD ["server"]
EXPOSE 80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  📌 Part 3 — Kubernetes Deployment
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;k8s/deployment.yaml&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-app
  labels:
    app: demo-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: demo-app
  template:
    metadata:
      labels:
        app: demo-app
    spec:
      containers:
      - name: demo-app
        image: latchudevops/argocd-demo-app:780e0f9bf323810e2acbbb60b8414b5e34b16af6
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: demo-app
spec:
  type: LoadBalancer
  selector:
    app: demo-app
  ports:
    - port: 80
      targetPort: 80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  📌 Part 4 — GitHub Actions CI/CD Pipeline
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;.github/workflows/ci-cd.yaml&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: CI-CD Pipeline

on:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: write

    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          token: ${{ secrets.GITHUB_TOKEN }}

      - name: Login to DockerHub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: Build &amp;amp; Push Docker Image
        run: |
          IMAGE=latchudevops/argocd-demo-app:${{ github.sha }}
          docker build -t $IMAGE .
          docker push $IMAGE
          echo "IMAGE_NAME=$IMAGE" &amp;gt;&amp;gt; $GITHUB_ENV

      - name: Update Kubernetes Manifest
        run: |
          sed -i "s|image: .*|image: $IMAGE_NAME|g" k8s/deployment.yaml

      - name: Commit Updated Manifest
        run: |
          git config --global user.email "actions@github.com"
          git config --global user.name "GitHub Actions"
          git add k8s/deployment.yaml
          git commit -m "Update image to $IMAGE_NAME" || echo "No changes to commit"
          git push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  📌 Part 5 — GitHub Secrets
&lt;/h2&gt;

&lt;p&gt;GitHub repo -&amp;gt; Settings -&amp;gt; Secrets and Variables -&amp;gt; Actions -&amp;gt; Add new repository secret&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fogd3r3e4yxmeh326fzvl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fogd3r3e4yxmeh326fzvl.png" alt="s" width="800" height="297"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  📌 Part 6 — ArgoCD Setup (GKE)
&lt;/h2&gt;

&lt;p&gt;To install and configure ArgoCD on Google Kubernetes Engine Cluster using below this link &lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/latchudevops/task-1-introduction-to-argocd-installation-on-gke-cluster-445m"&gt;ArgoCD Setup&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkbk1x55e76eogfmto7s3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkbk1x55e76eogfmto7s3.png" alt="a1" width="800" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fen6bviy73kmyc01zsbos.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fen6bviy73kmyc01zsbos.png" alt="a2" width="800" height="512"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  📌 Part 7 — To start CICD
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Push any changes inside app/main.go&lt;/li&gt;
&lt;li&gt;GitHub Action Workflow CICD pipeline start the build docker image, push the docker image to the docker hub and update the deployment yaml file inside k8s&lt;/li&gt;
&lt;li&gt;ArgoCD continuously watches the k8s mainfest yaml&lt;/li&gt;
&lt;li&gt;Manifests changed -&amp;gt; ArgoCD detects new commit&lt;/li&gt;
&lt;li&gt;Applies updated YAML to Kubernetes&lt;/li&gt;
&lt;li&gt;Deploys the new version into GKE cluster&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you check with GitHub Actions workflow,&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn9lbz2yndeweul7321qh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn9lbz2yndeweul7321qh.png" alt="g1" width="800" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you can check with ArgoCD UI&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwnzxkfdo6f6ldaqslsm3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwnzxkfdo6f6ldaqslsm3.png" alt="a4" width="800" height="361"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have a look at the GKE Cluster&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8qctibny9fdue0vnw0xs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8qctibny9fdue0vnw0xs.png" alt="k1" width="800" height="119"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The new version has been deployed in Kubernetes&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx3bu5ugz6zutlzhy01lp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx3bu5ugz6zutlzhy01lp.png" alt="v1" width="800" height="285"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;🌟 Thanks for reading! If this post added value, a like ❤️, follow, or share would encourage me to keep creating more content.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;— Latchu | Senior DevOps &amp;amp; Cloud Engineer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;☁️ AWS | GCP | ☸️ Kubernetes | 🔐 Security | ⚡ Automation&lt;br&gt;
📌 Sharing hands-on guides, best practices &amp;amp; real-world cloud solutions&lt;/p&gt;

</description>
      <category>cicd</category>
      <category>devops</category>
      <category>kubernetes</category>
      <category>argocd</category>
    </item>
    <item>
      <title>🎯 Task #3 — Enable AutoSync + Health Checks + Self-Heal in ArgoCD</title>
      <dc:creator>Latchu@DevOps</dc:creator>
      <pubDate>Thu, 27 Nov 2025 12:49:52 +0000</pubDate>
      <link>https://dev.to/latchudevops/task-3-enable-autosync-health-checks-self-heal-in-argocd-3pap</link>
      <guid>https://dev.to/latchudevops/task-3-enable-autosync-health-checks-self-heal-in-argocd-3pap</guid>
      <description>&lt;p&gt;ArgoCD is powerful because it continuously watches Git and your cluster, and keeps them in sync.&lt;br&gt;
This task enables:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ Auto-Sync&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Automatically apply changes from Git to the cluster.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ Self-Heal&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If someone manually edits or deletes a Kubernetes object, ArgoCD restores it from Git.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ Auto-Prune&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Remove Kubernetes resources that were removed from Git.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ Rollbacks&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If a sync fails, ArgoCD will automatically roll back to a good version.&lt;/p&gt;


&lt;h2&gt;
  
  
  ⭐ Step 1 — Enable AutoSync in ArgoCD UI
&lt;/h2&gt;

&lt;p&gt;Go to:&lt;/p&gt;

&lt;p&gt;Applications → Select your app → App Details → Sync Policy&lt;/p&gt;

&lt;p&gt;Turn ON:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Auto-Sync&lt;/li&gt;
&lt;li&gt;Prune Resources&lt;/li&gt;
&lt;li&gt;Self Heal&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffatz7ltbem00m6ra5dfk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffatz7ltbem00m6ra5dfk.png" alt="1" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These correspond to:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Setting&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Meaning&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Auto-Sync&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;If Git changes, ArgoCD automatically applies the changes to the cluster.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Prune&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;If a file (resource) is deleted from Git, ArgoCD deletes that resource from the cluster.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Self-Heal&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;If someone manually changes something in the cluster (via kubectl), ArgoCD restores it back to match Git.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;h2&gt;
  
  
  ⭐ Step 2 — Verify AutoSync is Working
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;(1) Update something in Git&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Edit your deployment.yaml image tag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;image: nginx:1.27
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Push it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add .
git commit -m "Update version"
git push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ArgoCD UI shows "OutOfSync → Syncing → Healthy"&lt;/li&gt;
&lt;li&gt;New image deployed automatically&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo3p0b4syymbtu4gw733o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo3p0b4syymbtu4gw733o.png" alt="2" width="800" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you check with pods,&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj5eck6yoya33s0utnkx8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj5eck6yoya33s0utnkx8.png" alt="3" width="800" height="258"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ⭐ Step 3 — Test Self-Heal (Drift Correction)
&lt;/h2&gt;

&lt;p&gt;Modify something manually in the cluster:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl edit deploy demo-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change replicas from 2 to 5 and save.&lt;/p&gt;

&lt;p&gt;➡️ ArgoCD will detect drift&lt;br&gt;
➡️ ArgoCD will automatically revert replicas back to the Git value (e.g. 2)&lt;/p&gt;

&lt;p&gt;This proves self-heal is working.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6cqilm5lro7b4ioicwzb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6cqilm5lro7b4ioicwzb.png" alt="4" width="800" height="188"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  ⭐ Step 4 — Test Auto-Rollback
&lt;/h2&gt;

&lt;p&gt;Break the deployment:&lt;/p&gt;

&lt;p&gt;Edit your deployment.yaml and use a fake image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;image: nginx:does-not-exist
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Push it.&lt;/p&gt;

&lt;p&gt;Expected:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ArgoCD tries to sync&lt;/li&gt;
&lt;li&gt;Sync fails&lt;/li&gt;
&lt;li&gt;ArgoCD rollback mechanism applies the last healthy version automatically (using retry + failure detection)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your app will remain healthy 👌&lt;/p&gt;




&lt;h2&gt;
  
  
  ⭐ Step 5 — Test Auto-Prune
&lt;/h2&gt;

&lt;p&gt;Delete the service from GitHub:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rm service.yaml
git add .
git commit -m "Remove service"
git push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;➡️ ArgoCD will detect the file removed&lt;br&gt;
➡️ It will delete the Service in Kubernetes automatically&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcvjmytx8gsaqpm517ztg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcvjmytx8gsaqpm517ztg.png" alt="5" width="800" height="142"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  🎉 Final Result — What You Achieved
&lt;/h2&gt;

&lt;p&gt;With Task #3 completed, your app now has:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;| Feature                                     | Status    |
| ------------------------------------------- | --------- |
| Automatic Git → Cluster sync                | ✅ Enabled |
| Automatically revert manual kubectl changes | ✅ Enabled |
| Automatically delete removed resources      | ✅ Enabled |
| Automatic rollback to last good version     | ✅ Enabled |
| Continuous health monitoring                | ✅ Enabled |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;🌟 Thanks for reading! If this post added value, a like ❤️, follow, or share would encourage me to keep creating more content.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;— Latchu | Senior DevOps &amp;amp; Cloud Engineer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;☁️ AWS | GCP | ☸️ Kubernetes | 🔐 Security | ⚡ Automation&lt;br&gt;
📌 Sharing hands-on guides, best practices &amp;amp; real-world cloud solutions&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>cicd</category>
      <category>argocd</category>
    </item>
    <item>
      <title>✅ Task #2 — Deploy Your First GitOps Application on GKE Cluster Using ArgoCD</title>
      <dc:creator>Latchu@DevOps</dc:creator>
      <pubDate>Thu, 27 Nov 2025 11:11:33 +0000</pubDate>
      <link>https://dev.to/latchudevops/task-2-deploy-your-first-gitops-application-on-gke-cluster-using-argocd-3ng1</link>
      <guid>https://dev.to/latchudevops/task-2-deploy-your-first-gitops-application-on-gke-cluster-using-argocd-3ng1</guid>
      <description>&lt;p&gt;In this task you will:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a simple Kubernetes manifest&lt;/li&gt;
&lt;li&gt;Push it to a GitHub repo&lt;/li&gt;
&lt;li&gt;Connect ArgoCD to that repo&lt;/li&gt;
&lt;li&gt;Deploy your app automatically&lt;/li&gt;
&lt;li&gt;Test GitOps Sync (manual + auto)&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  ⭐ STEP 1 — Create a GitHub Repo
&lt;/h2&gt;

&lt;p&gt;Create a new GitHub repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;argocd-demo-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add this structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;argocd-demo-app/
 └── deployment.yaml
 └── service.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ⭐ STEP 2 — Add a Simple NGINX App
&lt;/h2&gt;

&lt;p&gt;deployment.yaml&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-app
  labels:
    app: demo-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: demo-app
  template:
    metadata:
      labels:
        app: demo-app
    spec:
      containers:
        - name: nginx
          image: nginx:1.27
          ports:
            - containerPort: 80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;service.yaml&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: v1
kind: Service
metadata:
  name: demo-app
spec:
  type: LoadBalancer
  selector:
    app: demo-app
  ports:
    - port: 80
      targetPort: 80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Push to GitHub:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add .
git commit -m "first argocd app"
git push origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvaf4s45qhfvg0ev6tgmf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvaf4s45qhfvg0ev6tgmf.png" alt="1" width="800" height="361"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ⭐ STEP 3 — Create ArgoCD Application
&lt;/h2&gt;

&lt;p&gt;🎨 Create application using UI (Beginner-friendly)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open ArgoCD UI&lt;/li&gt;
&lt;li&gt;Click NEW APP&lt;/li&gt;
&lt;li&gt;Fill:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;| Field               | Value            |
| ------------------- | ---------------- |
| Application Name    | `demo-app`       |
| Project             | default          |
| Sync Policy         | Manual (for now) |
| Repository URL      | Your GitHub repo |
| Revision            | main             |
| Path                | `.`              |
| Destination Cluster | in-cluster       |
| Namespace           | default          |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Click create&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F04g7tjyqecu8ugy0g7vh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F04g7tjyqecu8ugy0g7vh.png" alt="2" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ⭐ STEP 4 — Sync Application
&lt;/h2&gt;

&lt;p&gt;In UI:&lt;/p&gt;

&lt;p&gt;👉 Select demo-app&lt;br&gt;
👉 Click SYNC → SYNCHRONIZE&lt;/p&gt;

&lt;p&gt;ArgoCD will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pull manifests from GitHub&lt;/li&gt;
&lt;li&gt;Deploy them into your GKE cluster&lt;/li&gt;
&lt;li&gt;Show pods, services, health status graphically&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check app in cluster:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get pods
kubectl get svc demo-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wait for service external IP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get svc demo-app -w
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open in browser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://&amp;lt;EXTERNAL-IP&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will see default NGINX page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ueooo38g27a58fdwdd7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ueooo38g27a58fdwdd7.png" alt="3" width="800" height="250"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ⭐ STEP 5 — Test GitOps (VERY IMPORTANT)
&lt;/h2&gt;

&lt;p&gt;Now edit repo:&lt;/p&gt;

&lt;p&gt;Edit deployment.yaml:&lt;/p&gt;

&lt;p&gt;Change image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;image: nginx:1.27 -&amp;gt; nginx:1.26
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Push:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git commit -am "downgrade image"
git push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;In ArgoCD:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You will see the app becomes OutOfSync&lt;/p&gt;

&lt;p&gt;Click SYNC&lt;/p&gt;

&lt;p&gt;ArgoCD will deploy the new version&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5xd2riucr0fll8qesxpq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5xd2riucr0fll8qesxpq.png" alt="4" width="800" height="169"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you check with ArgoCD,&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4tsghsmqriocm96nzzkx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4tsghsmqriocm96nzzkx.png" alt="5" width="800" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🎉 This is GitOps!&lt;/p&gt;




&lt;p&gt;🌟 Thanks for reading! If this post added value, a like ❤️, follow, or share would encourage me to keep creating more content.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;— Latchu | Senior DevOps &amp;amp; Cloud Engineer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;☁️ AWS | GCP | ☸️ Kubernetes | 🔐 Security | ⚡ Automation&lt;br&gt;
📌 Sharing hands-on guides, best practices &amp;amp; real-world cloud solutions&lt;/p&gt;

</description>
      <category>gitops</category>
      <category>cicd</category>
      <category>devops</category>
      <category>kubernetes</category>
    </item>
    <item>
      <title>✅ Task #1 — Introduction to ArgoCD + Installation on GKE Cluster</title>
      <dc:creator>Latchu@DevOps</dc:creator>
      <pubDate>Thu, 27 Nov 2025 10:19:06 +0000</pubDate>
      <link>https://dev.to/latchudevops/task-1-introduction-to-argocd-installation-on-gke-cluster-445m</link>
      <guid>https://dev.to/latchudevops/task-1-introduction-to-argocd-installation-on-gke-cluster-445m</guid>
      <description>&lt;h2&gt;
  
  
  1. What is ArgoCD? (Easy Explanation)
&lt;/h2&gt;

&lt;p&gt;ArgoCD is a GitOps-based Continuous Delivery (CD) tool for Kubernetes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔥 In simple words:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ArgoCD automatically deploys apps to your Kubernetes cluster from GitHub/GitLab, and keeps them in sync.&lt;/p&gt;

&lt;p&gt;If your cluster changes → ArgoCD fixes it&lt;br&gt;
If Git changes → ArgoCD deploys the new version&lt;br&gt;
If someone deletes a pod → ArgoCD recreates it&lt;/p&gt;


&lt;h2&gt;
  
  
  2. Why do we need ArgoCD? (Easy-to-understand)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;✅ 1. GitOps Automation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Anything you push to Git will be auto-deployed to Kubernetes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ 2. No manual kubectl apply&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ArgoCD replaces kubectl commands with automation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ 3. Application rollback&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One click → rollback to any previous Git commit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ 4. Full visibility&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A UI dashboard shows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pods&lt;/li&gt;
&lt;li&gt;Services&lt;/li&gt;
&lt;li&gt;Events&lt;/li&gt;
&lt;li&gt;Health status&lt;/li&gt;
&lt;li&gt;Sync status&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;✅ 5. Secure&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Your cluster never needs to pull code from CI.&lt;br&gt;
ArgoCD runs inside the cluster → it pulls manifests securely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ 6. Multi-cluster support&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One ArgoCD can deploy apps to many clusters.&lt;/p&gt;


&lt;h2&gt;
  
  
  ⭐ 3. Install ArgoCD on GKE — Step-by-Step (Task)
&lt;/h2&gt;

&lt;p&gt;Make sure kubectl is connected to your GKE cluster:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud container clusters get-credentials mycluster --region us-central1-a
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 1 — Create the namespace&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl create namespace argocd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2 — Install ArgoCD core components&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3 — Install ArgoCD CLI (optional but useful)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Linux:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo curl -sSL -o /usr/local/bin/argocd \
https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64

sudo chmod +x /usr/local/bin/argocd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4 — Expose ArgoCD UI using LoadBalancer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By default, ArgoCD creates a ClusterIP service.&lt;br&gt;
You need a LoadBalancer for browser login.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl patch svc argocd-server -n argocd \
  -p '{"spec": {"type": "LoadBalancer"}}'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wait for the external IP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get svc -n argocd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look for:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;argocd-server   LoadBalancer   EXTERNAL-IP: x.x.x.x
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 5 — Get the initial admin password&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get secret argocd-initial-admin-secret -n argocd \
  -o jsonpath="{.data.password}" | base64 -d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 6 — Login to ArgoCD (CLI)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;argocd login &amp;lt;EXTERNAL-IP&amp;gt; --username admin --password &amp;lt;PASSWORD&amp;gt; --insecure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 7 — Open ArgoCD UI&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Open in browser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://&amp;lt;EXTERNAL-IP&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg7u9fnll5t61z94zrboj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg7u9fnll5t61z94zrboj.png" alt="1" width="800" height="141"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Login:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Username: admin
Password: (the decoded password above)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frrsfvbbsxrsmzbemd0wt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frrsfvbbsxrsmzbemd0wt.png" alt="2" width="800" height="332"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;🌟 Thanks for reading! If this post added value, a like ❤️, follow, or share would encourage me to keep creating more content.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;— Latchu | Senior DevOps &amp;amp; Cloud Engineer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;☁️ AWS | GCP | ☸️ Kubernetes | 🔐 Security | ⚡ Automation&lt;br&gt;
📌 Sharing hands-on guides, best practices &amp;amp; real-world cloud solutions&lt;/p&gt;

</description>
      <category>argocd</category>
      <category>kubernetes</category>
      <category>cicd</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
