Ansible ile Ubuntu 18.04 Üzerine LEMP Kurulumu ve Yapılandırması
Ansible, modern BT altyapılarında otomasyonun temel taşlarından biridir. Sunucu yapılandırması, uygulama dağıtımı ve orkestrasyon gibi karmaşık görevleri basitleştirerek, sistem yöneticilerinin ve DevOps mühendislerinin iş yükünü önemli ölçüde azaltır. Bu teknik makalede, Ansible kullanarak Ubuntu 18.04 işletim sistemi üzerinde popüler bir web sunucu yığını olan LEMP’yi (Linux, Nginx, MySQL/MariaDB, PHP-FPM) nasıl kurup yapılandıracağımızı adım adım inceleyeceğiz.
LEMP yığını, yüksek performanslı web uygulamaları ve dinamik web siteleri için tercih edilen güçlü bir kombinasyondur. Nginx, düşük kaynak tüketimiyle yüksek eşzamanlı bağlantıları işleyebilirken, PHP-FPM dinamik içerik işleme yeteneği sunar. MariaDB ise güvenilir ve hızlı bir veritabanı çözümüdür. Bu bileşenlerin manuel olarak kurulması ve yapılandırılması zaman alıcı ve hataya açık bir süreç olabilir. Ansible sayesinde, bu süreci tamamen otomatikleştirerek tekrarlanabilir, tutarlı ve ölçeklenebilir bir çözüm elde edeceğiz.
1. Giriş ve Ön Koşullar
Bu rehber, bir Ansible kontrol sunucunuzun (genellikle yerel makineniz veya ayrı bir sunucu) olduğunu ve hedef Ubuntu 18.04 sunucusuna SSH erişiminizin olduğunu varsaymaktadır. Ansible, Python tabanlı olduğu için kontrol sunucunuzda Python 3 ve pip’in kurulu olması gerekmektedir.
1.1. Ansible Kontrol Sunucusu Hazırlığı
1. Python ve pip Kurulumu (Gerekliyse):
sudo apt update
sudo apt install python3 python3-pip -y
2. Ansible Kurulumu:
pip3 install ansible
3. SSH Anahtar Çifti Oluşturma:
Hedef sunuculara parola girmeden bağlanabilmek için SSH anahtar çifti oluşturmak en iyi uygulamadır.
ssh-keygen -t rsa -b 4096
Tüm soruları varsayılan olarak kabul edebilirsiniz.
4. SSH Anahtarını Hedef Sunucuya Kopyalama:
your_user kısmını hedef sunucudaki kullanıcı adınızla, your_server_ip kısmını ise hedef sunucunun IP adresiyle değiştirin.
ssh-copy-id your_user@your_server_ip
Bu komut, anahtarınızı hedef sunucudaki kullanıcının ~/.ssh/authorized_keys dosyasına ekleyecektir.
1.2. Hedef Ubuntu 18.04 Sunucusu Hazırlığı
Hedef sunucuda temel bir Ubuntu 18.04 kurulumu yeterlidir. Ansible’ın sorunsuz çalışabilmesi için hedef sunucuda python3 ve sudo yetkisine sahip bir kullanıcıya ihtiyacımız var. Ansible, varsayılan olarak root kullanıcısı yerine sudo yetkili bir kullanıcı ile bağlanmayı tercih eder.
* Sistemi güncelleyin: sudo apt update && sudo apt upgrade -y
* python3 kurulu olduğundan emin olun. Ubuntu 18.04’te varsayılan olarak gelir.
* Ansible’ın apt modülünü kullanabilmesi için python3-apt paketinin kurulu olması önemlidir. Genellikle Ansible bunu otomatik kurar, ancak manuel olarak da kontrol edilebilir: sudo apt install python3-apt -y
2. Ansible Proje Yapısı Oluşturma
Ansible ile çalışırken, düzenli bir proje yapısı oluşturmak iyi bir uygulamadır. Bu, playbook’larınızın, envanterinizin ve rollerinizin daha yönetilebilir olmasını sağlar.
lemp_ansible/
├── ansible.cfg
├── inventory.ini
├── playbooks/
│ └── main.yml
└── roles/
├── common/
│ ├── tasks/
│ │ └── main.yml
│ └── handlers/
│ └── main.yml
├── mariadb/
│ ├── tasks/
│ │ └── main.yml
│ ├── handlers/
│ │ └── main.yml
│ └── defaults/
│ └── main.yml
├── nginx/
│ ├── tasks/
│ │ └── main.yml
│ ├── handlers/
│ │ └── main.yml
│ └── templates/
│ ├── default.conf.j2
│ └── nginx.conf.j2
└── php/
├── tasks/
│ └── main.yml
└── handlers/
└── main.yml
Bu yapı, her bir LEMP bileşeni için ayrı bir rol tanımlamamızı sağlar. common rolü, tüm sunucularda yapılması gereken genel sistem güncellemeleri ve temel paket kurulumları gibi görevleri içerir.
3. Temel Ansible Yapılandırması
Proje dizininin kökünde (lemp_ansible/) aşağıdaki dosyaları oluşturalım:
3.1. inventory.ini
Bu dosya, Ansible’ın yöneteği hedef sunucuları tanımlar.
[lemp_servers]
your_server_ip_or_hostname ansible_user=your_ssh_user ansible_python_interpreter=/usr/bin/python3
* [lemp_servers]: Hedef sunucularımızı gruplandıran bir grup adı.
* your_server_ip_or_hostname: Hedef sunucunuzun IP adresi veya ana bilgisayar adı.
* ansible_user: Hedef sunucuya bağlanmak için kullanılacak SSH kullanıcı adı (SSH anahtarını kopyaladığınız kullanıcı).
* ansible_python_interpreter: Ansible’ın hedef sunucuda kullanacağı Python yorumlayıcısının yolu. Ubuntu 18.04 için /usr/bin/python3 olmalıdır.
3.2. ansible.cfg
Bu dosya, Ansible’ın varsayılan davranışlarını yapılandırmak için kullanılır.
[defaults]
inventory = inventory.ini
remote_user = your_ssh_user
ask_pass = False
host_key_checking = False
roles_path = roles
* inventory: Envanter dosyamızın yolu.
* remote_user: Eğer inventory.ini içinde belirtilmezse, varsayılan olarak kullanılacak uzak kullanıcı.
* ask_pass: SSH parolası sormayı devre dışı bırakır (SSH anahtarları kullandığımız için).
* host_key_checking: Yeni sunuculara bağlanırken SSH anahtar kontrolünü devre dışı bırakır (test ortamları için kullanışlıdır, üretimde dikkatli olunmalıdır).
* roles_path: Rollerin bulunduğu dizinin yolu.
4. Ansible Rollerini Oluşturma ve Yapılandırma
Şimdi sıra, LEMP yığınının her bir bileşeni için rolleri tanımlamaya geldi.
4.1. common Rolü
Bu rol, hedef sunucudaki işletim sistemini güncelleyecek ve temel paketleri kuracaktır.
* roles/common/tasks/main.yml:
---
- name: Update apt cache
apt:
update_cache: yes
cache_valid_time: 3600 # Cache'i 1 saat geçerli tut
- name: Upgrade all installed packages
apt:
upgrade: dist
autoremove: yes
- name: Install common packages
apt:
name:
- curl
- git
- unzip
- htop
- net-tools
- python3-apt # apt modülünün düzgün çalışması için
- aptitude # apt modülünün bazı bağımlılıkları için
state: present
- name: Install UFW (Uncomplicated Firewall)
apt:
name: ufw
state: present
- name: Allow SSH traffic
ufw:
rule: allow
name: OpenSSH
- name: Allow HTTP traffic
ufw:
rule: allow
port: '80'
proto: tcp
- name: Allow HTTPS traffic
ufw:
rule: allow
port: '443'
proto: tcp
- name: Enable UFW
ufw:
state: enabled
policy: deny # Varsayılan olarak tüm gelen bağlantıları reddet
* roles/common/handlers/main.yml: (Bu rol için özel bir handler’a gerek yok, ancak standart olarak oluşturulabilir.)
---
# Bu rol için özel bir handler'a gerek yok.
4.2. nginx Rolü
Bu rol, Nginx web sunucusunu kuracak, yapılandıracak ve başlatacaktır.
* roles/nginx/tasks/main.yml:
---
- name: Install Nginx
apt:
name: nginx
state: present
- name: Copy Nginx main configuration file
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: Restart Nginx
- name: Remove default Nginx site configuration
file:
path: /etc/nginx/sites-enabled/default
state: absent
notify: Restart Nginx
- name: Copy Nginx default site configuration
template:
src: default.conf.j2
dest: /etc/nginx/sites-available/default
notify: Restart Nginx
- name: Enable Nginx default site
file:
src: /etc/nginx/sites-available/default
dest: /etc/nginx/sites-enabled/default
state: link
notify: Restart Nginx
- name: Ensure Nginx service is running and enabled
systemd:
name: nginx
state: started
enabled: yes
* roles/nginx/handlers/main.yml:
---
- name: Restart Nginx
systemd:
name: nginx
state: restarted
* roles/nginx/templates/nginx.conf.j2: (Basit bir örnek, daha fazla optimizasyon yapılabilir.)
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
# multi_accept on;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
gzip on;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
* roles/nginx/templates/default.conf.j2: (PHP-FPM ile entegrasyonu gösteren örnek.)
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.php index.html index.htm index.nginx-debian.html;
server_name _;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php{{ php_version }}-fpm.sock; # php_version değişkeni kullanılacak
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
location ~ /\.ht {
deny all;
}
}
Burada php_version diye bir değişken kullandık. Bu değişkeni group_vars/lemp_servers.yml veya playbooks/main.yml içinde tanımlayacağız. Ubuntu 18.04 için varsayılan PHP sürümü 7.2’dir.
4.3. mariadb Rolü
Bu rol, MariaDB veritabanı sunucusunu kuracak, güvenliğini sağlayacak ve bir veritabanı ile kullanıcı oluşturacaktır.
* roles/mariadb/tasks/main.yml:
---
- name: Install MariaDB server and client
apt:
name:
- mariadb-server
- mariadb-client
state: present
- name: Ensure MariaDB service is running and enabled
systemd:
name: mariadb
state: started
enabled: yes
- name: Set MariaDB root password
community.mysql.mysql_user:
name: root
password: "{{ mariadb_root_password }}"
host: localhost
login_unix_socket: /var/run/mysqld/mysqld.sock
check_password_exists: no # İlk kurulumda şifre olmadığı için kontrol etme
no_log: true # Şifreyi loglara yazdırmamak için
- name: Remove anonymous users
community.mysql.mysql_user:
name: ''
host: "{{ item }}"
state: absent
login_user: root
login_password: "{{ mariadb_root_password }}"
with_items:
- localhost
- "{{ ansible_hostname }}"
no_log: true
- name: Remove test database
community.mysql.mysql_db:
name: test
state: absent
login_user: root
login_password: "{{ mariadb_root_password }}"
no_log: true
- name: Create database
community.mysql.mysql_db:
name: "{{ mariadb_database }}"
state: present
login_user: root
login_password: "{{ mariadb_root_password }}"
no_log: true
- name: Create database user
community.mysql.mysql_user:
name: "{{ mariadb_user }}"
password: "{{ mariadb_password }}"
host: localhost
priv: "{{ mariadb_database }}.*:ALL"
state: present
login_user: root
login_password: "{{ mariadb_root_password }}"
no_log: true
- name: Flush privileges
community.mysql.mysql_query:
query: FLUSH PRIVILEGES;
login_user: root
login_password: "{{ mariadb_root_password }}"
no_log: true
MariaDB görevleri için community.mysql koleksiyonuna ihtiyacımız var. Bunu Ansible kontrol sunucusunda kurmalıyız: ansible-galaxy collection install community.mysql.
* roles/mariadb/handlers/main.yml:
---
- name: Restart MariaDB
systemd:
name: mariadb
state: restarted
* roles/mariadb/defaults/main.yml: (Varsayılan değerler, group_vars veya vault ile üzerine yazılabilir.)
---
mariadb_root_password: "your_strong_root_password"
mariadb_database: "your_database_name"
mariadb_user: "your_database_user"
mariadb_password: "your_strong_database_password"
ÖNEMLİ: Şifreler gibi hassas verileri doğrudan bu dosyada bırakmak yerine Ansible Vault kullanmalıyız. Bunu bir sonraki bölümde ele alacağız.
4.4. php Rolü
Bu rol, PHP-FPM’i ve gerekli PHP modüllerini kuracak, yapılandıracak ve başlatacaktır.
* roles/php/tasks/main.yml:
---
- name: Install PHP-FPM and common PHP modules for Ubuntu 18.04 (PHP 7.2)
apt:
name:
- php{{ php_version }}-fpm
- php{{ php_version }}-mysql
- php{{ php_version }}-cli
- php{{ php_version }}-gd
- php{{ php_version }}-curl
- php{{ php_version }}-mbstring
- php{{ php_version }}-xml
- php{{ php_version }}-zip
- php{{ php_version }}-intl
state: present
- name: Ensure PHP-FPM service is running and enabled
systemd:
name: php{{ php_version }}-fpm
state: started
enabled: yes
notify: Restart PHP-FPM
* roles/php/handlers/main.yml:
---
- name: Restart PHP-FPM
systemd:
name: php{{ php_version }}-fpm
state: restarted
Burada da php_version değişkenini kullanıyoruz.
5. Ana Playbook (main.yml)
Şimdi tüm bu rolleri bir araya getiren ana playbook’u oluşturalım.
* playbooks/main.yml:
---
- name: Setup LEMP stack on Ubuntu 18.04
hosts: lemp_servers
become: yes # Tüm görevleri sudo ile çalıştır
vars:
php_version: "7.2" # Ubuntu 18.04 için varsayılan PHP sürümü
pre_tasks:
- name: Ensure python3-apt is installed on target hosts
raw: test -e /usr/bin/python3 || (apt update && apt install -y python3 python3-apt)
changed_when: false # Bu komutun idempotent olmaması durumunda bile "changed" olarak işaretlenmesini engeller
roles:
- common
- nginx
- mariadb
- php
pre_tasks bölümü, Ansible’ın ilk bağlantısında python3-apt paketinin kurulu olduğundan emin olmak için eklenmiştir. Bu, özellikle minimal sunucu kurulumlarında Ansible’ın apt modülünü kullanmadan önce gerekli Python modülünü yüklemesine olanak tanır.
6. Hassas Verilerin Yönetimi (Ansible Vault Kullanımı)
Veritabanı şifreleri gibi hassas bilgileri doğrudan playbook veya rol dosyalarında saklamak güvenlik açısından risklidir. Ansible Vault, bu tür verileri şifrelemek ve güvenli bir şekilde yönetmek için kullanılır.
1. Vault Dosyası Oluşturma:
ansible-vault create group_vars/lemp_servers.yml
Bu komut sizden bir parola isteyecektir. Bu parolayı unutmayın! Dosya bir metin düzenleyicide açılacak ve buraya hassas değişkenleri ekleyebilirsiniz:
mariadb_root_password: "your_super_strong_root_password"
mariadb_database: "my_webapp_db"
mariadb_user: "webapp_user"
mariadb_password: "your_super_strong_db_password"
Kaydedip kapatın. Artık bu dosya şifrelenmiş durumdadır.
2. Vault Dosyasını Düzenleme:
Daha sonra düzenlemek isterseniz:
ansible-vault edit group_vars/lemp_servers.yml
3. Vault Parolasını Kullanarak Playbook’u Çalıştırma:
Playbook’u çalıştırırken Ansible’a vault parolasını sağlamanız gerekecektir.
ansible-playbook -i inventory.ini playbooks/main.yml --ask-vault-pass
Veya bir dosya içinde saklanan parolayı kullanabilirsiniz (daha güvenli):
ansible-playbook -i inventory.ini playbooks/main.yml --vault-password-file ~/.ansible/vault_pass.txt
~/.ansible/vault_pass.txt dosyasının içeriği sadece vault parolası olmalıdır ve izinleri 600 olarak ayarlanmalıdır (chmod 600 ~/.ansible/vault_pass.txt).
7. Playbook’u Çalıştırma ve Doğrulama
Tüm dosyaları oluşturduktan ve Ansible Vault’u yapılandırdıktan sonra, playbook’u çalıştırmaya hazırız.
1. Ansible Koleksiyonlarını Kurma:
MariaDB rolünde community.mysql koleksiyonunu kullandığımız için, kontrol sunucusunda bunu kurmalıyız:
ansible-galaxy collection install community.mysql
2. Playbook’u Çalıştırma:
Proje kök dizininde (lemp_ansible/) aşağıdaki komutu çalıştırın:
ansible-playbook -i inventory.ini playbooks/main.yml --ask-vault-pass
Ansible, hedef sunucuya bağlanacak ve tanımladığımız tüm görevleri sırasıyla yürütecektir. Çıktıda her bir görevin durumu (changed, ok, skipped vb.) gösterilecektir.
3. Kurulumun Doğrulanması:
Playbook başarıyla tamamlandıktan sonra, LEMP yığınının doğru şekilde kurulup kurulmadığını doğrulamamız gerekir.
* Nginx Kontrolü:
Web tarayıcınızı açın ve hedef sunucunuzun IP adresine gidin. Nginx’in varsayılan “Welcome to Nginx!” sayfasını veya bizim default.conf.j2 dosyamızdaki /var/www/html dizininde bir index.html dosyası oluşturduysanız o içeriği görmelisiniz.
* PHP-FPM Kontrolü:
PHP’nin Nginx ile doğru bir şekilde entegre olup olmadığını test etmek için, /var/www/html dizininde bir info.php dosyası oluşturalım:
# Hedef sunucuya SSH ile bağlanın
sudo nano /var/www/html/info.php
Dosyanın içine aşağıdaki kodu yapıştırın:
Kaydedip çıkın. Ardından tarayıcınızda http://your_server_ip/info.php adresine gidin. PHP bilgi sayfasını görmelisiniz. İşiniz bittiğinde güvenlik nedeniyle bu dosyayı silmeyi unutmayın: sudo rm /var/www/html/info.php.
* MariaDB Kontrolü:
Hedef sunucuya SSH ile bağlanın ve MariaDB’ye bağlanmayı deneyin:
mysql -u webapp_user -p
webapp_user yerine group_vars/lemp_servers.yml dosyasında tanımladığınız kullanıcı adını ve parolayı girin. Başarılı bir şekilde bağlanabiliyorsanız ve SHOW DATABASES; komutu ile oluşturduğunuz veritabanını görüyorsanız, MariaDB de doğru şekilde çalışıyor demektir.
* Firewall Kontrolü:
Hedef sunucuda UFW durumunu kontrol edin:
sudo ufw status
SSH (22), HTTP (80) ve HTTPS (443) portlarının izinli olduğunu görmelisiniz.
8. Sonuç ve İleri Adımlar
Bu makalede, Ansible kullanarak Ubuntu 18.04 sunucusu üzerine LEMP yığınını (Nginx, MariaDB, PHP-FPM) nasıl otomatik olarak kurup yapılandıracağımızı detaylı bir şekilde öğrendik. Ansible’ın rol tabanlı yapısı, görev otomasyonu, idempotence (tekrarlı çalıştırmalarda tutarlılık) ve hassas veri yönetimi (Ansible Vault) gibi özellikleri sayesinde, karmaşık sunucu kurulumlarını basitleştirebilir, hataları azaltabilir ve dağıtım süreçlerinizi hızlandırabilirsiniz.
Bu kurulum, LEMP yığınının temelini oluşturur. İleri düzeyde, bu yapılandırmayı daha da geliştirebilirsiniz:
* SSL/TLS Kurulumu: Let’s Encrypt ile otomatik SSL sertifikaları kurmak için Nginx rolünü genişletmek.
* Birden Fazla Site Yönetimi: Nginx rolüne birden fazla sanal ana bilgisayar (virtual host) yapılandırması eklemek.
* Gelişmiş PHP Yapılandırması: php.ini veya PHP-FPM havuz ayarlarını özelleştirmek.
* Veritabanı Yedekleme: MariaDB için otomatik yedekleme görevleri eklemek.
* Monitoring ve Loglama: Prometheus, Grafana veya ELK Stack gibi araçlarla entegrasyon.
* CI/CD Entegrasyonu: Bu Ansible playbook’unu Jenkins, GitLab CI/CD veya GitHub Actions gibi sürekli entegrasyon/sürekli dağıtım (CI/CD) boru hatlarına dahil etmek.
Ansible, altyapı yönetimini bir sanat haline getiren güçlü bir araçtır. Bu rehber, otomasyon yolculuğunuzda sağlam bir başlangıç noktası sağlamalıdır.