XServer VPSにCentOS Stream 10 + MariaDB + Nginx + PHP + Postfixを設定(2025年版)

XServer VPSを試したときの覚書。
Gemini 3 Pro Previewと対話。

環境: CentOS Stream 10


1.初期設定

VNSコンソールを起動する。
日本語キーボードになっているので英語配列に変更。
確認してus配列を読み込む。
# localectl status
# localectl list-keymaps
# loadkeys us

コンソールの設定ファイルを変更。
XKB* 変数は Xorg/キーボード設定用なので無視してOK。
# less /etc/vconsole.conf

KEYMAP=us

YUMアップデートして、ホスト名変更。
# dnf update
# hostnamectl set-hostname xserver01.hoge.jp
# hostnamectl status

Location確認。
# timedatectl status

IPアドレスとネットワークインターフェースを確認。
# ip a

SSHの設定の確認。
# less /etc/ssh/sshd_config

VPSパネルでパケットフィルタを設定。
SSH, WEBを追加する。

Windows TerminalからSSHでログインできるか確認。

SELinuxを確認して無効化する。
# getenforce
# less /etc/selinux/config

SELINUX=disabled

再起動
# reboot

どんなサービスが起動しているか確認。
# systemctl list-unit-files -t service

Gemini先生に聞いて、不要なサービスを停止する。
「cloud-*」はVPS環境では必須らしい。

  •  bluetooth.service: Bluetooth機器用。
  • smartd.service: HDD/SSDの物理的健康状態(S.M.A.R.T)を監視。
  • udisks2.service: 外付けディスクやUSBメモリなどを自動マウント・管理するためのデーモン(主にデスクトップ環境向け)。
  • multipathd.service: 複数の経路でストレージに接続する冗長化構成(SANなど)用。
  • libstoragemgmt.service: 外部ストレージアレイを管理するためのAPI。
  • sssd.service: LDAPやActive Directoryなどで認証統合を行うためのデーモン。ローカルのユーザーだけで管理するなら不要。
  • iscsi-onboot.service / iscsi-starter.service: ネットワークストレージ(iSCSI)を使うための機能。
  • mdmonitor.service: ソフトウェアRAIDの監視用。cat /proc/mdstat コマンドを叩いて、RAIDが組まれていなければ不要。
  • atd.service: at コマンド(1回限りのタスク予約)用。
サービス停止コマンド一覧。
# systemctl disable --now bluetooth.service
# systemctl disable --now smartd.service
# systemctl disable --now udisks2.service
# systemctl disable --now multipathd.service
# systemctl disable --now libstoragemgmt.service
# systemctl disable --now sssd.service
# systemctl disable --now iscsi-onboot.service
# systemctl disable --now iscsi-starter.service
# systemctl disable --now mdmonitor.service
# systemctl disable --now atd.service

gitの設定。
# git --version
# git config --global user.name "Hoge"
# git config --global user.email "hoge@company.co.jp"

他のサーバーから秘密鍵をコピー&ペースト。
# vim .ssh/gitlab.pem
# vim .ssh/githab.pem
# vim .ssh/config
# chmod 600 .ssh/git*.pem

EPELリポジトリ追加
# dnf install epel-release
# dnf update

htopとcertbotはインストールしておく。
# dnf install htop certbot

ビルドするのでCRB(CoreReady Builder)のリポジトリを有効にする。
# dnf config-manager --set-enabled crb
# less /etc/yum.repos.d/centos.repo


2. MariaDB 11.8をインストール

ベクトル型を試したいので公式リポジトリを追加してMariaDB 11.8をインストールする。
参考: Download MariaDB Server - MariaDB.org
# vim /etc/yum.repos.d/mariadb.repo

# MariaDB 11.8 CentOS repository list - created 2025-11-28 00:45 UTC
# https://mariadb.org/download/
[mariadb]
name = MariaDB
# rpm.mariadb.org is a dynamic mirror if your preferred mirror goes offline. See https://mariadb.org/mirrorbits/ for details.
# baseurl = https://rpm.mariadb.org/11.8/centos/$releasever/$basearch
baseurl = https://ftp.yz.yamagata-u.ac.jp/pub/dbms/mariadb/yum/11.8/centos/$releasever/$basearch
# gpgkey = https://rpm.mariadb.org/RPM-GPG-KEY-MariaDB
gpgkey = https://ftp.yz.yamagata-u.ac.jp/pub/dbms/mariadb/yum/RPM-GPG-KEY-MariaDB
gpgcheck = 1

MariaDB-backupは保守用バッチ処理でmariabackupコマンドを使うため。
# dnf install MariaDB-server MariaDB-backup

