Skip to content

AWS Multi-Account Overview

CWIQ.IO uses a three-account AWS Organization structure: management (never touch), shared-services (central tools), and dev (application workloads).


Account Summary

Account ID CLI Profile Purpose
Management 921838417607 (default — see warning) AWS Organization root, billing, SCPs
Shared-Services 308188966547 shared-services GitLab, Vault, Nexus, Authentik, observability, Tailscale routers, Route53 zones
Dev 686123185567 dev Orchestrator app, LangFuse, Demo, EKS cluster, CI/CD runners

NEVER use the default AWS profile

The default AWS CLI profile (921838417607) is the management/root account. It contains orphaned duplicate Route53 zones and IAM resources. Any operation run against this account is likely wrong and may modify stale resources.

Always specify an explicit profile:

aws <command> --profile shared-services
aws <command> --profile dev


Verification Before Any AWS Operation

Run this before every terraform plan, terraform apply, or AWS CLI sequence:

# Shared-services operations
aws sts get-caller-identity --profile shared-services
# Expected: Account = 308188966547

# Dev operations
aws sts get-caller-identity --profile dev
# Expected: Account = 686123185567

Account Purposes in Detail

Shared-Services (308188966547)

Central infrastructure shared across all environments:

  • GitLab (gitlab.shared.cwiq.io) — source of truth, CI/CD, container registry
  • Vault (vault.shared.cwiq.io) — secrets management for all environments
  • Nexus (nexus.shared.cwiq.io) — artifact repository (Docker, RPM, PyPI, npm)
  • Authentik (sso.shared.cwiq.io) — SSO identity provider (HA, 2 instances)
  • Observability stack — Grafana, Prometheus, Loki, Alertmanager
  • Ansible server (ansible-shared-cwiq-io) — Ansible playbook execution
  • Icinga (icinga.shared.cwiq.io) — health check master
  • SonarQube (sonarqube.shared.cwiq.io) — code quality
  • DefectDojo (defectdojo.shared.cwiq.io) — security findings
  • Route53 zonesshared.cwiq.io (public + private), cwiq.io (root)
  • Tailscale subnet router — bridges shared VPC (10.0.0.0/16) to the mesh

Dev Account (686123185567)

Application workloads for the development environment:

  • Orchestrator DEV (orchestrator-dev-cwiq-io) — main platform server
  • Orchestrator Demo (orchestrator-demo-cwiq-io) — demo environment server
  • LangFuse (langfuse-dev-cwiq-io) — LLM observability
  • Identity-DB (identity-db-dev-cwiq-io) — sssd-db-identity PostgreSQL backend
  • EKS cluster (cwiq-dev-eks-cluster) — GitLab Kubernetes runners (K8s 1.31, Karpenter v1.1.1)
  • Route53 zonesdev.cwiq.io (public + private)
  • Tailscale subnet router — bridges dev VPC (10.1.0.0/16) to the mesh

VPC Peering

The two VPCs are connected via VPC peering for lower-level, non-Tailscale connectivity (e.g., EKS pods reaching Shared services over VPC private IPs):

Attribute Value
Peering ID pcx-0535aabbb2629e915
Shared VPC 10.0.0.0/16
Dev VPC 10.1.0.0/16
Direction Bidirectional routes

Tailscale vs VPC Peering

Most cross-account access uses Tailscale (servers, SSH, observability). VPC peering is used for EKS runner pods and services that cannot run Tailscale. See Cross-VPC Connectivity for the decision guide.


Terraform Profile Configuration

All Terraform modules specify the AWS profile in their provider.tf. Do not run Terraform without verifying the profile first.

# Example provider.tf — shared-services module
provider "aws" {
  region  = "us-west-2"
  profile = "shared-services"
}

If a module's provider.tf is missing the profile attribute, stop and ask before proceeding — never fall back to the default profile.