Document and commit the production bootstrap state after the initial Hetzner and Ansible rollout. - switch Ansible prod runbooks to use the shared vault password file - record production admin CIDRs, SSH key path, encrypted group vault, and encrypted per-host vault files - add generated production inventory and the prod setup history notes from the first bootstrap - keep root password login disabled while preserving key-based root access for Ansible bootstrap continuity - document separate Hetzner projects and tokens for test/prod and commit the prod provider lock file - remove the private Redis firewall allowance from the prod Terraform firewall and matching setup docs
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ı.
- Her ortam için ayrı Hetzner Cloud projesi ve API token'ı hazır olmalı (aşağıya bak).
terraform.tfvarsdosyası oluşturulmuş olmalı (bkz.terraform.tfvars.example).
⚠️ Her Ortam İçin Ayrı Hetzner Projesi Gereklidir
Test ve prod farklı Hetzner Cloud projeleri altında çalışır; her projenin kendi API token'ı olmalıdır.
Neden ayrı proje?
- Hetzner Cloud, aynı SSH public key'i bir projede yalnızca bir kez kabul eder. Test ortamının token'ı prod için kullanılırsa
terraform applySSH key çakışmasıyla (uniqueness_error) hata verir. - Kaynak izolasyonu: test destroy işlemi prod kaynaklarını etkilemez.
- Maliyet ve kota takibi ortam bazında yapılabilir.
Token nasıl alınır:
- Hetzner Cloud Console → ilgili projeyi seç (ör.
iklim_prod). - Security → API Tokens → Generate API Token — Read & Write izni ver.
- Token yalnızca bir kez gösterilir; hemen kopyala.
terraform.tfvarsiçindekihcloud_tokendeğerine yapıştır.
Test
terraform.tfvarsiçindeki token prod dizinine kopyalanmamalıdır. Her ortamın kendi dizininde kendi token'ı olmalıdır.
terraform.tfvars Kurulumu
# Test için:
cd terraform/hetzner/test
cp terraform.tfvars.example terraform.tfvars
# hcloud_token = iklim_test projesi token'ı
# Prod için:
cd terraform/hetzner/prod
cp terraform.tfvars.example terraform.tfvars
# hcloud_token = iklim_prod projesi token'ı
terraform.tfvars içindeki değişkenler:
| Değişken | Açıklama |
|---|---|
hcloud_token |
Ortama özel Hetzner Cloud API token'ı — test ve prod token'ları birbirinden farklıdır |
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.tfvarshassas 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 | Açı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 | Açı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 | Açı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 | Açı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 | Açıklama |
|---|---|
2379/tcp |
etcd client (Patroni + APISIX) |
Prod'a özgü (DB subnet içi, karşılıklı):
| Port | Açı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.