2025-11-28  9:52:06 0 [Warning] mariadbd: io_uring_queue_init() failed with EPERM: sysctl kernel.io_uring_disabled has the value 2, or 1 and the user of the process is not a member of sysctl kernel.io_uring_group. (see man 2 io_uring_setup).
create_uring failed: falling back to libaio

この警告メッセージの意味は、「最新の高速なディスク読み書き機能(io_uring)を使おうとしたが、OS(CentOS)のセキュリティ設定で禁止されていたため、従来の方法(libaio)に切り替えて起動した」というものです。

io_uring は高速な反面、不安定なため、そのまま放置で問題ないらしい。

起動、自動起動ON、確認。
# systemctl start mariadb
# systemctl enable mariadb
# systemctl status mariadb

初期設定スクリプトを実行。
このスクリプトの中でUnix Socketに変更してくれた。
# mariadb-secure-installation

デフォルトの文字コードが「utf8mb4」になっているか確認する。
# mariadb -u root -p
# MariaDB [(none)]> show variables like "chara%";

別サーバーからとりあえずの設定をコピー&ペースト。
# less /etc/my.cnf.d/server.cnf

MariaDB再起動。
# systemctl restart mariadb

「skip-networking」を設定したので待ち受けポートを確認(SSHしかListenしてないはず)。
# ss -atn


3. Nginx 1.28.0を手動ビルドしてインストール

ソースからビルドする前にnginxユーザー作成とビルドオプションを確認するためにdnf経由でインストールする。
# dnf install nginx

wwwグループがあるか確認して作成。
# less /etc/group
# groupadd www
# usermod -G www nginx
# groups nginx

ビルドオプションの表示。改行して見やすくする
# nginx -V 2>&1 | sed 's/ --/\n--/g'

nginx version: nginx/1.26.3
built with OpenSSL 3.2.2 4 Jun 2024 (running with OpenSSL 3.5.1 1 Jul 2025)
TLS SNI support enabled
configure arguments:
--prefix=/usr/share/nginx
--sbin-path=/usr/sbin/nginx
--modules-path=/usr/lib64/nginx/modules
--conf-path=/etc/nginx/nginx.conf
--error-log-path=/var/log/nginx/error.log
--http-log-path=/var/log/nginx/access.log
--http-client-body-temp-path=/var/lib/nginx/tmp/client_body
--http-proxy-temp-path=/var/lib/nginx/tmp/proxy
--http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi
--http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi
--http-scgi-temp-path=/var/lib/nginx/tmp/scgi
--pid-path=/run/nginx.pid
--lock-path=/run/lock/subsys/nginx
--user=nginx
--group=nginx
--with-compat
--with-debug
--with-file-aio
--with-http_addition_module
--with-http_auth_request_module
--with-http_dav_module
--with-http_degradation_module
--with-http_flv_module
--with-http_gunzip_module
--with-http_gzip_static_module
--with-http_image_filter_module=dynamic
--with-http_mp4_module
--with-http_perl_module=dynamic
--with-http_random_index_module
--with-http_realip_module
--with-http_secure_link_module
--with-http_slice_module
--with-http_ssl_module
--with-http_stub_status_module
--with-http_sub_module
--with-http_v2_module
--with-http_v3_module
--with-http_xslt_module=dynamic
--with-mail=dynamic
--with-mail_ssl_module
--with-openssl-opt=enable-ktls
--without-engine
--with-pcre
--with-pcre-jit
--with-stream=dynamic
--with-stream_realip_module
--with-stream_ssl_module
--with-stream_ssl_preread_module
--with-threads
--with-cc-opt='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wno-complain-wrong-lang -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64-v3 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2'
--with-ld-opt='-Wl,-z,relro -Wl,--as-needed -Wl,-z,pack-relative-relocs -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -Wl,--build-id=sha1 -specs=/usr/lib/rpm/redhat/redhat-package-notes -Wl,-E -O2'

必要なライブラリをインストール。
参考: CentOS Stream 10でNginxをソースからビルド
# dnf install gcc make cmake pcre2-devel openssl-devel libmaxminddb-devel 

最新の安定版(Stable version)をダウンロードする。
参考: nginx: download
# cd /usr/local/src/
# curl -O https://nginx.org/download/nginx-1.28.0.tar.gz
# tar xzvf nginx-1.28.0.tar.gz
# rm -f nginx-1.28.0.tar.gz
# cd nginx-1.28.0/

サードパーティ製モジュールのソースコードをgitでクローン。
--depth 1 を付けることで、最新のコミット1つ分のみを取得。

GeoIP2 (ngx_http_geoip2_module)
# git clone --depth 1 https://github.com/leev/ngx_http_geoip2_module.git

