ポート開放・固定IP不要!Raspberry PiとDocker、Cloudflare Tunnelで作る、堅牢でハイメンテな自宅WordPressサーバー

Raspberry Pi

0. この記事で構築するもの

家に眠っている古いRaspberry Piを、安全で実用的なWebサーバーとして蘇らせてみませんか?

この記事では、Raspberry Pi 3B+、Docker、そしてCloudflare Tunnelを組み合わせ、自宅サーバー運用の大きな壁であった「ポート開放」「固定IP」「SSL証明書」の問題をすべて解決する、モダンなWordPress環境の構築手順を解説します。

完成図(アーキテクチャ)

構築する環境の全体像は以下の通りです。

[インターネット] ⇔ [Cloudflareネットワーク] ⇔ [自宅のラズパイ (Dockerコンテナ)]

Cloudflareが盾となり、外部からの直接アクセスを完全に防ぐことで、非常にセキュアな環境が手に入ります。

この構成で得られる3つのメリット

  1. ポート開放が一切不要: ルーターに穴を開ける必要がなく、ご家庭のネットワークを危険に晒しません。
  2. 固定IPアドレスが不要: インターネット回線の契約に縛られません。
  3. SSL証明書が無料かつ自動更新: 面倒な証明書の管理から解放されます。

私が実際にハマった「502エラー」や「リダイレクトループ」といった落とし穴の回避策も網羅した決定版です。さあ、始めましょう!

1. 準備するもの

作業をスムーズに進めるため、事前に以下のものを準備してください。

ハードウェア

  • Raspberry Pi 3B+ 本体: もちろん、4や5でも構いません。
  • 高耐久SDカード(最重要): サーバーとして24時間稼働させるため、書き込み耐性の高い「High Endurance」や「産業用」モデルを強く推奨します。これがサーバーの寿命を左右します。
  • 電源アダプター: 安定した電力供給は、安定したサーバー運用の基本です。

ソフトウェア & サービス

  • Raspberry Pi OS: OSをインストールし、SSHでログインできる状態にしておいてください。(Lite版で十分です)
  • Cloudflare アカウント: 未登録の場合は、公式サイトからサインアップしてください。
  • 独自ドメイン: お名前.comやGoogle Domainsなどで取得したドメインを、Cloudflareの管理下に置いておく必要があります。(ネームサーバーをCloudflareに向ける設定を済ませておいてください。Cloudflareでも取得可能です。←これが一番楽)

2. 基盤構築:Raspberry Piのセットアップ

まず、サーバー本体となるラズパイの基礎を固めます。

2-1. サーバーの安定化:Swap領域の拡張

メモリ1GBのRaspberry Pi 3B+でWordPressを動かすには、メモリ不足を補う「スワップ(仮想メモリ)」が不可欠です。しかし、スワップはSDカードへの書き込みを急増させ、寿命を縮める原因にもなります。だからこそ、高耐久SDカードが活きてくるのです。

デフォルトの100MBでは力不足なため、2GBまで拡張します。

  1. ツールのインストール
    sudo apt install dphys-swapfile -y
    
  2. 設定ファイルの編集
    sudo nano /etc/dphys-swapfile
    

    ファイルの中から CONF_SWAPSIZE という項目を探し、行頭の # を削除して数値を 2048 に書き換えます。

    # set size to absolute value, leaving empty (default) then uses computed value
    #   you most likely don't want this, unless you have an special disk situation
    # CONF_SWAPSIZE=100
    CONF_SWAPSIZE=2048
    
  3. 設定の反映
    Ctrl + OEnter で保存し、Ctrl + X で終了後、以下のコマンドで設定を反映させます。

    sudo systemctl restart dphys-swapfile
    

2-2. コンテナ環境の構築:Dockerのインストール

次に、WordPressやデータベースを「コンテナ」として部品のように管理できるDockerをインストールします。

  1. インストールスクリプトの実行
    公式が配布しているスクリプトを使えば、Docker本体と関連ツールが一括で入ります。

    # パッケージリストを最新の状態に
    sudo apt update && sudo apt upgrade -y
    
    # 公式スクリプトをダウンロードして実行
    curl -fsSL https://get.docker.com -o get-docker.sh
    sudo sh get-docker.sh
    
  2. sudoなしでDockerコマンドを実行する設定
    このままでは毎回 sudo を付ける必要があり不便なため、現在のユーザーをdockerグループに追加します。

    sudo usermod -aG docker $USER
    

    【重要】 設定を反映させるため、ここで一度ラズパイからログアウトし、再ログインしてください。

  3. インストール確認
    再ログイン後、以下のコマンドでバージョン情報が表示されれば、Dockerの準備は完了です。

    docker compose version
    

