Murat ÖZDEMİR 27f4f83f73 docs(prod): resolve cross-layer inconsistencies and complete prod env implementation
Ansible roles:
- act_runner/defaults: set act_runner_name to inventory_hostname (was
  hardcoded to iklim-test-app); added vault_gitea_runner_token to vault.yml
- prod/group_vars/all: restructured from flat files to all/ directory;
  added act_runner_labels override (prod-runner,ubuntu-24.04,hostname);
  added storagebox_managed_directories; added swarm_manager_ip and other
  prod-specific vars
- prod/roles/db_stack: prod-specific db_node tasks using StorageBox paths
  (/mnt/storagebox/db/...) instead of local paths
- docker/tasks: split firewalld loop into all-nodes (Swarm ports) and
  app-only (80/443) tasks
- swarm/tasks: added --advertise-addr private_ip to join commands for
  correct multi-homed node advertisement
- hardening/tasks: corrected firewalld drop zone configuration
- node_dirs/tasks: added /opt/iklimco/vault/data for Vault Raft volume
- db_stack/tasks/app_node: updated stale comment (removed pg-proxy reference)
- db_stack/templates: removed pg-proxy and mongo-proxy service blocks
- test/host_vars/iklim-app-01: added act_runner_name override to preserve
  existing test runner registration

Roadmap and setup docs:
- roadmap/03-infra-stack-changes: added replicas:0 for etcd/postgresql/
  mongodb/pg-proxy/mongo-proxy in prod overlay; updated placement table;
  fixed grafana/data mkdir (auto-created by Ansible); translated Turkish
  note to English
- roadmap/08-deploy-pipeline-update: updated stale "remains idle" note
  for standalone etcd (now disabled with replicas:0)
- roadmap/01-swarm-init-multinode: consistency fixes
- setup/06: added Outputs section and etcd firewall port documentation
- setup/07: removed prometheus/data from StorageBox acceptance criteria;
  replaced manual StorageBox mkdir section with Ansible auto-creation note;
  updated prod README section with full bootstrap instructions and vault docs;
  added act_runner_labels prod policy
- setup/08: extensive rewrite — aligned with Patroni etcd overlay DNS,
  corrected hcloud_firewall.app reference, updated all StorageBox paths
  from /prod/db/ to /db/
- setup/09: removed prometheus/data from acceptance criteria; updated
  runner label policy (removed docker/swarm-manager labels); added
  acceptance criterion for disabled services absent from docker service ls

Terraform:
- prod/firewall.tf: added missing DB subnet mutual rules (etcd, Patroni)
- prod/outputs.tf: added prod_floating_ip and prod_private_ips outputs
- prod/servers.tf: aligned placement group and naming
- prod/variables.tf: corrected variable descriptions
- prod/terraform.tfvars.example: updated defaults
- terraform/hetzner/README.md: new comprehensive README covering both
  test and prod environments with firewall tables and inventory instructions

ansible/README.md: expanded prod section with inventory groups, bootstrap
  run order, runner label policy, and vault variable documentation
2026-05-18 19:17:56 +03:00
..

Terraform — iklim.co Hetzner Cloud Altyapısı

Bu dizin, iklim.co test ve prod ortamlarının Hetzner Cloud altyapısını Terraform ile yönetir.

Dizin Yapısı

terraform/hetzner/
  test/    — test ortamı: 1 app + 1 db node, single-node Swarm
  prod/    — prod ortamı: 3 app + 3 db node, 3-manager HA Swarm

Her ortam kendi bağımsız Terraform state dosyasına sahiptir; birbirini etkilemez.

Ortam Karşılaştırması

Özellik Test Prod
App node sayısı 1 (iklim-app-01) 3 (iklim-app-01/02/03)
DB node sayısı 1 (iklim-db-01) 3 (iklim-db-01/02/03)
App sunucu tipi cpx42 cpx42
DB sunucu tipi cpx42 cpx32
Swarm mimarisi Single-node 3-manager HA
App subnet 10.10.10.0/24 10.20.10.0/24
DB subnet 10.10.20.0/24 10.20.20.0/24
Floating IP Var Var
Placement group Yok Spread (farklı fiziksel host)

