Portfolio deployment using K3s, Terraform, Atmos, Cloudflare DNS, and ArgoCD on Oracle Cloud Free Tier
Overview · Prerequisites · Installation · Architecture · CI/CD Pipeline · Documentation · License
This repository demonstrates infrastructure automation and GitOps principles by deploying a portfolio website on Oracle Cloud Infrastructure Free Tier. The stack uses Terraform with Atmos for infrastructure orchestration, K3s for container orchestration, and ArgoCD for continuous deployment.
Key capabilities:
- Declarative infrastructure provisioning with Terraform (networking, IAM, OCI Vault, K3s cluster, Cloudflare DNS)
- GitOps workflow via ArgoCD ApplicationSets
- Automated image updates and zero-downtime deployments
- Secure secret management using SOPS and OCI Vault
- CI/CD pipeline with SOPS-encrypted OCI credentials and
GITHUB_TOKENfor GHCR - Observability with kube-prometheus-stack (Prometheus + Grafana), Loki log aggregation, and Gatus status page
Install the following tools before beginning:
- Create Oracle Cloud Infrastructure account and upgrade Free Tier to paid account for priority resource allocation (remains within Free Tier limits) (link)
- Create Cloudflare account and generate API token with DNS management permissions (link)
- Generate GitHub Personal Access Token with
repoandpackagesscopes (link)
git clone https://github.com/fapiper/fabianpiper.com.git
cd fabianpiper.comInitialize encryption and configure secrets:
make setupNote
This generates secrets/.sops.key and configures SOPS for all secret files.
Copy the example secrets files and add your credentials:
cp secrets/prod/secrets.example.yaml secrets/prod/secrets.decrypted.yaml
cp secrets/prod/www.example.yaml secrets/prod/www.decrypted.yamlEdit secrets/prod/*.decrypted.yaml with your actual values, then encrypt:
make sops-encrypt-prodDeploy the complete stack with a single command:
make deploy-prodThis provisions networking, IAM policies, OCI Vault, and a K3s cluster with ArgoCD automatically installed. DNS records are synced to Cloudflare after cluster bootstrap.
Verify deployment health:
make validate-prodRetrieve the admin password:
ssh -i ~/.ssh/id_rsa ubuntu@<INGRESS_IP> \
'ssh ubuntu@10.0.2.10 sudo kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d'Create a port forward to access the UI:
ssh -i ~/.ssh/id_rsa -L 8080:10.0.2.10:80 ubuntu@<INGRESS_IP>Open your browser to http://localhost:8080 and log in with username admin and the retrieved password.
The infrastructure consists of:
- VCN with public (10.0.1.0/24) and private (10.0.2.0/24) subnets
- Three ARM Ampere A1 instances running K3s
- OCI Vault for runtime secret storage via Instance Principal
- Cloudflare DNS with static A records provisioned by Terraform, dynamic records synced by
external-dnsfrom HTTPRoutes - ArgoCD managing GitOps deployments
- kube-prometheus-stack (Prometheus + Grafana) + Loki for observability
fabianpiper.com/
fabianpiper.com/
├── components/terraform/ # Atmos component wrappers
│ ├── networking/ # VCN, subnets, security lists
│ ├── iam/ # Dynamic groups and policies
│ ├── vault/ # OCI Vault and stored secrets
│ ├── dns/ # Cloudflare DNS records
│ └── cluster/ # K3s instances and cloud-init
├── modules/ # Terraform module implementations
├── stacks/ # Atmos stack configurations
│ ├── orgs/glg/prod/fra.yaml # Production deployment config
│ ├── mixins/ # Reusable configuration snippets
│ └── workflows/ # Multi-component workflows
├── kubernetes/ # GitOps manifests
│ ├── bootstrap/ # ArgoCD root app and ApplicationSets
│ ├── infrastructure/ # Platform services (cert-manager, gateway, monitoring…)
│ └── apps/ # Application deployments
├── apps/www/ # Website source code (Astro 5.7)
├── secrets/prod/ # SOPS-encrypted secrets
└── .github/workflows/ # CI/CD automation
The automated deployment flow:
- Code changes pushed to
mainbranch - GitHub Actions workflow triggered
- Docker image built and pushed to GHCR
- ArgoCD Image Updater detects new image digest
- ArgoCD automatically syncs and deploys updated application
Important
Only one GitHub secret is required: SOPS_AGE_KEY for infrastructure modifications.
For detailed operational procedures and agent-friendly instructions, refer to AGENTS.md.
This project is licensed under the MIT License. See the LICENSE file for details.