NixOSでnginxによるWebサーバの構築

前回の記事ではNixOSをCLIでVirtualBoxにインストールした。仮想HDDの消費状況をGUIインストール時と比較し、仮想HDDの消費状況は初期設定を終えた段階ではGUIインストールをほぼ同じである事を確認した。
今回は、当ブログの著者の家庭内の環境にて動作させるローカルなWebサーバを導入すべく、NixOSにnginxをインストールしWebサーバの基本的な構築と動作確認を行った。
過去の記事について NixOSネタの記事の一覧は、当記事内最下部の「NixOS関連の記事」欄内を参照。
 


Webサーバについて
今回はWebサーバとしてnginxを導入する。
nginxとは、Webサーバやリバースプロキシサーバやロードバランサ等さまざまな機能を備えたソフトウェアで、世界中で多くの導入実績がある。オープンソース版のnginxと商用版のNGINX Plusがある。
nginxはイベント駆動型(非同期処理)のアーキテクチャを採用している。これは、リクエストごとに新しいプロセスを立ち上げるのではなく、1つのプロセス(または少数のワーカープロセス)で多数のリクエストを非同期に処理できるというもので、Webサーバとして多く導入されているApacheのような、接続毎にスレッドやプロセスを分けるマルチプロセス型とは異なっている。
この設計により、nginxは非常に多くの同時接続を効率よく処理する事でCPUやメモリの消費を最小限に抑える事が期待される。特に、静的ファイルの配信、APIゲートウェイの構成、コンテナやマイクロサービス環境でのリバースプロキシなどでその真価を発揮する。
尚、nginxの表記に関してはnginxのサイト内での表記に倣い小文字で記載している。
 


当方の環境
ホスト機:macOS 15.4.1 / MacBook Pro 2020 / RAM: 16GB / CPU: Intel Core i5 2.0GHz
仮想化環境:Oracle VirtualBox 7.1.6 r167084
ゲストOS:NixOS 24.11 (Vicuna)
Webサーバ:nginx 1.26.3
2025年も5月に差し掛かった。そろそろNixOSの次のバージョン25.05がリリースされるだろう。
 


今回の要件
NixOSを新規に立ち上げてnginxを導入する。動作確認として、クライアント側(MacBook Pro)にてWebブラウザFirefoxとGoogle ChromeとMicrosoft Edgeを使用しnginxで構築したWebサイトにアクセス。テスト用のページが表示出来る事を確認する。
機能てんこ盛りなシステムは嫌なので、過去の記事にて扱ったDNSサーバやメールサーバ等の構築の際と同様にnginx用のNixOSを新規に立ち上げて、nginxのインストールや設定や動作確認を実施する。NixOSのインストールおよび初期設定は以下の内容を実施した。
https://debslink.hatenadiary.jp/entry/20250311/1741649715 NixOSの沼に片足を突っ込んだ
https://debslink.hatenadiary.jp/entry/20250320/1742459549 NixOSの環境構築(今回はneofetch未導入)
 
ざっくりとした要件は以下のとおり。
・nginxとOpenSSLを組み合わせた設定の学習のため、OpenSSLも導入する。
・サーバ証明書は自機にて生成し、nginx界隈でよく見かけるLet's Encryptの導入は今回は見送る。
・nginxの設定は/etc/nixos/configuration.nixファイルの中に追記するのではなく、/etc/nixos/nginx.nixファイルを新規作成しその中に記載する。
 
設定に取り掛かる前に、今の動作環境を出力。

[testsv99:~ ]# uname -a
Linux testsv99 6.6.88 #1-NixOS SMP PREEMPT_DYNAMIC Fri Apr 25 08:45:59 UTC 2025 x86_64 GNU/Linux
[testsv99:~ ]# 
[testsv99:~ ]# zsh --version
zsh 5.9 (x86_64-pc-linux-gnu)
[testsv99:~ ]# 

 


サーバ証明書の作成

1. OpenSSLのインストール
サーバ証明書を生成しnginxに読み込ませる必要がある為、当環境ではnginxのインストールや構築の前にOpenSSLをインストールした。
/etc/nixos/configuration.nixファイルを開き、以下の設定例のように導入パッケージの設定欄にopensslを追記する。

[testsv99:~ ]# sudo nvim /etc/nixos/configuration.nix
# Edit this configuration file to define what should be installed on
# your system.  Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running ‘nixos-help’).

{ config, pkgs, ... }:
:
省略
:
  # List packages installed in system profile. To search, run:
  # $ nix search wget
  environment.systemPackages = with pkgs; [
  #  vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default.
    zsh
    neovim
    chrony
    openssl ◻️◻️追記
  ];
