Redhat系OS + nginx + PHP + CGIついでにSSL環境の構築

目次

概要

タイトルにもあるように、このドキュメントはnginxをベースに新旧入り混じったweb環境を構築するための手順です。
今回は実際のサーバー環境について説明します。

導入背景と選定理由

さくらVPSサーバー環境で、CentOS + Apahce + PHP + CGI環境の運用がOSバージョンの期限切れでアップデートが必要となったため。

事前準備

独自ドメインを取得してください。

1. サーバー基礎設定

1.1 さくらVPSサーバーの作成とSSHログイン

1.2 swap領域の解放とパッケージ更新

VPSのRockylinuxはデフォルトでswap領域未設定なので、設定を追加します。
参考: Sakura VPSでswapを構築
https://manual.sakura.ad.jp/vps/os-packages/add-swapfile.html

# コマンド
free -h
→ Swap:             0B          0B          0B ならswap未設定。

sudo dd if=/dev/zero of=/swapfile bs=1M count=2048
→ 2GBぶんのswap領域作成。2147483648 byte copiedなどの表示を確認。

sudo chmod 600 /swapfile
sudo mkswap -L swap /swapfile
→ LABEL=swap, UUID=ふじこふじこ などの表示を確認。

sudo cp -p /etc/fstab /etc/fstab.org
echo "/swapfile none swap sw 0 0" | sudo tee -a /etc/fstab
→ /swapfile none swap sw 0 0 の表示を確認

→ /swapfile none swap sw 0 の表示を確認

tail -1 /etc/fstab
# 実機を再起動し、swap領域が確保されていることを確認。
free -h
→ Swap:          2.0Gi          0B       2.0Gi  になっていればOK

# インストール済パッケージの更新
sudo dnf -y update

1.3 epelリポジトリの追加と基本ユーザー設定

# インストール
sudo dnf -y install epel-release
sudo dnf -y install https://rpms.remirepo.net/enterprise/remi-release-10.rpm

2. WebサーバーとPHPの構築

2.1 nginxのインストールと実行ユーザー設定

# インストール
sudo dnf -y install nginx

# nginxを有効にする
sudo systemctl enable --now nginx
→ create symlinkを確認

# nginxのバージョンを隠す
sudo vi /etc/nginx/nginx.conf
# 29行目以降に追加(httpの枠内)
    server_tokens off;

# バーチャルホスト追加
sudo vi /etc/nginx/conf.d/virtual_host.conf

# 新規作成(サーバー名、ディレクトリはサンプル)
server {
    server_name  ai.record-holder.net;

    location / {
        root   /var/www/html/ai.record-holder.net/web;
        index  index.html index.htm index.php;
    }
}

# conf作成にともない、web用ディレクトリも作成
sudo mkdir -p /var/www/html/ai.record-holder.net/web

# ユーザーの作成
sudo useradd web-owner
sudo passwd web-owner
sudo id web-owner
→ uid=1001(web-owner) gid=1001(web-owner) groups=1001(web-owner) を確認

# グループnginxに実行ユーザーを追加
sudo usermod -G nginx web-owner
sudo id web-owner
→ uid=1001(web-owner) gid=1001(web-owner) groups=1001(web-owner),994(nginx)

# nginxのチェック
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を再起動
sudo systemctl restart nginx

# htmlファイルを作成
sudo vi /var/www/html/ai.record-holder.net/web/index.html

# 以下のソースを貼り付けて保存
<!DOCTYPE html>
<html>
<meta charset="UTF-8">
<body>
<h1>ai.record-holder.net</h1>
</body>
</html>

# URLにアクセス。<h1>内の文字が画面表示されていればOKです。
http://ai.record-holder.net

2.2 PHP/php-fpmのインストールと詳細設定

# PHPモジュールの利用可能バージョンを確認
sudo dnf list php
→ 以下の表示を確認
Available Packages
php.x86_64.   8.3.29-1.el10_1.   appstream

# 8.2にしたい場合、以下のようにバージョンを変更
sudo dnf module reset php
sudo dnf -y module enable php:8.2

# 8.3のままの場合、以下のインストールで。
sudo dnf -y install php

