はじめに
仕事の関係でテストサーバが必要となり、VPSサーバをレンタルしました。その設定過程を記載します。
私が求める条件としては、Rocky Linux 8.10が使用出来る、Node.jsがインストール出来る、ドメインのネームサーバの変更が出来るというものでした。
レンタルサーバ環境
xServerさんのVPSをレンタルすることにしました。
仕事で使用しているサーバがRed Hat Enterprise Linux release 8.10 (Ootpa)ですので、それと互換性があるRocky Linux 8.10を選択します。
OS: Rocky Linux 8.10(64bit)
メモリ: 2GB
ストレージ(NVMe SSD): 50GB
node version: v16.20.2 ※nvmで管理
npm version: 8.19.4
サーバにログイン
サーバ契約時に作成した公開鍵は、サーバの
/root/.ssh/authorized_keys
にあります。
サーバ契約時に作成した秘密鍵は自身のPCの以下に保存しています。
~/.ssh/xServerKey.pem
こちらのxServerさんのマニュアルを参考にして、SSHの接続を許可します。ポート番号はデフォルトの22のままにします。
※後述する通り、最終的にはフィルタールール設定は使用せず、ファイアウォールで対応することにしました。
以下のコマンドでログイン出来ます。
ssh -i ~/.ssh/xServerKey.pem root@(IPアドレス)
-i ~/.ssh/xServerKey.pem で使用する秘密鍵を指定しています。
ユーザの作成
以下のコマンドでユーザーを作成します。
adduser newusername
以下のコマンドでパスワードを設定します。
passwd newusername
ssh接続のための設定
作成したユーザでもssh接続を可能とするために、.ssh ディレクトリを作成します。
sudo mkdir -p /home/newusername/.ssh
ここで-pは、親ディレクトリが存在しない場合、自動で作成 するオプションです。
次に、.ssh ディレクトリとその中のファイルの所有者(ユーザー)とグループを newusername に変更します。
sudo chown -R newusername:newusername /home/newusername/.ssh
契約時にサーバー側で作成された 公開鍵 (/root/.ssh/authorized_keys) を、newusername の .ssh ディレクトリにコピーし、権限の変更などをします。
sudo cp /root/.ssh/authorized_keys /home/newusername/.ssh/authorized_keys
sudo chown newusername:newusername /home/newusername/.ssh/authorized_keys
sudo chmod 600 /home/newusername/.ssh/authorized_keys
これで以下のコマンドでログイン出来るようになりました。
ssh -i ~/.ssh/xServerKey.pem newusername@85.131.247.36
sudoコマンドを使用するための設定
デフォルトでは新しいユーザはsudoを実行する権限を持っていないので与えます。
usermod -aG wheel newusername
usermod:ユーザーの情報を変更するコマンド
-a:(append) 追加(既存のグループ設定を維持しながら追加)
-G:wheel 管理者権限(sudo)を持つユーザーが所属する特別なグループであるwheelグループに追加
これでsudoが使用出来るようになりました。
ファイアウォールの設定
firewalld をインストール
sudo dnf install -y firewalld
firewalld を有効化
sudo systemctl enable --now firewalld
FTP のポートを開放
sudo firewall-cmd --permanent --add-service=ftp
sudo firewall-cmd --permanent --add-port=40000-50000/tcp
sudo firewall-cmd --reload
上記のコマンドは以下の意味を持ちます。
• --add-service=ftp → FTPの標準ポート (21) を開放。
• --add-port=40000-50000/tcp → パッシブモードで使うポート範囲を開放。
• --reload → 設定を反映。
HTTP (80) と HTTPS (443) などのポートを許可
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
ついでによく使用する、3000、8080、8443のポートも許可しておきます。
sudo firewall-cmd --permanent --add-port=3000/tcp
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --permanent --add-port=8443/tcp
設定の反映
設定を反映させるには、firewalld をリロードします。
sudo firewall-cmd --reload
再度、開放されたポートやサービスを確認します。
sudo firewall-cmd --list-all
FTP設定
ローカルからサーバにファイルなどを転送するためにFTP設定をします。
FTP サーバーのインストール
sudo dnf install -y vsftpd
vsftpd の設定ファイルを編集
sudo vi /etc/vsftpd/vsftpd.conf
として、設定ファイルを開き編集していきます。
listen=YES(IPv4を有効化)
listen_ipv6=NO(IPv6を無効化)
pasv_enable=YES(クライアントが「PASV」コマンドを送ると、サーバーがデータ転送用のポートを開放し、クライアントにそのポート番号を通知する。)
pasv_min_port=40000
pasv_max_port=50000
を追記しました。
chroot_local_user=YES(すべてのユーザーを chroot で制限)
chroot_list_enable=YES (chroot_list に記載されたユーザーのみ chroot 解除)
chroot_list_file=/etc/vsftpd/chroot_list (chroot_listファイル)
allow_writeable_chroot=YES (エラー防止用。書き込み可能なディレクトリでもログインできるように)
/etc/vsftpd/chroot_listを作成してchrootを解除したユーザ名を記載します。
sudo touch /etc/vsftpd/chroot_list
sudo chmod 600 /etc/vsftpd/chroot_list
echo "newusername" | sudo tee -a /etc/vsftpd/chroot_list
SELinux の設定
FTP サーバーがホームディレクトリにアクセスすることを許可
sudo setsebool -P ftpd_full_access on
FTP を通じたファイルアップロードを許可
sudo setsebool -P allow_ftpd_full_access on
SELinux が有効な場合の FTP パッシブモードの設定
SELinux が Enforcing になっている場合、パッシブモードの FTP を許可する必要があります。
sudo setsebool -P ftpd_use_passive_mode on
• -P オプション → 設定を永続化(リブート後も有効)
• ftpd_use_passive_mode on → FTP のパッシブモードを許可
※SELinux(Security-Enhanced Linux)
Linux システムに強固なアクセス制御を追加するセキュリティ機能です。
Red Hat Enterprise Linux(RHEL)や Rocky Linux などのディストリビューション で標準搭載されています。
vsftpd を起動 & 自動起動設定
sudo systemctl start vsftpd
sudo systemctl enable vsftpd
2つのコマンドは、FTP サーバー vsftpd (Very Secure FTP Daemon) の起動と自動起動の設定を行うものです。
vsftpd は FTP サーバーのデーモン(バックグラウンドで動作するプロセス)です。
systemctl enable は systemd の機能で、サービスを 永続的に有効化 します。
これにより、サーバーを再起動しても vsftpd が自動的に起動するようになります。
FTPコマンドのインストール
sudo dnf install -y ftp
サーバ上で以下を実行すると、つながることが確認できます。
ftp localhost
クライアントから FTP に接続
ftp (IPアドレス)
として、ユーザ名、パスワードを入力すると、クライアントからサーバにつながります。
FileZillaを使う
以下の設定でつながりました。
ホストは、まだドメインを取得していないので、IPアドレスを記載しています。
nvmのインストール
ユーザでサーバにログインします。
こちらの記事を参考にインストールします。
node.jsのインストール
nvmを利用して、開発環境のホスティングサーバに合わせて
node version: v16.20.2
をインストールします。
nvm install v16.20.2
ちなみにnpmのバージョンは8.19.4がインストールされています。
Nginxのインストール
リバースプロキシを使用したいので、Nginxをインストールします。
問題意識としては、Node.jsのexpressを使用してサーバを立ち上げる時に、HTTPS接続だと「(failed) net::ERR_HTTP2_PROTOCOL_ERROR 」というエラーが頻発していました。これをどうにか解決したいと思い、リバースプロキシを使用する方法を試してみます。
リバースプロキシとは、クライアントとリバースプロキシ間はHTTPSを利用し、リバースプロキシとサーバ間はHTTPを利用するというものです。
こうすることで、HTTP/2プロトコル対応などはリバースプロキシに任せられるので、上記エラーが解消されると期待しています。
システムを最新の状態に更新
sudo dnf update -y
EPEL リポジトリを有効化
Rocky Linux のデフォルトリポジトリには nginx が含まれていますが、最新版を取得するために EPEL (Extra Packages for Enterprise Linux) リポジトリ を追加するのが一般的です。
sudo dnf install -y epel-release
Nginx のインストール
sudo dnf install -y nginx
インストール後、Nginx を起動し、OS 起動時に自動起動するように設定します。
# Nginx の起動
sudo systemctl start nginx
# Nginx を自動起動するように設定
sudo systemctl enable nginx
# Nginx の状態を確認
sudo systemctl status nginx
http://<サーバーのIPアドレス>
とすると確認できます。
Let's Encryptを利用したSSL/TLS 証明書の設定
Let's Encryptとは?
無料でSSL/TLS証明書を発行する認証局(CA: Certificate Authority) です。Let’s Encryptの証明書は 90日ごとに更新する必要がありますが、Certbot(Let’s Encrypt公式ツール)を使うと、自動更新 できるので手間がかかりません。
こちらのcerbotのページで作業をします。
Cerbotとは?
Let’s Encrypt が提供する 無料のSSL/TLS証明書 を取得・管理するためのツールで、Nginxの設定を自動で変更、証明書の自動更新が可能などの特徴があります。
My HTTP website is running [Nginx] on [Linux (snap)]で作業します。
snapは、Certbotの公式推奨インストール方法です。
設定手順
SSH into the server
sudo権限を持ったユーザで、SSH接続を利用してサーバに入ります。
Install snapd
snapdは、“Snap パッケージ” を管理するデーモン(バックグラウンドサービス) です。
通常、Linux ではソフトウェアをインストールする方法として dnf(RHEL, CentOS, Rocky Linux)や apt(Ubuntu, Debian)を使います。
しかし、これらの方法ではディストリビューションごとに異なるパッケージ管理システムがあり、互換性の問題が発生することがあります。
Snap は、その問題を解決するために設計された新しいパッケージ形式 です。
# まず EPEL リポジトリを有効化
sudo dnf install epel-release -y
# `snapd` をインストール
sudo dnf install snapd -y
# `snapd` を有効化
sudo systemctl enable --now snapd
# `snapd` の状態を確認
systemctl status snapd
Remove certbot-auto and any Certbot OS packages
dnfなどのcerbotパッケージが存在すると、うまく動かないようなので、念の為削除しておきます。
certbot --version
こちらのコマンドでcerbotが見つからなかったので、OKです。
Install Certbot
多少詰まりましたが、chatGPTに聞いてインストール出来ました。
Prepare the Certbot command
sudo ln -s /snap/bin/certbot /usr/bin/certbot
このコマンドは /snap/bin/certbot へのシンボリックリンク(ソフトリンク)を /usr/bin/certbot に作成するものです。
シンボリックリンク(-s オプション)は、ファイルやディレクトリへの 参照(ショートカット)を作成する 仕組みです。
この場合、/usr/bin/certbot を実行すると、実際には /snap/bin/certbot が呼び出されます。
このコマンドを実行することで、certbot を どこからでも実行できるようにする ことができます!
Choose how you'd like to run Certbot
sudo certbot --nginx
コマンドを実行後、質問をいくつかされるのでそれに回答すると終了です。
Test automatic renewal
証明書が自動更新するかテストします。
sudo certbot renew --dry-run
成功したので、実際の更新も問題なく動作するはずです。
Confirm that Certbot worked
最後にhttpsでページが見られるか確認しました。
nginxの設定ファイル
/etc/nginx/nginx.conf
に設定ファイルがあり、証明書の保存場所やリダイレクト設定などが記載されています。
以下のように設定して、解説も記載しました。cerbotによって設定されたものから、少し修正しています。
user nginx;
worker_processes auto; # サーバーの CPU コア数に応じて最適なプロセス数を自動設定
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024; # 1つのワーカープロセスが同時に処理できる最大の接続数 を設定
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
# アクセスログのフォーマットを定義
access_log /var/log/nginx/access.log main;
sendfile on; #ファイル送信の最適化
tcp_nopush on; #レスポンスの送信最適化
tcp_nodelay on; #リアルタイム応答の高速化
keepalive_timeout 65; #コネクションの維持時間
types_hash_max_size 2048;
include /etc/nginx/mime.types; #適用される MIMEタイプ
default_type application/octet-stream; #MIME タイプが不明なファイルは application/octet-stream(バイナリデータ)として送信
include /etc/nginx/conf.d/*.conf; # 設定の分割管理だが使用していない
server {
listen 80 default_server; #ポート 80(HTTP)で待ち受ける。
listen [::]:80 default_server; #IPv6 アドレスでも 80 を待ち受ける。#「default_server」はserver_name にも一致しないリクエストをこの server ブロックで処理
server_name k96mz.com;
root /usr/share/nginx/html; #Web サイトのルートディレクトリを指定
include /etc/nginx/default.d/*.conf; #追加の設定を分割管理できるが使用していない。
location / { # /(ルートディレクトリ)に対するリクエストを処理
}
error_page 404 /404.html; #404 エラーが発生した場合、/404.html を表示
location = /40x.html { #/40x.html にリクエストがあったときの処理を指定
}
error_page 500 502 503 504 /50x.html; #500(内部エラー)、502(Bad Gateway)、503(Service Unavailable)、504(Gateway Timeout)の場合、/50x.html を表示
location = /50x.html {
}
}
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name k96mz.com;
root /usr/share/nginx/html;
ssl_certificate /etc/letsencrypt/live/k96mz.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/k96mz.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
include /etc/nginx/default.d/*.conf;
#HTTP でバックエンドに転送
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host; #クライアントのホスト名を保持
proxy_set_header X-Real-IP $remote_addr; #クライアントの IP アドレスを保持
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #プロキシを経由した元の IP アドレスを送信
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
ここで肝になるのは、リバースプロキシ設定部分です。
例えば、
https://k96mz.com/test/index.html
にきたリクエストは、
http://localhost:8080/test/index.html
に転送されます。
この時、リダイレクトとは異なり、クライアントに表示されるURLは、
https://k96mz.com/test/index.html
のままです。
設定後は以下でエラーがないか確認します。
sudo nginx -t
コードを修正した後は、以下のコマンドで修正を反映します。
sudo systemctl reload nginx
node.jsでサーバを立ち上げる
node.jsでサーバを立ち上げて、実際の挙動を確かめました。
const express = require('express');
const app = express();
const PORT = 8080;
// ルート("/")にアクセスしたときのレスポンス
app.get('/', (req, res) => {
res.send('Hello, World!');
});
app.get('/test', (req, res) => {
res.send('Test response');
});
// サーバーを起動
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
実際に
https://k96mz.com
とすると「Hello, World!」が返り、
https://k96mz.com/test
とすると、「Test response」が返ります。
リバースプロキシを使用してベクトルタイルを表示
こちらの記事で、node.jsを用いてベクトルタイルサーバを作成しました。HTTPSでの地図表示について、非常に不安定な状態で、おそらくですがHTTP/2プロトコルでの表示がうまくいっていないようでした。そこで、今回はリバースプロキシを用いて、リバースプロキシとサーバ間はHTTP接続とすることで、不安定な状態を解決したいと思います。
使用するコードはこちらのGitHubページにあります。
コード修正
今回のサーバに合わせて以下の点を修正します。
・使用するポートは8080
・styleO-pbf.jsonのタイルURLは以下に変更
"tiles": ["https://k96mz.com/VTpractice/{z}/{x}/{y}.pbf"]
・styleO-mbtiles.jsonのタイルURLは以下に変更
"tiles": ["https://k96mz.com/VT/zxy/VTpracticegzip/{z}/{x}/{y}.pbf"]
上記の設定に修正することで、例えば、以下のURLにアクセスすると地図が表示されます。(現在はサーバを立ち上げていないので、地図は見られません。)
https://k96mz.com/map/mapO-mbtiles.html
コードの中で、appHttps.jsなどはHTTPS接続のための鍵を読み込んでいますが、リバースプロキシを利用すれば、そのようなことは意識しなくて良いので楽だと感じました
まとめ
レンタルしたVPSサーバの設定過程を記載しました。特にNginxを使用したリバースプロキシの挙動を試したかったのですが、地図表示がうまくいって良かったです。
Reference