はじめに
本サイトでは、SynologyNASをつかったWordPress Webサーバ(以下「Webサーバー」と記載)を紹介してきました。
ただ、NASが結構高価であるため、ちょっと試してみるというわけにはいきません。
また、ルーターでポート開放するので、セキュリティ上不安だったりします。
そこで、今回は、シングルボードコンピュータとして有名なRaspberryPi(以下「ラズパイ」と記載)を使ったWebサーバーの作り方を紹介します。
OSはLinuxを使用します。ラズパイでは専用にチューニングされたLinuxのRaspberry Pi OSを使用します。
サーバーなどは、Dockerを使って実装します。
また、ポート開放せずにCloudflare Tunnelをつかって、Webサイトを外部公開します。
Raspberry Pi OSとUbuntu はどちらも、DebianをベースにしたLinuxのため、PC + Ubuntu serverでも(ステップ1)以降は、ほぼ同じ作業でWebサーバーが作れます。
完成形は下図。大まかに、2ステップです。

- (ステップ1)自宅内専用(外部公開しない)Webサーバーの作成
外部公開しないので、気兼ねせずに、自宅内だけでいろいろ実験できます。 - (ステップ2)作ったWebサーバーの外部公開(Cloudflare Tunnelを利用)
Cloudflareを利用すれば、自宅にWebサーバーを作った際に、通常は必要なルーターのポート解放などせずに、また安全に外部公開ができます。
今回は(ステップ1)までを紹介します。
準備
必要なもの
- Raspberry Pi 5(4Bや3Bでも作れますが、5は4Bの2倍ほどの性能があるので、5をお勧めします。
RAMは4GBのものでも十分です。2サイト動かしても2GBも消費しません。
- ストレージ:microSDカード、USBメモリー、USB接続SSDのいずれか。
お試しであれば、USBメモリをお勧めします。32GBほどあれば十分です。
本格的に運用するのであれば、SSDでRAID1を組んだほうがよいです。
- ヒートシンク/ケース
まずは安いのでよいので、ヒートシンク付きケースをえらびましょう。
種類がものすごいたくさんあるので迷いますが、何を買ってもあとできっと買い替えたくなります。 - 電源アダプター
Raspberry Pi 5でも、3A出力のものでつかえますが、5A出力のものをおすすめします。
Amazonなどで、ラズパイ用電源で検索すれば、見つかります。 - OSインストール用PC
OSのインストール用にPCが必要です。WindowsでもMacでも可。Linuxでも可です。 - ドメイン
外部公開には必須です。ちなみに本サイトのドメインは取得費&1年目(2024年)は1円、2年目以降は1,721円/年かです。契約は1年単位で更新(ドメインによって異なる)です。XServer Domainがおすすめです。
記事内では、ドメインをxxx.comで記載しています。これをご自分のドメインに変更してください。
OSのインストール
PCを使って、RaspberryPi OSをストレージにインストールします。
今回は、GUIを備えたRaspberry Pi OS、CUIのRaspberry Pi OS Liteどちらでもよいです。慣れてない方は、前者をお勧めします。
専用のRaspberry Pi Imagerを使えば簡単です。
インストール方法は、いろいろな方が紹介しているので、ここでは割愛させていただきます。
起動、OSのアップデート
起動してログインしたら、以下コマンドでOSをアップデートします。
# 情報を最新にする
sudo apt update
# 実際のアップデートコマンド
sudo apt full-upgrade
# 途中で本当にアップデートするか確認があるので、y を入力終わったら念の為、再起動しておきます
ipアドレスの固定
デフォルトではDHCPによってルーターからipアドレスを取得しています。
起動するごとに変わる可能性があるので、固定します。
詳細はこちら
Docker(docker compose)のインストール
各種機能を構築するのに、Docker(docker compose)を使います。失敗してもOSに影響がなく、その部分だけやりなおしたり、削除したりすればよいので、非常に楽です。いくつか違う設定で試してみるなんてことも簡単です。
(ステップ1)自宅内専用(外部公開しない)Webサーバーの作成
通信のイメージ
自宅内のPCのWebブラウザ(Google Chromeや、Microsoft Edgeなど)から、xxx.comにアクセスした場合の流れです。インターネットの世界での処理を、自宅内だけで構築します。

- 自宅内PC(Client PC)でWebブラウザのアドレスにxxx.comを入力し、アクセス開始すると、PCがDNSサーバー(ラズパイのipアドレスに設定しておく)にxxx.comのipアドレスを問い合わせる
- DNS Server(coredns ラズパイ内Dockerコンテナ)で、xxx.comに対し、あらかじめ設定しておいたラズパイのipアドレスを、自宅PCに返す
- 自宅内PCが、そのIPアドレス(=ラズパイ)へhttps://xxx.comのデータを要求
- リバースプロキシ(Caddy ラズパイ内Dockerコンテナ)が、「xxx.com」をみて、Webサーバー(WordPress+MariaDB+Redis ラズパイDockerのコンテナ名:wp-main、ポート80)へ要求を送る
- ラズパイ内のWebサーバーが、表示するWebデータを返す
- 自宅内PC(Client PC)のWebブラウザに表示される
という通信の流れになります。
Dockerのフォルダ構成
<ユーザーフォルダ>
└ docker/
├── coredns/ ・・・DNSサーバー
├── Caddy/ ・・・リバースプロキシ
└── wp-main/ ・・・WordPress Webサーバーmkdir ~/dockerdockerの中にあるフォルダの作成は、後の作業内で行います。
Docker network 「wpnet」作成
それぞれのdockerコンテナが簡単な設定でお互いに通信できるよう、同じdockerネットワーク内(今回は名称を、「wpnet」としました)で動くようにしていきます。
そのネットワークを以下コマンドで作成します。
「wpnet」という名前は、お好きなものに変更してください。
Docker networkの名称「wpnet」を変更した場合は、下記に記載するすべてのコマンド、docker-compose.yamlの「wpnet」を書き換えてください。
docker network create wpnetDNSサーバーをつくる
corednsを使用しました。
フォルダ、ファイル構成
<ユーザーフォルダ>
└ docker/
├── coredns/ ・・・DNSサーバー
│ ├── docker-compose.yaml
│ └── config/
│ ├── Corefile
│ └── hosts cd ~/docker
mkdir coredns
# corednsへ移動
cd coredns
mkdir configdocker-compose.yaml
テキストエディタnanoを使って作成します。
nano docker-compose.yamlservices:
coredns:
image: coredns/coredns
container_name: coredns
command: -conf /etc/coredns/Corefile
restart: unless-stopped
expose:
- '53'
- '53/udp'
ports:
- '53:53'
- '53:53/udp'
volumes:
- './config:/etc/coredns'config/Corefile
nano config/Corefile.:53 {
whoami
# 自身のレコードにない場合はルータ 192.168.1.1 へ
forward . 192.168.1.1
# Google DNSサーバーにしたい場合は8.8.8.8を指定
# forward . 8.8.8.8
errors
log . "{proto} {remote} is Request: {name} {type} {>id}"
hosts /etc/coredns/hosts {
fallthrough
}
reload
}ルーターのipアドレスは、ご自分のものへ変更してください。外部DNSサーバー(例Google DNSサーバーだと8.8.8.8)を指定してもOKです。
config/hosts
nano config/hosts192.168.1.200 xxx.com
192.168.1.200 sub.xxx.com192.168.1.200は、ラズパイのipアドレス。xxx.comは設定するドメインとしてください。別のドメイン(今回はサブドメイン sub.xxx.com)も設定したい場合、2行目のようにします。
起動(参考:停止)
cd ~/docker/coredns
docker compose up -dフォルダ coredns にいる状態で起動する必要があります。起動した状態でラズパイ自体を再起動しても、ふたたびこのコマンドで起動させる必要はありません。
停止させたい場合は、以下コマンドです。
docker compose downClient PCのDNS設定
クライアントPCが、先ほど設定したDNSにドメインのipアドレスを問い合わせるように設定します。

Windows11の場合、ipv6が優先されるようですので、ipv6自体をoffにするか、ipv6 DNSサーバーにラズパイのipv6 ipアドレスを設定します。
動作確認
Windowsであれば、コマンドプロンプトにて「nslookup」コマンドで確認ができます。
C:\Users\mohlog>nslookup xxx.com
サーバー: UnKnown
Address: 192.168.1.200
名前: xxx.com
Address: 192.168.1.200ターミナルにて、dig <ドメイン名> で確認できます。
Caddy(Reverse Proxy)
リバースプロキシにはCaddyを使用しました。
フォルダ、ファイル構成
<ユーザーフォルダ>
└ docker/
├── Caddy/
│ ├── docker-compose.yaml
│ ├── Caddyfile
│ └── certs/cd ~/docker
mkdir Caddy
mkdir Caddy/ceerts
# ~/docker/Caddyへ移動
cd CaddyローカルCA
mkcertをインストール
Caddyを自前の証明書で動かすため、mkcert をインストールして、証明書を作成します。
sudo apt update
#必要なツールをインストール
sudo apt install -y libnss3-tools curl
#mkcertをインストール
curl -JLO "https://dl.filippo.io/mkcert/latest?for=linux/arm64"
chmod +x mkcert-v*-linux-arm64
sudo mv mkcert-v*-linux-arm64 /usr/local/bin/mkcertxxx.com (と sub.xxx.com)用の証明書を作成
今回、xxx.comだけでなく、サブドメインsub.xxx.comも使えるようにしました。
# ~/docker/Caddy/certs へ移動してそこに作成
cd ~/docker/Caddy/certs
mkcert xxx.com sub.xxx.com以下の2つのファイルが生成されます。
- xxx.com+1.pem
- xxx.com+1-key.pem
xxx.comだけでよい場合のコマンドは、
mkcert xxx.com
となります。生成されるファイルは「+1」がない
- xxx.com.pem
- xxx.com-key.pem
となります。
mkcert xxx.com "*.xxx.com"
とすれば、サブドメインすべての証明書が作成されます。
docker-compose.yaml
テキストエディタnanoを使って作成します。
# ~/docker/Caddy へ移動
cd ~/docker/Caddy
nano docker-compose.yamlservices:
caddy:
image: caddy:2.11-alpine
container_name: caddy
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- ./certs:/certs
# - ./caddy_data:/data
# - ./caddy_config:/config
networks:
- wpnet
restart: unless-stopped
networks:
wpnet:
external: true
Docker ネットワーク名を変えた場合は、「wpnet」の部分(2か所あり)を変更してください。
Caddyfile
nano Caddyfilexxx.com {
tls /certs/xxx.com+1.pem /certs/xxx.com+1-key.pem
reverse_proxy wp-main:80
}
sub.xxx.com {
tls /certs/xxx.com+1.pem /certs/xxx.com+1-key.pem
reverse_proxy wp-sub:80
}ファイル名:xxx.com+1.pem、xxx.com+1-key.pem
は、mkcertで作成した証明書のファイル名です。
起動(参考:停止)
cd ~/docker/Caddy
docker compose up -dWebサーバーをつくる xxx.com
フォルダ、ファイル構成
<ユーザーフォルダ>
└ docker/
├── wp_main/ ・・・Webサーバー
│ ├── docker-compose.yaml
│ ├── Dockerfile
│ ├── conf/
│ │ └── php.ini
│ ├── db/
│ └── radis/
cd ~/docker
mkdir wp_main
# wp_mainへ移動
cd wp_main
mkdir conf db redisdocker-compose.yaml
テキストエディタnanoを使って作成します。
nano docker-compose.yamlservices:
wordpress:
build:
context: .
dockerfile: Dockerfile
#7は、7.x.xまで対応、php8.4はphp8.4.xまで対応
image: wordpress:7-php8.4-apache
container_name: wp-main
# ports:
# - 8080:80
depends_on:
db:
condition: service_started
redis:
condition: service_healthy
volumes:
- ./wordpress:/var/www/html:rw
- ./conf/php.ini:/usr/local/etc/php/conf.d/php.ini:ro
#image: wordpress:7-php8.4-apacheでは以下は不要
# - ./conf/headers.load:/etc/apache2/mods-enabled/headers.load:ro
environment:
WORDPRESS_DB_HOST: db-main
WORDPRESS_DB_USER: wpdbuser
WORDPRESS_DB_PASSWORD: パスワード
WORDPRESS_DB_NAME: db_wp-main
WORDPRESS_CONFIG_EXTRA: "define('WP_REDIS_HOST', 'redis_main');"
restart: unless-stopped
#ループバック対策
# extra_hostが不要な場合と必要な場合がある。Wordpressでループバックエラーが出る場合は、削除。
# Caddyの動くサーバーiPアドレスを指定
extra_hosts:
- "xxx.com:192.168.1.200"
#Docker network
networks:
- wpnet
db:
image: mariadb:11.8
container_name: wp_main_db
security_opt:
- no-new-privileges:true
hostname: db-main
#Docker外からもdbにアクセス出きるようにするには、コメントアウトを消す
# ports:
# - 13306:3306
environment:
MYSQL_DATABASE: db_wp-main
MYSQL_USER: wpdbuser
MYSQL_PASSWORD: パスワード
MYSQL_ROOT_HOST: localhost
MYSQL_ROOT_PASSWORD: root
TZ: Asia/Tokyo
volumes:
- ./db:/var/lib/mysql:rw
healthcheck:
# mariadb ver 11.8の場合
test: ["CMD-SHELL", "mariadb -uroot -proot -e 'SELECT 1;' || exit 1"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
restart: unless-stopped
#Docker network
networks:
- wpnet
redis:
image: redis:8.4-alpine
hostname: redis_main
container_name: wp_main_redis
command: [
"redis-server",
"--maxmemory", "256mb",
"--maxmemory-policy", "allkeys-lru"
]
healthcheck:
test: ["CMD-SHELL", "redis-cli ping || exit 1"]
environment:
TZ: Asia/Tokyo
volumes:
- ./redis:/data:rw
restart: unless-stopped
#Docker network
networks:
- wpnet
#Docker network
networks:
wpnet:
external: true
Docker ネットワーク名を変えた場合は、「wpnet」の部分(4か所あり)を変更してください。
Dockerfile
nano DockerfileFROM wordpress:7-php8.4-apache
#docker-compose.yamlのdocker imageのバージョンに合わせる
#EWWW Image Optimizerプラグイン対策
# 必要なツールをインストール
RUN apt-get update && apt-get install -y \
gifsicle \
jpegoptim \
optipng \
libjpeg-progs \
&& apt-get cleanconf/php.ini
nano conf/php.inimax_execution_time=300
memory_limit=512M
post_max_size=512M
upload_max_filesize=512M
max_input_time=600
max_input_vars=2000
date_timezone=Asia/Tokyo
opcache.revalidate_freq=60
opcache.fast_shutdown=1
opcache.jit=1205
opcache.jit_buffer_size=16M起動(参考:停止)
cd ~/docker/wp_main
docker compose up --build -dWebサーバーをつくる sub.xxx.com
上記「Webサーバーをつくる xxx.com」と基本同じです。内容を
- main → sub
- xxx.com → sub.xxx.com
と変更すればOKです。
container_name が重複しないようにしてください
クライアントPCでmkcert で作った証明書を信頼させる
ここまでで、「自宅内専用(外部公開しない)Webサーバー」は完成していますが、クライアントPCで、xxx.com(もしくはsub.xxx.com)にアクセスすると、「信頼できないサイト」と表示されてしまいます。
これを直します。

Raspberry Pi(サーバー)で mkcert の root CA の場所を確認する
Raspberry Pi(サーバー)でmkcert -CAROOTに、rootCA.pemがあるかを確認します。
ls /home/<ユーザー名>/.local/share/mkcert/home/<ユーザー名>/.local/share/mkcert
このディレクトリの中に、次のファイルがあるとおもいます。
- rootCA.pem
- rootCA-key.pem
必要なのは rootCA.pem の方です。
rootCA.pem をクライアントPCにコピーする
ターミナル(macOS / Linux)、コマンドプロンプト(Windows)で、以下コマンドでrootCA.pemをクライアントPCにコピーします。
scp <ユーザー名>@<RaspberryPiのIPまたはホスト名>:/home/<ユーザー名>/.local/share/mkcert/rootCA.pem ./rootCA.pem をクライアントPCに信頼させる
macOSの場合
- Spotlight で:キーチェーンアクセス を検索して開く
- rootCA.pem を ダブルクリックしてインポート
- ここが重要
- キーチェーンは必ず「システム」を選ぶ
- 「ログイン」では Safari が信頼しない
- インポート時に「どのキーチェーンに追加しますか?」と聞かれたら 必ず「システム」 を選択。
- ここが重要
- 証明書の「信頼」設定を開く
- キーチェーンアクセスで rootCA.pem をダブルクリックすると 証明書の詳細ウィンドウが開く。
- 左上の「▶ 信頼」をクリックして展開
- 「この証明書を使用するとき」→ 「常に信頼」 に変更
- これを設定すると、下の項目(SSL、X.509 基本ポリシーなど)も自動で「常に信頼」になる。ウィンドウを閉じると macOS が管理者パスワードを求めるので入力。
- Safari を完全終了(⌘ + Q)して再起動
- Safari はキャッシュが強いので、 完全終了しないと新しい root CA を読み込まない。
Windows11の場合
1.証明書の名称を変更する
rootCA.pem → rootCA.crt
2.rootCA.crt を ダブルクリックする
開いたウィンドウで、「証明書のインストール」を行う

3.「証明書のインポートウィザード」が開く。
「現在のユーザー」か「ローカルコンピュータ」をえらぶ
「ローカルコンピュータ」であれば、ログインユーザー全員に反映される。

4.「証明書をすべての次のストアに登録する」で、「参照」から「信頼されたルート証明機関」 を選択

「次へ」をクリック
5.「完了」をクリックして終了


Linuxの場合
1.rootCA.pem を名前を変えて /usr/local/share/ca-certificates に配置
sudo cp rootCA.pem /usr/local/share/ca-certificates/mkcert-rootCA.crt※ 拡張子は .crt にする必要がある。
2. CA ストアを更新
sudo update-ca-certificatesUpdating certificates in /etc/ssl/certs…
rehash: warning: skipping ca-certificates.crt, it does not contain exactly one certificate or CRL
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d…
ca-certificates-java (20240118) のトリガを処理しています …
Replacing debian:mkcert-rootCA.pem
done.
done.warningは気にする必要なし
削除するときは、mkcert-rootCA.crtをけして、sudo update-ca-certificates –fresh とすればOK
3.Chrome (Linux)へのインポート
Linuxの場合は、システム(OS)側への登録は成功していても、Chrome(またはChromiumベースのブラウザ)が独自に管理している「認証局(CA)リスト」に mkcert の CA が登録する必要があります。
- Chromeの右上の「︙(三点リーダー)」から 「設定」 を開く。
- 左メニューの 「プライバシーとセキュリティ」 > 「セキュリティ」 をクリック。
- 下の方にある 「証明書の管理」(または「デバイス証明書の管理」)をクリック。
※新しい設定画面が開くので、「ローカル証明書」→カスタム(自分でインストール) - 信頼できる証明書「認証局」(Authorities)タブを選択し、「インポート」 ボタンを押す。
- ファイル選択ダイアログで、
mkcert -CAROOTで確認したディレクトリにあるrootCA.crtを選択する。










コメント