Ön Koşullar

  • Terraform >= 1.5 kurulu olmalı.
  • Hetzner Cloud ortama özel proje API token'ı hazır olmalı (test ve prod ayrı proje).
  • terraform.tfvars dosyası oluşturulmuş olmalı (bkz. terraform.tfvars.example).

terraform.tfvars Kurulumu

# Test için:
cd terraform/hetzner/test
cp terraform.tfvars.example terraform.tfvars

# Prod için:
cd terraform/hetzner/prod
cp terraform.tfvars.example terraform.tfvars

terraform.tfvars içindeki değişkenler:

Değişken ıklama
hcloud_token Hetzner Cloud ortama özel proje API token'ı
location Sunucu lokasyonu (örn. fsn1)
image Sunucu işletim sistemi (örn. rocky-10)
server_type_app App sunucu tipi
server_type_db DB sunucu tipi
admin_ssh_public_key_path Admin SSH public key dosya yolu
admin_allowed_cidrs SSH erişimine izin verilen CIDR listesi

terraform.tfvars hassas bilgi içerir; repository'e commit edilmez.

Terraform Komutları

Tüm komutlar ilgili ortam dizininden çalıştırılmalıdır:

# Test:
cd terraform/hetzner/test

# Prod:
cd terraform/hetzner/prod

Başlatma

terraform init

Değişiklik önizleme

terraform plan

Uygulama

terraform apply

Kaynakları kaldırma

terraform destroy

Ansible Inventory Üretimi

terraform apply tamamlandıktan sonra Ansible inventory'si şu komutlarla üretilir:

# Test inventory:
cd terraform/hetzner/test
terraform output -raw ansible_inventory_yaml \
  > ../../../ansible/test/inventory/generated/test.yml

# Prod inventory:
cd terraform/hetzner/prod
terraform output -raw ansible_inventory_yaml \
  > ../../../ansible/prod/inventory/generated/prod.yml

Sunucu ekleme/silme veya IP değişimi sonrası inventory yeniden üretilmelidir.

Outputs

Test

Output ıklama
ansible_inventory_yaml Ansible inventory YAML
test_private_ips Node private IP haritası
test_public_ips Node public IPv4 haritası
test_floating_ip Swarm giriş noktası floating IP

Prod

Output ıklama
ansible_inventory_yaml Ansible inventory YAML
prod_private_ips Node private IP haritası (app ve db alt anahtarlarıyla)
prod_public_ips Node public IPv4 haritası
prod_floating_ip Swarm giriş noktası floating IP — DNS A kaydı bu IP'ye yönlendirilir
# Floating IP'yi görmek için:
terraform output prod_floating_ip   # veya test_floating_ip

Güvenlik Duvarı Özeti

App Firewall (her iki ortam)

Port Protokol Kaynak ıklama
22 TCP admin_allowed_cidrs SSH
80 TCP 0.0.0.0/0 HTTP (SWAG)
443 TCP 0.0.0.0/0 HTTPS (SWAG)
2377 TCP DB subnet Docker Swarm control plane
7946 TCP/UDP DB subnet Docker Swarm node discovery
4789 UDP DB subnet Docker Swarm VXLAN overlay

DB Firewall (her iki ortam)

App subnet kaynaklı:

Port ıklama
22/tcp SSH
5432/tcp PostgreSQL
27017/tcp MongoDB
2377/tcp Docker Swarm control plane
7946/tcp,udp Docker Swarm node discovery
4789/udp Docker Swarm VXLAN overlay

Prod'a özgü (app subnet kaynaklı):

Port ıklama
2379/tcp etcd client (Patroni + APISIX)

Prod'a özgü (DB subnet içi, karşılıklı):

Port ıklama
5432/tcp Patroni replikasyon
27017/tcp MongoDB replica set internal
2379/tcp etcd client
2380/tcp etcd peer
8008/tcp Patroni REST API

IP kısıtlaması (admin paneli, dashboard vb.) Hetzner Firewall'da değil, SWAG nginx konfigürasyonunda yapılır.

Sonraki Adım

Terraform apply ve inventory üretiminin ardından Ansible bootstrap çalıştırılır. Detaylar için ansible/README.md dosyasına bakın.