ブログを自宅サーバーに引っ越した

経緯

もともと筆者のブログは、大学学部2年生のころ(2015年)に、当時所属していたサークルの友人がサーバーを立てるというので、その領域の一部をお借りして設置していた。当初は静的なHTMLサイトであったが、のちにオーナーの協力を得てWordpressを設置し、以後9年にわたって放置期間を挟みながら運営してきた。

このたび、友人が引っ越すこととなりサーバーの提供が一時停止したが、いつまでも友人の好意に甘えているのも忍びないので、会社でサーバー周りの知見を得たことも相まって、独立し自宅にサーバーを構えることとした。

自宅サーバーのメリット・デメリット

デメリット

  • 自宅のMacに外界からアクセスできるようにするということは、それ相応のリスクを抱えるということ。VPSである程度遮断できるにせよ、そのVPSのログを見てみると得体の知れないアクセス試行が大量にあることがわかる。
  • データ流出や不正アクセスの踏み台にされるなどのリスクは怖いので、セキュリティの設定はしっかりしないといけない。
  • 自宅のインターネットの速度変動が激しいと、ブログの速度変動も激しくなる。
  • 当然Macを常時起動にするので、電気代がかかる。

それでも、以下のメリットは私にとって大きいと思う。

メリット

  • サ終にともなうデータ消失のリスクがほぼない。Yahoo!ジオシティーズやinfoseekなど、一世を風靡した個人サイト構築プラットフォームのサービス終了に伴いインターネット上から消えてしまった資産は数知れないが、自宅サーバーにデータを保管しておけばそのリスクはほとんどないといえよう。流石にnginxやwpが消えたら知らん。
  • サーバーやコンテナの知識が増えて勉強になる。仕事で役立つことがある。
  • ローカルIPでブログ記事を執筆できるので、インターネットを介さず済むため、地味に動作がスムーズになる。ローカルIPだと記事が長くなってきた時にうまく動かない。なんでだろ?
  • 自分の枕の下でサーバーが動いていると思うと、「まあ私の家、サーバーありますけどw」と気持ちに余裕ができるので、多少その日嫌なことがあっても水に流せる。

構成

外界⇄VPSサーバー⇄(VPN)⇄自宅Mac mini (Sonoma 14.4)⇄Docker⇄nginx/Wordpress

筆者の居住する集合住宅は各部屋にグローバルIPが与えられないので、必然的にこの構成となる。グローバルIPを持つVPSを別途契約し、そのVPSとの間でトンネルを構築し、VPSへのリクエストを自宅Mac miniに転送することとなる。

筆者は昨年MacBookを新調し、ちょうど大学時代に研究室据置用として用いていたMac miniが遊休状態になっていた。そこでサーバーとして活用することとした。また、Dockerコンテナの中にサーバーを構築することで、大元のMac環境を壊すことなくnginxやwpを入れ、万が一のセキュリティインシデントがあった時には最悪コンテナを壊せばいい、という状態になることを企図している。

Mac mini側の設定(Docker)

まずDocker Desktopを入れたうえで、Docker imageを入れる。世の中便利なもので、VMware傘下のbitnamiが、WordPressとnginxをセットにしたコンテナをDocker hubに用意しているので、こちらをインストールすればすぐにでもWordpressのブログを構築できる。今回は、docker composeを利用してこちらのパッケージを入れた。

ただし、何もしないままではコンテナを終了させるとブログごと吹き飛ぶ。また、デフォルトの設定ではデータベースのパスワードが空っぽになっている。そこでdocker-compose.ymlは以下のように設定する。

version: '2'
services:
  mariadb:
    image: docker.io/bitnami/mariadb:latest
    volumes:
      - /path/to/your/DB/directory:/bitnami/mariadb
    environment:
      - MARIADB_USER=[user name]
      - MARIADB_DATABASE=[DB name]
      - MARIADB_PASSWORD=[DB password]
      - MARIADB_ROOT_PASSWORD=[root password]
  wordpress:
    image: docker.io/bitnami/wordpress-nginx:latest
    ports:
      - '80:8080'
      - '443:8443'
    volumes:
      - /path/to/your/DB/directory:/bitnami/wordpress
      - /path/to/your/cert/directory:/certs
    depends_on:
      - mariadb
    environment:
      - WORDPRESS_DATABASE_HOST=mariadb
      - WORDPRESS_DATABASE_PORT_NUMBER=3306
      - WORDPRESS_DATABASE_USER=[user name 上と同じ]
      - WORDPRESS_DATABASE_NAME=[DB name 上と同じ]
      - WORDPRESS_DATABASE_PASSWORD=[DB password 上と同じ]
      - WORDPRESS_USERNAME=[blogのuser name]
      - WORDPRESS_PASSWORD=[blogのpassword]
      - WP_AUTO_UPDATE_CORE=true
    build:
      context: .
      dockerfile: Dockerfile-wp