# PHPのデフォルトインストールを確認
sudo rpm -qa | grep php
→ 以下にリストアップされる。
php-common-8.3.29-1.el10_1.x86_64
php-fpm-8.3.29-1.el10_1.x86_64
php-cli-8.3.29-1.el10_1.x86_64
php-mbstring-8.3.29-1.el10_1.x86_64
php-pdo-8.3.29-1.el10_1.x86_64
php-xml-8.3.29-1.el10_1.x86_64
php-opcache-8.3.29-1.el10_1.x86_64
php-8.3.29-1.el10_1.x86_64

# 必要であれば追加インストール
sudo dnf -y install php-mysqlnd php-gd

# PHPの設定
sudo vi /etc/php.ini

# 以下の行を修正
## 518行目
display_errors = On
## 942行目
date.timezone = "Asia/Tokyo"

# php-fpmの設定
sudo vi /etc/php-fpm.d/www.conf

# 以下の行を修正
## 24行目
✕ user = apache
◯ user = web-owner    
## 26行目
✕ group = apache
◯ group = nginx
## 38行目(socketのパスを変更)
✕ listen = /run/php-fpm/www.sock
◯ listen = /var/run/php-fpm/php-fpm.sock
## 48、49行目
listen.owner = web-owner
listen.group = nginx
## 55行目 コメントアウト(しないと、ソケットはroot権限のまま)
✕ listen.acl_users = apache,nginx
◯ ;listen.acl_users = apache,nginx

# socket格納ディレクトリの権限をnginxに変更
sudo mkdir /var/run/php-fpm
sudo chown nginx:nginx /var/run/php-fpm

# php-fpmの状態を確認。loadedなら使用可能
sudo systemctl status php-fpm.service

2.3 nginxとPHPの連携・動作確認

# nginxとphp-fpmをまとめて再起動
sudo systemctl restart nginx php-fpm

# 状態の確認
sudo systemctl status nginx
→ activeであること
sudo systemctl status php-fpm
→ activeであること
ps aux | grep php
→ activeであることと、追加ユーザーがphp-fpmに紐づけられているか確認

# socket確認
cd /var/run/php-fpm & ls -l
→ 以下のようにphp-fpm.sockが作成されていればOKです。
-rw-r--r-- 1 root      root  5 Feb 10 16:00 php-fpm.pid
srw-rw---- 1 web-owner nginx 0 Feb 10 16:00 php-fpm.sock    

##バーチャルホストにPHP設定を追加、ブラウザでPHPが動くか確認
vi /etc/nginx/conf.d/virtual_host.conf

# 末尾の}の前行に以下を追加して、保存
location ~\.php$ {
    listen 80;
    root /var/www/html/ai.record-holder.net/web;
    fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_script_name;
    include fastcgi_params;
}

# nginxの設定に間違いないか確認後、リロード
sudo nginx -t
sudo systemctl reload nginx

# PHPファイル作成
sudo vi /var/www/html/ai.record-holder.net/web/phpinfo.php

# 以下のソースを貼り付けて保存
<?php phpinfo(); ?>

# URLにアクセス。PHPの環境情報が表示されていればOKです。
http://ai.record-holder.net/phpinfo.php

# セッション等の所有者をapache → nginxにする。これやらないとセッション作成できません。
sudo ls -l /var/lib/php/
→ 以下の設定を確認
drwxrwx--- 2 root apache 4096 Dec 15 06:17 opcache
drwxr-xr-x 2 root root   4096 Dec 15 06:17 peclxml
drwxrwx--- 2 root apache 4096 Jan  4 16:52 session
drwxrwx--- 2 root apache 4096 Dec 15 06:17 wsdlcache

# 所有者の変更
sudo chown -R root:nginx /var/lib/php/opcache
sudo chown -R root:nginx /var/lib/php/session
sudo chown -R root:nginx /var/lib/php/wsdlcache
sudo ls -l /var/lib/php/

# すぐにセッションを試したい方はリロード
sudo systemctl reload nginx

3. 拡張機能とセキュリティ設定(CGI/SSL)

3.1 fcgiwrapの導入とCGI環境の構築

# fcgiwrapがインストール可能か&配布元
dnf search fcgiwrap
dnf list fcgiwrap
→ 以下の検出があればインストール可能
fcgiwrap.x86_64    1.1.0-24.20181108git99c942c.el10_0    epel

