Terraform module that deploys Gatus on AWS Fargate with optional Application Load Balancer integration, freshly provisioned ECS infrastructure, and secret-aware configuration delivery via AWS Systems Manager Parameter Store and Secrets Manager.
- Highlights
- Architecture
- Prerequisites
- Quick Start
- Configuration Guide
- Inputs (highlights)
- Outputs
- Operations
- Security & IAM
- Development
- Support & Contributions
- ✅ Zero-to-running Gatus on Fargate with one module invocation.
- 🧩 Pluggable submodules: toggle ALB, ECS cluster, or service creation independently.
- 🔐 Secrets-aware config loader resolves
__FETCH_FROM_SECRET__.*markers at runtime. - 📦 Storage backends for memory, SQLite, or Postgres with minimal toggles.
- 🛰️ Built-in Service Connect namespace for service discovery inside your VPC.
+---------------------------+
| AWS Application Load |
| Balancer (optional) |
+-------------+-------------+
|
target_group_arn
|
+-------------v-------------+
| AWS ECS Service (Fargate)| <- gatus container
| - gatus-config-loader | <- sidecar container
+-------------+-------------+
|
+--------------+--------------+
| AWS ECS Cluster (optional) |
+--------------+--------------+
|
+-------------v-------------+
| AWS SSM Parameter Store |
| AWS Secrets Manager |
+---------------------------+
The loader sidecar fetches the latest Gatus configuration (from SSM or a provided ARN), replaces any secret placeholders with data from Secrets Manager, writes the final YAML into /config/user_config.yaml, then signals the main container to boot.
- Terraform
>= 1.4.0 - AWS provider
~> 6.0 - AWS credentials with permissions to create/manage ALB, ECS, IAM, CloudWatch Logs, SSM Parameter Store, Secrets Manager, Service Discovery, and optional KMS keys.
Copy the example below into your Terraform project. Adjust networking, KMS, and database modules to fit your environment.
terraform {
required_version = ">= 1.4.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.0"
}
}
}
provider "aws" {
region = "eu-central-1"
}
module "gatus" {
source = "github.com/GiamPy5/terraform-aws-gatus-ecs"
name = "prod-gatus"
create_alb = true
create_ecs_cluster = true
create_ecs_service = true
alb = {
public_subnets = module.vpc.public_subnets
vpc_id = module.vpc.vpc_id
vpc_cidr_block = module.vpc.vpc_cidr_block
acm_certificate_arn = aws_acm_certificate.gatus.arn
}
ecs = {
subnet_ids = module.vpc.private_subnets
}
kms_key_arn = aws_kms_key.gatus.arn
gatus = {
config = file("${path.module}/config.yaml")
}
storage_type = "postgres"
postgres_address = module.rds.address
postgres_db_name = "gatus"
storage_secret_arn = module.rds.master_user_secret_arn
tags = {
Project = "monitoring"
}
}See examples/complete for a full environment that provisions networking, RDS, KMS, and VPC endpoints alongside the module.
-
Gatus configuration
Supply the raw YAML viavar.gatus.config. Unless you passgatus.config_ssm_parameter_arn, the module writes the content to SSM Parameter Store and mounts it inside the container at/config/user_config.yaml. -
Secrets placeholders
Use placeholders like__FETCH_FROM_SECRET__.storage.passwordor__FETCH_FROM_SECRET__.oidc.client-secretin the Gatus config. Providestorage_secret_arnand/oroidc_secret_arn; the loader sidecar will fetch the referenced secret and substitute the value at runtime.- The ECS task definition injects the secret value into the loader container via native ECS Secrets (
STORAGE_SECRET,OIDC_SECRET). If the payload is JSON (e.g., RDS generated credentials), the loader parses it and resolves placeholders without another Secrets Manager API call. When the environment variable still contains an ARN (for backward compatibility), the loader falls back to fetching it directly.
- The ECS task definition injects the secret value into the loader container via native ECS Secrets (
-
Storage selection
Pick the backend withvar.storage_type. Postgres usage requires address, database name, port, and credentials. Supply credentials either as standard variables or, preferably, via Secrets Manager. -
Security configuration
Enablebasicoroidcauth by settingvar.security_typeand adding the respective object invar.security_config. OIDC credentials can also be delivered through Secrets Manager placeholders. -
Postgres credentials
Whenstorage_type = "postgres"andstorage_secret_arnis set, the module automatically injects placeholders for__FETCH_FROM_SECRET__.storage.usernameand.password, so the loader resolves them from the provided secret.- Retrieved usernames/passwords are URL-encoded by the loader to keep the resulting DSN valid even when credentials contain special characters.
-
Existing infrastructure
When integrating with pre-existing ALB or ECS resources, setcreate_alb,create_ecs_cluster, orcreate_ecs_servicetofalseand pass the required ARNs (e.g.,var.alb.target_group_arn,var.ecs.cluster_arn).
⚠️ Sensitive data
Prefer submitting credentials through Secrets Manager ARNs (storage_secret_arn,oidc_secret_arn) instead of plaintext Terraform variables. This keeps secrets out of state files, version control, and CLI history.
No requirements.
| Name | Version |
|---|---|
| aws | n/a |
| Name | Source | Version |
|---|---|---|
| alb-integration | ./modules/alb-integration | n/a |
| ecs-cluster | ./modules/ecs-cluster | n/a |
| ecs-service | ./modules/ecs-service | n/a |
| Name | Type |
|---|---|
| aws_caller_identity.current | data source |
| aws_region.current | data source |
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| additional_config | Additional YAML configuration to merge into the rendered Gatus configuration. | string |
"" |
no |
| alb | Configuration for an existing ALB integration when create_alb is false. | object({ |
n/a | yes |
| aws_region | AWS region override used for providers and logging; defaults to the current region when empty. | string |
"" |
no |
| create_alb | Controls whether this module provisions the accompanying Application Load Balancer integration. | bool |
true |
no |
| create_ecs_cluster | Controls whether a new ECS cluster is created instead of using an existing one. | bool |
true |
no |
| create_ecs_service | Controls whether the ECS service resources are created. | bool |
true |
no |
| ecs | Inputs for the ECS service, including network configuration and optional cluster ARN. | object({ |
n/a | yes |
| gatus | Configuration for the Gatus service, including version and configuration source. | object({ |
n/a | yes |
| kms_key_arn | ARN of the KMS key used to encrypt the generated Gatus configuration parameter. | string |
"" |
no |
| name | Base name used when generating resource names. | string |
"terraform-aws-gatus-ecs" |
no |
| oidc_secret_arn | ARN of the Secrets Manager secret that stores OIDC authentication values. | string |
"" |
no |
| postgres_address | Hostname or endpoint used to reach the Postgres instance. | string |
"" |
no |
| postgres_db_name | Database name included in the Postgres connection string. | string |
"" |
no |
| postgres_password | Password included in the Postgres connection string. | string |
"" |
no |
| postgres_port | Port number used when building the Postgres connection string. | number |
5432 |
no |
| postgres_secret_arn | ARN of a Secrets Manager secret that stores Postgres credentials. | string |
"" |
no |
| postgres_username | Username included in the Postgres connection string. | string |
"" |
no |
| security_config | Security configuration values that accompany the selected security_type. | object({ |
{} |
no |
| security_type | Authentication mode for the Gatus instance: basic, oidc, or left empty for none. | string |
"" |
no |
| sqlite_path | Path inside the container for the SQLite database file. | string |
"/data/gatus.db" |
no |
| storage_secret_arn | ARN of the Secrets Manager secret containing storage credentials for Postgres or other backends. | string |
"" |
no |
| storage_type | Type of storage backend to configure in the Gatus deployment. | string |
"memory" |
no |
| tags | Tags applied to all supported resources. | map(any) |
{} |
no |
| Name | Description |
|---|---|
| load_balancer_dns_name | n/a |
- Initialise providers:
terraform init - Review configuration:
terraform plan - Apply changes:
terraform apply - Validate drift: rerun
terraform planand review CloudWatch Logs (/aws/ecs/containerinsights/<name>) for loader messages.
Ensure the task execution role can:
- Decrypt the configured SSM parameter and any Secrets Manager ARNs you reference.
- Read logs in CloudWatch Logs (
logs:*as configured inmodules/ecs-service/main.tf).
The module grants least-privilege statements tailored to the provided inputs, but you remain responsible for KMS key policies and secret creation.
- Run
terraform fmtandterraform validatebefore submitting changes. - Use the
examples/completestack to test real deployments. - Lint Python changes in
modules/ecs-service/config_loader.py(PEP8) and keep dependencies to standard library only.
Issues and contributions are welcome. Please open a ticket or submit a pull request describing your scenario and any validation steps performed (terraform validate, etc.).