HN 日本語サマリー

← 一覧へ戻る
インフラ・DevOps

NixOSのRAMフットプリントとリソース要件を最小限に抑える

Shrinking NixOS RAM footprint and resource requirements to the bare minimum (lowendspirit.com)

46 pointsby birdculture4 コメント

要約

この記事は、NixOSのRAM使用量を劇的に削減する方法について解説しています。著者は、カーネルパラメータのチューニング、不要なモジュールのブラックリスト化、サービスの無効化、Nixのガベージコレクションの最適化など、様々な手法を用いて、アイドル時のRAM使用量を288MBから96MBに、再構築時のメモリ使用量を896MBから512MBにまで削減しました。これにより、512MB VPSのような低リソース環境でもNixOSが動作可能になります。

全文翻訳

NixOSのRAMフットプリントとリソース要件を最小限に抑える

数名の人々がNixOSでどこまで低くできるかに驚いていたので、私はそれを書き留めることにしました。というのも、それが特別なことだと気づいていなかったからです。作業中にメモは取っていましたが、ブログ記事を書くつもりはなかったので、あちこちで少し調整したことをいくつか見落としているかもしれません。

当初、この作業には半日を予定していましたが、実際には3日近くかかりました。

このガイドはディスク容量の節約にはあまり焦点を当てていません。ディスク容量節約ガイドが必要な場合は、すでに誰かがここで作成しています: https://nixcademy.com/posts/minimizing-nixos-images/。これには独自の課題や欠点があるため、もしそれらを組み合わせたいのであれば、ご自由にどうぞ [画像: :)]。私は、TierHive NixOSテンプレートにディスク削減オプションを実装しないことにしました。なぜなら、エンドユーザーが期待しないデフォルト設定になる可能性が非常に高いと感じたからです。

それでは始めましょう:

NixOS 26.05 は約96MBでアイドル状態になり、再構築には512MBを消費

変更を加える前の標準的なデプロイメント(cloud-init使用)では、1024MBのRAMで動作します。アイドル時は288MB使用し、89個のカーネルモジュールがロードされていました。同じリリースでのプレーンな再構築には896MBが必要でした(505MBのアノニマスメモリで768MBのnix-buildはOOMキルされました)。

現在では、512MB VPSで54個のモジュールを使用し、96MBでアイドル状態になります。フルチャンネルアップデートと再構築(必要であればカーネルを7.3に切り替える場合も含む)は、371MBのピークで512MBで完了し、OOMは発生しません。すべての数値は私の実行結果からのものです。時々正確な数値を記録しましたが、他の時はKBを省略してMBのみを記録しました [画像: :)]。第二回目の起動後、誰もログインしていない状態で、私のビルド環境テストツールを使用して測定しました(使用前にテンプレートにログインすることは決してないので、クリーンな状態です)。

