Skip to content

Blue green podman: add "both" mode, add nginx cache, improve logging, shared route generation - #505

Draft
aagbsn wants to merge 41 commits into
mainfrom
blue-green-podman-both
Draft

aagbsn wants to merge 41 commits into
mainfrom
blue-green-podman-both

Conversation

@aagbsn

@aagbsn aagbsn commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

Merged main, then:

Review comments addressed (one commit each)

  • deploy.py logs every ssh/scp/aws command it runs (secrets are only written to files, never logged).
  • Health check matches what ECS gives a new task: curl --max-time 5, two passes in a row, health_check_timeout
    (default 120 s, per service) instead of a single 20 s check.
  • If nginx -t fails, the live slot's upstream is restored and the deploy aborts without reloading nginx, instead
    of leaving a broken conf for the next reload.
  • Draining is bounded: worker_shutdown_timeout 300 s (like the ALB's deregistration delay), and the next deploy
    waits for the old slot to finish draining.

Fixes needed after merging main

  • Blue/green secrets use the per-service ClickHouse URLs that main introduced (otherwise terraform init fails).
  • The gateway's syslog tag is now ooniapi_gateway. nginx rejected the old tag, so the vhost could never have been
    installed.

One source of truth for routes

  • tf/modules/ooniapi_frontend/routes.yaml declares every API route.
  • The ALB's 18 hand-written listener rules become one for_each, with moved blocks. Planned against the old code:
    the same 18 rules, so applying only moves them in state.
  • The gateway's nginx locations are generated from the same file, through a filter plugin that fails the role on any
    route nginx can't serve the way the ALB does. This also picks up main's X-Protocol-Version rules, which the
    hand-written gateway was missing.
  • The oonimeasurements and testlists target group ARNs are now required.

Caching in the gateway

  • Caches GET/HEAD responses for the routes routes.yaml marks for caching (oonimeasurements, oonirun), honoring
    Cache-Control, 10 s when there is none. Skipped for requests with Authorization and for
    no-cache/private/Set-Cookie responses. Two zones, for short-lived and long-lived responses.
  • Each deploy invalidates the cache: the image tag is part of each service's cache key, so a deploy stops serving
    the old entries for that service only.

New deploy_mode = "both"

  • Deploys to ECS (run order 1) and then blue/green to the Hetzner hosts (run order 2) in the same pipeline; a
    failure in either fails the pipeline.
  • Keeps the original single DNS cutover: services run in both, DNS moves once, and the ALB still serves the
    current version if DNS has to move back.
  • The ecs and blue_green modes plan exactly as before.
hellais and others added 16 commits July 10, 2026 16:38
- Install docker-ce from Docker's official apt repo (distro-detected via
  ansible_distribution_release, not hardcoded), replacing Debian's
  docker.io/podman with containerd's nftables firewall backend enabled.
  Verify the downloaded apt signing key's fingerprint before trusting it.
- Rewrite the deploy stage as a single dependency-free deploy.py (stdlib
  only, shells out to ssh/scp/aws/docker) instead of inline buildspec bash.
- Render one docker-compose.yaml per slot instead of a Quadlet unit; slots
  are supervised by docker's own restart policy, no systemd unit needed.
- Move service secrets from a shared env file to Compose's native
  file-based secrets, so each is mounted read-only at /run/secrets/<name>
  instead of ending up in the container's environment.
- Stage files scp'd to target hosts in a private, deploy-user-owned
  directory (chmod 600 + scp -p) instead of world-readable /tmp, closing
  the window where they'd be briefly readable by other local users.
main replaced the shared clickhouse_write_url, clickhouse_readonly_url
and clickhouse_readonly_test_url parameters with one per service
(b7baff6). The blue/green service secrets are built from the same
parameters as each service's ECS task_secrets, so they now point at the
per-service ones again: ooniprobe, oonirun and oonimeasurements in dev,
oonirun in prod. dev oonifindings no longer gets a CLICKHOUSE_URL, like
its ECS task. Without this, terraform init fails on references to
undeclared data sources after merging main.
Review: "We should add a log.info on this" (on run()). Every ssh, scp
and aws command now goes through the logger with a timestamp, so the
CodeBuild log shows what ran against which host and when, not just the
start and end of each host's deploy. Secret values are only ever written
to files, never put on a command line, so they don't reach the log.
Review: "We should make sure 20s is enough". It wasn't comparable to
what the same images get on ECS: the target groups (ooniapi_service)
check /health every 30 s with a 5 s timeout and want 2 passes in a row,
so a new task has about a minute to come up. The blue/green check gave
20 s, a single pass sufficed, and curl had no timeout of its own.