:
省略
:

 
/etc/nixos/configuration.nixファイルの編集後、sudo nixos-rebuild switchコマンドを叩いてOpenSSLのパッケージをインストールする。

[testsv99:~ ]# sudo nixos-rebuild switch
building Nix...
building the system configuration...
:
省略
:

 
2. 自己証明書の生成
OpenSSLパッケージのインストールおよびビルドが終了したら、この後に生成する自己証明書や鍵などの保存先のディレクトリを作成する。
作成後、nginxが証明書や鍵を読み取れるようパーミッションを設定する。
尚、システムに登録されているユーザのホームディレクトリに証明書を作成すると、nginxのインストール直後に実行するnixos-rebuild switchコマンドの処理の中で、最後に自動で実行されるsystemctl start nginx.serviceがエラーを吐いて終了する。

[testsv99:~ ]# sudo mkdir /var/www
[testsv99:~ ]# sudo chown hechtia /var/www
[testsv99:~ ]# sudo chgrp users /var/www
[testsv99:~ ]# sudo chmod 777 /var/www

 
これより、上記で作成したディレクトリ内に移動し、自己証明書を作成する。
まず最初にopenssl genpkeyコマンドを叩いてRSA秘密鍵を作成する。オプション-aes-256-cbcを付けて実行する事で、パスワードを設定する事が出来る。

[testsv99:~ ]# cd /var/www
[testsv99:/var/www ]# 
[testsv99:/var/www ]# openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -aes-256-cbc -out privkey.pem
.....+...+..+...+.............+..+......+..........+...........+.+..+...+++++++++++++++++++++++++++++++++++++++*
........+......+.....+......+.........+++++++++++++++++++++++++++++++++++++++*...+......+.....+.+.....+...........
.......+.+....................+......+....+..+..........+..+...+.........+....+.....+.......+...+..+.......+..+.+..................+.....+.+...+..
+.+..+...+...+......+.+...++++++.+......+...+...+.........+.....+...+.+..+...................+.....+..................+...+.........+...++
+++++++++++++++++++++++++++++++++++++*..+.....+...+.............+..+.+.........+..+....+.....+.........+......+..
....+.........+............+...+....+.....+..................+....+......+...+..+...+....+...+.........+.....+.+..+......+.......+..+..........+..
.+++++++++++++++++++++++++++++++++++++++*...........+.......+..+......+.+.........+.....+......+.+.....+.........
.+...+.........+..+..........+...+.....+.+.........+.....+...+...+...............+.+.........+..+....+...+...+........+....+..+.+........+....+
..+...................+..+...+.+......+...+...........+...+.+.....+..........+.....+.+.....+.+..+......+.+......+........+....+...+............+
.....+.......+......+.....+...+....+...+...............+........+....+..++++++
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
[testsv99:/var/www ]#

 
続いて、上記で作成したRSA秘密鍵を使用し証明書署名要求を作成する。
LocationやFQDNなどが聞かれるが、家庭内環境での利用に留める為に必要最低限な設定にした。

[testsv99:/var/www ]# openssl req -new -key privkey.pem -out csr.pem
Enter pass phrase for privkey.pem:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:TOKTO
Locality Name (eg, city) []:UNKNOWN
Organization Name (eg, company) [Internet Widgits Pty Ltd]:UNKNOWN
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:testsv99.local
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
[testsv99:/var/www ]#

 
上記で作成した証明書署名要求を元に自己証明書を作成する。
オプションx509を付ける事で自己署名な証明書となる。有効期限は10年間とする。

[testsv99:/var/www ]# openssl x509 -req -in csr.pem -signkey privkey.pem -days 3650 -out crt.pem
Enter pass phrase for privkey.pem:
Certificate request self-signature ok
subject=C=JP, ST=TOKTO, L=UNKNOWN, O=UNKNOWN, CN=testsv99.local
[testsv99:/var/www ]# 

 
最後に、パスワードのファイルを作成する。
パスワードの文字列が丸見えなので、当記事内ではアスタリスクに変換している。
パスワードファイルの作成後、上記で作成したファイルをnginxが読み取れるようにパーミッションを設定する。

[testsv99:/var/www ]# echo ******** > /var/www/password
[testsv99:/var/www ]# 
[testsv99:/var/www ]# chmod 755 /var/www
[testsv99:/var/www ]# ls -la
total 24
drwxr-xr-x  2 hechtia users 4096 May  2 19:56 .
drwxr-xr-x 10 root    root  4096 May  2 19:49 ..
-rw-r--r--  1 hechtia users 1245 May  2 19:55 crt.pem
-rw-r--r--  1 hechtia users  989 May  2 19:54 csr.pem
-rw-r--r--  1 hechtia users    9 May  2 19:56 password
-rw-r--r--  1 hechtia users 1886 May  2 19:53 privkey.pem
[testsv99:/var/www ]# 
[testsv99:/var/www ]# cd                  
[testsv99:~ ]# 

 


