Repository navigation
Add self-hosted Grafana - #2287
Conversation
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
Four moderate issues affect deployment reliability, configuration, permissions, and safe teardown.
Review effort: Balanced
Findings: None
What changed in this PR
Adds self-hosted Grafana on ECS/Fargate with Aurora PostgreSQL, GitHub authentication, AWS observability data sources, and environment/DNS integration.
Changes:
- Adds Grafana infrastructure, networking, IAM, logging, secrets, ALB, and database resources.
- Adds deployment permissions, DNS, environment outputs, and ACM validation support.
- Enables Grafana in development while leaving staging and production disabled.
Required changes:
infra/deployments/forms/health/grafana.tf:2— Moderate (1 vote): Document or redesign the one-way feature flag because protected resources prevent disabling it.infra/modules/grafana/ecs.tf:135— Moderate (1 vote): Add an explicit HTTPS listener dependency to avoid first-deployment ordering failures.infra/modules/grafana/ecs.tf:31— Moderate (1 vote): Joinallowed_organizationswith commas rather than spaces.infra/modules/grafana/iam.tf:64— Moderate (1 vote): Grantlogs:DescribeLogStreamsfor CloudWatch log browsing and queries.
| File | Description |
|---|---|
infra/modules/grafana/variables.tf |
Defines Grafana module inputs. |
infra/modules/grafana/security-groups.tf |
Configures ALB, ECS, and database network access. |
infra/modules/grafana/README.md |
Documents setup and operations. |
infra/modules/grafana/rds.tf |
Provisions Aurora PostgreSQL. |
infra/modules/grafana/providers.tf |
Declares provider requirements. |
infra/modules/grafana/parameters.tf |
Configures secrets and credentials. |
infra/modules/grafana/outputs.tf |
Exposes ALB details. |
infra/modules/grafana/main.tf |
Defines shared module values. |
infra/modules/grafana/logging.tf |
Configures application logging. |
infra/modules/grafana/iam.tf |
Defines task and data-source permissions. |
infra/modules/grafana/ecs.tf |
Defines the Grafana task and ECS service. |
infra/modules/grafana/datasources.tf |
Provisions AWS data sources. |
infra/modules/grafana/alb.tf |
Creates the public HTTPS ALB and certificate. |
infra/modules/environment/outputs.tf |
Exposes networking and logging outputs. |
infra/modules/environment/alb.tf |
Permits Grafana ALB log delivery. |
infra/modules/deployer-access/policy.tf |
Grants Grafana deployment permissions. |
infra/modules/acm-cert-with-dns-validation/variables.tf |
Adds configurable validation-zone input. |
infra/modules/acm-cert-with-dns-validation/main.tf |
Uses the configured certificate validation zone. |
infra/deployments/forms/tfvars/staging.tfvars |
Keeps Grafana disabled in staging. |
infra/deployments/forms/tfvars/production.tfvars |
Keeps Grafana disabled in production. |
infra/deployments/forms/tfvars/dev.tfvars |
Enables Grafana in development. |
infra/deployments/forms/inputs.tf |
Defines deployment-level Grafana settings. |
infra/deployments/forms/health/outputs.tf |
Exposes Grafana ALB outputs. |
infra/deployments/forms/health/grafana.tf |
Conditionally instantiates Grafana. |
infra/deployments/forms/health/dependencies.tf |
Reads required account state. |
infra/deployments/forms/environment/outputs.tf |
Forwards environment outputs. |
infra/deployments/forms/dns/grafana.tf |
Creates the Grafana DNS alias. |
infra/deployments/forms/dns/dependencies.tf |
Reads health state for DNS. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
whi-tw
left a comment
There was a problem hiding this comment.
Other than a few nitpicks, lgtm
The Grafana hostname has no hosted zone of its own.
Grafana's load balancer in the health root needs both.
eef0ea0 to
f05f0ad
Compare
The other ECS services name their task and execution roles and policies `<environment>-<application>-...`. Do the same for Grafana so the deployer policy is consistent.
ECS rejects a service whose target group is not attached to a load balancer. The service only referenced the target group, so in a new environment Terraform could create it before the HTTPS listener had made that attachment.
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
It introduces a public authentication-enabled service and coordinated IAM, database, networking, DNS, and cross-root Terraform changes.
Review effort: Balanced
Findings: None

This PR adds Grafana to give GOV.UK Forms a central tool for visualising data.
We'll use it to show our key performance indicators (KPIs) and to centralise our observability stack, so there are fewer places to look during an incident.
As agreed in the ADR: govuk-forms/forms#264
Self-hosted rather than Amazon Managed Grafana (AMG)
At our team size, the costs are roughly the same. We can switch to AMG once Identity Center is set up and AWS supports Grafana v13.
What this adds
forms-<env>cluster, behind its own public ALB atgrafana.<root_domain>. HTTP redirects to HTTPS.govuk-forms.govuk-forms-infrastructuremembers are admins andgovuk-forms-devsmembers are editors. We'll add the rest of the team as viewers later.environmentroot.This has been tested and verified in dev.
This only switches Grafana on in dev. A follow-up PR will enable it in staging and production.
Deploying to dev
govuk-formswith these URLs:https://grafana.dev.forms.service.gov.ukhttps://grafana.dev.forms.service.gov.uk/login/githubThe break-glass
adminpassword is in/grafana/admin-password. Its login form is at/login?disableAutoLogin=true.