volumes:
  mariadb_data:
    driver: local
  wordpress_data:
    driver: local

基本的には、Githubの公式リポジトリにあるものと同じであるが、DBのパスワード周りを設定することと、DBのデータ、wpのデータ、証明書をMacにマウントして永続化している。また、後に述べるHTTPS化のためにcertbotをインストールする必要があるが、それはデフォルトでは入らないので、別途Dockerfileを設定しインストールする。Dockerfile-wpの中身は以下。参考文献「SSL証明書に関すること」の1番目に記載のある通りにした。

FROM bitnami/wordpress-nginx

USER 0
RUN install_packages certbot
RUN install_packages vim
USER 1001

まあcertbotとvimを手動で入れて、外から(docker execなら)rootで入れるようにする、てだけの話ですね。

ここまでできれば、docker compose up -dなどすることで、ローカルからHTTPでアクセス可能なWordpressは立つ。

このタイミングで筆者の場合は、友人からいただいていたmysqlのダンプデータをおよびwp-content配下のファイルを投入し、ブログの過去記事を復元した。

docker exec -it [mariadbのコンテナ] bash をした後に、参考文献のmysql dumpからの復元のどれかを実行したらできたはず。確か、-p を末尾に置いて、コンソールから別途パスワードを入れる形式にしないとうまくいかなかった。つまり、

mysql -u root < dump.sql -p

としEnter、その後PWを入力する形とした。

またwp-content/uploads配下をそのままMacのマウントディレクトリに持ってくることで、画像を復元できた。

Mac側の設定(VPN)

Mac App StoreからWireguardをまずインストールした。続いて、https://www.wireguardconfig.comにてconfigを作成した。Listen Portはデフォルト、Number of Clientsは1、CIDRは最小限の大きさかつ自宅のローカルIOと被らないようにするために、192.168.0.0/30 とした。Client Allowed IPsはあとで設定するVPSのローカルIPになるので、192.168.0.1/32とした。ほかは空欄でよい。出てきた設定ファイルのクライアントの分をWireguard トンネルの管理→設定ファイルのインポート、でMac側のWireguardに読み込ませる。後述のVPS側のWireguardの設定が終わったのちに、システム設定のVPNのトグルをONにすると、VPS側とのトンネルが繋がる。ping -c 3 192.168.0.1 などで適当に意思疎通確認するとよい。またMac側のファイヤウォールについても、「内蔵ソフトウェアが外部からの接続を受け入れるのを自動的に許可」、「ダウンロードされた署名付きソフトウェアが外部からの接続を受け入れるのを自動的に許可」を切っておくと安心だと思う。その他については、例えばAnydeskなど使うソフトウェアに合わせて設定するとよいだろう。

VPS側の設定

今回はablenet VPSのV0プランとした。リバースプロキシするだけなので十分だろう。月額600円弱なので、某声優事務所のファンクラブとほぼ同じぐらいの値段である。月に1回ラーメンを我慢すれば維持できる。リバースプロキシ側では、まずssh接続を可能にする。ablenet VPSであれば、まずABLE PANELに入って、初期化→Ubuntu Server 20.04 LTSをインストールする。適当にPWを設定して、一旦そのPWとユーザー名ubuntuでssh接続をする。もちろんユーザー名がubuntuの時点でパスワード認証は極めて危険なので、最低限手元で鍵作ってscpで公開鍵をVPS側に転送、公開鍵認証へ移行、PW認証を禁止、ポート変更、はすべきである。(参考文献のうちSSHに関することを参照)

ドメイン取得、DNS設定

安定のお名前.comで取得。”.com”が安かったのでそうしたが、”.yokohama”でも良かったかもしれない。横浜が好きなので。登録、契約したら、ネームサーバー設定→ドメインのDNS設定→ドメイン名を選び、DNSレコード設定を利用する、からDNSを設定する。Aレコードに契約したVPSのIPを入れることで、ドメイン名によるアクセスが可能となる。以降、ssh接続もドメイン名でやることとした。お名前.comの出番はここまで。

VPSへのWireguard, nginxインストール、設定

VPSにsshで入って、sudo apt update。

まず最初にufwの設定をしてしまうといい。原則は「不必要なポートは開けない」なので、Wireguard用の51820/udp、HTTP, HTTPS用の80, 443のTCP、SSH用のTCPだけをufw allowします。つまるところ

sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 51820/tcp
sudo ufw allow [SSH port]/tcp
sudo ufw default deny
sudo ufw reload
sudo ufw enable

をやる。これはとても重要。あとで/var/log/ufw.logとかみると、インターネット怖いってなる。

次にWireguardを入れて設定する。sudo apt install wireguardで普通に入るので、先ほど作ったconfigファイルのhostの中身を、/etc/wireguard/wg0.conf にコピペ。その後

sudo systemctl start wg-quick@wg0
sudo systemctl enable wg-quick@wg0
sudo reboot

すると、Wireguardが有効化される。こちらも適当にpingで疎通確認。192.168.0.2とかのはず。以降、VPSが再起動されてもwireguardは有効化されるが、時々なぜかpingしてやらないとお互いを見つけられないことがあるので、つながらないと思ったらやる。

次にnginxを入れる。sudo apt install nginxで入る。次に/etc/nginx/nginx.confを以下のようにいじる。

まず include /etc/nginx/sites-enabled/*; をコメントアウト。

次に、serverディレクティブを以下にする。

server{
   listen 80;
   proxy_headers_hash_max_size 1024;
   proxy_set_header Host $host;
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   proxy_set_header X-Forwarded-Host $host;
   proxy_set_header X-Forwarded-Server $host;
   proxy_set_header X-Real-IP $remote_addr;
   proxy_set_header X-Fowarded-Proto \$scheme;
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   proxy_http_version 1.1;
   server_name www.kbyk-sun.com;
   location /.well-known{
        root /var/www/適当なディレクトリ/;
   }

   location / {
     proxy_pass http://[ローカルIP];
   }
}

server{
   listen 80 default_server;
   return 444;
   }

server{
   listen 443 default_server ssl;
   server_name www.kbyk-sun.com;
   ssl_certificate [証明書の場所];
   ssl_certificate_key [証明書の場所];
   if ($host = [VPSのIPアドレス]){
        return 444;
   }
   proxy_set_header Host $host;
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   proxy_set_header X-Forwarded-Host $host;
   proxy_set_header X-Forwarded-Server $host;
   proxy_set_header X-Real-IP $remote_addr;
   proxy_set_header X-Fowarded-Proto \$scheme;
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   proxy_http_version 1.1;
   location / {
     proxy_pass https://[ローカルIP];
   }
}

この設定は2週間後に変わりました→自宅サーバーにNextcloudでオンラインストレージを立ててみた(記事執筆予定)

やってることといえば、VPSからトンネル先の自宅サーバーに飛ばすためのリバースプロキシを組んでいるだけであるが、ヘッダーは上記のようにフルで渡さないと、サイトが中途半端に表示されるとともに、なぜか非常に重くなった。

また、IPアドレス直打ちのアクセスは大抵よからぬことを試みようとする海外の連中なのでブロックする。nginx独自のステータスコードである444を返すことで、強制的に接続を切断する。hash_max_sizeは警告が出たのでデフォルトの2倍にしてみたがまだダメだった。原因はわからないが動いているのでよいことにする。

また、certbotをつかってHTTPS化するために、/.well-known配下へのファイルをcertbotがアクセスできるように、場所を一旦作っておく。

VPSのHTTPS化

certbotで行う。sudo apt update→sudo apt install certbotでcertbotを入れる。
その後、先ほどnginx.confに設定したディレクトリを活用して、certbot certonly –webroot -w /var/www/適当なディレクトリ -d [ドメイン]
を実行することで、簡単にHTTPS化ができる。

WordPressのHTTPS化

本節の内容はやらなくていいことが後日判明。443ポートから、直接http:// のローカルIPへproxy_passすればよい。VPSと自宅サーバーの間はVPNで結ばれているので、secureと考えてよい。

一応、bitnamiのWordpressをHTTPS化する方法はあるが、記事が長くなるので概略だけ。

概略:先のDockerfileの設定でcertbotは入っているので、
/opt/bitnami/nginx/conf/server_blocks/wordpres-server-block.conf
をいじって、/.well-knownを一時的にallowする。出てきた証明書を、永続化したフォルダに入れ、上述のconfファイルに加筆することでHTTPS化できる。

まとめ

今回は、以上の方法で弊Blogを自宅サーバーに移転した。Blogだけでも勿体無い気もするので、今後も自宅サーバーをいじって遊んでいきたい。

次回:Nextcloudを使って共有ファイルストレージを自宅サーバーに立ててみた

参考文献

VPS/VPNに関すること:

リバースプロキシに関すること:

SSL証明書に関すること:

mysqldumpに関すること:

SSHサーバーに関すること:


コメント

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です