このテンプレートで行ったことの順序と内容は以下の通りです(無害な失敗も含む):

  • sysctl.vm.mem_profiling=never をコマンドラインに設定。NixOSカーネルはデフォルトでアロケーションプロファイリングが有効になっており、トラッキングテーブルは約6MB(vmallocで3.9MB、slabで1.9MB)を消費します。単なる mem_profiling=never は無効なパラメータです。カーネルはそれをユーザー空間に渡すだけで何も変更されません。sysctl. プレフィックスが必要です。
  • kfence.sample_interval=0 でKFENCEプール(2MB)を解放します。
  • damon_stat.enabled=N と audit=0 でkdamondとkauditdスレッドを削除します。
  • initcall_blacklist=ksm_init,tpm_init,init_tis でksmd(1.4MB)とTPM関連ビット(0.3MB + kthread)を削除します。これらのゲストにはTPMはなく、ゲスト内のKSMは無意味です(TierHiveでは anyway)。
  • psi=0 ras=cec_disable nowatchdog nmi_watchdog=0 cryptomgr.notests 8250.nr_uarts=1 はすべて小さく、主にkthreadの数を減らし、ノイズを減らします。2GBのテストVMでは、コマンドライン全体の設定により、非キャッシュメモリが128.0MBから121MBに、kthreadが64から59に減少しました。
  • transparent_hugepage=never は、最も大きな効果をもたらした単一の変更の一つでした。THP(Transparent Huge Pages)が有効な場合、カーネルは vm.min_free_kbytes を41108に引き上げます(THP無効で896MBの場合3710)。これは使用できない予約メモリです。これを無効にすることで、2GBのシステムで52MBが解放され、896MBのシステムで103MB多く利用可能になりました。もちろん、ハイエンドや本番環境ではこれを行わない理由がありますが、日常的な使用では、おそらく違いに気づかないでしょう。
  • KVMゲストが持たない、または必要としないハードウェアをブラックリスト化しました: floppy, intel_agp, i2c_piix4, psmouse, mousedev, joydev, serio_raw, evdev, button (tiny_power_buttonがACPIシャットダウンを処理済み), rapl/cstate/uncore関連、kvm, cfg80211 (networkdがnl80211のためにこれをプルしていた)、ata_generic/pata_acpi, qemu_fw_cfg, dmi_sysfs, vga16fb。
  • virtio_consoleもブラックリスト化しました。エージェントチャネルを使用するものがなく、8MBのkmalloc-4kスラブを占有していました。
  • vsock, vmci, virtiofsは、ブラックリスト化する代わりに install <mod> /bin/false を使用します。これらはデバイスが存在しない状態でスイッチルート時に要求され、プレーンなブラックリストでは代わりに vmw_vmci がロードされてしまいました。
  • virtio_gpuをブラックリスト化し、VNCコンソールをプレーンなvgacon経由でvirtio-vgaで実行させました。これは6.18.59の修正/回避策のためでしたが、7.3には引き継がれません。しかし、これはオプションです。
  • Initrdを virtio_pci virtio_blk ext4 に削減し、includeDefaultModules = false を使用し、qemu-guestプロファイルをインポートしないようにしました。
  • 小さなDerivationでカーネルモジュールのツリーをトリムし、system.modulesTree を置き換えました。これにより、サウンド、GPU、Wi-Fi、USB、物理NIC、SCSI/ATA HBAドライバーなどが削除され、保持されるすべてのモジュールの依存関係は常に維持されます。ディスク上では162MBから45MBに削減され、udevは何も自動ロードしなくなりました。これは nixos-rebuild 内で実行されるため、カーネルアップデートでも同様に処理されます。
  • systemd-resolvedを無効化しました。8.3MBのPSSを消費し、0.0.0.0:5355でLLMNR/mDNSをリッスンしていました。cloud-initは代わりにプレーンなresolv.confを書き込みます。
  • systemd-timesyncd (4.6MB) を、タイマーで実行されるoneshotの busybox ntpd -n -q に置き換えました。起動時と毎時実行され、常駐しません(すべての環境で機能するわけではありませんが、ほとんどのKVMホストでは問題ないはずです)。
  • services.openssh.startWhenNeeded = true を設定し、sshdをソケットアクティベーション化しました。これにより、接続があるときだけ3.9MBのリスナーが存在します(NAT環境には最適ですが、パブリックIPでポート22をリッスンさせたい場合はスキップした方が良いかもしれません)。
  • systemd-oomd (1.8MB) を無効化しました。
  • 小さなoneshotサービスで、cloud-initで生成された.networkファイルに LLDP=no を追加し、アイドル時のネットワークソケットとaf_packetのロードを停止します。
  • 常駐しているのは、systemd, udevd, nsncd, networkd, journald, logind, dbus-broker, そして1つのgettyで、約40MBのユーザーランドPSSです。
  • zramをzstdアルゴリズムで memoryPercent = 100、最大512MBに設定し、ディスクスワップは使用しません。これが、次の項目と合わせて、512MBでの再構築を可能にしています。
  • vm.swappiness = 180 を設定し、カーネルがページキャッシュを破棄するよりもコールドアノニマスページをzramに圧縮することを優先するようにしました。vm.page-cluster = 0 は、zramでのリードアヘッドが無駄なメモリを消費するためです。vm.watermark_scale_factor = 125 と vm.watermark_boost_factor = 0 は、kswapdが早期に開始し、再構築がダイレクトリクレームで停滞しないようにします。512MBでの再構築中、zramは116MBの実際のRAMをピークで使用しました。
  • Nixが使用するBoehm GCをチューニングしました。システム全体で environment.variables を設定し、nixos-rebuild がそれを拾うようにしました。2GB VMでモジュールシステムを評価する (nix-instantiate '<nixpkgs/nixos>' -A system) と、標準では599MBをピークとしました(Nix 2.34はヒープをRAMの25%まで事前に拡張しますが、384MBが上限です)。GC_INITIAL_HEAP_SIZE=33554432 を設定すると597MBになり、GC_FREE_SPACE_DIVISOR=8 を追加すると562MB、GC_FORCE_UNMAP_ON_GCOLLECT=1 を追加すると548MBになりました。評価メモリを意味のある形で移動させる他の方法は見つかりませんでした。
  • クローザーをトリムしました。これは主にディスク容量に関係しますが、アップデート時にプルして管理する量が減ることを意味します: environment.defaultPackages = [ ]、ドキュメンテーションオフ、xdg mime/icons/soundsオフ、fontconfigオフ、lvmとbcacheオフ、systemd-importdを抑制(gnupg, openldap, cyrus-saslをプルし、約18MB消費)、nixos-optionオフ(man-dbとgroffをプルし、約11MB消費)、nixos-install/enter/build-vmsオフ、そしてsu.forwardXAuth を強制的にオフにしてxauthを削除しました。クローザーは963MBから910MBに、圧縮イメージは607MBから477MBに削減されました。