# fcgiwrapインストール
sudo dnf -y install fcgiwrap

# fcgiwrapの設定

# 参考サイト
https://qiita.com/ftoshiki/items/48d1f7e3ec6641f403da
https://wiki.archlinux.jp/index.php/Nginx#CGI_.E3.82.92.E5.8B.95.E3.81.8B.E3.81.99

sudo cat /usr/share/doc/fcgiwrap/SETUP

# fcgiサービス、ソケットの設定ファイルをコピー&編集
sudo cp -p /usr/lib/systemd/system/fcgiwrap@.service /etc/systemd/system/fcgiwrap.service
sudo cp -p /usr/lib/systemd/system/fcgiwrap@.socket /etc/systemd/system/fcgiwrap.socket

sudo vi /etc/systemd/system/fcgiwrap.socket

# 以下を編集(前→後に変える)
[Unit]
Description=fcgiwrap Socket

[Socket]
前 ListenStream=/run/fcgiwrap/fcgiwrap-%i.sock
後 ListenStream=/run/fcgiwrap/fcgiwrap.sock
RuntimeDirectory=fcgiwrap
前 SocketUser=%i
後 SocketUser=web-owner
SocketMode=0660

[Install]
WantedBy=sockets.target

sudo vi /etc/systemd/system/fcgiwrap.service

# 以下を編集(新を追加、前→後に変える)
[Unit]
Description=Simple CGI Server
After=nss-user-lookup.target
新 Requires=fcgiwrap.socket

[Service]
EnvironmentFile=/etc/sysconfig/fcgiwrap
ExecStart=/usr/sbin/fcgiwrap ${DAEMON_OPTS} -c ${DAEMON_PROCS}
前 User=%i
後 User=web-owner

[Install]
前 Also=fcgiwrap@%i.socket
後 Also=fcgiwrap.socket
sudo systemctl list-unit-files | grep fcgiwrap

# fcgiwrapを利用可能にする
→ 以下の状態であること
fcgiwrap.service                             indirect        disabled
fcgiwrap@.service                            indirect        disabled
fcgiwrap.socket                              disabled        disabled
fcgiwrap@.socket                             disabled        disabled

sudo systemctl enable fcgiwrap
→ Created symlink '/etc/systemd/system/sockets.target.wants/fcgiwrap.socket' → '/etc/systemd/system/fcgiwrap.socket'.

sudo systemctl list-unit-files | grep fcgiwrap
→ 以下の状態。fcgiwrap.socketがenabledなこと
fcgiwrap.service                             indirect        disabled
fcgiwrap@.service                            indirect        disabled
fcgiwrap.socket                              enabled         disabled
fcgiwrap@.socket                             disabled        disabled

# ソケットの権限変更
sudo ls -l /run/fcgiwrap/fcgiwrap.sock
sudo chown web-owner:nginx /run/fcgiwrap/fcgiwrap.sock 

# systemdに設定を反映
sudo systemctl daemon-reload

# fcgiwrapサービス起動&状態確認
sudo systemctl start fcgiwrap
sudo systemctl status fcgiwrap
→ activeなことを確認

# Perlのインストール+シンボリックリンク+確認
sudo dnf -y install perl
sudo ln -s /usr/bin/perl /usr/local/bin/perl
whereis perl

# バーチャルホストに以下の設定を追加
sudo vi /etc/nginx/conf.d/virtual_host.conf

# 末尾の}の前行に以下を追加
location ~ \.cgi$ {
    root /var/www/html/ai.record-holder.net/web;
    fastcgi_pass   unix:/run/fcgiwrap/fcgiwrap.sock;
    fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include        fastcgi_params;
}

# 設定に問題ないか確認後リロード
sudo nginx -t
sudo systemctl reload nginx

# cgiファイルの作成
sudo vi /var/www/html/ai.record-holder.net/web/test.cgi
→ 以下の内容を貼り付け
#!/usr/bin/perl
print "Content-Type: text/html\n\n";
print "Hello perl !!";

