Ubuntu 18.04を使用する場合
シングルボードコンピューターにOpenStreetMapのタイルサーバーを立ててみる
ラズベリーパイ 4 Model B + Ubuntu 20.04.1 LTS Serverを使用する場合
Raspberry Pi Imager for Windowsで32GB MicroSDにUbuntu 20.04.1 LTS Server をインストール。
MicroSDは32GB以上を使用。
64-bit server OS for arm64 architecture を選びます。
MicroSDの質や回線状況などの条件がよければ5分ほどで終了します。
初期設定
tileserverという新規ユーザーを作成してログインするようにしておいてください。
以下のページではUbuntu 18.04になっていますが、そこは無視してください。
最後のDesktop環境の構築は不要です。後の作業はSSH接続したコンソール上で行います。
タイルサーバーの構成
元ネタはこちら – Switch2OSM
Switch2OSMは18.04を対象に記述されています。20.04 LTS のリポジトリにはないパッケージもあるので注意する必要があります。
1:Softwareインストール
メインのOpenStreetMap.orgタイルサーバーで使用されているものと同様の最も標準的なバージョンについて説明します。
タイルサーバーはmod_tile、rendered、mapnik、osm2pgsql、postgresql / postgisデータベースという5つの主要コンポーネントで構成されています。
Mod_tileは、キャッシュされたタイルを提供し、どのタイルがまだキャッシュされていないか、または古くなっているため、再レンダリングが必要なタイルを決定するApacheモジュールです。
Renderedは、さまざまな種類のリクエストに優先キューイングシステムを提供し、レンダリングリクエストからの負荷を管理および平滑化します。
Mapnikは、実際のレンダリングを行うソフトウェアライブラリで、renderedによって使用されます。
osm2pgsql、postgresql / postgisはタイリング用のOpenStreetMapデータをデータベース化するためのコンポーネントです。
そしてApacheウェブサーバーが要求に従ってタイルデータを配信します。
これらのコンポーネントをビルドするために、さまざまな依存関係を最初にインストールしておきます。
1 |
sudo add-apt-repository multiverse |
20.04のリポジトリリストにはfocalしか記述されていませんが、bionicのリポジトリを見ないといけないパッケージもあるようです。
リポジトリのリストを編集します。
1 |
sudo nano /etc/apt/sources.list |
以下を追加(多分不要なのもあるとは思いますが、気にしない)。
deb http://ports.ubuntu.com/ubuntu-ports bionic universe
deb http://ports.ubuntu.com/ubuntu-ports bionic multiverse
deb http://ports.ubuntu.com/ubuntu-ports bionic-security universe
deb http://ports.ubuntu.com/ubuntu-ports bionic-security multiverse
deb http://ports.ubuntu.com/ubuntu-ports bionic-updates universe
deb http://ports.ubuntu.com/ubuntu-ports bionic-updates multiverse
deb http://ports.ubuntu.com/ubuntu-ports bionic-backports universe
deb http://ports.ubuntu.com/ubuntu-ports bionic-backports multiverse
アップデートしておきます。
1 |
sudo apt update |
Switch2OSMにあったlibprotobuf-c0-devについては、
libprotobuf-c0-dev は仮想パッケージで、libprotobuf-c-devで提供されるとのことなので、libprotobuf-c-devに変更。
以下を実行。
1 |
sudo apt install libboost-all-dev git-core tar unzip wget bzip2 build-essential autoconf libtool libxml2-dev libgeos-dev libgeos++-dev libpq-dev libbz2-dev libproj-dev munin-node munin libprotobuf-c-dev protobuf-c-compiler libfreetype6-dev libtiff5-dev libicu-dev libgdal-dev libcairo-dev libcairomm-1.0-dev apache2 apache2-dev libagg-dev liblua5.2-dev ttf-unifont lua5.1 liblua5.1-dev libgeotiff-epsg |
2:postgresql / postgisインストール
Switch2OSMでは10を使っていますが、バージョン12に変更します。
1 |
sudo apt-get install postgresql postgresql-contrib postgis postgresql-12-postgis-3 postgresql-12-postgis-3-scripts |
「postgresql」は地図データを保存するデータベースであり、「postgis」はグラフィカルサポートを追加します。
postgisデータベースを作成します。
1 2 3 4 5 |
sudo -u postgres -i createuser tileserver createdb -E UTF8 -O tileserver gis |
「postgres」ユーザーとして作業しながら、PostgreSQLデータベースでPostGISを設定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
psql postgres=#\c gis gis=#CREATE EXTENSION postgis; gis=#CREATE EXTENSION hstore; gis=#ALTER TABLE geometry_columns OWNER TO tileserver; gis=#ALTER TABLE spatial_ref_sys OWNER TO tileserver; gis=#\q exit |
3:データベースのチューニング
デフォルトのPostgreSQL設定は、OSMデータベースなどの非常に大規模なデータベースには適していません。 適切なチューニングにより、パフォーマンスが約2倍になります。
1 |
sudo nano /etc/postgresql/12/main/postgresql.conf |
推奨される最小設定
shared_buffers = 128MB
max_wal_size = 2GB
min_wal_size = 1GB
work_mem = 32MB
maintenance_work_mem = 256MB
autovacuum = off
fsync = off
再起動
1 |
sudo /etc/init.d/postgresql restart |
4:osm2pgsqlインストール
OpenStreetMapデータをデータベースにインポートおよび管理するためのツールosm2pgsqlを使用します。
1 2 3 4 5 6 7 |
mkdir ~/src cd ~/src git clone git://github.com/openstreetmap/osm2pgsql.git cd osm2pgsql |
前提条件をいくつかインストールしておきます。
1 2 3 4 |
sudo apt install make cmake g++ libboost-dev libboost-system-dev libboost-filesystem-dev libexpat1-dev zlib1g-dev libbz2-dev libpq-dev libgeos-dev libgeos++-dev libproj-dev lua5.2 liblua5.2-dev |
ビルドします。
1 2 3 4 5 6 7 8 9 10 11 |
mkdir build cd build cmake .. make sudo make install |
5:Mapnikをインストール
デフォルトバージョンを使用します。
Switch2OSMではPython2を使うようになっていますが、Python3に変更します。
1 |
sudo apt-get install autoconf apache2-dev libtool libxml2-dev libbz2-dev libgeos-dev libgeos++-dev libproj-dev gdal-bin libmapnik-dev mapnik-utils python3-mapnik python3-psycopg2 |
Python3を使ってインストールされたか確認します。
python3
>>> import mapnik
エラーが起きなければOKです。
Pythonコンソールから抜けます。
>>>quit()
6:mod_tile と renderdインストール
レンダリング用のmod_tileをインストールします。 「mod_tile」は、タイルのリクエストを処理するApacheモジュールです。 「renderd」は、「mod_tile」がタイルを要求したときに実際にタイルをレンダリングするデーモンです。
mod_tileのソースをコンパイル
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
cd ~/src git clone -b switch2osm git://github.com/SomeoneElseOSM/mod_tile.git cd mod_tile ./autogen.sh ./configure make sudo make install sudo make install-mod_tile sudo ldconfig |
7:スタイルシート構成
スタイルシートをダウンロードして構成します。
1 2 3 4 5 6 7 |
cd ~/src git clone git://github.com/gravitystorm/openstreetmap-carto.git cd openstreetmap-carto sudo apt install npm nodejs |
cartoのインストール
Switch2OSMでは最新のcartoをインストールするようになっていますが、これだと構成に失敗します。
cartoはバージョン0のものを使います。
1 2 3 4 |
sudo npm install -g carto@0 |
mapnik-referenceで表示された中ならmapnikのバージョンに一番近いものをつかいます。
インストールされたmapnikのバージョンは3.0(正確には3.0.19)なので3.0.20を使います。
1 2 3 4 5 |
npm install mapnik-reference node -e "console.log(require('mapnik-reference'))" |
cartoプロジェクトをMapnikが理解できるものに変換します。
(実行中は何も返ってこないダンマリ状態ですが進捗はしています)
1 2 |
carto -a "3.0.20" project.mml > mapnik.xml ls -l mapnik.xml |
8:データのロード
各国のデータはOpenStreetMap Data Extractsで提供されています。
文字表示用にロケールが適切に設定できれば、お好きな国のタイルサーバーが構成できると思います。
データをロードしてみます。日本全体だとosm.pbfファイル自体は1.5GB程度のサイズですがロードして展開すると40GBくらい消費します。7~8時間くらいかかります。
日本リージョンは、さらに8つのサブリージョンに分けられています。
(中部地方、中国地方、北海道、関西、関東、九州、四国、東北)
関西サブリージョンのみやってみます、30分弱で終わります。
1 2 3 4 5 6 7 8 9 |
mkdir ~/data cd ~/data wget http://download.geofabrik.de/asia/japan/kansai-latest.osm.pbf osm2pgsql -d gis --create --slim -G --hstore --tag-transform-script ~/src/openstreetmap-carto/openstreetmap-carto.lua -C 2500 --number-processes 1 -S ~/src/openstreetmap-carto/openstreetmap-carto.style ~/data/kansai-latest.osm.pbf |
ロードに続いてデータがソートされ、インデックスが作成されます。
osm2pgsqlではappendもできますし、createで実行すればデータベースは新規に再作成されます。
osm2pgsqlのオプションパラメータや使い方についてはこのページ参照
9:シェープファイルのダウンロード
ズーム率の低い、国の国境線などのためのシェープファイルがまだ必要です。
これらをダウンロードしてインデックスに登録します。
このプロセスにはかなりのダウンロードが含まれ、時間がかかる場合があります。実行中は画面にほとんど表示されません。 「openstreetmap-carto」の下の「data」ディレクトリに実際にデータが入力されます。
1 2 3 |
cd ~/src/openstreetmap-carto/ scripts/get-external-data.py |
INFO:root:Checking table simplified_water_polygons
INFO:root:Checking table water_polygons
INFO:root:Checking table icesheet_polygons
INFO:root:Checking table icesheet_outlines
INFO:root:Checking table ne_110m_admin_0_boundary_land
だいたい12分くらいで終了。
たまにConnectionErrorで失敗することがあります。
ちょっと時間をおいて再実行してみましょう。
10:Fontsのインストール
世界中の場所で使用されている名前は、常にラテン文字で書かれているとは限りません(使い慣れた西洋のアルファベットa〜z)。
必要なフォントをインストールするには、次の手順を実行します。
1 2 3 4 |
sudo apt-get install fonts-noto-cjk fonts-noto-hinted fonts-noto-unhinted ttf-unifont |
11:webサーバーのセットアップ
renderdの構成
「renderd」の設定ファイルは「/usr/local/etc/renderd.conf」です。
1 |
sudo nano /usr/local/etc/renderd.conf |
[renderd]のセクション
num_threads=4
[ajt]セクションは、「ajt」と呼ばれる「名前付きマップスタイル」に対応しています。 XML=/home/tileserver/src/openstreetmap-carto/mapnik.xml
URI=/hot/
Apacheの構成
Apacheに「mod_tile」について通知する必要があります。
1 2 3 4 5 6 7 8 9 10 |
sudo mkdir /var/lib/mod_tile sudo chown tileserver /var/lib/mod_tile sudo chmod -R a+x /var/lib/mod_tile sudo mkdir /var/run/renderd sudo chown tileserver /var/run/renderd |
mod_tile.confを新規に作成します。
1 2 3 |
sudo nano /etc/apache2/conf-available/mod_tile.conf |
以下を追記
1 2 3 4 |
LoadModule tile_module /usr/lib/apache2/modules/mod_tile.so |
mod_tileを起動
1 2 3 4 |
sudo a2enconf mod_tile |
次に、Apacheに「レンダリング」について通知する必要があります。
000-default.confをnanoなどのテキストエディターで編集します。
1 2 3 4 |
sudo nano /etc/apache2/sites-available/000-default.conf |
「ServerAdmin」行と「DocumentRoot」行の間に次を追加します。
1 2 3 4 5 6 7 8 9 |
LoadTileConfigFile /usr/local/etc/renderd.conf ModTileRenderdSocketName /var/run/renderd/renderd.sock # Timeout before giving up for a tile to be rendered ModTileRequestTimeout 0 # Timeout before giving up for a tile to be rendered that is otherwise missing ModTileMissingRequestTimeout 30 |
Apacheを2回リロードします。
(Apacheは、実行時に再構成すると「混乱」するため、2回実行する必要があります)
1 2 3 4 5 |
sudo service apache2 reload sudo service apache2 reload |
12:renderdをバックグラウンドで実行
renderd.initを編集
1 2 3 4 |
sudo nano ~/src/mod_tile/debian/renderd.init |
以下のように変更
RUNASUSER=tileserver
パーミッションを変更してシステムディレクトリにコピーします。
1 2 3 4 5 6 7 8 9 10 11 12 |
sudo cp ~/src/mod_tile/debian/renderd.init /etc/init.d/renderd sudo chmod u+x /etc/init.d/renderd sudo cp ~/src/mod_tile/debian/renderd.service /lib/systemd/system/ 起動 sudo /etc/init.d/renderd start 毎回自動的に開始するようにする sudo systemctl enable renderd |
13:タイル表示用のWebページ作成
Leafletライブラリを使ったサンプルが用意されています。
タイルを表示するために、mod_tileの「extras」フォルダーにある「sample_leaflet.html」というHTMLファイルを使ってみます。
Webのドキュメントルートは/var/www/htmlですので、ここにコピーします。
sample_leaflet.htmlはLeafletライブラリを使った地図表示用のWebアプリです。
lf.htmlという名前にしてみます。
1 2 3 4 |
sudo cp /home/tileserver/src/mod_tile/extra/sample_leaflet.html /var/www/html/lf.html |
編集してIPアドレスなどを変更します。
1 2 3 4 |
sudo nano /var/www/html/lf.html |
2か所変更
1 2 3 |
var map = L.map('map').setView([34.673791, 135.511708], 5); //<--zoom level 5で日本の上にViewを持ってきます L.tileLayer('http://127.0.0.1/hot/{z}/{x}/{y}.png', { //<--127.0.0.1をあなたのローカルIPに変更してください |
後でここにアクセスしてタイルを表示してみます。
14:レンダリングしたタイルを表示してみる
on-the-flyで実行してもストレスの元です。マニュアルでレンダリングしたデータを使ってみましょう。
事前にディレクトリを作っておきます。
1 2 3 4 |
mkdir /var/lib/mod_tile/ajt sudo chmod -R a+x /var/lib/mod_tile |
8で関西サブリージョンのデータベースを作っておきましたので、大阪のごく狭いエリアをレンダリングしてみます。
その前にズームレベル0から9までのタイルデータをダウンロードしておきます。このデータはWisteriaHillが作成したものですが、時間を短縮できます。
解凍すると80MBくらいのものです。0~9というフォルダー名のものをSAMBAなどで/var/lib/mod_tileにコピーしておきます。
コピー後のディレクトリ構成はこんな感じです。
/var/lib/mod_tile/ajt/0 1 2 ….. 9
レンダリングにrender_list_geo.plという名前でalx77によって開発されたコマンドラインPerlスクリプトを使用すると、地理座標を使用して特定の領域のタイルを自動的にプレレンダリングできます。
関連するGithub READMEには、使用方法とサンプルが記載されています。
1 2 3 |
cd ~/src git clone https://github.com/alx77/render_list_geo.pl cd render_list_geo.pl |
render_list_geo.plコマンドの主なオプション
-n スレッド数、Jetsonやラズパイの場合は1CPU 4Core 、1thread/1core なので4
-m タイルの保存場所、デフォルトは’default’ですが、現設定では’ajt’になっているので、明示的に指定
参考ファイルー>/usr/local/etc/renderd.conf
-z ズームレベルの最小値
-Z ズームレベルの最大値
-x 指定範囲の経度の最小値
-X 指定範囲の経度の最大値
-y 指定範囲の緯度の最小値
-Y 指定範囲の緯度の最大値
その他のオプション(通常使わない)
-a 標準入力から読み取る代わりに、指定されたズームレベル範囲内のすべてのタイルをレンダリングする
-t タイルディレクトリ、デフォルトは/var/lib/mod_tile
-f タイルが最新なように見えても強制的にレンダリングを実行
-l 負荷がこの値より高い場合はスリープ(デフォルトは16)
-s レンダリングに接続するためのUNIXドメインソケット名
念のためApacheとrenderdを再起動しておきます。
1 2 3 |
sudo systemctl restart apache2 sudo /etc/init.d/renderd restart |
本来レンダリングは最大ズームレベル18まで実行するのですが、18はタイル数が半端じゃないくらい多いです。で、17と18は見た目にはそんなに差はないですので、ここでは10~17までを実行してみます。
レンダリングの矩形範囲を確認するにはOpenstreeMapのExportサイトが便利です。
大阪のこの辺りをレンダリングしてみます。
1 |
./render_list_geo.pl -n 4 -m 'ajt' -z 10 -Z 17 -x 135.3735 -X 135.6101 -y 34.5996 -Y 34.7482 |
事前にレベル0~9のフォルダーをコピーしたので、再度パーミッションを指定しておきます。
1 |
sudo chmod -R a+x /var/lib/mod_tile |
13で作成したページにアクセス
http://<IPアドレス>/lf.html
大阪にアクセス、こんな感じです。
パワーやリソースがあるPCやワークステーション、AWSなどのクラウド環境を使えば、ズームしたりスクロールするごとにキャッシュに無かったり有効期限の切れたタイルは都度(On-The-Fly)レンダリングが実行されますがラズパイなどの、ちと非力なリソースしかないコンピュータの場合は、プレレンダリングしてキャッシュしておくという使い方がいいと思います(このサイトの眼目の一つは、地図をポータブルに使いたい……ということもあるんで ^^)。
レンダリングしたタイルをキャッシュする先を確保
上記の方法はラズパイのシステムがあるMicroSD内にタイルをキャッシュしていますが、日本全体のような、あるいは世界全体というようなタイルデータとなると容量が不足します。
外部ストレージを利用しましょう。これをマウントして利用します。
実際にタイルを作る前に保存先を決めます。
基本はどちらも、/var/lib/mod_tile/ajtをマウントポイントにしてストレージのディレクトリをマウントしてタイルデータをここにキャッシュします。
将来的にデータの増大などを顧慮するならNASやUSB接続のHDD(SSD)を使い、地域を限定して使うならUSBメモリで十分でしょう。
ストレージをマウントします。
NASの場合
試してみた実機はバッファローのLS210D021G(2TB)
cifsを使います。
1 2 3 |
sudo apt install cifs-utils |
マウントポイントを読み書き可能にしておきます。
1 2 3 |
sudo chmod 666 /var/lib/mod_tile/ajt |
NASのIPアドレスを調べておきます、例えば192.168.0.33だったとします。
NASのデータ保存先ディレクトリは共用フォルダー内のTileフォルダーだとします。
idコマンドでuidとgidを調べておきます。
NASのユーザー名(XXXXX)とパスワード(YYYYY)も確認しておいてください。
ラズパイの場合、例えばこんな感じになります。
1 2 3 |
sudo mount -t cifs //192.168.0.33/share/Tile /var/lib/mod_tile/ajt -o username=XXXXX,password=YYYYY,rw,uid=1001,gid=1001,vers=2.0,iocharset=utf8 |
Jetsonの場合エラーになりました。
マウントエラーのログを確認
1 2 3 |
tail -f /var/log/kern.log |
無効な引数があったので削除しました。
1 2 3 |
sudo mount -t cifs //192.168.0.33/share/Tile /var/lib/mod_tile/ajt -o username=XXXXX,password=YYYYY,rw,uid=1000,gid=1000 |
USBストレージの場合
NASより簡単です。
Disk情報を確認
1 2 3 |
sudo fdisk -l |
多分外部ストレージは
/dev/sda とか /dev/sdb と表示されると思います。
次にNASと同様にidコマンドでuidとgidを調べておきます。
例えばこんな感じでマウントします。
1 2 3 |
sudo mount -o owner,uid=1001,gid=1001,utf8,flush /dev/sda1 /var/lib/mod_tile/ajt |
mount: unknown filesystem type ‘exfat’ というエラーが出た場合
Ubuntuはデフォルトでは「exfat」のフォーマットに対応していない….。
以下を実行して、再度マウント
1 2 3 |
sudo apt-get install exfat-fuse exfat-utils |
Appendix
osmconvertのインストール
適当なフォルダーへ移動
sudo apt install osmctools
wget -O – http://m.m.i24.cc/osmconvert.c | sudo cc -x c – -lz -O3 -o osmconvert
osmosisのインストール
sudo apt install osmosis
Leave a Reply