Environment_Infrastructure/setup/02-test-ansible-bootstrap.md
Murat ÖZDEMİR 720c79d460 Add Hetzner Cloud production infrastructure with multi-node support
- This commit introduces the Terraform configuration to provision a production environment on Hetzner Cloud, building on the existing test setup.
- Key improvements and new features include:
* **Multi-node clusters:** Scaling to 3-node Swarm application and database clusters for improved resilience.
* **High availability:** Utilizing a Hetzner Floating IP for the application entry point and `spread` placement groups for fault tolerance across physical hosts.
* **Enhanced network security:** Internal management services (RabbitMQ, APISIX, Prometheus, Grafana) are restricted to the application subnet, expected to be accessed via an internal reverse proxy (SWAG).
* **Internal database replication:** New firewall rules enable PostgreSQL replication and MongoDB replica set traffic within the database subnet.
* **Refined test environment:** Updates to align `test` configuration with the new `prod` structure, including a dedicated floating IP and adjusted firewall rules.
* **Configuration standardization:** Environment-specific details moved to `locals.tf` for clarity, with upgraded server types and migration to Rocky Linux as the base image.
- Updates were also made to the latest version of Terraform to ensure consistency in the documentation
2026-05-10 15:43:22 +03:00

263 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 02 - Test Ansible Bootstrap
Bu asamanin amaci Terraform ile olusturulan test makinelerini Linux, hardening, Docker ve Swarm acisindan hazir hale getirmektir. DB yazilimi kurulumu bu asamanin disindadir.
## Hedef Makineler
| Host | Rol |
| --- | --- |
| `iklim-app-01` | Swarm manager + app worker |
| `iklim-db-01` | Manuel DB kurulumu icin OS-hardening uygulanmis DB node |
## Onerilen Dosya Yapisi
```text
ansible/
ansible.cfg
inventory/
generated/
test.yml
group_vars/
all.yml
test.yml
playbooks/
test-bootstrap.yml
roles/
base/
hardening/
docker/
swarm/
node_dirs/
storagebox/
```
## Base Role
Tum test node'larina uygulanir:
- `dnf update`
- temel paketler:
- `curl`
- `wget`
- `git`
- `jq`
- `unzip`
- `ca-certificates`
- `fail2ban`
- `chrony`
- `python3`
- `python3-pip`
- timezone: `Europe/Istanbul`
- hostname ayari
- sistem reboot gerekiyorsa kontrollu reboot
## Security Hardening Role
Tum test node'larina uygulanir:
- SSH password login kapatilir.
- Root SSH login kapatilir.
- Sadece SSH key ile login kalir.
- `PermitEmptyPasswords no`
- `MaxAuthTries 3`
- `fail2ban` SSH jail aktif edilir.
- `dnf-automatic` ile otomatik guvenlik guncellestirmeleri aktif edilir.
- `firewalld` default:
- incoming: deny (drop zone)
- outgoing: allow
- Public SSH sadece admin CIDR'dan acilir.
Not: Docker iptables kurallari firewalld ile etkilesebilir. Hetzner Cloud firewall asil dis perimeter kabul edilir; firewalld host icinde ikinci katman olarak kullanilir.
## Docker Role
Sadece `iklim-app-01` uzerinde zorunludur. `iklim-db-01` uzerinde DB manual kurulum stratejisine gore opsiyonel tutulabilir.
Docker kurulumu resmi Docker dnf repository uzerinden yapilir:
- Docker GPG key + dnf repository (`https://download.docker.com/linux/rhel/docker-ce.repo`)
- paketler:
- `docker-ce`
- `docker-ce-cli`
- `containerd.io`
- `docker-buildx-plugin`
- `docker-compose-plugin`
- Docker servisi enabled + started
Docker convenience script kullanilmayacak. Production benzeri test ortami icin paket repository yolu tercih edilir.
## Swarm Role
`iklim-app-01` uzerinde:
- `docker swarm init`
- advertise addr: `10.10.10.11`
- data path addr: `10.10.10.11`
- overlay network:
- `iklimco-net`
- driver: `overlay`
- attachable: `true`
- Node `type=service` label'i ile isaretlenir:
```bash
docker node update --label-add type=service iklim-app-01
```
- Node `AVAILABILITY=Active` kalir (drain edilmez); tek node hem manager hem worker'dir.
Test tek node Swarm oldugu icin join token kullanimi yoktur.
## Node Directory Role
`iklim-app-01` uzerinde deploy on kosullari:
```text
/opt/iklimco
/opt/iklimco/ssl
/opt/iklimco/init
/opt/iklimco/init/postgresql
/opt/iklimco/init/mongodb
```
DB node uzerinde manuel DB kurulumu icin minimum:
```text
/opt/iklimco
/opt/iklimco/db
/opt/iklimco/backup
```
## StorageBox DAVFS Mount Role
Her iki node'a uygulanir (`iklim-app-01` ve `iklim-db-01`).
### Amac
Hetzner StorageBox'u WebDAV (DAVFS) protokolü üzerinden `/mnt/storagebox` olarak mount eder. Docker volume'lari bu dizine baglanarak veri kaliciligini ve yedeklemeyi saglar.
### Test Ortami Sub-Account
| Parametre | Degisken | Deger |
| --- | --- | --- |
| Ana hesap | `storagebox_account` | `u469968` |
| Sub-account | `storagebox_user` | `u469968-sub1` |
| WebDAV URL | `storagebox_url` | `https://u469968-sub1.your-storagebox.de/` |
| Mount point | `storagebox_mount_point` | `/mnt/storagebox` |
### Role Degiskenleri
`group_vars/all.yml` — tum ortamlar icin ortak:
```yaml
storagebox_account: "u469968"
```
`group_vars/test.yml` — test ortamina ozgu; user ve url account'tan turetilir:
```yaml
storagebox_user: "{{ storagebox_account }}-sub1"
storagebox_url: "https://{{ storagebox_user }}.your-storagebox.de/"
storagebox_password: "{{ vault_storagebox_password }}" # Ansible Vault ile saklanir
storagebox_mount_point: "/mnt/storagebox"
```
Prod ortaminda yalnizca suffix degisir (`sub1` → `sub2`), geri kalan her sey turetilir.
`vault_storagebox_password` degeri Ansible Vault ile sifreli `group_vars/test-vault.yml` icinde tutulur:
```bash
# Sifreleme
ansible-vault encrypt group_vars/test-vault.yml
# Duzenleme
ansible-vault edit group_vars/test-vault.yml
```
`test-vault.yml` icerigi:
```yaml
vault_storagebox_password: "SUB_ACCOUNT_PAROLASI"
```
### Adimlar
1. **davfs2 kurulumu**
```yaml
- name: Install davfs2
ansible.builtin.dnf:
name: davfs2
state: present
```
2. **Kimlik bilgileri dosyasi** (`/etc/davfs2/secrets`)
```yaml
- name: Configure davfs2 secrets
ansible.builtin.lineinfile:
path: /etc/davfs2/secrets
line: "{{ storagebox_url }} {{ storagebox_user }} {{ storagebox_password }}"
create: yes
mode: "0600"
owner: root
group: root
```
3. **Mount point olustur**
```yaml
- name: Create mount point
ansible.builtin.file:
path: "{{ storagebox_mount_point }}"
state: directory
mode: "0755"
```
4. **fstab kaydı**
```yaml
- name: Add fstab entry
ansible.builtin.lineinfile:
path: /etc/fstab
line: >-
{{ storagebox_url }} {{ storagebox_mount_point }} davfs
_netdev,auto,user,rw,uid=root,gid=root 0 0
state: present
```
5. **Mount et**
```yaml
- name: Mount StorageBox
ansible.builtin.command: mount {{ storagebox_mount_point }}
args:
creates: "{{ storagebox_mount_point }}/.mounted_marker"
```
Mount basarisi icin dizine bir marker dosyasi yazilabilir:
```yaml
- name: Write mount marker
ansible.builtin.copy:
content: "mounted by ansible"
dest: "{{ storagebox_mount_point }}/.mounted_marker"
```
### Notlar
- `davfs2` paketi EPEL repository'sinde bulunur; base role'de `dnf install epel-release` yapilmalidir.
- StorageBox sifreleri asla plaintext olarak repository'e eklenmez; Ansible Vault zorunludur.
- Mount noktasi reboot'ta `_netdev` flag'i sayesinde network hazir olduktan sonra otomatik mount edilir.
- Docker volume'lari bu dizin altindaki bir alt klasore yonlendirilir, ornegin `/mnt/storagebox/volumes/`.
## Kabul Kriterleri
- `ansible -i inventory/generated/test.yml all -m ping` basarili olur.
- `iklim-app-01` uzerinde `docker info` calisir.
- `iklim-app-01` uzerinde Swarm active olur; node `AVAILABILITY=Active` (drain degil).
- `docker network ls` icinde `iklimco-net` gorulur.
- `docker node inspect iklim-app-01 --format '{{.Spec.Labels}}'` ciktisi `map[type:service]` icerir.
- `iklim-db-01` uzerinde public DB portu acik degildir.
- Public portlar Hetzner firewall + firewalld seviyesinde `22`, `80`, `443` ile sinirlidir.
- Her iki node'da `mount | grep storagebox` StorageBox mount'unu gosterir.
- `ls /mnt/storagebox/.mounted_marker` basarili olur.
- Reboot sonrasi mount otomatik olarak geri gelir.