❄️

NixOS入りVPS準備-OSインストール編

に公開

目的

  • 外部から自宅PCにVPN経由でssh接続して作業したい。 Tailscaleで良くね?
  • できればNixOSを使用したい。理由: 最近Nixにハマっているから

シリーズ記事

  • OSインストール編
  • 裏話

VPSなどにNixOSを入れた先人たち

前提

まず、外部から自宅PCに接続するにあたって、どうにかして接続先を固定する必要があります。以下のような方法があります。

  1. Dynamic DNS(DDNS)を使い、ドメインに動的IPアドレスを追従させ、ドメインで接続する。
  2. 固定IPアドレスを契約する。
  3. クラウドを契約し、VPNを中継させる。
  4. VPSを契約し、VPNを中継させる。

Claude君に聞いたところ、コスト面ではDDNSが良いけど、セキュリティや安定性との兼ね合いではVPSが一番良いとのことでした。 Tailscaleが最強なことに後で気づきました……

方式 コスト セキュリティ 安定性
DDNS 無料 難しめ 不安定
固定IP かなり高い 難しめ 安定
クラウド 中間 安心 安定
VPS 安い 安心 安定
Tailscale 無料 安心 安定

クラウドは通信量で従量課金されるのが一般的ですが、VPSはそうではないようです。さらに、VPNは低スペで十分で、固定IPが付いてくる点も魅力的です。

以上から、VPSを使用することにしました。使用するサービスは、大学時代に経験があるという一点でさくらのVPSを選びました。 以下はTailscaleに気づく前の記事です。Tailscaleで不足したり、VPN関係無くVPSでNixOS使いたいなら有用かも。

VPSの設定

さくらVPSの最安プランは石狩リージョンで、以下の通りです。

これを使用します。申し込み時に入れられるOSは事前用意されたもののみなので、適当に選びます。パスワードなども後で消し飛ばす設定なので、本当に適当で構いません。

クレカ払いなら、2週間のお試し期間があります。期間中は帯域とport25が制限されますが、特に支障はありません。もしうまくOSを入れられなければ契約を切ることもできましたが、今回はうまく構築できました。 すみません、Tailscaleの存在を知ってしまったので切ってしまいました……。今度はちゃんと事前調査しないと……

まず、ネットワークの項目を確認します。固定IP用の設定情報が書かれています。

DHCPがないので、これをOS側に手動で設定する必要があります。特に、インストーラにも設定する必要があります

isoイメージの作成

さくらVPSはisoイメージでのインストールが可能です。そこで、NixOSのカスタムisoを用意しました。

flake.nix
{
  description = "Mini NixOS installation media";
  inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11"; };
  outputs = { self, nixpkgs, ... }: {
    nixosConfigurations = {
      exampleIso = nixpkgs.lib.nixosSystem {
        system = "x86_64-linux";
        modules = [ ./configuration.nix ];
      };
    };
  };
}
configuration.nix
{ config, lib, pkgs, modulesPath, ... }: {
  imports = [ "${modulesPath}/installer/cd-dvd/installation-cd-minimal.nix" ];

  nix.settings.experimental-features = [ "nix-command" "flakes" ];

  time.timeZone = "Asia/Tokyo";
  networking = {
    hostName = "nixos";
    networkmanager.enable = true;
    interfaces.ens3 = {
      ipv4 = {
        addresses = [{
          address = "192.168.1.1"; # 要編集
          prefixLength = 23; # ネットマスクの立っているビットの数
        }];
      };
      ipv6 = {
        addresses = [{
          address = "1000:1000::2"; # 要編集
          prefixLength = 64;
        }];
      };
    };
    defaultGateway = {
      address = "192.168.0.1"; # 要編集
      interface = "ens3"; # もしかしたら違うかもしれません
    };
    nameservers = [ "192.168.0.1" "1000:1000::1" ]; # 要編集
  };

  environment.systemPackages = with pkgs; [ git networkmanager ];

  services.openssh.enable = false; # インストールもsshで操作したいならtrueにしたうえでユーザも用意

  system.stateVersion = "25.11";
}

ipv4.addresses.prefixLengthは、ネットマスクが255.255.254.0であることから、23と分かります。これは、ネットマスクを2進数にしたときに1が立っている数です。

isoイメージがインターネット接続できるかが今回は問題になりました(裏話)。自信がなく対話的にやりたい場合はnetworkmanagerを有効化し、interfacesの設定を削除しておきます。

書けたflakeを以下のコマンドでisoイメージにビルドします。

nix build .#nixosConfigurations.exampleIso.config.system.build.isoImage

コンパイル結果は./result/iso内に生成されます。なお、./resultはnix storeへのシンボリックリンクです。今回の場合、isoイメージは1.4GBでした。

ちなみに、ここでいくら設定してもそれはインストーラ環境の設定であり、インストールされる環境の設定ではないので注意。せいぜい下書きした設定ファイルを持ち込めるくらいです。

