Wayland Altında GPG Commit İmzalama Çilesi ve Rofi Entegrasyonu
Güvenli ve doğrulanabilir bir yazılım geliştirme iş akışı için Git commit’lerini GPG (GNU Privacy Guard) ile imzalamak günümüzde standart bir pratik haline geldi. Ancak bu güvenli limana ulaşmaya çalışırken, kullandığınız pencere yöneticisi ve terminal arayüzleri bazen süreci tamamen kilitleyebilir.
NixOS ve Hyprland (Wayland) tabanlı minimalist masaüstü ortamımda, terminal üzerinden git commit atmaya çalıştığımda veya bir dosyayı GPG ile imzalamak istediğimde sık sık şu hata ile karşılaşıyordum:
error: gpg failed to sign the data
fatal: failed to write commit object
Bazen de süreç hiçbir çıktı vermeden terminali tamamen kilitliyor, arka planda bir zaman aşımı (Timeout) veya “İşlem iptal edildi” (Operation cancelled) hatasıyla sonlanıyordu. En sık karşılaşılan hata çıktısı ise şu şekildedir:
gpg: signing failed: Inappropriate ioctl for device
Bu yazıda, bu kilitlenmenin teknik nedenini, geleneksel çevre değişkeni çözümlerinin neden yetersiz kaldığını ve arayüz seviyesinde nasıl kalıcı bir çözüm ürettiğimizi inceleyeceğiz.
Teşhis: TTY, GPG_TTY ve pinentry-curses Çıkmazı
GPG ile bir veriyi imzalamak istediğinizde, özel anahtarınızın (private key) şifresini çözmek için sistem sizden parola ister. Bu parolayı güvenli bir şekilde almak için gnupg-agent, pinentry adı verilen küçük arayüz araçlarını tetikler.
Benim önceki konfigürasyonumda pinentry paketi olarak terminal tabanlı olan pinentry-curses seçiliydi:
# Eski ve sorunlu yapılandırma
programs.gnupg.agent = {
enable = true;
pinentryPackage = pkgs.pinentry-curses;
};
Klasik Geçici Çözüm: GPG_TTY
Normal şartlarda, terminal tabanlı şifre sorucuların çalışabilmesi için işletim sisteminin GPG’ye hangi terminal cihazını (TTY) kullanacağını söylemesi gerekir. Bunun için kabuk (shell) profiline şu satır eklenir:
export GPG_TTY=$(tty)
Bu çevre değişkeni, basit terminal oturumlarında sorunu çözer. Ancak aşağıdaki senaryolarda GPG_TTY tamamen etkisiz kalır:
- Girdi Çakışması (stdin/pipe): GPG imzalama işlemi bir borulama (pipe) veya Git gibi bir ara katman tarafından tetiklendiğinde, standart girdi (
stdin) zaten başka bir süreç tarafından meşgul ediliyor olabilir.pinentry-cursesbu durumda klavye girdisini yakalayamaz. - Git Kancaları (Hooks) ve Arka Plan Süreçleri: Bir commit sırasında çalışan asenkron git kancaları (örneğin pre-commit linter’ları) veya IDE entegrasyonları çalıştığında, süreç aktif bir TTY olmadan (non-interactive) tetiklenir.
GPG_TTYtanımlı olsa bile ortada etkileşime geçilebilecek fiziksel bir TTY olmadığı içinInappropriate ioctl for devicehatası kaçınılmaz olur. - Wayland Odaklanma Sorunu: Hyprland gibi döşemeli (tiling) pencere yöneticilerinde, parola istemcisi görünmez bir TTY tünelinde asılı kalır. Kullanıcıya şifre sorulamaz ve ajan zaman aşımına uğrar.
Çözüm: Arayüzü Grafik Katmanına Taşımak (pinentry-rofi)
Bu TTY kilitlenmesini aşmanın en kararlı yolu, parola giriş ekranını terminalin içinden kurtarıp masaüstünün genel grafik katmanına taşımaktır. Hyprland/Wayland ortamında ana uygulama başlatıcı olarak Wofi tercih etsem de, parola sorma arayüzü olarak hafif ve bağımsız bir grafiksel pop-up sunan pinentry-rofi aracını entegre ettim.
NixOS’un modüler yapısı sayesinde, GPG ajanın şifre istemcisini doğrudan bu grafiksel popup penceresine yönlendirmek son derece basittir.
modules/core/gpg.nix dosyamı şu şekilde güncelledim:
{ config, pkgs, ... }:
{
# GPG (GNU Privacy Guard) Yapılandırması
programs.gnupg.agent = {
enable = true;
enableSSHSupport = true;
# Çözüm: GUI tabanlı ve Hyprland uyumlu pinentry-rofi geçişi
pinentryPackage = pkgs.pinentry-rofi;
settings = {
default-cache-ttl = 28800; # Parolayı 8 saat boyunca hafızada tut
max-cache-ttl = 28800;
};
};
# GPG paketini sistem geneline ekle
environment.systemPackages = [ pkgs.gnupg ];
}
Bu değişiklik uygulandığında (nixos-rebuild switch), imzalama işlemi tetiklendiği an ekranın ortasında temiz, odaklanma sorunu yaşamayan ve klavye girdisini doğrudan yakalayan bir grafiksel şifre kutusu açılmaya başladı. Terminalin stdin durumu ne olursa olsun, parola grafik katmanında girildiği için kilitlenmeler tamamen ortadan kalktı.
Ekstra Kazanımlar ve Mimari İnce Ayarlar
Bu geçişi yaparken sistem mimarisinde doğruladığım ve optimize ettiğim birkaç kritik nokta daha oldu:
1. SOPS-Nix ve GPG İzolasyonu
Sistem genelindeki gizli sırları (API anahtarları, şifreler vb.) Git üzerinde şifreli tutmak için kullandığım sops-nix modülünün bu değişiklikten etkilenip etkilenmeyeceğini kontrol ettim. sops-nix arka planda GPG yerine modern age şifreleme altyapısını ve kimlik doğrulaması için doğrudan ~/.ssh/id_ed25519 SSH anahtarını kullanıyor. Dolayısıyla GPG ajanındaki bu pinentry değişimi, sistemin sops-nix sır yönetimini tamamen izole tutarak hiçbir yan etki yaratmadı.
2. Çoklu Anahtar Öncelik Çıkmazı
Cüzdanınızda birden fazla GPG anahtarı olduğunda (örneğin Git commit imzalamak için eski bir RSA anahtarı ve genel şifrelemeler için yeni bir ED25519 anahtarı):
- Git,
.gitconfigdosyasındakiuser.signingkeydeğerine bakarak doğrudan belirtilen spesifik anahtarı (RSA) imzalamaya zorlar. - Ancak terminalden manuel bir dosya şifreleme veya imzalama komutu verdiğinizde, GPG varsayılan olarak cüzdandaki en üstte duran ilk anahtarı (ED25519) seçmeye çalışır.
Eğer manuel işlemlerde spesifik anahtarınızı zorlamak istiyorsanız, komutlarınıza --local-user parametresini eklemeyi unutmayın:
gpg --local-user YOUR_SPECIFIC_KEY_ID --sign document.txt
Sonuç
Masaüstü ortamınızı Wayland ve tiling window manager (Hyprland, Sway vb.) üzerine kuruyorsanız, terminal tabanlı araçların (curses varyantları) TTY odağı ve borulama süreçlerinde yaratabileceği kilitlenmeleri hesaba katmalısınız. GPG şifre sorma adımını pinentry-rofi gibi grafiksel bir arayüze taşımak, deklaratif sistem bütünlüğünü bozmadan iş akışınızı kesintisiz hale getirmenin en temiz yoludur.
Kaynaklar
- NixOS Search — gnupg.agent.pinentryPackage
- Arch Wiki — GnuPG (Pinentry Settings)
- GnuPG Official Documentation — Agent Options
İlgili:
- sops-nix: NixOS’ta Şifreli Secret Yönetimi
- NixOS’ta Şifreli Swap Çilesi: 90 Saniyelik Boot Gecikmesi ve Zram Çözümü