512MBでまだ苦労するのは、リリース間のジャンプ(26.05からunstableへ)です。4GBのディスクで最初の試みは約30分続き、その後nix-buildがOOMキルされました。古い世代は問題なく動作し続けました。再度実行すると、すべてがすでにダウンロードされていたため完了しました。リリースジャンプを行う場合は、その間により多くのRAMを用意するか、2回実行することを想定してください。30分待つ必要はありません。5〜10分後にキャンセルして、もう一度実行してください。ただし、これはリリース候補へのジャンプだったので、他にジャンプできるものがなかったのかもしれません。それが原因かもしれません。

完全な設定を以下に示します。tierhive.nix の一部はプラットフォーム関連(cloud-init、パスワードリセット、予約ブロック)であり、RAMとは直接関係ありませんが、完全な動作ファイルです。

configuration.nix

{ config, lib, pkgs, ... }:

{
  imports = [
    ./hardware-configuration.nix
    ./tierhive.nix
  ];

  environment.systemPackages = with pkgs; [ curl rsync ];

  system.stateVersion = "26.05";
}

hardware-configuration.nix

{ config, lib, pkgs, modulesPath, ... }:

{
  boot.initrd.includeDefaultModules = false;
  boot.initrd.availableKernelModules = [ "virtio_pci" "virtio_blk" "ext4" ];
  boot.initrd.kernelModules = [ ];
  boot.kernelModules = [ ];
  boot.extraModulePackages = [ ];

  fileSystems."/" = {
    device = "/dev/disk/by-label/nixos";
    fsType = "ext4";
  };

  swapDevices = [ ];

  nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}

tierhive.nix

# TierHive VPS プラットフォーム設定: ネットワーク、DNS、ホスト名は初回起動時にクラウドイニシャライザ経由でパネルから取得されます。
{ config, lib, pkgs, ... }:

