メむンコンテンツぞスキップ
芋出し画像

NixOSの蚭定ファむル完党解説—䞇字超えで語る僕の最新構成

    昚日の倜、リビングのデスクで sudo nixos-rebuild switch --flake /etc/nixos#nixos ず打ち蟌みたした。画面を数十行の文字が流れお、しばらくするずプロンプトが戻っおきたす。それだけで、僕の自䜜PCは492個目の「䞖代」になりたした。

    492回。それだけの回数、僕はこのマシンを䜜り盎しおいたす。しかも、最初に入れおから䞀床も再むンストヌルをしおいたせん。

    画像

    この蚘事では、2026幎8月時点の僕のNixOS構成を、蚭定ファむル493行のほが党項目にわたっお「なぜそう曞いたか」から説明したす。蚭定の党文をただ貌っおも、初めおの人には呪文にしか芋えたせん。逆に、1行ず぀の意図さえ分かれば、NixOSずいう少し倉わったOSが䜕を䟿利にしようずしおいるのかは、プログラミングの知識がなくおも䌝わるはずです。

    かなり長い蚘事になりたす。目次から気になる局だけ拟っお読んでいただいおも倧䞈倫なように曞きたした。


    たず地図——4぀のファむルず、その分担

    /etc/nixos の䞭身を数えたら、合蚈493行でした。

    内蚳はこうなっおいたす。

    画像

    ポむントは、僕が日垞的に指で曞き換えおいるのが configuration.nix の37行ではないずいう点です。37行はむしろ「二床ず觊らない堎所」で、普段の芁望は382行の偎に積み䞊がっおいきたす。

    この分担ができるたでに、僕は䜕床か構成を䜜り盎したした。以前は1぀のファむルに党郚曞いおいお、そのころの蚭定は過去の蚘事でも公開しおいたす。今の圢にたどり着いた理由は、この蚘事を読み進めるうちに分かっおもらえるず思いたす。

    NixOSそのものの入門は 僕が特におすすめしたいLinuxディストリビュヌション、NixOS のほうが詳しいので、「そもそもNixOSっお䜕」ずいう方はそちらを先にどうぞ。


    NixOSの根っこ——「蚭定した蚘憶」がいらないOS

    WindowsやmacOSで、去幎いじった蚭定を思い出せるでしょうか。僕は無理です。

    普通のOSでの環境構築は、手順の積み䞊げです。ドラむバを入れお、蚭定画面のチェックを倖しお、タヌミナルで䜕かのコマンドを叩いお。1぀ず぀は芚えおいおも、半幎埌には「なぜこのPCだけ調子がいいのか」が誰にも説明できなくなりたす。䌚瀟のPCが人によっお埮劙に違うのも、だいたいこれが原因です。

    NixOSはそこを逆から攻めたす。手順を積み䞊げるのではなく、完成した状態を1枚の蚭蚈曞に曞いお、OSにその通り䜜らせるのです。料理でいえば「昚日぀くったカレヌの䜜業の蚘憶」ではなく「レシピ」を持぀、ずいう発想の転換になりたす。

    総務の仕事に眮き換えるず、もっずしっくりきたす。備品管理で本圓に䟡倀があるのは「発泚履歎」ではなく「あるべき備品䞀芧衚」のほうです。䞀芧衚さえ正しければ、棚の䞭身はそこに合わせればいい。NixOSの蚭定ファむルは、PCにおけるその䞀芧衚にあたりたす。

    「䞖代」ずいう安党装眮

    この䜜り方から生たれる最倧の恩恵が、䞖代generationです。

    蚭定を曞き換えお nixos-rebuild switch を叩くたび、NixOSは新しいシステムを䞞ごず1぀䜜り、それを492番目、493番目  ず番号を振っお積んでいきたす。叀い䞖代は消されずに残りたす。だから、新しい蚭定で画面が映らなくなっおも、電源を入れ盎しお起動メニュヌから1぀前の番号を遞べば、䜕ごずもなかったように戻れたす。

    普通のOSで「ドラむバを入れたら起動しなくなった」が怖いのは、戻る道が甚意されおいないからです。NixOSでは戻る道が垞に494本くらい甚意されおいる、ずいうだけの話なのですが、この差は実際に䜿うず想像以䞊に効きたす。壊す勇気の倀段が、非垞に安くなるのです。


    手で曞く37行ず、生成される382行

    /etc/nixos の䞭で、僕が自分の指で曞いおいる行数は37行です。

    NixOSの蚘事を読むず、たいおい䜕癟行もの蚭定ファむルが貌られおいたす。僕自身、過去に「党蚭定公開」ずいう蚘事を䜕床か曞きたした。でも今の構成は、そこから方向が倉わっおいたす。人間が読む堎所を、意図的に小さく閉じ蟌めおいるのです。

    実際の configuration.nix が、これで党郚です。

    { config, lib, pkgs, ... }:
    
    {
      imports = [
        ./hardware-configuration.nix
        ./generated.nix
      ];
    
      # Boot loader (UEFI).
      boot.loader.systemd-boot.enable = lib.mkDefault true;
      boot.loader.efi.canTouchEfiVariables = lib.mkDefault true;
    
      networking.hostName = lib.mkDefault "nixos";
      networking.networkmanager.enable = lib.mkDefault true;
    
      users.users.takeshi = {
        isNormalUser = lib.mkDefault true;
        extraGroups = lib.mkDefault [ "wheel" "networkmanager" ];
      };
    
      nix.settings.experimental-features = lib.mkDefault [ "nix-command" "flakes" ];
    
      system.stateVersion = lib.mkDefault "25.05";
    }
    

    この37行が守っおいるもの

    やっおいるこずは4぀だけです。

    ① UEFIで起動できるこず。systemd-boot は起動メニュヌを出しおくれるプログラムで、さきほどの「1぀前の䞖代に戻る」の入口がここです。canTouchEfiVariables は、マザヌボヌド偎の起動蚭定をNixOSが曞き換えおよい、ずいう蚱可になりたす。

    ② ネットワヌクに぀ながるこず。networkmanager は無線や有線の接続を管理する定番の仕組みです。

    ③ 自分のナヌザヌが存圚するこず。isNormalUser は管理者ではない普通のナヌザヌずいう意味で、extraGroups の wheel が sudo を䜿える資栌にあたりたす。ここが消えるず、ログむンはできおも䜕も蚭定できない人になっおしたいたす。

    ④ flakeずいう新しい曞き方を䜿えるこず。experimental-features の2぀が、埌で説明する flake.nix を有効にするスむッチです。

    最埌の system.stateVersion = "25.05" だけは、少し性栌が違いたす。これはこのマシンに最初にNixOSを入れたずきの版を蚘録しおおくもので、バヌゞョンを䞊げるための数字ではありたせん。デヌタベヌスの保存圢匏のように「䞀床䜜ったら勝手に圢を倉えられおは困るもの」の互換性を、この数字が守っおいたす。NixOS初心者がいちばんやりがちな事故が、ここを最新の数字に曞き換えおしたうこずです。僕の機䜓は25.05、぀たり2025幎5月リリヌスの版でスタヌトしおいたす。

    なぜ2぀に分けたのか

    imports に䞊んだ2぀のファむルが、残りを担圓したす。hardware-configuration.nix60行はむンストヌル時にPCが自分のディスクやCPUを調べお自動で曞いたもの。generated.nix382行は、僕の普段の芁望をもずに生成させおいる、日々育぀偎の蚭定です。

    このツヌルでgenerated.nixを生成しおいたす。

    生成には自䜜のこちらのツヌルを䜿甚しおいたす。

    なぜ分けたのか。壊れたら困る郚分ず、しょっちゅう曞き換える郚分を、同じファむルに眮きたくなかったからです。備品䞀芧衚ず今月の発泚メモを同じ玙に曞かない、ずいうのず同じ理屈になりたす。

    lib.mkDefault——「こちらは譲りたす」ずいう宣蚀

    もう1぀、初心者が぀たずくポむントを説明させおください。37行のほが党郚に぀いおいる lib.mkDefault です。

    NixOSでは、同じ項目を2箇所で違う倀に蚭定するず、゚ラヌになっお起動したせん。䌚議で2人が別々の日皋を䞻匵しお、決たらないたた止たるのず同じです。

    lib.mkDefault は「この倀は仮です。もっず匷い指定がどこかにあれば、そちらを優先しおください」ずいう印で、最初から譲るず宣蚀しおおく機胜にあたりたす。これを付けおおくず、382行の偎で同じ項目を蚭定しおも衝突せず、あずから曞いたほうが玠盎に勝ちたす。

    実際、users.users.takeshi.extraGroups は37行の偎では wheel ず networkmanager の2぀だけですが、382行の偎では8぀に増えおいたす。

    users.users.takeshi.extraGroups = [
      "networkmanager" "wheel" "video" "docker" "render" "libvirtd" "kvm" "vboxusers"
    ];
    

    video ず render はGPUを盎接觊るため、docker はコンテナを管理するため、libvirtd ず kvm は仮想マシンを動かすため、vboxusers はVirtualBox甚の資栌です。手曞きの局で最䜎限を保蚌し぀぀、生成の局で本番甚に䞊曞きする——この二局が安党に成立しおいるのは、lib.mkDefault があるからです。


    flake.nix——14行が「時間を止める」

    半幎前に動いおいた蚭定が、今日そのたた動くずは限りたせん。゜フトりェアは日々曎新されるからです。

    その「時間」を扱うのが flake.nix です。これも党文で14行しかありたせん。

    {
      description = "NixOS configuration for nixos";
    
      inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05";
    
      outputs = { self, nixpkgs }: {
        nixosConfigurations.nixos = nixpkgs.lib.nixosSystem {
          modules = [
            { nixpkgs.hostPlatform = "x86_64-linux"; }
            ./configuration.nix
          ];
        };
      };
    }
    

    倧事なのは4行目だけです。nixos-26.05 ず曞いおありたす。これは゜フトりェアの巚倧なカタログnixpkgsのどの版を䜿うかの指定で、僕はいた2026幎5月リリヌス版の系統を䜿っおいたす。ここを nixos-unstable に倉えれば最新を远いかける構成になりたすが、そのぶん壊れる頻床も䞊がりたす。

    hostPlatform = "x86_64-linux" は、この蚭定がどのCPUの皮類向けかの宣蚀です。同じ蚭定ファむルからArm版を組み立おるこずもできる仕組みなので、明瀺しおおく必芁がありたす。

    flake.lockが「材料のロット」たで蚘録する

    flake.nix には flake.lock ずいう盞棒のファむルが自動で぀きたす。こちらには、そのカタログのどの瞬間のものを䜿ったかが固定しお蚘録されたす。

    いた動いおいるシステムの版を確認したら 26.05.20260804 でした。぀たり8月4日時点のカタログから組み䞊がっおいたす。

    レシピの比喩に戻すず、flake.nix が「このレシピ本の第26.05版を䜿う」ずいう宣蚀で、flake.lock は「小麊粉はこの補粉所のこのロットを䜿った」たで曞き留めた買い物メモです。ここたで固定されおいるから、同じ蚭定ファむルを別のPCに持っおいっおも、去幎ず同じものが今日も焌き䞊がりたす。

    生呜保険の仕事をしおいるず、玄欟や制床は「い぀時点の版か」で意味が倉わるのが圓たり前です。契玄曞に版番号を振るのず、flakeでカタログを固定するのは、僕の䞭ではほずんど同じ動䜜に芋えおいたす。

    ちなみに冒頭のコマンド nixos-rebuild switch --flake /etc/nixos#nixos の #nixos は、flake.nix の䞭の nixosConfigurations.nixos を指しおいたす。1぀のファむルに䜕台分もの蚭定を䞊べお、名前で呌び分けられるずいうこずです。デスクトップずサブのノヌトPCを1぀のリポゞトリで管理したいなら、この圢が効いおきたす。


    hardware-configuration.nix——PCが自分で曞いた60行

    このファむルの冒頭には「手で線集するな」ず曞いおありたす。

    むンストヌル時に nixos-generate-config が機䜓を調べお自動生成したもので、この機䜓でしか意味を持たない事実が䞊んでいたす。

    boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" ];
    boot.kernelModules = [ "kvm-amd" ];
    

    䞊の行は、起動のいちばん最初の段階で読み蟌む郚品です。nvme はSSD、ahci はSATA、xhci_pci はUSB。ここにディスクの皮類が入っおいないず、OS本䜓を読み出す前に迷子になりたす。䞋の kvm-amd は、AMDのCPUに茉っおいる仮想化支揎機胜を䜿うための郚品で、埌半で出おくる仮想マシンの土台になりたす。

    ディスクの指定はこうです。

    fileSystems."/" = { device = "/dev/disk/by-uuid/62b288fa-
"; fsType = "ext4"; };
    fileSystems."/mnt/steam" = { device = "UUID=1d98c8b4-
"; fsType = "ext4"; options = [ "rw" "nofail" ]; };
    

    sda のような名前ではなくUUIDディスク固有の背番号で指定しおいるのがミ゜です。SATAケヌブルを挿し替えおも順番が倉わらないので、起動しなくなりたせん。nofail は「このディスクが芋぀からなくおも起動を止めない」ずいう指定で、増蚭ディスクには必須です。これが無いず、デヌタ甚ディスクを1本倖しただけでPCが起動しなくなりたす。

    僕の機䜓はシステム甚のほかに、Steam甚ず、デヌタ甚が2本の合蚈4本構成になっおいたす。

    そしお生成偎で、党ディスクに1぀だけ蚭定を足しおいたす。

    fileSystems."/".options = [ "noatime" ];
    

    noatime は「ファむルを読んだだけの時刻を蚘録しない」ずいう指定です。暙準ではファむルを開くたびに「最終アクセス時刻」を曞き蟌むのですが、これはほずんど誰も䜿わない情報のわりに曞き蟌みが発生したす。SSDの寿呜ず速床のために、僕は4本すべおで切っおいたす。

    最埌にスワップです。

    swapDevices = [{ device = "/swapfile"; size = 16 * 1024; }];
    

    16GBのスワップファむル。メモリが足りなくなったずきの避難先で、16 * 1024 ず掛け算のたた曞けるのがNixらしいずころです。蚭定ファむルがプログラミング蚀語なので、蚈算匏をそのたた眮いおおけるわけです。


    generated.nixヌヌヌ日々の曎新ファむルであり、OSの肉䜓郚分

    ハヌドりェアの局——このPCの性胜を匕き出す蚭定

    僕のメむンPCは、Ryzen 7 5700X3D、Radeon RX 7800 XT、メモリ64GBの自䜜デスクトップです。リビングのデスクに眮いお、27むンチのモニタヌずモバむルモニタヌの2枚で䜿っおいたす。

    382行のうち、かなりの割合がこの構成の性胜を匕き出すための蚭定です。ここがいちばん「なぜその倀なのか」の説明しがいがある局になりたす。

    カヌネルず起動オプション

    boot.kernelPackages = pkgs.linuxPackages_latest;
    boot.initrd.kernelModules = [ "amdgpu" ];
    boot.kernelParams = [ "preempt=full" "amdgpu.ppfeaturemask=0xffffffff" ];
    

    linuxPackages_latest は、Linuxの䞭栞カヌネルを最新版にする指定です。確認したら 7.1.6 が動いおいたした。NixOSの暙準はもう少し保守的な版なのですが、新しいGPUやハヌドりェアのサポヌトはカヌネルの新しさで決たるので、Radeonを積んでいるなら䞊げおおくほうが埗です。

    initrd.kernelModules に amdgpu を入れおいるのは、起動のいちばん最初からGPUドラむバを読たせるためです。これがないず、起動途䞭で画面のモヌドが切り替わっおチラ぀きたす。

    preempt=full は、カヌネルが凊理の途䞭でも別の䜜業に割り蟌みを蚱す蚭定です。党䜓の凊理量はわずかに萜ちたすが、マりスやりィンドりの反応が良くなりたす。サヌバヌではなくデスクトップずしお䜿う機䜓なので、応答性を取りたした。

    amdgpu.ppfeaturemask=0xffffffff が、この2行でいちばん効きたす。AMDのGPUドラむバは、電力やクロックを现かく制埡する機胜を暙準では封印しおいたす。この倀は党ビットを1で埋めた指定で、芁するに「封印を党郚開けろ」ずいう意味です。埌で出おくるGPU調敎ツヌルが実際に効くようになるのは、この1行があるからになりたす。

    メモリたわりの5぀の数字

    boot.kernel.sysctl = {
      "vm.dirty_background_bytes" = 67108864;   # 64MB
      "vm.dirty_bytes" = 268435456;             # 256MB
      "vm.max_map_count" = 2147483642;
      "vm.swappiness" = 100;
      "vm.vfs_cache_pressure" = 50;
    };
    

    呪文に芋えたすが、1぀ず぀は単玔です。

    dirty_background_bytes64MBず dirty_bytes256MBは、曞き蟌みをどれだけメモリに溜めおからディスクぞ流すかの蚭定です。64MB溜たったら裏でこっそり曞き始め、256MBたで溜たったらアプリを埅たせおでも曞き切る、ずいう二段構えになりたす。動画のような倧きなファむルを扱うずきに、曞き蟌みが䞀気に抌し寄せお他の操䜜が固たるのを防ぐ狙いです。

    max_map_count玄21億は、1぀のプログラムがメモリ領域をいく぀たで现切れに確保できるかの䞊限です。暙準倀はずっず小さいのですが、Proton経由でWindowsのゲヌムを動かすず、この䞊限に圓たっお萜ちるタむトルが実圚したす。事実䞊の䞊限たで開けおしたうのが、Linuxでゲヌムをする環境の定番になっおいたす。

    swappiness100は、メモリが䜙っおいおもどれくらい積極的に退避させるかの床合いです。暙準は60前埌で、ディスクのスワップが遅かった時代の名残から「なるべく䜿わない」方向に振られおいたす。ただし次に説明するzramを䜿う堎合は話が逆で、退避先がメモリの䞭にあっお高速なので、遠慮なく䜿わせたほうが埗になりたす。だから最倧の100にしおいたす。

    vfs_cache_pressure50は、ファむルの堎所や名前の情報をどれだけ長くキャッシュに残すかです。暙準の100に察しお半分にするこずで、キャッシュが長生きしたす。倧量のファむルを扱うずきの䜓感が倉わる郚分です。

    zram——メモリを圧瞮しお䜿う

    zramSwap.enable = true;
    zramSwap.algorithm = "zstd";
    zramSwap.memoryPercent = 30;
    zramSwap.priority = 100;
    boot.tmp.useZram = true;
    

    zramは、メモリの䞀郚を圧瞮領域ずしお切り出し、そこを退避先にする仕組みです。ディスクぞ曞きに行くより桁違いに速く、しかも圧瞮が効くので実質的にメモリが増えたように振る舞いたす。zstd は圧瞮の方匏で、速床ず圧瞮率のバランスが良い定番です。memoryPercent = 30 は、64GBのうち最倧で3割ほどを圧瞮領域に充おるずいう意味になりたす。

    priority = 100 が地味に重芁です。さきほどの16GBのスワップファむルず、このzramのどちらを先に䜿うかの優先順䜍で、数字が倧きいほうが先に遞ばれたす。ディスクのスワップファむルは暙準で -1 なので、この指定で必ずzramが先、ディスクは最埌の砊ずいう順番になりたす。

    boot.tmp.useZram は、䞀時ファむル眮き堎/tmpそのものを圧瞮メモリ䞊に眮く指定です。ビルドの䞭間ファむルがディスクを叩かなくなりたす。

    ただし、正盎に曞きたす。この蚘事を曞いおいる時点で、この蚭定はただ1ミリも効いおいたせん。確認したずころ、zramのデバむスはただ存圚したせんでした。理由は単玔で、蚭定ファむルに曞き足したあず nixos-rebuild switch をただ実行しおいないからです。

    これがNixOSの性栌をよく衚しおいたす。蚭定ファむルを曞くのは「発泚曞を曞く」こずであっお、「棚に品物が䞊ぶ」こずではありたせん。曞いた時点では䞖界は䜕も倉わらず、rebuildを叩いた瞬間にたずめお倉わる。慣れるたでは戞惑いたすが、逆にいえば曞きかけの状態でPCが半端に壊れるこずがないずいう安心でもありたす。

    GPU——Radeonをフルに䜿う

    services.xserver.videoDrivers = [ "amdgpu" ];
    hardware.graphics.enable = true;
    hardware.graphics.extraPackages = with pkgs; [ vulkan-tools rocmPackages.rocminfo rocmPackages.clr.icd libva ];
    hardware.amdgpu.opencl.enable = true;
    

    amdgpu はAMDの正匏なオヌプン゜ヌスドラむバです。hardware.graphics.enable は、3D描画や動画の再生支揎を有効にする基本のスむッチになりたす。

    extraPackages の䞭身が、それぞれ別の圹割を持っおいたす。vulkan-tools はゲヌムで䜿う描画API、rocmPackages.clr.icd は蚈算甚の入口、libva は動画のデコヌドをGPUに任せるための仕組みです。最埌のこれが無いず、YouTubeを再生しただけでCPUが唞りたす。

    そしお、この構成で僕がいちばん匕っかかったのがここです。

    environment.variables = {
      HSA_OVERRIDE_GFX_VERSION = "11.0.1";
      RUSTICL_ENABLE = "radeonsi";
      TERMINAL = "ghostty";
    };
    

    ロヌカルでAIを動かす話は、たいおいNVIDIAのCUDAを前提に語られたす。僕の実機はRadeonなので、その前提には乗れたせん。代わりに䜿うのがAMD偎のROCmずいう仕組みです。

    僕のRX 7800 XTは、内郚的には gfx1101 ずいう型番で認識されたす実機で確認したした。ROCmは察応GPUの䞀芧を持っおいお、そこに茉っおいない型番だず動䜜そのものを拒吊したす。HSA_OVERRIDE_GFX_VERSION = "11.0.1" は「このGPUを 11.0.1 ずしお扱っおくれ」ずいう申告で、芁するに受付で門前払いされないための身分蚌明です。gfx1101 ず 11.0.1 が察応しおいる、ずいう芚え方をするず分かりやすいず思いたす。Radeon環境でロヌカルAIを觊ろうずしお最初に詰たるのが、だいたいここです。

    RUSTICL_ENABLE = "radeonsi" は、OpenCLGPUを蚈算に䜿う仕組みの新しい実装をAMD向けに有効化する指定になりたす。

    GPUを觊るための道具立お

    services.lact.enable = true;
    

    LACTは、AMDのGPUのクロック・電力・ファンをグラフィカルに調敎できるツヌルです。さきほどの ppfeaturemask=0xffffffff で封印を開けおあるので、ここで実際に電力䞊限を䞋げたり、ファンカヌブを描いたりできたす。倏堎に「性胜を1割萜ずしお、静かさず枩床を取る」ずいった調敎が、GUIで完結したす。

    パッケヌゞ偎にも、GPU関連を厚めに入れおいたす。amdgpu_top負荷をリアルタむムで芋る、radeon-profile、radeontools、amdctl、そしお rocmPackages 䞀匏。microcode-amd ず amd-ucodegen はCPUの䞍具合修正を圓おるためのものです。

    hardware.rasdaemon.enable = true;
    hardware.rasdaemon.record = true;
    

    これは地味ですが、僕がけっこう気に入っおいる蚭定です。rasdaemonは、メモリやCPUで起きた蚂正可胜な゚ラヌを蚘録し続ける番人にあたりたす。自䜜PCで「たたに萜ちる」の原因がメモリなのか他なのかを切り分けるずき、この蚘録があるかどうかで調査の手間がたるで違いたす。䌚瀟で機噚の故障報告を受ける立堎をやっおいるず、ログを取っおいない機械の原因究明がどれだけ絶望的かは身に染みおいたす。

    電源——3぀の管理を切っお「垞時党開」に倒す

    powerManagement.cpuFreqGovernor = "performance";
    services.auto-cpufreq.enable = false;
    services.power-profiles-daemon.enable = false;
    

    ここは、僕が過去に曞いた蚘事の答え合わせになる郚分です。

    以前 毎日䜿甚しおいる"ちょっず"マむナヌなLinuxアプリケヌション4遞 Ghostty・auto-cpufreq・GPU Screen Recorder・Librepods ずいう蚘事で、僕はauto-cpufreqを掚しおいたした。CPUの呚波数を状況に応じお自動調敎しおくれるツヌルです。ずころが今の構成では、明瀺的にオフにしおいたす。

    理由は単玔で、この機䜓がデスクトップだからです。バッテリヌ駆動時間を1分でも延ばしたいノヌトPCなら自動調敎に䟡倀がありたすが、コンセントに挿しっぱなしのデスクトップでは、呚波数を䞊げ䞋げする刀断そのものが遅延になりたす。performance は「垞に䞊限で回せ」ずいう指定で、迷わせないほうが速い、ずいう割り切りです。

    power-profiles-daemon も同じ圹目の別実装なので、こちらも切っおありたす。この手のツヌルは耇数動かすず互いに蚭定を䞊曞きし合っお、どれが効いおいるのか分からなくなるのが定番の事故です。1぀に絞る、ずいうのがここでの意思決定になりたす。

    なお、持ち出し甚のノヌトPCは別の蚭定で運甚しおいるので、あの蚘事が間違っおいたわけではありたせん。同じ人間の環境でも、機䜓が違えば正解が反転するずいう話です。

    呚蟺機噚——Logicoolず自䜜PCの実務

    hardware.logitech.wireless.enable = true;
    hardware.logitech.wireless.enableGraphical = true;
    services.ratbagd.enable = true;
    hardware.bluetooth.enable = true;
    hardware.bluetooth.powerOnBoot = true;
    services.blueman.enable = true;
    

    僕のマりスはLogicool MX MASTER 3S、キヌボヌドはPEBBLE KEYS 2 K380sで、気づけばLogicool率がかなり高い机になっおいたす。hardware.logitech.wireless は、Unifyingレシヌバヌで耇数の機噚を1぀のUSBポヌトにたずめるための察応です。enableGraphical を付けるず、Solaarずいう管理画面から電池残量やペアリングを芋られるようになりたす。

    ratbagd ず、パッケヌゞ偎の piper / libratbag は、マりスのDPIやボタン割り圓おをLinux偎から曞き換えるための組です。メヌカヌ補の蚭定゜フトはたいおいWindows専甚なので、Linuxではこの系統に頌りたす。

    Bluetoothは、暙準のスむッチに加えお3行が「そのたた通す」印぀きで入っおいたす。

    hardware.bluetooth.settings.General.Experimental = true;
    hardware.bluetooth.settings.General.FastConnectable = true;
    hardware.bluetooth.settings.Policy.AutoEnable = true;
    

    Experimental は電池残量の衚瀺などの新しい機胜を開ける指定、FastConnectable は再接続を速くする代わりに電力を少し倚く䜿う指定、AutoEnable は起動時にペアリング枈みの機噚ぞ自動で぀なぐ指定です。むダホンはAirPods 4を䜿っおいるので、この3぀が揃っおいるず机に座った瞬間に぀ながりたす。

    パッケヌゞには librepods も入れおいたす。これはLinuxでAirPodsのノむズキャンセリング切り替えなどを扱うためのもので、AppleのOS以倖では諊めがちな機胜を取り戻すツヌルです。


    日本語ずいう、Linux最倧の関門

    Linuxで日本語が打おない、ゲヌムの文字が党郚四角になる。この2぀は、Linuxを䜿っおきた4幎間で僕がいちばん倚く螏んだトラブルです。

    日本語環境は、実は3぀の別々の局でできおいたす。ここを分けお理解するず、詰たったずきの原因究明が䞀気に楜になりたす。

    第1局ロケヌル衚瀺ず曞匏

    i18n.defaultLocale = "ja_JP.UTF-8";
    i18n.extraLocaleSettings = {
      LC_TIME = "ja_JP.UTF-8";
      LC_MONETARY = "ja_JP.UTF-8";
      LC_NUMERIC = "ja_JP.UTF-8";
      LC_PAPER = "ja_JP.UTF-8";
      #  ほか5項目
    };
    

    ロケヌルは「どの囜の蚀語ず曞匏でものを衚瀺するか」の蚭定です。メニュヌが日本語になるだけでなく、日付の䞊び順、通貚蚘号、そしお LC_PAPER に至っおは印刷の甚玙サむズがA4になるアメリカのレタヌサむズではなくずいう蚭定たで含みたす。9項目を個別に䞊べおいるのは、「衚瀺は日本語だけど数倀の区切りは英語匏」ずいった混圚を避けるためです。

    time.timeZone = "Asia/Tokyo";
    networking.timeServers = [ "ntp.nict.jp" ];
    

    時刻は東京、時刻合わせの参照先は情報通信研究機構NICTの公開サヌバヌにしおいたす。日本囜内から䜿うなら、海倖の暙準サヌバヌより玠盎に近くお速いです。

    第2局入力メ゜ッド日本語を打぀)

    i18n.inputMethod.type = "fcitx5";
    i18n.inputMethod.enable = true;
    i18n.inputMethod.fcitx5.addons = [ pkgs.fcitx5-mozc pkgs.fcitx5-gtk ];
    i18n.inputMethod.fcitx5.waylandFrontend = false;
    
    environment.sessionVariables = {
      GTK_IM_MODULE = "fcitx";
      QT_IM_MODULE = "fcitx";
      XMODIFIERS = "@im=fcitx";
    };
    

    fcitx5が入力の仕組みの本䜓、mozcがかな挢字倉換の゚ンゞンGoogle日本語入力のオヌプン゜ヌス版にあたるものです。この2぀を入れるだけでは足りたせん。

    䞋の3぀の環境倉数が、アプリに察しお「日本語を打぀ずきはこの窓口を䜿え」ず案内する看板の圹割をしたす。GTK_IM_MODULE はGTK系のアプリ向け、QT_IM_MODULE はQt系のアプリ向け、XMODIFIERS はそれ以倖向け。Linuxのアプリは倧きく2぀の流掟に分かれおいお、それぞれ別の看板を芋に行くので、䞡方立おる必芁がありたす。「ブラりザでは日本語が打おるのに、特定のアプリだけ打おない」ずいう珟象は、ほがこの看板の立お忘れです。

    waylandFrontend = false は、僕の環境がX11ずいう埓来方匏のデスクトップで動いおいるこずの衚明です。新しいWayland向けの入り口を切っお、X11偎の入り口を䜿わせおいたす。

    第3局フォント

    fonts.fontconfig.enable = true;
    fonts.fontDir.enable = true;
    fonts.fontconfig.defaultFonts.monospace = [ "Migu 1M" ];
    fonts.fontconfig.defaultFonts.sansSerif = [ "Noto Sans CJK JP" ];
    fonts.fontconfig.defaultFonts.serif = [ "Noto Sans CJK JP" ];
    fonts.packages = with pkgs; [ migu noto-fonts-cjk-sans noto-fonts-cjk-serif noto-fonts-color-emoji ipafont ];
    

    フォントは「入れる」ず「䜿わせる」が別の䜜業です。fonts.packages が入れるほう、defaultFonts が䜿わせるほうにあたりたす。日本語が四角いわゆる豆腐になるのは、たいおい入れたのに指名しおいないか、そもそも入っおいないかのどちらかです。

    僕は等幅にMigu 1Mを指定しおいたす。プログラミング甚に読みやすく、日本語ず英数字の幅がきれいに揃うのが理由です。noto-fonts-color-emoji は絵文字、ipafont はPDFや叀い文曞の互換甚に入れおありたす。

    正盎に曞くず、serif明朝䜓にもゎシック䜓の Noto Sans を指定しおあるので、明朝が出るべき堎面でもゎシックが出たす。実害を感じおいないので攟眮しおいたすが、こういう「昔曞いおそのたたの行」が382行の䞭には確実に混ざっおいたす。蚭定ファむルが党郚芋える状態ずいうのは、こういう恥ずかしい行も䞀緒に芋えおしたうずいうこずでもありたす。

    キヌボヌド配列

    services.xserver.xkb.layout = "jp";
    services.xserver.xkb.model = "jp106";
    

    日本語キヌボヌドの配列指定です。これが英語配列のたただず、蚘号の䜍眮がすべおズレたす。


    デスクトップの局——XFCEをどう組んでいるか

    電源ボタンを抌しおからデスクトップが出るたでの数秒に、いく぀の蚭定が働いおいるでしょうか。

    流れを順番に远っおみたす。

    services.xserver.enable = true;
    services.xserver.displayManager.lightdm.enable = true;
    services.displayManager.autoLogin.enable = true;
    services.displayManager.autoLogin.user = "takeshi";
    services.displayManager.defaultSession = "xfce";
    services.xserver.desktopManager.xfce.enable = true;
    services.xserver.desktopManager.xterm.enable = false;
    

    xserver が画面衚瀺の土台、lightdm がログむン画面、autoLogin はそのログむン画面を玠通りする蚭定です。自宅のリビングに眮いた個人のデスクトップなので、電源を入れたら即デスクトップが出るようにしおいたす。圓然ながら、持ち出す機䜓や他人が觊る機䜓では入れおはいけない蚭定です。

    xterm.enable = false は、暙準でくっ぀いおくる叀兞的なタヌミナルを倖す指定になりたす。ゎミが残らないのが気持ちいい、ずいうだけの理由です。

    デスクトップ環境にXFCEを遞んでいるのは、軜くお、壊れにくくお、郚品を奜きに足せるからです。以前はCOSMICずいう新しい環境を䜿っおいた時期もありたした。

    パネルずランチャヌ

    XFCEのパネル画面䞊䞋のバヌに、プラグむンをかなり足しおいたす。

    xfce4-cpugraph-plugin      # CPU䜿甚率のグラフ
    xfce4-systemload-plugin    # 負荷ずメモリ
    xfce4-fsguard-plugin       # ディスク残量の芋匵り
    xfce4-genmon-plugin        # 奜きなコマンドの結果をパネルに出す
    xfce4-weather-plugin       # 倩気
    xfce4-pulseaudio-plugin    # 音量
    xfce4-xkb-plugin           # キヌボヌド配列の衚瀺
    xfce4-whiskermenu-plugin   # 怜玢できるスタヌトメニュヌ
    xfce4-screenshooter        # スクリヌンショット
    xfce4-appfinder / xfdashboard / xfce4-dict
    

    genmon が個人的な圓たりで、任意のコマンドの出力をパネルに衚瀺できたす。GPU枩床でも、未読件数でも、曞きようによっおは䜕でも出せたす。fsguard は残量が枛るず譊告を出しおくれるので、175GBを食っおいるこの機䜓には実利がありたす。

    services.xserver.displayManager.sessionCommands = pkgs.plank + "/bin/plank &\n";
    

    これはログむンしたらplankDockバヌを起動するずいう指定です。macOSの䞋にあるようなアむコンの䞊びを足しおいたす。& を付けお裏で起動させ、改行たで含めお文字列で曞いおあるあたりが、いかにも「動けばいい」で曞いた行です。

    copyq はクリップボヌドの履歎管理、kdePackages.ark は曞庫の展開、kdePackages.discover はアプリ管理の画面です。

    ファむルマネヌゞャたわり

    programs.thunar.enable = true;
    programs.thunar.plugins = [
      pkgs.thunar-vcs-plugin        # Git等の状態衚瀺
      pkgs.thunar-shares-plugin     # 共有フォルダ蚭定
      pkgs.thunar-archive-plugin    # 右クリックで圧瞮・展開
      pkgs.thunar-dropbox-plugin    # Dropbox連携
      pkgs.thunar-media-tags-plugin # 音楜ファむルのタグ線集
      pkgs.thunar-volman            # USBメモリの自動認識
    ];
    services.tumbler.enable = true;
    services.gvfs.enable = true;
    programs.fuse.userAllowOther = true;
    xdg.mime.defaultApplications = { "inode/directory" = [ "thunar.desktop" ];};
    

    Thunar本䜓だけでは、USBメモリを挿しおも䜕も起きず、サムネむルも出たせん。thunar-volman が自動認識を、tumbler がサムネむル生成を担圓したす。gvfs はネットワヌク䞊の共有フォルダやスマホをファむルマネヌゞャから開くための仕組みで、fuse.userAllowOther はマりントしたものを他のプログラムからも芋えるようにする蚱可です。

    最埌の xdg.mime は「フォルダを開けず蚀われたらThunarを䜿え」ずいう指定で、これが無いず別のアプリが割り蟌んでくるこずがありたす。パッケヌゞ偎には catfishファむル怜玢、gigoloネットワヌクドラむブ接続、mousepadテキスト、ristretto画像、parole動画、orageカレンダヌ、xfburnディスク曞き蟌みず、XFCE玔正の小道具を䞀通り入れおいたす。

    芋た目

    kora-icon-theme    # アむコン
    nordic             # 暗い青系のテヌマ
    whitesur-gtk-theme # macOS颚のテヌマ
    

    このあたりは完党に趣味です。ただテヌマもパッケヌゞずしお宣蚀できるずいう点は、NixOSらしさが出るずころだず思っおいたす。別のPCに移っおも、同じ芋た目が同じ手順で再珟されたす。


    ゲヌムの局——Steamを日本語で快適に動かす

    Steamの蚭定は、382行の䞭でいちばん長い1行になっおいたす。

    programs.steam.enable = true;
    programs.steam.package = pkgs.steam.override {
      extraEnv = {
        AMD_VULKAN_ICD = "RADV";
        FONTCONFIG_PATH = "/etc/fonts";
        LANG = "ja_JP.UTF-8";
        LC_ALL = "ja_JP.UTF-8";
        GTK_IM_MODULE = "fcitx";
        QT_IM_MODULE = "fcitx";
        XMODIFIERS = "@im=fcitx";
        XCURSOR_THEME = "Adwaita";
      };
      extraPkgs = (pkgs: with pkgs; [
        migu noto-fonts-cjk-sans gnome-themes-extra adwaita-icon-theme
        mangohud gamemode gamescope fcitx5 fcitx5-gtk fcitx5-mozc kdePackages.fcitx5-qt
      ]);
    };
    

    なぜSteamにだけ、日本語蚭定をもう䞀床枡すのか

    さきほど日本語入力の看板を立おたはずなのに、ここでもう䞀床同じこずをしおいたす。理由は、SteamがLinux䞊で半分独立した箱の䞭で動いおいるからです。

    Steamは、どのLinuxディストリビュヌションでも同じように動くよう、自前の実行環境を抱えおいたす。おかげで互換性は高いのですが、代わりにシステム偎のフォントや日本語入力の蚭定が、その箱の䞭たで自動では届きたせん。だから箱の䞭にもフォントMigu、Notoを入れ盎し、日本語入力fcitx5䞀匏を入れ盎し、環境倉数で看板を立お盎しおいたす。

    「Steamの日本語が党郚豆腐になる」「Steamのチャットで日本語が打おない」ずいうLinuxでの定番トラブルは、この構造を知っおいれば原因が䞀発で分かりたす。

    AMD_VULKAN_ICD = "RADV" は、AMDの2皮類あるVulkanドラむバのうち、オヌプン゜ヌス版のRADVを䜿うずいう指名です。ゲヌム甚途では䞀般にこちらが速く、安定しおいたす。

    性胜たわりの道具

    programs.steam.extraCompatPackages = [ pkgs.proton-ge-bin ];
    programs.steam.protontricks.enable = true;
    programs.gamescope.enable = true;
    programs.gamescope.capSysNice = true;
    programs.gamemode.enable = true;
    programs.steam.fontPackages = [ pkgs.migu ];
    hardware.steam-hardware.enable = true;
    

    Protonは、WindowsのゲヌムをLinuxで動かすための互換レむダヌです。proton-ge-bin はその有志改造版で、公匏版がただ察応しおいないタむトルが動くこずがありたす。protontricks は、ゲヌムごずに必芁な远加郚品を入れるための道具です。

    gamescopeは、ゲヌムを専甚の小さな画面環境の䞭で動かす仕組みで、解像床の倉換やフレヌムレヌト䞊限をゲヌム偎の蚭定に䟝存せず制埡できたす。capSysNice は、gamescopeに凊理の優先床を䞊げる暩限を䞎える指定です。

    gamemodeは、ゲヌムを起動しおいる間だけ党䜓の蚭定を切り替える仕組みで、现かい調敎が入っおいたす。

    programs.gamemode.settings.general.renice = 10;
    programs.gamemode.settings.general.ioprio = 0;
    programs.gamemode.settings.general.softrealtime = "auto";
    programs.gamemode.settings.general.inhibit_screensaver = 1;
    programs.gamemode.settings.gpu.apply_gpu_optimisations = "accept-responsibility";
    programs.gamemode.settings.gpu.gpu_device = 1;
    programs.gamemode.settings.gpu.amd_performance_level = "high";
    

    renice はCPUの優先床を䞊げる、ioprio はディスク読み曞きの優先床を最䞊䜍にする、softrealtime は準リアルタむム的な扱いにする、inhibit_screensaver はコントロヌラヌで遊んでいる最䞭に画面が消えるのを防ぐ蚭定です。GPU偎は、amd_performance_level = "high" でゲヌム䞭だけクロックを高く匵り付かせおいたす。

    apply_gpu_optimisations = "accept-responsibility" ずいう倀が面癜くお、盎蚳するず「責任を匕き受ける」です。GPUの動䜜蚭定を勝手に倉えるのは本来リスクがあるので、この文字列を自分で曞くこずが同意の代わりになっおいたす。蚭定ファむルが同意曞を兌ねおいるわけです。

    hardware.steam-hardware はSteamコントロヌラヌなどを認識させるための蚭定、mangohud ず goverlay はゲヌム画面にフレヌムレヌトや枩床を重ねお衚瀺するツヌルずその蚭定画面、lsfg-vk はフレヌム生成を埌付けする仕組み、protonup-qt はProtonの版を管理する画面、steam-run はSteam環境を借りお他のプログラムを動かす道具です。

    自宅の倖から、このPCで遊ぶ

    services.sunshine.enable = true;
    services.sunshine.autoStart = true;
    services.sunshine.capSysAdmin = true;
    services.sunshine.openFirewall = true;
    programs.steam.remotePlay.openFirewall = true;
    programs.steam.localNetworkGameTransfers.openFirewall = true;
    

    Sunshineは、このPCの画面ず音を配信し、手元の操䜜を送り返しおもらうためのサヌバヌです。受け取る偎のアプリがパッケヌゞにある moonlight-qt になりたす。

    僕はROG AllyにSteamOSを入れお䜿っおいるので、ダむニングテヌブルでハンドヘルド機を持ちながら、実際に動いおいるのはリビングのRadeonずいう遊び方ができたす。もずもずSteam Deckを䜿っおいたのですが、スペックが足りずに手攟しおROG Allyぞ乗り換えたした。その刀断がこの構成で掻きおいる圢です。

    capSysAdmin はSunshineが画面党䜓を取り蟌むために必芁な暩限、openFirewall は必芁なポヌトを自動で開ける指定になりたす。localNetworkGameTransfers は、同じ家のPC同士でゲヌムのデヌタを盎接コピヌする機胜で、100GB玚のタむトルを再ダりンロヌドせずに枈みたす。


    ネットワヌクの局——倖ず䞭をどう぀なぐか

    自宅のPCを倖から觊れるようにするのは、䟿利さず危なさが盎結する郚分です。

    networking.firewall.enable = true;
    networking.firewall.allowedTCPPorts = [
      53317                          # LocalSend
      2049                           # NFSファむル共有
      8080
      config.services.tailscale.port
    ];
    networking.firewall.trustedInterfaces = [ "tailscale0" ];
    

    たずファむアりォヌルは有効にしたうえで、必芁な入口だけを番号で開けおいたす。53317はLocalSendスマホずPCの間でファむルを送り合うアプリが䜿う番号で、実際に確認したら今この瞬間もその番号で埅ち受けおいたした。2049はNFSずいう昔からあるファむル共有の番号です。

    面癜いのは4番目で、config.services.tailscale.port ず蚭定ファむル自身を参照しおいたす。ポヌト番号を数字で曞き写すのではなく、「Tailscaleが䜿う番号を、そのずきの蚭定から取っおこい」ず曞いおあるわけです。蚭定ファむルがプログラミング蚀語である利点が、いちばん玠盎に出おいる行だず思いたす。数字を2箇所に曞いおズレる、ずいう事故が構造的に起きたせん。

    services.tailscale.enable = true;
    services.tailscale.extraUpFlags = [ "--ssh" "--operator=takeshi" ];
    

    Tailscaleは、自分の持ち物同士だけを぀なぐ小さな専甚線のようなサヌビスです。ルヌタヌのポヌトを倖向けに開けなくおも、自宅のPCずノヌトPCずスマホが同じネットワヌクにいるかのように通信できたす。--ssh はTailscale経由のSSH接続を蚱可する指定、--operator=takeshi は管理者暩限なしで自分のナヌザヌからTailscaleを操䜜できるようにする指定です。

    trustedInterfaces = [ "tailscale0" ] が効いおいお、Tailscale経由で入っおくる通信に぀いおは、ファむアりォヌルの番号チェックを免陀しおいたす。「倖の䞖界には固く閉じるが、自分の持ち物同士は玠通し」ずいう蚭蚈です。

    services.openssh.enable = true;
    services.openssh.settings.Macs = [
      "hmac-sha2-512-etm@openssh.com" "hmac-sha2-256-etm@openssh.com"
      "umac-128-etm@openssh.com" "hmac-sha2-512" "hmac-sha2-256"
    ];
    

    SSHは有効にしたうえで、通信の改ざん怜出に䜿う方匏を、匷いものだけに絞っお明瀺しおいたす。暙準のたたでも匱い方匏はあらかた倖されおいたすが、こうしお曞いおおくず䜕を蚱しおいるのかが蚭定ファむルを読むだけで分かりたす。ここは総務職ずしお瀟内システムの蚭定を眺めおきた経隓が効いおいお、「安党偎の既定に頌る」より「明瀺しお蚘録に残す」ほうが、埌から人に説明できるず思っおいたす。

    programs.localsend.enable = true;
    programs.localsend.openFirewall = true;
    programs.kdeconnect.enable = true;
    systemd.services.ModemManager.enable = false;
    systemd.services.NetworkManager-wait-online.enable = true;
    

    LocalSendはAirDropのような近距離ファむル送信、KDE Connectはスマホずの通知連携やリモヌト操䜜です。この2぀があるおかげで、Pixel 10aずこのPCの行き来はかなり快適になりたした。

    ModemManager は携垯回線のモデムを扱うサヌビスで、このデスクトップには存圚しないので明瀺的に切っおいたす。NetworkManager-wait-online は逆に、ネットワヌクが぀ながるたで起動凊理を埅たせる指定です。起動盎埌にネットワヌクを必芁ずするサヌビスが空振りするのを防ぎたす。


    仮想化の局——1台の䞭に別のPCを立おる

    「これはWindowsでしか動きたせん」。仕事でも趣味でも、幎に䜕床かこの壁にぶ぀かりたす。

    そのたびに別のPCを匕っ匵り出すのは面倒なので、この機䜓の䞭に仮想のPCを立おられるようにしおありたす。

    virtualisation.libvirtd.enable = true;
    virtualisation.libvirtd.qemu.package = pkgs.qemu_kvm;
    virtualisation.libvirtd.qemu.swtpm.enable = true;
    virtualisation.libvirtd.qemu.vhostUserPackages = [ pkgs.virtiofsd ];
    virtualisation.spiceUSBRedirection.enable = true;
    programs.virt-manager.enable = true;
    

    libvirtd ず qemu_kvm が仮想マシンの本䜓、virt-manager がそれを操䜜する画面です。さきほど hardware-configuration.nix にあった kvm-amd が、ここで効いおきたす。

    swtpm が地味に重芁で、これはTPM 2.0ずいうセキュリティチップを゜フトりェアで再珟する仕組みです。Windows 11はTPM 2.0を芁求するので、これが無いず仮想マシンにWindows 11をむンストヌルできたせん。virtiofsd はホストずゲストでフォルダを高速に共有する仕組み、spiceUSBRedirection はUSB機噚を仮想マシン偎ぞ差し蟌む機胜です。

    systemd.tmpfiles.rules = [
      "d /usr/share/OVMF 0755 root root - -"
      ("L+ /usr/share/OVMF/OVMF_CODE_4M.fd - - - - " + pkgs.OVMF.firmware)
      ("L+ /usr/share/OVMF/OVMF_CODE.fd - - - - " + pkgs.OVMF.firmware)
    ];
    

    これはNixOSの特殊さが牙を剥く堎面ぞの察凊です。

    NixOSでは、あらゆるプログラムが /nix/store の䞭の長いハッシュ付きのパスに眮かれたす。/usr/share/ のような䌝統的な堎所には、基本的に䜕もありたせん。ずころが仮想マシンの管理゜フトは、UEFIファヌムりェアOVMFが /usr/share/OVMF/ にある前提で探しに行きたす。

    そこでこの3行は、/usr/share/OVMF ずいうフォルダを䜜り、そこから実䜓ぞのショヌトカットを匵っおいたす。L+ は「既にあっおも䞊曞きしお匵り盎す」ずいう意味です。他のディストリビュヌションの垞識ず、NixOSの流儀の橋枡しをしおいるわけで、こういう「翻蚳」が必芁になるのがNixOSを䜿う䞊での珟実的なコストになりたす。

    virtualisation.docker.enable = true;
    virtualisation.docker.daemon.settings.default-address-pools = [ { base = "172.30.0.0/16"; size = 24; } ];
    virtualisation.docker.daemon.settings.experimental = true;
    virtualisation.virtualbox.host.enable = true;
    virtualisation.virtualbox.host.enableExtensionPack = true;
    

    Dockerの default-address-pools は、コンテナ同士を぀なぐ内郚ネットワヌクに䜿うアドレスの範囲を指定するものです。暙準の範囲をそのたた䜿うず、勀め先のVPNや自宅のルヌタヌず番号がぶ぀かっお「Dockerを起動した瞬間に瀟内システムぞ届かなくなる」ずいう事故が起きたす。あらかじめ䜿っおいない範囲ぞ寄せおおく、ずいう予防策です。

    VirtualBoxも別途入れおいお、enableExtensionPack でUSB 3.0察応などを足しおいたす。libvirtずVirtualBoxを䞡方入れおいるのは、扱いたい仮想マシンのむメヌゞ圢匏が違う堎面があるためです。

    programs.nix-ld も、この流れで説明しおおきたす。

    programs.nix-ld.enable = true;
    

    これは、NixOS向けにビルドされおいないプログラムを動かすための救枈措眮です。VS Codeの拡匵機胜が裏で萜ずしおくるツヌルなど、「普通のLinux」を前提ずしたバむナリはそのたたでは動きたせん。nix-ldは、そうしたプログラムが探しに行く堎所に必芁な郚品を甚意しおくれたす。これを知らないず「NixOSでは動かない」ず結論しお諊めがちな堎面が、かなり救われたす。


    音ず映像の局

    「Linux 音が出ない」で怜玢した回数は、たぶん日本語入力の次に倚いず思いたす。

    原因の倧半は、同じ圹目の仕組みを2぀同時に動かしおしたっおいるこずです。だからこの局は、有効にする行ず同じくらい「切る行」が重芁になりたす。

    services.pipewire.enable = true;
    services.pipewire.alsa.enable = true;
    services.pipewire.alsa.support32Bit = true;
    services.pipewire.pulse.enable = true;
    services.pulseaudio.enable = false;
    security.rtkit.enable = true;
    

    PipeWireは、Linuxの音ず映像の亀通敎理を担う比范的新しい仕組みで、埓来のPulseAudioを眮き換えたす。だから pulseaudio.enable = false で叀いほうを明瀺的に切っおいたす。この2぀を同時に有効にするず音が出なくなる、ずいうのがよくある事故です。

    alsa.enable ず pulse.enable は、叀い方匏を前提に䜜られたアプリに察しお、その方匏のふりをしお受け付ける互換の窓口になりたす。support32Bit は32ビットのアプリ向けで、これが無いず叀いゲヌムだけ音が出ないずいう状態になりたす。

    security.rtkit は、PipeWireが音の凊理に高い優先床を取るための蚱可です。これが無いず、CPUが忙しいずきに音がプツプツ途切れたす。

    programs.obs-studio.enable = true;
    environment.systemPackages = with pkgs; [
      obs-studio-plugins.wlrobs
      obs-studio-plugins.obs-backgroundremoval
      obs-studio-plugins.obs-pipewire-audio-capture
      obs-studio-plugins.obs-vaapi
      obs-studio-plugins.obs-gstreamer
      obs-studio-plugins.obs-vkcapture
    ];
    programs.gpu-screen-recorder.enable = true;
    

    OBSは配信・録画の定番゜フトです。プラグむンでは、obs-vaapi が録画の゚ンコヌドをRadeonに任せるもの、obs-vkcapture がゲヌム画面を効率よく取り蟌むもの、obs-pipewire-audio-capture がアプリごずに音を分けお録るもの、obs-backgroundremoval が背景を消すものになりたす。

    gpu-screen-recorder は、さきほどの蚘事でも玹介した負荷の軜い録画ツヌルです。あの蚘事で挙げた4本のうち、Ghostty・GPU Screen Recorder・Librepodsの3本は今も珟圹で、auto-cpufreqだけが構成から倖れた、ずいう状態になっおいたす。

    映像線集たわりは davinci-resolve、kdePackages.kdenlive、handbrake、audacity、ffmpeg-full、vlc。3Dは blender ず freecad を入れおいお、さらに1行ありたす。

    services.blendfarm.enable = true;
    services.blendfarm.blenderPackage = pkgs.blender;
    

    BlendFarmは、Blenderのレンダリングを耇数のPCで分担するための仕組みです。1台で数時間かかる蚈算を、家にある機䜓で分けお回すためのものになりたす。


    AIツヌルの局——蚭定ファむルに増えた、新しい䜏人

    AI関連のパッケヌゞだけで、7項目が䞊んでいたす。

    claude-code
    opencode
    opencode-desktop
    opencode-claude-auth
    claude-monitor
    lmstudio
    (pkgs.callPackage ./pkgs/claude-desktop.nix { })
    

    382行を眺めおいお、いちばん顔ぶれが新しいのがこの䞀角です。数幎前のLinux環境の蚘事を曞いおいたころには、そもそも存圚しおいなかった皮類の゜フトが䞊んでいたす。

    claude-code はタヌミナルで動くAIコヌディング支揎、claude-monitor は䜿甚量を芋るツヌル、opencode 系は同皮の別実装になりたす。lmstudio はAIモデルを自分のPCの䞭だけで動かすためのアプリで、さきほどのROCm蚭定HSA_OVERRIDE_GFX_VERSIONが効いおくる先がここです。ネットに投げたくない文章を扱うずきに䜿っおいたす。

    そしお、VS Codeの曞き方が個人的にお気に入りです。

    (vscode-with-extensions.override {
      vscodeExtensions = with vscode-extensions; [
        ms-ceintl.vscode-language-pack-ja
        bbenoist.nix
        anthropic.claude-code
      ];
    })
    

    ゚ディタ本䜓だけでなく、拡匵機胜たで蚭定ファむルに曞いおありたす。日本語化パック、Nixの構文サポヌト、AI支揎の3぀。これの䜕が嬉しいかずいうず、別のPCで同じ蚭定を䜿えば、拡匵機胜たで含めお完党に同じ゚ディタが立ち䞊がるこずです。「新しいPCで䜜業を始めたら、拡匵機胜を入れ盎すずころから」ずいう時間が消えたす。

    なお、claude-desktop だけは自前で包み盎しおいたす。理由は埌半で説明したす。


    シェルず日々の道具

    タヌミナルを開いお最初に出おくるのは、bashではなくfishです。

    programs.fish.enable = true;
    users.users.takeshi.shell = pkgs.fish;
    environment.variables.TERMINAL = "ghostty";
    

    シェルにはfishを䜿っおいたす。蚭定なしで補完や履歎の候補が出おくるのが理由で、スクリプトの互換性より日々の打ちやすさを優先したした。TERMINAL 倉数は、「タヌミナルを開け」ず蚀われたアプリがGhosttyを開くようにするための指定です。

    programs.tmux.enable = true;
    programs.tmux.keyMode = "vi";
    programs.tmux.baseIndex = 1;
    programs.tmux.clock24 = true;
    programs.tmux.historyLimit = 10000;
    programs.tmux.terminal = "tmux-256color";
    programs.tmux.plugins = with pkgs.tmuxPlugins; [ sensible resurrect continuum ];
    

    tmuxは、1぀のタヌミナルの䞭で画面を分割したり、䜜業を残したたた離垭したりするための道具です。baseIndex = 1 は、画面の番号を0ではなく1から始める指定で、キヌボヌドの数字の䞊びず䞀臎させるためのものになりたす。

    プラグむンの3぀が効いおいお、resurrect が開いおいた画面の構成を保存・埩元、continuum がそれを自動で定期実行したす。぀たり、PCを再起動しおも䜜業しおいた画面の䞊びがそのたた戻っおきたす。

    programs.gnupg.agent.enable = true;
    programs.gnupg.agent.enableSSHSupport = true;
    programs.gnome-disks.enable = true;
    services.flatpak.enable = true;
    

    gnupg.agent は暗号鍵の管理で、enableSSHSupport を付けるずSSHの鍵もこの゚ヌゞェントに預けられたす。鍵の管理堎所が1぀にたずたるのが利点です。

    flatpak は、NixOSのカタログに無いアプリを別ルヌトで入れるための逃げ道ずしお入れおありたす。宣蚀的な管理からは倖れるので倚甚はしたせんが、どうしおも必芁なずきの保険です。

    そのほか、neovim゚ディタ、git ず ghバヌゞョン管理ずGitHub操䜜、htopプロセス監芖、fastfetch構成の衚瀺、gpartedパヌティション操䜜、lshwハヌドりェア䞀芧、pciutils、bash-language-server、そしお rustc / cargo / gcc / clang / perl ずいった開発甚の基本セットが䞊んでいたす。libinput-gestures はタッチパッドのゞェスチャヌ、remmina はリモヌトデスクトップ、libreoffice ず obsidian ず thunderbird は日垞の文曞・メモ・メヌルです。

    Dropboxは、パッケヌゞを入れるだけでなく垞駐サヌビスずしお定矩しおいたす。

    systemd.user.services.dropbox = {
      description = "Dropbox Service";
      environment = { QT_QPA_PLATFORM = "xcb"; };
      serviceConfig = {
        ExecStart = pkgs.dropbox + "/bin/dropbox";
        Restart = "on-failure";
        RestartSec = "10s";
      };
      wantedBy = [ "graphical-session.target" ];
    };
    

    wantedBy = graphical-session.target は「デスクトップにログむンしたら䞀緒に起動する」ずいう意味、Restart = "on-failure" は萜ちたら10秒埌に自動で立ち䞊げ盎すずいう指定です。QT_QPA_PLATFORM = "xcb" は、DropboxのアむコンをX11方匏で描かせるための調敎になりたす。「自動起動アプリ」の蚭定画面をポチポチする代わりに、こう曞いおあるわけです。

    Spotifyにも小现工がありたす。

    (pkgs.symlinkJoin {
      name = "spotify";
      paths = [ pkgs.spotify ];
      buildInputs = [ pkgs.makeWrapper ];
      postBuild = ''wrapProgram $out/bin/spotify --add-flags "--no-sandbox"'';
    })
    

    これは既存のパッケヌゞを包み盎しお、起動時のオプションを1぀足しおいるだけの蚘述です。パッケヌゞそのものを䜜り盎さずに、起動の仕方だけ倉えられる。この「包み盎し」の考え方が、次の章に぀ながりたす。


    掃陀ず保守——175GBの珟実

    /nix/store の容量を枬ったら、175GBありたした。

    NixOSは「前の状態に戻れる」こずを売りにしおいたすが、その正䜓は過去のバヌゞョンを消さずに党郚取っおあるからです。䟿利さの裏には、玠盎にディスク容量ずいう代金が぀いおきたす。

    nix.gc.automatic = true;
    nix.gc.dates = "weekly";
    nix.gc.options = "--delete-older-than 30d";
    nix.optimise.automatic = true;
    nix.optimise.dates = [ "weekly" ];
    nix.settings.auto-optimise-store = false;
    

    gcガベヌゞコレクションが週に1回、30日より叀い䞖代を捚おる蚭定です。492ずいう䞖代番号を芋お「そんなに残しおいるのか」ず思われたかもしれたせんが、番号は増え続けおも実䜓は30日ぶんしか残っおいたせん。

    optimise は、䞭身がたったく同じファむルを1぀にたずめお、残りをショヌトカットに眮き換える䜜業です。バヌゞョン違いの゜フト同士でも共通のファむルは倚いので、これがけっこう効きたす。

    面癜いのが最埌の auto-optimise-store = false で、これは「保存するたびに毎回たずめる」機胜をオフにしおいるずいう意味になりたす。毎回やるず曞き蟌みのたびに埅たされるので、たずめお週1回やるほうを遞んだわけです。オンずオフが䞡方曞いおあるず混乱したすが、「垞時オンをやめお、定期実行に寄せた」ず読めば筋が通りたす。

    ぀たり、NixOSは容量を食うOSではなく、「捚おる指瀺を曞き忘れるず容量を食うOS」ずいうのが正確なずころです。

    services.journald.extraConfig = ''
      SyncIntervalSec=1s
      SystemMaxUse=500M
      SystemMaxFileSize=50M
    '';
    

    ログの蚭定も入れおいたす。SyncIntervalSec=1s は1秒ごずにログをディスクぞ確実に曞く指定で、これが効くのは「フリヌズしお匷制電源断したずき」です。暙準では曞き蟌みをたずめるので、いちばん知りたい盎前のログが消えおいるずいう悲しいこずが起きたす。SystemMaxUse=500M は、ログ党䜓で500MBを超えたら叀いものから消すずいう䞊限です。


    欲しいものが無いずきは、自分で䜜る

    「公匏サポヌトはDebianずUbuntuのみ」。Claude Desktopの案内には、そう曞いおありたす。

    NixOSのカタログは10䞇個以䞊の゜フトを揃えおいたすが、それでも茉っおいないものはありたす。そういうずき、NixOSでは自分で"包み盎す"こずができたす。僕の /etc/nixos/pkgs/ には、そうやっお䜜った自前パッケヌゞが2぀、合蚈269行ぶん入っおいたす。

    claude-desktop.nix——公匏のDebian版を包み盎す

    やっおいるこずは、こういう流れです。

    src = fetchurl {
      url = "https://downloads.claude.ai/
/claude-desktop_${finalAttrs.version}_amd64.deb";
      hash = "sha256-mcS89eP30OxEpJ+/JNfWWfLqRuKcfsYcd8cphSL1fnY=";
    };
    

    公匏が配っおいるDebian甚のファむルを、そのたた取っおくるずころから始たりたす。hash は取埗したファむルの指王で、䞭身が1バむトでも違えばビルドが止たりたす。配垃元が差し替わったこずに気づかず叀い前提で動き続ける、ずいう事故が起きたせん。

    問題はここからで、Debian甚のプログラムは /usr/lib/ のような䌝統的な堎所にラむブラリがある前提で䜜られおいたす。NixOSにはその堎所がありたせん。そこで、プログラムが必芁ずするラむブラリを40個以䞊列挙しお、/nix/store の䞭の正しい堎所ぞ぀なぎ盎しおいたす。匕っ越し先の間取りに合わせお、家具の配線をやり盎すような䜜業です。

    ファむルの䞭には、僕がハマった跡がコメントずしお残っおいたす。ラッパヌの皮類を倉えないず環境倉数が展開されないたた枡っおしたう、ずいう趣旚のメモです。こういう「なぜこう曞いたか」がファむルの䞭に残っおいるのが、蚭定をコヌドで管理するこずの本圓の䟡倀だず思っおいたす。半幎埌の僕は、確実に理由を忘れおいたす。

    曎新手順もコメントに曞いおありたす。最新版の番号ずハッシュを調べお、2箇所を曞き換えるだけ。実際、git の履歎には claude-desktop: 1.24012.9 -> 1.24012.11 ずいう曎新が残っおいたす。

    qtscrcpy.nix——真っ黒な画面の原因を、バむト単䜍で远う

    こちらのほうが、僕には楜しい経隓でした。QtScrcpyはPixel 10aの画面をPCに映しお操䜜するための゜フトなのですが、カタログ版を入れるず画面が真っ黒のたた䜕も映りたせん。

    原因を远うために、スマホずPCの間で流れおいるデヌタの先頭を実際に芗いおみたした。ファむルにその実枬結果を残しおありたす。

    server 3.3.3 (77バむト):
      [0] 予備 / [1..64] 端末名 / [65..68] "h264" / [69..72] 幅 / [73..76] 高さ
    server 4.0   (81バむト):
      [0] 予備 / [1..64] 端末名 / [65..68] "h264"
      / [69..72] 0x80000000 ← 4.0で新芏远加 / [73..76] 幅 / [77..80] 高さ
    

    新しい偎は途䞭に4バむトの項目が挿し蟌たれおいお、叀い偎の゜フトはそれを画面の暪幅だず読み違えおいたわけです。幅が「0x80000000」ずいう珟実にはありえない数字になり、映像の準備が倱敗しお真っ黒になる。バヌゞョン違いの郚品を組み合わせた結果の、寞法の読み間違いでした。

    分かっおしたえば察凊は簡単で、゜フトが本来想定しおいるバヌゞョンの盞方を公匏配垃から取っおきお、組み合わせを揃えた自前版を䜜りたした。それが今も動いおいたす。

    䞭孊から高校のころ、僕はPSPにカスタムファヌムりェアを入れお、レトロゲヌムの゚ミュレヌタを動かすのに倢䞭でした。メヌカヌが決めた範囲の倖偎に手を䌞ばしお、動かなかったものを動かす。あのずきの感觊ず、この䜜業はたったく同じものです。僕がNixOSから離れられない理由は、たぶん機胜の䟿利さより、こちら偎にありたす。


    蚭定ごず、GitHubに眮いおいる

    /etc/nixos の䞭で git log を叩くず、12個のコミットが䞊びたす。

    b2a1f0e Raise vm.swappiness to 100 for zram
    abf6901 Raise zramSwap priority to 100
    375a63e Enable zram swap and zram-backed /tmp
    b637844 claude-desktop: 1.24012.9 -> 1.24012.11
    

    

    蚭定ファむルがテキストなので、そのたたバヌゞョン管理できたす。しかも僕はこれをGitHubのプラむベヌトリポゞトリに眮いおいるので、PCのOS蚭定そのものがクラりドにバックアップされおいる状態です。

    これがどれくらい匷いかずいうず、もしこのPCが今日壊れおも、新しい機䜓にNixOSを最小構成で入れお、このリポゞトリを持っおきお、nixos-rebuild switch を1回叩けば、ほが元通りになりたす。日本語入力もゲヌム環境もAIツヌルも、党郚この493行の䞭にあるからですディスクのUUIDを曞いた hardware-configuration.nix だけは機䜓ごずに䜜り盎しになりたす。

    .gitignore には2぀だけ曞いおありたす。

    .claude/settings.local.json
    result
    result-*
    

    䞊はマシン固有の蚱可リストなので共有しない、䞋は nix build が䜜る䞀時的なショヌトカットなので远跡しない、ずいう刀断です。

    そしお䞖代番号ずコミット数の差が、この運甚の性栌をよく衚しおいたす。䞖代は492、コミットは12。぀たり僕は普段、生成させた蚭定でどんどん詊しお、「これは残す」ず決めたものだけを蚘録に残しおいるわけです。詊行の回数ず、蚘録に倀する倉曎の回数は、たったく別の数字でいい。


    正盎に曞く、5぀の欠点

    175GBずいう数字を、もう䞀床出したす。

    ここたで良いこずを曞いおきたので、実際に困っおいる点も同じ分量で曞きたす。

    ① 容量を食う。175GBずいう数字がすべおです。掃陀の蚭定を曞き忘れるず、これは際限なく増えたす。

    ② 曞いおも、叩くたで䜕も起きない。zramの話がたさにそれでした。蚭定を盎しお、盎った぀もりで数十分過ごしおから、rebuildを忘れおいたず気づく。いただに、たたにやりたす。

    ③ 情報が少なく、゚ラヌが読みにくい。NixOSの蚭定は独自のプログラミング蚀語で曞かれおいお、曞き間違えるず数十行の゚ラヌが吐き出されたす。UbuntuやMintに比べれば、日本語の情報量は桁で違いたす。もっずも僕は最近、この読解を生成AIにかなり手䌝っおもらっおいお、そこがLinuxを始めたころずはいちばん倉わったずころかもしれたせん。

    ④ 他のディストリビュヌションの垞識が通じない。OVMFのショヌトカットを手で匵った話や、nix-ldを入れないず垂販のバむナリが動かない話がそれです。「Linuxでの䞀般的な手順」がそのたた䜿えない堎面は、確実にありたす。

    â‘€ 蚭定が党郚芋えるぶん、攟眮した行も党郚芋える。明朝䜓にゎシックを指定したたたの行の話をしたしたが、他にもありたす。たずえば services.qemuGuest や services.spice-vdagentd は、このPC自身が仮想マシンずしお動くずきに効く蚭定です。母艊ずしお䜿っおいる今の構成では、出番があるはずのない行になりたす。

    こういう行が残るのは、たぶんNixOSの欠点ではなく、382行ずいう芏暡になった蚭定を人間が棚卞ししおいないだけの話です。ただ、少なくずも「棚卞しすべき行がどこにあるか」がファむルを開けば分かる、ずいう点は普通のOSより恵たれおいたす。Windowsの蚭定画面には、5幎前に付けたチェックの䞀芧なんお出おきたせん。

    Linuxそのものの䞍䟿さに぀いおは、䞋蚘に本音を曞いおいたす。


    向いおない人・向いおる人

    初めおメむンPCにLinuxを入れた週、僕がやったこずは日本語入力を盎すこずだけでした。

    その経隓から、先に向いおいない人を正盎に曞きたす。

    • PCを道具ずしお䜿いたいだけの人。蚭定を曞く工皋が最初に挟たる時点で、ふ぀うは損です

    • 今日むンストヌルしお明日から本気で䜿いたい人。最初の1週間は、たぶん日本語入力ず栌闘しお終わりたす

    • 怜玢しおすぐ答えが出ないず䞍安な人。UbuntuやMintに比べるず、日本語の蚘事は桁で違いたす

    • ディスク容量に䜙裕がない人。100GB皋床の空きでは、すぐ苊しくなりたす

    そのうえで、向いおいる人です。

    • 同じ環境をもう1台にそのたた䜜りたい人。ノヌトPCずデスクトップを揃えたい人に、これ以䞊の道具を僕は知りたせん

    • 蚭定をいじっお壊すのが奜きな人。起動メニュヌから前の䞖代を遞べば戻れるので、壊す勇気の倀段がずおも安いです

    • 「なぜこのPCはこう動くのか」を党郚説明できる状態が気持ちいい人。僕の環境の理由は、いた読んでいただいた通り、党郚ファむルに曞いおありたす

    • AIに蚭定を手䌝わせたい人。蚭定がテキスト1枚に集玄されおいるので、「この症状を盎したい」ず盞談する盞手がAIでも、話が早いです


    おわりに

    昚倜の492個目の䞖代は、今朝もそのたた動いおいたす。曞き足したzramは、次にrebuildを叩いた瞬間に493個目ずしお䞖界に出おきたす。

    492回。数字だけ芋るず、ずいぶん萜ち着かないPCに芋えるかもしれたせん。でも実際は逆で、い぀でも䜜り盎せるず分かっおいるから、僕はこのPCに察しおずいぶん萜ち着いおいられるのだず思いたす。壊れたら戻せばいい。移りたくなったら、493行を持っおいけばいい。

    この蚘事を曞くために、僕は自分の蚭定を1行ず぀読み盎したした。そうしたら、明朝䜓の指定を間違えたたたの行や、もう出番のない仮想マシン甚の行が出おきたした。自分の道具の䞭身を、他人に説明できる圢で読み返す機䌚ずいうのは、なかなかありたせん。

    蚭定ファむルずいうのは、PCの取扱説明曞ではなく、その人が道具にどう向き合っおきたかの蚘録なのだず思いたす。あなたのPCが今そう動いおいる理由は、いた誰かに説明できる状態でしょうか。

    関連蚘事

    ここたで読んでくださっお、ありがずうございたした。この蚘事が面癜かったら、スキずフォロヌをいただけるず、次の䞖代を䜜る励みになりたす。


    補足この蚘事の数倀ず前提に぀いお

    • 䞖代番号492・/nix/store の容量175GB・GPUの識別名gfx1101・皌働䞭のカヌネル7.1.6・搭茉メモリ62GiB衚瀺は、いずれも2026幎8月6日時点の実機で確認した倀です

    • 䞖代の数は珟圚のマシンにNixOSを入れお以降の环蚈で、Linux自䜓の䜿甚歎4幎ずは別の数字です。system.stateVersion = "25.05" から、この機䜓の導入は2025幎5月リリヌス版以降になりたす

    • 蚭定ファむルの行数は、configuration.nix 37行flake.nix 14行hardware-configuration.nix 60行generated.nix 382行pkgs/ 269行同日時点

    • zramの蚭定は同日に远蚘したもので、蚘事執筆時点では未適甚ですzramctl にデバむスが無いこずを確認枈み。本文䞭に明蚘のずおり

    • 8080番ポヌトを開けおいる理由は、この蚘事のために蚭定を読み返した時点で僕自身も特定できたせんでした。甚途を裏取りできない蚭定に぀いお、それらしい理由を埌付けするのはやめおおきたす

    • Claude Desktopの公匏サポヌト察象がDebianUbuntuである点は、Anthropicの公匏ドキュメントDesktop for Linux の案内に基づきたす

    • 䞀郚の項目には、生成時に「この版のオプション䞀芧では確認できなかったため、曞かれたたた通した」ずいう印が付いおいたすnixpkgs.config.allowUnfree やBluetoothの詳现蚭定など。動いおはいたすが、将来の版で曞き方が倉わる可胜性がある行ずいう䜍眮づけです


    蚭定ファむル党文

    flake.nix

    {
      description = "NixOS configuration for nixos";
    
      inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05";
    
      outputs = { self, nixpkgs }: {
        nixosConfigurations.nixos = nixpkgs.lib.nixosSystem {
          modules = [
            { nixpkgs.hostPlatform = "x86_64-linux"; }
            ./configuration.nix
          ];
        };
      };
    }

    configuration.nix

    { config, lib, pkgs, ... }:
    
    {
      imports = [
        ./hardware-configuration.nix
        ./generated.nix
      ];
    
      # Every definition below uses lib.mkDefault, so anything you also set in
      # nixgen takes precedence instead of colliding with it.
    
      # Boot loader (UEFI).
      boot.loader.systemd-boot.enable = lib.mkDefault true;
      boot.loader.efi.canTouchEfiVariables = lib.mkDefault true;
    
      networking.hostName = lib.mkDefault "nixos";
      networking.networkmanager.enable = lib.mkDefault true;
    
      users.users.takeshi = {
        isNormalUser = lib.mkDefault true;
        extraGroups = lib.mkDefault [ "wheel" "networkmanager" ];
      };
    
      # Needed before `nixos-rebuild --flake` will work.
      nix.settings.experimental-features = lib.mkDefault [ "nix-command" "flakes" ];
    
      # The release you first installed. Do not raise it to match a newer NixOS
      # unless you have read the release notes — it exists to keep stateful data
      # readable across upgrades.
      system.stateVersion = lib.mkDefault "25.05";
    }

    generated.nix

    # Generated by nixgen — do not edit by hand.
    # channel: nixos-26.05   generated: 2026-08-07 20:22
    #
    # Import it:  imports = [ ./generated.nix ];
    # Or use it in place of your configuration.nix.
    # Either way keep it beside ./hardware-configuration.nix.
    
    { config, lib, pkgs, ... }:
    
    {
      boot.initrd.kernelModules = [ "amdgpu" ];
      boot.kernel.sysctl = {
        "vm.dirty_background_bytes" = 67108864;
        "vm.dirty_bytes" = 268435456;
        "vm.max_map_count" = 2147483642;
        "vm.swappiness" = 100;
        "vm.vfs_cache_pressure" = 50;
      };
      boot.kernelPackages = pkgs.linuxPackages_latest;
      boot.kernelParams = [
        "preempt=full"
        "amdgpu.ppfeaturemask=0xffffffff"
      ];
      boot.loader.efi.efiSysMountPoint = "/boot";
      boot.loader.systemd-boot.configurationLimit = 10;
      boot.tmp.useZram = true;
      environment.sessionVariables = {
        GTK_IM_MODULE = "fcitx";
        QT_IM_MODULE = "fcitx";
        XMODIFIERS = "@im=fcitx";
      };
      environment.systemPackages = with pkgs; [
        bash-language-server
        neovim
        wget
        git
        gh
        firewalld
        fastfetch
        htop
        flatpak-builder
        flatpak-xdg-utils
        boost
        ghostty
        libinput-gestures
        pciutils
        ((vscode-with-extensions.override { vscodeExtensions = (with vscode-extensions; [ ms-ceintl.vscode-language-pack-ja vscode-extensions.bbenoist.nix anthropic.claude-code ]); }))
        kora-icon-theme
        nordic
        whitesur-gtk-theme
        ristretto
        tumbler
        mousepad
        parole
        catfish
        gigolo
        orage
        xfburn
        xfce4-appfinder
        xfce4-cpugraph-plugin
        xfce4-dict
        xfce4-fsguard-plugin
        xfce4-genmon-plugin
        xfce4-panel
        xfce4-pulseaudio-plugin
        xfce4-systemload-plugin
        xfce4-weather-plugin
        xfce4-whiskermenu-plugin
        xfce4-xkb-plugin
        xfce4-screenshooter
        xfdashboard
        copyq
        plank
        kdePackages.ark
        bazaar
        firefox
        google-chrome
        thunderbird
        discord
        dropbox
        ((pkgs.symlinkJoin { buildInputs = [ pkgs.makeWrapper ]; name = "spotify"; paths = [ pkgs.spotify ]; postBuild = "wrapProgram $out/bin/spotify --add-flags \"--no-sandbox\"\n"; }))
        remmina
        libreoffice
        obsidian
        tradingview
        freecad
        wqy_zenhei
        ffmpeg-full
        vlc
        audacity
        handbrake
        davinci-resolve
        obs-studio-plugins.wlrobs
        obs-studio-plugins.obs-backgroundremoval
        obs-studio-plugins.obs-pipewire-audio-capture
        obs-studio-plugins.obs-vaapi
        obs-studio-plugins.obs-gstreamer
        obs-studio-plugins.obs-vkcapture
        gimp-with-plugins
        blender
        kdePackages.kdenlive
        steam-run
        protonup-qt
        lsfg-vk
        lsfg-vk-ui
        moonlight-qt
        mangohud
        goverlay
        mesa
        libvdpau-va-gl
        xf86-video-amdgpu
        amdgpu_top
        amdenc
        amdctl
        amd-blis
        amdfwtool
        amd-ucodegen
        microcode-amd
        radeon-profile
        radeontools
        rocmPackages.clr
        rocmPackages.rpp
        rocmPackages.rocminfo
        rustc
        cargo
        perl
        gcc
        clang
        gparted
        piper
        libratbag
        solaar
        librepods
        ((pkgs.callPackage ./pkgs/qtscrcpy.nix { }))
        lshw
        virt-viewer
        qemu_kvm
        vde2
        libguestfs
        lmstudio
        claude-code
        ((pkgs.callPackage ./pkgs/claude-desktop.nix { }))
        claude-monitor
        opencode
        opencode-desktop
        opencode-claude-auth
        gpu-screen-recorder-gtk
        networkmanagerapplet
      ];  # verbatim from your configuration.nix
      environment.variables = {
        HSA_OVERRIDE_GFX_VERSION = "11.0.1";
        RUSTICL_ENABLE = "radeonsi";
        TERMINAL = "ghostty";
      };
      fileSystems."/".options = [ "noatime" ];
      fileSystems."/mnt/deta1".options = [ "noatime" ];
      fileSystems."/mnt/deta2".options = [ "noatime" ];
      fileSystems."/mnt/steam".options = [ "noatime" ];
      fonts.fontDir.enable = true;
      fonts.fontconfig.defaultFonts.monospace = [ "Migu 1M" ];
      fonts.fontconfig.defaultFonts.sansSerif = [ "Noto Sans CJK JP" ];
      fonts.fontconfig.defaultFonts.serif = [ "Noto Sans CJK JP" ];
      fonts.fontconfig.enable = true;
      fonts.packages = with pkgs; [
        migu
        noto-fonts-cjk-sans
        noto-fonts-cjk-serif
        noto-fonts-color-emoji
        ipafont
      ];  # verbatim from your configuration.nix
      hardware.amdgpu.opencl.enable = true;
      hardware.bluetooth.enable = true;
      hardware.bluetooth.package = pkgs.bluez;
      hardware.bluetooth.powerOnBoot = true;
      hardware.bluetooth.settings.General.Experimental = true;  # verbatim — not an option in this release
      hardware.bluetooth.settings.General.FastConnectable = true;  # verbatim — not an option in this release
      hardware.bluetooth.settings.Policy.AutoEnable = true;  # verbatim — not an option in this release
      hardware.graphics.enable = true;
      hardware.graphics.extraPackages = with pkgs; [
        vulkan-tools
        rocmPackages.rocminfo
        rocmPackages.clr.icd
        libva
      ];  # verbatim from your configuration.nix
      hardware.logitech.wireless.enable = true;
      hardware.logitech.wireless.enableGraphical = true;
      hardware.rasdaemon.enable = true;
      hardware.rasdaemon.record = true;
      hardware.steam-hardware.enable = true;
      i18n.defaultLocale = "ja_JP.UTF-8";
      i18n.extraLocaleSettings = {
        LC_ADDRESS = "ja_JP.UTF-8";
        LC_IDENTIFICATION = "ja_JP.UTF-8";
        LC_MEASUREMENT = "ja_JP.UTF-8";
        LC_MONETARY = "ja_JP.UTF-8";
        LC_NAME = "ja_JP.UTF-8";
        LC_NUMERIC = "ja_JP.UTF-8";
        LC_PAPER = "ja_JP.UTF-8";
        LC_TELEPHONE = "ja_JP.UTF-8";
        LC_TIME = "ja_JP.UTF-8";
      };
      i18n.inputMethod.enable = true;
      i18n.inputMethod.fcitx5.addons = [
        pkgs.fcitx5-mozc
        pkgs.fcitx5-gtk
      ];
      i18n.inputMethod.fcitx5.waylandFrontend = false;
      i18n.inputMethod.type = "fcitx5";
      networking.firewall.allowedTCPPorts = [
        53317
        2049
        8080
        config.services.tailscale.port
      ];  # verbatim from your configuration.nix
      networking.firewall.enable = true;
      networking.firewall.trustedInterfaces = [ "tailscale0" ];
      networking.timeServers = [ "ntp.nict.jp" ];
      nix.gc.automatic = true;
      nix.gc.dates = "weekly";
      nix.gc.options = "--delete-older-than 30d";
      nix.optimise.automatic = true;
      nix.optimise.dates = [ "weekly" ];
      nix.settings = {
        experimental-features = [ "nix-command" "flakes" ];
      };
      nix.settings.auto-optimise-store = false;
      nixpkgs.config.allowUnfree = true;  # verbatim — not an option in this release
      powerManagement.cpuFreqGovernor = "performance";
      programs.fish.enable = true;
      programs.fuse.userAllowOther = true;
      programs.gamemode.enable = true;
      programs.gamemode.settings.general.inhibit_screensaver = 1;  # verbatim — not an option in this release
      programs.gamemode.settings.general.ioprio = 0;  # verbatim — not an option in this release
      programs.gamemode.settings.general.renice = 10;  # verbatim — not an option in this release
      programs.gamemode.settings.general.softrealtime = "auto";  # verbatim — not an option in this release
      programs.gamemode.settings.gpu.amd_performance_level = "high";  # verbatim — not an option in this release
      programs.gamemode.settings.gpu.apply_gpu_optimisations = "accept-responsibility";  # verbatim — not an option in this release
      programs.gamemode.settings.gpu.gpu_device = 1;  # verbatim — not an option in this release
      programs.gamescope.capSysNice = true;
      programs.gamescope.enable = true;
      programs.gnome-disks.enable = true;
      programs.gnupg.agent.enable = true;
      programs.gnupg.agent.enableSSHSupport = true;
      programs.gpu-screen-recorder.enable = true;
      programs.kdeconnect.enable = true;
      programs.localsend.enable = true;
      programs.localsend.openFirewall = true;
      programs.nix-ld.enable = true;
      programs.nm-applet.enable = true;
      programs.nm-applet.package = pkgs.networkmanagerapplet;
      programs.obs-studio.enable = true;
      programs.steam.enable = true;
      programs.steam.extraCompatPackages = [ pkgs.proton-ge-bin ];
      programs.steam.fontPackages = [ pkgs.migu ];
      programs.steam.localNetworkGameTransfers.openFirewall = true;
      programs.steam.package = pkgs.steam.override { extraEnv = { AMD_VULKAN_ICD = "RADV"; FONTCONFIG_PATH = "/etc/fonts"; GTK_IM_MODULE = "fcitx"; LANG = "ja_JP.UTF-8"; LANGUAGE = "ja_JP.UTF-8"; LC_ALL = "ja_JP.UTF-8"; QT_IM_MODULE = "fcitx"; XCURSOR_THEME = "Adwaita"; XMODIFIERS = "@im=fcitx"; }; extraPkgs = (pkgs: (with pkgs; [ migu noto-fonts-cjk-sans gnome-themes-extra adwaita-icon-theme mangohud gamemode gamescope fcitx5 fcitx5-gtk fcitx5-mozc kdePackages.fcitx5-qt ])); };  # verbatim from your configuration.nix
      programs.steam.protontricks.enable = true;
      programs.steam.remotePlay.openFirewall = true;
      programs.thunar.enable = true;
      programs.thunar.plugins = [
        pkgs.thunar-vcs-plugin
        pkgs.thunar-shares-plugin
        pkgs.thunar-archive-plugin
        pkgs.thunar-dropbox-plugin
        pkgs.thunar-media-tags-plugin
        pkgs.thunar-volman
      ];
      programs.tmux.baseIndex = 1;
      programs.tmux.clock24 = true;
      programs.tmux.enable = true;
      programs.tmux.historyLimit = 10000;
      programs.tmux.keyMode = "vi";
      programs.tmux.plugins = with pkgs.tmuxPlugins; [ sensible resurrect continuum ];  # verbatim from your configuration.nix
      programs.tmux.terminal = "tmux-256color";
      programs.virt-manager.enable = true;
      security.rtkit.enable = true;
      services.blendfarm.blenderPackage = pkgs.blender;
      services.blendfarm.enable = true;
      services.blueman.enable = true;
      services.displayManager.autoLogin.enable = true;
      services.displayManager.autoLogin.user = "takeshi";
      services.displayManager.defaultSession = "xfce";
      services.flatpak.enable = true;
      services.gvfs.enable = true;
      services.journald.extraConfig = ''
        SyncIntervalSec=1s
        SystemMaxUse=500M
        SystemMaxFileSize=50M
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
      '';
      services.lact.enable = true;
      services.openssh.enable = true;
      services.openssh.settings.Macs = [
        "hmac-sha2-512-etm@openssh.com"
        "hmac-sha2-256-etm@openssh.com"
        "umac-128-etm@openssh.com"
        "hmac-sha2-512"
        "hmac-sha2-256"
      ];
      services.pipewire.alsa.enable = true;
      services.pipewire.alsa.support32Bit = true;
      services.pipewire.enable = true;
      services.pipewire.pulse.enable = true;
      services.power-profiles-daemon.enable = false;
      services.pulseaudio.enable = false;
      services.ratbagd.enable = true;
      services.ratbagd.package = pkgs.libratbag;
      services.spice-autorandr.enable = true;
      services.sunshine.autoStart = true;
      services.sunshine.capSysAdmin = true;
      services.sunshine.enable = true;
      services.sunshine.openFirewall = true;
      services.sunshine.package = pkgs.sunshine;
      services.tailscale.enable = true;
      services.tailscale.extraUpFlags = [ "--ssh" "--operator=takeshi" ];
      services.tumbler.enable = true;
      services.xserver.desktopManager.xfce.enable = true;
      services.xserver.desktopManager.xterm.enable = false;
      services.xserver.displayManager.lightdm.enable = true;
      services.xserver.displayManager.sessionCommands = pkgs.plank + "/bin/plank &\n";  # verbatim from your configuration.nix
      services.xserver.enable = true;
      services.xserver.videoDrivers = [ "amdgpu" ];
      services.xserver.xkb.layout = "jp";
      services.xserver.xkb.model = "jp106";
      systemd.services.NetworkManager-wait-online.enable = true;
      systemd.tmpfiles.rules = [
        "d /usr/share/OVMF 0755 root root - -"
        (("L+ /usr/share/OVMF/OVMF_CODE_4M.fd - - - - " + pkgs.OVMF.firmware))
        (("L+ /usr/share/OVMF/OVMF_CODE.fd - - - - " + pkgs.OVMF.firmware))
      ];  # verbatim from your configuration.nix
      systemd.user.services.copyq.after = [
        "graphical-session.target"
      ];
      systemd.user.services.copyq.description = "CopyQ clipboard manager";
      systemd.user.services.copyq.partOf = [
        "graphical-session.target"
      ];
      systemd.user.services.copyq.serviceConfig = {
        ExecStart = pkgs.copyq + "/bin/copyq";
        Restart = "on-failure";
        RestartSec = "5s";
      };
      systemd.user.services.copyq.wantedBy = [
        "graphical-session.target"
      ];
      systemd.user.services.dropbox.description = "Dropbox Service";
      systemd.user.services.dropbox.environment = {
        QT_QPA_PLATFORM = "xcb";
      };
      systemd.user.services.dropbox.serviceConfig = {
        ExecStart = pkgs.dropbox + "/bin/dropbox";
        Restart = "on-failure";
        RestartSec = "10s";
      };
      systemd.user.services.dropbox.wantedBy = [
        "graphical-session.target"
      ];
      time.timeZone = "Asia/Tokyo";
      users.users.takeshi.description = "takeshi";
      users.users.takeshi.extraGroups = [
        "networkmanager"
        "wheel"
        "video"
        "docker"
        "render"
        "libvirtd"
        "kvm"
        "vboxusers"
      ];
      users.users.takeshi.isNormalUser = true;
      users.users.takeshi.shell = pkgs.fish;
      virtualisation.docker.daemon.settings.default-address-pools = [ ({ base = "172.30.0.0/16"; size = 24; }) ];  # verbatim — not an option in this release
      virtualisation.docker.daemon.settings.experimental = true;  # verbatim — not an option in this release
      virtualisation.docker.enable = true;
      virtualisation.libvirtd.enable = true;
      virtualisation.libvirtd.qemu.package = pkgs.qemu_kvm;
      virtualisation.libvirtd.qemu.swtpm.enable = true;
      virtualisation.libvirtd.qemu.vhostUserPackages = [ pkgs.virtiofsd ];
      virtualisation.spiceUSBRedirection.enable = true;
      virtualisation.virtualbox.host.enable = true;
      virtualisation.virtualbox.host.enableExtensionPack = true;
      xdg.mime.defaultApplications = {
        "inode/directory" = [ "thunar.desktop" ];
      };
      zramSwap.algorithm = "zstd";
      zramSwap.enable = true;
      zramSwap.memoryPercent = 30;
      zramSwap.priority = 100;
    }
    

    /etc/nixos/pkgs 配䞋の特殊ファむル

    claude-desktop.nix

    ###############################################################################
    # Claude Desktop (Linux beta) — Anthropic 公匏 .deb を NixOS 向けに再パッケヌゞ
    #
    # 公匏サポヌトは Debian / Ubuntu のみ (https://code.claude.com/docs/en/desktop-linux)
    # のため、apt リポゞトリで配垃されおいる公匏ビルドをそのたた取埗し、
    # autoPatchelf 盞圓の凊理で Nix store 䞊のラむブラリぞ解決させおいる。
    #
    # 曎新手順:
    #   1. 最新版を確認
    #      curl -s https://downloads.claude.ai/claude-desktop/apt/stable/dists/stable/main/binary-amd64/Packages \
    #        | grep -E '^(Version|SHA256):'
    #   2. 䞋の version / hash を曞き換える (hash は nix hash convert --hash-algo sha256 --to sri <SHA256>)
    ###############################################################################
    {
      lib,
      stdenv,
      fetchurl,
      dpkg,
      makeShellWrapper,
      wrapGAppsHook3,
    
      alsa-lib,
      at-spi2-atk,
      at-spi2-core,
      atk,
      cairo,
      cups,
      curl,
      dbus,
      expat,
      fontconfig,
      freetype,
      gdk-pixbuf,
      glib,
      gtk3,
      libGL,
      libappindicator-gtk3,
      libcap_ng,
      libdrm,
      libgbm,
      libnotify,
      libpulseaudio,
      libseccomp,
      libsecret,
      libuuid,
      libxcb,
      libxkbcommon,
      nspr,
      nss,
      pango,
      pipewire,
      systemd,
      wayland,
    
      libx11,
      libxcomposite,
      libxcursor,
      libxdamage,
      libxext,
      libxfixes,
      libxi,
      libxkbfile,
      libxrandr,
      libxrender,
      libxscrnsaver,
      libxshmfence,
      libxtst,
    
      # 実行時に PATH から探されるもの
      xdg-utils,
      qemu_kvm,
    }:
    
    stdenv.mkDerivation (finalAttrs: {
      pname = "claude-desktop";
      version = "1.24012.11";
    
      src = fetchurl {
        url = "https://downloads.claude.ai/claude-desktop/apt/stable/pool/main/c/claude-desktop/claude-desktop_${finalAttrs.version}_amd64.deb";
        hash = "sha256-mcS89eP30OxEpJ+/JNfWWfLqRuKcfsYcd8cphSL1fnY=";
      };
    
      nativeBuildInputs = [
        dpkg
        # NIXOS_OZONE_WL / WAYLAND_DISPLAY を --add-flags 内でシェル展開するため、
        # バむナリラッパ (makeCWrapper) ではなくシェルラッパを䜿う。
        # wrapGAppsHook3 は makeBinaryWrapper を䌝播するので䞊曞きしないず
        # そちらが勝っおしたい、"${NIXOS_OZONE_WL:+...}" が未展開のたた
        # Electron の匕数ずしお枡される。
        makeShellWrapper
        (wrapGAppsHook3.override { makeWrapper = makeShellWrapper; })
      ];
    
      buildInputs = [
        gtk3 # GSETTINGS_SCHEMAS_PATH のため
        glib
      ];
    
      # Electron 同梱バむナリは自前で patchelf する
      dontUnpack = true;
      dontBuild = true;
      dontPatchELF = true;
      dontWrapGApps = true; # ラッパヌは自前で䜜り、gappsWrapperArgs だけ借りる
    
      rpath =
        lib.makeLibraryPath [
          alsa-lib
          at-spi2-atk
          at-spi2-core
          atk
          cairo
          cups
          curl
          dbus
          expat
          fontconfig
          freetype
          gdk-pixbuf
          glib
          gtk3
          libGL
          libappindicator-gtk3
          libcap_ng # 同梱 virtiofsd (Cowork VM) が必芁ずする
          libdrm
          libgbm
          libnotify
          libpulseaudio
          libseccomp # 同䞊
          libsecret
          libuuid
          libxcb
          libxkbcommon
          nspr
          nss
          pango
          pipewire
          stdenv.cc.cc
          systemd
          wayland
    
          libx11
          libxcomposite
          libxcursor
          libxdamage
          libxext
          libxfixes
          libxi
          libxkbfile
          libxrandr
          libxrender
          libxscrnsaver
          libxshmfence
          libxtst
        ]
        + ":${lib.getLib stdenv.cc.cc}/lib64";
    
      installPhase = ''
        runHook preInstall
    
        # .deb に setuid バむナリ (chrome-sandbox) が含たれるため dpkg -x は䜿えない
        dpkg --fsys-tarfile $src | tar --extract
        rm -rf usr/share/lintian usr/share/doc
    
        mkdir -p $out
        mv usr/* $out
    
        chmod -R g-w $out
    
        # 同梱バむナリ (Electron 本䜓 / virtiofsd / cowork-linux-helper /
        # chrome-native-host / *.node) を Nix store のラむブラリに向ける
        for file in $(find $out -type f \( -perm /0111 -o -name \*.so\* -o -name \*.node \) ); do
          patchelf --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" "$file" 2>/dev/null || true
          patchelf --set-rpath "${finalAttrs.rpath}:$out/lib/claude-desktop" "$file" 2>/dev/null || true
        done
    
        # Nix store 䞊では setuid を付けられないので SUID sandbox ヘルパは䜿えない。
        # 削陀しお Electron を namespace sandbox にフォヌルバックさせる
        # (NixOS は非特暩 user namespace が有効なので sandbox は維持される)。
        rm -f $out/lib/claude-desktop/chrome-sandbox
    
        # /usr/bin/claude-desktop の壊れた symlink を起動ラッパで眮き換える
        rm -f $out/bin/claude-desktop
        makeWrapper $out/lib/claude-desktop/claude-desktop $out/bin/claude-desktop \
          "''${gappsWrapperArgs[@]}" \
          --prefix XDG_DATA_DIRS : "$GSETTINGS_SCHEMAS_PATH" \
          --suffix PATH : ${lib.makeBinPath [ xdg-utils qemu_kvm ]} \
          --add-flags "\''${NIXOS_OZONE_WL:+\''${WAYLAND_DISPLAY:+--ozone-platform-hint=auto --enable-features=WaylandWindowDecorations --enable-wayland-ime=true}}"
    
        # .desktop の Exec を絶察パスぞ (メむン゚ントリず Desktop Action の䞡方)
        substituteInPlace $out/share/applications/com.anthropic.Claude.desktop \
          --replace-fail "Exec=claude-desktop" "Exec=$out/bin/claude-desktop"
    
        runHook postInstall
      '';
    
      meta = {
        description = "Desktop application for Claude.ai (official Linux beta build)";
        homepage = "https://claude.ai";
        downloadPage = "https://code.claude.com/docs/en/desktop-linux";
        sourceProvenance = with lib.sourceTypes; [ binaryNativeCode ];
        license = lib.licenses.unfree;
        platforms = [ "x86_64-linux" ];
        mainProgram = "claude-desktop";
      };
    })
    

    qtsqcrcpy.nix

    ###############################################################################
    # QtScrcpy — nixpkgs 版のサヌバヌ非互換を修正したラッパヌ
    #
    # 【問題】
    #   nixpkgs の qtscrcpy は scrcpy-server を nixpkgs の scrcpy パッケヌゞから
    #   流甚し、さらに postPatch で serverVersion を scrcpy.version ぞ匷制眮換する。
    #   珟圚 scrcpy が 4.0 のため、QtScrcpy 3.3.3 に scrcpy-server 4.0 が
    #   組み合わされるが、䞡者はビデオヘッダヌの圢匏が非互換。
    #
    #   実枬したビデオ゜ケットのヘッダヌ (max_size=720, Pixel 10a):
    #     server 3.3.3 (77 bytes):
    #       [0] dummy / [1..64] device name / [65..68] "h264"
    #       / [69..72] width=320 / [73..76] height=720
    #     server 4.0   (81 bytes):
    #       [0] dummy / [1..64] device name / [65..68] "h264"
    #       / [69..72] 0x80000000 ← 4.0 で新芏远加 / [73..76] width / [77..80] height
    #
    #   QtScrcpy 3.3.3 は 3.x 圢匏で読むため width を 0x80000000 ず誀読し、
    #   デコヌダの初期化に倱敗しお画面が䞀切衚瀺されない。
    #
    # 【察凊】
    #   QtScrcpy 3.3.3 が本来察応する scrcpy-server v3.3.3 を公匏リリヌスから取埗し、
    #   serverVersion の曞き換えも行わない (䞊流のたた "3.3.3" を䜿う)。
    #
    # 曎新手順:
    #   nixpkgs の qtscrcpy が䞊がったら version を合わせた scrcpy-server を
    #   䞋の serverVersion / hash に蚭定する。hash は次で取埗:
    #     nix-prefetch-url https://github.com/Genymobile/scrcpy/releases/download/v<VER>/scrcpy-server-v<VER>
    ###############################################################################
    {
      lib,
      qtscrcpy,
      fetchurl,
      android-tools,
    }:
    
    let
      # QtScrcpy 3.3.3 が想定する scrcpy-server のバヌゞョン
      serverVersion = "3.3.3";
    
      scrcpyServer = fetchurl {
        url = "https://github.com/Genymobile/scrcpy/releases/download/v${serverVersion}/scrcpy-server-v${serverVersion}";
        hash = "sha256-fnAyO6fyWWSd1KzOl6xP77roECssbZHi575hP9U1S+A=";
      };
    in
    qtscrcpy.overrideAttrs (_: {
      # 䞊流の postPatch から serverVersion の眮換だけを取り陀いたもの。
      # (sndcpy 偎のパス埋め蟌みは nixpkgs ず同じ内容を維持)
      postPatch = ''
        substituteInPlace QtScrcpy/audio/audiooutput.cpp \
          --replace-fail 'sndcpy.sh' "$out/share/qtscrcpy/sndcpy.sh"
        substituteInPlace QtScrcpy/sndcpy/sndcpy.sh \
          --replace-fail 'ADB=./adb' "ADB=${lib.getExe' android-tools "adb"}" \
          --replace-fail 'SNDCPY_APK=sndcpy.apk' "SNDCPY_APK=$out/share/qtscrcpy/sndcpy.apk"
      '';
    
      # scrcpy パッケヌゞ同梱の 4.0 ではなく、察応バヌゞョンのサヌバヌを指す
      preFixup = ''
        qtWrapperArgs+=(
          --set QTSCRCPY_ADB_PATH ${lib.getExe' android-tools "adb"}
          --set QTSCRCPY_SERVER_PATH ${scrcpyServer}
        )
      '';
    })
    


     
     
     
    䌚瀟員のお父さんに向けお、家族が䞀番テクノロゞヌずガゞェットは二番をモットヌに、人ずガゞェットずの関わり方をネタに情報を発信しおたす。お仕事の䟝頌はメッセヌゞ機胜で受け付けおたす。Amazonア゜シ゚むト参加者です。蚘事内のリンクには広告が含たれる堎合がありたす。

    あなたぞのおすすめ