WSLにNginxとPHPを入れてPukiwikiを立てる手順(2022.12時点)

# 記事の内容
　Windows11上の WSL2 の上に nginx+php-fpm を導入し、さらに Pukiwiki のサイトを作ってみる作業手順のメモです。WSL調査の一環となります。検索すると同様のことをしている記事はいくつかあるようなのですが、すでに情報が古くなっているようなので現時点(2022.12)で行った作業手順を一通りメモしておきます。
　最近は情報共有やナレッジ管理の手段としては Wiki よりも Notion や Obsidian などのMarkdownを使えるツールが好まれるようになってきているようですが、それらについてはまた別途調べようと思います。個人的には、Wikiも手軽に使えてまだまだ役立つと思っています。

# 使用したバージョン
* Windows
エディション	Windows 11 Pro
バージョン	22H2
OS ビルド	22621.963
エクスペリエンス	Windows Feature Experience Pack 1000.22638.1000.0

* WSLとディストリビューション
```:コンソール
C:\>wsl --version
WSL バージョン: 1.0.3.0
カーネル バージョン: 5.15.79.1
WSLg バージョン: 1.0.47
MSRDC バージョン: 1.2.3575
Direct3D バージョン: 1.606.4
DXCore バージョン: 10.0.25131.1002-220531-1700.rs-onecore-base2-hyp
Windowsバージョン: 10.0.22621.963

C:\>wsl -l -v
  NAME                   STATE           VERSION
* Ubuntu                 Running         2
```