Now each check has curl --max-time 5, the slot must pass twice in a row,
and it has health_check_timeout seconds (default 120, per service) to do
so. The time it took is logged, so the deadline can be tuned per service
from real deploys; at 2 hosts per deploy it stays well within the deploy
job's 20 minute build timeout.
Review: "what happens if nginx -t fails". The new upstream conf was
moved into conf.d before nginx -t, and left there when it failed. nginx
kept serving its old config, but the next reload on that host (another
service's deploy, a certificate renewal) would fail, and a restart would
take every service on the host down.

Now a failing nginx -t puts back the upstream of the slot that is still
serving and checks it again, then aborts the deploy without reloading
nginx or moving the active_slot marker. If nginx -t fails even then, the
config is broken independently of this deploy, and the error says so.
The restore uses the same mv the deploy user's sudoers already allows.
Review: "We should make sure there is some kind of timeout on connections
while draining". After a flip, nginx workers from before the reload keep
serving their in-flight requests to the old slot, with nothing bounding
them but proxy_read_timeout (900 s), and long lived HTTP/2 connections
can keep them longer. On ECS the ALB bounds the same thing with its
deregistration delay, the AWS default of 300 s here.

- ooniapi_gateway sets worker_shutdown_timeout to
  ooniapi_gateway_drain_timeout (300 s), through modules-enabled/, the
  only place included in nginx's main context.
- The next deploy of a service replaces the slot that is draining, so
  deploy.py now waits until drain_timeout (300 s, per service) has passed
  since the previous flip, from the active_slot marker's mtime, before
  restarting it. A first deploy has no marker and does not wait.
The routes of the API are going to be served by two frontends, the ALB
for the services on ECS and the nginx gateway on the Hetzner hosts for
those deployed blue/green, and their copies have already drifted: the
gateway's hand written locations predate main's X-Protocol-Version rules.
routes.yaml becomes the one place they are declared; this change has
Terraform read it, the gateway follows.

The 18 hand written listener rules become one aws_lb_listener_rule with
for_each over routes.yaml, with moved blocks from their old addresses.
Planned with fake ARNs (no state), the old and the new code produce the
same 18 rules: same priorities, targets, conditions and tags. Applying
should only move them in the state.

The "hotfix" that made the oonimeasurements and testlists rules
optional (count = arn != null ? 1 : 0) is removed rather than carried
over. It had stopped working anyway: oonimeasurements_rule_3 lacked the
count, so the frontend couldn't be planned without oonimeasurements.
Both environments pass every target group, so those two inputs are now
required and nullable = false. A missing service fails the plan with
"Required variable not set" instead of silently losing its routes. The
planned rules are unchanged.
The gateway's locations were a hand written copy of the ALB rules, and had
already fallen behind them (main's X-Protocol-Version rules). They are now
generated from tf/modules/ooniapi_frontend/routes.yaml, which the ALB rules
are generated from too, as are the per service direct-host vhosts.

nginx can't follow ALB priorities: it picks an exact match, then the
longest prefix. filter_plugins/ooniapi_routes.py turns each ALB pattern
into an exact or ^~ prefix location and lists the routes nginx couldn't
serve the same way (a wildcard other than a trailing *, the same path
twice, a prefix of one service covering a path of another); the role
fails on any. A plugin rather than inline Jinja, so the result doesn't
depend on how a given ansible-core converts templated strings.

Routes marked legacy (ooniprobe_legacy, being retired) are left to the
ALB: the gateway doesn't run it, so those paths go to ooniprobe.

Rendered with ansible-core 2.21 for all six services plus testlists
proxied cross-cloud, the generated config has the same 46 locations, with
the same match types and upstreams, as the hand written one.
nginx only allows letters, digits and underscores in a syslog tag, so
nginx -t rejected the gateway vhost ("syslog \"tag\" only allows
alphanumeric characters and underscore", nginx 1.27) and it could never
have been installed. The tag is now ooniapi_gateway.
Nothing caches oonimeasurements or oonirun today: on api.ooni.org every
repeated request reaches uvicorn (only the reverseproxy's /api/_/ paths
show x-cache-status: HIT), and for oonimeasurements that means ClickHouse,
saturated on data2. The gateway now caches GET/HEAD responses of the
routes routes.yaml marks cache (oonimeasurements, oonirun), as long as
their Cache-Control allows, or 10 s without one, like the legacy ooni-api
vhost's apicache. Requests with an Authorization header never use the
cache (oonirun links can differ per user), and nginx doesn't store
no-cache, private or max-age=0 responses, or any setting a cookie.

Two zones, since nginx keeps an entry until it goes unused for inactive,
expired or not: lists and aggregations valid for minutes would otherwise
push out measurement bodies valid for a day. Sized per host as if it got
all the traffic, from data2's query_log and responses of api.ooni.org:

- long (raw_measurement, measurement_meta; valid 1 d): at most ~50K
  distinct bodies a day of ~76 KB (max seen ~160 KB), ~3.8 GB a day:
  max_size 8g, keys_zone 16m (~130K keys), inactive 1d.
- short (everything else cached; valid 10 s to 1 h): ~7.5K requests an
  hour of up to ~60 KB, ~450 MB an hour if all were distinct: max_size
  2g, keys_zone 8m, inactive 1h.

The access log now records $upstream_cache_status, to tune these from
real hit rates. Cache directives and X-Cache-Status are set per server,
since an add_header in a location would drop the server's HSTS headers.

Checked with nginx 1.27 and stub upstreams: lists, bodies (long zone)
and header-less aggregations miss then hit; Authorization bypasses and
isn't stored; no-cache isn't stored; ooniprobe and the default route
aren't cached; every response keeps HSTS.
A deploy can change what a service returns, but the gateway would keep
serving responses cached from the old slot, for up to a day for
measurement bodies. nginx without the commercial purge API can't drop
entries, so each service's cache key now starts with a version: the
image tag, which deploy.py writes into <service>-upstream.conf as
$ooniapi_cache_version_<service>, the same file and the same reload
that put the new slot in rotation. From then on the old entries are
never looked up and age out of the zones; other services' caches are
left alone. (The slot letter wouldn't do: slots alternate, so it would
bring back responses from two deploys ago.)

When nginx -t rejects the new upstream conf, deploy.py now puts the
previous file back as it was, cache version included, rather than
rendering it again. The image tag is checked to be a plain tag, since
it ends up in an nginx string. The placeholder upstream conf the role
seeds before a first deploy defines an empty version.

Checked with nginx 1.27: after a deploy of oonimeasurements its cached
list missed (new upstream response) then hit again, while oonirun's
cached response kept hitting; redeploying the previous tag found that
tag's entries again, as long as they were still valid.
A service had to choose between ECS and the Hetzner hosts. Switching
one to "blue_green" removes the ECS deploy action but leaves the ECS
service running, so the ALB keeps sending api.ooni.org and
<service>.prod.ooni.io traffic to tasks that no longer get new
versions, until DNS moves to the hosts.

"both" deploys the same build artifact to ECS and then, in the same
Deploy stage, runs the blue/green deploy to the hosts. The ECS deploy
runs first, so the hosts never get a version ECS rejected. Either
failing fails the pipeline. The migration can then keep the single DNS
cutover of the original design while every service runs in "both":
the hosts are proven before the move, and DNS can go back to the ALB,
which still serves the current version, if they aren't.

"ecs" and "blue_green" plan exactly as before. Planned with fake
inputs, one service per mode, and the account id lookup replaced by a
constant: the 6 and 13 resources are identical. A "both" service gets
the 13 blue/green resources and a Deploy stage with ECS "Deploy" (run
order 1) then CodeBuild "DeployBlueGreen" (run order 2). Both actions
need their own name and namespace. The pipeline role already allows
ecs:* and codebuild:StartBuild on any resource.

The per-service comments in dev and prod now mention "both", and no
longer say the blue/green deploy uses systemd (it uses Docker Compose
since e11b071).
@aagbsn
aagbsn marked this pull request as draft October 4, 2026 04:56
@github-actions

github-actions Bot commented Oct 4, 2026 •

Copy link
Copy Markdown

Terraform Run Output 🤖

Format and Style 🖌success

Initialization ⚙️success

Validation 🤖success

Validation Output

$ terraform validate

Warning: Argument is deprecated

  with aws_s3_bucket.anoncred_manifests,
  on main.tf line 383, in resource "aws_s3_bucket" "anoncred_manifests":
 383: resource "aws_s3_bucket" "anoncred_manifests" {

Use the aws_s3_bucket_versioning resource instead

Warning: Available Write-only Attribute Alternative

  with module.ooni_monitoring.aws_ssm_parameter.ooni_monitoring_access_key,
  on ../../modules/ooni_monitoring/main.tf line 47, in resource "aws_ssm_parameter" "ooni_monitoring_access_key":
  47:   value = aws_iam_access_key.ooni_monitoring.id

The attribute value has a write-only alternative value_wo available. Use the
write-only alternative of the attribute when possible.

(and one more similar warning elsewhere)
Success! The configuration is valid, but there were some validation warnings
as shown above.

Plan 📖success

  • Plan: 19 to add, 7 to change, 5 to destroy.
Show Plan

$ terraform plan

Warning: Deprecated Parameter

The parameter "dynamodb_table" is deprecated. Use parameter "use_lockfile"
instead.
module.ansible_inventory.local_file.ansible_inventory: Refreshing state... [id=b6de844ed8d384f890fa6f467502390de843f758]
module.ooni_fastpath.module.ec2.data.cloudinit_config.ooni_ec2: Reading...
random_id.artifact_id: Refreshing state... [id=8Ujqew]
module.ooniapi_frontend.random_id.artifact_id: Refreshing state... [id=_3cQlA]
module.ooni_jumphost.data.cloudinit_config.ooni_ec2: Reading...
module.ooniapi_testlists.data.cloudinit_config.ooni_ec2: Reading...
module.adm_iam_roles.tls_private_key.oonidevops: Refreshing state... [id=b49a9fdb9f720320340226016efe24808dd68203]
module.ooniapi_testlists.data.cloudinit_config.ooni_ec2: Read complete after 0s [id=2022394177]
data.dns_a_record_set.ooniapi_deploy_host: Reading...
data.dns_a_record_set.monitoring_host: Reading...
module.ooni_clickhouse_proxy.data.cloudinit_config.ooni_ec2: Reading...
module.ooni_jumphost.data.cloudinit_config.ooni_ec2: Read complete after 0s [id=2022394177]
module.ooni_monitoring_proxy.data.cloudinit_config.ooni_ec2: Reading...
module.ooni_fastpath.module.ec2.data.cloudinit_config.ooni_ec2: Read complete after 0s [id=2022394177]
module.ooni_clickhouse_proxy.data.cloudinit_config.ooni_ec2: Read complete after 0s [id=2022394177]
module.ooni_monitoring_proxy.data.cloudinit_config.ooni_ec2: Read complete after 0s [id=2022394177]
module.ansible_inventory.null_resource.ansible_update_known_hosts: Refreshing state... [id=236461505953331670]
data.dns_a_record_set.ooniapi_deploy_host: Read complete after 0s [id=backend-hel.ooni.org]
data.dns_a_record_set.monitoring_host: Read complete after 0s [id=monitoring.ooni.org]
module.ooniapi_ooniprobe.aws_cloudwatch_log_group.ooniapi_service: Refreshing state... [id=ooni-ecs-group/ooniapi-service-ooniprobe]
module.ooniapi_ooniprobe_deployer.data.aws_caller_identity.current: Reading...
module.ooniapi_ooniprobe_legacy.aws_cloudwatch_log_group.ooniapi_service: Refreshing state... [id=ooni-ecs-group/ooniapi-service-ooniprobe-legacy]
data.aws_ssm_parameter.prometheus_metrics_password: Reading...
data.aws_ssm_parameter.do_token: Reading...
module.ooniapi_oonifindings_deployer.data.aws_caller_identity.current: Reading...
module.ooniapi_user.aws_secretsmanager_secret.aws_secret_access_key: Refreshing state... [id=arn:aws:secretsmanager:eu-central-1:905418398257:secret:oonidevops/ooniapi_user/aws_secret_access_key-L0DQDr]
module.oonidevops_github_user.aws_secretsmanager_secret.oonidevops_github: Refreshing state... [id=arn:aws:secretsmanager:eu-central-1:905418398257:secret:oonidevops/github_user/access_key_json-9JTJgd]
module.ooniapi_oonimeasurements.aws_ecs_task_definition.ooniapi_service (deposed object 65743afa): Refreshing state... [id=ooniapi-service-oonimeasurements-td]
module.adm_iam_roles.aws_iam_policy.oonidevops: Refreshing state... [id=arn:aws:iam::905418398257:policy/OONIDevopsPolicy]
module.ooniapi_oonifindings_deployer.data.aws_caller_identity.current: Read complete after 0s [id=905418398257]
module.ooniapi_oonimeasurements_deployer.data.aws_caller_identity.current: Reading...
module.ooniapi_ooniprobe.data.aws_ecs_container_definition.ooniapi_service_current[0]: Reading...
module.ooniapi_ooniprobe_deployer.data.aws_caller_identity.current: Read complete after 0s [id=905418398257]
aws_s3_bucket.ooniapi_codepipeline_bucket: Refreshing state... [id=codepipeline-ooniapi-eu-central-1-f148ea7b]
module.ooniapi_oonimeasurements_deployer.data.aws_caller_identity.current: Read complete after 0s [id=905418398257]
module.ooniapi_reverseproxy.aws_cloudwatch_log_group.ooniapi_service: Refreshing state... [id=ooni-ecs-group/ooniapi-service-reverseproxy]
data.aws_ssm_parameter.prometheus_metrics_password: Read complete after 1s [id=/oonidevops/ooni_services/prometheus_metrics_password]
module.ooniapi_oonirun.data.aws_ecs_container_definition.ooniapi_service_current[0]: Reading...
module.ooniapi_oonifindings.aws_iam_role.ooniapi_service_task: Refreshing state... [id=ooniapi-service-oonifindings-task-role]
data.aws_ssm_parameter.do_token: Read complete after 1s [id=/oonidevops/secrets/digitalocean_access_token]
module.ooniapi_frontend.aws_s3_bucket.load_balancer_logs: Refreshing state... [id=lb-logs-eu-central-1-ff771094]
module.ooniapi_ooniprobe_legacy.data.aws_ecs_container_definition.ooniapi_service_current[0]: Reading...
module.ooniapi_oonifindings.data.aws_ecs_container_definition.ooniapi_service_current[0]: Reading...
module.ooniapi_ooniprobe.data.aws_ecs_container_definition.ooniapi_service_current[0]: Read complete after 1s [id=ooniapi-service-ooniprobe-td/ooniapi-service-ooniprobe]
module.ooniapi_ooniprobe_legacy.aws_iam_role.ooniapi_service_task: Refreshing state... [id=ooniapi-service-ooniprobe-legacy-task-role]
module.fastpath_builder.data.aws_caller_identity.current: Reading...
module.ooni_monitoring_proxy.data.aws_ssm_parameter.ubuntu_22_ami: Reading...
module.ooniapi_oonirun.data.aws_ecs_container_definition.ooniapi_service_current[0]: Read complete after 0s [id=ooniapi-service-oonirun-td/ooniapi-service-oonirun]
module.ooniapi_oonirun.aws_iam_role.ooniapi_service_task: Refreshing state... [id=ooniapi-service-oonirun-task-role]
module.ooniapi_ooniprobe_legacy.data.aws_ecs_container_definition.ooniapi_service_current[0]: Read complete after 0s [id=ooniapi-service-ooniprobe-legacy-td/ooniapi-service-ooniprobe-legacy]
module.ooniapi_reverseproxy.data.aws_ecs_container_definition.ooniapi_service_current[0]: Reading...
data.aws_ssm_parameter.oonipg_url: Reading...
module.ooniapi_ooniauth_deployer.aws_iam_policy.codepipeline: Refreshing state... [id=arn:aws:iam::905418398257:policy/service-role/codepipeline-ooniapi-ooniauth]
module.fastpath_builder.data.aws_caller_identity.current: Read complete after 0s [id=905418398257]
module.adm_iam_roles.data.aws_iam_policy_document.assume_role: Reading...
module.adm_iam_roles.data.aws_iam_policy_document.assume_role: Read complete after 0s [id=3569030007]
module.oonidevops_github_user.aws_iam_user.oonidevops_github: Refreshing state... [id=oonidevops-github]
module.oonitier1plus_cluster.aws_iam_role.container_host: Refreshing state... [id=oonitier1plus-ecs-cluster-container-host-role]
module.ooniapi_oonifindings.data.aws_ecs_container_definition.ooniapi_service_current[0]: Read complete after 0s [id=ooniapi-service-oonifindings-td/ooniapi-service-oonifindings]
aws_s3_bucket.ooniprobe_failed_reports: Refreshing state... [id=ooniprobe-failed-reports-eu-central-1]
module.ooni_monitoring_proxy.data.aws_ssm_parameter.ubuntu_22_ami: Read complete after 0s [id=/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id]
aws_secretsmanager_secret.oonipg_url: Refreshing state... [id=arn:aws:secretsmanager:eu-central-1:905418398257:secret:oonidevops/ooni-tier0-postgres/postgresql_url-w62CTZ]
module.oonitier1plus_cluster.data.aws_ssm_parameter.ecs_optimized_ami: Reading...
aws_iam_role.monitoring_proxy_yace: Refreshing state... [id=monitoring-proxy-yace]
module.ooniapi_reverseproxy.data.aws_ecs_container_definition.ooniapi_service_current[0]: Read complete after 0s [id=ooniapi-service-reverseproxy-td/ooniapi-service-reverseproxy]
module.ooniapi_oonifindings.aws_cloudwatch_log_group.ooniapi_service: Refreshing state... [id=ooni-ecs-group/ooniapi-service-oonifindings]
module.ooniapi_ooniauth.data.aws_ecs_container_definition.ooniapi_service_current[0]: Reading...
data.aws_ssm_parameter.oonipg_url: Read complete after 0s [id=/oonidevops/secrets/ooni-tier0-postgres/postgresql_write_url]
module.ooni_clickhouse_proxy.data.aws_ssm_parameter.ubuntu_22_ami: Reading...
module.ooniapi_reverseproxy_deployer.aws_iam_policy.codepipeline: Refreshing state... [id=arn:aws:iam::905418398257:policy/service-role/codepipeline-ooniapi-reverseproxy]
module.oonitier1plus_cluster.data.aws_ssm_parameter.ecs_optimized_ami: Read complete after 0s [id=/aws/service/ecs/optimized-ami/amazon-linux-2023/recommended]
module.ooniapi_cluster.aws_cloudwatch_log_group.ooniapi_services: Refreshing state... [id=ooni-ecs-group/ooniapi-ecs-cluster]
module.ooniapi_ooniauth.data.aws_ecs_container_definition.ooniapi_service_current[0]: Read complete after 0s [id=ooniapi-service-ooniauth-td/ooniapi-service-ooniauth]
data.aws_ssm_parameter.clickhouse_ooniprobe_url: Reading...
aws_s3_bucket.anoncred_manifests: Refreshing state... [id=ooni-anoncreds-manifests-dev-eu-central-1]
module.ooni_clickhouse_proxy.data.aws_ssm_parameter.ubuntu_22_ami: Read complete after 0s [id=/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id]
module.ooniapi_oonimeasurements_deployer.aws_iam_policy.codepipeline: Refreshing state... [id=arn:aws:iam::905418398257:policy/service-role/codepipeline-ooniapi-oonimeasurements]
module.oonitier1plus_cluster.aws_cloudwatch_log_group.ooniapi_services: Refreshing state... [id=ooni-ecs-group/oonitier1plus-ecs-cluster]
module.ooniapi_cluster.data.aws_ssm_parameter.ecs_optimized_ami: Reading...
module.ooniapi_oonimeasurements.aws_iam_role.ooniapi_service_task: Refreshing state... [id=ooniapi-service-oonimeasurements-task-role]
module.ooniapi_reverseproxy.aws_iam_role.ooniapi_service_task: Refreshing state... [id=ooniapi-service-reverseproxy-task-role]
data.aws_ssm_parameter.clickhouse_ooniprobe_url: Read complete after 0s [id=/oonidevops/secrets/clickhouse_ooniprobe_url]
data.aws_ssm_parameter.clickhouse_oonimeasurements_url: Reading...
module.ooniapi_cluster.data.aws_ssm_parameter.ecs_optimized_ami: Read complete after 0s [id=/aws/service/ecs/optimized-ami/amazon-linux-2023/recommended]
module.ooni_jumphost.data.aws_ssm_parameter.ubuntu_22_ami: Reading...
module.ooniapi_oonifindings_deployer.aws_iam_policy.codepipeline: Refreshing state... [id=arn:aws:iam::905418398257:policy/service-role/codepipeline-ooniapi-oonifindings]
module.ooniapi_cluster.aws_iam_role.container_host: Refreshing state... [id=ooniapi-ecs-cluster-container-host-role]
data.aws_ssm_parameter.jwt_secret_legacy: Reading...
module.ooniapi_ooniprobe_deployer.aws_iam_policy.codepipeline: Refreshing state... [id=arn:aws:iam::905418398257:policy/service-role/codepipeline-ooniapi-ooniprobe]
data.aws_ssm_parameter.clickhouse_oonimeasurements_url: Read complete after 0s [id=/oonidevops/secrets/clickhouse_oonimeasurements_url]
data.aws_availability_zones.available: Reading...
data.aws_ssm_parameter.clickhouse_oonimeasurements_test_url: Reading...
module.ooni_jumphost.data.aws_ssm_parameter.ubuntu_22_ami: Read complete after 0s [id=/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id]
module.oonidevops_github_user.aws_iam_policy.oonidevops_github: Refreshing state... [id=arn:aws:iam::905418398257:policy/oonidevops-github-policy]
module.ooniapi_user.aws_ses_email_identity.ooniapi: Refreshing state... [id=admin+dev@ooni.org]
module.ooniapi_ooniprobe.aws_iam_role.ooniapi_service_task: Refreshing state... [id=ooniapi-service-ooniprobe-task-role]
module.ooniapi_user.aws_secretsmanager_secret.aws_access_key_id: Refreshing state... [id=arn:aws:secretsmanager:eu-central-1:905418398257:secret:oonidevops/ooniapi_user/aws_access_key_id-EcXOBx]
data.aws_ssm_parameter.jwt_secret_legacy: Read complete after 0s [id=/oonidevops/secrets/ooni_services/jwt_secret_legacy]
module.ooniapi_user.aws_iam_user.ooniapi: Refreshing state... [id=oonidevops-ooniapi]
data.aws_ssm_parameter.clickhouse_oonimeasurements_test_url: Read complete after 0s [id=/oonidevops/secrets/clickhouse_oonimeasurements_test_url]
module.fastpath_builder.aws_iam_policy.codepipeline: Refreshing state... [id=arn:aws:iam::905418398257:policy/service-role/codepipeline-oonidkr-fastpath]
module.adm_iam_roles.aws_key_pair.oonidevops: Refreshing state... [id=oonidevops]
module.testlists_builder.aws_iam_policy.codepipeline: Refreshing state... [id=arn:aws:iam::905418398257:policy/service-role/codepipeline-oonidkr-testlists]
module.ooniapi_oonirun_deployer.aws_iam_policy.codepipeline: Refreshing state... [id=arn:aws:iam::905418398257:policy/service-role/codepipeline-ooniapi-oonirun]
module.ooniapi_oonimeasurements.aws_cloudwatch_log_group.ooniapi_service: Refreshing state... [id=ooni-ecs-group/ooniapi-service-oonimeasurements]
data.aws_ssm_parameter.clickhouse_oonirun_url: Reading...
module.ooniapi_testlists.data.aws_ssm_parameter.ubuntu_22_ami: Reading...
data.aws_ssm_parameter.clickhouse_oonirun_url: Read complete after 0s [id=/oonidevops/secrets/clickhouse_oonirun_url]
module.testlists_builder.data.aws_caller_identity.current: Reading...
module.ooniapi_testlists.data.aws_ssm_parameter.ubuntu_22_ami: Read complete after 0s [id=/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id]
module.ooniapi_reverseproxy_deployer.data.aws_caller_identity.current: Reading...
module.ooniapi_frontend.aws_s3_bucket.athena_results: Refreshing state... [id=ooni-athena-results-ff771094]
aws_s3_bucket.ooni_private_config_bucket: Refreshing state... [id=ooni-config-eu-central-1-f148ea7b]
data.aws_availability_zones.available: Read complete after 1s [id=eu-central-1]
aws_s3_bucket.oonith_codepipeline_bucket: Refreshing state... [id=codepipeline-oonith-eu-central-1-f148ea7b]
module.testlists_builder.data.aws_caller_identity.current: Read complete after 0s [id=905418398257]
module.ooniapi_oonirun.aws_cloudwatch_log_group.ooniapi_service: Refreshing state... [id=ooni-ecs-group/ooniapi-service-oonirun]
module.ooniapi_reverseproxy_deployer.data.aws_caller_identity.current: Read complete after 0s [id=905418398257]
data.aws_ssm_parameter.jwt_secret: Reading...
data.aws_ssm_parameter.account_id_hashing_key: Reading...
data.aws_ssm_parameter.jwt_secret: Read complete after 0s [id=/oonidevops/secrets/ooni_services/jwt_secret]
module.ooni_fastpath.module.ec2.data.aws_ssm_parameter.ubuntu_22_ami: Reading...
data.aws_ssm_parameter.account_id_hashing_key: Read complete after 0s [id=/oonidevops/secrets/ooni_services/account_id_hashing_key]
module.ooniapi_ooniauth.aws_iam_role.ooniapi_service_task: Refreshing state... [id=ooniapi-service-ooniauth-task-role]
module.ooni_monitoring.aws_iam_user.ooni_monitoring: Refreshing state... [id=oonidevops-monitoring]
module.ooni_fastpath.module.ec2.data.aws_ssm_parameter.ubuntu_22_ami: Read complete after 0s [id=/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id]
data.aws_ssm_parameter.anonc_secret_key: Reading...
module.ooniapi_oonirun_deployer.data.aws_caller_identity.current: Reading...
module.ooniapi_ooniauth_deployer.data.aws_caller_identity.current: Reading...
module.ooniapi_ooniauth.aws_cloudwatch_log_group.ooniapi_service: Refreshing state... [id=ooni-ecs-group/ooniapi-service-ooniauth]
module.ooniapi_oonirun_deployer.data.aws_caller_identity.current: Read complete after 0s [id=905418398257]
module.adm_iam_roles.aws_secretsmanager_secret.oonidevops_deploy_key: Refreshing state... [id=arn:aws:secretsmanager:eu-central-1:905418398257:secret:oonidevops/deploy_key-2ebqSe]
data.aws_ssm_parameter.anonc_secret_key: Read complete after 0s [id=/oonidevops/secrets/zkp/secret_key]
aws_acm_certificate.ooniapi_frontend: Refreshing state... [id=arn:aws:acm:eu-central-1:905418398257:certificate/c6d8f7a1-5b6d-4302-9aa6-92850ded970e]
module.ooniapi_ooniauth_deployer.data.aws_caller_identity.current: Read complete after 0s [id=905418398257]
module.ooniapi_oonifindings.aws_iam_role_policy.ooniapi_service_task: Refreshing state... [id=ooniapi-service-oonifindings-task-role:ooniapi-service-oonifindings-task-role]
module.ooniapi_ooniprobe_legacy.aws_iam_role_policy.ooniapi_service_task: Refreshing state... [id=ooniapi-service-ooniprobe-legacy-task-role:ooniapi-service-ooniprobe-legacy-task-role]
module.adm_iam_roles.aws_iam_role.oonidevops: Refreshing state... [id=oonidevops]
module.ooniapi_oonirun.aws_iam_role_policy.ooniapi_service_task: Refreshing state... [id=ooniapi-service-oonirun-task-role:ooniapi-service-oonirun-task-role]
module.oonidevops_github_user.aws_iam_access_key.oonidevops_github: Refreshing state... [id=AKIA5FTZELIYXDN55SMS]
module.ooniapi_ooniauth_deployer.aws_iam_role.codepipeline: Refreshing state... [id=codepipeline-ooniapi-ooniauth]
module.oonitier1plus_cluster.aws_iam_instance_profile.container_host: Refreshing state... [id=oonitier1plus-ecs-cluster]
module.oonitier1plus_cluster.aws_iam_role_policy.container_host: Refreshing state... [id=oonitier1plus-ecs-cluster-container-host-role:oonitier1plus-ecs-cluster-instance-role-policy]
aws_iam_instance_profile.monitoring_proxy_yace: Refreshing state... [id=oonidevops-dev-monitoring-proxy-yace]
aws_iam_role_policy.monitoring_proxy_yace: Refreshing state... [id=monitoring-proxy-yace:yace-cloudwatch-read]
module.ooniapi_reverseproxy_deployer.aws_iam_role.codepipeline: Refreshing state... [id=codepipeline-ooniapi-reverseproxy]
module.ooniapi_oonimeasurements_deployer.aws_iam_role.codepipeline: Refreshing state... [id=codepipeline-ooniapi-oonimeasurements]
module.ooniapi_cluster.aws_ecs_cluster.main: Refreshing state... [id=arn:aws:ecs:eu-central-1:905418398257:cluster/ooniapi-ecs-cluster]
module.ooniapi_oonimeasurements.aws_iam_role_policy.ooniapi_service_task: Refreshing state... [id=ooniapi-service-oonimeasurements-task-role:ooniapi-service-oonimeasurements-task-role]
module.ooniapi_reverseproxy.aws_iam_role_policy.ooniapi_service_task: Refreshing state... [id=ooniapi-service-reverseproxy-task-role:ooniapi-service-reverseproxy-task-role]
module.ooniapi_oonifindings_deployer.aws_iam_role.codepipeline: Refreshing state... [id=codepipeline-ooniapi-oonifindings]
module.oonitier1plus_cluster.aws_ecs_cluster.main: Refreshing state... [id=arn:aws:ecs:eu-central-1:905418398257:cluster/oonitier1plus-ecs-cluster]
module.oonidevops_github_user.aws_iam_user_policy_attachment.oonidevops_github: Refreshing state... [id=oonidevops-github-20240313195612421500000001]
module.ooniapi_ooniprobe_deployer.aws_iam_role.codepipeline: Refreshing state... [id=codepipeline-ooniapi-ooniprobe]
module.ooniapi_cluster.aws_iam_role_policy.container_host: Refreshing state... [id=ooniapi-ecs-cluster-container-host-role:ooniapi-ecs-cluster-instance-role-policy]
module.ooniapi_cluster.aws_iam_instance_profile.container_host: Refreshing state... [id=ooniapi-ecs-cluster]
module.ooniapi_user.aws_iam_user_policy.ooniapi: Refreshing state... [id=oonidevops-ooniapi:oonidevops-ooniapi-policy]
module.ooniapi_user.aws_iam_access_key.ooniapi: Refreshing state... [id=AKIA5FTZELIYSK2XEVOT]
module.ooniapi_ooniprobe.aws_iam_role_policy.ooniapi_service_task: Refreshing state... [id=ooniapi-service-ooniprobe-task-role:ooniapi-service-ooniprobe-task-role]
module.fastpath_builder.aws_iam_role.codepipeline: Refreshing state... [id=codepipeline-oonidkr-fastpath]
module.testlists_builder.aws_iam_role.codepipeline: Refreshing state... [id=codepipeline-oonidkr-testlists]
module.ooniapi_oonirun_deployer.aws_iam_role.codepipeline: Refreshing state... [id=codepipeline-ooniapi-oonirun]
module.ooni_monitoring.aws_iam_user_policy.ooni_monitoring: Refreshing state... [id=oonidevops-monitoring:oonidevops-monitoring-policy]
module.ooni_monitoring.aws_iam_access_key.ooni_monitoring: Refreshing state... [id=AKIA5FTZELIYWULOT65S]
module.ooniapi_ooniauth.aws_iam_role_policy.ooniapi_service_task: Refreshing state... [id=ooniapi-service-ooniauth-task-role:ooniapi-service-ooniauth-task-role]
module.ooniapi_reverseproxy.aws_ecs_task_definition.ooniapi_service: Refreshing state... [id=ooniapi-service-reverseproxy-td]
data.aws_secretsmanager_secret_version.ooniapi_user_secret_access_key: Reading...
module.ooniapi_frontend.aws_s3_bucket_ownership_controls.load_balancer_logs: Refreshing state... [id=lb-logs-eu-central-1-ff771094]
module.ooniapi_frontend.aws_s3_bucket_policy.alb_logs_policy: Refreshing state... [id=lb-logs-eu-central-1-ff771094]
module.ooniapi_frontend.aws_s3_bucket_lifecycle_configuration.load_balancer_logs: Refreshing state... [id=lb-logs-eu-central-1-ff771094]
module.oonidevops_github_user.aws_secretsmanager_secret_version.oonidevops_github: Refreshing state... [id=arn:aws:secretsmanager:eu-central-1:905418398257:secret:oonidevops/github_user/access_key_json-9JTJgd|terraform-20240519071250187000000004]
module.adm_iam_roles.aws_secretsmanager_secret_version.oonidevops_deploy_key: Refreshing state... [id=arn:aws:secretsmanager:eu-central-1:905418398257:secret:oonidevops/deploy_key-2ebqSe|terraform-20240925140131946100000002]
module.ooniapi_user.aws_secretsmanager_secret_version.aws_access_key_id: Refreshing state... [id=arn:aws:secretsmanager:eu-central-1:905418398257:secret:oonidevops/ooniapi_user/aws_access_key_id-EcXOBx|terraform-20240314200140918400000007]
module.ooniapi_user.aws_secretsmanager_secret_version.aws_secret_access_key: Refreshing state... [id=arn:aws:secretsmanager:eu-central-1:905418398257:secret:oonidevops/ooniapi_user/aws_secret_access_key-L0DQDr|terraform-20240314200140914600000006]
data.aws_secretsmanager_secret_version.ooniapi_user_secret_access_key: Read complete after 0s [id=arn:aws:secretsmanager:eu-central-1:905418398257:secret:oonidevops/ooniapi_user/aws_secret_access_key-L0DQDr|AWSCURRENT]
data.aws_secretsmanager_secret_version.ooniapi_user_access_key_id: Reading...
aws_route53_record.ooniapi_frontend_cert_validation["api.dev.ooni.io"]: Refreshing state... [id=Z055356431RGCLK3JXZDL__cd4729fc0c282e771d056e719a7bdf4f.api.dev.ooni.io._CNAME]
aws_route53_record.ooniapi_frontend_cert_validation["testlists.dev.ooni.io"]: Refreshing state... [id=Z055356431RGCLK3JXZDL__2b445be660c03a7eecbd5429f176ec99.testlists.dev.ooni.io._CNAME]
aws_route53_record.ooniapi_frontend_cert_validation["8.th.dev.ooni.io"]: Refreshing state... [id=Z055356431RGCLK3JXZDL__ef17825e5fd9713f596344bdd9626f5e.8.th.dev.ooni.io._CNAME]
aws_route53_record.ooniapi_frontend_cert_validation["oonirun.dev.ooni.io"]: Refreshing state... [id=Z055356431RGCLK3JXZDL__05c891caeb4509d4cd7f9c24d8b6dbd0.oonirun.dev.ooni.io._CNAME]
aws_route53_record.ooniapi_frontend_cert_validation["ooniprobe.dev.ooni.io"]: Refreshing state... [id=Z055356431RGCLK3JXZDL__a064be8aa084a037ff9fa5e3e541c87d.ooniprobe.dev.ooni.io._CNAME]
data.aws_secretsmanager_secret_version.ooniapi_user_access_key_id: Read complete after 0s [id=arn:aws:secretsmanager:eu-central-1:905418398257:secret:oonidevops/ooniapi_user/aws_access_key_id-EcXOBx|AWSCURRENT]
aws_route53_record.ooniapi_frontend_cert_validation["oonimeasurements.dev.ooni.io"]: Refreshing state... [id=Z055356431RGCLK3JXZDL__8fb10887c4ca7af87e33703c03c4c82e.oonimeasurements.dev.ooni.io._CNAME]
aws_route53_record.ooniapi_frontend_cert_validation["ooniauth.dev.ooni.io"]: Refreshing state... [id=Z055356431RGCLK3JXZDL__48cd4e71cee9930614228176b7deefb9.ooniauth.dev.ooni.io._CNAME]
module.ooniapi_oonifindings.aws_ecs_task_definition.ooniapi_service: Refreshing state... [id=ooniapi-service-oonifindings-td]
module.ooniapi_oonirun.aws_ecs_task_definition.ooniapi_service: Refreshing state... [id=ooniapi-service-oonirun-td]
module.ooni_monitoring.aws_ssm_parameter.ooni_monitoring_secret_key: Refreshing state... [id=/oonidevops/secrets/ooni_monitoring/secret_key]
module.ooni_monitoring.aws_ssm_parameter.ooni_monitoring_access_key: Refreshing state... [id=/oonidevops/secrets/ooni_monitoring/access_key]
aws_s3_bucket_ownership_controls.anonc_manifests: Refreshing state... [id=ooni-anoncreds-manifests-dev-eu-central-1]
aws_s3_bucket_versioning.anoncred_manifests_version: Refreshing state... [id=ooni-anoncreds-manifests-dev-eu-central-1]
aws_s3_bucket_public_access_block.anonc_manifests: Refreshing state... [id=ooni-anoncreds-manifests-dev-eu-central-1]
aws_s3_bucket_policy.anonc_manifests_policy: Refreshing state... [id=ooni-anoncreds-manifests-dev-eu-central-1]
aws_s3_object.test_manifest: Refreshing state... [id=test_manifest.json]
aws_s3_object.manifest: Refreshing state... [id=manifest.json]
module.ooniapi_frontend.aws_s3_bucket_lifecycle_configuration.athena_results: Refreshing state... [id=ooni-athena-results-ff771094]
module.ooniapi_frontend.aws_athena_database.load_balancer_logs: Refreshing state... [id=load_balancer_logs]
module.ooniapi_frontend.aws_athena_workgroup.ooni_workgroup: Refreshing state... [id=ooni-workgroup]
aws_iam_role_policy.ooniprobe_role: Refreshing state... [id=ooniapi-ecs-cluster-container-host-role:oonidevops-dev-task-role]
module.ooniapi_ooniauth.aws_ecs_task_definition.ooniapi_service: Refreshing state... [id=ooniapi-service-ooniauth-td]
aws_codestarconnections_connection.oonidevops: Refreshing state... [id=arn:aws:codestar-connections:eu-central-1:905418398257:connection/6bd492f6-c11d-43ec-92b0-24c47700d528]
data.aws_secretsmanager_secret_version.deploy_key: Reading...
aws_acm_certificate_validation.ooniapi_frontend: Refreshing state... [id=2026-03-02 13:38:05.483 +0000 UTC]
aws_s3_bucket_acl.anonc_manifests: Refreshing state... [id=ooni-anoncreds-manifests-dev-eu-central-1,public-read]
data.aws_secretsmanager_secret_version.deploy_key: Read complete after 0s [id=arn:aws:secretsmanager:eu-central-1:905418398257:secret:oonidevops/deploy_key-2ebqSe|AWSCURRENT]
module.terraform_state_backend.data.aws_region.current: Reading...
module.terraform_state_backend.data.aws_region.current: Read complete after 0s [id=eu-central-1]
digitalocean_ssh_key.oonidevops: Refreshing state... [id=58596998]
module.network.aws_vpc.main: Refreshing state... [id=vpc-0e382f3ad89286de9]
module.terraform_state_backend.aws_s3_bucket.default[0]: Refreshing state... [id=oonidevops-dev-terraform-state]
module.terraform_state_backend.data.aws_iam_policy_document.bucket_policy[0]: Reading...
module.terraform_state_backend.aws_dynamodb_table.with_server_side_encryption[0]: Refreshing state... [id=oonidevops-dev-terraform-state-lock]
module.terraform_state_backend.data.aws_iam_policy_document.bucket_policy[0]: Read complete after 0s [id=2666303363]
module.terraform_state_backend.data.aws_iam_policy_document.aggregated_policy[0]: Reading...
module.terraform_state_backend.data.aws_iam_policy_document.aggregated_policy[0]: Read complete after 0s [id=2666303363]
module.ooni_test_helpers_wc.digitalocean_droplet.ooni_th: Refreshing state... [id=593495708]
module.ooniapi_oonifindings_deployer.aws_iam_policy.codebuild: Refreshing state... [id=arn:aws:iam::905418398257:policy/service-role/codebuild-oonifindings-eu-central-1]
module.ooniapi_ooniprobe_deployer.aws_iam_policy.codebuild: Refreshing state... [id=arn:aws:iam::905418398257:policy/service-role/codebuild-ooniprobe-eu-central-1]
module.ooniapi_reverseproxy_deployer.aws_iam_policy.codebuild: Refreshing state... [id=arn:aws:iam::905418398257:policy/service-role/codebuild-reverseproxy-eu-central-1]
module.ooniapi_ooniauth_deployer.aws_iam_policy.codebuild: Refreshing state... [id=arn:aws:iam::905418398257:policy/service-role/codebuild-ooniauth-eu-central-1]
module.testlists_builder.aws_iam_policy.codebuild: Refreshing state... [id=arn:aws:iam::905418398257:policy/service-role/codebuild-testlists-eu-central-1]
module.ooniapi_oonirun_deployer.aws_iam_policy.codebuild: Refreshing state... [id=arn:aws:iam::905418398257:policy/service-role/codebuild-oonirun-eu-central-1]
module.fastpath_builder.aws_iam_policy.codebuild: Refreshing state... [id=arn:aws:iam::905418398257:policy/service-role/codebuild-fastpath-eu-central-1]
module.ooniapi_oonimeasurements_deployer.aws_iam_policy.codebuild: Refreshing state... [id=arn:aws:iam::905418398257:policy/service-role/codebuild-oonimeasurements-eu-central-1]
module.testlists_builder.aws_iam_role.codebuild: Refreshing state... [id=codebuild-oonidkr-testlists]
module.ooniapi_ooniauth_deployer.aws_iam_role.codebuild: Refreshing state... [id=codebuild-ooniapi-ooniauth]
module.ooniapi_reverseproxy_deployer.aws_iam_role.codebuild: Refreshing state... [id=codebuild-ooniapi-reverseproxy]
module.ooniapi_oonifindings_deployer.aws_iam_role.codebuild: Refreshing state... [id=codebuild-ooniapi-oonifindings]
module.ooniapi_ooniprobe_deployer.aws_iam_role.codebuild: Refreshing state... [id=codebuild-ooniapi-ooniprobe]
module.ooniapi_oonirun_deployer.aws_iam_role.codebuild: Refreshing state... [id=codebuild-ooniapi-oonirun]
module.fastpath_builder.aws_iam_role.codebuild: Refreshing state... [id=codebuild-oonidkr-fastpath]
module.ooniapi_oonimeasurements_deployer.aws_iam_role.codebuild: Refreshing state... [id=codebuild-ooniapi-oonimeasurements]
module.testlists_builder.aws_codebuild_project.oonidkr: Refreshing state... [id=arn:aws:codebuild:eu-central-1:905418398257:project/oonidkr-testlists]
module.ooniapi_ooniauth_deployer.aws_codebuild_project.ooniapi: Refreshing state... [id=arn:aws:codebuild:eu-central-1:905418398257:project/ooniapi-ooniauth]
module.ooniapi_reverseproxy_deployer.aws_codebuild_project.ooniapi: Refreshing state... [id=arn:aws:codebuild:eu-central-1:905418398257:project/ooniapi-reverseproxy]
module.ooniapi_ooniprobe_deployer.aws_codebuild_project.ooniapi: Refreshing state... [id=arn:aws:codebuild:eu-central-1:905418398257:project/ooniapi-ooniprobe]
module.ooniapi_oonifindings_deployer.aws_codebuild_project.ooniapi: Refreshing state... [id=arn:aws:codebuild:eu-central-1:905418398257:project/ooniapi-oonifindings]
module.ooniapi_oonirun_deployer.aws_codebuild_project.ooniapi: Refreshing state... [id=arn:aws:codebuild:eu-central-1:905418398257:project/ooniapi-oonirun]
module.fastpath_builder.aws_codebuild_project.oonidkr: Refreshing state... [id=arn:aws:codebuild:eu-central-1:905418398257:project/oonidkr-fastpath]
module.ooniapi_oonimeasurements_deployer.aws_codebuild_project.ooniapi: Refreshing state... [id=arn:aws:codebuild:eu-central-1:905418398257:project/ooniapi-oonimeasurements]
module.ooni_test_helpers_wc.aws_route53_record.ooni_th: Refreshing state... [id=Z055356431RGCLK3JXZDL_wc.th.dev.ooni.io_A]
module.testlists_builder.aws_codepipeline.oonidkr: Refreshing state... [id=oonidkr-testlists]
module.network.aws_internet_gateway.gw: Refreshing state... [id=igw-0c080e9b235ed29d1]
module.ooniapi_oonirun.aws_alb_target_group.ooniapi_service: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:targetgroup/OrunM-20250115122624347100000003/17e1664b99b708a5]
aws_security_group.elasticache_sg: Refreshing state... [id=sg-071f88ba24fb3d6ed]
module.ooniapi_ooniprobe_legacy.aws_alb_target_group.ooniapi_service: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:targetgroup/OproM-20260928101128763400000001/fce94d403b20acc9]
module.ooniapi_testlists.aws_security_group.ec2_sg: Refreshing state... [id=sg-031fd5ff750f4c94b]
module.ooniapi_reverseproxy.aws_alb_target_group.ooniapi_service: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:targetgroup/OrevM-20250115122624347000000002/32c2f9b4e4d3b8c4]
module.ooniapi_oonimeasurements.aws_alb_target_group.ooniapi_service: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:targetgroup/OmeaM-20250116160254864500000001/4d88cb32eb2f381c]
module.ooniapi_cluster.aws_security_group.web: Refreshing state... [id=sg-0187eedfe39538357]
module.ooniapi_testlists.aws_alb_target_group.ooni_ec2: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:targetgroup/ootstl20260302133704045300000001/4892b94962057fea]
module.ooni_monitoring_proxy.aws_security_group.ec2_sg: Refreshing state... [id=sg-00c4199ae6a658579]
module.ooni_monitoring_proxy.aws_alb_target_group.ooni_ec2: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:targetgroup/oomnpr20250423083217708600000002/90babad6f0c8b903]
module.fastpath_builder.aws_codepipeline.oonidkr: Refreshing state... [id=oonidkr-fastpath]
module.network.aws_route_table.private: Refreshing state... [id=rtb-011463437da96c77b]
module.network.aws_subnet.public[0]: Refreshing state... [id=subnet-0e7a4478be988463f]
module.network.aws_subnet.public[1]: Refreshing state... [id=subnet-0b18966cccfc9d5ef]
module.network.aws_route_table.public: Refreshing state... [id=rtb-0ccb0852e6a365a95]
module.network.aws_subnet.private[0]: Refreshing state... [id=subnet-09314a43ec89d6331]
module.network.aws_subnet.private[1]: Refreshing state... [id=subnet-0b899a7ad10406d06]
module.ooniapi_ooniauth.aws_alb_target_group.ooniapi_service: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:targetgroup/OautM-20250115122624347200000004/6e746a968782a49f]
module.ooniapi_testlists.aws_security_group_rule.ec2_sg_egress[0]: Refreshing state... [id=sgrule-3440521332]
module.ooniapi_testlists.aws_security_group_rule.ec2_sg_egress[1]: Refreshing state... [id=sgrule-1726180651]
module.ooni_fastpath.module.ec2.aws_alb_target_group.ooni_ec2: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:targetgroup/oofstp20260423110252291900000001/63d84df4b8ea92a9]
module.ooni_fastpath.module.ec2.aws_security_group.ec2_sg: Refreshing state... [id=sg-03507eea1e0e5bb0c]
module.ooniapi_ooniprobe.aws_alb_target_group.ooniapi_service: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:targetgroup/OproM-20250115122624346700000001/9f9264a4e53931d3]
module.ooni_jumphost.aws_alb_target_group.ooni_ec2: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:targetgroup/oojump20251216144624441200000002/52a32be88e2fcac5]
module.ooni_jumphost.aws_security_group.ec2_sg: Refreshing state... [id=sg-0ee46dd91ace739e1]
module.ooniapi_oonifindings.aws_alb_target_group.ooniapi_service: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:targetgroup/OfinM-20250115122624350600000005/ad715c6e26dd616c]
module.ooni_clickhouse_proxy.aws_security_group.ec2_sg: Refreshing state... [id=sg-0903c108a44c922a5]
module.ooni_clickhouse_proxy.aws_alb_target_group.ooni_ec2: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:targetgroup/oockpr20250116192249626700000002/2e9dada4dd22c268]
module.oonitier1plus_cluster.aws_security_group.web: Refreshing state... [id=sg-07090c14e80a5def2]
module.ooni_monitoring_proxy.aws_security_group_rule.ec2_sg_ingress[3]: Refreshing state... [id=sgrule-1109732603]
module.ooni_monitoring_proxy.aws_security_group_rule.ec2_sg_ingress[0]: Refreshing state... [id=sgrule-2756751855]
module.ooni_monitoring_proxy.aws_security_group_rule.ec2_sg_ingress[1]: Refreshing state... [id=sgrule-316337242]
module.ooni_monitoring_proxy.aws_security_group_rule.ec2_sg_ingress[2]: Refreshing state... [id=sgrule-2383513485]
module.ooni_monitoring_proxy.aws_security_group_rule.ec2_sg_egress[0]: Refreshing state... [id=sgrule-4288788045]
module.ooni_monitoring_proxy.aws_security_group_rule.ec2_sg_egress[1]: Refreshing state... [id=sgrule-3806784481]
module.terraform_state_backend.aws_s3_bucket_server_side_encryption_configuration.default[0]: Refreshing state... [id=oonidevops-dev-terraform-state]
module.terraform_state_backend.aws_s3_bucket_versioning.default[0]: Refreshing state... [id=oonidevops-dev-terraform-state]
module.terraform_state_backend.aws_s3_bucket_public_access_block.default[0]: Refreshing state... [id=oonidevops-dev-terraform-state]
module.ooniapi_reverseproxy.aws_ecs_service.ooniapi_service: Refreshing state... [id=arn:aws:ecs:eu-central-1:905418398257:service/ooniapi-ecs-cluster/ooniapi-service-reverseproxy]
module.ooniapi_oonirun.aws_ecs_service.ooniapi_service: Refreshing state... [id=arn:aws:ecs:eu-central-1:905418398257:service/ooniapi-ecs-cluster/ooniapi-service-oonirun]
module.network.aws_route_table_association.public[0]: Refreshing state... [id=rtbassoc-0dbd7fb16801ee049]
module.network.aws_route_table_association.public[1]: Refreshing state... [id=rtbassoc-08ab18165bf481054]
module.network.aws_route_table_association.private[0]: Refreshing state... [id=rtbassoc-0e7933e6b804ff2c1]
module.network.aws_route_table_association.private[1]: Refreshing state... [id=rtbassoc-0c9cc0f117ef15fe7]
module.ooni_fastpath.module.ec2.aws_security_group_rule.ec2_sg_egress[1]: Refreshing state... [id=sgrule-2098199074]
module.ooni_fastpath.module.ec2.aws_security_group_rule.ec2_sg_egress[0]: Refreshing state... [id=sgrule-3915082054]
module.ooni_jumphost.aws_security_group_rule.ec2_sg_egress[1]: Refreshing state... [id=sgrule-780291060]
module.ooni_jumphost.aws_security_group_rule.ec2_sg_egress[0]: Refreshing state... [id=sgrule-844844036]
module.ooniapi_ooniauth.aws_ecs_service.ooniapi_service: Refreshing state... [id=arn:aws:ecs:eu-central-1:905418398257:service/ooniapi-ecs-cluster/ooniapi-service-ooniauth]
module.ooni_clickhouse_proxy.aws_security_group_rule.ec2_sg_egress[0]: Refreshing state... [id=sgrule-1099643652]
module.ooni_clickhouse_proxy.aws_security_group_rule.ec2_sg_egress[1]: Refreshing state... [id=sgrule-1281654482]
module.ooniapi_oonifindings.aws_ecs_service.ooniapi_service: Refreshing state... [id=arn:aws:ecs:eu-central-1:905418398257:service/ooniapi-ecs-cluster/ooniapi-service-oonifindings]
module.terraform_state_backend.aws_s3_bucket_policy.default[0]: Refreshing state... [id=oonidevops-dev-terraform-state]
aws_elasticache_serverless_cache.ooniapi: Refreshing state... [id=ooniapi-dev-cache]
aws_security_group_rule.elasticache_sg_rule: Refreshing state... [id=sgrule-1589925589]
module.oonipg.aws_db_subnet_group.pg: Refreshing state... [id=ooni-tier0-postgres-dbsng]
module.ooni_clickhouse_proxy.aws_launch_template.ooni_ec2: Refreshing state... [id=lt-0855bc6373ff4c75b]
module.ooniapi_testlists.aws_launch_template.ooni_ec2: Refreshing state... [id=lt-01d0fc9e7bff14cac]
module.ooni_jumphost.aws_launch_template.ooni_ec2: Refreshing state... [id=lt-093e415469bef9855]
module.oonipg.aws_security_group.pg: Refreshing state... [id=sg-005ca579eb9c08cda]
module.ooni_monitoring_proxy.aws_launch_template.ooni_ec2: Refreshing state... [id=lt-0c9dddb576a4f71a3]
module.oonitier1plus_cluster.aws_security_group.container_host: Refreshing state... [id=sg-0e74a206196727883]
module.ooniapi_cluster.aws_security_group.container_host: Refreshing state... [id=sg-0aa6a97400b619de3]
module.ooniapi_frontend.aws_alb.ooniapi: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:loadbalancer/app/ooni-api-frontend/4a50f3dd46584390]
module.terraform_state_backend.time_sleep.wait_for_aws_s3_bucket_settings[0]: Refreshing state... [id=2024-03-10T15:06:17Z]
module.ooni_fastpath.module.ec2.aws_launch_template.ooni_ec2: Refreshing state... [id=lt-04f17f1d49bea5597]
module.ooniapi_reverseproxy_deployer.aws_codepipeline.ooniapi: Refreshing state... [id=ooniapi-reverseproxy]
module.oonitier1plus_cluster.aws_launch_template.container_host: Refreshing state... [id=lt-0eb432177b5a9f2aa]
module.terraform_state_backend.aws_s3_bucket_ownership_controls.default[0]: Refreshing state... [id=oonidevops-dev-terraform-state]
module.ooniapi_oonirun_deployer.aws_codepipeline.ooniapi: Refreshing state... [id=ooniapi-oonirun]
module.ooni_clickhouse_proxy.aws_instance.ooni_ec2: Refreshing state... [id=i-0757310827bc642fa]
module.ooniapi_testlists.aws_instance.ooni_ec2: Refreshing state... [id=i-07217491c5a2f9d77]
module.ooni_jumphost.aws_instance.ooni_ec2: Refreshing state... [id=i-0ab8df111ab0fa5a3]
module.ooni_monitoring_proxy.aws_instance.ooni_ec2: Refreshing state... [id=i-067b337ada2d9cc00]
module.ooniapi_cluster.aws_launch_template.container_host: Refreshing state... [id=lt-0e328a8671f870c64]
module.ooniapi_oonifindings_deployer.aws_codepipeline.ooniapi: Refreshing state... [id=ooniapi-oonifindings]
module.ooniapi_ooniauth_deployer.aws_codepipeline.ooniapi: Refreshing state... [id=ooniapi-ooniauth]
module.ooni_fastpath.module.ec2.aws_instance.ooni_ec2: Refreshing state... [id=i-0eeb4d9320fc9dd3a]
module.ooniapi_frontend.aws_alb_listener.ooniapi_listener_https: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45]
module.ooniapi_frontend.aws_alb_listener.ooniapi_listener_http: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener/app/ooni-api-frontend/4a50f3dd46584390/664a34cfb30f72e8]
module.oonipg.aws_db_instance.pg: Refreshing state... [id=db-27N7Q6XIBNASFCOXN4N7C762L4]
module.oonitier1plus_cluster.aws_autoscaling_group.container_host: Refreshing state... [id=oonitier1plus-ecs-cluster20251022145227179100000007]
aws_route53_record.ooniapi_frontend_main: Refreshing state... [id=Z055356431RGCLK3JXZDL_api.dev.ooni.io_A]
aws_route53_record.ooniapi_frontend_alt["8.th.dev.ooni.io"]: Refreshing state... [id=Z055356431RGCLK3JXZDL_8.th.dev.ooni.io_A]
aws_route53_record.ooniapi_frontend_alt["ooniauth.dev.ooni.io"]: Refreshing state... [id=Z055356431RGCLK3JXZDL_ooniauth.dev.ooni.io_A]
aws_route53_record.ooniapi_frontend_alt["oonimeasurements.dev.ooni.io"]: Refreshing state... [id=Z055356431RGCLK3JXZDL_oonimeasurements.dev.ooni.io_A]
aws_route53_record.ooniapi_frontend_alt["ooniprobe.dev.ooni.io"]: Refreshing state... [id=Z055356431RGCLK3JXZDL_ooniprobe.dev.ooni.io_A]
aws_route53_record.ooniapi_frontend_alt["oonirun.dev.ooni.io"]: Refreshing state... [id=Z055356431RGCLK3JXZDL_oonirun.dev.ooni.io_A]
aws_route53_record.ooniapi_frontend_alt["testlists.dev.ooni.io"]: Refreshing state... [id=Z055356431RGCLK3JXZDL_testlists.dev.ooni.io_A]
module.ooniapi_cluster.aws_autoscaling_group.container_host: Refreshing state... [id=ooniapi-ecs-cluster20240310192644083800000003]
module.ooniapi_frontend.aws_alb_listener_rule.ooniapi_th: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/775cd6d0dc062fd3]
module.ooniapi_frontend.aws_lb_listener_rule.route["oonimeasurements_rule_2"]: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/e6dbe09be108b001]
module.ooniapi_frontend.aws_lb_listener_rule.route["oonimeasurements_rule_host"]: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/f3d75d5d93fd6903]
module.ooniapi_frontend.aws_lb_listener_rule.route["ooniauth_rule"]: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/178511e1b6ae89c5]
module.ooniapi_frontend.aws_lb_listener_rule.route["oonimeasurements_rule_1"]: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/1cf3d6a7a694eec9]
module.ooniapi_frontend.aws_lb_listener_rule.route["ooniprobe_rule"]: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/82069bb29bca6af1]
module.ooniapi_frontend.aws_lb_listener_rule.route["ooniprobe_rule_3_no_version"]: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/43cddc54b665d441]
module.ooniapi_frontend.aws_lb_listener_rule.route["oonimeasurements_rule_3"]: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/48b97ed405c9c6cc]
module.ooniapi_frontend.aws_lb_listener_rule.route["ooniprobe_rule_4"]: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/6026e8ac5ba962ec]
module.ooniapi_frontend.aws_lb_listener_rule.route["oonirun_rule_host"]: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/9af03e886f8803f2]
module.ooniapi_frontend.aws_lb_listener_rule.route["oonirun_rule"]: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/cc29701b6ed6aa2e]
module.ooniapi_frontend.aws_lb_listener_rule.route["ooniauth_rule_host"]: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/f4bf91203c7ca76e]
module.ooniapi_frontend.aws_lb_listener_rule.route["ooniprobe_rule_3_legacy_version"]: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/0f857b3b0593e95e]
module.ooniapi_frontend.aws_lb_listener_rule.route["oonifindings_rule"]: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/36d49e835c0b81c5]
module.ooniapi_frontend.aws_lb_listener_rule.route["ooniprobe_rule_2"]: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/5f2394ffa8b71f98]
module.ooniapi_frontend.aws_lb_listener_rule.route["oonifindings_rule_host"]: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/54cda6e694a0103f]
module.ooniapi_frontend.aws_lb_listener_rule.route["testlists_rule"]: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/2864c2a72dfd4018]
module.ooniapi_frontend.aws_lb_listener_rule.route["ooniprobe_rule_3_current_version"]: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/0210f85a9024bd06]
module.ooniapi_frontend.aws_lb_listener_rule.route["ooniprobe_rule_host"]: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/583471b0bdc1c388]
module.oonitier1plus_cluster.aws_ecs_capacity_provider.capacity_provider: Refreshing state... [id=arn:aws:ecs:eu-central-1:905418398257:capacity-provider/oonitier1plus-ecs-cluster-capacity-provider]
module.ooniapi_cluster.aws_ecs_capacity_provider.capacity_provider: Refreshing state... [id=arn:aws:ecs:eu-central-1:905418398257:capacity-provider/ooniapi-ecs-cluster-capacity-provider]
aws_route53_record.postgres_dns: Refreshing state... [id=Z091407123AEJO90Z3H6D_postgres.dev.ooni.nu_CNAME]
data.aws_secretsmanager_secret_version.pg_login: Reading...
module.oonitier1plus_cluster.aws_ecs_cluster_capacity_providers.cluster_capacity_providers: Refreshing state... [id=oonitier1plus-ecs-cluster]
module.ooniapi_cluster.aws_ecs_cluster_capacity_providers.cluster_capacity_providers: Refreshing state... [id=ooniapi-ecs-cluster]
module.ooni_jumphost.aws_lb_target_group_attachment.oonibackend_proxy: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:targetgroup/oojump20251216144624441200000002/52a32be88e2fcac5-20251216144651363600000006]
aws_route53_record.jumphost_alias: Refreshing state... [id=Z055356431RGCLK3JXZDL_jumphost.dev.ooni.io_CNAME]
data.aws_secretsmanager_secret_version.pg_login: Read complete after 0s [id=arn:aws:secretsmanager:eu-central-1:905418398257:secret:rds!db-5fe27151-3a37-44e0-a5bd-3517363fa2e8-BDI0KI|AWSCURRENT]
module.ooniapi_testlists.aws_lb_target_group_attachment.oonibackend_proxy: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:targetgroup/ootstl20260302133704045300000001/4892b94962057fea-20260302133730682200000008]
aws_route53_record.testlists_alias: Refreshing state... [id=Z055356431RGCLK3JXZDL_testlist-ec2.dev.ooni.io_CNAME]
aws_secretsmanager_secret_version.oonipg_url: Refreshing state... [id=arn:aws:secretsmanager:eu-central-1:905418398257:secret:oonidevops/ooni-tier0-postgres/postgresql_url-w62CTZ|terraform-20260923103643766700000007]
module.ooni_clickhouse_proxy.aws_lb_target_group_attachment.oonibackend_proxy: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:targetgroup/oockpr20250116192249626700000002/2e9dada4dd22c268-20260227131827648300000002]
aws_route53_record.clickhouse_proxy_alias: Refreshing state... [id=Z055356431RGCLK3JXZDL_clickhouseproxy.dev.ooni.io_CNAME]
module.ooni_monitoring_proxy.aws_lb_target_group_attachment.oonibackend_proxy: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:targetgroup/oomnpr20250423083217708600000002/90babad6f0c8b903-20250423083239704200000006]
aws_route53_record.monitoring_proxy_alias: Refreshing state... [id=Z055356431RGCLK3JXZDL_monitoringproxy.dev.ooni.io_CNAME]
module.ooniapi_testlists.aws_security_group_rule.ec2_sg_ingress[3]: Refreshing state... [id=sgrule-2701186690]
module.ooniapi_testlists.aws_security_group_rule.ec2_sg_ingress[1]: Refreshing state... [id=sgrule-606204409]
module.ooniapi_testlists.aws_security_group_rule.ec2_sg_ingress[0]: Refreshing state... [id=sgrule-2460724300]
module.ooniapi_testlists.aws_security_group_rule.ec2_sg_ingress[2]: Refreshing state... [id=sgrule-14456781]
module.ooni_jumphost.aws_security_group_rule.ec2_sg_ingress[0]: Refreshing state... [id=sgrule-4143979435]
module.ooni_jumphost.aws_security_group_rule.ec2_sg_ingress[1]: Refreshing state... [id=sgrule-1099580958]
module.ooni_jumphost.aws_security_group_rule.ec2_sg_ingress[2]: Refreshing state... [id=sgrule-1528835277]
module.ooni_fastpath.module.ec2.aws_lb_target_group_attachment.oonibackend_proxy: Refreshing state... [id=arn:aws:elasticloadbalancing:eu-central-1:905418398257:targetgroup/oofstp20260423110252291900000001/63d84df4b8ea92a9-20260423110318998700000007]
module.ooni_fastpath.module.ec2.aws_security_group_rule.ec2_sg_ingress[1]: Refreshing state... [id=sgrule-2656646093]
module.ooni_fastpath.module.ec2.aws_security_group_rule.ec2_sg_ingress[2]: Refreshing state... [id=sgrule-3549062282]
module.ooni_fastpath.module.ec2.aws_security_group_rule.ec2_sg_ingress[3]: Refreshing state... [id=sgrule-3011210381]
module.ooni_fastpath.module.ec2.aws_security_group_rule.ec2_sg_ingress[4]: Refreshing state... [id=sgrule-858198288]
module.ooni_fastpath.module.ec2.aws_security_group_rule.ec2_sg_ingress[0]: Refreshing state... [id=sgrule-4279797320]
module.ooni_fastpath.aws_route53_record.fastpath_alias: Refreshing state... [id=Z055356431RGCLK3JXZDL_fastpath.dev.ooni.io_CNAME]
module.ooni_clickhouse_proxy.aws_security_group_rule.ec2_sg_ingress[2]: Refreshing state... [id=sgrule-3265385170]
module.ooni_clickhouse_proxy.aws_security_group_rule.ec2_sg_ingress[4]: Refreshing state... [id=sgrule-3520426823]
module.ooni_clickhouse_proxy.aws_security_group_rule.ec2_sg_ingress[3]: Refreshing state... [id=sgrule-3953292375]
module.ooni_clickhouse_proxy.aws_security_group_rule.ec2_sg_ingress[0]: Refreshing state... [id=sgrule-1921217342]
module.ooni_clickhouse_proxy.aws_security_group_rule.ec2_sg_ingress[1]: Refreshing state... [id=sgrule-3288936075]
module.ooniapi_ooniprobe_legacy.aws_ecs_task_definition.ooniapi_service: Refreshing state... [id=ooniapi-service-ooniprobe-legacy-td]
module.ooniapi_ooniprobe.aws_ecs_task_definition.ooniapi_service: Refreshing state... [id=ooniapi-service-ooniprobe-td]
module.ooniapi_ooniprobe_legacy.aws_ecs_service.ooniapi_service: Refreshing state... [id=arn:aws:ecs:eu-central-1:905418398257:service/ooniapi-ecs-cluster/ooniapi-service-ooniprobe-legacy]
module.ooniapi_ooniprobe.aws_ecs_service.ooniapi_service: Refreshing state... [id=arn:aws:ecs:eu-central-1:905418398257:service/ooniapi-ecs-cluster/ooniapi-service-ooniprobe]
module.ooniapi_ooniprobe_deployer.aws_codepipeline.ooniapi: Refreshing state... [id=ooniapi-ooniprobe]

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  + create
  ~ update in-place
  - destroy
