Sistem yöneticileri için Claude kullanımı ve ipuçları
Claude ile log analizi, systemd birimi oluşturma ve Nginx yapılandırma incelemesi gibi altı kritik sunucu görevini nasıl hızlandıracağınızı ve güvenlik risklerini öğrenin.
Sistem yöneticileri için Claude: önce tavsiye, sonra uygulama
Sistem yöneticileri için Claude, en iyi bir inceleme aracı olarak çalışır. Bir günlük kaydı kesiti, yapılandırma dosyası, tanımadığınız bir komut veya bir hata dizisi yapıştırdığınızda, sunucunuzda herhangi bir değişiklik yapmadan önce doğrulayabileceğiniz bir açıklama alırsınız. Yanlış bir cevap, siz onu çalıştırana kadar size bir maliyet çıkarmaz; bu nedenle modeli bu çizginin tavsiye tarafında tutmak, tüm güvenlik modelini oluşturur.
Kiralanan bir Linux VPS (sanal özel sunucu) üzerinde her hafta altı görev ortaya çıkar. Aşağıdakilerin her biri, çalışan bir istem kalıbına, cevabı kanıtlayan komuta ve beklemeniz gereken hata moduna sahiptir. Bunların hiçbiri, modelin sunucunuza erişmesini gerektirmez. Bir tarayıcı sekmesinden veya kendi masaüstünüzdeki bir pencereden yapıştırma yapabilirsiniz, çünkü Claude, Linux üzerinde hem masaüstü uygulaması hem de CLI olarak yerel biçimde çalışır.
Üretim ortamındaki bir sunucuda sıra önemlidir: açıklamayı okuyun, kontrolü kendiniz yapın ve ardından karar verin. Deneme amaçlı bir VM üzerinde özerklik sorun yaratmaz. Müşterilerinize hizmet veren sunucuda ise inceleme kazanır, çünkü model tahmin yürüttüğü durumu göremez.
Asla yapıştırmamanız gerekenler
İstem içerisine yazdığınız her şey sunucunuzdan dışarı çıkar. Aşağıdaki dört kategorideki veriler sunucuda kalmalıdır:
- Özel anahtarlar:
~/.ssh/id_ed25519,/etc/ssh/ssh_host_*_keyve/etc/letsencrypt/live/altındaki tüm TLS (transport layer security) anahtarları. - Kimlik bilgisi dosyaları:
.env,~/.aws/credentials,/root/.docker/config.jsonve herhangi bir dosya veya günlük satırındaki veritabanı parolaları. - Hesap verileri:
/etc/shadowve/etc/gshadow. Hiçbir sistem yöneticisi sorusu, yanıtlanmak için parola özeti (hash) gerektirmez. - Kullanıcılarınıza ait her türlü veri: e-posta adresleri, sipariş satırları, oturum çerezleri veya PII (kişisel olarak tanımlanabilir bilgiler) içeren istek günlükleri.
Açık anahtarların yapıştırılmasında sakınca yoktur. Özel anahtarlar ise paylaşılmamalıdır. İki dosya türü ilk bakışta birbirine benzer, bu yüzden kopyalamadan önce ilk satırı okuyun: ilk satırında BEGIN OPENSSH PRIVATE KEY ifadesi bulunan bir dosya asla isteme eklenmemelidir. SSH anahtar materyallerinizi düzenli tutmak üzerine on dakika ayırmaya değer.
200 satırlık bir metin içinde tek bir belirteci fark etmeye çalışmak yerine, yapıştırmadan önce sansürleme yapın:
sudo journalctl -u myapp -n 200 --no-pager | sed -E 's/(token|secret|password|api[_-]?key)[=:][^[:space:]]+/\1=REDACTED/gI'Docker ile ilgili özel bir tuzak mevcuttur. docker compose config, .env değerlerinizi yazdırdığı çıktıya dahil eder; bu nedenle diskteki dosya gizli olmasa bile çıktı gizli hale gelir. Doğrulama yapan ancak hiçbir şey yazdırmayan docker compose config -q komutunu kullanın. Bir yapay zeka aracının neleri görmesine izin verileceğine dair genel politika için gizli bilgileri yapay zeka araçlarından uzak tutmak bölümüne göz atabilirsiniz.
İş 1: Bu servis neden başarısız oldu?
Cevabı barındıran iki komutla başlayın:
systemctl status myapp.service --no-pager
sudo journalctl -u myapp.service -b -n 100 --no-pager -o short-isoHer ikisini de, modelin tahmin edemeyeceği bağlamla birlikte yapıştırın: dağıtım ve sürüm, en son neyi değiştirdiğiniz, daha önce çalışıp çalışmadığı ve ne kadar süre önce bozulduğu. İlk olarak mekanizmayı sorun.
Ubuntu 24.04.myapp.servicebir saat önce unit dosyasını düzenleyene kadar sorunsuz çalışıyordu. İştesystemctl statusve son 100 günlük kaydı satırı. İlk gerçek hata satırı hangisi ve ne anlama geliyor? Henüz bir düzeltme yapmadım.
"Henüz bir düzeltme yapmadım" ifadesi, bu komut isteminde kritik bir rol oynar. Günlük kayıtları, ilk hatayı kendi neden olduğu yeniden denemelerin altına gömer; bu yüzden bir düzeltme istenen model, gördüğü son satırı açıklamaya odaklanır. Önemli olan satır, genellikle gürültünün yirmi satır yukarısındadır.
Sonuç, Main PID: 1841 (code=exited, status=203/EXEC) gibi bir satır olacaktır. 203/EXEC çıkış durumu, çekirdeğin ExecStart içinde belirtilen dosyayı çalıştıramadığı anlamına gelir: ya yol mevcut değildir ya da dosya mevcuttur ancak çalıştırılabilir değildir. Yüklü olmayan bir yorumlayıcıyı işaret eden bir #! satırı da aynı durumu üretir. Bunların tamamı ls -l ve head -1 ile test edilebilir.
Hata modu: uydurma bir neden. Çok az bilgi yapıştırırsanız model boşluğu "port zaten kullanımda" gibi genel bir ifadeyle doldurur. Bunun çözümü, bir soru geri gitmektir: "Verdiğim metnin hangi satırı bunu destekliyor?" Metin içinde kimsenin işaret edemediği bir neden, sadece bir tahmindir.
Görev 2: Bir systemd birimi veya cron girdisi tasarlayın
Bir birim dosyasının ihtiyaç duyduğu gerçekleri belirtin: tam komut, çalıştırılacağı kullanıcı, çalışma dizini, ağın beklenip beklenmeyeceği ve sıfır olmayan bir çıkış durumunda ne yapılması gerektiği. Ardından, herhangi bir şeyi etkinleştirmeden önce dönen sonucu doğrulayın.
sudo systemd-analyze verify /etc/systemd/system/myapp.service
sudo systemctl daemon-reload
sudo systemctl start myapp.service
systemctl status myapp.service --no-pagersystemd-analyze verify, dosyayı systemd'nin yaptığı şekilde ayrıştırır; bu sayede insan gözünün kaçırdığı hataları yakalar. Yanlış yazılmış bir direktif /etc/systemd/system/myapp.service:7: Unknown key name 'Enviroment' in section 'Service', ignoring. çıktısı verir. Eksik bir ikili dosya Command /usr/local/bin/myapp is not executable: No such file or directory çıktısı verir. Her ikisi de daemon-reload sırasında sessiz kalır; bu nedenle bir birim sorunsuz yüklenebilir ancak çalıştığı anda başarısız olabilir.
İki taslak hatası sürekli olarak tekrarlanır. Birincisi, yalnızca ağ yığınının yapılandırıldığı, ancak henüz bir adresin mevcut olmadığı anlamına gelen After=network.target kullanımıdır. Belirli bir IP adresine bağlanan bir servis, önyükleme sırasında bind: Cannot assign requested address hatasıyla başarısız olur; çözüm ise Wants=network-online.target ile birlikte After=network-online.target kullanmaktır. İkincisi, daemon haline gelen bir program için Type=simple kullanımıdır: systemd ilk süreci servis olarak kabul eder, ana süreç hemen çıkar ve gerçek süreç yönetilmeksizin çalışmaya devam ederken birim ölü olarak işaretlenir. Bir modelin size sunması en muhtemel hata budur, çünkü komutunuzdan ikili dosyanın çatallanıp çatallanmadığını anlayamaz. Bu nedenle, taslağı kabul etmeden önce her Type= değerinin systemd'ye ne vaat ettiğini bilmek faydalıdır.
Zamanlanmış bir görev için, okumak yerine kontrol edin:
systemd-analyze calendar 'Mon *-*-* 04:00:00'Bu komut, normalleştirilmiş biçimi ve ifadenin bir sonraki çalışma zamanını yazdırır; bu da ifadenin ne anlama geldiği konusundaki tüm tartışmaları sonlandırır. Bir timer ile crontab arasında seçim yapıyorsanız, bir VPS üzerinde systemd servisleri ve timer'lar bu ikisi arasındaki farkları açıklar.
Cron, siz sormadığınız sürece hiçbir modelin sizi uyarmayacağı bir tuzağa sahiptir. Cron, işleri minimal bir ortamla çalıştırır; bu nedenle PATH kabaca /usr/bin:/bin değerine eşittir ve kabuk profiliniz asla okunmaz. Terminalinize yapıştırdığınızda çalışan bir iş, cron altında /bin/sh: 1: docker: not found hatasıyla başarısız olur, çünkü o ikili dosya /usr/local/bin dizininde bulunur. Crontab dosyalarında mutlak yollar kullanın. Bir birim dosyasının kullanıcıyı, ortamı ve bağımlılıkları açıkça belirtme zorunluluğu, tek satırlık bir crontab girdisinin yanında zahmetli görünüyorsa, systemd'nin çözmek için tasarlandığı sorunlar bu ayrıntılı yapının nedenini açıklar.
İş 3: Canlıya almadan önce bir Nginx veya Compose dosyasını inceleyin
Bu iş en yüksek verimi sağlar. Dosyayı yapıştırın, ne yapması gerektiğini belirtin ve gerçekte ne yaptığına dair satır satır bir açıklama isteyin.
Bu vhost,example.comüzerinden HTTPS sunmalı ve/apitrafiğini 8080 numaralı porttaki yerel bir servise proxy etmelidir. Bunu bana geri okuyun ve bu tanıma uymayan her şeyi belirtin.
Ardından dil bilgisini bilen aracı çalıştırın:
sudo nginx -t
docker compose config -qnginx -t, nginx: configuration file /etc/nginx/nginx.conf test is successful çıktısını verir veya nginx: [emerg] unknown directive "proxy_pas" in /etc/nginx/conf.d/app.conf:12 örneğinde olduğu gibi dosya adını ve satır numarasını belirtir. docker compose config -q, dosya ayrıştırıldığında hiçbir şey yazdırmaz; girintileme hatası gibi durumlarda ise yaml: line 7: did not find expected key gibi kısa bir hata mesajı verir.
Hiçbir araç niyetinizi kontrol etmez. nginx -t testinden geçen bir yapılandırma, yanlış porta proxy yapabilir veya 127.0.0.1 hedeflemeniz gerekirken 0.0.0.0 üzerinde dinleme yapabilir. Modelin değerini kanıtladığı yer bu boşluktur; ancak başarısız olduğu yer de burasıdır: Tek bir direktifi düzeltmesi istendiğinde, genellikle tüm dosyayı yeniden yazar ve direktiflerinizden ikisini sessizce eksik bırakır. Değiştirilen satırları ve her birinin nedenini isteyin, ardından düzenlemeyi manuel olarak yapın.
Gerçekte neyi dış dünyaya açtığınızı doğrulayın:
sudo ss -tulpnsudo olmadan dinleme yapan soketleri görürsünüz ancak bunlara sahip olan süreçleri göremezsiniz. Eğer bu çıktı sizi şaşırtırsa, portların ne olduğu ve Linux'un bunları nasıl bağladığı konusu daha kısa bir okumadır.
İş 4: çalıştırmadan önce alışılmadık bir komutu açıklayın
Komutu yapıştırın ve hakkında dört soru sorun: her bir bayrak (flag) ne işe yarar, ne yazar, neyi siler ve iki kez çalıştırırsam ne olur? Son soru, diğerlerinden daha fazla hasarı önler.
find /var/log -name '*.gz' -mtime +7 -delete komutunu ele alalım. İyi bir yanıt, -mtime +7 ifadesinin tam 24 saatlik periyotları saydığını ve kesirli kısımları attığını, bu nedenle yedi gün yerine en az sekiz günlük dosyalarla eşleştiğini belirtir. Ayrıca find ifadesinin kendi ifadesini soldan sağa değerlendirdiğini, bu yüzden -delete ifadesini -name önüne almanın başlangıç yolunun altındaki her şeyi sileceğini söyler. Bu ikinci nokta, find kılavuz sayfasında bir uyarı olarak yer alır ve insanlara /var/log verilerine mal olmuştur.
Veya rsync -a --delete /srv/app/ /backup/app/ komutunu ele alalım. Kaynak yolun sonundaki eğik çizgi, "bu dizinin içeriği" anlamına gelir. Çizgiyi kaldırırsanız /backup/app/app/ sonucunu alırsınız. --delete eklerseniz, hedef dizinde olup kaynakta olmayan her şey silinir; bu bir yansıtma (mirror) işlemi için doğrudur ancak kaynak yol yanlışsa bir felakettir.
Model ile değil, araç ile doğrulayın:
rsync -a --delete --dry-run /srv/app/ /backup/app/ | head -20
find /var/log -name '*.gz' -mtime +7find komutunu -delete olmadan çalıştırırsanız, veri kaybı yerine bir liste elde edersiniz.
Hata modu: bayrak halüsinasyonu. Model, otuz yıllık dokümantasyona sahip araçlarda güvenilirdir; ancak satıcı CLI (komut satırı arayüzleri) ve yeni alt komutlarda çok daha zayıftır; burada kulağa mükemmel gelen ancak mevcut olmayan bir bayrak üretebilir. --help bunu bir saniyede netleştirir. Tırnak işaretleri diğer zayıf noktadır, bu nedenle bir komut bir $(...) ifadesini sarmaladığında, açıklamaya güvenmek yerine komut çalışmadan önce komut ikamesinin nasıl genişlediğini okuyun.
İş 5: Shell geçmişinizi bir operasyonel el kitabına (runbook) dönüştürün
Bir şeyi çalışır hale getirmek için iki saatinizi harcadınız. Bu bilgi terminal geçmişinizde (scrollback) duruyor ve gelecek ay silinmiş olacak.
history 200 > /tmp/session.txtBu dosyayı okuyun ve herhangi bir yere taşımadan önce parola, token veya müşteri tanımlayıcı içeren her satırı silin. Shell geçmişi, bir Linux sisteminde gizli verileri bulmak için en güvenilir yerlerden biridir; çünkü herkes en az bir kez satır içinde bir parola yazar. ~/.bashrc dosyanızda HISTCONTROL=ignorespace ayarını yaparsanız, başına boşluk eklenerek yazılan bir komut geçmişe asla kaydedilmez.
Kullanılabilir bir runbook üreten istem, yalnızca adımları değil, aynı zamanda kontrolleri de talep etmelidir:
Bu, temiz bir Debian 13 sunucusunu çalışan bir Postgres kurulumuna getiren bir shell oturumudur. Bunu numaralandırılmış bir runbook olarak yaz. Her adımda bir komut olsun. Her adımdan sonra, çalıştığını kanıtlayan komutu ver ve sağlıklı çıktının nasıl göründüğünü tarif et. Benim özel sunucuma bağımlı olan adımları işaretle.
Hata modu: düzenli bir hikaye anlatımı. Oturumunuzda, düzeltmeden önce iki kez yanlış yaptığınız bir adım olabilir; modeller, transkript daha temiz göründüğü için bu adımı genellikle yok sayar. Runbook'u geçmişinizle karşılaştırın ve düzeltmeyi geri ekleyin. Ayrıca model makul doğrulama komutları da uydurabilir, bu yüzden dosyayı kaydetmeden önce yazdığı her kontrolü çalıştırın. Eğer runbook ilk kurulumu kapsıyorsa, yeni bir VPS üzerindeki ilk on dakika ile karşılaştırarak okuyun; böylece çözülmüş bir problemin daha kötü bir versiyonunu yazmamış olursunuz.
Görev 6: bir hata mesajını çözüme dönüştürme
Tam hata dizisini, hatayı üreten komutu ve bu hata ortaya çıkmadan önce değiştirdiğiniz tek bir şeyi yapıştırın. Olası nedenleri sıralamalarını isteyin ve her biri için test edilebilir bir doğrulama komutu talep edin.
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use). Olası nedenleri sıralayın ve her neden için durumu doğrulayan veya eleyen bir komut verin.
Bu hata için mekanizma belirsiz değildir: başka bir süreç halihazırda 80 numaralı portu kullanıyordur ve sudo ss -tulpn | grep ':80 ' bu süreci tanımlar. Genellikle bu durum, başarısız bir yeniden yükleme sonrası geride kalan ikinci bir Nginx ana süreci veya bağımlılık olarak yüklenip kendi kendine başlayan Apache servisidir.
Hata modu: nedeni gizleyerek çalışan bir çözüm. chmod 777, --privileged, SELinux'u devre dışı bırakmak ve servisi root yetkileriyle çalıştırmak hatayı ortadan kaldırır. Dar kapsamlı izinlerin neden başarısız olduğu açıklanmadan, izinleri genişleten hiçbir çözümü kabul etmeyin. Asıl cevap bu açıklamadır. Geçici bir çözüm (workaround) hatayı yalnızca sessizleştirir.
Güvenilir biçimde hatalı olduğu durumlar
- Sunucunuzu göremez. Her yanıt, yapıştırdığınız içeriğin bir fonksiyonudur; alıntının çok kısa olduğu konusunda sizi uyarmaz.
- Sürümler konusunda sapmalar yaşar. Paket isimleri ve varsayılan flag değerleri dağıtımlar ve sürümler arasında değişir; model ise bunların ortalamasını alır.
- Hatalı olduğunda bile akıcıdır. Uydurma bir mekanizma, doğru bir mekanizma ile aynı tonda okunur; yukarıdaki her nedenin bir doğrulama komutuyla birlikte verilmesinin sebebi budur.
- Uzun oturumlarda konuyu kaybeder. İki saatlik bir konuşmanın başındaki bilgiler, konuşmanın sonundaki yanıtları şekillendirmeyi bırakır.
Son madde bir model sorunundan ziyade bir çalışma yöntemidir ve uzun bir Claude Code oturumunda bağlam yönetimi bunun pratik çözümüdür: daha kısa oturumlar ve her oturumda tek bir görev.
Ajanı doğrudan sunucuya yerleştirme
Yukarıdaki her şey kopyala-yapıştır yöntemine dayalıdır, bu nedenle model makinenize doğrudan erişmez. Ajan sunucu üzerinde çalışmaya başladığında, dosyaları okuyup komutları yürüttüğünde riskin boyutu değişir: hatalı bir komut artık bir servisin durmasına neden olabilir. Ajanı root yerine yetkisiz bir kullanıcı ile çalıştırın, davranışlarını öğrenene kadar üretim sunucunuzdan uzak tutun ve öncesinde bir snapshot alın. Claude Code'u bir VPS üzerinde güvenli bir şekilde çalıştırma rehberi, sandbox oluşturma ve izin modelini ele alır. Claude Code'u tmux içinde çalıştırma, SSH (secure shell) oturumunun kopması durumunda ön planda çalışan ajanın işinin yarım kalması sorununu çözdüğü için denklemin diğer yarısını tamamlar. Hesap kurulumunu, VPS üzerinde en düşük yetkili kullanıcılar rehberinde belirtildiği gibi, herhangi bir servis hesabı oluşturur gibi gerçekleştirin.
FAQ
Claude sunucu günlüklerimi doğrudan okuyabilir mi?
Tek başına hayır. Sohbet arayüzü yalnızca içine yapıştırdığınız metni görür. Sunucuda bir komut satırı aracı olarak çalıştırılan Claude Code, dosyaları okuyabilir ve başlatıldığı kullanıcının izinleriyle komut çalıştırabilir; bu daha büyük bir güven kararı gerektirir. Sıradan bir destek sorusu için, 100 satırlık sansürlenmiş bir alıntıyı yapıştırmak, bir araca kabuk erişimi vermekten daha hızlı ve güvenlidir.
Bir sunucudan asla neyi yapıştırmamalıyım?
Özel anahtarlar, .env dosyaları ve diğer kimlik bilgisi depoları, /etc/shadow ve kullanıcılarınıza ait tüm veriler. Günlük alıntılarındaki belirteçleri (token) isteme ulaşmadan önce sansürleyin. Belirgin olmayan bir durum: docker compose config çıktısı, .env değerlerinizin içine işlenmiş halini içerir; bu yüzden dosyayı doğrulayan ve hiçbir şey yazdırmayan docker compose config -q komutunu kullanın.
Claude'un bir üretim VPS'sinde komut çalıştırmasına izin vermek güvenli mi?
Bunu bağlamı olmayan yeni bir yönetici gibi değerlendirin: okuma için uygundur, yazma için inceleme gerekir. Üretim ortamında, açıklamayı isteyin ve komutu kendiniz çalıştırın. Eğer bir aracın yürütmesini istiyorsanız, ona sudo yetkisi olmayan özel bir hesap verin ve hatanın kesinti yerine yeniden kurulum maliyeti getireceği bir test (staging) ortamında başlatın.
Claude neden var olmayan bir bayrak (flag) öneriyor?
Çünkü makul görünen metinleri tahmin eder ve makul bir bayrak, gerçek bir bayrakla aynı görünür. Bu durum en çok, modelin arkasındaki dokümantasyonun zayıf olduğu veya sonradan değiştiği satıcı CLI'larında ve yeni alt komutlarda yaşanır. --help ve man nihai karar vericidir; silme veya üzerine yazma yapan her komut önce bir deneme çalıştırmasını (dry run) hak eder.
Bir systemd birimini etkinleştirmeden önce nasıl kontrol ederim?
sudo systemd-analyze verify /etc/systemd/system/myapp.service komutunu çalıştırın. Dosyayı systemd'nin kendi ayrıştırıcısı ile ayrıştırır, bilinmeyen yönergeleri satır numaralarıyla bildirir ve eksik veya çalıştırılabilir olmayan bir ExecStart ikili dosyasını işaretler. Ardından daemon-reload ve start komutlarını çalıştırın ve enable yapmadan önce systemctl status dosyasını okuyun; çünkü sorunsuz yüklenen bir birim ilk çalıştırılmasında yine de başarısız olabilir.