Security Groups¶
CWIQ.IO uses centralized shared security groups (Tailscale, NAT) applied to all instances, supplemented by application-specific groups only when inter-service communication requires it.
Design Philosophy¶
Every EC2 instance receives two shared security groups created centrally in environments/<env>/security-groups/:
| Shared SG | Name Pattern | Purpose |
|---|---|---|
| Tailscale | <env>-tailscale-sg |
WireGuard mesh connectivity, developer SSH via Tailscale |
| NAT Gateway | <env>-nat-gateway-sg |
Outbound internet access through NAT |
Application-specific security groups are only created when an application must accept traffic from another specific service. For anything accessible only via Tailscale, the shared groups are sufficient.
Shared Security Groups¶
Tailscale SG (<env>-tailscale-sg)¶
Allows WireGuard UDP traffic and inbound connections from the Tailscale mesh. Applied to every EC2 instance — enables developer SSH and cross-server communication without public exposure.
NAT Gateway SG (<env>-nat-gateway-sg)¶
Allows outbound internet egress through the VPC NAT Gateway. Applied to all instances in private subnets needing package downloads, API calls to external services, or GitLab registry pushes.
Application-Specific Security Groups¶
Created inside each EC2 module (ec2-instances/<app>/security-groups.tf or security.tf) only when needed.
GitLab ALB SG (shared-gitlab-alb-sg)¶
Purpose: Internet-facing ALB in front of GitLab.
| Direction | Protocol | Port | Source | Description |
|---|---|---|---|---|
| Ingress | TCP | 443 | 0.0.0.0/0 |
HTTPS from internet |
| Ingress | TCP | 80 | 0.0.0.0/0 |
HTTP redirect to HTTPS |
| Egress | All | All | 0.0.0.0/0 |
Forward to GitLab instance |
GitLab Application SG (shared-gitlab-sg)¶
Purpose: GitLab EC2 instance, sits behind the ALB.
| Direction | Protocol | Port | Source | Description |
|---|---|---|---|---|
| Ingress | TCP | 80 | shared-gitlab-alb-sg |
HTTP from ALB only |
| Ingress | TCP | 443 | 100.64.0.0/10 |
HTTPS from Tailscale clients |
| Ingress | TCP | 2222 | 100.64.0.0/10 |
SSH Git via Tailscale |
| Egress | All | All | 0.0.0.0/0 |
All outbound |
Authentik NLB SG (shared-authentik-nlb-sg)¶
Purpose: Network Load Balancer for Authentik HA pair. Accepts traffic from Tailscale subnet router CIDR (SNAT mode).
| Direction | Protocol | Port | Source | Description |
|---|---|---|---|---|
| Ingress | TCP | 443 | 10.0.12.0/26 |
HTTPS from Tailscale subnet router |
| Ingress | TCP | 80 | 10.0.12.0/26 |
HTTP from Tailscale subnet router |
Nexus Docker Registry SG (shared-nexus-registry-sg)¶
Purpose: Expose Docker registry ports (8443 push, 8444 pull) to EKS runner pods via VPC peering.
| Direction | Protocol | Port | Source | Description |
|---|---|---|---|---|
| Ingress | TCP | 8443 | 10.1.0.0/16 |
Docker push from dev VPC (runners) |
| Ingress | TCP | 8444 | 10.1.0.0/16 |
Docker pull from dev VPC (runners) |
SonarQube SG (shared-sonarqube-sg)¶
Purpose: Allow EKS runner pods to reach SonarQube over VPC peering without Tailscale.
| Direction | Protocol | Port | Source | Description |
|---|---|---|---|---|
| Ingress | TCP | 9000 | 10.1.0.0/16 |
SonarQube API from dev VPC |
Vault SG (shared-vault-sg)¶
Purpose: Vault API access for CI/CD JWT authentication (EKS pods reach Vault via VPC peering).
| Direction | Protocol | Port | Source | Description |
|---|---|---|---|---|
| Ingress | TCP | 8200 | 10.1.0.0/16 |
Vault API from dev VPC |
| Ingress | TCP | 8200 | 100.64.0.0/10 |
Vault API from Tailscale clients |
EKS Cluster Security Group¶
EKS runner pods get VPC CNI IPs in the 10.1.34.x/10.1.35.x subnets. The cluster security group must permit:
- Outbound to
10.0.0.0/16(shared-services VPC, for GitLab server, Vault, Nexus, SonarQube) - Outbound to
10.1.35.46port 22 (SSH deploy-dev jobs reaching the orchestrator server) - Inbound from ALB health check IPs (if using internal ALB for runners)
When to Create an Application-Specific SG¶
| Situation | Action |
|---|---|
| App accessible only via Tailscale | Use shared SGs only |
| App behind a public ALB | Create ALB SG + app SG (ALB → app only) |
| App must accept traffic from EKS pods (no Tailscale) | Create app SG with source CIDR 10.1.0.0/16 |
| App must accept traffic from another specific service SG | Create app SG referencing the source SG |
| Background worker, no inbound | Use shared SGs only |
Terraform Location¶
terraform-plan/organization/environments/
├── shared-services/
│ ├── security-groups/ ← shared SGs (tailscale, nat-gateway)
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ └── ec2-instances/
│ ├── gitlab/
│ │ └── security-groups.tf ← ALB SG + app SG
│ ├── nexus/
│ │ └── security-groups.tf ← registry port SG
│ └── ...
└── dev/
├── security-groups/ ← shared SGs
└── ec2-instances/
└── ...
Related Pages¶
- VPC & Networking — Subnet CIDRs referenced in SG rules
- ALB Patterns — ALB SG configuration details
- EKS Cluster — Runner pod network constraints
- Tailscale Cross-VPC — Why Tailscale CGNAT range appears in rules