-/+ destroy and then create replacement

Terraform planned the following actions, but then encountered a problem:

  # aws_s3_bucket.ooniapi_deploy will be created
  + resource "aws_s3_bucket" "ooniapi_deploy" {
      + acceleration_status         = (known after apply)
      + acl                         = (known after apply)
      + arn                         = (known after apply)
      + bucket                      = "ooniapi-deploy-eu-central-1-f148ea7b"
      + bucket_domain_name          = (known after apply)
      + bucket_prefix               = (known after apply)
      + bucket_regional_domain_name = (known after apply)
      + force_destroy               = false
      + hosted_zone_id              = (known after apply)
      + id                          = (known after apply)
      + object_lock_enabled         = (known after apply)
      + policy                      = (known after apply)
      + region                      = (known after apply)
      + request_payer               = (known after apply)
      + tags                        = {
          + "Environment" = "dev"
          + "Name"        = "oonidevops-dev"
          + "Repository"  = "https://github.com/ooni/devops"
        }
      + tags_all                    = {
          + "Environment" = "dev"
          + "Name"        = "oonidevops-dev"
          + "Repository"  = "https://github.com/ooni/devops"
        }
      + website_domain              = (known after apply)
      + website_endpoint            = (known after apply)

      + cors_rule (known after apply)

      + grant (known after apply)

      + lifecycle_rule (known after apply)

      + logging (known after apply)

      + object_lock_configuration (known after apply)

      + replication_configuration (known after apply)

      + server_side_encryption_configuration (known after apply)

      + versioning (known after apply)

      + website (known after apply)
    }

  # aws_secretsmanager_secret.ooniapi_deploy_service_secrets["ooniauth"] will be created
  + resource "aws_secretsmanager_secret" "ooniapi_deploy_service_secrets" {
      + arn                            = (known after apply)
      + force_overwrite_replica_secret = false
      + id                             = (known after apply)
      + name                           = "oonidevops/ooniapi/ooniauth/service_secrets"
      + name_prefix                    = (known after apply)
      + policy                         = (known after apply)
      + recovery_window_in_days        = 30
      + tags                           = {
          + "Environment" = "dev"
          + "Name"        = "oonidevops-dev"
          + "Repository"  = "https://github.com/ooni/devops"
        }
      + tags_all                       = {
          + "Environment" = "dev"
          + "Name"        = "oonidevops-dev"
          + "Repository"  = "https://github.com/ooni/devops"
        }

      + replica (known after apply)
    }

  # aws_secretsmanager_secret.ooniapi_deploy_service_secrets["oonifindings"] will be created
  + resource "aws_secretsmanager_secret" "ooniapi_deploy_service_secrets" {
      + arn                            = (known after apply)
      + force_overwrite_replica_secret = false
      + id                             = (known after apply)
      + name                           = "oonidevops/ooniapi/oonifindings/service_secrets"
      + name_prefix                    = (known after apply)
      + policy                         = (known after apply)
      + recovery_window_in_days        = 30
      + tags                           = {
          + "Environment" = "dev"
          + "Name"        = "oonidevops-dev"
          + "Repository"  = "https://github.com/ooni/devops"
        }
      + tags_all                       = {
          + "Environment" = "dev"
          + "Name"        = "oonidevops-dev"
          + "Repository"  = "https://github.com/ooni/devops"
        }

      + replica (known after apply)
    }

  # aws_secretsmanager_secret.ooniapi_deploy_service_secrets["oonimeasurements"] will be created
  + resource "aws_secretsmanager_secret" "ooniapi_deploy_service_secrets" {
      + arn                            = (known after apply)
      + force_overwrite_replica_secret = false
      + id                             = (known after apply)
      + name                           = "oonidevops/ooniapi/oonimeasurements/service_secrets"
      + name_prefix                    = (known after apply)
      + policy                         = (known after apply)
      + recovery_window_in_days        = 30
      + tags                           = {
          + "Environment" = "dev"
          + "Name"        = "oonidevops-dev"
          + "Repository"  = "https://github.com/ooni/devops"
        }
      + tags_all                       = {
          + "Environment" = "dev"
          + "Name"        = "oonidevops-dev"
          + "Repository"  = "https://github.com/ooni/devops"
        }

      + replica (known after apply)
    }

  # aws_secretsmanager_secret.ooniapi_deploy_service_secrets["ooniprobe"] will be created
  + resource "aws_secretsmanager_secret" "ooniapi_deploy_service_secrets" {
      + arn                            = (known after apply)
      + force_overwrite_replica_secret = false
      + id                             = (known after apply)
      + name                           = "oonidevops/ooniapi/ooniprobe/service_secrets"
      + name_prefix                    = (known after apply)
      + policy                         = (known after apply)
      + recovery_window_in_days        = 30
      + tags                           = {
          + "Environment" = "dev"
          + "Name"        = "oonidevops-dev"
          + "Repository"  = "https://github.com/ooni/devops"
        }
      + tags_all                       = {
          + "Environment" = "dev"
          + "Name"        = "oonidevops-dev"
          + "Repository"  = "https://github.com/ooni/devops"
        }

      + replica (known after apply)
    }

  # aws_secretsmanager_secret.ooniapi_deploy_service_secrets["oonirun"] will be created
  + resource "aws_secretsmanager_secret" "ooniapi_deploy_service_secrets" {
      + arn                            = (known after apply)
      + force_overwrite_replica_secret = false
      + id                             = (known after apply)
      + name                           = "oonidevops/ooniapi/oonirun/service_secrets"
      + name_prefix                    = (known after apply)
      + policy                         = (known after apply)
      + recovery_window_in_days        = 30
      + tags                           = {
          + "Environment" = "dev"
          + "Name"        = "oonidevops-dev"
          + "Repository"  = "https://github.com/ooni/devops"
        }
      + tags_all                       = {
          + "Environment" = "dev"
          + "Name"        = "oonidevops-dev"
          + "Repository"  = "https://github.com/ooni/devops"
        }

      + replica (known after apply)
    }

  # aws_secretsmanager_secret.ooniapi_deploy_service_secrets["reverseproxy"] will be created
  + resource "aws_secretsmanager_secret" "ooniapi_deploy_service_secrets" {
      + arn                            = (known after apply)
      + force_overwrite_replica_secret = false
      + id                             = (known after apply)
      + name                           = "oonidevops/ooniapi/reverseproxy/service_secrets"
      + name_prefix                    = (known after apply)
      + policy                         = (known after apply)
      + recovery_window_in_days        = 30
      + tags                           = {
          + "Environment" = "dev"
          + "Name"        = "oonidevops-dev"
          + "Repository"  = "https://github.com/ooni/devops"
        }
      + tags_all                       = {
          + "Environment" = "dev"
          + "Name"        = "oonidevops-dev"
          + "Repository"  = "https://github.com/ooni/devops"
        }

      + replica (known after apply)
    }

  # aws_secretsmanager_secret.ooniapi_deploy_ssh_key will be created
  + resource "aws_secretsmanager_secret" "ooniapi_deploy_ssh_key" {
      + arn                            = (known after apply)
      + force_overwrite_replica_secret = false
      + id                             = (known after apply)
      + name                           = "oonidevops/ooniapi/deploy_ssh_key"
      + name_prefix                    = (known after apply)
      + policy                         = (known after apply)
      + recovery_window_in_days        = 30
      + tags                           = {
          + "Environment" = "dev"
          + "Name"        = "oonidevops-dev"
          + "Repository"  = "https://github.com/ooni/devops"
        }
      + tags_all                       = {
          + "Environment" = "dev"
          + "Name"        = "oonidevops-dev"
          + "Repository"  = "https://github.com/ooni/devops"
        }

      + replica (known after apply)
    }

  # aws_secretsmanager_secret_version.ooniapi_deploy_service_secrets["ooniauth"] will be created
  + resource "aws_secretsmanager_secret_version" "ooniapi_deploy_service_secrets" {
      + arn            = (known after apply)
      + id             = (known after apply)
      + secret_id      = (known after apply)
      + secret_string  = (sensitive value)
      + version_id     = (known after apply)
      + version_stages = (known after apply)
    }

  # aws_secretsmanager_secret_version.ooniapi_deploy_service_secrets["oonifindings"] will be created
  + resource "aws_secretsmanager_secret_version" "ooniapi_deploy_service_secrets" {
      + arn            = (known after apply)
      + id             = (known after apply)
      + secret_id      = (known after apply)
      + secret_string  = (sensitive value)
      + version_id     = (known after apply)
      + version_stages = (known after apply)
    }

  # aws_secretsmanager_secret_version.ooniapi_deploy_service_secrets["oonimeasurements"] will be created
  + resource "aws_secretsmanager_secret_version" "ooniapi_deploy_service_secrets" {
      + arn            = (known after apply)
      + id             = (known after apply)
      + secret_id      = (known after apply)
      + secret_string  = (sensitive value)
      + version_id     = (known after apply)
      + version_stages = (known after apply)
    }

  # aws_secretsmanager_secret_version.ooniapi_deploy_service_secrets["ooniprobe"] will be created
  + resource "aws_secretsmanager_secret_version" "ooniapi_deploy_service_secrets" {
      + arn            = (known after apply)
      + id             = (known after apply)
      + secret_id      = (known after apply)
      + secret_string  = (sensitive value)
      + version_id     = (known after apply)
      + version_stages = (known after apply)
    }

  # aws_secretsmanager_secret_version.ooniapi_deploy_service_secrets["oonirun"] will be created
  + resource "aws_secretsmanager_secret_version" "ooniapi_deploy_service_secrets" {
      + arn            = (known after apply)
      + id             = (known after apply)
      + secret_id      = (known after apply)
      + secret_string  = (sensitive value)
      + version_id     = (known after apply)
      + version_stages = (known after apply)
    }

  # aws_secretsmanager_secret_version.ooniapi_deploy_service_secrets["reverseproxy"] will be created
  + resource "aws_secretsmanager_secret_version" "ooniapi_deploy_service_secrets" {
      + arn            = (known after apply)
      + id             = (known after apply)
      + secret_id      = (known after apply)
      + secret_string  = (sensitive value)
      + version_id     = (known after apply)
      + version_stages = (known after apply)
    }

  # aws_secretsmanager_secret_version.ooniapi_deploy_ssh_key will be created
  + resource "aws_secretsmanager_secret_version" "ooniapi_deploy_ssh_key" {
      + arn            = (known after apply)
      + id             = (known after apply)
      + secret_id      = (known after apply)
      + secret_string  = (sensitive value)
      + version_id     = (known after apply)
      + version_stages = (known after apply)
    }

  # aws_secretsmanager_secret_version.oonipg_url must be replaced
