VPS でマルチサイトの運用方法を学ぶ

VPS でマルチサイトを運用する機会があり、いくつか勉強になったことがあったので記事にします。

またこの記事では、マルチサイトをルートドメインとサブドメインを利用した複数サイトを指していることと、サーバーの設定は最小限の設定ですので本番運用される際は十分にご注意ください。



サーバー Xserver VPS
SSL Xserver ワイルドカードSSL
OS Ubuntu 22.04.2 LTS
Webサーバー nginx
アプリケーション a-blog cms

VPS でマルチサイトを運用する仕組み

この記事で触れること、実装して何ができるかについて説明します。www.example.com または example.com のルートドメインと vhost.example.com のようなサブドメインのディレクトリを用意し、nginx のバーチャルホストを利用してアクセス先を分割します。そして、バーチャルホストに SSL と a-blog cms を動作させるための設定を行い、サブドメインは SFTP のみでアクセスできるようにします。この実装を行うことでルートドメインで運用を行い、サブドメインでは特定のエンドユーザーにサイトを与え、複数のサイト運用ができます。

ディレクトリの構成

ルートドメイン
/var/www/html/ にします。
サブドメイン
/var/www/vhost/ にします。エンドユーザーには触って欲しくないファイルがある場合は、サブドメインのディレクトリ直下に2つ用意し、1つブラウザに表示するためのアプリケーションを設置し、その中からユーザーが触っていいファイルだけもう一つのディレクトリに抜き出して、ブラウザ表示用にシンボリックリンクを貼ります。これにより SFTP での制限を設け、エンドユーザーはファイルを操作することができるようにしていきます。

nginx の Webサーバー設定

まずはサンプルコードをご確認ください。ルートドメインの設定です。

# -------------------------
# サーバー設定
# -------------------------

# www つきにリダイレクト
server {
    listen 80;
    listen 443 ssl;
    server_name example.com;

    location / {
         return 301 https://www.example.com$request_uri;
    }
}

# SSL にリダイレクト
server {
    listen 80;
    server_name www.example.com;

    location / {
        return 301 https://$host$request_uri;
    }
}

# SSL の表示用サーバー設定
server {
    listen 443 ssl;
    server_name www.example.com;

    # SSL / LTS
    ssl_certificate /etc/nginx/ssl/crt/example.crt; // 公開鍵にコモンネームなどの情報をつけたもの
    ssl_certificate_key /etc/nginx/ssl/key/example.key; // 秘密鍵

    # ドキュメントルート
    root /var/www/html;
    index index.php;

    include snippets/example.conf; // a-blog cms のサーバー設定

www付きへリダイレクトしていることが server_namelocation から分かります。また、SSLとドキュメントルートが先ほど用意したパスへ繋がるように設定しています。

そしてもう一つ、サブドメインの設定も必要です。server_namevhost.example.com​ のようにサブドメインに置き換えるだけで大丈夫です。SSL については、サブドメインも含め1つの証明書で暗号化できる Xserver ワイルドカードSSL を使用しています。ですので ssl_certificate​ と ssl_certificate_key​ は、ルートドメインと共通で使用できます。ドキュメントルートもサブドメイン用のディレクトリパスに変えてください。

nginx で動かす a-blog cms

a-blog cms を動作させるためのサーバー設定も必要です。a-blog cms 同梱の .htaccess​ は Apache で動作させるためのファイルですので nginx では使えません。ルートドメインもサブドメインも a-blog cms ですので、共通のファイルで管理をして Webサーバー設定の include で以下の設定を読み込みます。

# -------------------------
# これは、a-blog cms を動作させるための設定です。Apache の .htaccess に当たります。
# -------------------------

# 隠しファイルへのアクセス禁止
location ~ /\. {
        deny all;
}

# アセットのキャッシュ・セキュリティ設定
location ~* \.(css|js)$ {
        expires 365d;
        add_header Cache-Control "public, max-age=31536000";
        add_header X-Frame-Options SAMEORIGIN;
        add_header X-Content-Type-Options nosniff;
        add_header X-XSS-Protection "1; mode=block";
        add_header Strict-Transport-Security "max-age=31536000";
        add_header Referrer-Policy "strict-origin-when-cross-origin";
        gzip on;
        gzip_types text/css application/javascript;
        gzip_vary on;
}

# 画像およびメディアファイルのキャッシュ設定
location ~* \.(gif|jpeg|jpg|png|flv|mp4|ico|svg|webp)$ {
        expires 365d;
        add_header Cache-Control "public, max-age=31536000";
        add_header ETag "";
}

# FastCGI 設定
location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;  # PHPのバージョンに応じて変更
}

# 画像のWebP対応
location ~* ^(.+)\.(jpe?g|png)$ {
        set $base $1;
        set $ext $2;
        if ($http_accept ~* "image/webp") {
            set $webp_suffix ".webp";
        }
        if ($arg_type = "original") {
            set $webp_suffix "";
        }
        try_files $base$webp_suffix /path/to/your/webp/images$uri =404;
        add_header Vary Accept;

        location ~* ^(.+)\.webp$ {
            expires 365d;
            add_header Cache-Control "public, max-age=31536000";
            add_header Content-Type image/webp;
        }
}

# ルートディレクトリの処理設定
location / {
	try_files $uri $uri/ /index.php$is_args$args;
}

# URL書き換え設定
rewrite ^/(.*)/index\.html/?$ https://$host/$1/ permanent;

SSH / SFTP

ここでは、サブドメインをエンドユーザーが触ることを想定して設定していきます。

前提として、サブドメインのサイトにはユーザーID とパスワードの発行が必要です。このユーザーID とパスワードでディレクトリ権限を与えます。ただ、これだと ssh でアクセスされセキュリティに問題があるので、SFTP でのアクセスのみ許可するようにします。

そのために SFTPサーバーの internal-sftp を使用します。internal-sftp は、外部プログラムに依存せずに、SSHデーモンの一部として動作する内部サブシステムです。internal-sftp を使うにあたって注意点があり、ChrootDirectory で指定しているディレクトリとその親達は root権限にしておく必要があります。そして、アクセスするユーザーに root権限のディレクトリの書き込み権限は与えないようにします。権限を与えていいのは、ChrootDirectory の中の ファイル / ディレクトリ のみです。もし間違っていると、セキュリティ上の理由でアクセス拒否されてしまいます。

以下が sftp の設定です。ChrootDirectory は sftp のアクセス先を設定してください。

Subsystem sftp internal-sftp
Match User !exampleUser1,!exampleUser2
	ChrootDirectory /var/www/vhost/sftp
	ForceCommand internal-sftp

以上が、ルートドメインで運用を行い、サブドメインでは特定のエンドユーザーにサイトを与え、複数のサイト運用をする仕組みです。

実装をしてみて

実装していてよく権限で困った印象があります。SFTP の ChrootDirectory だったり、a-blog cms の一部が動作しなかったことがありました。サーバー自体この時ほぼ初めて触ったこともあり、いい経験になりました。


シェアする

Webにまつわる お困りごとをご相談ください。

こんなお手伝いができます

Webコンサルタントとしてのお手伝い/UIデザインのご相談/デジタルメディアの総合プロデュース/パンフレット・DMなどのDTP、ロゴ制作などのビジュアルデザイン