# iklim.co Ansible Kullanım Rehberi

Bu dizin, iklim.co test ve prod sunucu ortamlarının Ansible ile hazırlanması için kullanılan playbook, role, inventory ve değişken dosyalarını içerir.

Mevcut kapsam:

- Test ortamı bootstrap ve post-stack hazırlıkları.
- Ortak Ansible rollerinin yönetimi.
- Terraform tarafından üretilen inventory dosyalarının kullanımı.
- Ansible Vault ile şifreli değişken yönetimi.
- Prod ortamı için başlangıç playbook yapısı.

Prod ortamı tamamlandıkça bu README içindeki prod başlıkları genişletilecektir.

## Dizin Yapısı

```text
Environment_Infrastructure/ansible/
  README.md
  requirements.yml
  roles/
  test/
    ansible.cfg
    inventory/generated/test.yml
    group_vars/
    host_vars/
    test-bootstrap.yml
    test-app-post-stack.yml
    test-db-post-stack.yml
  prod/
    ansible.cfg
    inventory/generated/prod.yml
    group_vars/
    prod-bootstrap.yml
```

## Temel Kavramlar

| Kavram | Açıklama |
| --- | --- |
| Playbook | Çalıştırılacak Ansible iş akışını tanımlar. Örn. `test-bootstrap.yml`. |
| Role | Tekrarlanabilir kurulum birimidir. Örn. `docker`, `swarm`, `db_stack`. |
| Inventory | Ansible'ın bağlanacağı hostları ve host gruplarını tanımlar. |
| Tag | Playbook içindeki belirli role/task'ları seçerek çalıştırmayı sağlar. |
| Vault | Şifreli değişkenlerin güvenli tutulması için Ansible Vault kullanımıdır. |
| `ansible.cfg` | Inventory, role path, remote user ve privilege escalation gibi varsayılanları belirler. |

## Inventory Kaynağı

Inventory dosyaları elle yazılan ana kaynak değildir. Terraform tarafından üretilen `ansible_inventory_yaml` output'u dosyaya aktarılır.

Test inventory üretimi:

```bash
cd Environment_Infrastructure/terraform/hetzner/test
terraform output -raw ansible_inventory_yaml > ../../../ansible/test/inventory/generated/test.yml
```

Prod inventory üretimi:

```bash
cd Environment_Infrastructure/terraform/hetzner/prod
terraform output -raw ansible_inventory_yaml > ../../../ansible/prod/inventory/generated/prod.yml
```

Inventory içeriği Terraform'un oluşturduğu Hetzner kaynaklarından gelir:

- Host adı
- Public IP: `ansible_host`
- SSH kullanıcısı: `ansible_user`
- Private network IP: `private_ip`

Sunucu ekleme/silme, public IP değişimi veya private IP değişimi Terraform tarafında yapıldıktan sonra inventory yeniden üretilmelidir. Aksi halde Ansible eski host bilgileriyle çalışır.

## Ortak Komut Parametreleri

| Parametre | Açıklama |
| --- | --- |
| `ansible-playbook` | Bir playbook dosyasını çalıştırır. |
| `-i <inventory>` | Kullanılacak inventory dosyasını belirtir. |
| `--tags <tag>` | Sadece belirtilen tag'e sahip role/task'ları çalıştırır. |
| `--limit <host-or-group>` | Çalışmayı belirli host veya host grubuyla sınırlar. |
| `--vault-password-file=<file>` | Ansible Vault ile şifrelenmiş değişkenleri açmak için parola dosyasını kullanır. |
| `--check` | Değişiklikleri uygulamadan deneme çalıştırması yapar. |
| `--list-tasks` | Çalışacak task listesini gösterir. |

## Test Ortamı

Test komutları `Environment_Infrastructure/ansible/test` dizini altından çalıştırılmalıdır:

```bash
cd Environment_Infrastructure/ansible/test
```

Bu dizindeki `ansible.cfg` şu varsayılanları tanımlar:

- `inventory = inventory/generated/test.yml`
- `remote_user = root`
- `roles_path = ../roles`
- `become = True`