-/+ resource "aws_secretsmanager_secret_version" "oonipg_url" {
      ~ arn            = "arn:aws:secretsmanager:eu-central-1:905418398257:secret:oonidevops/ooni-tier0-postgres/postgresql_url-w62CTZ" -> (known after apply)
      ~ id             = "arn:aws:secretsmanager:eu-central-1:905418398257:secret:oonidevops/ooni-tier0-postgres/postgresql_url-w62CTZ|terraform-20260923103643766700000007" -> (known after apply)
      ~ secret_string  = (sensitive value) # forces replacement
      ~ version_id     = "terraform-20260923103643766700000007" -> (known after apply)
      ~ version_stages = [
          - "AWSCURRENT",
        ] -> (known after apply)
        # (2 unchanged attributes hidden)
    }

  # module.ooni_clickhouse_proxy.aws_launch_template.ooni_ec2 will be updated in-place
  ~ resource "aws_launch_template" "ooni_ec2" {
        id                                   = "lt-0855bc6373ff4c75b"
      ~ image_id                             = (sensitive value)
      ~ latest_version                       = 36 -> (known after apply)
        name                                 = "oonickprx-tmpl-20250116192253018000000003"
        tags                                 = {}
        # (16 unchanged attributes hidden)

        # (2 unchanged blocks hidden)
    }

  # module.ooni_clickhouse_proxy.aws_security_group_rule.ec2_sg_ingress[2] must be replaced
