今回はコンテナで、Nextcloud の SSL(Let’s Encript) 環境を作ってみましたので、手順をご紹介します。仮想化技術のおかげでどんどん楽にサーバーが立てられるようになっています。20年以上自宅サーバーを構築/管理していますが、VM だとスナップショットがあれば問題が起きる前に戻せますし、ちょっとお試しで・・・なんてことも気楽にできます。OSのインストールから何度もやり直していた、物理ハードにセットアップしていたころが馬鹿らしいです。さらにコンテナだと、ほとんど考えることなく、ワンラインで気楽にサーバーの起動停止ができるので、よりコンテンツに時間を割くことができるようになっています。インフラエンジニアとしては肩身が狭くなっていきます。しっかり勉強していきましょう。
バーチャルマシン(VM)とコンテナの違いはここでは話しませんが、今回はコンテナ技術(podman)を使って Nextcloud のサーバー構築したお話です。
参考:
https://docs.podman.io/en/v4.4/markdown/podman-pod-create.1.html
https://docs.podman.io/en/latest/markdown/podman-run.1.html
https://hub.docker.com/_/nextcloud
https://hub.docker.com/_/mysql
https://hub.docker.com/_/redis
https://docs.bunkerweb.io/1.4/
今回紹介する Nextcloud の構成
今回紹介するのは、Nextcloud と redis、mariadb の3つのコンテナを1つの pod として扱います。この pod はバックエンドになります。フロントエンドには、 Bunkerweb のコンテナを利用しました。ここでは、Bunkerweb については、細かくは触れませんがセキュアなフロントエンドとして利用することができますし、Let’s Encript の操作を自動化してくれ、さらに複数のバックエンド(ウェブサイト)に名前(DNS名)で振り分けることも可能な(簡単にマルチサイト化できる)ため採用しました。
環境
podman version 4.6.1
コマンド操作は全て、root アカウントで実施しています。
下準備
コンテナを終了させても、Nextcloud はデータを保持したいため、永続化ボリュームが必要です。永続化ボリュームなどを配置するために、ディレクトリを作成します。chown は後の pod を作成させる際に、ホストとコンテナ間でuid/gidのマッピングを行っているため、これに合わせて設定します。
mkdir -p /var/local/containers/nextcloud/app/{data,conf,html}
chown 100999.100999 /var/local/containers/nextcloud/db
chown -R 100033.100033 /var/local/containers/nextcloud/app
また、ログを残すためにログのディレクトリも作成しておきます。
バックエンドの Bunkerweb のための永続化ボリュームの準備し、ファイアウォールを開けておきます。
chown 100101.100101 /var/local/containers/bunkerweb/data
firewall-cmd --add-port=80/tcp --permanent
firewall-cmd --add-port=443/tcp --permanent
firewall-cmd --reload
バックエンド(Nextcloud)を立ち上げる
バックエンドとなる pod を準備します。この pod は、ホストの 2080 ポートへアクセスされると、pod(コンテナ)の 80 ポートへアクセスさせます。また、uid や gid は、コンテナの 0 をホストの 100000 にマップします。
pod の中に、mariadb のコンテナを作成します。–log-driver を指定しているのは、–log-opt path に指定したファイルにログを吐かせるためです。デフォルトでは思ったところにログを吐いてくれませんでした。latest が安定バージョンのようです(現時点で 11.2.2 でした)。-v で ローカルホストの /var/local/containers/nextcloud/db に コンテナの /var/lib/mysql をマウントさせます。これでコンテナをつぶしても DB が残ります。「:Z」 は、SELinux のためのオプション(プライベート非共有ラベル)です。
--log-driver k8s-file --log-opt path=/var/log/containers/nc-db.log \
-e MYSQL_ROOT_PASSWORD="password" -e MYSQL_DATABASE="nextcloud" -e MYSQL_USER="nextcloud" -e MYSQL_PASSWORD="password" \
-v /var/local/containers/nextcloud/db:/var/lib/mysql:Z \
docker.io/library/mariadb:latest
pod の中に、redis のコンテナを作成します。latest で問題ないでしょう・・。(現時点で 7.2.4 でした)。
--log-driver k8s-file --log-opt path=/var/log/containers/nc-cache.log \
docker.io/library/redis:latest
pod の中に、nextcloud のコンテナを作成します。stable を指定します。(現時点で 27.1.6 でした)。-v で /var/local/containers/nextcloud/app/ の各ディレクトリをマウントしています。data には保存されるデータが入ります。config には、config.php が入っているので出しました。html は、cron.php をホストから触るために出しています。「:z」は、SELinux のためのオプション(共有コンテンツラベル)です。
--log-driver k8s-file --log-opt path=/var/log/containers/nc-app.log \
-e MYSQL_DATABASE="nextcloud" -e MYSQL_USER="nextcloud" -e MYSQL_PASSWORD="password" \
-e MYSQL_HOST="127.0.0.1" -e REDIS_HOST="127.0.0.1" \
-v /var/local/containers/nextcloud/app/html:/var/www/html:z \
-v /var/local/containers/nextcloud/app/data:/var/www/html/data:z \
-v /var/local/containers/nextcloud/app/conf:/var/www/html/config:z \
docker.io/library/nextcloud:stable
これだけで、Nextcloud が立ち上がっているはずです。いったん http://ホストのIP:2080 にアクセスして確認してみましょう。Nextcloudが立ち上がっていると思います。また、管理者ユーザーのセットアップを完了させておきましょう。config.php が変更されます。もし、アクセスできない場合は、/var/log/containers/nc-app.log にログが出ていると思いますので、それを確認しましょう。
今作った Nextcloud pod を systemd で自動起動するために以下のコマンドを実行します。
一旦、停止して、
systemd の設定ファイルを生成し、systemd で起動しなおします。
podman generate systemd --files --name nextcloud
systemctl daemon-reload
systemctl enable pod-nextcloud.service
systemctl start pod-nextcloud.service
フロントエンド(Bunkerweb)を立ち上げる
Let’s Encript(SSL) の自動化と、セキュリティを強化するために、フロントエンドに Bunkerweb を立ち上げます。社内や自宅内だけで使う場合は、先ほど立ち上げたバックエンドだけでも十分に機能すると思います。
/var/local/containers/bunkerweb/podman.env ファイルを作成し以下を記載
USE_REVERSE_PROXY=yes
REVERSE_PROXY_URL=/
REVERSE_PROXY_HOST=http://ホストのIP:2080
ALLOWED_METHODS=GET|POST|HEAD|PROPFIND|DELETE|PUT|MKCOL|MOVE|COPY|PROPPATCH|REPORT|OPTIONS
BAD_BEHAVIOR_STATUS_CODES=400 401 403 405 444
INTERCEPTED_ERROR_CODES=400 401 403 405 500 501 502 503 504
USE_DNSBL=no
USE_BUNKERNET=no
USE_MODSECURITY=no
USE_MODSECURITY_CRS=no
LIMIT_REQ_RATE=40r/s
SERVE_FILES=no
DISABLE_DEFAULT_SERVER=yes
AUTO_LETS_ENCRYPT=yes
USE_LETS_ENCRYPT_STAGING=yes (注1)
USE_GZIP=yes
X_FRAME_OPTIONS=SAMEORIGIN
MAX_CLIENT_SIZE=10G
/etc/systemd/system/container-bunkerweb.service を作成し、以下を記載
Description=Podman container-bunkerweb.service
[Service]
Restart=on-failure
ExecStartPre=/usr/bin/rm -f %t/%n-pid %t/%n-cid
ExecStart=/usr/bin/podman run --conmon-pidfile %t/%n-pid --cidfile %t/%n-cid \
-d -p 80:8080 -p 443:8443 \
-v /var/local/containers/bunkerweb/data:/data:z \
--uidmap 0:100000:5000 --gidmap 0:100000:5000 \
--tz=Asia/Tokyo \
--env-file /var/local/containers/bunkerweb/podman.env \
--log-driver k8s-file \
--log-opt path=/var/log/containers/bunkerweb.log \
--name=bunkerweb docker.io/bunkerity/bunkerweb:1.4.8
ExecStop=/usr/bin/podman stop -t 10 bunkerweb
ExecStopPost=/usr/bin/sh -c "/usr/bin/podman rm bunkerweb"
KillMode=none
Type=forking
PIDFile=%t/%n-pid
[Install]
WantedBy=default.target
以下のコマンドで Bunkerweb が自動起動するように設定します。
systemctl start container-bunkerweb
systemctl enable container-bunkerweb
Nextcloud の config 設定
/var/local/containers/nextcloud/app/conf/config.php ファイルを開いて、フロントエンド(proxyサーバー)の設定を入れます。
'trusted_domains' =>
array (
0 => 'ホストのIP:2080',
1 => 'server1.example.com',
),
・・・
'trusted_proxies' =>
array (
0 => 'ホストのIP',
),
・・・
'overwrite.cli.url' => 'https://server1.example.com',
'overwriteprotocol' => 'https',
'overwritehost' => 'server1.example.com',
'default_phone_region' => 'JP',
'default_language' => 'ja',
'default_locale' => 'ja',
・・・
以下のコマンドで、バックエンドに設定を再読み込みします。
これで、https://server1.example.com にアクセスできると思います。アクセスできない場合は、/var/log/containers/bunkerweb.log にログが出ていると思いますので、それを確認しましょう。
微調整
Webサーバーで “/.well-known/carddav” が解決されるように正しく設定されていません。詳細については、ドキュメントをご覧ください。
このエラーを消すためには、Bunkerweb の方にリダイレクトの設定を追加します。
/var/local/containers/bunkerweb/data/configs/server-http/redirect.conf を開き以下の設定を追加します。nginx の config ファイルなので少し見慣れませんでしたが、このようにするとリダイレクトできるようです。
return 301 $scheme://$host/remote.php/dav;
}
location /.well-known/caldav {
return 301 $scheme://$host/remote.php/dav;
}
このエラーを消すのは、そのままです。「基本設定」からメールサーバーの設定を行ってください。
cron ジョブの実行
cron ジョブが一番悩みました。基本設定でバックグラウンドジョブを「Cron(推奨)」にして放置していると、そのうちエラーが出ます。
コンテナでは cron を実行させるためには工夫がいるようなので、cron.php をホスト側から呼ぶようにしました。 /etc/cron.d/pod-nextcloud ファイルを作成し以下を記述します。
cron が実行されるようにアクセス権を設定します。