[ OK ]Kernel başlatılıyor...
~/im/blog
Beni İşe Alın

Konuşalım

Çözülmesi gereken bir altyapı probleminiz mi var veya projeniz için desteğe mi ihtiyacınız var? Yeni projeler için bana ulaşabilirsiniz.

İletişime geç

Bağlantılar

Beni sosyal medyada ve profesyonel ağlarda bulun.

© 2026 Irfan Miral. Tüm hakları saklıdır.Geliştiren:Irfan Miral
Gizlilik PolitikasıŞartlar & Koşullar
Ana SayfaHizmetlerHakkımda/ÖzgeçmişBlogİletişimAraçlar
2026-02-05• 5 dk okuma süresi

Her Yeni Sunucuda Çalıştırdığım Ansible Playbook'u

DevOps Ansible Automation Linux Administration

Reklam

Daha önce her yeni sunucuda mutlaka uyguladığım kontrol listesi hakkında yazmıştım: root olmayan bir kullanıcı, sadece anahtar tabanlı (key-only) SSH, varsayılanı "reddet" olan bir güvenlik duvarı, Fail2ban ve otomatik güncellemeler. Bunları manuel olarak yapmak bir saatten az sürer. Zor bir iş değildir.

Ancak "her sunucu için manuel olarak bir saatten az", eğer üçten fazla sunucu yönetiyorsanız çok hızlı bir şekilde devasa bir yüke dönüşür. Dahası, küçük tutarsızlıkların sisteme sızdığı yer tam olarak manuel adımlardır. O gün sunucuyu kuran kişinin acelesi olduğu için bir sunucuda MaxAuthTries 3 ayarı yapılırken diğerinde unutulur.

Bunun kesin çözümü, kontrol listesini bir playbook'a çevirmektir. Her seferinde aynı adımlar, aynı sırada işlenir. Ve en önemlisi idempotent olmasıdır: zaten ayarlanmış bir sunucuda tekrar çalıştırdığınızda hiçbir şeyi bozmaz veya değiştirmez.

Playbook'un kendisi

---
- name: Yeni bir sunucu için temel güvenlik (hardening)
  hosts: new_servers
  become: true

  vars:
    admin_user: deploy
    ssh_public_key: "{{ lookup('file', '~/.ssh/id_ed25519.pub') }}"

  tasks:
    - name: Admin kullanıcısı oluştur
      user:
        name: "{{ admin_user }}"
        groups: sudo
        shell: /bin/bash
        create_home: true

    - name: Admin kullanıcısı için SSH anahtarı ekle
      authorized_key:
        user: "{{ admin_user }}"
        key: "{{ ssh_public_key }}"

    - name: SSH yapılandırmasını sıkılaştır (cloud-init varsayılanlarını ezer)
      copy:
        dest: /etc/ssh/sshd_config.d/99-hardening.conf
        content: |
          PermitRootLogin no
          PasswordAuthentication no
          MaxAuthTries 3
        mode: '0644'
      notify: restart sshd

    - name: UFW ve Fail2ban kur
      apt:
        name: [ufw, fail2ban]
        state: present
        update_cache: true

    - name: UFW varsayılanlarını ayarla
      ufw:
        direction: "{{ item.direction }}"
        policy: "{{ item.policy }}"
      loop:
        - { direction: incoming, policy: deny }
        - { direction: outgoing, policy: allow }

    - name: Gerekli portlara izin ver
      ufw:
        rule: allow
        port: "{{ item }}"
        proto: tcp
      loop: ['22', '80', '443']

    - name: UFW'yi aktifleştir
      ufw:
        state: enabled

    - name: Fail2ban'i aktifleştir
      systemd:
        name: fail2ban
        enabled: true
        state: started

    - name: Unattended-upgrades paketini kur
      apt:
        name: unattended-upgrades
        state: present

  handlers:
    - name: restart sshd
      systemd:
        name: ssh
        state: restarted

Çalıştırma

Yeni bir sunucu ayağa kalktığında envantere (inventory) eklenir ve playbook sadece o hedefe karşı çalıştırılır:

ansible-playbook -i inventory.ini baseline.yml -l yeni-sunucu-01 -u root

Sıfır bir sunucuda elimizdeki tek kullanıcı root olduğu için ilk çalıştırma mutlaka root olarak yapılmalıdır. Playbook tamamlandığında root girişi zaten kapatılmış olacaktır. Bundan sonraki tüm işlemler için giriş noktanız deploy kullanıcısıdır:

ansible-playbook -i inventory.ini baseline.yml -l yeni-sunucu-01 -u deploy

İlk çalıştırma tüm ağır yükü kaldırır: kullanıcıyı oluşturur, SSH'ı kilitler ve güvenlik duvarını kurar. Sondaki handler, sshd servisini yalnızca yapılandırma dosyasında gerçekten bir değişiklik yapıldıysa yeniden başlatır. Bundan sonraki her çalıştırma, sistemde hiçbir ayarın kaymadığını (drift) onaylayan boş bir işlemden ibaret olacaktır.

İnteraktif olarak deneyin: Bu sitedeki Ansible Baseline Generator aracı, bu playbook'u bir kullanıcı arayüzü üzerinden yapılandırmanıza olanak tanır. Admin kullanıcı adını, SSH portunu ayarlayabilir, dahil edilecek modülleri seçebilir ve hazırlanan tam YAML çıktısını kopyalayabilirsiniz.

Asıl mesele neden "idempotency" (tekrar edilebilirlik)?

Buradaki asıl değer, ilk gün tasarruf edilen o kısacık zaman değildir. Komutları elle yazmak o kadar da yavaşlatmaz. Asıl değer şudur: altı ay sonra, bir sunucunun gerçekten düzgün şekilde ayarlandığından mı yoksa bir kriz anında aceleye mi getirildiğinden emin olamadığımda, bu playbook'u tekrar çalıştırıp gerçeği görebilirim.

Eğer her şey olması gerektiği gibiyse, Ansible sıfır değişiklik raporlar ve ben yoluma devam ederim. Eğer eksik bir şey varsa, o an düzeltilir. O beş manuel adımdan hangisinin atlandığını hatırlamak zorunda kalmam.

Bu playbook kasıtlı olarak kısa tutulmuştur. Uygulama yığınlarını (stack) veya projeye özel servisleri kurmaz. Üzerine başka herhangi bir şey inşa edilmeden önce her sunucunun oturması gereken en temel zemindir. Bunu projeye özel playbook'lardan ayrı tutmak stabil kalmasını sağlar. Sık değişmeyen bir temel, her seferinde kodu baştan sona okumadan körü körüne güvenebileceğiniz bir temeldir.

Reklam

Yardıma mı ihtiyacınız var?

Eğer Konteynerleştirme ve Otomasyon işini sizin yerinize birinin halletmesini tercih ederseniz, benim asıl işim tam olarak bu.

İletişime Geç
ÖncekiKüçük Projeler İçin Kurtarıcı GitLab CI/CD Pipeline'ıSonraki Sunucu Yapılandırmaları Neden Aklınızda Değil Git'te Durmalı?