-/+ resource "aws_security_group_rule" "ec2_sg_ingress" {
      ~ cidr_blocks              = [ # forces replacement
            # (5 unchanged elements hidden)
            "18.199.92.80/32",
          + "65.108.192.151/32",
        ]
      ~ id                       = "sgrule-3265385170" -> (known after apply)
      + security_group_rule_id   = (known after apply)
      + source_security_group_id = (known after apply)
        # (6 unchanged attributes hidden)
    }

  # module.ooni_jumphost.aws_launch_template.ooni_ec2 will be updated in-place
  ~ resource "aws_launch_template" "ooni_ec2" {
        id                                   = "lt-093e415469bef9855"
      ~ image_id                             = (sensitive value)
      ~ latest_version                       = 16 -> (known after apply)
        name                                 = "jumphost-tmpl-20251216144627050000000003"
        tags                                 = {}
        # (16 unchanged attributes hidden)

        # (2 unchanged blocks hidden)
    }

  # module.ooni_monitoring_proxy.aws_launch_template.ooni_ec2 will be updated in-place
  ~ resource "aws_launch_template" "ooni_ec2" {
        id                                   = "lt-0c9dddb576a4f71a3"
      ~ image_id                             = (sensitive value)
      ~ latest_version                       = 32 -> (known after apply)
        name                                 = "oonimnprx-tmpl-20250423083219772900000003"
        tags                                 = {}
        # (16 unchanged attributes hidden)

        # (3 unchanged blocks hidden)
    }

  # module.ooniapi_cluster.aws_launch_template.container_host will be updated in-place
  ~ resource "aws_launch_template" "container_host" {
      ~ default_version                      = 99 -> (known after apply)
        id                                   = "lt-0e328a8671f870c64"
      ~ image_id                             = (sensitive value)
      ~ latest_version                       = 99 -> (known after apply)
        name                                 = "ooniapi-ecs-cluster20240310192643664900000001"
        tags                                 = {}
        # (16 unchanged attributes hidden)

        # (3 unchanged blocks hidden)
    }

  # module.ooniapi_frontend.aws_lb_listener_rule.ooniapi_ooniauth_rule has moved to module.ooniapi_frontend.aws_lb_listener_rule.route["ooniauth_rule"]
    resource "aws_lb_listener_rule" "route" {
        id           = "arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/178511e1b6ae89c5"
        tags         = {}
        # (4 unchanged attributes hidden)

        # (2 unchanged blocks hidden)
    }

  # module.ooniapi_frontend.aws_lb_listener_rule.ooniapi_ooniauth_rule_host has moved to module.ooniapi_frontend.aws_lb_listener_rule.route["ooniauth_rule_host"]
    resource "aws_lb_listener_rule" "route" {
        id           = "arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/f4bf91203c7ca76e"
        tags         = {}
        # (4 unchanged attributes hidden)

        # (2 unchanged blocks hidden)
    }

  # module.ooniapi_frontend.aws_lb_listener_rule.ooniapi_oonifindings_rule has moved to module.ooniapi_frontend.aws_lb_listener_rule.route["oonifindings_rule"]
    resource "aws_lb_listener_rule" "route" {
        id           = "arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/36d49e835c0b81c5"
        tags         = {}
        # (4 unchanged attributes hidden)

        # (2 unchanged blocks hidden)
    }

  # module.ooniapi_frontend.aws_lb_listener_rule.ooniapi_oonifindings_rule_host has moved to module.ooniapi_frontend.aws_lb_listener_rule.route["oonifindings_rule_host"]
    resource "aws_lb_listener_rule" "route" {
        id           = "arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/54cda6e694a0103f"
        tags         = {}
        # (4 unchanged attributes hidden)

        # (2 unchanged blocks hidden)
    }

  # module.ooniapi_frontend.aws_lb_listener_rule.ooniapi_oonimeasurements_rule_1[0] has moved to module.ooniapi_frontend.aws_lb_listener_rule.route["oonimeasurements_rule_1"]
    resource "aws_lb_listener_rule" "route" {
        id           = "arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/1cf3d6a7a694eec9"
        tags         = {}
        # (4 unchanged attributes hidden)

        # (2 unchanged blocks hidden)
    }

  # module.ooniapi_frontend.aws_lb_listener_rule.ooniapi_oonimeasurements_rule_2[0] has moved to module.ooniapi_frontend.aws_lb_listener_rule.route["oonimeasurements_rule_2"]
    resource "aws_lb_listener_rule" "route" {
        id           = "arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/e6dbe09be108b001"
        tags         = {}
        # (4 unchanged attributes hidden)

        # (2 unchanged blocks hidden)
    }

  # module.ooniapi_frontend.aws_lb_listener_rule.ooniapi_oonimeasurements_rule_3 has moved to module.ooniapi_frontend.aws_lb_listener_rule.route["oonimeasurements_rule_3"]
    resource "aws_lb_listener_rule" "route" {
        id           = "arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/48b97ed405c9c6cc"
        tags         = {}
        # (4 unchanged attributes hidden)

        # (2 unchanged blocks hidden)
    }

  # module.ooniapi_frontend.aws_lb_listener_rule.ooniapi_oonimeasurements_rule_host[0] has moved to module.ooniapi_frontend.aws_lb_listener_rule.route["oonimeasurements_rule_host"]
    resource "aws_lb_listener_rule" "route" {
        id           = "arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/f3d75d5d93fd6903"
        tags         = {}
        # (4 unchanged attributes hidden)

        # (2 unchanged blocks hidden)
    }

  # module.ooniapi_frontend.aws_lb_listener_rule.ooniapi_ooniprobe_rule has moved to module.ooniapi_frontend.aws_lb_listener_rule.route["ooniprobe_rule"]
    resource "aws_lb_listener_rule" "route" {
        id           = "arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/82069bb29bca6af1"
        tags         = {}
        # (4 unchanged attributes hidden)

        # (2 unchanged blocks hidden)
    }

  # module.ooniapi_frontend.aws_lb_listener_rule.ooniapi_ooniprobe_rule_2 has moved to module.ooniapi_frontend.aws_lb_listener_rule.route["ooniprobe_rule_2"]
    resource "aws_lb_listener_rule" "route" {
        id           = "arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/5f2394ffa8b71f98"
        tags         = {}
        # (4 unchanged attributes hidden)

        # (2 unchanged blocks hidden)
    }

  # module.ooniapi_frontend.aws_lb_listener_rule.ooniapi_ooniprobe_rule_3_current_version has moved to module.ooniapi_frontend.aws_lb_listener_rule.route["ooniprobe_rule_3_current_version"]
    resource "aws_lb_listener_rule" "route" {
        id           = "arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/0210f85a9024bd06"
        tags         = {}
        # (4 unchanged attributes hidden)

        # (3 unchanged blocks hidden)
    }

  # module.ooniapi_frontend.aws_lb_listener_rule.ooniapi_ooniprobe_rule_3_legacy_version has moved to module.ooniapi_frontend.aws_lb_listener_rule.route["ooniprobe_rule_3_legacy_version"]
    resource "aws_lb_listener_rule" "route" {
        id           = "arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/0f857b3b0593e95e"
        tags         = {}
        # (4 unchanged attributes hidden)

        # (3 unchanged blocks hidden)
    }

  # module.ooniapi_frontend.aws_lb_listener_rule.ooniapi_ooniprobe_rule_3_no_version has moved to module.ooniapi_frontend.aws_lb_listener_rule.route["ooniprobe_rule_3_no_version"]
    resource "aws_lb_listener_rule" "route" {
        id           = "arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/43cddc54b665d441"
        tags         = {}
        # (4 unchanged attributes hidden)

        # (2 unchanged blocks hidden)
    }

  # module.ooniapi_frontend.aws_lb_listener_rule.ooniapi_ooniprobe_rule_4 has moved to module.ooniapi_frontend.aws_lb_listener_rule.route["ooniprobe_rule_4"]
    resource "aws_lb_listener_rule" "route" {
        id           = "arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/6026e8ac5ba962ec"
        tags         = {}
        # (4 unchanged attributes hidden)

        # (2 unchanged blocks hidden)
    }

  # module.ooniapi_frontend.aws_lb_listener_rule.ooniapi_ooniprobe_rule_host has moved to module.ooniapi_frontend.aws_lb_listener_rule.route["ooniprobe_rule_host"]
    resource "aws_lb_listener_rule" "route" {
        id           = "arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/583471b0bdc1c388"
        tags         = {}
        # (4 unchanged attributes hidden)

        # (2 unchanged blocks hidden)
    }

  # module.ooniapi_frontend.aws_lb_listener_rule.ooniapi_oonirun_rule has moved to module.ooniapi_frontend.aws_lb_listener_rule.route["oonirun_rule"]
    resource "aws_lb_listener_rule" "route" {
        id           = "arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/cc29701b6ed6aa2e"
        tags         = {}
        # (4 unchanged attributes hidden)

        # (2 unchanged blocks hidden)
    }

  # module.ooniapi_frontend.aws_lb_listener_rule.ooniapi_oonirun_rule_host has moved to module.ooniapi_frontend.aws_lb_listener_rule.route["oonirun_rule_host"]
    resource "aws_lb_listener_rule" "route" {
        id           = "arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/9af03e886f8803f2"
        tags         = {}
        # (4 unchanged attributes hidden)

        # (2 unchanged blocks hidden)
    }

  # module.ooniapi_frontend.aws_lb_listener_rule.ooniapi_testlists_rule[0] has moved to module.ooniapi_frontend.aws_lb_listener_rule.route["testlists_rule"]
    resource "aws_lb_listener_rule" "route" {
        id           = "arn:aws:elasticloadbalancing:eu-central-1:905418398257:listener-rule/app/ooni-api-frontend/4a50f3dd46584390/9ef650e256f41d45/2864c2a72dfd4018"
        tags         = {}
        # (4 unchanged attributes hidden)

        # (2 unchanged blocks hidden)
    }

  # module.ooniapi_oonimeasurements.aws_ecs_task_definition.ooniapi_service (deposed object 65743afa) will be destroyed
  # (left over from a partially-failed replacement of this instance)
  - resource "aws_ecs_task_definition" "ooniapi_service" {
      - arn                      = "arn:aws:ecs:eu-central-1:905418398257:task-definition/ooniapi-service-oonimeasurements-td:169" -> null
      - arn_without_revision     = "arn:aws:ecs:eu-central-1:905418398257:task-definition/ooniapi-service-oonimeasurements-td" -> null
      - container_definitions    = jsonencode(
            [
              - {
                  - environment       = [
                      - {
                          - name  = "BASE_URL"
                          - value = "https://api.dev.ooni.io"
                        },
                      - {
                          - name  = "OTHER_COLLECTORS"
                          - value = jsonencode(
                                [
                                  - "http://10.0.0.78:8475",
                                ]
                            )
                        },
                      - {
                          - name  = "RATE_LIMITS"
                          - value = "10/minute;400000/day;200000/7day"
                        },
                      - {
                          - name  = "RATE_LIMITS_UNMETERED_PAGES"
                          - value = jsonencode(
                                [
                                  - "/metrics",
                                  - "/health",
                                ]
                            )
                        },
                      - {
                          - name  = "RATE_LIMITS_WHITELISTED_IPADDRS"
                          - value = jsonencode(
                                [
                                  - "5.9.112.244",
                                ]
                            )
                        },
                      - {
                          - name  = "S3_BUCKET_NAME"
                          - value = "ooni-data-eu-fra-test"
                        },
                      - {
                          - name  = "VALKEY_URL"
                          - value = "valkeys://ooniapi-dev-cache-3oue9i.serverless.euc1.cache.amazonaws.com:6379"
                        },
                    ]
                  - essential         = true
                  - image             = "ooni/api-oonimeasurements:20261002-c266af3c"
                  - logConfiguration  = {
                      - logDriver = "awslogs"
                      - options   = {
                          - awslogs-group  = "ooni-ecs-group/ooniapi-service-oonimeasurements"
                          - awslogs-region = "eu-central-1"
                        }
                    }
                  - memory            = 1024
                  - memoryReservation = 256
                  - mountPoints       = []
                  - name              = "ooniapi-service-oonimeasurements"
                  - portMappings      = [
                      - {
                          - containerPort = 80
                          - hostPort      = 0
                          - protocol      = "tcp"
                        },
                    ]
                  - secrets           = [
                      - {
                          - name      = "ACCOUNT_ID_HASHING_KEY"
                          - valueFrom = "arn:aws:ssm:eu-central-1:905418398257:parameter/oonidevops/secrets/ooni_services/account_id_hashing_key"
                        },
                      - {
                          - name      = "CLICKHOUSE_URL"
                          - valueFrom = "arn:aws:ssm:eu-central-1:905418398257:parameter/oonidevops/secrets/clickhouse_oonimeasurements_test_url"
                        },
                      - {
                          - name      = "JWT_ENCRYPTION_KEY"
                          - valueFrom = "arn:aws:ssm:eu-central-1:905418398257:parameter/oonidevops/secrets/ooni_services/jwt_secret"
                        },
                      - {
                          - name      = "POSTGRESQL_URL"
                          - valueFrom = "arn:aws:ssm:eu-central-1:905418398257:parameter/oonidevops/secrets/ooni-tier0-postgres/postgresql_write_url"
                        },
                      - {
                          - name      = "PROMETHEUS_METRICS_PASSWORD"
                          - valueFrom = "arn:aws:ssm:eu-central-1:905418398257:parameter/oonidevops/ooni_services/prometheus_metrics_password"
                        },
                    ]
                  - systemControls    = []
                  - volumesFrom       = []
                },
            ]
        ) -> null
      - enable_fault_injection   = false -> null
      - execution_role_arn       = "arn:aws:iam::905418398257:role/ooniapi-service-oonimeasurements-task-role" -> null
      - family                   = "ooniapi-service-oonimeasurements-td" -> null
      - id                       = "ooniapi-service-oonimeasurements-td" -> null
      - network_mode             = "bridge" -> null
      - requires_compatibilities = [] -> null
      - revision                 = 169 -> null
      - skip_destroy             = false -> null
      - tags                     = {
          - "Environment" = "dev"
          - "Name"        = "ooni-tier0-oonimeasurements"
          - "Repository"  = "https://github.com/ooni/devops"
        } -> null
      - tags_all                 = {
          - "Environment" = "dev"
          - "Name"        = "ooni-tier0-oonimeasurements"
          - "Repository"  = "https://github.com/ooni/devops"
        } -> null
      - track_latest             = true -> null
        # (5 unchanged attributes hidden)
    }

  # module.ooniapi_testlists.aws_launch_template.ooni_ec2 will be updated in-place
  ~ resource "aws_launch_template" "ooni_ec2" {
        id                                   = "lt-01d0fc9e7bff14cac"
      ~ image_id                             = (sensitive value)
      ~ latest_version                       = 14 -> (known after apply)
        name                                 = "oonitestlists-tmpl-20260302133710480100000005"
        tags                                 = {}
        # (16 unchanged attributes hidden)

        # (2 unchanged blocks hidden)
    }

  # module.oonipg.aws_security_group.pg will be updated in-place
  ~ resource "aws_security_group" "pg" {
        id                     = "sg-005ca579eb9c08cda"
      ~ ingress                = [
          - {
              - cidr_blocks      = [
                  - "10.0.0.0/8",
                ]
              - from_port        = 5432
              - ipv6_cidr_blocks = []
              - prefix_list_ids  = []
              - protocol         = "tcp"
              - security_groups  = [
                  - "sg-0ee46dd91ace739e1",
                ]
              - self             = false
              - to_port          = 5432
                # (1 unchanged attribute hidden)
            },
          + {
              + cidr_blocks      = [
                  + "10.0.0.0/8",
                  + "65.108.192.151/32",
                ]
              + from_port        = 5432
              + ipv6_cidr_blocks = []
              + prefix_list_ids  = []
              + protocol         = "tcp"
              + security_groups  = [
                  + "sg-0ee46dd91ace739e1",
                ]
              + self             = false
              + to_port          = 5432
                # (1 unchanged attribute hidden)
            },
        ]
        name                   = "oonipg20240422154923257500000004"
        tags                   = {
            "Environment" = "dev"
            "Name"        = "ooni-tier0-postgres"
            "Repository"  = "https://github.com/ooni/devops"
        }
        # (8 unchanged attributes hidden)
    }

  # module.oonitier1plus_cluster.aws_launch_template.container_host will be updated in-place
  ~ resource "aws_launch_template" "container_host" {
      ~ default_version                      = 34 -> (known after apply)
        id                                   = "lt-0eb432177b5a9f2aa"
      ~ image_id                             = (sensitive value)
      ~ latest_version                       = 34 -> (known after apply)
        name                                 = "oonitier1plus-ecs-cluster20251022145221257700000004"
        tags                                 = {}
        # (16 unchanged attributes hidden)

        # (3 unchanged blocks hidden)
    }

  # module.ooni_fastpath.module.ec2.aws_security_group_rule.ec2_sg_ingress[1] must be replaced
