Environment_Infrastructure/setup/03-test-ansible-bootstrap.md
Murat ÖZDEMİR b115a4cbdf Implement Hetzner sizing report recommendations and detailed DB setups
- Add `hetzner-sizing-report.md` defining data-driven server type recommendations for test and prod environments.
- Update Terraform configurations to align with the recommended `CPX` server types and refine firewall rules for Docker Swarm and database interactions.
- Introduce comprehensive documentation and stack files for:
    - Single-node PostgreSQL/MongoDB deployment on a test DB worker node.
    - High-availability 3-node MongoDB replica set and Patroni+etcd PostgreSQL cluster for production.
- Enhance Ansible bootstrap roles with SELinux disabling, fail2ban configuration, and StorageBox SSH key management for CI/CD.
- Reorganize and rename setup documentation files for improved structure and clarity.
2026-05-11 14:54:09 +03:00

9.7 KiB
Raw Blame History

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

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 (sirasıyla kurulur):
    • epel-release — fail2ban ve davfs2 bu repo'dan gelir; once kurulur
    • curl
    • wget
    • git
    • jq
    • tar
    • unzip
    • bash-completion
    • gettext — envsubst icin; CI/CD deploy pipeline'larinda gerekli
    • tree
    • 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.

SELinux Karari

Rocky Linux 10 SELinux enforcing modda gelir. Karar: disabled.

Gerekce:

  • Hetzner Cloud firewall (dis perimeter) + firewalld (host) iki katman ag guvenligini saglar.
  • Docker + davfs2 + firewalld kombinasyonu SELinux enforcing modda ek policy ve volume label yonetimi gerektirir.
  • Utils VPS'te de disabled yapilmis; tutarlilik saglanir.
# /etc/selinux/config icinde:
SELINUX=disabled
# Degisiklik reboot sonrasi aktif olur
reboot

Ansible'da:

- name: Disable SELinux
  ansible.posix.selinux:
    state: disabled
  register: selinux_change

- name: Reboot if SELinux state changed
  ansible.builtin.reboot:
  when: selinux_change.changed

fail2ban Konfigurasyonu

/etc/fail2ban/jail.local icerigi:

[DEFAULT]
ignoreip = 127.0.0.1/8 {{ admin_allowed_cidrs }}
bantime  = 21600
findtime = 300
maxretry = 5
banaction = iptables-multiport
backend = systemd

[sshd]
enabled = true
  • bantime: 6 saat ban
  • findtime: 5 dakika icinde
  • maxretry: 5 basarisiz giris → ban
  • ignoreip: admin CIDR'lari ban'dan muaf tutar

Ansible'da admin_allowed_cidrs listesi space-separated stringe donusturulup template'e basilir.

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:
    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:

/opt/iklimco
/opt/iklimco/ssl
/opt/iklimco/init
/opt/iklimco/init/postgresql
/opt/iklimco/init/mongodb

DB node uzerinde manuel DB kurulumu icin minimum:

/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:

storagebox_account: "u469968"

group_vars/test.yml — test ortamina ozgu; user ve url account'tan turetilir:

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 (sub1sub2), geri kalan her sey turetilir.

vault_storagebox_password degeri Ansible Vault ile sifreli group_vars/test-vault.yml icinde tutulur:

# Sifreleme
ansible-vault encrypt group_vars/test-vault.yml

# Duzenleme
ansible-vault edit group_vars/test-vault.yml

test-vault.yml icerigi:

vault_storagebox_password: "SUB_ACCOUNT_PAROLASI"

Adimlar

  1. davfs2 kurulumu

    - name: Install davfs2
      ansible.builtin.dnf:
        name: davfs2
        state: present
    
  2. Kimlik bilgileri dosyasi (/etc/davfs2/secrets)

    - 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

    - name: Create mount point
      ansible.builtin.file:
        path: "{{ storagebox_mount_point }}"
        state: directory
        mode: "0755"
    
  4. fstab kaydı

    - 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

    - 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:

    - 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 epel-release'i zaten kurar.
  • 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 Swarm servisleri /mnt/storagebox/<env>/<service>/ altindaki dizinleri bind mount olarak kullanir.

StorageBox SSH Key Role

Her iki node'a uygulanir (iklim-app-01 ve iklim-db-01).

Amac

Sunucu uzerinde ed25519 SSH anahtar cifti uretilir ve StorageBox ana hesabina yuklenir. Bu sayede CI/CD pipeline'lari STORAGEBOX_SSH_PRIV Gitea secret'ini kullanarak sifre girmeden StorageBox'a erisebilir.

Adimlar

  1. SSH key uret (eger yoksa)

    - name: Generate SSH key for storagebox
      ansible.builtin.user:
        name: root
        generate_ssh_key: yes
        ssh_key_type: ed25519
        ssh_key_file: /root/.ssh/id_ed25519_storagebox
        ssh_key_comment: "{{ inventory_hostname }}-storagebox"
    
  2. Public key'i StorageBox'a yukle

    Bu adim manuel yapilir (ilk kez sifre gerektirir):

    cat /root/.ssh/id_ed25519_storagebox.pub | ssh -p23 u469968-sub1@u469968-sub1.your-storagebox.de install-ssh-key
    

    Sonraki erisimler sifresiz calisir:

    sftp -P23 u469968-sub1@u469968-sub1.your-storagebox.de
    
  3. Private ve public key'leri Gitea'ya ekle

    Gitea → Organization Settings → Actions → Secrets:

    Secret Adi Deger
    STORAGEBOX_SSH_PRIV /root/.ssh/id_ed25519_storagebox icerigi
    STORAGEBOX_SSH_PUB /root/.ssh/id_ed25519_storagebox.pub icerigi

    Key icerigini almak icin:

    cat /root/.ssh/id_ed25519_storagebox
    cat /root/.ssh/id_ed25519_storagebox.pub
    

Notlar

  • Her sunucu icin ayri key uretilir; tum public key'ler StorageBox ana hesabina yuklenir.
  • Private key asla repo'ya commit edilmez; yalnizca Gitea secret olarak saklanir.

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.