# パーミッション、所有者の変更
ls -l /var/www/html/ai.record-holder.net/web/test.cgi
sudo chmod 755 /var/www/html/ai.record-holder.net/web/test.cgi
sudo chown web-owner:nginx /var/www/html/ai.record-holder.net/web/test.cgi

# 以下のURLにアクセスして「Hello perl !!」が表示できればOKです。
http://ai.record-holder.net/test.cgi

3.2 SSL証明書のインストールとHTTPS化

Let's Encryptをインストールします。

参考リンク
https://qiita.com/ten-056/items/e6b8c58918d6064e80cf
https://qiita.com/sk_35o37o/items/367874b70481e4267d21
https://qiita.com/shadowhat/items/449c82ec546d8c9ccc19

# snapインストール&有効化
sudo dnf -y install snapd
sudo systemctl enable --now snapd.socket
sudo ln -s /var/lib/snapd/snap /snap

# snap install coreを実行するとtoo earlyエラーが出る
<a target="_blank" href="https://www.quick-solutions.jp/snap-install-core_error/">https://www.quick-solutions.jp/snap-install-core_error/</a>

sudo snap install core
→ error: too early for operation, device not yet seeded or device model not acknowledged と出ることがある。数分時間をおいてから上記を実行すると上手くいくと思われる。

sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo certbot --version

# webの証明書を取得
sudo certbot certonly --webroot -w /var/www/html/ai.record-holder.net/web -d ai.record-holder.net

# Emailの入力
Enter email address or hit Enter to skip.
(Enter 'c' to cancel): 任意のメールアドレス                    

# 利用規約に同意
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at:
https://letsencrypt.org/documents/LE-SA-v1.6-August-18-2025.pdf
You must agree in order to register with the ACME server. Do you agree?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y

# メールアドレスの提供を求められる
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing, once your first certificate is successfully issued, to
share your email address with the Electronic Frontier Foundation, a founding
partner of the Let's Encrypt project and the non-profit organization that
develops Certbot? We'd like to send you email about our work encrypting the web,
EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: N

→ 以下のメッセージで登録成功
Account registered.
Requesting a certificate for ai.record-holder.net

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/ai.record-holder.net/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/ai.record-holder.net/privkey.pem
This certificate expires on 2026-05-11.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
* Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
* Donating to EFF:                    https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

# 念のためSSLの有効期限を確認
sudo certbot certificates

→ 以下のレスポンスとなることを確認
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Found the following certs:
Certificate Name: ai.record-holder.net
    Serial Number: 5755da673ec04281751e3eceb64aa646f05
    Key Type: ECDSA
    Identifiers: ai.record-holder.net
    Expiry Date: 2026-05-11 14:00:26+00:00 (VALID: 89 days)
    Certificate Path: /etc/letsencrypt/live/ai.record-holder.net/fullchain.pem
    Private Key Path: /etc/letsencrypt/live/ai.record-holder.net/privkey.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

# バーチャルホストのファイルにSSL設定を追加
sudo vi /etc/nginx/conf.d/virtual_host.conf

server {
    listen 80;
    #ここから
    listen 443 ssl;
    ssl_certificate     /etc/letsencrypt/live/ai.record-holder.net/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/ai.record-holder.net/privkey.pem;
    ssl_protocols   TLSv1.2 TLSv1.3;
    #ここまで
    server_name  ai.record-holder.net;
    (省略)
}

# 設定に問題ないか確認後リロード
sudo nginx -t
sudo systemctl reload nginx

# 以下のURLにアクセスしてal.record-holderが表示できればSSLはOKです。
https://ai.record-holder.net/

3.3 ディレクトリ権限の最適化と後片付け

# webディレクトリのオーナー、グループを変更
sudo chown -R web-owner:nginx /var/www/html/ai.record-holder.net/web

# パッケージの整理
sudo dnf clean all

サーバー設定あとがき

オリジナルのnginx.confを編集せず、バーチャルホストを作成すれば影響最小限だと思います。
nginx → PHP → fcgiwrap → SSLの順にインストールして、それぞれインストール後にnginxのconfファイルを編集してからnginxをリロードする流れです。
あと、nginxならではの設定変更がいくつかあり厄介です(笑)セッションの権限変更等忘れずに。
Basic認証や、.htaccessの代替対応については割愛します。