VTS (nginx-module-vts)
# git clone --depth 1 https://github.com/vozlt/nginx-module-vts.git

Cache Purge (ngx_cache_purge)
# git clone --depth 1 https://github.com/nginx-modules/ngx_cache_purge.git

configureを実行。

  • 「--without-engine」を削除。1.28.0では不要。
  • 「-specs=/usr/lib/rpm/redhat/...」を削除。手動ビルドでは不要。

# ./configure \
--prefix=/usr/share/nginx \
--sbin-path=/usr/sbin/nginx \
--modules-path=/usr/lib64/nginx/modules \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--http-client-body-temp-path=/var/lib/nginx/tmp/client_body \
--http-proxy-temp-path=/var/lib/nginx/tmp/proxy \
--http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi \
--http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi \
--http-scgi-temp-path=/var/lib/nginx/tmp/scgi \
--pid-path=/run/nginx.pid \
--lock-path=/run/lock/subsys/nginx \
--user=nginx \
--group=www \
--with-compat \
--with-file-aio \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_realip_module \
--with-http_slice_module \
--with-http_ssl_module \
--with-http_stub_status_module \
--with-http_sub_module \
--with-http_v2_module \
--with-http_v3_module \
--with-openssl-opt=enable-ktls \
--with-pcre \
--with-pcre-jit \
--with-threads \
--without-mail_imap_module \
--without-mail_pop3_module \
--without-mail_smtp_module \
--add-module=./ngx_http_geoip2_module \
--add-module=./nginx-module-vts \
--add-module=./ngx_cache_purge \
--with-cc-opt='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wno-complain-wrong-lang -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong -m64 -march=x86-64-v3 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2' \
--with-ld-opt='-Wl,-z,relro -Wl,--as-needed -Wl,-z,pack-relative-relocs -Wl,-z,now -Wl,--build-id=sha1 -Wl,-E -O2'

オプションの意味はGemini先生に聞けば教えてくれる。
エラーになったらGemini先生に報告して指示を仰ぐ。

configureが通ったらビルド実行。
# make

ビルド後のバージョン確認とテスト実行。
# ./objs/nginx -V
# ./objs/nginx -t

dnfでインストールしたNginxのサービスファイルの場所確認。
# systemctl status nginx

アンインストールする前にサービスファイルをコピー。
/usr/lib/systemd/system/はdnfパッケージマネージャー用。
/etc/systemd/system/はシステム管理者用。
# cp /usr/lib/systemd/system/nginx.service /etc/systemd/system/
# chmod +x /etc/systemd/system/nginx.service

nginx.confをバックアップ(dnf remove nginxすると削除されるので)
# cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak20251128

dnf経由でインストールしたNginxをアンインストール。
# dnf remove nginx

ビルドしたNginxをインストール。
# make install

確認して設定ファイルを元に戻してテスト。
# nginx -V
# cd /etc/nginx/
# cp nginx.conf.bak20251128 nginx.conf
# nginx -t

systemdのリロードとサービスの有効化。
# systemctl daemon-reload
# systemctl enable nginx
# systemctl start nginx
# systemctl status nginx

ssl_dhparam鍵ファイルを作る。15分ほど掛かった。
# openssl dhparam -out /etc/ssl/dhparam.pem 4096

Nginxの共通設定をcloneする。
include/http_tuning.incに設定してあるFastCGIキャッシュディレクトリを作成。
# mkdir -p /var/cache/nginx/fastcgi_www
# chown -R nginx:www /var/cache/nginx/

テストしてnginx再読み込み。
# nginx -t
# systemctl reload nginx


4. geoipupdateをインストール

CentOS Stream 9のときとほぼ同じ。
参考: CentOS Stream 9 + geoipupdate + Python 3.11をインストール

# cd
# curl -OL https://github.com/maxmind/geoipupdate/releases/download/v7.1.1/geoipupdate_7.1.1_linux_amd64.rpm
# dnf install ./geoipupdate_7.1.1_linux_amd64.rpm

Account IDとLicense Keyを設定ファイルに記述。
国別データベースの場合は GeoLite2-Countryを指定(別サーバーからコピー&ペースト)。
# less /etc/GeoIP.conf

動作確認。
# geoipupdate -v

保存場所確認。
ダウンロードしたrpm削除。
# ls -l /usr/share/GeoIP
# rm rm geoipupdate_7.1.1_linux_amd64.rpm

python用ライブラリをインストール。
# dnf install python3-maxminddb

自社製の確認スクリプトの動作確認。
# mkdir /home/software
# cd /home/software
# git clone git@gitlab.com:webrec-app/server-utility.git
# cd server-utility/
# python3 check_mmdb_meta.py

ついでに他のバッチ処理用スクリプトもcloneしておく。


