A public, forkable reference deployment of Coder on AWS GovCloud EKS, intended for teams that want to stand up their own GovCloud Coder environment based on proven, battle-tested patterns.
Status: v0. Structural scaffold only. The CI gates, placeholder schema, and sanitized documentation are in place. Full parameterization of the
deploy/,gitops/,terraform/, andcoder-templates/trees is in progress and will land incrementally. See Pending items below.
This repo captures the patterns and structure for running Coder in a US-Government AWS GovCloud account. It is the public half of a private/public split:
| Repo | Audience | Contains |
|---|---|---|
| usgov-reference (this repo) | Public (fork and adapt) | Sanitized patterns, placeholder schema, CI gates |
| Private live-env repo | Internal operators | Real identifiers, live state, operator runbooks |
No real account IDs, domain names, certificate ARNs, VPC/subnet/SG IDs, or other environment-specific identifiers appear in this repository. Enforcement is two-layer:
- Generic regex scanner (
scripts/check-identifiers.sh, runs in CI): flags 12-digit account IDs in ARN/ECR contexts, AWS resource IDs, ACM certificate UUIDs, and an optional configurable base domain. - Literal denylist (private, in the private upstream repository): lists the specific live-env identifiers and runs in the promotion pipeline before any file is published here. Real values never enter this public tree.
- EKS control plane (3 AZs, private subnets) running Coder, Keycloak, Istio, Grafana/Prometheus/Loki, and the External Secrets Operator.
- RDS PostgreSQL Multi-AZ for Coder and Keycloak state.
- ECR private registry (mirrored from public upstreams; no pull-through in GovCloud).
- GitLab Omnibus on EC2 for in-boundary source control.
- AWS Bedrock (IRSA, no static keys) for AI Gateway workloads.
- Route53 (GovCloud hosted zone, NS-delegated from a commercial account).
- Terraform IaC for VPC, EKS, RDS, IAM/IRSA, and ECR.
- Flux GitOps for Helm release management.
See docs/architecture-overview.md for
the full narrative.
Install these tools before working with this repository:
| Tool | Minimum version | Notes |
|---|---|---|
| aws CLI | 2.x | GovCloud profile support requires v2 |
| terraform | 1.9 | Matches provider constraints in terraform/versions.tf |
| helm | 3.x | Used for Helm chart rendering and dry-run checks |
| kubectl | 1.28 (client) | Match the <KUBERNETES_VERSION> you deploy |
| gitleaks | 8.x | Secret pattern scanner; also runs in CI |
| yamllint | 1.35 | YAML static analysis; also runs in CI |
| tflint | 0.52 | Terraform linter |
| shellcheck | 0.9 | Shell script linter |
.
├── docs/ # Sanitized architecture and runbook docs
│ └── architecture-overview.md
├── scripts/
│ ├── check-identifiers.sh # Generic identifier pattern scanner
│ └── forbidden-strings.txt # Identifier format reference (no real values)
├── values/
│ └── env.example.yaml # Full placeholder schema for a new environment
├── .github/workflows/
│ └── ci.yml # Gitleaks + identifier scan + yamllint CI gates
├── CONTRIBUTING.md
└── README.md
The following source trees from the private live-env repo will be
parameterized and added here incrementally. Each item requires replacing
real identifiers with <PLACEHOLDER> tokens that callers supply via
values/env.example.yaml (or a fork of it):
| Tree | Notes |
|---|---|
terraform/ |
VPC, EKS, RDS, IRSA, ECR modules; all account/zone/cert IDs parameterized |
deploy/platform/ |
ingress-nginx, AWS LBC, node pools, namespaces |
deploy/coder/ |
Helm values, External Secrets objects |
deploy/keycloak/ |
Helm values, realm JSON |
deploy/istio/ |
Operator config, VirtualServices, DestinationRules (no live cert ARN) |
deploy/observability/ |
Grafana/Prom/Loki stack, datasources (no live RDS endpoint) |
deploy/gitlab/ |
Omnibus config, runner registration |
gitops/ |
Flux HelmRelease/Kustomization manifests |
coder-templates/ |
Workspace templates (EKS, OCP, AI agent variants) |
scripts/ |
Bootstrap, mirror-images, preflight, persona setup |
The following support files are referenced in the schema but will be added by the base parameterization follow-up:
versions.lock.yaml: chart version lock file referenced invalues/env.example.yaml.deploy/coder/secrets.example.yaml: full placeholder schema for Coder secrets; the current scaffold is incomplete pending parameterization.
- Fork this repository.
- Copy
values/env.example.yamlto a file outside the repo (e.g.,~/.config/myenv/env.yaml) and fill in every<PLACEHOLDER>. - Bootstrap state backend (S3 bucket + DynamoDB table) before running
Terraform:
aws s3 mb s3://<CLUSTER_NAME>-tfstate-<ACCOUNT_ID> --region <REGION> aws dynamodb create-table \ --table-name <CLUSTER_NAME>-tflock \ --attribute-definitions AttributeName=LockID,AttributeType=S \ --key-schema AttributeName=LockID,KeyType=HASH \ --billing-mode PAY_PER_REQUEST \ --region <REGION>
- Apply Terraform to provision VPC, EKS, RDS, IAM, and ECR.
- Mirror images into your ECR registry (see
scripts/mirror-images.shonce it is promoted). - Install the platform layer (ingress-nginx, LBC, ESO, Istio) via Flux or direct Helm.
- Install Coder via the official Helm chart (see
deploy/coder/once promoted). - Run the CI gate locally before any push:
bash scripts/check-identifiers.sh
| Job | Tool | What it checks |
|---|---|---|
gitleaks |
gitleaks | Generic secret patterns (API keys, tokens, credentials) |
check-identifiers |
scripts/check-identifiers.sh |
AWS account IDs in ARN/ECR, resource IDs, ACM cert UUIDs, optional base domain |
yamllint |
yamllint | YAML syntax and style across all .yaml and .yml files |
All jobs run on every pull request and push to main.
A PR may not be merged if any job fails.
See LICENSE (to be added).