This repository contains the GitOps platform for the Ortelius application stack. Terraform provisions infrastructure (EKS or GKE) and bootstraps FluxCD, which then manages all application deployments via Helm.
ageandsops— for secret encryptionawsCLI (EKS only)kubectl,flux,helm
Both clusters:
export TF_VAR_github_token="ghp_..." # GitHub PAT with repo + admin:public_key scopesGKE:
gcloud auth application-default loginEKS:
aws configure # or set AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGIONaws_region = "us-east-1" # AWS region
cluster_name = "ortelius-eks" # EKS cluster name
vpc_cidr = "10.0.0.0/16" # VPC CIDR
domain = "eks.deployhub.com" # Domain for ACM cert and ingress
github_org = "ortelius"
github_repo = "platform-iac"
dns_provider = "cloudflare" # "cloudflare" or "route53"
dns_zone_name = "deployhub.com" # Parent DNS zoneproject_id = "your-gcp-project-id"
region = "us-central1"
cluster_name = "ortelius-gke"
github_org = "ortelius"
github_repo = "platform-iac"deploy.sh is the single entrypoint for installing Ortelius on either EKS or GKE.
./terraform/deploy.sh <gke|eks> [plan|apply|destroy]Examples:
./terraform/deploy.sh eks apply # Deploy to AWS EKS
./terraform/deploy.sh gke apply # Deploy to GCP GKE
./terraform/deploy.sh eks plan # Preview changes
./terraform/deploy.sh eks destroy # Tear down the clusterThe script requires TF_VAR_github_token to be set in the environment before running.
On the first run, deploy.sh generates an age encryption keypair and then prompts for all application secrets. These are encrypted with SOPS and committed to the repo as clusters/<cluster>/ortelius/secrets.enc.yaml.
| Prompt | Description |
|---|---|
smtp.username |
SMTP email address for outbound mail |
arangodb.arangodb_pass |
ArangoDB root password |
ortelius.rbac_repo_token |
GitHub PAT for the RBAC config repo |
ortelius.clientSecret |
GitHub OAuth app client secret |
ortelius.appId |
GitHub App ID |
ortelius.clientId |
GitHub OAuth app client ID |
ortelius.baseUrl |
Public base URL (e.g. https://eks.deployhub.com) |
smtp.password |
SMTP account password |
ortelius.privateKey |
GitHub App private key (paste PEM block, then Ctrl-D) |
cloudflare.apiToken (EKS + Cloudflare only) |
Cloudflare API token for ExternalDNS (or set TF_VAR_cloudflare_api_token) |
The age private key is saved to ~/.ssh/<cluster-name>.sops.key. Back this up — losing it means losing access to all encrypted secrets.
Subsequent runs skip the prompts if secrets.enc.yaml already exists.
- Installs
ageandsopsif missing - Generates (or reuses) an age keypair at
~/.ssh/<cluster-name>.sops.key - Prompts for application secrets and writes the encrypted
secrets.enc.yaml - Commits
.sops.yamlandsecrets.enc.yamlto the repo - Runs
terraform initandterraform apply - Terraform provisions infrastructure (VPC, cluster, IAM, ACM cert)
- Injects the
sops-ageKubernetes secret intoflux-systembefore Flux bootstrap - Runs
flux bootstrap github— installs Flux controllers and registers a deploy key - Writes and commits
clusters/<cluster>/flux-system/kustomization.yamlwith the SOPS patch - Flux reconciles the stack: ALB/GLB controller → ExternalDNS → ortelius HelmRelease
ExternalDNS automatically creates DNS records for the ALB. For ACM certificate validation, add the CNAME shown by:
aws acm describe-certificate \
--certificate-arn $(terraform -chdir=terraform/eks output -raw acm_certificate_arn) \
--query 'Certificate.DomainValidationOptions[0].ResourceRecord'platform-iac/
├── terraform/
│ ├── deploy.sh # Single entrypoint — run this to install Ortelius
│ ├── eks/
│ │ ├── main.tf # VPC, EKS, ALB IAM, ACM, Flux bootstrap
│ │ ├── sops.tf # age keypair, sops-age secret, kustomization patch
│ │ └── terraform.tfvars # ← Edit before deploying EKS
│ └── gke/
│ ├── main.tf # VPC, GKE cluster, static IP, Flux bootstrap
│ ├── sops.tf # age keypair, sops-age secret, kustomization patch
│ └── terraform.tfvars # ← Edit before deploying GKE
│
└── clusters/
├── .sops.yaml # age public key routing (written by deploy.sh)
├── eks/
│ ├── flux-system/ # Flux controllers and kustomizations
│ └── ortelius/
│ ├── values.yaml # Auto-written by Terraform with cert ARN + subnets
│ └── secrets.enc.yaml # ← SOPS-encrypted secrets (written by deploy.sh)
└── gke/
├── flux-system/
└── ortelius/
├── values.yaml
└── secrets.enc.yaml # ← SOPS-encrypted secrets (written by deploy.sh)
# Check Flux controllers
kubectl get pods -n flux-system
# Check application pods
kubectl get pods -n ortelius
# Check HelmRelease status
kubectl get helmrelease -n ortelius
# Check ingress
kubectl get ingress -n orteliusExpected HelmRelease output:
NAME READY STATUS
frontend True Release reconciliation succeeded
ortelius True Release reconciliation succeeded
arangodb True Release reconciliation succeeded