Bu nedenle `-i inventory/generated/test.yml` parametresi teknik olarak zorunlu değildir; komutlarda görünürlük için kullanılabilir.

### Test Inventory Grupları

| Grup | Host | Amaç |
| --- | --- | --- |
| `app` | `iklim-app-01` | Uygulama node'u, runner ve deploy işleri |
| `db` | `iklim-db-01` | Veritabanı node'u, DB stack ve WireGuard |

`--limit` örnekleri:

```bash
--limit iklim-app-01
--limit app
--limit db
```

### Test Playbook'ları

| Playbook | Host kapsamı | Amaç |
| --- | --- | --- |
| `test-bootstrap.yml` | `all`, `app`, `db` | Base, hardening, Docker, node dizinleri, StorageBox ve Swarm hazırlıkları |
| `test-app-post-stack.yml` | `app` | Gitea runner ve app node deploy ön koşulları |
| `test-db-post-stack.yml` | `db` | DB stack ve WireGuard hazırlıkları |

### Test Bootstrap

Sadece `base` tag'ini `iklim-app-01` üzerinde çalıştırmak için:

```bash
ansible-playbook test-bootstrap.yml \
  -i inventory/generated/test.yml \
  --tags base \
  --limit iklim-app-01 \
  --vault-password-file=../.vault_pass
```

`test-bootstrap.yml` içindeki başlıca tag'ler:

| Tag | Rol | Amaç |
| --- | --- | --- |
| `base` | `base` | Temel paketler, sistem ayarları ve genel hazırlıklar |
| `hardening` | `hardening` | SSH ve güvenlik sıkılaştırmaları |
| `docker` | `docker` | Docker kurulumu ve ayarları |
| `node_dirs` | `node_dirs` | Ortak node dizinlerinin hazırlanması |
| `storagebox` | `storagebox` | StorageBox mount/dizin hazırlıkları |
| `storagebox_ssh_key` | `storagebox_ssh_key` | StorageBox SSH key hazırlığı |
| `swarm` | `swarm` | Docker Swarm kurulumu |

Örnekler:

```bash
# Tüm hostlarda Docker rolünü çalıştır
ansible-playbook test-bootstrap.yml \
  --tags docker \
  --vault-password-file=../.vault_pass

# Sadece app grubunda hardening rolünü çalıştır
ansible-playbook test-bootstrap.yml \
  --tags hardening \
  --limit app \
  --vault-password-file=../.vault_pass

# Swarm kurulumunu çalıştır
ansible-playbook test-bootstrap.yml \
  --tags swarm \
  --vault-password-file=../.vault_pass
```

### Test App Node Hazırlıkları

```bash
ansible-playbook test-app-post-stack.yml \
  -i inventory/generated/test.yml \
  --tags act_runner \
  --vault-password-file=../.vault_pass
```

Bu komut `app` grubundaki hostlarda `act_runner` rolünü çalıştırır.

Amaç:

- Gitea Actions runner kurulumu.
- Runner servis/dizin hazırlığı.
- Deploy ön koşullarının hazırlanması.

Ön koşul:

- Gitea arayüzünden `Organization -> Settings -> Actions -> Runners` altında registration token alınır.
- Token, Vault ile şifreli değişkenlerde `vault_gitea_runner_token` olarak tanımlanır.

Not:

- Token tanımlı değilse kurulum tamamlanabilir ama runner kayıt adımı atlanır.
- `.runner` dosyası varsa kayıt tekrar yapılmaz; rol idempotent çalışacak şekilde tasarlanmıştır.

### Test DB Node Hazırlıkları

```bash
ansible-playbook test-db-post-stack.yml \
  -i inventory/generated/test.yml \
  --tags db_stack \
  --vault-password-file=../.vault_pass
```

Bu komut `db` grubundaki hostlarda `db_stack` rolünü çalıştırır.

Amaç:

- PostgreSQL/PostGIS ve MongoDB için host hazırlıkları.
- DB ile ilgili dizin, config ve secret bağımlılıklarının hazırlanması.
- Test ortamındaki DB node'un stack sonrası operasyonel hale getirilmesi.

