{"id":1686,"date":"2025-11-11T15:45:22","date_gmt":"2025-11-11T12:45:22","guid":{"rendered":"https:\/\/www.dchost.com\/blog\/bulutun-ilk-nefesi-cloud%e2%80%91init-ve-ansible-ile-tekrar-uretilebilir-vps-nasil-kurulur\/"},"modified":"2025-11-11T15:45:22","modified_gmt":"2025-11-11T12:45:22","slug":"bulutun-ilk-nefesi-cloud%e2%80%91init-ve-ansible-ile-tekrar-uretilebilir-vps-nasil-kurulur","status":"publish","type":"post","link":"https:\/\/www.dchost.com\/blog\/bulutun-ilk-nefesi-cloud%e2%80%91init-ve-ansible-ile-tekrar-uretilebilir-vps-nasil-kurulur\/","title":{"rendered":"Bulutun \u0130lk Nefesi: cloud\u2011init ve Ansible ile Tekrar \u00dcretilebilir VPS Nas\u0131l Kurulur?"},"content":{"rendered":"<div class=\"dchost-blog-content-wrapper\"><div id=\"toc_container\" class=\"toc_transparent no_bullets\"><p class=\"toc_title\">\u0130&ccedil;indekiler<\/p><ul class=\"toc_list\"><li><a href=\"#Bir_VPS_Ilk_Nefes_ve_Kucuk_Bir_Aydinlanma\"><span class=\"toc_number toc_depth_1\">1<\/span> Bir VPS, \u0130lk Nefes ve K\u00fc\u00e7\u00fck Bir Ayd\u0131nlanma<\/a><\/li><li><a href=\"#Neden_Ilk_Bootta_Otomasyon_Cunku_Zaman_Dikkat_ve_Tutarlilik\"><span class=\"toc_number toc_depth_1\">2<\/span> Neden \u0130lk Boot\u2019ta Otomasyon? \u00c7\u00fcnk\u00fc Zaman, Dikkat ve Tutarl\u0131l\u0131k<\/a><\/li><li><a href=\"#cloudinit_Temelleri_Kucuk_Bir_YAML_Buyuk_Bir_Baslangic\"><span class=\"toc_number toc_depth_1\">3<\/span> cloud\u2011init Temelleri: K\u00fc\u00e7\u00fck Bir YAML, B\u00fcy\u00fck Bir Ba\u015flang\u0131\u00e7<\/a><\/li><li><a href=\"#Ilk_Bootta_Kullanici_ve_SSH_Guvenligi_Sakin_Net_ve_Tek_Sefer\"><span class=\"toc_number toc_depth_1\">4<\/span> \u0130lk Boot\u2019ta Kullan\u0131c\u0131 ve SSH G\u00fcvenli\u011fi: Sakin, Net ve Tek Sefer<\/a><\/li><li><a href=\"#Guvenlik_Duvari_ve_Fail2ban_Sessiz_Kahramanlari_Ilk_Gunden_Sahneye_Almak\"><span class=\"toc_number toc_depth_1\">5<\/span> G\u00fcvenlik Duvar\u0131 ve Fail2ban: Sessiz Kahramanlar\u0131 \u0130lk G\u00fcnden Sahneye Almak<\/a><\/li><li><a href=\"#Ansible_ile_Servis_Otomasyonu_Recete_Defterini_Sunucuya_Verin\"><span class=\"toc_number toc_depth_1\">6<\/span> Ansible ile Servis Otomasyonu: Re\u00e7ete Defterini Sunucuya Verin<\/a><\/li><li><a href=\"#Servisleri_Ilk_Bootta_Kalicilastirmak_systemd_ile_Kucuk_Bir_Dans\"><span class=\"toc_number toc_depth_1\">7<\/span> Servisleri \u0130lk Boot\u2019ta Kal\u0131c\u0131la\u015ft\u0131rmak: systemd ile K\u00fc\u00e7\u00fck Bir Dans<\/a><\/li><li><a href=\"#Gizli_Bilgiler_Ortam_Degiskenleri_ve_Kucuk_Sirlar\"><span class=\"toc_number toc_depth_1\">8<\/span> Gizli Bilgiler, Ortam De\u011fi\u015fkenleri ve K\u00fc\u00e7\u00fck S\u0131rlar<\/a><\/li><li><a href=\"#Test_Ederken_Korkmadan_Deneyin_NoCloud_ve_Yerel_Emulasyon\"><span class=\"toc_number toc_depth_1\">9<\/span> Test Ederken Korkmadan Deneyin: NoCloud ve Yerel Em\u00fclasyon<\/a><\/li><li><a href=\"#Kucuk_Tuzaklar_ve_Nazik_Cozumler_Deneyimlerden_Notlar\"><span class=\"toc_number toc_depth_1\">10<\/span> K\u00fc\u00e7\u00fck Tuzaklar ve Nazik \u00c7\u00f6z\u00fcmler: Deneyimlerden Notlar<\/a><\/li><li><a href=\"#Guncellemeler_Rotasyon_ve_Kucuk_Bakim_Torenleri\"><span class=\"toc_number toc_depth_1\">11<\/span> G\u00fcncellemeler, Rotasyon ve K\u00fc\u00e7\u00fck Bak\u0131m T\u00f6renleri<\/a><\/li><li><a href=\"#Kapanis_Ilk_Nefeste_Dogan_Standart\"><span class=\"toc_number toc_depth_1\">12<\/span> Kapan\u0131\u015f: \u0130lk Nefeste Do\u011fan Standart<\/a><\/li><\/ul><\/div>\n<h2 id=\"section-1\"><span id=\"Bir_VPS_Ilk_Nefes_ve_Kucuk_Bir_Aydinlanma\">Bir <a href=\"https:\/\/www.dchost.com\/tr\/vps\">VPS<\/a>, \u0130lk Nefes ve K\u00fc\u00e7\u00fck Bir Ayd\u0131nlanma<\/span><\/h2>\n<p>Ge\u00e7en hafta, k\u00fc\u00e7\u00fck bir VPS\u2019i h\u0131zl\u0131ca aya\u011fa kald\u0131rmam gerekti. Ak\u015fam\u00fcst\u00fc g\u00fcne\u015f camdan k\u0131r\u0131l\u0131rken, \u201cBir kullan\u0131c\u0131 a\u00e7, SSH\u2019\u0131 s\u0131k\u0131la\u015ft\u0131r, firewall\u2019u yak, uygulamay\u0131 kald\u0131r\u201d diye diye klavyeye vuruyorum. Tam her \u015fey bitti derken ufak bir ayar unutulmu\u015f; root giri\u015fini kapatmam\u0131\u015f\u0131m. Geri d\u00f6n, d\u00fczelt, restart et. Hi\u00e7 ba\u015f\u0131n\u0131za geldi mi? Ayn\u0131 ad\u0131mlar\u0131 defalarca tekrarlarken, bir detay g\u00f6zden ka\u00e7ar ve b\u00fct\u00fcn heves s\u00f6ner. O an dedim ki, bu i\u015fin ilk nefeste d\u00fczg\u00fcn ve tekrar \u00fcretilebilir olmas\u0131 \u015fart.<\/p>\n<p>Benim i\u00e7in \u00e7\u00f6z\u00fcm, <strong>cloud\u2011init<\/strong> ile makine ilk kez boot eder etmez temel i\u015fleri hallettirmek, ard\u0131ndan <strong>Ansible<\/strong> ile t\u00fcm servisleri ve ince ayarlar\u0131 idempotent bir \u015fekilde da\u011f\u0131tmak oldu. Bu yaz\u0131da, VPS\u2019inize ilk nefesinde kullan\u0131c\u0131, g\u00fcvenlik ve servis otomasyonunu nas\u0131l verece\u011finizi anlataca\u011f\u0131m. Arada ufak hikayeler, baz\u0131 pratik kod \u00f6rnekleri ve can s\u0131k\u0131c\u0131 tuzaklardan ka\u00e7\u0131nma yollar\u0131 da var. Mesela \u015f\u00f6yle d\u00fc\u015f\u00fcn\u00fcn: T\u0131k diye bir butona bas\u0131yorsunuz ve be\u015f dakika sonra ayn\u0131 ayarlarla ikinci, \u00fc\u00e7\u00fcnc\u00fc VPS\u2019iniz de haz\u0131r. G\u00fczel de\u011fil mi?<\/p>\n<h2 id=\"section-2\"><span id=\"Neden_Ilk_Bootta_Otomasyon_Cunku_Zaman_Dikkat_ve_Tutarlilik\">Neden \u0130lk Boot\u2019ta Otomasyon? \u00c7\u00fcnk\u00fc Zaman, Dikkat ve Tutarl\u0131l\u0131k<\/span><\/h2>\n<p>Bir sunucuyu elle kurarken ilk on dakikada yap\u0131lanlar genelde birbirine benzer. Kullan\u0131c\u0131 a\u00e7\u0131l\u0131r, sudo verilir, SSH anahtarlar\u0131 y\u00fcklenir, parolal\u0131 giri\u015f kapat\u0131l\u0131r, ufw veya nftables ile kap\u0131lar ayarlan\u0131r. Yine de her seferinde ufak farklar \u00e7\u0131kar. Bir defas\u0131nda authorized_keys dosyas\u0131n\u0131 yanl\u0131\u015f izinle b\u0131rakm\u0131\u015ft\u0131m; giri\u015fler tek tek patlam\u0131\u015ft\u0131. O g\u00fcn anlad\u0131m ki ilk boot\u2019ta, tek bir kaynak dosyadan beslenen bir otomasyon b\u00fct\u00fcn bu k\u00fc\u00e7\u00fck hatalar\u0131 t\u00f6rp\u00fcl\u00fcyor. \u00dcstelik ayn\u0131 ad\u0131mlar, ayn\u0131 s\u0131rayla uygulan\u0131nca sonu\u00e7 hep ayn\u0131 oluyor.<\/p>\n<p>cloud\u2011init burada sihirli bir anahtar gibi. Sanal sunucu sa\u011flay\u0131c\u0131n\u0131z\u0131n kullan\u0131c\u0131 verisi alan\u0131na bir YAML dosyas\u0131 koyuyorsunuz; sunucu ilk aya\u011fa kalkt\u0131\u011f\u0131nda o dosyadaki her ad\u0131m\u0131 uyguluyor. Ard\u0131ndan sahneyi Ansible\u2019a b\u0131rak\u0131yorsunuz. O da \u201cE\u011fer bu paket kurulu de\u011filse kur, bu dosya bu i\u00e7erikte de\u011filse d\u00fczelt\u201d diyerek, tekrarlad\u0131\u011f\u0131n\u0131zda dahi ayn\u0131 sonucu g\u00fcvenle \u00fcretmeye devam ediyor. Yani makine ne yapaca\u011f\u0131n\u0131 sizden \u00f6\u011freniyor, siz de klavye ba\u015f\u0131nda ayn\u0131 komutlar\u0131 ezberlemekten kurtuluyorsunuz.<\/p>\n<h2 id=\"section-3\"><span id=\"cloudinit_Temelleri_Kucuk_Bir_YAML_Buyuk_Bir_Baslangic\">cloud\u2011init Temelleri: K\u00fc\u00e7\u00fck Bir YAML, B\u00fcy\u00fck Bir Ba\u015flang\u0131\u00e7<\/span><\/h2>\n<p>cloud\u2011init\u2019i ilk kez g\u00f6r\u00fcnce insan\u0131n akl\u0131na \u201cBu kadarc\u0131k dosya ile t\u00fcm kurulum mu?\u201d sorusu geliyor. Evet, \u00e7o\u011fu zaman yetiyor. <strong>users<\/strong> b\u00f6l\u00fcm\u00fcnde kullan\u0131c\u0131lar\u0131 tan\u0131mlars\u0131n\u0131z, <strong>ssh_authorized_keys<\/strong> ile anahtarlar\u0131n\u0131z\u0131 yerle\u015ftirirsiniz, <strong>packages<\/strong> ile temel paketleri kurars\u0131n\u0131z. Hatta <strong>write_files<\/strong> ile yap\u0131land\u0131rma dosyalar\u0131n\u0131 yazd\u0131rabilir, <strong>runcmd<\/strong> ile k\u00fc\u00e7\u00fck komut dizileri \u00e7al\u0131\u015ft\u0131rabilirsiniz. Hepsi, makine ilk kez nefes al\u0131rken.<\/p>\n<p>Mesela \u015f\u00f6yle d\u00fc\u015f\u00fcn\u00fcn: Deploy kullan\u0131c\u0131s\u0131n\u0131 olu\u015fturup sudo yetkisi verelim, parolal\u0131 giri\u015fleri kapatal\u0131m, ufw ve fail2ban\u2019\u0131 kurup aya\u011fa kald\u0131ral\u0131m, sonra da Ansible ile daha ileri ayarlar\u0131 \u00e7ekelim. A\u015fa\u011f\u0131daki kapsay\u0131c\u0131 bir ba\u015flang\u0131\u00e7 olabilir:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">#cloud-config\nusers:\n  - name: deploy\n    gecos: Deploy User\n    groups: [sudo, docker]\n    sudo: &quot;ALL=(ALL) NOPASSWD:ALL&quot;\n    shell: \/bin\/bash\n    ssh_authorized_keys:\n      - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI...kendi_anahtariniz...\n\npackage_update: true\npackage_upgrade: true\npackages:\n  - ufw\n  - fail2ban\n  - curl\n  - git\n  - python3\n  - python3-pip\n\nwrite_files:\n  - path: \/etc\/ssh\/sshd_config.d\/01-hardening.conf\n    permissions: '0644'\n    content: |\n      PasswordAuthentication no\n      PermitRootLogin no\n      PubkeyAuthentication yes\n\nruncmd:\n  - systemctl restart ssh\n  - ufw allow OpenSSH\n  - ufw allow 80,443\/tcp\n  - ufw --force enable\n  - systemctl enable --now fail2ban\n  - pip3 install --upgrade pip\n  - pip3 install ansible\n  - ansible-pull -U https:\/\/github.com\/yourorg\/infra.git -C main site.yml -i localhost, --extra-vars &quot;env=prod&quot;\n<\/code><\/pre>\n<p>Bu dosyay\u0131 VPS sa\u011flay\u0131c\u0131n\u0131z\u0131n \u201cUser data\u201d alan\u0131na yap\u0131\u015ft\u0131rd\u0131\u011f\u0131n\u0131zda, sunucunuz a\u00e7\u0131l\u0131r a\u00e7\u0131lmaz t\u00fcm bu ad\u0131mlar ger\u00e7ekle\u015fir. Ben i\u015fin \u201cansible-pull\u201d k\u0131sm\u0131n\u0131 \u00e7ok seviyorum; sunucu, sanki mutfa\u011fa girip kendi tarif defterini raftan al\u0131yor ve yemek yapmaya ba\u015fl\u0131yor. Tabii o defteri, yani Git deposunu d\u00fczenli tutmak da size d\u00fc\u015f\u00fcyor.<\/p>\n<p>Daha fazla ayr\u0131nt\u0131 ve mod\u00fcl i\u00e7in <a href=\"https:\/\/cloudinit.readthedocs.io\/en\/latest\/\" rel=\"nofollow noopener\" target=\"_blank\">cloud\u2011init belgelerine<\/a> g\u00f6z atman\u0131z\u0131 \u00f6neririm. Orada sadece kullan\u0131c\u0131 ve paketler de\u011fil, a\u011f ayarlar\u0131ndan dosya sistemine kadar pek \u00e7ok konuyu ilk boot\u2019a s\u0131\u011fd\u0131rabilece\u011finizi g\u00f6r\u00fcrs\u00fcn\u00fcz.<\/p>\n<h2 id=\"section-4\"><span id=\"Ilk_Bootta_Kullanici_ve_SSH_Guvenligi_Sakin_Net_ve_Tek_Sefer\">\u0130lk Boot\u2019ta Kullan\u0131c\u0131 ve SSH G\u00fcvenli\u011fi: Sakin, Net ve Tek Sefer<\/span><\/h2>\n<p>SSH g\u00fcvenli\u011fi, tekrar \u00fcretilebilirli\u011fin \u015fefkatli ama titiz taraf\u0131. Bir kere kurars\u0131n\u0131z, sonra unutursunuz. Ama ilk kurulumda a\u00e7\u0131k kap\u0131 b\u0131rakmak istemezsiniz. \u0130lk boot\u2019ta yeni bir kullan\u0131c\u0131 olu\u015fturup sudo verin, <strong>authorized_keys<\/strong> ile anahtar\u0131 girin, parolal\u0131 giri\u015fleri kapat\u0131n ve root giri\u015fini tamamen devre d\u0131\u015f\u0131 b\u0131rak\u0131n. K\u00fc\u00e7\u00fck bir dosya ile koca bir riski s\u0131f\u0131rlam\u0131\u015f olursunuz.<\/p>\n<p>SSH\u2019\u0131 biraz daha sevgiyle s\u0131k\u0131la\u015ft\u0131rmak isterseniz, ba\u011flant\u0131 denemelerini s\u0131n\u0131rlayan ayarlar ve <strong>Fail2ban<\/strong> gibi ufak yard\u0131mc\u0131lar \u00e7ok i\u015fe yarar. \u0130lk g\u00fcnlerde bunlara gerek yokmu\u015f gibi hissettiren \u015fey, bir gece ans\u0131z\u0131n loglara d\u00fc\u015fen ba\u015far\u0131s\u0131z giri\u015f denemeleriyle anlam kazan\u0131r. Kendi pratik notlar\u0131m\u0131 derledi\u011fim \u201c<a href=\"https:\/\/www.dchost.com\/blog\/vpste-ssh-guvenligi-nasil-saglamlasir-fido2-anahtarlari-ssh-ca-ve-rotasyonun-sicacik-yolculugu\/\">VPS\u2019te SSH g\u00fcvenli\u011fini s\u0131cak tutman\u0131n yollar\u0131<\/a>\u201d ba\u015fl\u0131kl\u0131 yaz\u0131 da i\u015fin devam\u0131n\u0131 merak edenlere fikir verebilir.<\/p>\n<p>Ansible taraf\u0131nda da bu i\u015fin bir rol\u00fc olur. Mesela \u201cssh_hardening\u201d benzeri bir rol, belirli dosyalar\u0131n i\u00e7eriklerini, dosya izinlerini ve servis ayarlar\u0131n\u0131 tek tek d\u00fczenler. Bir kez tan\u0131mlay\u0131p t\u00fcm sunuculara yayarken, her seansta ayn\u0131 sonucu al\u0131rs\u0131n\u0131z. Bu, beyin yorgunlu\u011funu al\u0131p yerine keyifli bir rutin koymak gibi.<\/p>\n<h2 id=\"section-5\"><span id=\"Guvenlik_Duvari_ve_Fail2ban_Sessiz_Kahramanlari_Ilk_Gunden_Sahneye_Almak\">G\u00fcvenlik Duvar\u0131 ve Fail2ban: Sessiz Kahramanlar\u0131 \u0130lk G\u00fcnden Sahneye Almak<\/span><\/h2>\n<p>Bir VPS, internete a\u00e7\u0131ld\u0131\u011f\u0131 an dikkat \u00e7eker. Bu ka\u00e7\u0131n\u0131lmaz. Bu y\u00fczden ilk boot\u2019ta g\u00fcvenlik duvar\u0131n\u0131 aya\u011fa kald\u0131rmak iyi hissettirir. Ufw ile ba\u015flamak kolay; sadece belli portlar\u0131 a\u00e7ar, di\u011ferlerini kapat\u0131rs\u0131n\u0131z. Biraz daha ileri gidip kurallar\u0131 detayland\u0131rmak isterseniz, <strong>nftables<\/strong> ile daha zengin bir dil ve esneklik elde edersiniz. Ben, kurallar\u0131n tekrar \u00fcretilebilir olmas\u0131n\u0131 sevdi\u011fim i\u00e7in, temel seti cloud\u2011init ile kurdurup, ince ayarlar\u0131 Ansible rol\u00fcne b\u0131rak\u0131yorum.<\/p>\n<p>nftables\u2019\u0131 daha keyifli kullanmak i\u00e7in pratik \u00f6rneklerle haz\u0131rlad\u0131\u011f\u0131m \u201c<a href=\"https:\/\/www.dchost.com\/blog\/nftables-ile-vps-guvenlik-duvari-rehberi-rate-limit-port-knocking-ve-ipv6-kurallari-nasil-tatli-tatli-kurulur\/\">nftables ile VPS G\u00fcvenlik Duvar\u0131 Rehberi<\/a>\u201d yaz\u0131s\u0131na g\u00f6z atabilirsiniz. Orada rate limit ve IPv6 gibi detaylar\u0131 nazik\u00e7e elden ge\u00e7iriyoruz. Ayr\u0131ca Fail2ban\u2019\u0131n ufak hapsetme hamleleri, kaba kuvvet denemelerini ilk dakikada yumu\u015fat\u0131r. \u0130lk boot\u2019ta \u201csystemctl enable &#8211;now fail2ban\u201d demek bile \u00e7o\u011fu durumda b\u00fcy\u00fck fark yarat\u0131r.<\/p>\n<p>Uygulama katman\u0131nda da k\u00fc\u00e7\u00fck \u00f6nlemler tatl\u0131 sonu\u00e7 verir. Mesela web uygulamalar\u0131n\u0131zda a\u015f\u0131r\u0131 istekleri biraz frenlemek isterseniz, \u201c<a href=\"https:\/\/www.dchost.com\/blog\/nginx-rate-limiting-ve-fail2ban-ile-wp%e2%80%91login-php-ve-xml%e2%80%91rpc-brute%e2%80%91force-saldirilarini-nasil-saksiya-alirsin\/\">Nginx rate limiting ile Fail2ban\u2019\u0131 el ele y\u00fcr\u00fctmek<\/a>\u201d hakk\u0131nda anlatt\u0131klar\u0131m\u0131n, burada kurdu\u011funuz temel g\u00fcvenlik yakla\u015f\u0131m\u0131yla g\u00fczelce birle\u015fti\u011fini g\u00f6receksiniz.<\/p>\n<h2 id=\"section-6\"><span id=\"Ansible_ile_Servis_Otomasyonu_Recete_Defterini_Sunucuya_Verin\">Ansible ile Servis Otomasyonu: Re\u00e7ete Defterini Sunucuya Verin<\/span><\/h2>\n<p>cloud\u2011init\u2019i, sahneye perde a\u00e7an g\u00f6revli gibi d\u00fc\u015f\u00fcn\u00fcn. As\u0131l oyunu oynayan genellikle Ansible oluyor. Ben \u201cansible-pull\u201d yap\u0131s\u0131n\u0131 seviyorum \u00e7\u00fcnk\u00fc push i\u00e7in merkezi bir ba\u011flant\u0131 a\u00e7mak zorunda kalm\u0131yorsunuz. Sunucu, Git deposuna gider, playbook\u2019u \u00e7eker ve kendi kendine uygular. Mesela Nginx, Docker ve uygulama rolleri ile k\u00fc\u00e7\u00fck bir platform \u015fablonu kurmak \u00e7ok do\u011fal ak\u0131yor.<\/p>\n<p>\u00d6rnek bir \u00fcst seviye playbook hayal edelim. Bu, tek makine i\u00e7in bile g\u00fczel; ama as\u0131l g\u00fcc\u00fcn\u00fc benzer makinelere \u00e7o\u011faltt\u0131\u011f\u0131n\u0131zda hissediyorsunuz:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">---\n- name: VPS temel kurulum ve uygulama rolleri\n  hosts: localhost\n  connection: local\n  become: true\n  vars:\n    domain: example.com\n    env: prod\n  roles:\n    - role: common\n    - role: ssh_hardening\n    - role: docker\n    - role: nginx\n    - role: app_deploy\n<\/code><\/pre>\n<p>Rollerin her biri k\u00fc\u00e7\u00fck, net ve idempotent olmal\u0131. common rol\u00fc ile zaman dilimi, locale ve log rotasyonunu; ssh_hardening ile servis ayarlar\u0131n\u0131; docker ile runtime ve kullan\u0131c\u0131 grubunu; nginx ile site tan\u0131mlar\u0131n\u0131; app_deploy ile de uygulaman\u0131z\u0131 ve environment dosyalar\u0131n\u0131z\u0131 sa\u011flayabilirsiniz. Ansible\u2019\u0131n \u201c\u015fu dosya bu i\u00e7erikte mi, de\u011filse b\u00f6yle yap\u201d yakla\u015f\u0131m\u0131 sayesinde, playbook\u2019u ka\u00e7 kez \u00e7al\u0131\u015ft\u0131r\u0131rsan\u0131z \u00e7al\u0131\u015ft\u0131r\u0131n, sonu\u00e7 ayn\u0131 kal\u0131r. Bu, tekrar \u00fcretilebilirli\u011fin en sevdi\u011fim yan\u0131.<\/p>\n<p>Hangi mod\u00fcller, hangi parametreler derken dal\u0131p giderseniz, resmi <a href=\"https:\/\/docs.ansible.com\/ansible\/latest\/\" rel=\"nofollow noopener\" target=\"_blank\">Ansible dok\u00fcmantasyonunu<\/a> bir yer imi gibi kenarda tutmak \u00e7ok yard\u0131mc\u0131 oluyor. \u00d6zellikle file, template, copy, service, ufw (community mod\u00fcllerinde) ve docker_* mod\u00fclleri bu yolculukta s\u0131k s\u0131k el sall\u0131yor.<\/p>\n<h2 id=\"section-7\"><span id=\"Servisleri_Ilk_Bootta_Kalicilastirmak_systemd_ile_Kucuk_Bir_Dans\">Servisleri \u0130lk Boot\u2019ta Kal\u0131c\u0131la\u015ft\u0131rmak: systemd ile K\u00fc\u00e7\u00fck Bir Dans<\/span><\/h2>\n<p>Bazen tek seferlik bir komut yetmez; bir servis tan\u0131m\u0131 gerekir. cloud\u2011init ile bir <strong>systemd service<\/strong> dosyas\u0131 yazd\u0131rmak, ard\u0131ndan Ansible rol\u00fcnde \u015fablonla g\u00fcncellemek iyi bir ikili. Mesela Docker Compose ile \u00e7al\u0131\u015fan bir uygulaman\u0131z var; \u201cdocker compose up\u201d demek yerine, bunu bir unit haline getirip sistem a\u00e7\u0131ld\u0131\u011f\u0131nda \u00e7al\u0131\u015fmas\u0131n\u0131 istersiniz. O zaman write_files ile unit dosyas\u0131n\u0131 yazd\u0131r\u0131p, runcmd ile \u201csystemctl enable &#8211;now\u201d diyebilirsiniz.<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">write_files:\n  - path: \/etc\/systemd\/system\/myapp.service\n    permissions: '0644'\n    content: |\n      [Unit]\n      Description=My App (Compose)\n      After=network-online.target docker.service\n      Wants=network-online.target\n\n      [Service]\n      Type=oneshot\n      RemainAfterExit=yes\n      WorkingDirectory=\/opt\/myapp\n      ExecStart=\/usr\/bin\/docker compose up -d\n      ExecStop=\/usr\/bin\/docker compose down\n      Restart=on-failure\n      RestartSec=5\n\n      [Install]\n      WantedBy=multi-user.target\n\nruncmd:\n  - systemctl daemon-reload\n  - systemctl enable --now myapp.service\n<\/code><\/pre>\n<p>\u0130lerleyen g\u00fcnlerde bu unit dosyas\u0131n\u0131 Ansible\u2019da bir template\u2019e ta\u015f\u0131y\u0131p de\u011fi\u015fkenlerle beslemek daha konforlu oluyor. Versiyon y\u00fckseltirken sadece imaj etiketini de\u011fi\u015ftiriyor, playbook\u2019u \u00e7al\u0131\u015ft\u0131r\u0131yorsunuz. Hepsi o. Detay sevenler i\u00e7in <a href=\"https:\/\/www.freedesktop.org\/software\/systemd\/man\/latest\/systemd.service.html\" rel=\"nofollow noopener\" target=\"_blank\">systemd service tan\u0131mlar\u0131<\/a> belgeleri, uzun bir ak\u015fam\u0131 keyifli bir \u00f6\u011frenme turuna \u00e7evirebilir.<\/p>\n<h2 id=\"section-8\"><span id=\"Gizli_Bilgiler_Ortam_Degiskenleri_ve_Kucuk_Sirlar\">Gizli Bilgiler, Ortam De\u011fi\u015fkenleri ve K\u00fc\u00e7\u00fck S\u0131rlar<\/span><\/h2>\n<p>Tekrar \u00fcretilebilirlik harika, ama gizli bilgiler i\u015fi biraz \u00f6zen istiyor. API anahtarlar\u0131, veritaban\u0131 parolalar\u0131 ve benzeri s\u0131rlar\u0131 cloud\u2011init i\u00e7ine g\u00f6mmek istemezsiniz. Bunun yerine, Ansible taraf\u0131nda <strong>Vault<\/strong> kullanmak veya secrets\u2019lar\u0131 bir <strong>CI\/CD<\/strong> sistemi \u00fczerinden \u201cansible-pull\u201d komutuna tek seferlik de\u011fi\u015fken olarak enjekte etmek iyi \u00e7al\u0131\u015f\u0131yor. Local\u2019de test ederken sahte de\u011ferler, prod\u2019da ger\u00e7ek de\u011ferler\u2026 Hepsi ayn\u0131 playbook\u2019ta anlaml\u0131 bir ak\u0131\u015fa oturuyor.<\/p>\n<p>Ortam de\u011fi\u015fkenlerini .env dosyalar\u0131nda tutuyorsan\u0131z, template mod\u00fcl\u00fc ile <strong>owner\/grup\/izin<\/strong> ayarlar\u0131n\u0131 titizlikle set edin. Ayr\u0131ca g\u00fcnl\u00fck dosyalar\u0131 ve d\u00f6k\u00fcmler i\u00e7in logrotate veya sistemin kendi journal rotasyon ayarlar\u0131n\u0131 g\u00f6zden ge\u00e7irmek iyi bir al\u0131\u015fkanl\u0131k. \u0130lk g\u00fcnden bu disipline girince, aylar sonra bile makine \u201cben haz\u0131r\u0131m\u201d der gibi sakin \u00e7al\u0131\u015f\u0131yor.<\/p>\n<h2 id=\"section-9\"><span id=\"Test_Ederken_Korkmadan_Deneyin_NoCloud_ve_Yerel_Emulasyon\">Test Ederken Korkmadan Deneyin: NoCloud ve Yerel Em\u00fclasyon<\/span><\/h2>\n<p>\u201cPeki bunu her seferinde ger\u00e7ek bir VPS\u2019te mi deneyece\u011fiz?\u201d diye soran \u00e7ok oluyor. Asl\u0131nda hay\u0131r. cloud\u2011init\u2019in <strong>NoCloud<\/strong> veri kayna\u011f\u0131 sayesinde, user-data dosyan\u0131z\u0131 yerelde bir ISO\u2019ya \u00e7evirip sanal bir makinede test edebilirsiniz. K\u00fc\u00e7\u00fck bir komut dizisiyle, sanki uzak bir sa\u011flay\u0131c\u0131daym\u0131\u015f gibi ilk boot senaryosunu canland\u0131r\u0131rs\u0131n\u0131z. Bu, \u00f6zellikle yaz\u0131m hatalar\u0131n\u0131 yakalamak i\u00e7in \u015fahane.<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\"># user-data.yaml dosyan\u0131z\u0131 haz\u0131rlay\u0131n\ncloud-localds user-data.iso user-data.yaml\n\n# QEMU ile ba\u015flat\u0131n (\u00f6rnek, minimal):\nqemu-system-x86_64 \n  -m 2048 \n  -drive file=disk.qcow2,if=virtio \n  -cdrom user-data.iso \n  -nic user,model=virtio \n  -enable-kvm\n<\/code><\/pre>\n<p>Ben genelde k\u00fc\u00e7\u00fck bir disk imaj\u0131 olu\u015fturup, user-data\u2019y\u0131 de\u011fi\u015ftirerek tekrar tekrar deniyorum. \u0130lk boot\u2019ta bekledi\u011fim dosyalar ve servisler aya\u011fa kalk\u0131nca i\u00e7im rahat ediyor. cloud\u2011init\u2019in NoCloud kullan\u0131m\u0131na dair \u00f6rnekler i\u00e7in <a href=\"https:\/\/cloudinit.readthedocs.io\/en\/latest\/\" rel=\"nofollow noopener\" target=\"_blank\">resmi belgeler<\/a> yine en g\u00fcvenli rehber oluyor. Test etti\u011finiz ak\u0131\u015f\u0131, canl\u0131ya aynen uygulad\u0131\u011f\u0131n\u0131zda s\u00fcrprizler azal\u0131yor.<\/p>\n<h2 id=\"section-10\"><span id=\"Kucuk_Tuzaklar_ve_Nazik_Cozumler_Deneyimlerden_Notlar\">K\u00fc\u00e7\u00fck Tuzaklar ve Nazik \u00c7\u00f6z\u00fcmler: Deneyimlerden Notlar<\/span><\/h2>\n<p>Bir kere, authorized_keys izinleri y\u00fcz\u00fcnden anahtarlar g\u00f6rmezden gelinmi\u015fti. Dosyay\u0131 0600 yap\u0131p sahibi do\u011fru kullan\u0131c\u0131ya verince d\u00fczeldi. Bir ba\u015fka sefer, runcmd s\u0131ras\u0131ndaki bir komutun exit kodu y\u00fcz\u00fcnden kalan ad\u0131mlar \u00e7al\u0131\u015fmam\u0131\u015ft\u0131; onu \u201c|| true\u201d ile yumu\u015fatarak ak\u0131\u015f\u0131 bozmamay\u0131 se\u00e7tim. Yine de bu t\u00fcr bypass\u2019lar\u0131 dikkatli kullan\u0131n; as\u0131l hatay\u0131 saklamas\u0131n.<\/p>\n<p>Bir de s\u0131ra meselesi var. cloud\u2011init a\u015famalar\u0131n\u0131 d\u00fc\u015f\u00fcn\u00fcrken, paket kurmay\u0131 ve yaz\u0131 dosyalar\u0131n\u0131 yerle\u015ftirmeyi, servisleri ba\u015flatmadan \u00f6nce bitirmek gerekiyor. Yoksa servis, eski ayarlarla ba\u015fl\u0131yor. Benim \u00e7\u00f6z\u00fcm\u00fcm: write_files biter bitmez \u201csystemctl daemon-reload\u201d ve ard\u0131ndan ilgili servislerin restart\u2019\u0131. K\u00fc\u00e7\u00fck gibi g\u00f6r\u00fcnen bu jest, gereksiz reboot\u2019lar\u0131 \u00e7\u00f6pe at\u0131yor.<\/p>\n<p>Uygulama taraf\u0131nda h\u0131zla yay\u0131na \u00e7\u0131karken, oturum a\u00e7ma u\u00e7 noktalar\u0131 ve y\u00f6netim ekranlar\u0131 biraz ekstra sevgi ister. Nginx taraf\u0131nda yumu\u015fak bir rate limit, Fail2ban ile yaramaz giri\u015fimleri s\u00fczmek iyi hissettiriyor. Bu yakla\u015f\u0131m\u0131, yukar\u0131da payla\u015ft\u0131\u011f\u0131m <a href=\"https:\/\/www.dchost.com\/blog\/nginx-rate-limiting-ve-fail2ban-ile-wp%e2%80%91login-php-ve-xml%e2%80%91rpc-brute%e2%80%91force-saldirilarini-nasil-saksiya-alirsin\/\">k\u0131lavuzdaki pratiklerle<\/a> birle\u015ftirince, \u201cilk g\u00fcn tedbirleri\u201d g\u00fczelce tamamlan\u0131yor.<\/p>\n<h2 id=\"section-11\"><span id=\"Guncellemeler_Rotasyon_ve_Kucuk_Bakim_Torenleri\">G\u00fcncellemeler, Rotasyon ve K\u00fc\u00e7\u00fck Bak\u0131m T\u00f6renleri<\/span><\/h2>\n<p>\u0130lk boot\u2019ta g\u00fcncelleme yapt\u0131rmak iyi, ama orada kalmas\u0131n. Ansible ile periyodik g\u00f6revler veya k\u00fc\u00e7\u00fck bir CI pipeline\u2019\u0131 kurup playbook\u2019u belirli aral\u0131klarla yeniden \u00e7al\u0131\u015ft\u0131rmak harika sonu\u00e7 veriyor. Rollerde k\u00fc\u00e7\u00fck d\u00fczeltmeler yapt\u0131k\u00e7a, t\u00fcm sunucular sessizce ayn\u0131 standarda \u00e7ekiliyor. \u00d6nemli nokta \u015fu: idempotent davran\u0131\u015f bozulmas\u0131n. Yani playbook tekrar \u00e7al\u0131\u015f\u0131nca \u201cyeniden yaratma\u201d de\u011fil \u201cayn\u0131 ayar\u0131 teyit etme\u201d olsun.<\/p>\n<p>SSH anahtarlar\u0131n\u0131n rotasyonu, kullan\u0131c\u0131 eri\u015fimlerinin g\u00f6zden ge\u00e7irilmesi ve sertifikalar\u0131n yenilenmesi gibi i\u015fler de bu t\u00f6rene dahil. Bu ak\u0131\u015f\u0131 otomatikle\u015ftirdik\u00e7e, ak\u015fam\u00fcst\u00fc kahveleri ger\u00e7ekten kahve tad\u0131nda oluyor. Zor anlarda, ekstra g\u00fcvenlik notlar\u0131na ihtiyac\u0131n\u0131z olursa \u201c<a href=\"https:\/\/www.dchost.com\/blog\/vpste-ssh-guvenligi-nasil-saglamlasir-fido2-anahtarlari-ssh-ca-ve-rotasyonun-sicacik-yolculugu\/\">SSH g\u00fcvenli\u011fini sa\u011flamla\u015ft\u0131rma<\/a>\u201d yaz\u0131s\u0131ndaki pratik \u00f6neriler yine elinizin alt\u0131nda.<\/p>\n<h2 id=\"section-12\"><span id=\"Kapanis_Ilk_Nefeste_Dogan_Standart\">Kapan\u0131\u015f: \u0130lk Nefeste Do\u011fan Standart<\/span><\/h2>\n<p>\u015eimdi ba\u015fa d\u00f6nelim. O ak\u015fam\u00fcst\u00fc, cloud\u2011init ve Ansible ikilisiyle kurdu\u011fum k\u00fc\u00e7\u00fck d\u00fczen bana \u015f\u00f6yle bir \u015fey \u00f6\u011fretti: \u0130lk nefes ne kadar temiz ve d\u00fczenliyse, sonras\u0131 da o kadar huzurlu ge\u00e7iyor. Kullan\u0131c\u0131lar, SSH ayarlar\u0131, g\u00fcvenlik duvar\u0131 ve servisler ilk boot\u2019ta yerini ald\u0131 m\u0131, makine ikinci, \u00fc\u00e7\u00fcnc\u00fc, d\u00f6rd\u00fcnc\u00fc kez tekrarland\u0131\u011f\u0131nda da ayn\u0131 hisle aya\u011fa kalk\u0131yor. Bir tu\u015fa bas\u0131p beklemek, ard\u0131ndan \u201ctam oldu\u201d demek\u2026 \u0130nsana iyi geliyor.<\/p>\n<p>Pratik bir \u00f6\u011f\u00fctle bitireyim. cloud\u2011init dosyan\u0131z\u0131 k\u00fc\u00e7\u00fck ba\u015flay\u0131n, \u00e7al\u0131\u015ft\u0131k\u00e7a b\u00fcy\u00fct\u00fcn. Ansible rollerini minik par\u00e7alara ay\u0131r\u0131n, her birini tek bir amaca odaklay\u0131n. Test etmekten \u00e7ekinmeyin; NoCloud ile yerelde prova yapmak \u00e7ok rahatlat\u0131yor. Ve unutmay\u0131n: G\u00fcvenlik ilk g\u00fcn davran\u0131\u015f\u0131d\u0131r. Bir sonraki yaz\u0131da, bu temelin \u00fczerine ufak bir CI\/CD ak\u0131\u015f\u0131 ve s\u0131f\u0131r kesintili da\u011f\u0131t\u0131m konu\u015fal\u0131m m\u0131? Umar\u0131m bu yaz\u0131 yolunuzu ayd\u0131nlatm\u0131\u015ft\u0131r. G\u00f6r\u00fc\u015fmek \u00fczere.<\/p>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>\u0130&ccedil;indekiler1 Bir VPS, \u0130lk Nefes ve K\u00fc\u00e7\u00fck Bir Ayd\u0131nlanma2 Neden \u0130lk Boot\u2019ta Otomasyon? \u00c7\u00fcnk\u00fc Zaman, Dikkat ve Tutarl\u0131l\u0131k3 cloud\u2011init Temelleri: K\u00fc\u00e7\u00fck Bir YAML, B\u00fcy\u00fck Bir Ba\u015flang\u0131\u00e74 \u0130lk Boot\u2019ta Kullan\u0131c\u0131 ve SSH G\u00fcvenli\u011fi: Sakin, Net ve Tek Sefer5 G\u00fcvenlik Duvar\u0131 ve Fail2ban: Sessiz Kahramanlar\u0131 \u0130lk G\u00fcnden Sahneye Almak6 Ansible ile Servis Otomasyonu: Re\u00e7ete Defterini Sunucuya Verin7 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1687,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26],"tags":[],"class_list":["post-1686","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-teknoloji"],"_links":{"self":[{"href":"https:\/\/www.dchost.com\/blog\/wp-json\/wp\/v2\/posts\/1686","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dchost.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dchost.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/wp-json\/wp\/v2\/comments?post=1686"}],"version-history":[{"count":0,"href":"https:\/\/www.dchost.com\/blog\/wp-json\/wp\/v2\/posts\/1686\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/wp-json\/wp\/v2\/media\/1687"}],"wp:attachment":[{"href":"https:\/\/www.dchost.com\/blog\/wp-json\/wp\/v2\/media?parent=1686"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/wp-json\/wp\/v2\/categories?post=1686"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/wp-json\/wp\/v2\/tags?post=1686"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}