isoイメージの実行

VPSのコントロールパネルを開いたら、OS再インストールボタンがあるので、これを押します。指定された通りに、sftpでisoファイルをアップロードします。

うまくアップロードできたら、内容確認→OS再インストールから電源を付けます。するとコンソール起動を促すポップアップが出るので起動します。ちなみに、ストレージが初期化すると書かれていても、実際にはisoが起動されるだけでストレージはそのままです。

起動するとNixOSをインストールする際に出るGUIが一瞬表示され、

自動でコンソールにログインします。

メモリが足りるか不安でしたが、足りました。

なお、VPSを停止してしまっても、isoイメージはアップロードから24時間以内なら再アップロードせずにそのまま使えます。isoイメージのinstallからインストールメディアを起動することができます。このとき、ディスクは以前の状態のままなので安心です。

インターネットに接続できることを確認しておきます。もしうまく行かなければ、isoイメージの設定がおかしかったことになります。

ping google.com

NixOS Install

ここからは普通にインストーラを触ってインストールを進めます。

パーティショニング

Claude君によると、一般のVPSではbootパーティションなどは不要で、rootパーティションのみで十分とのことです。そのため、パーティションはデフォルトに従い、vda2をrootにします。vda1はbios boot partitionという、UEFIブートした際に使用するパーティションです。

vda2はすでにext4にされていますが、中身は最初に選んだOSです。フォーマットし、マウントします。

sudo mkfs.ext4 /dev/vda2
sudo mount /dev/vda2 /mnt

configuration.nixの編集

続いて、ここにconfiguration.nixを生成します。

sudo mkdir -p /mnt/etc/nixos  # 実際は、インストーラのデフォルトのmkdirは-pを使用できません
sudo nixos-generate-config --root /mnt

これで/mnt/etc/nixosにconfiguration.nixとhardware-configuration.nixが生成されます。nanoやvimでconfiguration.nixを編集します。あるいは、gitコマンドなどで事前に用意したプロファイルを持ち込んでも構いません。

sudo nano /mnt/etc/nixos/configuration.nix

ここで、ネットワーク設定とユーザ設定は必須です。後で書き換える前提で平文パスワードにしておきます。忘れるとログインやsudoができずに詰むので注意。もし詰んだら、OS再インストールからisoイメージを再起動すれば戻って来れます。

ちなみに、flakeはこの段階では認識されないので、おとなしくconfiguration.nixを書きましょう。

{ config, lib, pkgs, ... }: {
  imports = [ ./hardware-configuration.nix ];
  boot.loader.grub.enable = true; # 直接/dev/vda2に/bootが生成される
  boot.loader.grub.device = "/dev/vda";

  networking = { # 要編集
    hostName = "nixos";
    networkmanager.enable = false;
    interfaces.ens3 = {
      ipv4 = {
        addresses = [{
          address = "192.168.1.1";
          prefixLength = 23;
        }];
      };
      ipv6 = {
        addresses = [{
          address = "1000:1000::2";
          prefixLength = 64;
        }];
      };
    };
    defaultGateway = {
      address = "192.168.0.1";
      interface = "ens3";
    };
    nameservers = [ "192.168.0.1" "1000:1000::1" ];
  };
  time.timeZone = "Asia/Tokyo";
  users.users.username = {
    isNormalUser = true;
    password = "ABCDEFG"; # 非常に良くないので早めに別の方法で設定すること。sopsを推奨。
    extraGroups = [ "wheel" ]; # sudoに必要
  };
  security.sudo = {
    wheelNeedsPassword = true; # sudoコマンド時パスワード要求
  };
  environment.systemPackages = with pkgs; [
    vim
    wget
    git
    tmux
  ]; # 必要そうなものを用意しておく
  networking.firewall.enable = true;
  swapDevices = [{ # メモリ不足しないようにswapを設定
    device = "/var/lib/swapfile";
    size = 2 * 1024; # MB
  }];
  system.stateVersion = "25.11"; # デフォルトから変更しないこと
}

さて、このまま進めるとOOMで止まります。なので、先にswapを用意します。ここでは適当に2GB用意します。

sudo dd if=/dev/zero of=/mnt/var/lib/swapfile bs=1M count=2048
sudo chmod 600 /mnt/var/lib/swapfile
sudo mkswap /mnt/var/lib/swapfile
sudo swapon /mnt/var/lib/swapfile
sudo swapon --show

問題ないと思ったら、NixOSをinstallします。

sudo nixos-install

文法エラーも論理エラーもなければinstallが始まります。(swap含めて)メモリが足りていれば数分で終わります。

install確認

installが無事完了したら、VPSを再起動します。ログインし、sudo nixos-rebuild switchが成功したらinstall成功です。

次回

まずconfiguration.nixをflake化します。セキュリティのための設定をして、ついでにWireguardのinstallと設定までする予定です。

TailscaleでVPN接続することになったので次回は無いです

Discussion