Environment_Infrastructure/setup/03-test-ansible-bootstrap.md
Murat ÖZDEMİR 65443e81e7 Refine: Update documentation to accurately reflect Ansible assets and structure
This commit brings the `README.md` and Ansible setup guides (`03-test-ansible-bootstrap.md`, `07-prod-ansible-bootstrap.md`) in sync with the current state of the Ansible automation.

Key updates include:
- Acknowledging the presence of in-repository Ansible playbooks and shared roles.
- Correcting Ansible inventory output paths and Terraform output commands.
- Detailing the new `group_vars/all/{vars.yml,vault.yml}` structure.
- Updating Ansible prerequisites to include `passlib` for password hashing.
- Adding documentation for `iklim` system user creation, keyboard layout, and refined firewall rules.
- Removing outdated "Known Gaps" related to missing Ansible code.
2026-05-11 19:00:10 +03:00

12 KiB
Raw Blame History

03 - Test Ansible Bootstrap

Bu aşamanın amacı Terraform ile oluşturulan test makinelerini Linux, hardening, Docker ve Swarm açısından hazır hale getirmektir. DB yazılımı kurulumu bu aşamanın dışındadır.

Ansible Kurulumu

Ansible, kontrol makinesinde (kendi bilgisayarınızda) yüklü olmalıdır. Hedef sunuculara herhangi bir ajan kurulmaz, sadece SSH erişimi yeterlidir.

İşletim Sistemine Göre Kurulum

  • Ubuntu / Debian:
    sudo apt update  
    sudo apt install -y pipx python3-venv  
    
    pipx ensurepath  
    export PATH="$HOME/.local/bin:$PATH"  
    
    pipx install --include-deps ansible
    

Not: sudo apt install ansible komutu bazı Ubuntu/Debian sürümlerinde eski Ansible paketlerini kurabilir. Bu nedenle güncel Ansible kullanımı için pipx yöntemi tercih edilmelidir.

  • Fedora / Rocky Linux / RHEL:

    sudo dnf install -y pipx python3-virtualenv
    
    pipx ensurepath
    export PATH="$HOME/.local/bin:$PATH"
    
    pipx install --include-deps ansible
    
  • macOS (Homebrew):

    brew install ansible
    
  • Python Pip ile (Her platformda):

    pipx install --include-deps ansible
    

Ek Python Bağımlılıkları

password_hash filtresi için passlib kontrol makinesinde gereklidir:

pipx inject ansible passlib

pip ile kurduysanız: pip install passlib

Kurulumun Doğrulanması

Hangi yöntemle kurarsanız kurun, kurulumun başarılı olduğunu doğrulamak için aşağıdaki komutları kullanın:

# Ansible versiyonunu ve yapılandırma yollarını kontrol edin
ansible --version

# Ansible binarysinin hangi konumdan çalıştığını kontrol edin
which -a ansible

Ansible Komutlarını Çalıştırma

Tüm komutlar ansible/test/ dizininden çalıştırılmalıdır. ansible.cfg inventory ve roles_path'i otomatik olarak tanımlar.

0. Gerekli Collection'ları Kur (İlk kurulumda bir kez)

ansible-galaxy collection install -r ../requirements.yml

1. Bağlantı Testi (Ping)

ansible all -m ping

2. Bootstrap Playbook'unu Çalıştırma

ansible-playbook test-bootstrap.yml --ask-vault-pass

Not: --ask-vault-pass parametresi Ansible Vault parolasını sorar; StorageBox şifresi bu şekilde çözülür.

3. Sadece Belirli Bir Rolü Çalıştırma (Tags)

ansible-playbook test-bootstrap.yml --tags "hardening" --ask-vault-pass

Hedef Makineler

Host Rol
iklim-app-01 Swarm manager + app worker
iklim-db-01 Manuel DB kurulumu için OS-hardening uygulanmış DB node

Önerilen Dosya Yapısı

ansible/
  test/
    ansible.cfg
    inventory/
      generated/
        test.yml
    group_vars/
      all/
        vars.yml
        vault.yml
    test-bootstrap.yml
  roles/
    base/
    hardening/
    docker/
    swarm/
    node_dirs/
    storagebox/
    storagebox_ssh_key/

Base Role

Tüm test node'larına uygulanır:

  • dnf update
  • epel-release — ayrı task olarak önce kurulur; fail2ban, davfs2, htop, btop bu repoya bağımlı
  • temel paketler (epel-release aktif olduktan sonra):
    • curl
    • wget
    • git
    • jq
    • tar
    • unzip
    • bash-completion
    • gettext — envsubst için; CI/CD deploy pipeline'larında gerekli
    • tree
    • ca-certificates
    • fail2ban
    • chrony
    • python3
    • python3-pip
    • python3-passlibpassword_hash filtresi için (EPEL)
    • htop — interaktif proses izleme (EPEL)
    • btop — kaynak monitörü, grafik arayüz (EPEL)
  • timezone: Europe/Istanbul
  • hostname ayarı
  • klavye düzeni: trq (Türkçe Q)
  • sistem reboot gerekiyorsa kontrollü reboot

Security Hardening Role

