マッピング地域の紹介

この記事は OpenStreetMap Advent Calendar 2018 の1日目の記事です。

Windows10 + IE 11 で HackMD の内容が表示されなかったのではてなブログに移動しました。

自分でマッピングしている地域と主なマッピング方法を紹介しようと思います。

3地域ありますが(「主な」とは)どの地域も基本的にアームチェアマッピングです。

埼玉県杉戸町

実家があり、osm を始めた最初の頃から断続的にマッピングしている地域です。

日本で Yahoo/ALPS データのインポートが始まる頃に最初の集中マッピングをしていて、Yahoo/ALPS データのノードの多さや接続の形状が主観的によくないと判断し、町の外周部から内側に向かって Bing から道路のトレースを行っていました。

次に集中的にマッピングを始めたのが基盤地図情報のトレースが出来るようになった頃で、千葉県に接する東側から建物を書き始めました。
埼玉県さいたま市浦和区川越市のトレースと平行して現在もボチボチ思い出したように建物を書いています。

その後、2015年頃にアジアにマッパーらによる日本の道路データクリーンナッププロジェクトに連動して道路など地物のクリーンナップを行いました。
当初の道路トレースの後に地震による岩盤のスライドがあり、地物の地球上の位置が相対的にずれていたり、道路の建設などを反映する更新を行いました。

杉戸町では杉戸町富岡町川内村地域間共助推進協議会を中心に東日本の震災の教訓を元にした協働型災害訓練という催しを行っていて、避難所の運営などの災害対応シミュレーションを行っています。その中でOSMを使ったアームチェアマッピングのワークショップも行われ、広い地域で建物が追加されています。

建物については西側1/3が割と残っていて、しかもそこは街の中心地と新興住宅地があるため全体として概ね半分程度のカバー率と推測しています。


大きな地図を表示

ソースは道路が Bing と基盤地図情報、建物は基盤地図情報をトレースしています。

埼玉県川越市

現在住んでいる地域です。
この地域には hatochan というベテランマッパーがおり、道路の多くは hatochan が自転車で廻ってマッピングしていて、高いカバー率になっています。

ある日 hatochan が市街地から建物をトレースしている事に気づき、触発されてトレースをするようになりました。もっとも、あまりにマッピング地域に近いからスタートしたので、反対側から始めればよかったかなと思ってるところです。

中心地の建物を概ね書き終えた後、市域の南東側を中心に建物を書き始めました。現在は建物が南東から北西側にかけて多くマッピングされていて、北東や南側が手薄です。今後北西側から時計回りに建物をトレースしていくつもりでいます。
手前 Tasking Manager でタスクを用意して進捗を眺めていますが、まだ先は長そうです。

観光地という側面も持つ川越市なので観光資源の周辺は積極的に POI の追加もしていきたいところです。


大きな地図を表示

建物をトレースする際のソースは基盤地図情報を背景にしてトレースをしています。

埼玉県深谷市

現在最も注力している地域です。
オープンデータになった航空写真のトレース許可を申請いただき許可されたことで、高精細な画像からマッピングできます。

タイル化された航空写真を元にまずは道路の形状変更と追加を中心地に行っているところです。航空写真が高精細なあまり、油断すると様々なものをトレースしてしまうため、トレースする地物を絞ってマッピングする方針にしています。


大きな地図を表示

こちらも手前 Tasking Manager でタスクを用意して進めています。航空写真の鮮度もあるため早めに終わらせたいのですが、ランチタイムに少しずつ進める程度になっています。

基盤地図情報のトレースについて

基盤地図情報はインポートしてはいけませんが、トレースすることができます。
データをダウンロードしただけでは JOSM などで読み込めないため、次のような手順でトレース元画像にしています。

  1. ダウンロードサービスからダウンロード
  2. 基盤地図情報ビューアシェープファイル
  3. QGIS で不要属性の削除、EPSG:4326に変換
  4. GeoServerWMS

何気に 2. の段階で JOSM のオープンデータツールを使って読み込めますが、うっかりアップロードしてしまうのが怖くて WMS にしています。

HTTPS の証明書更新に失敗してたので手動で更新した

Let's Encrypt で HTTPS 化した Tasking Manager 3 の証明書更新が成功しませんでした。

k-side.hatenablog.jp

