This repository contains a complete solution for the DevOps Assessment, provisioning a scalable, secure infrastructure on DigitalOcean using Terraform, Ansible, and GitHub Actions CI/CD pipeline.
βββββββββββββββββββββββββ
β GitHub Actions β
β CI/CD Orchestrator β
ββββββββββββ¬βββββββββββββ
βββββββββββββββββββββββββ¬ββββββ΄βββββββββ¬βββββββββββββββββββββ
β β β β
ββββββββββββββΌββββββββββ ββββββββββββΌββββββββββ β βββββββββΌββββββββββ
β Terraform State β β Blue-Green β β β DigitalOcean β
β (DO Spaces) β β Deployment β β β API β
ββββββββββββββ¬ββββββββββ ββββββββββββ¬ββββββββββ β βββββββββ¬ββββββββββ
β β β β
ββββββββββββββββββ΄ββββββββ β β β
β β β β β
β HashiCorp Vault β βββββββββββββββ β β
β Secrets Management ββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β β β
βββββββββββ¬βββββββββββββββ β β β
β β β β
β β β β
β βββββββββββββββββββββββββββββββββββββ β β β
β β β β β β
ββββββΆβ Monitoring Stack β β β β
β βββββββββββββββββββββββββββββ β β β β
β β Prometheus β β β β β
β βββββββββββββββββββββββββββββ β β β β
β βββββββββββββββββββββββββββββ β β β β
β β Grafana β β β β β
β βββββββββββββββββββββββββββββ β β β β
β βββββββββββββββββββββββββββββ β β β β
β β Uptime-Kuma β β β β β
β βββββββββββββββββββββββββββββ β β β β
ββββββββββββββββ¬βββββββββββββββββββ β β β
β β β β
β βΌ β β
ββββββββββββββββββββββββββββββββ΄ββββββββββββββββββββββββββββββββββββββββ΄βββ΄ββββββββββββββββββ
β β
β DigitalOcean Infrastructure β
β β
β βββββββββββββββββββββββ βββββββββββββββββββββββ βββββββββββββββββββββββ β
β β Droplet #1 β β Droplet #2 β β Droplet #3 β β
β β β β β β β β
β β - Apache Proxy β β - Apache Proxy β β - Apache Proxy β β
β β - Laravel β β - Laravel β β - Laravel ββββββββββββββββββ
β β - Node.js #1 β β - Node.js #1 β β - Node.js #1 β
β β - Node.js #2 β β - Node.js #2 β β - Node.js #2 β
β β - Docker Runtime β β - Docker Runtime β β - Docker Runtime β
β βββββββββββββββββββββββ βββββββββββββββββββββββ βββββββββββββββββββββββ
β β
β βββββββββββββββββββββββ βββββββββββββββββββββββ βββββββββββββββββββββββββββββββββββββ β
β β Droplet #4 β β Droplet #5 β β Kubernetes Cluster (DOKS) β β
β β β β β β β β
β β - Apache Proxy β β - Apache Proxy β β βββββββββββββββββββββββββββββββ β β
β β - Laravel β β - Laravel β β β Laravel Helm Charts β β β
β β - Node.js #1 β β - Node.js #1 β β βββββββββββββββββββββββββββββββ β β
β β - Node.js #2 β β - Node.js #2 β β βββββββββββββββββββββββββββββββ β β
β β - Docker Runtime β β - Docker Runtime β β β Node.js #1 Helm Charts β β β
β βββββββββββββββββββββββ βββββββββββββββββββββββ β βββββββββββββββββββββββββββββββ β β
β β βββββββββββββββββββββββββββββββ β β
β ββββββββββββββββββββββββββββββββββββββββββββββ β β Node.js #2 Helm Charts β β β
β β Managed PostgreSQL Cluster β β βββββββββββββββββββββββββββββββ β β
β β High Availability Database β β βββββββββββββββββββββββββββββββ β β
β ββββββββββββββββββββββββββββββββββββββββββββββ β β Ingress Controller β β β
β β βββββββββββββββββββββββββββββββ β β
β βββββββββββββββββββββββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- 5 DigitalOcean droplets (Ubuntu 22.04+)
- Managed PostgreSQL database with high availability
- DigitalOcean Kubernetes Cluster (DOKS) for bonus tasks
- DigitalOcean Spaces for Terraform state storage
- SSH key management and security groups configuration
- Server setup for each droplet:
- PHP 8.2+ with Composer
- Node.js 18+
- Apache as reverse proxy
- Docker runtime
- SSL certificates via Let's Encrypt
- Application deployment:
- 1 Laravel application per droplet
- 2 Node.js applications per droplet
- Testing of Laravel and Node.js applications
- Code scanning with:
- SonarCloud for quality analysis
- Snyk for vulnerability detection
- GitHub CodeQL for security analysis
- Infrastructure provisioning via Terraform
- Configuration application via Ansible
- Blue-Green deployment for zero downtime updates
- Centralized secrets storage outside of the GitHub repository
- Dynamic credentials for database access
- Integration with CI/CD pipeline
- Secure access for applications and services
- Docker containerization of all applications
- Kubernetes orchestration via DigitalOcean Kubernetes Service
- Comprehensive monitoring with:
- Prometheus for metrics collection
- Grafana for visualization and alerting
- Uptime-Kuma for status monitoring
- DigitalOcean Account with API Token
- HashiCorp Vault instance for secrets management
- GitHub Account for hosting code and CI/CD
- Terraform installed locally
- Ansible installed locally
- Docker and kubectl (for bonus tasks)
-
Configure HashiCorp Vault for Secrets Management:
# Initialize Vault vault operator init # Unseal Vault (you'll need the unseal keys from the init step) vault operator unseal <unseal-key-1> vault operator unseal <unseal-key-2> vault operator unseal <unseal-key-3> # Login to Vault vault login # Enable secrets engines vault secrets enable -path=digitalocean kv vault secrets enable -path=database kv vault secrets enable -path=certificates kv # Store DigitalOcean API token vault kv put digitalocean/api token=your_do_api_token # Store database credentials vault kv put database/postgres \ username=dbuser \ password=securepassword \ host=db-postgresql-nyc3-12345.db.digitalocean.com \ port=25060 \ dbname=defaultdb # Create policies for access control vault policy write terraform terraform-policy.hcl vault policy write github-actions github-actions-policy.hcl vault policy write applications applications-policy.hcl
-
Configure GitHub Repository:
Add the following secrets to your GitHub repository:
VAULT_ADDR
: URL of your Vault instanceVAULT_TOKEN
: Token with appropriate permissions to read secretsTERRAFORM_CLOUD_TOKEN
: If using Terraform Cloud (optional)
-
Deploy Infrastructure using Terraform:
# Initialize Terraform cd terraform terraform init -backend-config="access_key=DO_SPACES_KEY" -backend-config="secret_key=DO_SPACES_SECRET" # Plan infrastructure changes terraform plan -var-file="terraform.tfvars" # Apply infrastructure changes terraform apply -var-file="terraform.tfvars"
-
Configure Servers with Ansible:
# Update inventory with Terraform outputs cd ansible # Run Ansible playbook ansible-playbook -i inventory.yml playbooks/main.yml
-
Trigger CI/CD Pipeline:
# Push code to GitHub to trigger the workflow git add . git commit -m "Initial deployment" git push origin main
Once deployed, the applications can be accessed at:
- Laravel Application:
https://api.okemwag.com
- Node.js App 1:
https://app1.okemwag.com
- Node.js App 2:
https://app2.okemwag.com
- Grafana Dashboard:
https://monitoring.okemwag.com
- Prometheus:
https://metrics.okemwag.com
- Uptime-Kuma:
https://status.okemwag.com
This solution implements a blue-green deployment strategy to ensure zero downtime during updates:
-
Initial State:
- All traffic is directed to the "blue" environment (original version)
- The "green" environment is inactive or doesn't exist yet
-
Deployment Process:
βββββββββββββββββ β Ingress β β Controller β βββββββββ¬ββββββββ β β βΌ βββββββββββββββββ β Service β β (selector) β βββββββββ¬ββββββββ β ββββββββββββββ΄βββββββββββββ β β βΌ βΌ βββββββββββββββββββ βββββββββββββββββββ β Blue ββββββββ€ Green β β Deployment β β Deployment β β (active) β β (staging) β βββββββββββββββββββ βββββββββββββββββββ
-
Deployment Steps:
- The new version is deployed to the "green" environment
- Automated tests are run against the green environment
- Once tests pass, traffic is gradually shifted from blue to green
- When all traffic is on green, blue becomes inactive
-
Rollback Process:
- If issues are detected, traffic can be immediately shifted back to blue
- The problematic green deployment can be debugged without affecting users
-
Next Deployment Cycle:
- The roles are reversed, with green becoming the active environment
- The next update is deployed to blue (which is now the staging environment)
The blue-green deployment is implemented through:
- Apache Virtual Hosts: Using mod_proxy to route traffic between environments
- Docker Containers: Using tagged images for versioning
- Kubernetes (Bonus): Using service selectors to direct traffic between deployments
The solution uses HashiCorp Vault for secure secrets management, avoiding the use of GitHub Secrets for sensitive information:
-
Secret Storage:
- All secrets (API tokens, credentials, certificates) are stored in Vault
- Secrets are organized by type and environment (dev, staging, prod)
-
Secret Access:
- The CI/CD pipeline authenticates to Vault using a dedicated token
- Applications access secrets using AppRole authentication
-
Secret Flow:
ββββββββββββββββββ βββββββββββββββββ βββββββββββββββββ β β β β β β β HashiCorp VaultβββββββΊβ GitHub ActionsβββββββΊβ Terraform β β β β β β β βββββββββ¬βββββββββ βββββββββββββββββ βββββββββββββββββ β β β β β βΌ β βββββββββββββββββ β β β ββββββββββββββββββββββββββββββββββββββββΊ Applications β β β βββββββββββββββββ
-
Secret Rotation:
- Database credentials can be rotated automatically
- API tokens and other secrets can be rotated manually with minimal downtime
devops-assessment/
βββ terraform/
β βββ main.tf
β βββ variables.tf
β βββ outputs.tf
β βββ providers.tf
β βββ modules/
β β βββ droplets/
β β βββ database/
β β βββ kubernetes/
β β βββ monitoring/
β βββ terraform.tfvars.example
βββ ansible/
β βββ inventory.yml
β βββ playbooks/
β β βββ main.yml
β β βββ prerequisites.yml
β β βββ docker.yml
β β βββ apache.yml
β β βββ certbot.yml
β β βββ apps.yml
β β βββ monitoring.yml
β βββ roles/
β β βββ common/
β β βββ docker/
β β βββ apache/
β β βββ certbot/
β β βββ laravel/
β β βββ nodejs/
β β βββ monitoring/
β βββ templates/
β βββ apache/
β βββ docker-compose/
β βββ monitoring/
βββ kubernetes/
β βββ manifests/
β β βββ laravel/
β β βββ nodejs/
β β βββ ingress/
β βββ helm/
β βββ laravel-app/
β βββ nodejs-app/
βββ apps/
β βββ laravel-app/
β β βββ [Laravel application code]
β βββ nodejs-app/
β βββ [Node.js application code]
βββ vault/
β βββ config/
β βββ policies/
βββ .github/
β βββ workflows/
β βββ ci.yml
β βββ provisioning.yml
β βββ laravel-deploy.yml
β βββ nodejs-deploy.yml
βββ README.md
- Implement autoscaling for applications based on metrics
- Add network policies for enhanced security
- Set up distributed tracing with Jaeger
- Implement GitOps with ArgoCD or Flux
- Add disaster recovery procedures and regular backup testing
This project is licensed under the MIT License - see the LICENSE file for details.