Tüm test node'larına uygulanır:

  • SSH password login kapatılır.
  • Root SSH login kapatılır.
  • Sadece SSH key ile login kalır.
  • PermitEmptyPasswords no
  • MaxAuthTries 3
  • fail2ban SSH jail aktif edilir.
  • dnf-automatic ile otomatik güvenlik güncelleştirmeleri aktif edilir.
  • iklim sistem kullanıcısı oluşturulur; wheel grubuna eklenir (şifre vault'tan alınır).
  • firewalld default:
    • incoming: deny (drop zone)
    • outgoing: allow
  • SSH kuralı önce drop zone'a rich rule olarak yazılır, ardından default zone drop yapılır — kilitleme riski ortadan kalkar.
  • Public SSH sadece admin CIDR'dan açılır.

SELinux Kararı

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

Gerekçe:

  • Hetzner Cloud firewall (dış perimeter) + firewalld (host) iki katman ağ güvenliğini sağlar.
  • Docker + davfs2 + firewalld kombinasyonu SELinux enforcing modda ek policy ve volume label yönetimi gerektirir.
  • Utils VPS'te de disabled yapılmış; tutarlılık sağlanır.
# /etc/selinux/config içinde:
SELINUX=disabled
# Değişiklik reboot sonrası 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 Konfigürasyonu

/etc/fail2ban/jail.local içeriği:

[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 içinde
  • maxretry: 5 başarısız giriş → ban
  • ignoreip: admin CIDR'ları ban'dan muaf tutar

Ansible'da admin_allowed_cidrs listesi space-separated stringe dönüştürülüp template'e basılır.

Not: Docker iptables kuralları firewalld ile etkileşebilir. Hetzner Cloud firewall asıl dış perimeter kabul edilir; firewalld host içinde ikinci katman olarak kullanılır.

Docker Role

Her iki node (iklim-app-01 ve iklim-db-01) üzerinde de zorunludur. DB node'u Swarm Worker olarak ağa dahil olacağı için Docker Engine her iki makinede de kurulu olmalıdır.

Docker kurulumu resmi Docker dnf repository üzerinden yapılır:

  • 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 kullanılmayacak. Production benzeri test ortamı için paket repository yolu tercih edilir.

Swarm Role

  • iklim-app-01 üzerinde Swarm Manager olarak init edilir.
  • iklim-db-01 üzerinde Swarm Worker olarak join edilir (Overlay network erişimi için).
  • advertise addr: 10.10.10.11 (manager için)
  • overlay network:
    • iklimco-net
    • driver: overlay
    • attachable: true
  • Node etiketleri:
    • iklim-app-01 -> type=service
    • iklim-db-01 -> role=db
  • iklim-app-01 üzerinde hem manager hem worker (Active) görevini sürdürür.

Node Directory Role

iklim-app-01 üzerinde deploy ön koşulları:

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

DB node üzerinde manuel DB kurulumu için minimum:

/opt/iklimco
/opt/iklimco/db
/opt/iklimco/backup

StorageBox DAVFS Mount Role

Her iki node'a uygulanır (iklim-app-01 ve iklim-db-01).

Amaç

Hetzner StorageBox'u WebDAV (DAVFS) protokolü üzerinden /mnt/storagebox olarak mount eder. Docker volume'ları bu dizine bağlanarak veri kalıcılığını ve yedeklemeyi sağlar.

Test Ortamı Sub-Account

Parametre Değişken Değer
Ana hesap storagebox_account u469968
Sub-account storagebox_user u469968-sub4
WebDAV URL storagebox_url https://u469968-sub4.your-storagebox.de/
Mount point storagebox_mount_point /mnt/storagebox

Role Değişkenleri

Tüm değişkenler group_vars/all/vars.yml içinde tanımlanır:

storagebox_account: "u469968"
storagebox_user: "{{ storagebox_account }}-sub4"
storagebox_url: "https://{{ storagebox_user }}.your-storagebox.de/"
storagebox_password: "{{ vault_storagebox_password }}"
storagebox_mount_point: "/mnt/storagebox"

Prod ortamında suffix sub4sub5 olarak değişir.

Şifreler Ansible Vault ile şifreli group_vars/all/vault.yml içinde tutulur:

ansible-vault edit group_vars/all/vault.yml

vault.yml içeriği:

vault_storagebox_password: "SUB_ACCOUNT_PAROLASI"
vault_iklim_password: "IKLIM_KULLANICI_PAROLASI"

Adımlar

  1. davfs2 kurulumu

    - name: Install davfs2
      ansible.builtin.dnf:
        name: davfs2
        state: present
    
  2. Kimlik bilgileri dosyası (/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 oluştur

    - 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 başarısı için dizine bir marker dosyası yazılabilir:

    - 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 şifreleri asla plaintext olarak repository'e eklenmez; Ansible Vault zorunludur.
  • Mount noktası reboot'ta _netdev flag'ı sayesinde network hazır olduktan sonra otomatik mount edilir.
  • Docker Swarm servisleri /mnt/storagebox/<env>/<service>/ altındaki dizinleri bind mount olarak kullanır.

StorageBox SSH Key Role

Her iki node'a uygulanır (iklim-app-01 ve iklim-db-01).

Amaç

Sunucu üzerinde ed25519 SSH anahtar çifti üretilir ve StorageBox ana hesabına yüklenir. Bu sayede CI/CD pipeline'ları STORAGEBOX_SSH_PRIV Gitea secret'ini kullanarak şifresiz erişim sağlayabilir.

Adımlar

  1. SSH Key üretimi

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

    Bu adım manuel yapılır (ilk kez şifre gerektirir):

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

    Sonraki erişimler şifresiz çalışır:

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

    Gitea → Organization Settings → Actions → Secrets:

    Secret Adı Değer
    STORAGEBOX_SSH_PRIV /root/.ssh/id_ed25519_storagebox içeriği
    STORAGEBOX_SSH_PUB /root/.ssh/id_ed25519_storagebox.pub içeriği

    Key içeriğini almak için:

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

Notlar

  • Her sunucu için ayrı key üretilir; tüm public key'ler StorageBox ana hesabına yüklenir.
  • Private key asla repo'ya commit edilmez; yalnızca Gitea secret olarak saklanır.

Kabul Kriterleri