2026年04月
オイオイ、とうとう無料の VPS が出たのかいな。
無料VPS | 圧倒的な性能・コスパのVPS | XServer VPS
XServerのサブドメインが無料で利用できます。
もちろん、制約もあります。
VPS から外部へのメール送信ができません。
システムに過度な負荷をかける行為や不正行為に対し、自動検知システムにより制限が適用される場合があります。
コントロールパネルから2日または4日ごとに契約を更新する必要があります。
CPU の情報を確認したければ、下記コマンドなどで。
:~# cat /proc/cpuinfo
:~# lscpu
CentOS Stream 10 (64bit) を試してみました。
僕は、インスタンス作成時に自前の公開鍵で SSH Key 設定をしています。
まず、「パケットフィルター設定」でポートを開けないと SSH 接続すらできないようです。
参考:SSH接続方法
端末から接続します。
:~$ ssh root@xxx.xxx.xxx.xxx
「VNCコンソール」と「シリアルコンソール」でのコンソール接続もできます。
参考:コンソール接続
主な項目を確認。
:~# sshd -T | grep -i -E 'SyslogFacility|PermitRootLogin|PermitEmptyPasswords|PasswordAuthentication'
permitrootlogin without-password
passwordauthentication no
permitemptypasswords no
syslogfacility AUTHPRIV
僕はこれで問題なかったので変更していませんが、変更するなら、
:~# vi /etc/ssh/sshd_config
を編集して、sshd 再起動。
:~# systemctl restart sshd
システムのタイムゾーンなどを確認。Time zone は Asia/Tokyo でした。
:~# timedatectl
文字コードなどを確認。LANG=ja_JP.UTF-8 でした。
:~# localectl
SELINUX は、disabled にしています。
:~# vi /etc/sysconfig/selinux
メモリ確認。
:~# free -m
ホスト名を変更。XServerのサブドメインを利用したので、それに合わせています。
:~# hostnamectl set-hostname xxxxx.xvps.jp
確認。
:~# hostnamectl
端末上の表記は再ログインなどで反映されます。
以下を見ておく。
:~# cat /etc/hostname
:~# cat /etc/hosts
:~# cat /etc/resolv.conf
:~# nmcli d
DEVICE TYPE STATE CONNECTION
ens3 ethernet 接続済み cloud-init ens3
lo loopback 接続済み (外部) lo
:~# nmcli d show ens3
「パケットフィルター設定」を行っていますが、firewalld も起動しました。
:~# systemctl enable --now firewalld
アクティブゾーンを確認する。
:~# firewall-cmd --get-active-zones
public (default)
interfaces: ens3
アクティブゾーンの恒久的なファイアウォール設定を確認。
:~# firewall-cmd --list-all --zone=public --permanent
public (default)
target: default
ingress-priority: 0
egress-priority: 0
icmp-block-inversion: no
interfaces:
sources:
services: cockpit dhcpv6-client ssh
ports:
protocols:
forward: yes
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
EPEL のリポジトリをインストール
:~# dnf -y install epel-release
EPEL 関係、無効化。(使うときには、--enablerepo= を付ける)
:~# dnf config-manager --disable epel
有効化されているリポジトリの一覧を確認するなら。
:~# dnf repolist
有効および無効なリポジトリーの両方を一覧表示するなら。
:~# dnf repolist all
dnf アップデート
:~# dnf -y update
dnf-automatic インストール。
:~# dnf -y install dnf-automatic
dnf-automatic-install 自動起動有効+起動。
:~# systemctl enable --now dnf-automatic-install.timer
nkf コマンドインストール。
:~# dnf --enablerepo=epel install nkf
jq コマンドインストール。(インストール済みでした)
:~# dnf install jq
現在使用中のカーネルバージョンを確認する。
:~# uname -r
インストール済みを確認する。
:~# dnf repoquery --installonly
カーネルがアップデートされていると思うので再起動する。
:~# reboot
Chrony はインストール済みでした。
:~# vi /etc/chrony.conf
変更。(追加)
# Use public servers from the pool.ntp.org project.
# Please consider joining the pool (https://www.pool.ntp.org/join.html).
#pool 2.centos.pool.ntp.org iburst
pool ntp.nict.jp iburst
再起動。
:~# systemctl restart chronyd
時刻同期状態確認。
:~# chronyc sources
perl-CPAN をインストール。
:~# dnf install perl-CPAN
入力。
:~# perl -MCPAN -e shell
CPAN.pm requires configuration, but most of it can be done automatically.
If you answer 'no' below, you will enter an interactive dialog for each
configuration option instead.
Would you like to configure as much as possible automatically? [yes] yes
Perl site library directory "/usr/local/share/perl5/5.40" does not exist.
Perl site library directory "/usr/local/share/perl5/5.40" created.
Perl site library directory "/usr/local/lib64/perl5/5.40" does not exist.
Perl site library directory "/usr/local/lib64/perl5/5.40" created.
We initialized your 'urllist' to https://cpan.org/. Type 'o conf init urllist' to change it.
Autoconfiguration complete.
commit: wrote '/root/.cpan/CPAN/MyConfig.pm'
You can re-run configuration any time with 'o conf init' in the CPAN shell
Terminal does not support AddHistory.
To fix that, maybe try> install Term::ReadLine::Perl
cpan shell -- CPAN exploration and modules installation (v2.36)
Enter 'h' for help.
cpan[1]> install MIME::Base64
cpan[2]> install CGI
cpan[3]> install Jcode
cpan[4]> quit
Apache と PHP 及び PHP 関連パッケージをインストール。
:~# dnf -y install httpd php php-mbstring php-gd php-json php-xml
インストールされたモジュールの一覧を確認するなら。
:~# php -m
Apache 設定ファイル編集。
:~# vi /etc/httpd/conf/httpd.conf
変更と追加と削除。
ServerAdmin root@localhost
↓↓↓
ServerAdmin webmaster@xxxxx.xvps.jp
・・・
・・・
#ServerName www.example.com:80
↓↓↓
ServerName xxxxx.xvps.jp:80
・・・
・・・
<Directory "/var/www/html">
#
# Possible values for the Options directive are "None", "All",
# or any combination of:
# Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
#
# Note that "MultiViews" must be named *explicitly* --- "Options All"
# doesn't give it to you.
#
# The Options directive is both complicated and important. Please see
# http://httpd.apache.org/docs/2.4/mod/core.html#options
# for more information.
#
Options Indexes FollowSymLinks
↓↓↓
Options Includes ExecCGI FollowSymLinks
#
# AllowOverride controls what directives may be placed in .htaccess files.
# It can be "All", "None", or any combination of the keywords:
# Options FileInfo AuthConfig Limit
#
AllowOverride None
↓↓↓
AllowOverride All
#
# Controls who can get stuff from this server.
#
Require all granted
</Directory>
・・・
・・・
<IfModule log_config_module>
#
# The following directives define some format nicknames for use with
# a CustomLog directive (see below).
#
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
↓↓↓
LogFormat "%h %l %u %t \"%!414r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
・・・
・・・
#
# If you prefer a logfile with access, agent, and referer information
# (Combined Logfile Format) you can use the following directive.
#
SetEnvIf Request_URI "default\.ida" no_log
SetEnvIf Request_URI "cmd\.exe" no_log
SetEnvIf Request_URI "root\.exe" no_log
SetEnvIf Request_URI "Admin\.dll" no_log
SetEnvIf Request_URI "NULL\.IDA" no_log
SetEnvIf Remote_Addr 127.0.0.1 no_log
CustomLog "logs/access_log" combined env=!no_log
</IfModule>
・・・
・・・
#AddHandler cgi-script .cgi .pl
以下を最終行へ追加。
ServerTokens Prod
TraceEnable off
autoindex 設定ファイル編集。
:~# vi /etc/httpd/conf.d/autoindex.conf
削除。
<Directory "/usr/share/httpd/icons">
Options Indexes MultiViews FollowSymlinks
AllowOverride None
Require all granted
</Directory>
テストページ削除。
:~# rm -f /etc/httpd/conf.d/welcome.conf
Perl コマンドへ /usr/local/bin/perl でもアクセスできるようにする。
:~# ln -s /usr/bin/perl /usr/local/bin/perl
Perl のパスを確認。
:~# whereis perl
Apache 自動起動有効+起動。
:~# systemctl enable --now httpd
ポート開放。
:~# firewall-cmd --add-service=http --zone=public --permanent
:~# firewall-cmd --reload
「パケットフィルター設定」で「フィルター:Web」を追加。
Web コンテンツ編集ユーザ(例:himari)を作成。
:~# useradd himari
:~# passwd himari
ドキュメントルート所有者を変更する。
:~# chown himari: /var/www/html/
himari で SSH 鍵方式ログイン出来るようにする。
himari にスイッチする。
:~# su - himari
:~$ mkdir ~/.ssh
:~$ chmod 700 ~/.ssh
公開鍵の中身を authorized_keys にコピペして保存。
:~$ vi ~/.ssh/authorized_keys
:~$ chmod 600 ~/.ssh/authorized_keys
:~# vi /etc/php.ini
変更と削除と追加。
short_open_tag = Off
↓↓↓
short_open_tag = On
output_buffering = 4096
↓↓↓
output_buffering = Off
display_errors = Off
↓↓↓
display_errors = On
;date.timezone = Asia/Tokyo
;mbstring.language = Japanese
;mbstring.internal_encoding = UTF-8
;mbstring.http_input = UTF-8
;mbstring.http_output = UTF-8
;mbstring.encoding_translation = Off
↓↓↓
mbstring.encoding_translation = On
;mbstring.detect_order = auto
;mbstring.substitute_character = none
↓↓↓
mbstring.substitute_character = "?"
httpd リロード。
:~# systemctl reload httpd
ImageMagick をインストール。
:~# dnf --enablerepo=epel,crb install ImageMagick ImageMagick-devel
僕は WebP への変換で cwebp, gif2webp, webpmux を使っているので、libwebp-tools をインストール。
:~# dnf --enablerepo=epel,crb install libwebp-tools
確認。
:~# magick --version
:~# cwebp -version
:~# gif2webp -version
:~# webpmux -version
必要なパッケージをインストール。
:~# dnf install php-devel php-pear
pecl で imagick をインストール。
Enter
:~# pecl install imagick
・・・
・・・
Please provide the prefix of ImageMagick installation [autodetect] : ⏎
・・・
・・・
You should add "extension=imagick.so" to php.ini
php.ini 最下部に追記。
:~# vi /etc/php.ini
・・・
・・・
extension=imagick.so
反映。
:~# systemctl restart php-fpm
Certbot クライアントをインストールします。参考:Certbot Instructions
まず、snapd をインストールし、自動起動有効+起動。
:~# dnf --enablerepo=epel install snapd
:~# systemctl enable --now snapd.socket
シンボリックリンクを作成。
:~# ln -s /var/lib/snapd/snap /snap
snap のパスが正しく更新されるようにするには、一度ログアウトして再度ログインするか、システムを再起動してください。
certbot をインストール。
:~# snap install --classic certbot
下記エラーが出たら、数分待ってから再度実行する。
error: too early for operation, device not yet seeded or device model not acknowledged
シンボリックリンクを作成。
:~# ln -s /snap/bin/certbot /usr/local/bin/certbot
証明書取得。(80番ポートが外部からアクセス可能であること)
:~# certbot certonly --webroot \
-w /var/www/html \
-m you@example.com \
--agree-tos \
-d xxxxx.xvps.jp
・・・
・・・
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/xxxxx.xvps.jp/fullchain.pem
Key is saved at: /etc/letsencrypt/live/xxxxx.xvps.jp/privkey.pem
This certificate expires on 2026-07-14.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.
・・・
・・・
mod_ssl インストール。
:~# dnf -y install mod_ssl
SSL 設定ファイル編集。
:~# vi /etc/httpd/conf.d/ssl.conf
変更と追加。
# Use separate log files for the SSL virtual host; note that LogLevel
# is not inherited from httpd.conf.
ErrorLog logs/ssl_error_log
↓↓↓
ErrorLog logs/error_log
TransferLog logs/ssl_access_log
↓↓↓
CustomLog logs/access_log combined env=!no_log
LogLevel warn
・・・
・・・
#SSLProtocol all -SSLv3
#SSLProxyProtocol all -SSLv3
SSLProtocol TLSv1.2 TLSv1.3
SSLProxyProtocol TLSv1.2 TLSv1.3
・・・
・・・
SSLHonorCipherOrder on
・・・
・・・
SSLCipherSuite PROFILE=SYSTEM
↓↓↓
SSLCipherSuite HIGH:!aNULL:!MD5:!3DES:!CAMELLIA:!AESCCM:!ECDSA
・・・
・・・
SSLCertificateFile /etc/pki/tls/certs/localhost.crt
↓↓↓
SSLCertificateFile /etc/letsencrypt/live/xxxxx.xvps.jp/fullchain.pem
・・・
・・・
SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
↓↓↓
SSLCertificateKeyFile /etc/letsencrypt/live/xxxxx.xvps.jp/privkey.pem
・・・
・・・
Header always set Strict-Transport-Security "max-age=15768000"
</VirtualHost>
Apache 設定反映。
:~# systemctl reload httpd
ポート開放。
:~# firewall-cmd --add-service=https --zone=public --permanent
:~# firewall-cmd --reload
自動更新をテストする。
:~# certbot renew --dry-run
php-mysqlnd も一緒にインストールしています。
:~# dnf -y install mariadb-server php-mysqlnd
MariaDB 設定ファイル編集。
追加。
:~# vi /etc/my.cnf.d/mariadb-server.cnf
# This group is only read by MariaDB-10.11 servers.
# If you use the same .cnf file for MariaDB of different versions,
# use this group for options that older servers don't understand
[mariadb-10.11]
character-set-server = utf8mb4
:~# vi /etc/my.cnf.d/client.cnf
# This group is not read by mysql client library,
# If you use the same .cnf file for MySQL and MariaDB,
# use it for MariaDB-only client options
[client-mariadb]
default-character-set = utf8mb4
自動起動有効+起動。
:~# systemctl enable --now mariadb
MariaDB 初期設定。
:~# mysql_secure_installation
入力。
NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
SERVERS IN PRODUCTION USE! PLEASE READ EACH STEP CAREFULLY!
In order to log into MariaDB to secure it, we'll need the current
password for the root user. If you've just installed MariaDB, and
haven't set the root password yet, you should just press enter here.
Enter current password for root (enter for none): ⏎
OK, successfully used password, moving on...
Setting the root password or using the unix_socket ensures that nobody
can log into the MariaDB root user without the proper authorisation.
You already have your root account protected, so you can safely answer 'n'.
Switch to unix_socket authentication [Y/n] n
... skipping.
You already have your root account protected, so you can safely answer 'n'.
Change the root password? [Y/n] n
... skipping.
By default, a MariaDB installation has an anonymous user, allowing anyone
to log into MariaDB without having to have a user account created for
them. This is intended only for testing, and to make the installation
go a bit smoother. You should remove them before moving into a
production environment.
Remove anonymous users? [Y/n] ⏎
... Success!
Normally, root should only be allowed to connect from 'localhost'. This
ensures that someone cannot guess at the root password from the network.
Disallow root login remotely? [Y/n] ⏎
... Success!
By default, MariaDB comes with a database named 'test' that anyone can
access. This is also intended only for testing, and should be removed
before moving into a production environment.
Remove test database and access to it? [Y/n] ⏎
- Dropping test database...
... Success!
- Removing privileges on test database...
... Success!
Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.
Reload privilege tables now? [Y/n] ⏎
... Success!
Cleaning up...
All done! If you've completed all of the above steps, your MariaDB
installation should now be secure.
Thanks for using MariaDB!
【MariaDB 操作】
MariaDB へ root でログイン。(パスワード不要)
:~# mysql
testDB データベースへの全てのアクセス権限を持った、新規ユーザー mei(パスワード:meipass )を登録。
MariaDB [(none)]> grant all privileges on testDB.* to mei@localhost identified by 'meipass';
ログアウト。
MariaDB [(none)]> exit
Bye
MariaDB へ mei ユーザでログイン。
:~# mysql -u mei -pmeipass
testDB データベース作成。
MariaDB [(none)]> create database testDB;
:~# curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
確認。
:~# composer --version
Composer 本体のアップデート方法。
:~# composer self-update
composer update は プロジェクト内のライブラリを更新するコマンド であり、 Composer 本体の更新とは別です。
Composer 本体 → composer self-update
プロジェクトの依存パッケージ → composer update(慎重に扱う必要あり)
Brevo で利用可能なSMTPポートには、465, 587 に加えて、2525 があります。
465, 587 へは VPS の制限から接続できないのですが、2525 には接続できたので 2525 ポートを使って PHPMailer でメール送信ができます。
OpenSSL で SMTP サーバーに直接接続できるか確認する。
:~# openssl s_client -connect smtp-relay.brevo.com:465
何も返らず固まる(アウトバウンド制限)
:~# openssl s_client -starttls smtp -connect smtp-relay.brevo.com:587
何も返らず固まる(アウトバウンド制限)
:~# openssl s_client -starttls smtp -connect smtp-relay.brevo.com:2525
証明書情報や 250 などの応答が返る
また、Brevo で提供している API を使えばそもそもポートを気にせずにメール送信ができます。(API は 443 ポートで通信するためブロックされません)
API 送信をする。PHP SDK | Brevo API Documentation
/usr/local/lib で Composer を実行して SDK をインストール。
:~# cd /usr/local/lib
:/usr/local/lib# composer require getbrevo/brevo-php
:/usr/local/lib# composer require guzzlehttp/guzzle
APIキーを取得して、authorized IP address も登録する。
PHPコード例:
<?php
require_once '/usr/local/lib/vendor/autoload.php';
use Brevo\Brevo;
use Brevo\TransactionalEmails\Requests\SendTransacEmailRequest;
use Brevo\TransactionalEmails\Types\SendTransacEmailRequestSender;
use Brevo\TransactionalEmails\Types\SendTransacEmailRequestToItem;
// APIクライアント初期化
$client = new Brevo(apiKey: 'YOUR_BREVO_API_KEY');
// メール送信
$result = $client->transactionalEmails->sendTransacEmail(
new SendTransacEmailRequest([
'subject' => 'Hello from Brevo API!',
'htmlContent' => '<html><body><p>Hello!</p><p>This is a test email via Brevo API.</p></body></html>',
'sender' => new SendTransacEmailRequestSender([
'name' => 'Your Name',
'email' => '[email protected]',
]),
'to' => [
new SendTransacEmailRequestToItem([
'email' => '[email protected]',
'name' => 'John Doe',
]),
],
])
);
echo 'Email sent. Message ID: ' . $result->messageId . PHP_EOL;
「logwatch → ファイル出力 → PHP で Brevo API 送信」という構成。
logwatch をインストール。
:~# dnf install logwatch
logwatch をファイル出力にするコマンド。
logwatch --output file --filename /var/log/logwatch-report.txt
PHP でファイルを読み込んで Brevo API 送信。
/usr/local/scripts ディレクトリ作成。
:~# mkdir -p /usr/local/scripts
:~# chmod 755 /usr/local/scripts
PHPコード例:
:~# vi /usr/local/scripts/send-logwatch.php
<?php
require_once '/usr/local/lib/vendor/autoload.php';
use Brevo\Brevo;
use Brevo\TransactionalEmails\Requests\SendTransacEmailRequest;
use Brevo\TransactionalEmails\Types\SendTransacEmailRequestSender;
use Brevo\TransactionalEmails\Types\SendTransacEmailRequestToItem;
// logwatch のレポートを読み込む
$report = file_get_contents('/var/log/logwatch-report.txt');
// Brevo API クライアント
$client = new Brevo(apiKey: 'YOUR_BREVO_API_KEY');
// メール送信
$result = $client->transactionalEmails->sendTransacEmail(
new SendTransacEmailRequest([
'subject' => 'Daily Logwatch Report',
'htmlContent' => nl2br(htmlspecialchars($report)),
'sender' => new SendTransacEmailRequestSender([
'name' => 'Server',
'email' => '[email protected]',
]),
'to' => [
new SendTransacEmailRequestToItem([
'email' => '[email protected]',
'name' => 'Your Name',
]),
],
])
);
echo "Sent: " . $result->messageId . PHP_EOL;
毎日実行するように cron に登録例:
:~# crontab -e
0 7 * * * /usr/sbin/logwatch --output file --filename /var/log/logwatch-report.txt
5 7 * * * /usr/bin/php /usr/local/scripts/send-logwatch.php
- guitar site WAVE -