-/+ resource "aws_security_group_rule" "ec2_sg_ingress" {
      ~ cidr_blocks              = [ # forces replacement
            # (3 unchanged elements hidden)
            "10.0.1.0/24",
          + "65.108.192.151/32",
        ]
      ~ id                       = "sgrule-2656646093" -> (known after apply)
      + security_group_rule_id   = (known after apply)
      + source_security_group_id = (known after apply)
        # (6 unchanged attributes hidden)
    }

  # module.ooni_fastpath.module.ec2.aws_security_group_rule.ec2_sg_ingress[2] must be replaced
-/+ resource "aws_security_group_rule" "ec2_sg_ingress" {
      ~ cidr_blocks              = [ # forces replacement
            # (3 unchanged elements hidden)
            "10.0.1.0/24",
          + "65.108.192.151/32",
        ]
      ~ id                       = "sgrule-3549062282" -> (known after apply)
      + security_group_rule_id   = (known after apply)
      + source_security_group_id = (known after apply)
        # (6 unchanged attributes hidden)
    }

Plan: 19 to add, 7 to change, 5 to destroy.

Warning: Argument is deprecated

  with aws_s3_bucket.anoncred_manifests,
  on main.tf line 383, in resource "aws_s3_bucket" "anoncred_manifests":
 383: resource "aws_s3_bucket" "anoncred_manifests" {

Use the aws_s3_bucket_versioning resource instead

(and 5 more similar warnings elsewhere)

Warning: Available Write-only Attribute Alternative

  with module.ooni_monitoring.aws_ssm_parameter.ooni_monitoring_access_key,
  on ../../modules/ooni_monitoring/main.tf line 47, in resource "aws_ssm_parameter" "ooni_monitoring_access_key":
  47:   value = aws_iam_access_key.ooni_monitoring.id

The attribute value has a write-only alternative value_wo available. Use the
write-only alternative of the attribute when possible.

(and one more similar warning elsewhere)
Pusher @aagbsn
Action pull_request
Environment dev
Workflow .github/workflows/check_terraform.yml
Last updated Sun, 04 Oct 2026 06:41:36 GMT
aagbsn added 12 commits October 4, 2026 05:18
Applying prod as it was would create 7 Secrets Manager secrets: a JSON copy
of each service's credentials (Postgres URL, JWT key, ClickHouse URL,
ooniauth's AWS keys) and the deploy SSH key container. Every prod service
is still deploy_mode = "ecs", so nothing would read them.

They are commented out in place, with each deployer's pre-wired
env_vars/secrets block, so moving a prod service to "blue_green" or "both"
starts by uncommenting both. Against main, tf/environments/prod now
differs only by comments and the explicit deploy_mode = "ecs" (the
default), so the prod plan of this branch is the ooniapi_frontend
listener rules moving to their routes.yaml addresses: planned against a
state built from main's module with prod's inputs, 18 moved, 0 to add,
change or destroy. terraform validate and fmt pass.
Dev needs one Hetzner host: an outage while it reboots costs nothing, and
backend-hel is free for it. With both hosts required, a dev service would
have to name backend-hel twice, and deploy.py would then deploy to it
twice, the second time waiting out the drain timeout (300 s) for the slot
it had just taken out of rotation.

Without deploy_host_secondary the deploy job gets no
DEPLOY_HOST_SECONDARY and deploy.py deploys to the primary alone. Planned
with the deployer test module in each mode, a service with both hosts
plans the same resources as before (only the deploy.py object changes);
without the secondary, only that environment variable is left out.
backend-hel has been re-imaged and is free; one host is enough for dev.
Until now nothing said where a dev service would go: the pre-wired
deployers had no host, ports, network or deploy bucket, and the gateway
playbook targeted backend-fsn, which still serves the legacy API, as well.

- tf/environments/dev: each deployer gets backend-hel as its only host,
  its slot ports, the ooniapi docker network and container port 80, and a
  deploy bucket for the compose files, upstream confs and deploy.py. The
  services stay deploy_mode = "ecs", so the only resource this adds is the
  bucket.
- host_vars/backend-hel.ooni.org/ooniapi_gateway.yml: the gateway answers
  for api.dev.ooni.io and <service>.dev.ooni.io, with the same ports.
  testlists stays on its EC2 instance, which serves only plain HTTP, so
  the gateway proxies it over HTTPS through the ALB at
  testlists.dev.ooni.io; that name stays on the ALB at the DNS cutover.
  The dev names' certificate can only be issued after the cutover; the
  file says how.
- deploy-ooniapi-gateway.yml targets backend-hel only, and installs the
  nginx and dehydrated roles the gateway role expects first.

Rendered with these settings, the gateway vhost passes nginx -t (nginx
1.27) with all routes.yaml locations, the five direct-host vhosts and the
testlists passthrough. terraform validate and fmt pass for dev.
The role gave the deploy user its staging directory and sudoers rule but
never created it, so on a fresh host (backend-hel was just re-imaged) its
first task owning a path by that user fails, and the deploy job has no
account to log in to.

The role now creates the user, without groups, and authorizes only
ooniapi_gateway_deploy_ssh_public_key, the public half of the key in the
environment's oonidevops/ooniapi/deploy_ssh_key secret. It stops with
instructions while that is unset; for backend-hel it is left empty until
the key pair exists. Run in a Debian bookworm container with the pinned
ansible 9.3.0: creates the user and key, a second run changes nothing,
and an empty key fails with the message.
oonimeasurements keeps its rate limit counters in valkey, on ECS the
ElastiCache Serverless cache, which only answers inside the VPC: from a
Hetzner host the service could not reach it.

The gateway role now runs a valkey container named valkey on the shared
docker network, without a published port, in memory only (save and
appendonly off, 256 MB, allkeys-lru): losing the counters on a restart
only resets the limits. Dev's oonimeasurements blue/green env uses
valkey://valkey:6379; ECS keeps ElastiCache. Each host keeps its own
counters, so with two hosts behind DNS a client's limit is per host.

Checked with oonimeasurements' limits storage (RedisStorage with
async+valkey://) against valkey/valkey:8.1-alpine started with these
arguments: a 3/minute limit allows 3 hits and refuses the 4th and 5th.
The dev services on backend-hel reach the same backends as on ECS, but
from outside the VPC:

- fastpath: the host firewall the fastpath playbook installs already
  accepts 8472 (measurement submission) and 8475 (measurement spool) from
  anywhere; it is the instance's security group that only lets in the
  VPC. ooni_fastpath gains extra_ingress_cidrs (default none, so prod's
  three instances keep their rules), and dev passes backend-hel. The
  blue/green env of ooniprobe (FASTPATH_URLS) and oonimeasurements
  (OTHER_COLLECTORS) uses fastpath.dev.ooni.io instead of the instance's
  private IP, which only resolves to something reachable inside AWS.
- Postgres (publicly accessible, open to 10.0.0.0/8 only) and the
  ClickHouse proxy (9000-9002, the VPC and listed instances) let
  backend-hel in too.

backend-hel's addresses come from DNS, the way monitoring.ooni.org's do
for the ClickHouse proxy. The ClickHouse hosts' own nftables allow list
already has backend-hel. Measurements and the spool travel plain HTTP
between Hetzner and AWS, as they do from probes. terraform validate and
fmt pass for dev and prod.
oonimeasurements' blue/green env had valkey://valkey:6379 inline, a
literal that silently depended on the container name the gateway role
picks. It is now ooniapi_deploy_valkey_url, next to the docker network
and slot ports in dev's deploy locals, which all have to match the host,
and the role's container name is ooniapi_gateway_valkey_name, each
pointing at the other.
Neither service uses Postgres: ooniauth sends login emails through SES
and signs JWTs, oonimeasurements reads ClickHouse only. Their blue/green
service secrets still carried POSTGRESQL_URL, copied from their ECS
task_secrets, and the deploy job would write it to disk on the host.

Removed from dev's service secrets and from prod's commented-out ones.
prune_service_credentials removes the same variable from their ECS
tasks. terraform validate passes for dev and prod.
The services' CORS middleware (Starlette) answers a request from an
allowed origin with Access-Control-Allow-Origin set to that origin, and
a request without an Origin, or from a disallowed one, with no CORS
headers and no Vary: Origin. The cache key left Origin out, so whichever
request filled an entry decided what every origin got: one curl request
without Origin was enough to make browsers on the Explorer fail the
response's CORS check, for up to a day in the long zone.

The key now includes $http_origin, so each origin gets the response the
service gave it. A client sending random origins only misses the cache,
as random query parameters already would.

Reproduced with the gateway rendered for backend-hel in nginx 1.27, in
front of a FastAPI app with oonimeasurements' CORS settings, on
/api/v1/aggregation:
- before: a request without Origin, then one from explorer.ooni.org:
  HIT without Access-Control-Allow-Origin
- after: the explorer.ooni.org request is a MISS answered with its
  Access-Control-Allow-Origin, and a HIT with it when repeated; an
  unknown origin gets no CORS header; test-lists.ooni.org gets its own
…easurements

The gateway appends the address it received a request from to
X-Forwarded-For, as the ALB does in append mode, so services behind it
read the client's address from the last entry (ooni/backend
client_ip_from_proxy). backend-fsn forwards ooniprobe and measurement
API requests to ooniprobe.prod.ooni.io and oonimeasurements.prod.ooni.io;
once those names point at the gateway, its address is the last entry for
those requests, as it is behind the ALB today. The commented-out env
for both services now carries TRUSTED_PROXIES with backend-fsn's
address, matching their ECS tasks (ooniprobe_trusted_proxies), so it
comes back when a prod service moves to "blue_green" or "both".
Dev needs none: nothing forwards to the dev gateway.
…e file