動かなかったらどうしよ(

とか書いてたらその通りですよ…。

手動で証明書を更新する

VPS に接続して手動で更新を試みました。

$ sudo ~/src/certbot/certbot-auto renew
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/%ドメイン%.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cert not yet due for renewal

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

The following certs are not due for renewal yet:
  /etc/letsencrypt/live/%ドメイン%/fullchain.pem expires on 2018-XX-XX (skipped)
No renewals were attempted.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

どうやら証明書自体は cron で更新されたっぽいです。

良く見ると表示された fullchain.pem のフルパス名と /etc/nginx/sites-available/tm3 に記録した各種 pem のパスが異なっています。

一覧を見てみます。

$ sudo ls /etc/letsencrypt/live/%ドメイン%/ -lo
total 4
lrwxrwxrwx 1 root  36 Sep 14 03:00 cert.pem -> ../../archive/%ドメイン%/cert2.pem
lrwxrwxrwx 1 root  37 Sep 14 03:00 chain.pem -> ../../archive/%ドメイン%/chain2.pem
lrwxrwxrwx 1 root  41 Sep 14 03:00 fullchain.pem -> ../../archive/%ドメイン%/fullchain2.pem
lrwxrwxrwx 1 root  39 Sep 14 03:00 privkey.pem -> ../../archive/ドメイン/privkey2.pem
-rw-r--r-- 1 root 682 Jul 12 14:49 README

どうやら /etc/letsencrypt/archive/%ドメイン%/ にあった各種ファイル名の最後にある数値がインクリメントされていて、 /live/%ドメイン%/ の各種ファイルは archive/%ドメイン%/ の新しいファイルにシンボリックリンクが貼られているようです。

ということで新しいファイルを nginx に認識してもらうために設定ファイルを書き換えます。

$ sudo vi /etc/nginx/sites-available/tm3
-    ssl_certificate /etc/letsencrypt/archive/%ドメイン%/fullchain1.pem;
-    ssl_certificate_key /etc/letsencrypt/archive/%ドメイン%/privkey1.pem;
-    ssl_trusted_certificate /etc/letsencrypt/archive/%ドメイン%/fullchain1.pem;
+    ssl_certificate /etc/letsencrypt/live/%ドメイン%/fullchain.pem;
+    ssl_certificate_key /etc/letsencrypt/live/%ドメイン%/privkey.pem;
+    ssl_trusted_certificate /etc/letsencrypt/live/%ドメイン%/fullchain.pem; 
  • 内容としては archive ディレクトリではなく live ディレクトリに書き換える
  • 各種ファイルの最後にある数値を取り除く

最後に nginx を呼び出し直してあげます。

$ sudo systemctl reload nginx.service

これで再び HTTPS 接続できるようになりました。

OSM の変更セットを Changeset-map で開くブックマークレットを作った

できあがりはこちら

経緯的なもの

日本国内で OSM のデータが編集されると山下さんのpsmjp_都道府県から編集された都道府県のアカウントが変更セットのコメントとユーザー名とコメントをツイートしています。

自分の編集で参考にするために埼玉県の編集をツイートするアカウントをフォローしていて面白そうな編集を見に行くのですが、openstreetmap.org が表示する編集内容に併せて Changeset Map で編集内容を視覚的に確認したい場合があります。

今までは変更セットの ID をコピーして Changeset Map に貼り付けていたのですが、だんだん面倒になってきたので変更セットの URL から Changeset Map の URL を作って遷移するブックマークレットを作ってみました。

osmjp_saitama から気になった編集のツイートにあるリンクをクリック→ブラウザで変更セットの表示→ブックマークレットで Changeset Map を表示みたいな流れで確認しやすくなりました。

MySQL のログローテーションでトラブってた話

debian 9.5 上で MySQL 5.5 っぽい MariaDB 10.1 についての話です。
MariaDB ですがファイル類が mysql 表記なので MySQL と書いていきます。

自宅にある Zabbix サーバーが動いていたマシンの HDD にトラブルがあり、新しい HDD に移行作業を行いました。/var/lib/mysql をまるっとコピーするという移行なので若干のトラブルはありそうと思っていましたが…。

新サーバーセットアップ時のログローテーション用ユーザーと旧サーバーのログローテーション用ユーザーでパスワードが違うことが原因っぽいです。

  • MySQLdebian-sys-maint ユーザーの存在を確認
  • あればパスワードを再設定、なければユーザーを作成
  • /etc/mysql/debian.cnf の内容を編集

でイケると思う。

順を追って原因を探ってみた

logrotate のエラーはこんな感じ

/etc/cron.daily/logrotate:
mysqladmin: connect to server at 'localhost' failed
error: 'Access denied for user 'root'@'localhost' (using password: NO)'
error: error running shared postrotate script for '/var/log/mysql/mysql.log /var/log/mysql/mysql-slow.log /var/log/mysql/mariadb-slow.log /var/log/mysql/error.log '
run-parts: /etc/cron.daily/logrotate exited with return code 1

/etc/cron.daily/logrotate を実行した時のログなのでファイルを見ると

#!/bin/sh

test -x /usr/sbin/logrotate || exit 0
/usr/sbin/logrotate /etc/logrotate.conf

設定ファイルは /etc/logrotate.conf なのでこっちも見る。
めぼしい設定がないので include してるディレクトリになんかありそう。

<snip>
# packages drop log rotation information into this directory
include /etc/logrotate.d
<snip>
$ ls /etc/logrotate.d/ -1
apache2
apt
dpkg
exim4-base
exim4-paniclog
mysql-server
rsyslog
samba
ufw
unattended-upgrades
zabbix-agent
zabbix-server-mysql

/etc/logrotate.d/mysql-server を開いて見ると

# - I put everything in one block and added sharedscripts, so that mysql gets
#   flush-logs'd only once.
#   Else the binary logs would automatically increase by n times every day.
# - The error log is obsolete, messages go to syslog now.
/var/log/mysql/mysql.log /var/log/mysql/mysql-slow.log /var/log/mysql/mariadb-slow.log /var/log/mysql/error.log {
        daily
        rotate 7
        missingok
        create 640 mysql adm
        compress
        sharedscripts
        postrotate
          test -x /usr/bin/mysqladmin || exit 0
          if [ -f `my_print_defaults --mysqld | grep -m 1 -oP "pid-file=\K.+$"` ]; then
            # If this fails, check debian.conf!
            mysqladmin --defaults-file=/etc/mysql/debian.cnf --local flush-error-log \
              flush-engine-log flush-general-log flush-slow-log
          fi
        endscript
}

mysqladmin/etc/mysql/debian.cnf を読み込ませてるっぽい
/etc/mysql/debian.cnf は root 所有で 600 なので sudo で見てみると

[client]
host     = localhost
user     = root
password =
socket   = /var/run/mysqld/mysqld.sock
[mysql_upgrade]
host     = localhost
user     = root
password =
socket   = /var/run/mysqld/mysqld.sock
basedir  = /usr

別のマシンではここでユーザーに debian-sys-maint が入っていてしっかりパスワードが設定されています。
MySQL にログローテーション用ユーザーを追加してこのファイルを書き換えてあげれば良さそう。

MySQL のコンソールに入ってユーザーの情報を確認します。

$ mysql -uroot -p
MariaDB > SELECT Host, User FROM mysql.user;
+-----------+------------------+
| Host      | User             |
+-----------+------------------+
| %         | zoar             |
| 127.0.0.1 | root             |
| ::1       | root             |
| localhost | debian-sys-maint |
| localhost | root             |
| localhost | zabbix           |
+-----------+------------------+

debian-sys-maint ユーザーはいるので旧 HDD から /etc/mysql/debian.cnf を持ってくるかパスワードを再設定すればよさそうです。
旧 HDD は既に外してしまっているのでパスワードを再設定します。

MariaBD > SET PASSWORD FOR 'debian-sys-maint'@'localhost' = PASSWORD('%見せないよ%'); 

/etc/mysql/debian.cnf にさっきのパスワードを入れておきます。

$ sudo vi /etc/mysql/debian.cnf
# Automatically generated for Debian scripts. DO NOT TOUCH!
[client]
host     = localhost
user     = debian-sys-maint
password = %見せないよ%
socket   = /var/run/mysqld/mysqld.sock
[mysql_upgrade]
host     = localhost
user     = debian-sys-maint
password = %見せないよ%
socket   = /var/run/mysqld/mysqld.sock
basedir  = /usr

ローテーションを試してみます。

$ sudo logrotate -d /etc/logrotate.d/mysql-server

エラーは出てないっぽいのでコレでイケるんじゃないかな。

SIMA を GeoJSON に変換する npm パッケージを公開しました

測量データ共通フォーマット SIMA の通称 CSV 版を GeoJSON ファイルに変換できるスクリプトを npm のパッケージとして公開しました。ソースは GitHub置いてあります。

使い方

インストールは npm から簡単にできます。

# sudo npm i -g sima2geojson

SIMA ファイルと SIMA に記録されている座標の平面直角座標の系を EPSG コードで与えると WGS 84 で点の GeoJSON と面の GeoJSON を出力します。 EPSG のコードは epsg.io とかで検索すると出てきます。

測地成果2000の場合は系番号Ⅰが EPSG:2443 で系番号ⅩⅨは EPSG:2461
測地成果2011の場合は系番号Ⅰが EPSG:6669 で系番号ⅩⅨは EPSG:6687

みたいな感じです。

# sima2geojson -S sample.sim -E 6677
→ sample.point.geojson
→ sample.polygon.geojson

試しに3515の点を持ち1035の画地が登録された SIMA データを変換しましたが割と一瞬で GeoJSON が出来てきました。

今のところコマンドライン専用ですが気が向いたら他の JavaScript からインポートして使える形にするかもしれません。

能書き

GeoJSON の RFCで座標参照系を指定する項目が削除され、 座標は緯度経度を使って WGS 84 で表現することになったため、以前公開した Ruby スクリプトJavaScript 版のように出力先の GeoJSON に座標参照系を埋め込むパターンが使えなくなってしまいました。
QGIS など一部のソフトウェアでは互換性維持のためなのか座標参照系を認識してくれますが、いつまで認識してもらえるかわからないので日本の測量座標系を WGS 84 に変換するタイプのスクリプトを書こうと思っていました。

今回公開したパッケージでは投影系や座標参照系を変換してくれる Proj4 の npm パッケージを使って日本の測量座標系を WGS 84 に変換しています。

なお、今回のパッケージでも以前から課題である「路線データの変換」にはまだ対応していません。
測量データ共通フォーマット SIMA Ver.04.1の仕様が書かれた本が存在するようなので取り寄せてちゃんと理解する必要があるので時間かかると思います。

Tasking Manager 3 を更新する

いくつかの言語で表示するとタスクが2回表示される問題が解決されたので解決済のシステムに更新します。

まずサービスを停止させます。

$ sudo systemctl stop tm3.service
$ sudo systemctl stop nginx.service

TM3 のディレクトリに入って GitHub から最新のシステムを引っ張ってきます。

$ cd ~/tasking-manager/
$ git pull
error: Your local changes to the following files would be overwritten by merge:
        server/config.py
Please commit your changes or stash them before you merge.
Aborting

git の追跡対象である server/config.py に書かれた APP_BASE_URL を書き換えているのでどうにかしろと言われ pull が中断します。
現在の内容をパッチに書き出してローカルの最新コミットの状態に戻します。

$ git diff server/config.py > ~/config.patch
$ git checkout -- server/config.py

今度は大丈夫なはず

$ git pull

無事更新されたら server/config.py の内容にパッチを当てて自分の環境用にします。

$ patch server/config.py ~/config.patch

今回の目玉、フロントエンドの更新です。

$ cd client

//更新された npm パッケージがないか確認する
$ npm outdated

Current と Wanted が違ってなさそうなのでOK。
フロントエンドをビルドします。

$ gulp build

最後にサービスを起動すればOK。

$ cd ~
$ sudo systemctl start tm3.service
$ sudo systemctl start nginx.service

ブラウザからアクセスすると問題が解決しているはずです。

f:id:k-side:20180717095332p:plain

Tasking Manager 3のサイトを HTTPS 化する

前回設定した Tasking Manager 3 を Let's Encrypt で HTTPS 化します。

k-side.hatenablog.jp

作業はこんな感じ。

  • 設定のバックアップ
  • certbot の導入
  • nginxの設定
  • Tasking Managerの設定
  • 自動更新の設定

設定のバックアップ

etckeeper でいいやって楽しました。

$ sudo apt install -y etckeeper

debian 9.4 では勝手に Initial commit までやってくれました。

次に certbot に渡す nginx のドキュメントルートを確認しておきます。
今回はこんな感じになっています。

/home/%user name%/tasking-manager/server/web/static/dist

ファイアウォールhttps 接続で使われるポートを開けておきます。

$ sudo ufw allow https

certbot の導入・証明書取得と作成

Let's Encrypt の処理をよしなにやってくれる certbot を導入します。
wget でホームディレクトリの src 内に certbot ディレクトリを作ってそこに置いておきます。

$ mkdir -p ~/src/certbot
$ cd ~/src/certbot
$ wget https://dl.eff.org/certbot-auto
$ chmod a+x certbot-auto

配置できたら早速証明書の取得をします。
確認しておいた nginx のドキュメントルートとドメインを渡して実行すればOK。

$ certbot-auto certonly --webroot \
-w /home/%user name%/tasking-manager/server/web/static/dist \
-d %ドメイン%

取得した証明書は次のディレクトリに保存されていました。

/etc/letsencrypt/archive/%ドメイン%/fullchain1.pem;
/etc/letsencrypt/archive/%ドメイン%/privkey1.pem;

Key Exchange のスコアを上げるために dhparam を作っておきます。

$ sudo openssl dhparam -out /etc/ssl/dhparam.pem 2048

個々で指定したパス /etc/ssl/dhparam.pem は nginx の設定に使います。

nginx の設定

nginx の設定ファイルを書き換えます。

$ sudo vi /etc/nginx/sites-available/tm3

次の行を追加しました。確認した証明書の保存場所をここで使います。
元からあった listen 80; と同じインデントレベルに置いてあります。

    listen 443 ssl;
    ssl_certificate /etc/letsencrypt/live/%ドメイン%/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/%ドメイン%/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/%ドメイン%/fullchain.pem; 


    //openssl で作った dhparam へのパスです
    ssl_dhparam /etc/ssl/dhparam.pem;

    ssl_stapling on;
    ssl_stapling_verify on;

    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;

    ssl_ciphers ECDHE+RSAGCM:ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:!EXPORT:!DES:!3DES:!MD5:!DSS;
    ssl_prefer_server_ciphers  on;

    add_header Strict-Transport-Security max-age=15768000;

書き換えたら nginx をリロードしてエラーが出なければOK。

$ sudo systemctl reload nginx.service

2018-11-08 修正

更新がうまく行かなかったので設定ファイルを変更しました。

-    ssl_certificate /etc/letsencrypt/archive/%ドメイン%/fullchain1.pem;
-    ssl_certificate_key /etc/letsencrypt/archive/%ドメイン%/privkey1.pem;
-    ssl_trusted_certificate /etc/letsencrypt/archive/%ドメイン%/fullchain1.pem;
+    ssl_certificate /etc/letsencrypt/live/%ドメイン%/fullchain.pem;
+    ssl_certificate_key /etc/letsencrypt/live/%ドメイン%/privkey.pem;
+    ssl_trusted_certificate /etc/letsencrypt/live/%ドメイン%/fullchain.pem; 

詳しい内容はコチラ↓

k-side.hatenablog.jp

Tasking Manager の設定

Tasking Manager には OSM アカウントで認証した後に戻ってくるコールバック URL などで使われる APP_BASE_URL が設定されているので、ここを https にしておかないとアカウント認証をして Tasking Manager に戻ってくる時に http 接続に戻ってしまいます。

$ cd ~/tasking-manager/server/
$ vi config.py

下記の部分を書き換えればOK。

  class ProdConfig(EnvironmentConfig): 
-     APP_BASE_URL = 'http://%ドメイン%'
+     APP_BASE_URL = 'https://%ドメイン%'

gunicorn を再起動させます。

$ sudo systemctl restart tm3.service

ここで Tasking Manager に HTTPS アクセスできれば大丈夫なはず。

自動更新の設定

自動で証明書が更新されるように cron に設定を追加します。

今回は毎月13日の午前3時00分に更新させる設定にしました。
crontab を使わずに直接 /etc/cron.d/ にファイルを作っちゃいました。

動かなかったらどうしよ(

sudo sh -c "echo '00 03 13 * * root /home/%user name%/src/certbot/certbot-auto renew --post-hook \"systemctl reload nginx.service\"' > /etc/cron.d/letsencrypt"

SSL のスコア

Qualys SSL LABS SSL Server Test でセキュリティレベルを計測したところ A+ でした。

f:id:k-side:20180712155929p:plain