3. ローカル環境でWordPressを立ち上げる

いよいよWordPressを構築しますが、最初から世界に公開するのは危険です。まずは安全な自宅LAN内だけでアクセスできるサイトを立ち上げ、動作確認を行います。

3-1. 設計図の作成:docker-compose.yml

作業用のディレクトリを作成し、コンテナ構成を定義する docker-compose.yml ファイルを作成します。

mkdir ~/wordpress-docker
cd ~/wordpress-docker
nano docker-compose.yml

エディタが開いたら、以下の内容を貼り付けてください。

services:
  # データベース (MariaDB)
  db:
    image: mariadb:10.6
    volumes:
      - db_data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: your_strong_db_password # ※必ず変更してください
      MYSQL_DATABASE: wordpress
      MYSQL_USER: user
      MYSQL_PASSWORD: your_strong_user_password   # ※必ず変更してください
    restart: always

  # WordPress本体
  wordpress:
    image: wordpress:latest
    ports:
      - "8000:80"
    volumes:
      - ./html:/var/www/html  # WordPressファイルをホスト側と同期
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: user
      WORDPRESS_DB_PASSWORD: your_strong_user_password # ※上で設定したパスワード
      WORDPRESS_DB_NAME: wordpress
    depends_on:
      - db
    restart: always

  # Cloudflare Tunnel(★今はまだ使わないのでコメントアウト)
  # tunnel:
  #   image: cloudflare/cloudflared:latest
  #   restart: always
  #   command: tunnel run
  #   environment:
  #     - TUNNEL_TOKEN=ここに後で取得するトークンを貼り付け

  # WordPressコマンドラインツール(後のURL置換で使用)
  cli:
    image: wordpress:cli
    volumes:
      - ./html:/var/www/html
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: user
      WORDPRESS_DB_PASSWORD: your_strong_user_password # ※上で設定したパスワード
      WORDPRESS_DB_NAME: wordpress
    depends_on:
      - db

volumes:
  db_data:

3-2. 権限問題を解決し、初期起動する

DockerでWordPressを動かす際、コンテナが生成したファイルの所有者問題で、後から編集できなくなるトラブルが頻発します。これを未然に防ぐため、あらかじめ適切な権限を設定します。

  1. WordPressのファイルを格納するフォルダを作成
    mkdir html
    
  2. フォルダの所有権と権限を設定
    所有者をWordPress(ID:33)に、グループを現在のユーザー($USER)に設定し、両者が書き込めるようにします。

    sudo chown -R 33:$USER ./html
    sudo chmod -R 775 ./html
    
  3. コンテナを起動
    docker compose up -d
    

これでコンテナがバックグラウンドで起動しました。PCのブラウザから http://<ラズパイのIPアドレス>:8000 にアクセスし、画面の指示に従ってWordPressのインストール(サイト名や管理者アカウントの作成)を完了させてください。

4. Cloudflare Tunnelで世界へ公開する

ローカルでの動作が確認できたら、いよいよCloudflareの力を使って、このサイトを安全にインターネットへ公開します。

4-1. トンネルの作成と「鍵」の取得

まず、ラズパイとCloudflareを接続するための「トンネル」を作成し、接続用の「鍵(トークン)」を取得します。PCのブラウザで Cloudflare Zero Trust ダッシュボード を開いてください。

  1. NetworksTunnels を開き、Create a tunnel をクリック。
    Cloudflared Connectorを選択

  2. Connectorタイプは Cloudflared を選択して Next をクリック。
    Cloudflare Tunnels一覧画面

  3. トンネルに任意の名前(例: raspi-wordpress)を付けて Save tunnel をクリック。
    トンネル名を入力

  4. Install connector 画面で Docker タブを選び、表示されたコマンドの中からトークン部分(eyJh... で始まる非常に長い文字列)だけをコピーします。このトークンは後で使うので、テキストエディタなどに控えておいてください。
    Docker用のトンネル トークンを取得

4-2. ドメインと紐付ける(公開設定)

次に、取得したドメインとトンネルを紐付け、「このドメインへのアクセスが来たら、トンネルを通してラズパイへ送る」というルールを設定します。