`test-db-post-stack.yml` içindeki tag'ler:

| Tag | Rol | Amaç |
| --- | --- | --- |
| `db_stack` | `db_stack` | PostgreSQL/MongoDB stack hazırlıkları |
| `wireguard` | `wireguard` | WireGuard VPN client/server ayarları |

Sadece WireGuard güncellemek için:

```bash
ansible-playbook test-db-post-stack.yml \
  --tags wireguard \
  --vault-password-file=../.vault_pass
```

WireGuard client eklemek için `group_vars/all/vars.yml` içindeki `wireguard_clients` listesine client public key'i eklenir.

### Test İçin Önerilen Çalıştırma Sırası

```bash
# 1. Temel sunucu hazırlıkları
ansible-playbook test-bootstrap.yml \
  --tags base,hardening,docker,node_dirs,storagebox,storagebox_ssh_key \
  --vault-password-file=../.vault_pass

# 2. Swarm kurulumu
ansible-playbook test-bootstrap.yml \
  --tags swarm \
  --vault-password-file=../.vault_pass

# 3. App node runner/deploy hazırlıkları
ansible-playbook test-app-post-stack.yml \
  --tags act_runner \
  --vault-password-file=../.vault_pass

# 4. DB node hazırlıkları
ansible-playbook test-db-post-stack.yml \
  --tags db_stack,wireguard \
  --vault-password-file=../.vault_pass
```

Rolleri tek tek çalıştırmak, hata durumunda hangi adımın problem çıkardığını daha net görmeyi sağlar.

## Prod Ortamı

Prod ortamı için mevcut başlangıç dosyaları:

```text
prod/ansible.cfg
prod/prod-bootstrap.yml
prod/group_vars/
```

Prod komutları `Environment_Infrastructure/ansible/prod` dizini altından çalıştırılmalıdır:

```bash
cd Environment_Infrastructure/ansible/prod
```

Bu dizindeki `ansible.cfg` şu varsayılanları tanımlar:

- `inventory = inventory/generated/prod.yml`
- `remote_user = root`
- `roles_path = ../roles`
- `become = True`

Prod inventory, prod Terraform çıktısından üretilir:

```bash
cd Environment_Infrastructure/terraform/hetzner/prod
terraform output -raw ansible_inventory_yaml > ../../../ansible/prod/inventory/generated/prod.yml
```

### Prod Inventory Grupları

| Grup | Host'lar | Rol |
| --- | --- | --- |
| `app` | `iklim-app-01`, `iklim-app-02`, `iklim-app-03` | Swarm manager + uygulama worker |
| `db` | `iklim-db-01`, `iklim-db-02`, `iklim-db-03` | Swarm worker + DB cluster node'u |

`--limit` örnekleri:

```bash
--limit iklim-app-01
--limit app
--limit db
```

### Prod Playbook ve Tag'ler

Ana playbook: `prod-bootstrap.yml`

| Tag | Rol | Host kapsamı | Amaç |
| --- | --- | --- | --- |
| `base` | `base` | `all` | Temel paketler, timezone, hostname, NTP |
| `hardening` | `hardening` | `all` | SSH, fail2ban, firewalld drop zone, dnf-automatic, iklim kullanıcısı |
| `docker` | `docker` | `all` | Docker Engine kurulumu ve Swarm portları |
| `node_dirs` | `node_dirs` | `all` | Node dizinleri (`/opt/iklimco/...`) |
| `storagebox` | `storagebox` | `all` | WebDAV mount ve yönetilen dizinlerin oluşturulması |
| `storagebox_ssh_key` | `storagebox_ssh_key` | `all` | StorageBox SSH key üretimi |
| `swarm` | `swarm` | `app`, `db` | Swarm init/join, overlay ağ, node label'ları |
| `db_labels` | inline task | `iklim-app-01` | DB node'larına `role=db` ve `db-index=01/02/03` label'ı ekler |
| `db_stack` | `db_stack` | `db` | StorageBox'ta MongoDB ve PostgreSQL config dizinleri |
| `act_runner` | `act_runner` | `app` | Gitea Actions runner kurulumu ve kaydı |

