Sunucu Config'leri Neden Kafanda Değil, Git'te Olmalı!
Devraldığım hemen her sunucuda aynı sessiz problem var: config'ler çalışıyor, ama kimse neden böyle göründüklerini söyleyemiyor. Bir Nginx vhost'unda proxy_read_timeout 300 saniyeye çıkarılmış. Bir fail2ban jail'inde whitelist'e alınmış bir IP aralığı var. Bir sysctl ayarı bir connection limit'ini ikiye katlıyor. Her değişiklik o anda muhtemelen doğru karardı, canlıda yapıldı, biraz baskı altında, ve sonra dosyanın kendisi dışında hiçbir yere yazılmadı. Altı ay sonra, hangi değişikliklerin kritik olduğunu hangilerinin kalıntı deney olduğunu kimse hatırlamıyor, ve kimse yanlış satırı silen kişi olmak istemiyor.
En hafif çözüm: etckeeper
Tek bir sunucu için en küçük faydalı adım etckeeper, /etc'i git altına alıyor ve paket yöneticisi bir config dosyasına her dokunduğunda otomatik commit ediyor:
apt install etckeeper
cd /etc
git log --oneline -10
Bu noktadan sonra, yaptığınız her manuel edit, etckeeper'ın bir sonraki commit'inde yakalanıyor (ya da edit'ten hemen sonra kendiniz git add -A && git commit çalıştırabilirsiniz). Bunun karşılığı, bir config değişikliğinden sonra bir şey bozulduğunda şunu çalıştırabilmeniz:
git log -p -- nginx/sites-enabled/example.com
ve tam olarak neyin değiştiğini, ne zaman, ve bir commit mesajı yazdıysanız neden değiştiğini görebilmeniz. Asıl fark da burada: git commit -m "yavaş rapor export endpoint'i için proxy_read_timeout artırıldı", gelecekteki sizin config'i anlaması ile gelecekteki sizin ona dokunmaktan çekinmesi arasındaki fark.
Birden fazla sunucu için: müşteri başına bir configs repo'su
etckeeper tek bir makineye özel, bu tek bir VPS için sorun değil ama bir müşterinin ilişkili config'lere sahip üç dört sunucusu olduğunda işe yaramıyor. Bunlar için, host'a göre yapılandırılmış ayrı bir repo tutuyorum:
client-configs/
├── web-01/
│ ├── nginx/sites-available/example.com
│ └── fail2ban/jail.local
├── db-01/
│ ├── postgresql/postgresql.conf
│ └── pgbackrest/pgbackrest.conf
└── deploy.sh
Değişiklikler lokalde yapılıyor, herhangi bir yere gitmeden önce bir diff'te review ediliyor, ve küçük bir deploy.sh, ilgili dosyaları doğru host'a push ediyor:
#!/bin/bash
HOST=$1
rsync -av "$HOST/" "deploy@$HOST.internal:/" --dry-run
# remove --dry-run once the diff looks right
--dry-run varsayılanı bilinçli bir seçim. Config deploy'ları, rsync'te yanlış yere konmuş bir trailing slash'ın istenenden fazlasını ezebileceği tam da o türden işler, bu yüzden varsayılan davranış, gerçekten olmadan önce neyin değişeceğini gösteriyor.
Bunun dokümantasyonun sağlamadığı kazancı
Genel alternatif, "önemli config değişikliklerini" anlatan bir wiki sayfası ya da README. Bunlar neredeyse anında bayatlıyor, çünkü wiki'yi güncellemek değişikliği yapmaktan ayrı bir adım, ve ayrı adımlar zaman baskısı altında atlanıyor. Git history'de bu problem yok: kayıt, üstüne eklenen ekstra bir görev değil, işin yapılmasının bir yan ürünü.
Bu aynı zamanda değişikliklerin nasıl yapıldığını da değiştiriyor. Bir config git'te yaşadığında, doğal hareket, SSH ile girip canlı dosyayı direkt edit etmek yerine onu lokalde edit etmek, gerekçeyi açıklayan bir mesajla commit etmek, ve sonra deploy etmek oluyor. Workflow'daki bu küçük kayma, değerin asıl geldiği yer: backup değil, ne'den bir an önce neden'i yazma alışkanlığı. Üç ay sonra, biri (genelde ben) bir config'in önünde durup belirli bir satırın güvenle silinip silinemeyeceğini merak ettiğinde, commit mesajındaki o tek cümle bir saatlik dikkatli arkeolojiyi kurtarıyor.