Nextcloudで日本語PDFが白紙になる問題をTraefikとnginxで回避した話
はじめに
NextcloudのPDFビューアーで、日本語を含むPDFを開くとページが真っ白になることがあります。
調べてみると、PDF.jsが日本語の表示に必要とするCMapファイル(.bcmap)を取得できず、HTTP 404になる問題が、NextcloudのGitHub Issueで報告されていました。
そこで私は、Nextcloud本体には手を入れず、TraefikでCMap用のリクエストだけを別のnginxコンテナに振り分けるというアプローチを取ってみました。
この記事では、その構成と設定例を紹介します。
原因
Nextcloudの一部のApache構成では、.htaccess のRewriteRuleによって、CMapファイルへのアクセスが index.php に書き換えられてしまう場合があります。
関連Issueでも、ファイルが存在するのに404になる問題が報告されています。
回避方法
構成自体は、思いついてしまえば単純なものです。
TraefikでCMap用のURLへのリクエストだけを別のnginxコンテナへ振り分け、それ以外は従来どおりNextcloudへ送られます。
これならNextcloud本体の設定やファイルを変更する必要がありませんし、既存環境への影響も最小限に抑えられそうです。
CMapファイルへのリクエストだけをnginxに振り分け、それ以外は従来どおりNextcloudへ送ります。
Docker Composeの例
services:
cmap_proxy:
image: nginx:alpine
restart: unless-stopped
volumes:
- /srv/nextcloud/apps/files_pdfviewer/js/pdfjs/web/cmaps:/usr/share/nginx/html/cmaps:ro
- ./nginx.conf:/etc/nginx/nginx.conf:ro
networks:
- reverseproxy
labels:
traefik.enable: "true"
traefik.docker.network: reverseproxy
traefik.http.routers.cmaps.rule: "Host(`cloud.example.com`) && PathPrefix(`/apps/files_pdfviewer/js/pdfjs/web/cmaps/`)"
traefik.http.routers.cmaps.entrypoints: websecure
traefik.http.routers.cmaps.tls: "true"
traefik.http.services.cmaps.loadbalancer.server.port: "80"
networks:
reverseproxy:
external: true
nginxの設定例
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
server {
listen 80;
server_name _;
location /apps/files_pdfviewer/js/pdfjs/web/cmaps/ {
alias /usr/share/nginx/html/cmaps/;
}
location / {
return 404;
}
}
}
これでCMap用URLへのアクセスはnginxが処理し、対応するファイルを直接返します。
設定例についての注意点
- ホスト名やパスを匿名化・簡略化した実運用ベースの例です。この構成のままで再検証したものではありません。
-
reverseproxyはTraefikと共有するDockerネットワークです。 - CMapの実際の配置場所は環境に合わせて変更してください。nginxから対象ディレクトリを読み取れる必要があります。
- Traefikの既存Nextcloudルーターとの優先順位も確認してください。
-
.bcmap拡張子だけを制限する設定ではなく、CMap用URLプレフィックスをnginxに振り分ける構成です。 - 他の場所にある
.json、.ftl、.pfbなどの取得問題を解決するものではありません。
動作確認
今回、PHP2Shellへの対応としてNextcloudを nextcloud:32-apache に更新したあと、コンテナ内のPHPが修正版の8.3.36になっていることを確認しました。
その状態でCMapファイルへのHTTPS GETがHTTP 200を返し、日本語PDFも正常に表示されることを確認できました。
https://cloud.example.com/apps/files_pdfviewer/js/pdfjs/web/cmaps/Adobe-Japan1-UCS2.bcmap
また、日本語PDFが正常に表示されることを検証環境で確認しています。
HTTP 200だけで応答元がnginxであることやファイル内容の完全性まで証明できるわけではありませんが、少なくとも今回の環境では更新後もPDFを表示できています。
おわりに
この方法のよかったところは、Nextcloud本体の .htaccess やアプリケーションファイルを直接変更しなくて済んだことです。
Nextcloudの更新によって本体の修正が上書きされる心配を減らせるため、以前からこの構成で運用しています。
今回の回避策はPHP2Shellへの対応で作ったものではありませんが、その後のNextcloud更新でも利用できることを確認できました。
Dockerに移行した経緯やPHP2Shell対応で苦労した話も含めた記事は、自社サイトにまとめています。
Dockerでアプリケーションを隔離しただけのつもりが、Traefikのおかげでアプリケーションに手を入れずに不具合まで回避できた