Each slot becomes /etc/containers/systemd/<service>-<slot>.container, run by
rootful Podman with UserNS=auto. Secrets become Podman secrets passed to the
container as environment variables: the services' settings only read
environment variables, so the compose file's /run/secrets files were never
read.
Secrets go in a root-owned, mode 600 env file per slot, which the unit
loads, instead of Podman secrets: creating those through sudo would need a
wildcard name, and sudoers' "*" also matches spaces, so a caller could add
--driver shell and run a command as root. The deploy user's sudoers rule now
lists each command it runs, per service and slot, with no wildcards.
aagbsn added 13 commits October 29, 2026 13:33
Rootful Podman with Quadlet, netavark on nftables, the services' network as
a Quadlet .network unit that the slots' units depend on, and Valkey as a
Quadlet unit. This also drops the nftables setting written to containerd's
config, which Docker never read. Docker, if an earlier run installed it, is
removed.
Each service gets its own IPv4 network, ooniapi-<service>, with a /28 set in
host_vars; Valkey joins only the networks of the services that use it.
Slices cap CPU and memory: dev's slots and Valkey run in ooniapi-dev.slice
(4 CPUs, 4 GB, CPU weight 20). reverseproxy leaves backend-hel's list, since
it doesn't move to the hosts.
The gateway doesn't fall back to the legacy API through reverseproxy, as the
ALB does: what's missing is ported instead.
…ranges

