İçindekiler
- 1 Neden Terraform ve Ansible ile VPS Otomasyonu Kurmalısınız?
- 2 Genel Mimarinin Resmi: Terraform Nerede, Ansible Nerede?
- 3 Terraform ile VPS Altyapısını Kodlamak
- 4 Ansible ile VPS Konfigürasyonunu Kodlamak
- 5 Terraform Çıktısını Ansible Envanterine Bağlamak
- 6 Güvenlik, Secrets ve Erişim Yönetimi
- 7 Gerçekçi Senaryolar: DCHost Üzerinde Terraform + Ansible Kullanım Örnekleri
- 8 Sık Yapılan Hatalar ve İyileştirme İpuçları
- 9 DCHost ile Terraform ve Ansible Otomasyonunu Hayata Geçirmek
Neden Terraform ve Ansible ile VPS Otomasyonu Kurmalısınız?
Yeni bir proje için VPS altyapısını planlarken genellikle aynı sorular etrafında dönüyoruz: Hangi boyutta VPS alacağız, hangi portlar açılacak, hangi paketler kurulacak, SSH anahtarları nasıl dağıtılacak, güvenlik duvarı kuralları nasıl standart olacak? Bir projede elle yaptığınız her adımı, birkaç ay sonra başka bir ortamda tekrar yapmaya çalıştığınızda aradaki küçük farkların nasıl büyük sorunlara dönüştüğünü mutlaka yaşamışsınızdır. Bir yerde ufw açık, diğerinde kapalı; birinde swap var, diğerinde yok; PHP ayarları iki ortamda da farklı…
Tam da bu noktada Terraform + Ansible ikilisi hayat kurtarıyor. Terraform ile VPS altyapınızı kod olarak tanımlayıp, Ansible ile de işletim sistemi ve uygulama konfigürasyonunu tekrar üretilebilir hale getirdiğinizde, aynı sunucuyu her seferinde tek komutla ayağa kaldırabilirsiniz. DCHost tarafında biz de günlük operasyonlarımızda bu yaklaşımı kullanıyoruz: staging ve üretim ortamlarını senkron tutmak, hızlı felaket kurtarma yapabilmek ve ekipteki herkesin aynı oyunu oynamasını sağlamak için altyapı kodunu zorunlu görüyoruz.
Bu yazıda, DCHost üzerinde Terraform ve Ansible ile tamamen otomatik VPS kurulum akışını adım adım kurgulayacağız. Yapıyı basitten başlayıp geliştireceğiz; sonunda elinizde tek tuşla yeni VPS açan, güvenlik ayarlarını yapan, Nginx veya Apache kuran, uygulamanızı deploy etmeye hazır hale getiren bir iskelet olacak.
Genel Mimarinin Resmi: Terraform Nerede, Ansible Nerede?
Önce rolleri netleştirelim. Terraform ve Ansible aynı problemi çözmez, birbirini tamamlar:
- Terraform: Altyapıyı kurar. Yani DCHost üzerinde VPS oluşturur, gerekirse ek disk, ağ, IP, DNS kaydı gibi nesneleri oluşturup yönetir.
- Ansible: Kurulan VPS’in içini hazırlar. Paketleri kurar, ayar dosyalarını yerleştirir, servisleri başlatır, güvenlik sertleştirmesini yapar.
Bu ikili sayesinde üç katmanınız olur:
- Katman 1 – Altyapı: VPS, ağ, IP, DNS (Terraform)
- Katman 2 – İşletim sistemi ve temel servisler: SSH, firewall, log, izleme (Ansible rolleri)
- Katman 3 – Uygulama: PHP/Node.js/Java, veritabanı, cache, kodun deploy’u (Yine Ansible rolleri + CI/CD)
Terraform tarafındaki akışın daha derinine girmek isterseniz, blogda yer alan Terraform ile VPS ve DNS otomasyonu yazısında DNS ve çok bölgeli yapılarla birleştirilmiş daha gelişmiş bir senaryoyu da inceleyebilirsiniz.
Terraform ile VPS Altyapısını Kodlamak
Temel Kavramlar: Provider, Resource, State
Terraform’un üç temel kavramını netleştirelim:
- Provider: Terraform’un konuştuğu API katmanını temsil eder. Örneğin bu yazıda örneklerde dchost adında hayali bir provider ismi kullanacağız.
- Resource: Oluşturmak istediğiniz nesneler: vps, disk, network, dns_record gibi.
- State: Terraform’un “şu an ne var” bilgisini tuttuğu durum dosyası. Bu sayede sadece farkları uygular.
Basit bir dizin yapısıyla başlayalım:
infra/
main.tf
variables.tf
outputs.tf
terraform.tfvars
Örnek Terraform Yapılandırması
Aşağıdaki örnek, DCHost üzerinde tek bir VPS oluşturmak için basitleştirilmiş bir Terraform konfigurasyonudur. Provider isimleri örnektir; siz kendi ortamınıza göre uyarlamalısınız.
# main.tf
terraform {
required_version = ">= 1.5.0"
}
provider "dchost" {
api_token = var.dchost_api_token
}
resource "dchost_vps" "app" {
name = var.instance_name
region = var.region
plan = var.plan # Örn: "nvme-2c-4g"
image = var.image # Örn: "ubuntu-22.04"
ssh_keys = [
var.ssh_public_key
]
}
output "app_ip" {
value = dchost_vps.app.ip_address
}
Değişkenleri variables.tf içinde tanımlayalım:
# variables.tf
variable "dchost_api_token" {
type = string
sensitive = true
}
variable "instance_name" {
type = string
default = "demo-app-01"
}
variable "region" {
type = string
default = "eu-tr"
}
variable "plan" {
type = string
default = "nvme-2c-4g"
}
variable "image" {
type = string
default = "ubuntu-22.04"
}
variable "ssh_public_key" {
type = string
}
Son olarak da terraform.tfvars ile değerleri doldurun:
# terraform.tfvars
instance_name = "demo-app-01"
region = "eu-tr"
plan = "nvme-2c-4g"
image = "ubuntu-22.04"
ssh_public_key = "ssh-ed25519 AAAA... senin_anahtarın"
dchost_api_token = "xxxxxxxxxxxxxxx"
Artık aşağıdaki komutlar ile VPS’inizi koddan oluşturabilirsiniz:
cd infra
terraform init
terraform plan
terraform apply
Burada kritik nokta: Bu dosyaları Git deposunda tutarak, hangi değişiklikle hangi sunucunun nasıl evrildiğini tarihsel olarak takip edebilirsiniz. Yani “geçen ay bu sunucunun RAM’ini yükseltmiştik, Terraform’da hangi commit’ti” sorusunun cevabı hep kayıtlıdır.
cloud-init ile İlk Nefes: Ansible’a Hazırlık
Terraform yalnızca VPS’i oluşturmakla kalmayabilir; cloud-init user data ile VPS ilk açılırken temel ayarların yapılmasını da tetikleyebilir. Örneğin bir kullanıcı oluşturmak, SSH anahtarı koymak, Ansible için Python kurmak gibi.
Bu mimariyi daha derinlemesine anlatan cloud-init ve Ansible ile tekrar üretilebilir VPS kurulumu yazısına mutlaka göz atmanızı öneririm; burada ise daha çok Terraform + Ansible entegrasyonuna odaklanacağız.
Ansible ile VPS Konfigürasyonunu Kodlamak
Envanter, Playbook ve Roller
Ansible tarafında temel yapı taşlarımız:
- Inventory: Hangi sunucular var, IP adresleri, gruplar, değişkenler.
- Playbook: Hangi gruplara hangi rollerin uygulanacağını söyleyen orkestrasyon dosyası.
- Role: Belirli bir işi üstlenen, yeniden kullanılabilir görev paketleri (örneğin nginx, php, security_hardening rolü).
Örnek dizin yapısı kuralım:
config/
inventory/
hosts.ini
playbooks/
site.yml
roles/
common/
tasks/main.yml
nginx/
tasks/main.yml
Basit Bir Inventory Örneği
Başlangıçta Terraform çıktısını kullanmadan, IP’yi elle yazdığımız basit bir inventory ile başlayalım:
# config/inventory/hosts.ini
[app]
app-01 ansible_host=1.2.3.4 ansible_user=ubuntu
Ardından basit bir playbook:
# config/playbooks/site.yml
---
- hosts: app
become: true
roles:
- role: common
- role: nginx
common rolü temel işletim sistemi güncellemeleri, ssh ayarları, zaman dilimi, log ayarları gibi işleri üstlenebilir.
# config/roles/common/tasks/main.yml
---
- name: Paket listelerini güncelle
apt:
update_cache: yes
cache_valid_time: 3600
- name: Gerekli temel paketleri kur
apt:
name:
- htop
- curl
- git
state: present
- name: Zaman dilimini ayarla
timezone:
name: "Europe/Istanbul"
Basit bir Nginx kurulumu da şöyle olabilir:
# config/roles/nginx/tasks/main.yml
---
- name: Nginx'i kur
apt:
name: nginx
state: present
- name: Varsayılan siteyi kapat
file:
path: /etc/nginx/sites-enabled/default
state: absent
- name: Uygulama site konfigürasyonunu yerleştir
template:
src: app.conf.j2
dest: /etc/nginx/sites-available/app.conf
- name: Siteyi etkinleştir
file:
src: /etc/nginx/sites-available/app.conf
dest: /etc/nginx/sites-enabled/app.conf
state: link
- name: Nginx'i yeniden başlat
service:
name: nginx
state: restarted
enabled: yes
Bu iskelet ile ansible-playbook komutunu çalıştırdığınızda, VPS’iniz tekrarlanabilir bir şekilde aynı hale gelecektir:
cd config
ansible-playbook -i inventory/hosts.ini playbooks/site.yml
Güvenlik Sertleştirmesini Role Haline Getirmek
Güvenlik ayarlarını da Ansible rolü olarak tanımladığınızda, yeni açılan her VPS’in otomatik olarak sertleştirilmesini sağlayabilirsiniz. Örneğin:
- root ile SSH girişini kapatma
- parola ile giriş yerine yalnızca anahtar ile oturum açma
- ufw veya nftables ile temel firewall kuralları
- fail2ban ile brute-force saldırılarına karşı koruma
Bu konuları derinlemesine ele aldığımız VPS güvenlik sertleştirme kontrol listesi ve SSH güvenliğini sağlamlaştırma yazılarını, Ansible rolünüzü tasarlarken referans rehber gibi kullanabilirsiniz.
Terraform Çıktısını Ansible Envanterine Bağlamak
Şimdi asıl sihirli kısma gelelim: Terraform’un oluşturduğu VPS’lerin IP adreslerini otomatik olarak Ansible envanterine aktararak tek komutla hem altyapıyı kurmak hem de konfigürasyonu uygulamak.
Terraform Output ile Dinamik Envanter Üretmek
Önce Terraform çıktımızı biraz zenginleştirelim:
# outputs.tf
output "app_ip" {
value = dchost_vps.app.ip_address
description = "Uygulama sunucusunun IP adresi"
}
output "ansible_inventory" {
value = <<EOT
[app]
app-01 ansible_host=${dchost_vps.app.ip_address} ansible_user=ubuntu
EOT
}
Şimdi küçük bir script ile Terraform çıktısını Ansible inventory dosyasına yazdıralım. Örneğin scripts/generate_inventory.sh:
#!/usr/bin/env bash
set -euo pipefail
cd "$(dirname "$0")/.." # proje köküne geç
cd infra
terraform output -raw ansible_inventory > ../config/inventory/hosts.ini
Artık akışımız şöyle olabilir:
terraform applyile VPS’i oluştur.generate_inventory.shile IP’leri Ansible envanterine yaz.ansible-playbookile VPS’i yapılandır.
Bunların hepsini tek komuta indirmek için bir Makefile da kullanabilirsiniz.
Makefile ile Tek Komutluk Akış
# Makefile
.PHONY: all infra config destroy
all: infra config
infra:
cd infra && terraform init && terraform apply -auto-approve
./scripts/generate_inventory.sh
config:
cd config && ansible-playbook -i inventory/hosts.ini playbooks/site.yml
destroy:
cd infra && terraform destroy -auto-approve
Artık yalnızca şu komutu verdiğinizde:
make all
Adım adım şu işlemler gerçekleşir:
- DCHost üzerinde Terraform ile yeni VPS oluşturulur.
- Oluşan IP adresi otomatik olarak Ansible envanterine yazılır.
- Ansible playbook’ları ile sunucu güncellenir, güvenliği sertleştirilir, Nginx ve diğer servisler kurulur.
Bir felaket senaryosunda aynı komutla sıfırdan yeni bir VPS’i ayağa kaldırıp, aynı konfigürasyona saniyeler-birkaç dakika içinde ulaşabilirsiniz. Bu konuyu daha geniş ölçekteki felaket kurtarma planları ile birleştirmek isterseniz, felaket kurtarma planı nasıl yazılır yazımız size iyi bir çerçeve sunar.
Güvenlik, Secrets ve Erişim Yönetimi
API Anahtarları ve SSH Anahtarlarını Nasıl Saklamalı?
Terraform ve Ansible ile otomasyon kurarken en kritik konulardan biri, gizli anahtarların (secrets) yönetimidir. Hata yapmaya çok açık alanlar:
- Terraform veya Ansible dosyalarında API token’larını düz metin olarak bırakmak
- SSH özel anahtarlarını Git deposuna yanlışlıkla commit etmek
- Üretim ortamı şifrelerini staging ortamıyla karıştırmak
En azından şu temel önlemleri almanızı öneririz:
- Git deposunda .gitignore ile özel anahtar dosyalarını hariç tutun.
- Terraform tarafında
sensitive = truedeğişkenler kullanın veterraform.tfvarsdosyasını özel olarak saklayın. - Ansible için ansible-vault veya harici bir secrets yöneticisi (örneğin sops + age) kullanın.
Gizli bilgilerin yönetimini derinlemesine ele aldığımız VPS’te secrets yönetimi rehberi, Terraform/Ansible akışınızı güvenli hale getirirken size somut örnekler sağlayacaktır.
SSH Erişimini Standartlaştırmak
Elle sunucu kurduğunuzda, herkes kendi zevkine göre SSH ayarı yapar. Terraform + Ansible akışında bunu da kodlaştırmak büyük konfor sağlar:
- Yalnızca belirli kullanıcıların public key’leri Ansible ile dağıtılır.
/etc/ssh/sshd_configşablon haline getirilir; root login kapatılır, parola ile giriş engellenir.- Her yeni VPS aynı SSH güvenlik seviyesinde başlar.
Bunu bir ssh_hardening rolüne koyup tüm playbook’lara eklediğinizde, “şu sunucuda neden hala parola girişi açık” sürprizleri ortadan kalkar. DCHost olarak kendi altyapımızda da en çok değer verdiğimiz şeylerden biri, tutarlı güvenlik seviyesidir.
Gerçekçi Senaryolar: DCHost Üzerinde Terraform + Ansible Kullanım Örnekleri
1. Staging ve Üretim Ortamlarını Aynı Hale Getirmek
En sık gördüğümüz problemlerden biri, staging ortamında çalışan bir özelliğin üretimde farklı davranması. Sebep çoğu zaman yazılım değil, altyapı farkları oluyor: farklı PHP sürümü, farklı Nginx ayarı, farklı kernel parametresi…
Terraform ve Ansible ile şu modeli kurabilirsiniz:
- Aynı Terraform modülü ile iki farklı workspace:
stagingveprod - Aynı Ansible rol ve playbook’ları, yalnızca birkaç değişken farkıyla iki ortama da uygulanır.
- Örneğin staging’de daha küçük plan, prod’da daha büyük plan kullanırsınız; diğer her şey aynıdır.
Böylece staging’de yaptığınız her test, üretim ortamındaki davranışa çok daha yakın olur. Özellikle yüksek trafikli WordPress ve Laravel projelerinde, geliştirme–staging–canlı yolculuğu yazısında anlattığımız dağıtım akışları ile birleştiğinde, hem kod hem altyapı tarafında uçtan uca tekrar üretilebilir bir sistem elde edersiniz.
2. Aynı Uygulamayı Farklı Bölgelerde Çoğaltmak
Kurumsal bir müşteriniz için uygulamayı hem Türkiye’deki kullanıcılar hem de Avrupa’daki kullanıcılar için düşük gecikmeli sunmak istiyorsunuz diyelim. Terraform ile iki farklı bölgede benzer VPS kümeleri oluşturup, Ansible ile hepsini aynı şekilde yapılandırabilirsiniz.
İleride DNS veya Anycast tabanlı bir çok bölgeli mimariye geçmek isterseniz, blogda detaylandırdığımız çok bölgeli mimariler rehberi ile Terraform/Ansible altyapınızı birleştirmeniz oldukça doğal bir adım olur.
3. Sıfırdan Kaldırmak Gerekebilen Riskli Denemeler
Bazen yeni bir veritabanı sürümü, yeni bir PHP versiyonu veya yeni bir cache mimarisi denemek istersiniz. Üretim sunucusu üzerinde doğrudan deneme yapmak yerine, Terraform + Ansible ile çöpe atılabilir test ortamları oluşturmak çok daha güvenlidir.
make allile test ortamını kurarsınız.- Load test, sorgu optimizasyonu veya konfigürasyon denemelerinizi yaparsınız.
- İşiniz bitince
make destroyile her şeyi temizlersiniz.
Böylece hem test maliyetini düşürür, hem de üretim ortamını gereksiz risklerden korursunuz.
Sık Yapılan Hatalar ve İyileştirme İpuçları
Hata 1: Her Şeyi Tek Dev VPS Üzerine Yığmak
Terraform ile otomasyon kurduğunuzda, çoğu zaman “madem kolay kuruyoruz, bütün işleri tek büyük VPS’e koyalım” düşüncesi devreye giriyor. Özellikle veritabanı, uygulama ve cache katmanını tek makinada toplamak bazen kaçınılmaz olabilir ama otomasyonunuz hazırken erken ayrıştırma yapmak uzun vadede işinizi çok kolaylaştırır.
Veritabanını ayrı bir VPS’e taşımanın ne zaman mantıklı olduğu sorusunu, blogdaki veritabanı sunucusunu uygulamadan ayırmak rehberinde detaylıca tartıştık. Terraform/Ansible iskeletiniz varken bu ayrımı yapmak çok daha az zahmetli olacaktır.
Hata 2: State Dosyasını Ciddiye Almamak
Terraform’un state dosyası, tüm altyapınızın tek doğruluk kaynağıdır. Lokal bir terraform.tfstate dosyasını rastgele makinelerde tutmak, ekip büyüdüğünde ciddi problemlere yol açar.
Önerimiz:
- State’i uzak bir backend’de (S3 uyumlu nesne depolama, Terraform Cloud vb.) tutun.
- State kilitlemeyi (locking) aktif hale getirin, aynı anda birden fazla kişinin
applyçalıştırmasını engelleyin. - State dosyasını da düzenli olarak yedekleyin; sonuçta bu da kritik bir veridir.
Hata 3: Ansible Rollerini Spagetti Hale Getirmek
Zamanla Ansible rolleri büyüyüp iç içe geçtiğinde, “bu sunucuya ne kuruldu” sorusunun cevabı zorlaşmaya başlar. Bunu engellemek için:
- Her rolün net bir sorumluluğu olsun:
nginx,php_fpm,mysql,security_hardeninggibi. - Rolleri yalnızca ihtiyaç duyan sunucu gruplarına atayın; her rolü her yere yüklemeye çalışmayın.
- Değişkenleri rollere özel
defaultsklasöründe tutun; environment farklarını group_vars ile yönetin.
Hata 4: İzleme ve Loglamayı Unutmak
Otomasyonla VPS kurduk, uygulamayı deploy ettik, her şey çalışıyor… Peki CPU tavan yaptığında, disk dolduğunda veya 5xx hataları fırladığında ne olacak? Terraform ve Ansible akışınıza izleme ve loglama ajanlarını eklemediyseniz, sorunları hala elle teşhis etmek zorunda kalırsınız.
Bu aşamada, blogda detaylandırdığımız VPS izleme ve alarm kurulumu rehberindeki ajanları ve dashboard kurulumlarını Ansible rolleri haline getirip, her yeni VPS’inize otomatik olarak ekleyebilirsiniz.
DCHost ile Terraform ve Ansible Otomasyonunu Hayata Geçirmek
Buraya kadar anlattığımız yapı, ilk bakışta kapsamlı görünebilir; ancak küçük adımlarla gittiğinizde her adımın somut bir getirisi oluyor. Özetle:
- Terraform ile VPS, disk, ağ ve temel kaynakları kod olarak tanımlıyorsunuz.
- Ansible ile işletim sistemi, güvenlik ayarları, web sunucusu ve uygulama katmanını tekrar üretilebilir hale getiriyorsunuz.
- Terraform çıktısını Ansible envanterine bağlayarak tek komutla baştan sona çalışan bir akış kuruyorsunuz.
DCHost tarafında sunduğumuz VPS, dedicated ve colocation altyapıları, bu tarz otomasyon senaryolarını rahatça taşıyabileceğiniz şekilde tasarlanıyor. Özellikle tekrar tekrar kurmanız gereken staging, test ve kısa ömürlü ortamlarınız varsa, otomasyonlu bir yapı kurduğunuzda hem operasyon yükünüz hem de insan hatası kaynaklı riskler ciddi oranda azalır.
Bir sonraki adım olarak şunları yapmanızı öneririm:
- Küçük bir proje seçin ve Terraform ile yalnızca tek bir VPS tanımı yapın.
- Ansible ile sadece temel güvenlik ve Nginx kurulumunu role çevirin.
- Bunları bir
Makefileveya basit bir script ile uçtan uca bağlayın.
Bu ilk iskeleti oturttuktan sonra, veritabanı, cache, izleme, loglama, yedekleme gibi bileşenleri tek tek bu yapıya ekleyerek büyütebilirsiniz. DCHost olarak bu yolculukta, ister altyapı seçimi ister Terraform/Ansible mimarisi olsun, ekibinizle birlikte aynı dili konuşan bir partner olmaktan memnuniyet duyarız.