この時点ではまだトンネルが起動していないため、サイトは表示されませんが、それで正常です。 先にCloudflare側で「行き先」を定義しておきます。

  1. 先ほどのトンネル設定画面で Public Hostname タブを開き、Add a public hostname をクリックします。
  2. 以下のように設定します。ここが最大の落とし穴なので慎重に進めましょう。
  • Subdomain/Domain: 公開したいドメイン(例: blog.example.com
  • Service: HTTP
  • URL: wordpress:80

    Public Hostnameの設定

    ⚠️ なぜ「wordpress:80」なのか?

    ここで localhost:8000 と指定すると、後で 502 Bad Gateway エラーになります。TunnelコンテナはDockerの内部ネットワークにおり、ホストOS(ラズパイ)のlocalhostは見えません。コンテナ同士はサービス名で通信するため、WordPressコンテナのサービス名 (wordpress) とその内部ポート (80) を指定するのが正解です。

4-3. ラズパイからトンネルを起動する

Cloudflare側の設定が完了したので、いよいよラズパイからトンネルを起動して世界と接続します。

  1. docker-compose.yml を編集
    ラズパイに戻り、docker-compose.yml を編集します。

    nano ~/wordpress-docker/docker-compose.yml
    

    tunnel: セクションのコメントアウト(#)を全て解除し、TUNNEL_TOKEN に「4-1」で控えておいたトークンを貼り付けます。

     # ... (wordpressサービスの下)
    
     # Cloudflare Tunnel(コメントアウトを解除!)
     tunnel:
       image: cloudflare/cloudflared:latest
       restart: always
       command: tunnel run
       environment:
         - TUNNEL_TOKEN=ey...(ここに取得したトークンを貼り付け)
    
     # ... (cliサービスの上)
    
  2. コンテナを再起動
    保存後、以下のコマンドでコンテナを再起動し、設定を反映させます。

    docker compose up -d
    

    数秒待つとCloudflareのダッシュボードでトンネルのステータスが HEALTHY に変わり、あなたのドメインでサイトが表示されるようになります。

4-4. SSL通信を有効化(リダイレクトループ対策)

サイトが表示されたものの、今度は「リダイレクトが繰り返し行われました」というエラーが発生する場合があります。これは、CloudflareからWordPressへの通信が暗号化(HTTPS)されているにも関わらず、WordPress側がそれを認識できずにHTTPにリダイレクトしようとするためです。

wp-config.php に「Cloudflareからの通信は信頼できるHTTPS通信だよ」と教えてあげるおまじないを追記します。

nano ~/wordpress-docker/html/wp-config.php

ファイルの先頭、<?php のすぐ下に以下のコードを追加してください。

<?php
// Cloudflare SSL対応 (リダイレクトループ防止)
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
    $_SERVER['HTTPS'] = 'on';
}
// ... (元からあるコード)

5. 仕上げ:サイトURLの正規化

これでサイトは正しく表示されるようになりましたが、最後の仕上げが残っています。WordPressのデータベース内には、初期設定時のローカルアドレス (http://<ラズパイのIPアドレス>:8000) が記録されたままです。これを正しい公開ドメイン (`https://…`) に一括で書き換えないと、画像が表示されないなどの不具合が発生します。

docker-compose.yml に仕込んでおいた cli コンテナがここで役立ちます。

# 【重要】IPアドレスとドメインはご自身の環境に合わせてください
cd ~/wordpress-docker

# 1. ドライラン(予行演習:どこが置き換わるかを確認)
docker compose run --rm cli wp search-replace 'http://192.168.1.95:8000' 'https://blog.example.com' --dry-run

# 2. 本番実行(実際にデータベースを書き換え)
docker compose run --rm cli wp search-replace 'http://192.168.1.95:8000' 'https://blog.example.com'

# 3. キャッシュクリア(念のため)
docker compose run --rm cli wp cache flush

6. まとめ

お疲れ様でした! これで、古いRaspberry Pi 3B+が「SSL完全対応・外部アクセス可能・メンテナンス容易」な、堅牢なWebサーバーとして完全に蘇りました。

コンテナ化されているため、バックアップやサーバーの引っ越しも非常に簡単です。この構成は一度作ってしまえば本当に管理が楽なので、ぜひ挑戦してみてください!

コメント

タイトルとURLをコピーしました