5. PHP 8.3をインストール

仮想マシンでやったときとほぼ同じ。
参考: CentOS Stream 10 + Nginx + PHP8.3 + MariaDBの仮想マシンを構築する手順まとめ(2025年版)

dnf経由でインストール。
このサーバーはmecabをビルドするのでphp-develもインストールする。
# dnf search php
# dnf install php php-fpm php-mysqlnd php-gd php-pecl-zip php-opcache php-pecl-apcu php-devel

バージョン確認。
# php --version

PHP 8.3.26 (cli) (built: Sep 23 2025 17:57:26) (NTS gcc x86_64)
Copyright (c) The PHP Group
Zend Engine v4.3.26, Copyright (c) Zend Technologies
    with Zend OPcache v8.3.26, Copyright (c), by Zend Technologies

php-fpmの実行ユーザーを変更する。
aclはコメントアウト(そのままだとWARNINGが表示される)。
unix socketで通信するか確認する。
# less /etc/php-fpm.d/www.conf

user = nginx
group = www
listen.owner = nginx
listen.group = www
listen.mode = 0660
;listen.acl_users = apache,nginx

タイムゾーンを設定する。
# less /etc/php.ini

date.timezone = "Asia/Tokyo"

タイムゾーンの確認。
# php -r 'echo date("Y/m/d H:i");'

セッションの書き込みディレクトリ権限を変更。
# chown nginx:www -R /var/lib/php/*

※ PHP更新時に毎回変更しないといけない

php-fpmを起動。
# systemctl start php-fpm
# systemctl enable php-fpm

OPcacheの設定。
参考: CentOS Stream 9 + PHP 8.1 + OPcache

iniファイルの場所を確認して別サーバーからコピー&ペースト。
# php --ini
# less /etc/php.d/10-opcache.ini

APCuの設定。
# less /etc/php.d/40-apcu.ini

テストしてphp-fpmを再起動。

# php-fpm -t
# systemctl reload php-fpm

php-infoの設定値を確認。
# php -i | grep opcache

前の記事を参考にphpMyAdminをインストールする。
参考: CentOS Stream 8 + Nginx + PHP + MariaDB + Postfixの環境を構築(2021年版)

このサーバーはWordPress専用ウェブサーバーなのでphp-fpmのプロセス数を固定する。
pm.max_children(同時に処理できるPHPリクエストの最大数)はCPUのコア数の倍数で設定する。
PHPが使える最大メモリ量 = memory_limit × pm.max_children
# less /etc/php-fpm.d/www.conf

pm = static
pm.max_children = 12
pm.status_path = /phpfpm_status

バージョン情報を隠す。
# less /etc/php.ini

expose_php = Off

テストしてphp_fpmサービス再読み込み。
# php-fpm -t
# systemctl restart php-fpm
# systemctl status php-fpm

htopでphp-fpmのプロセス数を確認。
F4 -> 「PHP」フィルタする。
# htop


6. Postfix + Rspamdをインストール

XServerはVPSアカウント登録後の最初の72時間の間、外向け25番ポートがブロックされている「OP25B(Outbound Port25 Blocking)」ので注意。

前の記事を参考にPostfixをインストール。
XServer VPSはIPv6なしなので、main.cfの「inet_protocols = ipv4」にする。
参考:  CentOS Stream 8 + Nginx + PHP + MariaDB + Postfixの環境を構築(2021年版)

OpenDKIMは開発停止状態なので、Rspamdに乗り換えてみた。
参考: CentOS Stream 10 + Rspamd(OpenDKIMの代替)


7. Subversionをインストール

このサーバーはSubversionのリポジトリを格納するので、前の記事に従ってインストール。参考: CentOS8にSubversion1.14+httpdをインストールしてnginxでリバースプロキシする

TortoizeSVNでコミットすると下記エラー。

Command: Commit to http://svn.hoge.jp/test1  
Error: Commit failed (details follow):  
Error: Can't open file '/home/svn/repo/test1/db/txn-current-lock': Read-only file  
Error:  system  
Completed!:   

Gemini先生にログを報告して対策を教えてもらう。
CentOS Stream 10はApache(httpd)のサービス定義ファイルで、/home ディレクトリへの書き込みが制限しているらしい。

権限確認。
# systemctl cat httpd

ProtectHome=read-only

/home ディレクトリへの書き込みを可能にする。
# systemctl edit httpd

 [Service]
ProtectHome=off

Ctrl-O -> Enterで保存してCtrl-Xで終了。
設定を反映させてApacheを再起動。
# systemctl daemon-reload
# systemctl restart httpd

TortoizeSVNでコミットして確認。



その他やること


▼ 関連記事