nginxのインストールと設定

1. nginxのインストール
自己証明書の準備が出来たところで、nginxの導入設定およびnginxの設定に進む。
/etc/nixos/configuration.nixファイル内の上の方に有るimportsの項目にて、nginxの設定ファイル/etc/nixos/nginx.nixを読み込ませる設定を追記する。
ただし、/etc/nixos/nginx.nixファイル作成せず/etc/nixos/configuration.nixファイル内にnginxの設定を書く場合は、/etc/nixos/configuration.nixファイルにnginx.nixを追記する必要は無い。

[testsv99:~ ]# sudo nvim /etc/nixos/configuration.nix
# Edit this configuration file to define what should be installed on
# your system.  Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running ‘nixos-help’).

{ config, pkgs, ... }:

{
  imports =
    [ # Include the results of the hardware scan.
      ./hardware-configuration.nix
      ./ssh.nix
      ./zsh.nix
      ./nvim.nix
      ./chrony.nix
      ./nginx.nix ◻️◻️追記
    ];
:
省略
:

 
同じく/etc/nixos/configuration.nixファイル内にて、以下のようにnginxパッケージとcacertパッケージのインストールの設定を追記する。

  # List packages installed in system profile. To search, run:
  # $ nix search wget
  environment.systemPackages = with pkgs; [
  #  vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default.
    zsh
    neovim
    chrony
    openssl
    nginx ◻️◻️追記
    cacert ◻️◻️追記
  ];
:
省略
:

 
NixOSでファイアウォール設定を使用している場合、/etc/nixos/configuration.nixファイル内にポートを追記する。
ファイアウォール設定を有効にしていない環境では以下の設定が無くてもWebサーバにアクセスが可能である。
・nginx:TCP/80(HTTP)、TCP/443(HTTPS)
・ssh:TCP/22(SSHアクセスが不要な環境では不要)
・chrony:TCP/123(chronyの未導入な環境では不要)

:
省略
:
  # Open ports in the firewall.
  # networking.firewall.allowedTCPPorts = [ ... ];
  # networking.firewall.allowedUDPPorts = [ ... ];
  # Or disable the firewall altogether.
  networking.firewall.enable = true;   ◻️◻️コメントアウトを外しfalseをtrueに修正
  networking.firewall.allowPing = true;  ◻️◻️追記
  networking.firewall.interfaces."enp0s3".allowedTCPPorts = [ 22 80 443 ];  ◻️◻️追記
  networking.firewall.interfaces."enp0s3".allowedUDPPorts = [ 123 ];  ◻️◻️追記
:
省略
:

 

2. nginxの設定およびビルド
NixOSにおけるnginxの設定ファイル、/etc/nixos/nginx.nixファイルを作成する。
テストページや上記にて作成した自己証明書関連の設定も、/etc/nixos/nginx.nixファイルで完結させる事が出来る。
当環境では公開ディレクトリを/var/www/testとしている。上記にて言及しているとおり自己証明書は/var/wwwディレクトリ直下に置かれているので、本来であれば自己証明書は別のディレクトリに置くのが望ましいだろう。
 
自己証明書を使用しnginxをビルドすると、systemctl status nginx.serviceを叩いた際にnginx: [warn] "ssl_stapling" ignored...のログが出力される。このログが出力されてもWebサーバ自体は動作するが、出力を抑えるにはsl_stapling offとssl_stapling_verify offの設定を入れる必要がある。

[testsv99:~ ]# sudo nvim /etc/nixos/nginx.nix 
{
  services.nginx = {
    enable = true;
    recommendedTlsSettings = true;
    virtualHosts."testsv99.local" = {
       root = "/var/www/test";
       locations."/" = {
         return = "200 '<html><body><font size=15><center>NixOS and nginx</center></font></body></html>'";
	 extraConfig = ''
	   default_type text/html;
	   '';
	 };
       addSSL = true;
       sslCertificate = "/var/www/crt.pem";
       sslCertificateKey = "/var/www/privkey.pem";
       extraConfig = ''
         ssl_password_file "/var/www/password";
	 ssl_prefer_server_ciphers on;
	 ssl_stapling off;
	 ssl_stapling_verify off;
	 '';
       };
    };
}
[testsv99:~ ]#

 
設定を終えたら、sudo nixos-rebuild switchコマンドを叩きnginxのインストールおよびビルドを実行する。
/etc/nixos/configuration.nixファイルや/etc/nixos/nginx.nixファイルの内容に問題が無ければ、ビルドの途中で出力されるResultsはNo issues found、Summaryはカウント無しとなる。
 
しかしまだ安心は出来ない。ビルドの最後にthe following new units were started: nginx.serviceが出力されてnginxのサービスが正常に立ち上がった事を確認出来たら、nginxのインストールと設定が完了となる。

[testsv99:~ ]# sudo nixos-rebuild switch
building Nix...
building the system configuration...
these 28 derivations will be built:
  /nix/store/02l41hl5wnwbzw4gqpy146cxyp4ysvgl-system-path.drv
  /nix/store/cxjj3vc6kxqkqbskgq05m5c2c73y6sb4-nixos.conf.drv
:
省略
:
==================== Results ===================
No issues found.

==================== Summary ===================
Total issues:
    Unspecified: 0
    Low: 0
    Medium: 0
    High: 0
:
省略
:
reloading user units for hechtia...
restarting sysinit-reactivation.target
reloading the following units: dbus.service, firewall.service
starting the following units: logrotate-checkconf.service, systemd-modules-load.service, systemd-tmpfiles-resetup.service
the following new units were started: nginx.service
[testsv99:~ ]# 

 
sudo systemctl status nginx.serviceコマンドを叩き、nginxサービスの動作を確認。Active: active (running)になっている事からnginxサービスは正常に起動している事を確認出来た。
これでnginxのインストールは完了。お疲れ様でした。
 
ログの中に/nix/store/w6lnj2qhaddw32vivlr5jyd84xf71qx6-nginx.confというファイルが見えるが、これはnginxを設定しビルドした際に生成されるファイルであり、NixOSはこれをシンボリックリンクで参照する。他のパッケージも同様に、.nixファイルを直接読み取ってnginxを動作させているのではない。

[testsv99:~ ]# sudo systemctl status nginx.service
● nginx.service - Nginx Web Server
     Loaded: loaded (/etc/systemd/system/nginx.service; enabled; preset: ignored)
     Active: active (running) since Fri 2025-05-02 20:38:58 JST; 1min 15s ago
 Invocation: 3a22a98df6b14489a70cd195e938ab29
    Process: 4396 ExecStartPre=/nix/store/1xg06zbim3hk70slqxm3l3scnv4hjrpi-unit-script-nginx-pre-start/bin/nginx-pre-start (code=exited, status=0/SUCCESS)
   Main PID: 4399 (nginx)
         IP: 0B in, 0B out
         IO: 0B read, 0B written
      Tasks: 2 (limit: 4662)
     Memory: 2.6M (peak: 3.8M)
        CPU: 97ms
     CGroup: /system.slice/nginx.service
             ├─4399 "nginx: master process /nix/store/msswcm5a2icdji217x4r2wx3rkjbcx60-nginx-1.26.3/bin/nginx -c /nix/store/w6lnj2qhaddw32vivlr5jyd84xf71qx6-nginx.conf"
             └─4400 "nginx: worker process"

May 02 20:38:58 testsv99 systemd[1]: Starting Nginx Web Server...
May 02 20:38:58 testsv99 nginx-pre-start[4397]: nginx: the configuration file /nix/store/w6lnj2qhaddw32vivlr5jyd84xf71qx6-nginx.conf syntax is ok
May 02 20:38:58 testsv99 nginx-pre-start[4397]: nginx: configuration file /nix/store/w6lnj2qhaddw32vivlr5jyd84xf71qx6-nginx.conf test is successful
May 02 20:38:58 testsv99 systemd[1]: Started Nginx Web Server.
[testsv99:~ ]# 

 


Webサーバの動作確認
nginxの設定を終えたところで、クライアント側にてWebブラウザを立ち上げてWebサーバにアクセスし、上記で設定したテストページ(NixOS and Nginx)がWebブラウザで表示されるか確認する。
確認用のWebブラウザとして、普段利用しているFirefoxの他にGoogle ChromeとMicrosoft Edgeを使用した。
 
WebブラウザからWebサーバにアクセスすると、当環境のWebサーバでは自己証明書を使用している為、Firefoxでは初回アクセスの時に「警告:潜在的なセキュリティリスクあり」が表示される。「詳細へ進む」をクリックし、更に「自己署名をしているためこの証明書は信頼されません」が表示されるが「危険性を承知の上で使用」をクリックすると、今回構築したテスト用のページが表示される。
同様の警告は他のWebブラウザGoogle ChromeとMicrosoft Edgeでも表示される為、Firefoxと同じような手順を辿ってテストページを表示させる。
 
以下の画像のとおり、3つのWebブラウザ共にテストページを表示させる事が出来た。


 

今回はここまで。
元々は以前に当ブログにて公開したメールサーバの構築の記事のようにSSL無しとSSL有りの両方の記事を作成する予定だったが、SSL無しのnginxの構築はあっけなく完了し非常に寂しい内容となった為、今回はSSL有りの1本で記事を作成し公開した。
nginxに読み込ませるファイルの設定で苦戦した。サーバの自己証明書が読み込めてもパスワードファイルが読み込めないとnginxは正常に起動出来ない。パスワードファイルを読み込ませる為のNixのオプションが分からなかった為、extraConfigの中にssl_password_fileを書いて強引にパスワードファイルを読み込ませた。
 


振り返り
気が付けば、NixOSに触れ始めてから2ヶ月が経とうとしている。決して多忙ではないもののクタクタな業務環境が続く中で、NixOSの独特な設計思想や設定方法は非常に良い気分転換となった。今後も利用するつもりなので、お礼の意味を込めてNixOS Foundationに対し僅かながらではあるが寄付をした。
NixOSネタは当投稿で13連投目。もはや当Blogのカテゴリ「かじってみた」の段階ではないな...
 


参照サイト
https://nixos.org/ Nix & NixOS Declarative builds and deployments
https://nixos.org/manual/nixos/stable/ NixOS Manual
https://search.nixos.org/packages NixOS Search Packages
https://search.nixos.org/options? NixOS Search Options
https://nixos.wiki/wiki/Nginx NixOS Wiki - Nginx
https://wiki.nixos.org/wiki/Nginx NixOS Wiki - Nginx
https://nixos.org/donate/ NixOS - Donate
https://nginx.org/en/ nginx
https://www.f5.com/ja_jp/products/nginx/nginx-plus F5 NGINX Plus
https://qiita.com/kaznak/items/923a353c88b252adbced NixOS で PHP 環境作ったった - Qiita
https://qiita.com/ohakutsu/items/814825a76b5299a96661 Nginxに自己署名証明書を設定してHTTPS接続してみる - Qiita
https://www.server-world.info/query?os=CentOS_Stream_9&p=nginx&f=1 Server World - CentOS Stream 9 - Nginx
  


NixOS関連の記事
https://debslink.hatenadiary.jp/entry/20250311/1741649715 NixOSの沼に片足を突っ込んだ
https://debslink.hatenadiary.jp/entry/20250316/1742128054 NixOSにFlakeを導入した
https://debslink.hatenadiary.jp/entry/20250320/1742459549 NixOSの環境構築
https://debslink.hatenadiary.jp/entry/20250323/1742731080 NixOSでSFTPサーバの設定
https://debslink.hatenadiary.jp/entry/20250328/1743167901 NixOSでSambaによるファイルサーバの構築
https://debslink.hatenadiary.jp/entry/20250405/1743844940 NixOSでrsyslogの設定
https://debslink.hatenadiary.jp/entry/20250411/1744300480 NixOSでDNSサーバの構築
https://debslink.hatenadiary.jp/entry/20250413/1744551596 NixOSのシステムの再現性の検証
https://debslink.hatenadiary.jp/entry/20250418/1744924524 NixOSでPostfixとDovecotによるメールサーバの構築
https://debslink.hatenadiary.jp/entry/20250419/1745062553 NixOSでPostfixとDovecotによるメールサーバの構築 - SASL認証編
https://debslink.hatenadiary.jp/entry/20250421/1745236668 NixOSのパッケージやOSのアップデートに関するメモ
https://debslink.hatenadiary.jp/entry/20250428/1745795434 NixOSをCLIでインストールした
https://debslink.hatenadiary.jp/entry/20250503/1746235454 NixOSでnginxによるWebサーバの構築
https://debslink.hatenadiary.jp/entry/20250508/1746706416 NixOSでPrometheusとGrafanaによる監視基盤の構築
https://debslink.hatenadiary.jp/entry/20250510/1746884897 NixOSの導入にあたり参考になったサイト
https://debslink.hatenadiary.jp/entry/20250524/1748072722 NixOSを24.11から25.05にアップデートした
https://debslink.hatenadiary.jp/entry/20251214/1765688458 NixOSを25.05から25.11にアップデートした
https://debslink.hatenadiary.jp/entry/20260117/1768615582 Raspberry Pi 4BにNixOSを導入しファイルサーバを構築した
https://debslink.hatenadiary.jp/entry/20260503/1777775392 NixOSで構築したサーバの運用について