QGIS で作成したデータ("プロジェクト")を Web ページで表示する方法について、ノウハウを共有します。
初回の QGIS データを Web で表示 #1 - qgis2web では、QGIS のプラグインである qgis2web を使用して、QGIS で作成したデータを表示するためのスタンドアロンな Web 地図を作成しました。
これは QGIS プロジェクトのある時点でのスナップショットを切り出して、OpenLayers または Leaflet という地図データ表示 javascript が理解可能なデータを作成して利用する、ある意味で静的な Web 地図を作成するものでした。ウェブ・サーバ上に QGIS のプロジェクトやデータ・ファイルを保有する必要はありませんが、ローカルに保持する QGIS プロジェクトに拡張や変更があるたびにスナップショットを取り直して、Web 地図のページを再作成する必要があります。
0. 全体の構想
今から構築しようとしている Web 地図システムにおいては、QGIS のプロジェクトとデータ・ファイルそのものをインターネット上のサーバに置きます。そして、次の3つのモジュールを連携させて Web 地図を表示します。
- QGIS Server
- QWC2 (QGIS Web Client 2)
- MapCache
最初の二つ、すなわち QGIS Server と QWC2 を連携させれば Web 地図の表示が可能になります。しかし、それだけでは地図の表示速度に問題が出るため、二つの間にキャッシュ・サーバを置いてパフォーマンスを改善します。
この作業をモジュールごとに何回かに分けて説明します。今回は QGIS Server、次回とその次の回は QWC2、そして最後に MapCache です。
なお、これについては、Docker を使って QGIS Server と QWC2 を核とした統合的な環境である qwc-services をインストールして利用する方法もあり、むしろ、そちらの方が推奨されています。(Quick start - Running QWC2 as part of qwc-services を参照)。しかし、ここでは、それぞれを個別にインストールして、手作業で連携させていきます。そうしなければならない理由は無いのですが、一度は個別のインストールと設定の作業を経験して、各モジュールに対する理解を深めておく方が良いと考えたからです。
1. 環境 : AlmaLinux 9.5
AlmaLinux 9.5 の最小限インストール(Minimal Install)から開始します。
QGIS Server を解説している文書では Debin/Ubuntu 系の linux を前提にしている場合が多いのですが、AlmaLinux です。これは CentOS から AlmaLinux へと RHEL 系の linux を使い続けてきて慣れているという私の個人的な事情によります。
読者として linux のインストールとパッケージ管理について最小限度の知識と経験がある人を想定していますので、dnf
や vi
の使い方などに関しては詳しくは述べません。
なお、サーバ名は webgis.mydomain
、アドレスは 192.168.0.9
、常用するユーザ名は my-account
であると仮定します。
1-1. 追加設定
AlmaLinux インストール直後に、私はいくつかの追加の設定を行っていますが、今回の作業に関係する項目だけを挙げます。
1-1-1. SELinux を無効化する
これは推奨されないことですが、よく知らないし、いろいろと面倒くさいので、SELinux を無効化します。ごめん。やり方を知っている人は SELinux を無効化せずに進めて下さい。
/etc/selinux/config
を下記のように修正します。
# SELINUX=enforcing
SELINUX=disabled
再起動が必要です。
sudo reboot
1-1-2. EPEL レポジトリを追加する
sudo dnf install epel-release
1-1-3. CRB レポジトリを有効化する
sudo dnf config-manager --set-enabled crb
以前の PowerTools に相当する CRB レポジトリを有効化していないと、QGIS Server のインストールで依存の解消が出来なくて、二進も三進も行かなくなります。
2. QGIS Server
QGIS Server Guide/Manual を参照しながら、作業を進めます。
2-1. QGIS Server をインストールする
QGIS Server を dnf
でインストールします。
sudo dnf install qgis-server
これによって QGIS Server が依存する QGIS も一緒にインストールされます。下記のコマンドで QGIS の存在を確認することが出来ます。
which qgis
qgis -v
qgis_mapserv.fcgi
がインストールされた場所を確認します。
Debian/Ubuntu 系の linux では /usr/lib/cgi-bin/qgis/qgis_mapserv.fcg
としてインストールされるようですが、AlmaLinux の場合は /usr/libexec/qgis/qgis_mapserv.fcg
です。
次のコマンドを実行して、FCGI サーバとして動作することを確認して下さい。
/usr/libexec/qgis/qgis_mapserv.fcgi
この段階では、先ほどの qgis -v
で表示されたバージョンの QGIS が起動されたことさえ確認できれば、何らかのエラーが表示されても気にする必要はありません。
2-2. Xvfb をインストールする
Minimal Install でインストールした環境では X Window が使えません。QGIS / QGIS Server では地図の描画処理(特に印刷)に X Window のフレーム・バッファを使用しますないので、代りに、Xvfb (X virtual frame buffer) をインストールします。
Server with GUI などでインストールした環境では X Window が使えるので Xvfb をインストールする必要はありません。
sudo dnf install Xvfb
/etc/systemd/system/xvfb.service
を以下の内容で作成します。
[Unit]
Description=X Virtual Frame Buffer Service
After=network.target
[Service]
ExecStart=/usr/bin/Xvfb :99 -screen 0 1024x768x24 -ac +extension GLX +render -noreset
[Install]
WantedBy=multi-user.target
上記で :99
が Xvfb のディスプレイ番号です。
Xvfb サービスを起動し、自動起動するように設定します。
sudo systemctl start xvfb.service
sudo systemctl enable xvfb.service
2-3. QGIS プロジェクトを設置する
QGIS Server で使用する QGIS プロジェクトをサーバ上に設置します。
ディレクトリ構成については、二つの案が考えられます。
2-3-1. ディレクトリ構成案(1) 効率重視型
基準ディレクトリ (例えば "/home/my-account/qgis-projects")
+ common (プロジェクト間共有ディレクトリ)
+ rasters
+ shpfiles
- project_1.qgs
+ project1 (プロジェクト1 専用のディレクトリ)
+ rasters
+ shpfiles
- project_2.qgs
+ project2 (プロジェクト2 専用のディレクトリ)
+ rasters
+ shpfiles
...
-
common
ディレクトリを作って、プロジェクト間で共有するデータを入れる - プロジェクト・ファイル (
*.qgs
) は、すべて、基準ディレクトリに入れる - プロジェクトと同名のディレクトリを作って、プロジェクト固有のデータを入れる
長所:
- 効率的
短所:
- データの共有に関する問題が生じやすい
- 基準ディレクトリ直下にファイルが散乱しやすい
2-3-2. ディレクトリ構成案(2) 安全重視型
基準ディレクトリ (例えば "/home/my-account/qgis-projects")
+ project_1
- project_1.qgs
+ rasters
+ shpfiles
+ project_2
- project_2.qgs
+ rasters
+ shpfiles
...
- 基準ディレクトリ内にプロジェクトと同名の専用ディレクトリを作る
- 専用ディレクトリ内に、プロジェクト・ファイルと全てのデータ・ファイルを入れる
長所:
- プロジェクト間の干渉を防げる
短所:
- 非効率的
2-3-3. ディレクトリ構成
一長一短ですが、ここでは、第1案を採用します。
2-3-4. デモ・プロジェクトを配置する
自分で作ったプロジェクトを設置しても良いのですが、QGIS Server で利用するためには、QGIS プロジェクト側でいくつか必要な設定があります。(後述します)
この段階では、必要な設定が済んでいるプロジェクトを使用したいので、QGIS の公式レポジトリで提供されているデモ・プロジェクトを使用することにします。
まず、wget
と unzip
が必要なので、インストールしておきます。
sudo dnf install wget
sudo dnf install unzip
プロジェクト基準ディレクトリに移動します。
cd $HOME/qgis-projects
zip ファイルを取得して展開し、必要なものを設置します。
wget https://github.com/qgis/QGIS-Training-Data/archive/release_3.34.zip
mv QGIS-Training-Data-release_3.34/exercise_data/qgis-server-tutorial-data/world.qgs ./.
mv QGIS-Training-Data-release_3.34/exercise_data/qgis-server-tutorial-data/naturalearth.sqlite ./.
以上で、次のようにデモ・プロジェクトが設置されます。
基準ディレクトリ (例えば "/home/my-account/qgis-projects")
- world.qgs
- naturalearth.sqlite
このプロジェクトのデータ・ファイルは sqlite
データベース・ファイルなので、dnf
で sqlite
をインストールします。
sudo dnf install sqlite
2-4. nginx をインストールする
QGIS Server を供用するためには HTTP サーバが必要ですので、nginx をインストールします。httpd (Apache2) でも良いのですが、慣れている nginx を使う事にします。
AlmaLinux の標準パッケージにも少し古いバージョンの nginx が含まれています。実用上はそれで十分だと思いますが、最新版をインストールするために、以下の内容で /etc/yum.repos.d/nginx.repo
を作成します。
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
そして、dnf
でインストールします。
sudo dnf install nginx
nginx を起動し、自動起動するように設定します。
sudo systemctl start nginx
sudo sustemctl enable nginx
2-5. ファイアウォールを設定する
この段階で、ブラウザでサーバ(例えば http://webgis.mydomain/
)にアクセスしてみると、接続に失敗すると思います。システムを Minimal Install で始めたので、ファイアウォールが http
を通さない設定になっている筈だからです。
ファイアウォールの設定を確認します。
sudo firewall-cmd --list-all
services: のリストに http
という文字が出て来ない場合は、http
サービスが通るようにファイアウォールの設定を変更する必要があります。
sudo firewall-cmd --add-service=http --permanent
sudo systemctl restart firewalld
firewall-cmd --list-all
で設定を再確認し、http://webgis.mydomain/
にブラウザでアクセスして、nginx の Welcome ページが表示されることを確かめます。
2-6. Systemd の socket と service を設定する
nginx から FastCGI プロセスとして QGIS Server を呼び出すために、Systemd の socket ユニットと service ユニットを使用します。
FastCGI プロセスの呼び出しには spawn-fcgi または fcgiwrap を使用しても良いのですが、Systemd を使用する方法が最も簡明・堅牢かつ高性能です。
また、QGIS プロジェクトごとに専用の socket と service を使用したいので、Systemd のテンプレート・ユニットを使います。
2-6-1. qgis-server sockets
以下の内容で /etc/systemd/system/qgis-server@.socket
を作成します。
[Unit]
Description=QGIS Server socket for %i
PartOf=qgis-server@%i.service
[Socket]
Accept=false
ListenStream=/run/qgis-server-%i.sock
SocketUser=nginx
SocketGroup=nginx
SocketMode=0600
[Install]
WantedBy=sockets.target
これはテンプレートになっていて、実際に作成される socket は %i
を指定のプロジェクト名で置き換えたものになります。例えば、QGIS プロジェクト名が world
であれば、/run/qgis-server-world.sock
となります。この socket が対応する qgis-server@world.service
を起動して呼び出します。
2-6-2. qgis-server services
以下の内容で /etc/systemd/system/qgis-server@.service
を作成します。
[Unit]
Description=QGIS Server instance (%i
After=network.target
[Service]
User=nginx
Group=nginx
StandardOutput=null
StandardError=journal
StandardInput=socket
ExecStart=/usr/libexec/qgis/qgis_mapserv.fcgi
Environment=QGIS_PROJECT_FILE=/home/my-account/qgis-projects/%i.qgs
Environment=QGIS_SERVER_LOG_STDERR=1
Environment=QGIS_SERVER_LOG_LEVEL=0
Environment=QGIS_SERVER_CACHE_DIRECTORY=/var/cache/qgis-server
Environment=DISPLAY=:99
[Install]
WantedBy=multi-user.target
これもテンプレートになっていて、実際に開始される service は @
の後ろに指定した QGIS プロジェクト名を追加したもの、例えば qgis-service@world.service
となります。
- QGIS_PROJECT_FILE ...
%i
が指定したプロジェクト名に置き換わります - QGIS_SERVER_LOG_LEVEL ... 運用環境では
3
を推奨します - QGIS_SERVER_CACHE_DIRECTORY ... nginx が読み書き可能なディレクトリを用意しておきます
- DISPLAY ... Xvfb のディスプレイを指定します(Xvfb を使わない場合はこの行を削除)
QGIS_PROJECT_FILE は絶対パスで指定します。このパスの途中にシンボリック・リンクが含まれているとプロジェクト・ファイルを開くときにエラーが出るようなので注意して下さい。
2-6-3. socket と service の起動
今回使用する QGIS プロジェクトは 'world' という名前ですので、次のようにして socket と service の自動起動を設定しておきます。
sudo systemctl daemon-reload
sudo systemctl enable qgis-server@world.socket
sudo systemctl enable qgis-server@world.service
そして、socket と service を起動します。
sudo systemctl start qgis-server@world.socket
sudo systemctl start qgis-server@world.service
service の方は socket から最初に呼び出されたときに自動的に起動されますので、手動で起動しなくても構いません。
2-7. nginx によるルーティングを設定する
2-7-1. ファイアウォールの 8082 番ポートを開ける
QGIS Server へのアクセスをルーティングするために、QGIS Server へのゲートウェイをデフォルトの 80 番ポートではなく、8082 番ポートに変更します。そのために、ファイアウォールの設定を変更します。
この際、ついでですから、今後使用する予定のポートも開けておきます。
sudo firewall-cmd --add-port=8080/tcp --permanent
sudo firewall-cmd --add-port=8081/tcp --permanent
sudo firewall-cmd --add-port=8082/tcp --permanent
sudo systemctl restart firewalld
- 8080 ... MapCache ルーティング用
- 8081 ... QWC2(開発版)用
- 8082 ... QGIS Server ルーティング用
2-7-2. qgis-server.conf
/etc/nginx/conf.d/qgis-server.conf
を以下の内容で作成します。
server {
listen 8082;
server_name webgif.mydomain;
gzip off;
include fastcgi_params;
# CORS を許可
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
location /world/ {
fastcgi_pass unix:/run/qgis-server-world.sock;
}
error_log /var/log/nginx/qgis-server-error.log;
access_log /var/log/nginx/qgis-server-access.log;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
nginx を再起動します。
sudo systemctl restart nginx
2-6. 動作確認
ブラウザから次のアドレスにアクセスします。
http://webgis.mydomain:8082/world?LAYERS=countries&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&CRS=EPSG:4326&WIDTH=800&HEIGHT=400&BBOX=-90,-180,90,180
お疲れ様でした。国別に色分けされた世界地図が表示されたら、QGIS Server が正常に動作している証拠です。
うまく表示されない場合は、以下の方法で原因を探って下さい。
-
/var/log/nginx/
以下のログ・ファイルを見る -
journalctl -xe -t qgis_mapserv.fcgi
で、qgis_mapserv.fcgi に関連するログを調査する
3. QGIS プロジェクトの設定
自分で作成した QGIS プロジェクトを QGIS Server で使用するためには、いくつかの変更が必要です。
3-1. 一般的な注意
3-1-1. データ・ファイルを「外」に置かない
プロジェクトで使用するデータ・ファイルは、プロジェクト・ファイルが置かれているディレクトリまたはそのサブ・ディレクトリに置くのが良いでしょう。
QGIS のプロジェクト・ファイルはデータ・ファイルを相対パスで管理します。従って、データ・ファイルがプロジェクト・ファイルのディレクトリの「外」にある場合、例えば、../other-project/.
や、../common-data/.
というようなディレクトリにある場合であっても、位置関係を維持しながらそれらのディレクトリをコピーすれば、おそらく大丈夫でしょう。確認は取っていません。しかし、運用時、特にデータ・ファイルを更新するときなどに、コピーし忘れたりする問題が起きやすいことも事実でしょう。
結局は、プロジェクトごとに独立したディレクトリを持つようにするのが、一番安全です。
今回は、全てのプロジェクト・ファイルを単一の基準ディレクトリ直下に置き、参照するファイルをプロジェクト間で共有するものとプロジェクト専用のものに分けて、サブ・ディレクトリに置いています。共有するファイルが別のプロジェクトから想定外の変更を加えることが無いように注意してください。
3-1-2. *.qgz ではなく *.qgs の形式を使う
プロジェクト・ファイルの形式は、圧縮形式である *.qgz
ではなく、*.qgs
にする方が良いでしょう。*.qgz
が使えない訳ではありませんが、*.qgs
にする方が楽です。
3-2 プロジェクトのプロパティ
QGIS プロジェクトには、QGIS Server などの外部プログラムからのアクセスを制御するプロパティが存在します。これを適切に設定しないと、QGIS Server から利用することが出来ません。
詳細については、マニュアルの 2.4 Configure your project に書かれていますが、ここでは、重要だと思われるものに絞って説明します。
編集が必要な項目は メニュー・バー > プロジェクト > プロパティ... > QGIS サーバー
および メニュー・バー > レイヤ > レイヤのプロパティ... > QGIS サーバー
にあります。
3-2-1. Service Capabilities
-
メニュー・バー > プロジェクト > プロパティ... > QGIS サーバー > Service Capabilities
-
Service Capabilities を有効化
を必ず ON にする -
短い名前
... 必ず設定する(例えば "world") -
タイトル
... 必ず設定する(例えば "世界地図") -
要約
... 設定を推奨 -
キーワード
... 設定を推奨 - その他は放置して可
-
3-2-2. WMS
-
メニュー・バー > プロジェクト > プロパティ... > QGIS サーバー > WMS
-
Advertise 範囲
を必ず ON にする-
範囲
の設定方法- マウス・ボタンを押して、画面上で領域を指定
- ドロップダウン・リスト
- レイヤから計算
- 対象レイヤを選択
- レイアウトマップから計算
- ブックマークから計算
- 現在のキャンバス領域を利用
- レイヤから計算
-
-
レイヤの除外
-
+
ボタンを押して、除外したいレイヤを選択して追加 - XYZ などの外部サービスを利用する背景レイヤは除外して良い
-
- その他は放置して可
-
Adgertise 範囲
は、プロジェクトが想定する初期表示範囲です。
3-2-3. WMTS
メニュー・バー > プロジェクト > プロパティ... > QGIS サーバー > WMTS
「出力されたレイヤ」と「発行済み」はほとんど誤訳です。それぞれ「出力レイヤ」と「発行(公開)」と読み替えてください。
それぞれのレイヤについて、発行(公開)するかどうか、形式として PNG および JPEG をサポートするかどうかを設定します。
3-2-4. WFS/OAPIF
メニュー・バー > プロジェクト > プロパティ... > QGIS サーバー > OAPIF
ここでも「発行済み」は「発行(公開)」と読み替えてください。
それぞれのレイヤについて、発行(公開)するかどうか、更新・挿入・削除をサポートするかどうかを設定します。ジオメトリの精度は規定値の 8
のままで良いでしょう。
3-2-5. WCS
メニュー・バー > プロジェクト > プロパティ... > QGIS サーバー > WCS
ここでも「発行済み」は「発行(公開)」と読み替えてください。
それぞれのレイヤについて、発行(公開)するかどうかを設定します。一般に、背景レイヤは除外するのが良いでしょう。
3-2-6. レイヤごとのプロパティ
-
メニュー・バー > レイヤ > レイヤのプロパティ... > QGIS サーバー
- 説明
- 短い名前 ... 必ず設定する(例えば "spots")
- タイトル ... 必ず設定する(例えば "注目スポット")
- WFS title ... ベクタ・レイヤのみ。放置して可
- 要約 ... 設定を推奨
- キーワード ... 設定を推奨
- その他は放置して可
- 説明
3-2-7. ベクタ・レイヤのフィールド
メニュー・バー > レイヤ > レイヤのプロパティ... > フィールド
を開くと、下のような画面になります。
それぞれのフィールドについて、設定
のカラムのドロップダウンで、公開する必要の無いもの、公開してはいけないものについて、チェックを入れます。
- ドロップダウン
- Not searchable
- WMS 経由で公開しない
- WFS 経由で公開しない
ここでは、"スポット" のレイヤについて、"名称" フィールドだけを公開する設定にしています。
3-3. フォント
ベクタ・レイヤで文字表示に使用するフォントは linux でも使えるものに変更しておく必要があります。そうしないと地物のラベルなどが □□□□ のような豆腐の連続になります。
お奨めは Google の Noto フォントです。これなら AlmaLinux の最小インストールでも最初から入っています。Windows では入っていませんので QGIS Desktop を Windows で使用している場合はインストールする必要があります。
3-4. プロジェクトの CRS
QGIS Server 単体で考える時は、プロジェクトの CRS は何でも良いでしょう。
私は ESPG:6673 JGD2011 / Japan Plane Rectangular CS V
を良く使用します。これは、私が作成する地図の表示範囲が兵庫県の内陸部であるため、その適用対象範囲から見てこれが良いだろう(同じ範囲でも JGD2000
ではなくて、新しい方の JGD2011
だよな)と考えて選んだ結果です。
しかし、QWC2 との連携、特に MapCache との連携を念頭に置いた場合は、ESPG:3857 WGS 84 Pseudo-Mercator
を選んでおく方が、後々、作業がスムーズに出来ます。
各レイヤの CRS はそのままにしておいて、プロジェクトの CRS だけを ESPG:3857
に変更するのが良いと思われます。
And so, what's next?
次回は QWC2 (QGIS Web Client 2) をインストールして、QGIS Server と連携させ、一通り動く Web 地図システムを作成します。