let
  # KVM VPS が決して持たないハードウェア用のドライバーを除いたカーネルモジュールツリー。保持されるモジュールは常に依存関係を維持します。
  kernel = config.boot.kernelPackages.kernel;
  moduleTreeRemove = [
    "kernel/sound/*"
    "kernel/drivers/accel/*" "kernel/drivers/accessibility/*" "kernel/drivers/atm/*" "kernel/drivers/auxdisplay/*" "kernel/drivers/bcma/*"
    "kernel/drivers/bluetooth/*" "kernel/drivers/bus/*" "kernel/drivers/clk/*" "kernel/drivers/comedi/*" "kernel/drivers/counter/*"
    "kernel/drivers/cpufreq/*" "kernel/drivers/crypto/*" "kernel/drivers/cxl/*" "kernel/drivers/dca/*" "kernel/drivers/devfreq/*"
    "kernel/drivers/dma/*" "kernel/drivers/edac/*" "kernel/drivers/extcon/*" "kernel/drivers/firewire/*" "kernel/drivers/fpga/*"
    "kernel/drivers/fsi/*" "kernel/drivers/fwctl/*" "kernel/drivers/gnss/*" "kernel/drivers/gpio/*" "kernel/drivers/greybus/*"
    "kernel/drivers/hid/*" "kernel/drivers/hsi/*" "kernel/drivers/hv/*" "kernel/drivers/hwmon/*" "kernel/drivers/hwtracing/*"
    "kernel/drivers/i2c/*" "kernel/drivers/i3c/*" "kernel/drivers/iio/*" "kernel/drivers/infiniband/hw/*" "kernel/drivers/ipack/*"
    "kernel/drivers/leds/*" "kernel/drivers/macintosh/*" "kernel/drivers/mailbox/*" "kernel/drivers/mcb/*" "kernel/drivers/media/*"
    "kernel/drivers/memstick/*" "kernel/drivers/message/*" "kernel/drivers/mfd/*" "kernel/drivers/mmc/*" "kernel/drivers/most/*"
    "kernel/drivers/mtd/*" "kernel/drivers/mux/*" "kernel/drivers/nfc/*" "kernel/drivers/ntb/*" "kernel/drivers/nvdimm/*"
    "kernel/drivers/nvmem/*" "kernel/drivers/parport/*" "kernel/drivers/pcmcia/*" "kernel/drivers/peci/*" "kernel/drivers/perf/*"
    "kernel/drivers/phy/*" "kernel/drivers/pinctrl/*" "kernel/drivers/platform/*" "kernel/drivers/power/*" "kernel/drivers/powercap/*"
    "kernel/drivers/rapidio/*" "kernel/drivers/ras/*" "kernel/drivers/regulator/*" "kernel/drivers/reset/*" "kernel/drivers/rpmsg/*"
    "kernel/drivers/siox/*" "kernel/drivers/slimbus/*" "kernel/drivers/soc/*" "kernel/drivers/soundwire/*" "kernel/drivers/spi/*"
    "kernel/drivers/spmi/*" "kernel/drivers/ssb/*" "kernel/drivers/staging/*" "kernel/drivers/tee/*" "kernel/drivers/thermal/*"
    "kernel/drivers/thunderbolt/*" "kernel/drivers/ufs/*" "kernel/drivers/usb/*" "kernel/drivers/w1/*" "kernel/drivers/xen/*"
    "kernel/drivers/video/fbdev/*" "kernel/drivers/video/backlight/*" "kernel/drivers/gpu/drm/*/*"
    "kernel/drivers/input/joystick/*" "kernel/drivers/input/touchscreen/*" "kernel/drivers/input/tablet/*"
    "kernel/drivers/input/gameport/*" "kernel/drivers/input/rmi4/*"
    "kernel/drivers/net/ethernet/*" "kernel/drivers/net/wireless/*" "kernel/drivers/net/wwan/*" "kernel/drivers/net/usb/*"
    "kernel/drivers/net/arcnet/*" "kernel/drivers/net/fddi/*" "kernel/drivers/net/hamradio/*" "kernel/drivers/net/hippi/*"
    "kernel/drivers/net/ieee802154/*" "kernel/drivers/net/wan/*" "kernel/drivers/net/plip/*" "kernel/drivers/net/fjes/*"
    "kernel/drivers/net/hyperv/*" "kernel/drivers/net/vmxnet3/*" "kernel/drivers/net/xen-netback/*" "kernel/drivers/net/xen-netfront.ko*"
    "kernel/drivers/net/thunderbolt/*" "kernel/drivers/net/mhi_net.ko*" "kernel/drivers/net/dsa/*" "kernel/drivers/net/rionet.ko*"
    "kernel/drivers/net/ntb_netdev.ko*" "kernel/drivers/net/sungem_phy.ko*"
    "kernel/drivers/block/floppy.ko*" "kernel/drivers/block/mtip32xx/*" "kernel/drivers/block/xen-blk*"
    "kernel/drivers/scsi/*" "kernel/drivers/ata/*" "kernel/drivers/watchdog/*" "kernel/drivers/rtc/*"
  ];
  moduleTreeKeep = [
    "kernel/drivers/gpu/drm/virtio/*"
    "kernel/drivers/scsi/scsi_mod.ko*" "kernel/drivers/scsi/scsi_common.ko*" "kernel/drivers/scsi/sd_mod.ko*" "kernel/drivers/scsi/sr_mod.ko*"
    "kernel/drivers/scsi/sg.ko*" "kernel/drivers/scsi/st.ko*" "kernel/drivers/scsi/ch.ko*" "kernel/drivers/scsi/ses.ko*"
    "kernel/drivers/scsi/raid_class.ko*" "kernel/drivers/scsi/virtio_scsi.ko*" "kernel/drivers/scsi/scsi_transport_*"
    "kernel/drivers/scsi/iscsi_tcp.ko*" "kernel/drivers/scsi/libiscsi.ko*" "kernel/drivers/scsi/libiscsi_tcp.ko*"
    "kernel/drivers/scsi/iscsi_boot_sysfs.ko*"
    "kernel/drivers/ata/libata.ko*" "kernel/drivers/ata/ata_piix.ko*" "kernel/drivers/ata/ahci.ko*" "kernel/drivers/ata/libahci.ko*"
    "kernel/drivers/watchdog/watchdog.ko*" "kernel/drivers/watchdog/i6300esb.ko*" "kernel/drivers/watchdog/softdog.ko*"
    "kernel/drivers/rtc/rtc-cmos.ko*"
  ];
  modulesSrc = lib.getOutput "modules" kernel;
  trimmedModules = pkgs.runCommand "${kernel.name}-modules-tierhive" { nativeBuildInputs = [ pkgs.kmod ]; } ''
    set -f
    remove="${lib.concatStringsSep " " moduleTreeRemove}"
    keep="${lib.concatStringsSep " " moduleTreeKeep}"
    ver=$(ls ${modulesSrc}/lib/modules)
    src=${modulesSrc}/lib/modules/$ver
    dst=$out/lib/modules/$ver
    match() { local f=$1 p; for p in $2; do case $f in $p) return 0;; esac; done; return 1; }
    declare -A want
    while IFS= read -r line; do
      m=''${line%%:*}
      if match "$m" "$remove" && ! match "$m" "$keep"; then continue; fi
      want[$m]=1
      for d in ''${line#*:}; do want[$d]=1; done
    done < $src/modules.dep
    for m in "''${!want[@]}"; do mkdir -p "$dst/$(dirname "$m")"; cp "$src/$m" "$dst/$m"; done
    cp $src/modules.builtin $src/modules.builtin.modinfo $dst/
    while IFS= read -r o; do
      for m in "$o" "$o.xz" "$o.zst" "$o.gz"; do [ -n "''${want[$m]:-}" ] && { echo "$o"; break; }; done
    done < $src/modules.order > $dst/modules.order
    depmod -b $out -a $ver
  '';
in
{
  boot.loader.grub.enable = true;
  boot.loader.grub.device = "/dev/vda";

  boot.kernelParams = [
    "sysctl.vm.mem_profiling=never" "damon_stat.enabled=N" "kfence.sample_interval=0" "audit=0"
    "initcall_blacklist=ksm_init,tpm_init,init_tis" "psi=0" "ras=cec_disable" "nowatchdog" "nmi_watchdog=0"
    "cryptomgr.notests" "8250.nr_uarts=1" "transparent_hugepage=never"
  ];
  system.modulesTree = lib.mkForce ([ trimmedModules ] ++ config.boot.extraModulePackages);
  boot.blacklistedKernelModules = [
    "virtio_console" "floppy" "intel_agp" "i2c_piix4" "psmouse" "mousedev" "joydev" "serio_raw" "mac_hid"
    "input_leds" "evdev" "button" "rapl" "intel_rapl_msr" "intel_rapl_common" "intel_cstate" "intel_uncore"
    "kvm_intel" "kvm_amd" "kvm" "cfg80211" "ata_generic" "pata_acpi" "qemu_fw_cfg" "dmi_sysfs" "vga16fb" "virtio_gpu"
  ];
  boot.extraModprobeConfig = lib.concatMapStrings (m: "install ${m} ${pkgs.coreutils}/bin/false\n") [
    "vsock" "vmw_vsock_virtio_transport" "vsock_loopback" "vmw_vsock_vmci_transport" "vmw_vmci" "virtiofs"
  ];

  boot.kernel.sysctl = {
    "kernel.panic_on_oops" = 1;
    "kernel.panic" = 10;
    "vm.swappiness" = 180;
    "vm.page-cluster" = 0;
    "vm.watermark_scale_factor" = 125;
    "vm.watermark_boost_factor" = 0;
  };

  services.udev.extraRules = ''
    ACTION=="add|change", KERNEL=="vd[a-z]*", ENV{DEVTYPE}=="disk", ATTR{queue/scheduler}="none", ATTR{queue/read_ahead_kb}="128"
  '';

  zramSwap = {
    enable = true;
    algorithm = "zstd";
    memoryPercent = 100;
    memoryMax = 536870912;
  };

  networking.hostName = "";
  networking.useDHCP = false;
  networking.resolvconf.enable = false;
  services.resolved.enable = false;
  systemd.oomd.enable = false;

  services.timesyncd.enable = false;
  systemd.services.tierhive-ntp = {
    description = "One-shot clock sync";
    after = [ "network-online.target" ];
    wants = [ "network-online.target" ];
    serviceConfig.Type = "oneshot";
    serviceConfig.ExecStart = "${pkgs.busybox}/bin/ntpd -n -q ${lib.concatMapStringsSep " " (s: "-p ${s}") config.networking.timeServers}";
  };
  systemd.timers.tierhive-ntp = {
    wantedBy = [ "timers.target" ];
    timerConfig.OnBootSec = "30s";
    timerConfig.OnCalendar = "*-*-* *:17:00";
  };

  environment.etc."systemd/journald.conf.d/10-tierhive.conf".text = ''
    [Journal]
    SystemMaxUse=50M
  '';

  environment.variables = {
    GC_INITIAL_HEAP_SIZE = "33554432";
    GC_FREE_SPACE_DIVISOR = "8";
    GC_FORCE_UNMAP_ON_GCOLLECT = "1";
  };

  environment.defaultPackages = [ ];
  xdg.mime.enable = false;
  xdg.icons.enable = false;
  xdg.sounds.enable = false;
  fonts.fontconfig.enable = false;
  services.lvm.enable = false;
  boot.bcache.enable = false;
  systemd.suppressedSystemUnits = [ "systemd-importd.service" "sys-kernel-config.mount" ];
  system.tools.nixos-option.enable = false;
  system.tools.nixos-build-vms.enable = false;
  system.tools.nixos-install.enable = false;
  system.tools.nixos-enter.enable = false;
  security.pam.services.su.forwardXAuth = lib.mkForce false;

  documentation.enable = false;
  documentation.man.enable = false;
  documentation.nixos.enable = false;

  services.openssh = {
    enable = true;
    startWhenNeeded = true;
    settings.PermitRootLogin = null;
    settings.PasswordAuthentication = null;
    settings.KbdInteractiveAuthentication = false;
    extraConfig = "Include /etc/ssh/sshd_config.d/*.conf";
  };
  security.pam.services.sshd.unixAuth = lib.mkForce true;
  systemd.tmpfiles.rules = [ "d /etc/ssh/sshd_config.d 0755 root root -" ];

  environment.etc.fstab.mode = "0644";

  services.cloud-init = {
    enable = true;
    network.enable = true;
    settings = {
      datasource_list = [ "NoCloud" ];
      system_info = {
        distro = "nixos";
        network.renderers = [ "networkd" ];
        paths.templates_dir = "${pkgs.cloud-init}/${pkgs.python3.sitePackages}/etc/cloud/templates";
      };
      unverified_modules = [ "resolv_conf" ];
      ssh_deletekeys = false;
      ssh_genkeytypes = [ ];
      cloud_init_modules = [ "seed_random" "bootcmd" "write_files" "growpart" "resizefs" "set_hostname" "update_hostname" "update_etc_hosts" "resolv_conf" "users_groups" "ssh" ];
      cloud_config_modules = [ "set_passwords" "runcmd" ];
      cloud_final_modules = [ "package_update_upgrade_install" "write_files_deferred" "scripts_vendor" "scripts_per_once" "scripts_per_boot" "scripts_per_instance" "scripts_user" "keys_to_console" "final_message" ];
    };
  };
  systemd.services.cloud-init-local.unitConfig.ConditionPathExists = "!/etc/cloud/cloud-init.disabled";
  systemd.services.cloud-init.unitConfig.ConditionPathExists = "!/etc/cloud/cloud-init.disabled";
  systemd.services.cloud-config.unitConfig.ConditionPathExists = "!/etc/cloud/cloud-init.disabled";
  systemd.services.cloud-final.unitConfig.ConditionPathExists = "!/etc/cloud/cloud-init.disabled";

  systemd.services.tierhive-lldp-off = {
    description = "Disable LLDP reception on the cloud-init network files";
    unitConfig.DefaultDependencies = false;
    after = [ "cloud-init-local.service" ];
    before = [ "systemd-networkd.service" ];
    wantedBy = [ "multi-user.target" ];
    serviceConfig.Type = "oneshot";
    script = ''
      for f in /etc/systemd/network/10-cloud-init-*.network; do
        [ -e "$f" ] || continue
        [ -e "$f.d/10-tierhive-lldp.conf" ] && continue
        mkdir -p "$f.d"
        printf '[Network]\nLLDP=no\n' > "$f.d/10-tierhive-lldp.conf"
      done
    '';
  };

  systemd.services.tierhive-reserved-blocks = {
    description = "Set root fs reserved blocks to 0.01% after first-boot grow";
    wantedBy = [ "multi-user.target" ];
    after = [ "cloud-init.service" ];
    unitConfig.ConditionPathExists = "!/var/lib/tierhive/reserved-blocks.done";
    path = [ pkgs.e2fsprogs pkgs.util-linux pkgs.gawk ];
    serviceConfig.Type = "oneshot";
    script = ''
      dev=$(findmnt -no SOURCE /)
      blocks=$(tune2fs -l "$dev" | awk -F: '#{print $2}')
      tune2fs -r $((blocks / 10000)) "$dev"
      mkdir -p /var/lib/tierhive
      touch /var/lib/tierhive/reserved-blocks.done
    '';
  };
}

試してみて、調整して、フィードバックをください。もしかしたら、もっと進めることができるかもしれません [画像: :)]

TierHive - 毎時VPS - NATネイティブ - 顧客あたり/24 - DE, UK, SG, CA x2, USA x5, FR x3, AU, PL, NL, JP, BR, ZA
サインアップ時に無料トークンをプレゼント。購入前に試用してください。| 静的ホスティングは永年無料: https://tierhive.com/static-hosting/