Found running the role on a fresh trixie host: Debian's Podman packages
create neither /etc/containers/containers.conf.d nor the subuid and subgid
ranges for the user "containers" that UserNS=auto takes containers' IDs
from, so the netavark setting couldn't be written and no container started.
flush ruleset also deleted other tables, so a reload cut off containers by
removing netavark's rules (and Docker's NAT on hosts that run it).
The input chain drops by default, and containers reach aardvark-dns on
their bridge's address, which is host input.
A cadvisor role (the release binary; Debian doesn't package it) reports
each container's CPU, memory, network and OOM kills. Both exporters sit
behind nginx on 9001, as on the test helpers, and Prometheus scrapes them.
deploy_mode "both": ECS deploys first and keeps serving through the ALB;
then the same build goes to backend-hel's blue/green slots. DNS doesn't
change. oonifindings goes first because it only needs Postgres.
It sits next to the private key's secret in the dev account, as
/oonidevops/ooniapi/deploy_ssh_public_key, so rotating the pair needs no
commit.
As with oonifindings, deploy_mode "both" keeps ECS and the ALB serving.
ooniprobe waits: it reads S3 with the ECS task role's credentials, which
the hosts don't have.
On ECS ooniprobe reaches its buckets with the task role; on the hosts it
gets an IAM user with the same access (read the config and anoncred
manifest buckets, write failed reports), as AWS_ACCESS_KEY_ID and
AWS_SECRET_ACCESS_KEY in its host service secret. Its /health reads the
anoncred manifest, so without them the slot would never go live.
@ai-13rac1

Copy link
Copy Markdown

A review by Opus 5.5 as requested by @aagbsn

Review of ooni/devops PR 505 (blue/green deploys to Hetzner)

The ALB refactor is correct, but the blue/green path has three problems I'd fix before relying on it: a CI build can steal a key that gives root on backend-hel, Pull=always can stop every service on a reboot, and a deploy that half-fails can make the next deploy restart the live slot. I reviewed all 41 commits (about 2,400 lines across 30 files) and checked my assumptions against the ooni/backend source. I couldn't read the PR description (the API was blocked here), and I didn't run terraform plan or Ansible.

What's solid: routes.yaml matches the old ALB rules (same priorities, paths, headers and target groups), and every moved block has the right [0] index for the rules that used count. The sudoers patterns match the exact commands deploy.py runs. Restoring the old upstream when nginx -t fails is a good touch. Changing nftables.conf to replace only its own table fixes a real problem.

High

  1. CI builds can read the deploy SSH key. The build role (tf/modules/ooniapi_service_deployer/main.tf:99) has the AWS-managed SecretsManagerReadWrite policy. That build runs whatever buildspec is on the tracked ooni/backend branch, and dev tracks feature branches. This PR puts deploy_ssh_key and each service's secrets in Secrets Manager, so anyone who can push to those branches can read or overwrite the key, and the key is root on the host (see 5). The broad policy existed before, but it now reaches much more valuable secrets. Fix: scope the build role, or add a resource policy on the key secret that denies everyone except the deploy role.

  2. Pull=always in slot.container.tftpl:10. Podman fails the start if the pull fails, even when the image is already on the host. So a reboot during a Docker Hub outage or rate limit leaves every slot down. With Restart=always, a crash-looping slot also pulls on every restart and burns through anonymous pull limits. Image tags are date-sha and never reused (checked in the backend Makefile), so Pull=missing is safe.

  3. active_slot is written after nginx has already switched (deploy.py:205-206). If the tee fails or the build is killed between those two lines, nginx serves the new slot but the file still names the old one. The next deploy then picks the live slot as its target, restarts it while the other slot is marked down, and the service is out until the health check passes. Fix: work out the active slot from the upstream file nginx actually serves, or write the file first.

    • It's more likely than it looks: the deploy build's timeout is 20 minutes (main.tf:296). With a second host, the worst case is two × (300 s drain + 300 s start/pull + 120 s health check), about 24 minutes, so CodeBuild can kill a deploy at exactly this point.

Medium

  1. The cache key ignores User-Agent on /api/v1/measurements. In oonimeasurements (measurements.py:743, commented "Cannot be cached due to user_agent"), clients whose UA starts with okhttp get a stub response with no Cache-Control. Everyone else gets real results cached for 60 s. With the key in gateway.conf.j2:101:

    • okhttp clients get the full cached list, which defeats the workaround;
    • browsers can get the stub for 10 s.

    Fix: bypass the cache for that UA, or add it to the key for that location.

  2. The deploy key is effectively root, so the sudoers scoping doesn't contain it. sudo install of a job-written Quadlet unit can run a privileged container with / mounted. sudo mv of the upstream file (deploy.py:189) leaves a deploy-owned file in /etc/nginx/conf.d, which the deploy user can edit later without sudo. Consider a root-owned helper that takes only <service> <slot> <tag> and renders the unit itself, and use install -o root for the upstream file.

  3. The deploy job never checks host keys. StrictHostKeyChecking=accept-new in a fresh CodeBuild container trusts whatever answers, and the job then copies every service secret to it. Pin the host key in known_hosts (from SSM, for example) and use StrictHostKeyChecking=yes.

  4. Clients control X-Forwarded-For. The backend's rate limiter and probe geolocation both use the leftmost X-Forwarded-For entry, and $proxy_add_x_forwarded_for keeps whatever the client sent. That allows rate-limit bypass and IP spoofing. The ALB behaves the same today, but the gateway is the edge, so proxy_set_header X-Forwarded-For $remote_addr; fixes it here.

  5. The per-service vhosts (e.g. ooniprobe.dev.ooni.io, gateway.conf.j2:115-140) diverge from the main one. They lack client_max_body_size, so nginx's 1 MB default rejects large submissions sent there with a 413; the main vhost allows 200 MB. They also skip caching and the TLS settings.

  6. The testlists passthrough (gateway.conf.j2:104) has two problems:

    • nginx resolves the ALB hostname only when the config is loaded, and ALB IPs change, so it breaks between reloads.
    • It sends neither SNI nor certificate verification. URL submissions carry users' tokens over that unverified TLS across the internet.

    Add a resolver with a variable in proxy_pass, plus proxy_ssl_server_name on; and proxy_ssl_verify on;.

  7. The dev API certificate will stop renewing after the cutover. deploy-ooni-backend.yml:16 sets ssl_domains: [backend-hel.ooni.org] as role vars, which take precedence over host_vars. The next run of that playbook rewrites domains.txt without the api.dev names, renewal stops silently, and the cert expires about 90 days later.

  8. Database traffic makes a round trip through AWS. On backend-hel, ClickHouse traffic goes Hetzner → the AWS t3a.nano proxy → Hetzner ClickHouse (dev/main.tf:984). That costs latency and AWS egress on every query result, and sends ClickHouse credentials in plaintext over the internet twice. Fastpath is also plain HTTP (:744), and RDS is publicly reachable (sslmode not visible here). Fine as a stepping stone, but connect to ClickHouse directly before prod.

Low and nits

  • A failed deploy leaves the bad image crash-looping in the idle slot, pulling on each restart. Stop the slot on health-check failure.
  • The drained slot runs old code indefinitely, doubling memory and database connections inside the 4G slice.
  • The secret copy doesn't stay in sync. The comment at dev/main.tf:265 says "both deploy paths stay in sync automatically", but the copy is a snapshot taken at terraform apply. Rotating a value in SSM doesn't reach the hosts until someone runs apply and then redeploys. The IAM access key secrets also end up in Terraform state.
  • The commented prod blocks still use VPC-private addresses (FASTPATH_URL http://10.0.0.32, ElastiCache VALKEY_URL), which dev already found unreachable from the host.
  • No keepalive between nginx and the slots. The upstream template has no keepalive and the gateway doesn't clear the Connection header, so every request opens a new connection to the slot.
  • Subnet edits don't apply. Quadlet only creates a network if it's missing, so changing its subnet later does nothing, and the DNS firewall rule then no longer matches.
  • Concurrent deploys of different services can trip each other's nginx -t, and the error then wrongly says the config is "broken independently".
  • Missing config isn't caught at plan time. Nothing stops blue_green mode being set without ports or a host; add preconditions.
  • env_file() breaks on non-string values. A number or boolean in the secret JSON causes a TypeError, and a local variable in deploy_host shadows the function name.
  • listen … http2 is deprecated on current nginx.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

3 participants