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.