Impermanence: NixOS'ta Her Boot'ta Sıfırlanan Bir Root

NixOS’un en özgün özelliklerinden biri, çoğu kullanıcının ilk duyduğunda “neden isteyeyim ki?” dediği bir şey: impermanence — kalıcısızlık.

Fikir basit: root dosya sistemi her boot’ta sıfırlanır. Sistem bir önceki oturumdan hiçbir iz taşımaz. Ne apt install kalıntıları, ne elle düzenlenmiş /etc/hosts, ne “şu an hatırlamıyorum ama çalışıyor” konfigürasyonları. Her boot, deklaratif konfigürasyonun tam yansıması.

Bu yazı teorik bir anlatı değil. Kendi kurulumumdaki gerçek disk yapısını, hangi verilerin kalıcı hangilerinin geçici olduğunu ve neden bu yapıyı tercih ettiğimi anlatıyor.

Disk Yapısı

Tek bir NVMe disk, etiket tabanlı bölümler:

MountTürBtrfs subvolAçıklama
/tmpfsEphemeral root — RAM’de, boot’ta sıfırlanır
/bootFAT32EFI bölümü
/nixBtrfs@nixNix store — kalıcı
/homeBtrfs@homeKullanıcı dizini — kalıcı
/persistBtrfs@persistSistem state — kalıcı

hardware.nix dosyasındaki gerçek tanım:

fileSystems."/" = {
  device = "none";
  fsType = "tmpfs";
  options = [ "defaults" "size=8G" "mode=755" ];
};

fileSystems."/nix"] = {
  device = "/dev/disk/by-label/NIXOS";
  fsType = "btrfs";
  options = [ "subvol=@nix" "compress=zstd" "noatime" ];
  neededForBoot = true;
};

fileSystems."/persist" = {
  device = "/dev/disk/by-label/NIXOS";
  fsType = "btrfs";
  options = [ "subvol=@persist" "compress=zstd" "noatime" ];
  neededForBoot = true;
};

Root için device = "none" ve fsType = "tmpfs" — disk değil, RAM. Her boot’ta boş başlar.

Ne Ephemeral, Ne Değil?

Bu kurulumda tam “everything ephemeral” yaklaşımı yok. Hibrit bir model:

Ephemeral (tmpfs, boot’ta sıfırlanır):

Kalıcı:

/home’un kalıcı olması bazı impermanence kurulumlarından farklı. Tam impermanence’ta home da tmpfs olur ve her dosya home.persistence ile açıkça tanımlanır. Bu daha radikal bir yaklaşım; şu an benim için gereğinden fazla.

Hangi Sistem Verileri Persist Ediliyor?

Root tmpfs olunca bir sorun çıkıyor: bazı servisler çalışma süresinde /var/lib ve /etc altına veri yazıyor — NetworkManager bağlantı profilleri, Docker volume’ları, makine ID’si gibi. Bunlar tmpfs’te kalırsa her boot’ta sıfırlanır.

nix-community/impermanence modülü bu sorunu çözüyor: belirtilen dizin ve dosyaları /persist altından bind-mount ederek kalıcı hale getiriyor.

Benim modules/core/impermanence.nix:

environment.persistence."/persist" = {
  hideMounts = true;

  directories = [
    "/etc/NetworkManager/system-connections"
    "/var/log"
    "/var/lib/nixos"
    "/var/lib/docker"
    "/var/lib/libvirt"
    "/var/lib/postgresql"
    "/var/lib/private/open-webui"
    "/var/lib/sddm"
    "/var/cache/nix"
  ];

  files = [
    "/etc/machine-id"
  ];
};

hideMounts = true ile bu bind-mount’lar df -h çıktısında gizlenir — listeyi karmaşıklaştırmaz.

/etc/machine-id özellikle kritik: bu ID değişirse systemd journal’ı bozulur, bazı lisans mekanizmaları sıfırlanır, Tailscale yeniden auth ister. Bir kez üretilip /persist’te saklanıyor.

sops-nix: Neden SSH Key /persist’te?

sops-nix, NixOS secrets yönetimi için age şifrelemesi kullanıyor. Şifre çözme anahtarı SSH private key’i.

Şifre çözme boot sürecinde gerçekleşiyor — NixOS servisleri başlamadan önce. Ama bu noktada /home henüz mount edilmemiş. @home subvolume’u boot’un ilerleyen aşamalarında mount ediliyor.

Bu yüzden SSH anahtarı /home/xmrah/.ssh/ değil, /persist/xmrah/.ssh/ altında duruyor:

# modules/core/sops.nix
age.sshKeyPaths = [ "/persist/xmrah/.ssh/id_ed25519" ];

/persist ise neededForBoot = true ile işaretli — boot sürecinin erken aşamalarında mount ediliyor. Anahtar orada, boot sırasında ulaşılabilir.

Gerçekte Ne Kadar “Sıfırlanıyor”?

Şu anki disk durumu:

Filesystem      Size  Used Avail  Mount
none            8,0G   70M  8,0G  /
/dev/nvme0n1p3  899G  184G  714G  /home
/dev/nvme0n1p3  899G  184G  714G  /nix
/dev/nvme0n1p3  899G  184G  714G  /persist

Root tmpfs’te 70MB — bunun büyük çoğunluğu boot sonrası NixOS’un /etc altına yazdıkları ve çalışan servislerin geçici dosyaları. Disk yazılmıyor.

Neden İstiyorum Bunu?

İki ana neden:

Sürüklenme (drift) olmuyor. Geleneksel Linux sistemlerinde zaman içinde “şimdilik böyle yapayım” kararları birikir. Bir yere bir şey eklenir, bir config düzenlenir, bir servis elle başlatılır ve unutulur. Sistem gerçekte ne olduğunu artık tam yansıtmıyor. Impermanence bunu imkânsız kılıyor — her boot deklaratif konfigürasyonun tam yansıması.

Temiz başlangıç garantisi. Yeni bir paket denerken veya servisi test ederken, sistemi pislettiğimi düşünmüyorum. Bir sonraki boot her şeyi geri alır. Persist etmek istediğim bir şeyi açıkça tanımlamam gerekiyor — bu da neyin gerçekten kalıcı olmaya değer olduğunu düşündürüyor.

NixOS, sistem konfigürasyonunu zaten deklaratif yönetiyor. Impermanence bunu runtime state’e kadar genişletiyor.


İlgili: NixOS: Kaostan Düzene Declarative Bir Yolculuk

EOF.