* Ubuntu
```: WSL/Ubuntu
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04.5 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.5 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal
```
* Pukiwiki
 [Pukiwiki 1.5.4 (UTF-8版)](https://pukiwiki.osdn.jp/?PukiWiki/Download/1.5.4)

https://pukiwiki.osdn.jp/?PukiWiki/Download/1.5.4

# nginx/php-fpmのインストール
 まずnginxと php-fpm をインストールします。
nginxについてはさすがに説明不要かと思いますが、最近流行のWebサーバです。[C10K問題](https://yohei-a.hatenablog.jp/entry/20120504/1336157667)(リクエストが増えるとプロセスがリソースを消費して性能に影響するという問題)に強いと言う特徴があり人気です。php-fpm とはPHPのFastCGI実装の一つです。FPM=FastCGI Process Manager です。
 FastCGIとは、Webサーバ上でユーザプログラムを動作させるためのインタフェース仕様の一種です。通常のCGIだとリクエスト毎にPHPのプロセスが立ち上がるのを、FastCGIでは一度起動したプロセスをメモリ上に保持しておいて処理効率を良くするというものです。WebサーバからPHPを実行する場合、Apacheでは動作方式によってモジュール版とCGI版という２種類の実行方法があります。nginxの場合はCGI版しかありません。モジュールとCGIの違いは、Webサーバのプロセスの一部として動作するのが前者、Webサーバとは別プロセスとして動作するのが後者です。

インストールコマンドは以下の通りです。当然ながら外部ネットワークへの接続環境は必要です。
```:WSL
$ sudo apt-get install nginx php-fpm
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages were automatically installed and are no longer required:
  libfwupdplugin1 libxmlb1
Use 'sudo apt autoremove' to remove them.
The following additional packages will be installed:
  libgd3 libnginx-mod-http-image-filter libnginx-mod-http-xslt-filter libnginx-mod-mail libnginx-mod-stream nginx-common nginx-core php-common php7.4-cli php7.4-common
  php7.4-fpm php7.4-json php7.4-opcache php7.4-readline
Suggested packages:
  libgd-tools fcgiwrap nginx-doc ssl-cert php-pear
The following NEW packages will be installed:
  libgd3 libnginx-mod-http-image-filter libnginx-mod-http-xslt-filter libnginx-mod-mail libnginx-mod-stream nginx nginx-common nginx-core php-common php-fpm php7.4-cli
  php7.4-common php7.4-fpm php7.4-json php7.4-opcache php7.4-readline
0 upgraded, 16 newly installed, 0 to remove and 0 not upgraded.
Need to get 4695 kB/4813 kB of archives.
After this operation, 20.7 MB of additional disk space will be used.
Do you want to continue? [Y/n] Y
Get:1 http://archive.ubuntu.com/ubuntu focal-updates/main amd64 nginx-common all 1.18.0-0ubuntu1.4 [37.7 kB]
・・・（以下略）

$ sudo apt autoremove
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages will be REMOVED:
  libfwupdplugin1 libxmlb1
0 upgraded, 0 newly installed, 2 to remove and 0 not upgraded.
After this operation, 628 kB disk space will be freed.
Do you want to continue? [Y/n] Y
(Reading database ... 36545 files and directories currently installed.)
Removing libfwupdplugin1:amd64 (1.5.11-0ubuntu1~20.04.2) ...
Removing libxmlb1:amd64 (0.1.15-2ubuntu1~20.04.1) ...
Processing triggers for libc-bin (2.31-0ubuntu9.9) ...
```
メッセージに従いインストール後に不要なライブラリを削除(apt autoremove)しています。

## インストールされたnginxとPHPのバージョンを確認する
以下の通りです。
```:WSL
$ nginx -v
nginx version: nginx/1.18.0 (Ubuntu)

$ php -v
PHP 7.4.3 (cli) (built: Nov  2 2022 09:53:44) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v7.4.3, Copyright (c), by Zend Technologies
```

## nginxの設定を行う
VSCode でWSLに接続します。やり方は[以前の記事](https://qiita.com/smats-rd/items/e65feae601b4496be381#vscode%E3%81%A7%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%82%92%E8%B5%B7%E5%8B%95)でも書きましたので必要ならばご参照ください。
VSCode で /etc/nginx/sites-available/default を開き、編集します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2261111/97e90274-ec65-0370-5ca6-ea7ffd430ef4.png)
ここで、なぜ編集する設定ファイルがnginx.confではないのでしょうか。その理由は、nginx の設定ファイルにはその用途に応じて種類があり、置き場所が違うからです。

|置き場所とファイル名|用途|
|----|----|
|/etc/nginx/nginx.conf|一番大本の設定ファイル。これに全部設定を書いても良い（その代わり各設定が長くて読みにくくなる）。普通は他の設定ファイルをこのファイルからインクルードして使う。|
|/etc/nginx/conf.d/*.conf|デフォルトの設定を上書きする設定を記述するファイルの置き場。/etc/nginx/conf.d/配下に*.confという名前の設定ファイルを作成すると、設定を追加できる。インストール直後は空。|
|/etc/nginx/modules-available/*.conf|モジュール用soファイルの置き場所を書いた設定ファイルを置いておく場所（だと思うが、実際には何も置かれておらず、意図不明）。|
|/etc/nginx/modules-enabled/*.conf|モジュール用soファイルの置き場所を書いた設定ファイルへのシンボリックリンクをここから貼っておくとモジュールが読み込まれる。そう聞くと上に書いたようにシンボリックリンク先の実ファイルがmodules-availableディレクトリの下にあるのかと思いきや、そこには置かれず実際のconfファイルは/usr/share/nginx/modules-available にあるようで、意味がわからない。|
|/etc/nginx/sites-available/default|バーチャルホストの追加設定を記述するファイルを置いておく。運用したいドメインごとに\<domain名\>.confファイルを作成して設定を記述する。defaultファイルと言うのは文字通りどのドメインにも共通のデフォルト値を入れるものらしい。最初にnginxをインストールした時点で作られている。今回はこれを書き換える。|
|/etc/nginx/sites-enabled/*.conf|/etc/nginx/sites-available/配下のファイルへのシンボリックリンクを貼る。設定を無効にしたい場合はシンボリックリンクを削除すれば、設定ファイルは/etc/nginx/sites-availableに残したままにできる…ということなのだが、直接sites-availebleにあるファイルをインクルードしてはなぜいけないのだろうか？これもよくわからないが、そういうルールらしい。|

ls してみると確かにシンボリックリンクになっています。
```: WSL
$ ll sites-enabled/
total 8
drwxr-xr-x 2 root root 4096 Dec 26 14:40 ./
drwxr-xr-x 8 root root 4096 Dec 26 14:40 ../
lrwxrwxrwx 1 root root   34 Dec 26 14:40 default -> /etc/nginx/sites-available/default
```

defaultファイルの中身
``` conf: default
server {	
    listen 80 default_server;	
    listen [::]:80 default_server;	
	
    # SSL configuration	
    #	
    # listen 443 ssl default_server;	
    # listen [::]:443 ssl default_server;	
    #	
    # Note: You should disable gzip for SSL traffic.	
    # See: https://bugs.debian.org/773332	
    #	
    # Read up on ssl_ciphers to ensure a secure configuration.	
    # See: https://bugs.debian.org/765782	
    #	
    # Self signed certs generated by the ssl-cert package	
    # Don't use them in a production server!	
    #	
    # include snippets/snakeoil.conf;	

    # html を置く場所のルート。今回はここへPukiwikiを置く。	
    root /var/www/html;	
	
    #ここに index.php を追加する。
    # Add index.php to the list if you are using PHP　
    index index.php index.html index.htm index.nginx-debian.html;	
	
    # ここは適当にホスト名やドメイン名、IPアドレスに書き換えてもよい
    # server_name _;	
    server_name localhost;	
	
    # ここは書き換えない
    location / {	
        # First attempt to serve request as file, then	
        # as directory, then fall back to displaying a 404.	
        try_files $uri $uri/ =404;	
    }	
	
    # pass PHP scripts to FastCGI server	
    # ブロックのコメントを外し、php-fpm.sock ファイルのパスを実際の位置に合わせる。
    location ~ \.php$ {	
        include snippets/fastcgi-php.conf;	
	
        # With php-fpm (or other unix sockets):	
        # fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; ←最初こうなっていたために502エラーになった
        fastcgi_pass unix:/run/php/php7.4-fpm.sock;
    }	
	
    # deny access to .htaccess files, if Apache's document root	
    # concurs with nginx's one	
    # comment out here 2022.12.26	
    location ~ /\.ht {	
        deny all;	
    }	
}	
```
ここで注意する点として、コメントにあるように fastcgi_pass unix: の後に php7.4-fpm.sock への正しいパスを記載する必要があります。（※どうやってこの場所を調べたかは後述します。）
php7.4-fpm.sock と言うのはUNIXドメインソケットと呼ばれる、一種のエンドポイントを表すファイルです。「UNIX系OSに共通する機能やプログラム仕様を定めた標準規格「POSIX（Portable Operating System Interface）」に準拠した標準コンポーネント」とのことです。UNIXではソケットなどの通信もファイルと同じように扱おうという思想があるので、プロセス間通信の接続先を .sock ファイルとして表現できるようになっているのだと思われます。

https://qiita.com/toshihirock/items/b643ed0edd30e6fd1f14

設定に文法的な間違いがないかをチェックできます。問題なければ以下のようになります。

```:WSL
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
```

nginx を起動します。
```:WSL
$ sudo service nginx start
 * Starting nginx nginx   [ OK ]
```

php-fpm を起動します。（※ここで、今回はたまたまバージョンが7.4なのでphp7.4-fpmとしていますが、違うバージョンなら当然そのバージョンに合わせる必要がありますのでご注意下さい。）
```:WSL
$ sudo service php7.4-fpm start
$
```
何も表示されませんが、これで成功しているらしいです。

ブラウザで http://localhost へ接続してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2261111/0fb50259-a095-f0c3-1e7a-3139a29da1af.png)
Welcomeページが表示されましたので、nginx は問題なく起動できたようです。

次に、phpが正しく動くか確認するため、以下のようなファイルを作成し、/var/www/html に置いてみました。PHP動作確認の定番のやり方です。
``` php: info.php
<?php phpinfo(); ?>			
```
しかしこれは 502 エラーになってしまいました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2261111/052dadc1-ac77-6d3f-4977-564a77fbfdf7.png)
後でわかりましたが、これは上で書いた default 設定での php-fpm のUNIXドメインソケットへのパスが間違っていたためでした。nginxとphp-fpm とのプロセス間通信に失敗したためこのようなエラーになっています。

## php-fpmのエラー原因を調査
調査のため、systemctl status コマンドでサービスの状態を確認してみます。ところが…
```:WSL
$ sudo systemctl status nginx
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down
```
調べてみると、どうもWSLではデフォルトで systemd が起動していないためにこうなるようです。これへの対応は、/etc/wsl.conf というファイルを作成し、中身を以下のように記述します。
``` conf: wsl.conf
[boot]
systemd=true
```
次に、いったんWSLから抜けて、WSLを再起動します。
```:コンソール
C:\> wsl --shutdown
C:\> wsl
```
これによって、systemctl status が動作するようになります。
``` : WSL
$ systemctl status nginx											
● nginx.service - A high performance web server and a reverse proxy server											
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)											
     Active: active (running) since Mon 2022-12-26 18:29:03 JST; 5min ago											
       Docs: man:nginx(8)											
   Main PID: 355 (nginx)											
      Tasks: 9 (limit: 9455)											
     Memory: 15.2M											
     CGroup: /system.slice/nginx.service											
             ├─355 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;											
             ├─356 nginx: worker process											
             ├─357 nginx: worker process											
             ├─358 nginx: worker process											
             ├─359 nginx: worker process											
             ├─360 nginx: worker process											
             ├─361 nginx: worker process											
             ├─362 nginx: worker process											
             └─363 nginx: worker process	
										
$ systemctl status php7.4-fpm				
● php7.4-fpm.service - The PHP 7.4 FastCGI Process Manager				
     Loaded: loaded (/lib/systemd/system/php7.4-fpm.service; enabled; vendor preset: enabled)				
     Active: active (running) since Tue 2022-12-27 10:17:30 JST; 9s ago				
       Docs: man:php-fpm7.4(8)				
    Process: 5811 ExecStartPost=/usr/lib/php/php-fpm-socket-helper install /run/php/php-fpm.sock /etc/php/7.4/fpm/pool.d/www.conf 74 (code>				
   Main PID: 5808 (php-fpm7.4)				
     Status: "Ready to handle connections"				
      Tasks: 3 (limit: 9455)				
     Memory: 8.5M				
     CGroup: /system.slice/php7.4-fpm.service				
             ├─5808 php-fpm: master process (/etc/php/7.4/fpm/php-fpm.conf)				
             ├─5809 php-fpm: pool www				
             └─5810 php-fpm: pool www				
				
Dec 27 10:17:30 XXXX systemd[1]: Starting The PHP 7.4 FastCGI Process Manager...				
Dec 27 10:17:30 XXXX systemd[1]: Started The PHP 7.4 FastCGI Process Manager.				
```
nginxもphp-fpmも正常動作しているように見えます。

## fpm の設定ファイルを確認
ここで念のため、fpm の設定ファイルを確認しておきます。
``` conf: /etc/php/7.4/fpm/pool.d/www.conf
; Start a new pool named 'www'.
; the variable $pool can be used in any directive and will be replaced by the
; pool name ('www' here)
[www]

; Per pool prefix
; It only applies on the following directives:
; - 'access.log'
; - 'slowlog'
; - 'listen' (unixsocket)
; - 'chroot'
; - 'chdir'
; - 'php_values'
; - 'php_admin_values'
; When not set, the global prefix (or /usr) applies instead.
; Note: This directive can also be relative to the global prefix.
; Default Value: none
;prefix = /path/to/pools/$pool

; Unix user/group of processes
; Note: The user is mandatory. If the group is not set, the default user's group
;       will be used.
user = www-data
group = www-data

; The address on which to accept FastCGI requests.
; Valid syntaxes are:
;   'ip.add.re.ss:port'    - to listen on a TCP socket to a specific IPv4 address on
;                            a specific port;
;   '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on
;                            a specific port;
;   'port'                 - to listen on a TCP socket to all addresses
;                            (IPv6 and IPv4-mapped) on a specific port;
;   '/path/to/unix/socket' - to listen on a unix socket.
; Note: This value is mandatory.
listen = /run/php/php7.4-fpm.sock
```
この最後の行に注目です。さきほど nginx の設定ファイルに書いた sock ファイルのパスと微妙に異なっています。これにより502エラーが発生していたと思われます。

``` : default（nginxの設定ファイル）
location ~ \.php$ {	
 ...
    誤：fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
    正：fastcgi_pass unix:/run/php/php7.4-fpm.sock;
}
```
いやらしい点は、この２つのどちらのパスにも該当の sock ファイルは存在していることです。しかしプロセス間通信の送信側と受信側の両方で、sockファイルのパスは合っている必要があるようです。今回はこれが合っていなかったので通信が失敗したということです。
defaultファイルを修正してnginxをリスタートし、再度info.phpを表示してみると、今度は無事phpの実行結果が表示されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2261111/8563f856-8f4c-7d1e-8896-92c4f9d1c267.png)

これでnginx + PHP が動く状態になりましたので、Pukiwikiの導入へ進みます。

# Pukiwikiの導入
/var/www/html/wiki フォルダを作成し、そこへPukiwikiのソースをコピーします。ダウンロードした直後のファイルをWSLにコピーすると.Identifier という拡張子のついたファイルができるのですが、これは気にせず削除してしまって良いようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2261111/fde7d7f3-94d6-c065-3edb-9d29e95cfc24.png)
それだけで動くとは思っていませんでしたが、やはり単純にコピーしただけではダメらしいです。
Pukiwikiの初期設定ファイルを見ると、フォルダ名は下記のようになっています。
``` php: pukiwiki.ini.php
define('DATA_DIR',      DATA_HOME . 'wiki/'     ); // Latest wiki texts
define('DIFF_DIR',      DATA_HOME . 'diff/'     ); // Latest diffs
define('BACKUP_DIR',    DATA_HOME . 'backup/'   ); // Backups
define('CACHE_DIR',     DATA_HOME . 'cache/'    ); // Some sort of caches
define('UPLOAD_DIR',    DATA_HOME . 'attach/'   ); // Attached files and logs
define('COUNTER_DIR',   DATA_HOME . 'counter/'  ); // Counter plugin's counts
define('PLUGIN_DIR',    DATA_HOME . 'plugin/'   ); // Plugin directory
```										
これらのディレクトリの属性はコピー直後は644になっていますので書き込み権限がありません。エラーメッセージの通り not writable です。そこでこれらのディレクトリの属性を777にします。
```:WSL
sudo chmod 777 wiki diff backup cache attach counter plugin
```
再度表示してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2261111/8e1e5a79-5cf4-91ce-23d4-113fe448065b.png)

初期状態での表示ができました。
ここまで行けば、後は以下のようなPukiwikiの通常の初期設定をやればOKです。
* wikiディレクトリなどにあるデータファイルの属性は 666 とする。
* 管理パスワード($adminpass)の設定
* ユーザとパスワードの設定($auth_users)
* 編集用の認証の設定($edit_auth = 1;) をやるなら設定
* その他の設定を好みに合わせて設定
``` php: pukiwiki.ini.php
  ($page_title, $modifier, $modifierlink, $nowikiname)など
```
https://pukiwiki.osdn.jp/?PukiWiki/Install/%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E6%96%B9%E6%B3%95

## その他注意点
その他の注意点としてはエンコードがあります。Pukiwiki 1.4 系まではテキストデータのエンコードがEUCだったのでそれらのバージョンのPukiwikiデータを最新のUTF-8版に移行したい場合は、エンコードの移行処理をする必要があります。専用のツールが用意されているようなのでそれを使えばよいと思います。

https://pukiwiki.osdn.jp/dev/?EUC-JP+to+UTF-8

# 付記：WSL上に構築したサイトへそのPCの外側からアクセスするには
今回のようにWSL上に構築したWebサイトはデフォルトではそのWSLのあるPC上からしかアクセスできません。PCの外側（LAN上にある他のマシンなど）からアクセスしたい場合はまずファイアウォール設定でポート80を開けた上で、PC本体からWSL上の仮想マシンへポートフォワードをする必要があります。
ポートフォワードの手順は以下の通りです。

* WSLのIPｱﾄﾞﾚｽを確認する。
```:WSL
$ ifconfig	
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500	
        inet 192.168.232.248  netmask 255.255.240.0  broadcast 192.168.239.255	
        inet6 fe80::215:5dff:fefe:2b27  prefixlen 64  scopeid 0x20<link>	
        ether 00:15:5d:fe:2b:27  txqueuelen 1000  (Ethernet)	
        RX packets 49395  bytes 248386251 (248.3 MB)	
        RX errors 0  dropped 0  overruns 0  frame 0	
        TX packets 12908  bytes 951338 (951.3 KB)	
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0	
	
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536	
        inet 127.0.0.1  netmask 255.0.0.0	
        inet6 ::1  prefixlen 128  scopeid 0x10<host>	
        loop  txqueuelen 1000  (Local Loopback)	
        RX packets 60419  bytes 53268812 (53.2 MB)	
        RX errors 0  dropped 0  overruns 0  frame 0	
        TX packets 60419  bytes 53268812 (53.2 MB)	
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0	
```
WSLのIPアドレスが 192.168.232.248 であることがわかったので、netshでこのアドレスへポートフォワードします（管理者権限が必要です）。なおこのIPアドレスはWSLを再起動するたびに変わってしまうので、基本的に一時的なものであり長期間にわたって使えるようなものではありません。

```:コンソール
C:\>netsh interface portproxy add v4tov4 listenaddress=* listenport=80 connectaddress=192.168.232.248 connectport=80
C:\>netsh interface portproxy show all
ipv4 をリッスンする:         ipv4 に接続する:
Address         Port        Address         Port
--------------- ----------  --------------- ----------
*               80          192.168.232.248 80
```

これでPCの外側からWSL上に構築したPukiwikiにアクセスできます。アクセスの際のURLは上記WSLのアドレスではなく、WSLを動かしているPCのアドレス(コマンドラインでipconfigすると表示されるIPアドレス）を指定します。
ポートフォワード設定はPCを再起動しても消えませんので、削除したい場合は下記コマンドを打ちます。

```:コンソール
c:\>netsh interface portproxy delete v4tov4 listenport=80
```

今回は以上です。どなたかの参考になれば幸いです。

# 参考にした記事
https://qiita.com/ncore/items/f1f20addc29c0d6b9b79

https://qiita.com/kotarella1110/items/634f6fafeb33ae0f51dc

* nginxの設定ファイルについては下記ページの記述を参考にしました。

https://qiita.com/tomokon/items/e782636c1e5ec6b5dfdc