### Prod Bootstrap Çalıştırma Sırası

```bash
# 1. Temel sunucu hazırlıkları (tüm node'lar)
ansible-playbook prod-bootstrap.yml \
  --tags base,hardening,docker,node_dirs,storagebox,storagebox_ssh_key \
  --vault-password-file=../.vault_pass

# 2. Swarm kurulumu (app node'lar önce, ardından db node'lar)
ansible-playbook prod-bootstrap.yml \
  --tags swarm \
  --vault-password-file=../.vault_pass

# 3. DB node label'ları (Patroni koordinasyonu için)
ansible-playbook prod-bootstrap.yml \
  --tags db_labels \
  --vault-password-file=../.vault_pass

# 4. DB node konfigürasyonu (StorageBox dizin ve config dosyaları)
ansible-playbook prod-bootstrap.yml \
  --tags db_stack \
  --vault-password-file=../.vault_pass

# 5. App node runner kurulumu
ansible-playbook prod-bootstrap.yml \
  --tags act_runner \
  --vault-password-file=../.vault_pass
```

### Prod Act Runner

Runner'lar tüm app node'larında (`iklim-app-01/02/03`) systemd servisi olarak kurulur.

Label'lar `prod/group_vars/all/vars.yml` içinde tanımlıdır:

```
prod-runner
ubuntu-24.04
iklim-app-01   (veya iklim-app-02, iklim-app-03 — node'a göre değişir)
```

Kayıt token'ı `prod/group_vars/all/vault.yml` içinde `vault_gitea_runner_token` olarak tutulur. Token tanımlı değilse kayıt adımı atlanır; `.runner` dosyası varsa kayıt tekrar yapılmaz.

Gitea üzerinden token almak için: **Organization → Settings → Actions → Runners → Add Runner**

### Prod Vault Dosyası

`prod/group_vars/all/vault.yml` şifreli olarak tutulur ve şu değişkenleri içerir:

| Değişken | Açıklama |
| --- | --- |
| `vault_storagebox_password` | StorageBox WebDAV şifresi |
| `vault_iklim_password` | `iklim` sistem kullanıcısı şifresi |
| `vault_gitea_runner_token` | Gitea runner kayıt token'ı |

Şifreleme:

```bash
cd Environment_Infrastructure/ansible/prod
ansible-vault encrypt group_vars/all/vault.yml
```

Şifre çözme (düzenleme için):

```bash
ansible-vault edit group_vars/all/vault.yml
```

## Vault Kullanımı

Bu Ansible yapısı şifreli değerler için Ansible Vault kullanır.

Örnek şifreli dosyalar:

```text
test/group_vars/all/vault.yml
test/host_vars/iklim-app-01/vault.yml
test/host_vars/iklim-db-01/vault.yml
```

Komutlarda kullanılan parametre:

```bash
--vault-password-file=../.vault_pass
```

Bu parametre, Ansible'ın Vault ile şifrelenmiş değişkenleri açabilmesini sağlar. `.vault_pass` dosyası repository dışına sızdırılmamalı ve CI/CD ortamında güvenli secret olarak yönetilmelidir.

## Kontrol Komutları

Komutu gerçekten çalıştırmadan hangi host ve task'ların etkileneceğini görmek için:

```bash
ansible-playbook test-bootstrap.yml \
  --tags base \
  --limit iklim-app-01 \
  --vault-password-file=../.vault_pass \
  --check
```

Hangi task'ların çalışacağını listelemek için:

```bash
ansible-playbook test-bootstrap.yml \
  --tags base \
  --list-tasks \
  --vault-password-file=../.vault_pass
```

Inventory'deki hostları görmek için:

```bash
ansible-inventory \
  -i inventory/generated/test.yml \
  --list
```

Belirli host'a ping atmak için:

```bash
ansible iklim-app-01 \
  -i inventory/generated/test.yml \
  -m ping \
  --vault-password-file=../.vault_pass
```

Prod için aynı komutlar `ansible/prod` dizininden ve `inventory/generated/prod.yml` inventory'siyle çalıştırılmalıdır.
