にせねこメモ

はてなダイアリーがUTF-8じゃないので移ってきました。

粉末状完全食・日米対決: COMP vs. Soylent飲み比べ

f:id:nixeneko:20180407222131p:plain

完全食について

完全食とは、健康を維持するために必要な栄養をすべて含んだ食品のこと。ここでは、SoylentとCOMPをとりあげる。


Soylentという、食事を代替することを目的とした粉末状の食料がある。粉末のプロテインのように水などに溶かして飲む。2013年にアメリカでクラウドファンディングが実施され、2014年から最初の商品であるSoylent v1.0が出荷された。

公式の通販サイトでは日本への発送はしていないのだが、このたび知人がアメリカに行くとのことだったので、お土産にSoylentをリクエストしてみた。


COMPはSoylentの日本版とでもいうべきものであり、Soylentが日本への配送を行っていないことが開発の一つのきっかけであったらしい*1
成分についても、日本の厚生労働省が出している必要な栄養素を元にしていて、材料も日本で手に入るものに変えているとのことである。

実食

実際に飲み比べたのは

  • COMP v.4
  • Soylentのformlula v.1.8

である。食品なのにバージョン表記がなされているのが工学っぽい。

見た目比較

f:id:nixeneko:20180407224215p:plain
左がCOMP、右がSoylentである。

  • 粉の色: Soylentの方が黄色っぽく、COMPの方は白っぽい
  • 体積ベースで、粉:水=1:1になるようにシェーカーに投入し、振り混ぜた。
  • 液体の色: 混ぜた後の液体の色としてはほとんど変わらないが、Soylentの方がやや白っぽい

飲み比べ

f:id:nixeneko:20180407222802p:plain

COMP V.4
  • きな粉っぽさが強い
    • 全体として粉っぽさがあり、舌触りがざらざらしている
  • シナモンの香りがする
  • 甘く、飲みやすい
    • なんとなく、飲む八つ橋といった感じもある

COMPはv.3時代に購入して飲んでたのだが、v.3は豆乳臭さが残っていた。それに比べて、v.4は初めて飲んだのだが、凄く飲みやすく、おいしくなっていて驚いた。

Soylent v1.8
  • 塩味が強めに感じられる
  • 甘味もあるが、薄めな気がする
    • 全体として、「甘い」というより「しょっぱい」という印象
  • 液はなめらかであり、粉っぽさはないが、噛むとじゃりじゃりした感覚が少しある。

COMPと比較するとしょっぱさが際立つという感想だったが、Soylent単体で飲んでみたところ、そこまでしょっぱさが気になる訳でもなかった。味の雰囲気を牛乳に近づけているような気がする。
(2018-04-16追記)濃いめだと「しょっぱい」という印象だったが、もう少し水で薄めると塩味も気にならなくなり、さらに薄めると豆乳っぽさが感じられた。(追記終)


全体として、以前自分がCOMP v.3を飲んでたための慣れもあるのだろうけれど、COMP v.4の方がSoylentより飲みやすく感じた。

成分量比較

甘味や塩味について、400kcalあたりの分量で比較してみると、

ナトリウム 炭水化物 食物繊維 糖質
Soylent 320mg 39g 5g 34g
COMP 264mg 59.3g 4.3g 55g

となっている。

ナトリウムについてはCOMPは少なめになっている。これはナトリウムの基準量は上限であり、他の食事で多めに摂取されることが予想されるからだろう。逆に糖質についてはCOMPの方が多い*2。これらは実食したときの味の感覚と合っているように思う。

*1:食に関心のないミレニアルが「完全食」で半年生活してみた | BUSINESS INSIDER JAPAN

*2:とはいえ、甘さに寄与しない糖質もあるし、糖質以外でも甘さをもつものもあり(人工甘味料など)、甘味への寄与は何ともわからない。

Ubuntu 16.04でgooglei18n/fontviewをビルド

OpenTypeのvariable fontが発表され、デモフォントとvariable font対応のフォントビューアが公開された。そのフォントビューアがgoogle18n/fontviewである。

たぶん最初の対応ビューアなので、variable font開発でも確認に使われているだろうと思われる。

これは、主にMac向けらしい(Mac向けバイナリも配布されている)が、Linuxでもビルドできるようなので、メモしておく。なお、一筋縄ではいかない模様。

環境

依存するライブラリ等のインストール

さて、README.mdを読んでいくと、次のような記述がある。

Building on Linux

You need to first install wxWidgets as well as latest versions of FreeType, HarfBuzz and FriBiDi.

https://github.com/googlei18n/fontview

これに従って、wxWidgets, FreeType, HarfBuzz, FriBiDiをインストールしていく。

wxWidgets

sudo apt install libwxgtk3.0-dev

FreeType

コンパイル面倒なのでStefan GlasenhardtによるPPAレポジトリを追加して入れる。

sudo add-apt-repository ppa:glasen/freetype2
sudo apt update
sudo apt install libfreetype6-dev

入ったバージョンは2.8.1。

HarfBuzz

harfbuzz/BUILD.md at master · harfbuzz/harfbuzz · GitHubに従ってインストールする。

sudo apt install libicu-dev libcairo2-dev libgraphite2-dev gcc g++ libfreetype6-dev libglib2.0-dev libcairo2-dev
wget https://www.freedesktop.org/software/harfbuzz/release/harfbuzz-1.5.1.tar.bz2
tar xvf harfbuzz-1.5.1.tar.bz2
cd harfbuzz-1.5.1
./configure
make
sudo make install

FriBiDi

リポジトリに入っているバージョンが0.19.7だったので、そのままリポジトリから入れてしまう。

sudo apt install libfribidi-dev 

Raqm

fontviewが必要とするのでこれも入れる。

sudo apt install libglib2.0-dev gtk-doc-tools
cd ~
wget https://github.com/HOST-Oman/libraqm/releases/download/v0.5.0/raqm-0.5.0.tar.gz
tar xvf raqm-0.5.0.tar.gz
cd raqm-0.5.0
./configure
make
sudo make install

FontViewのインストール

cd ~
sudo apt install git
git clone https://github.com/googlei18n/fontview.git
cd fontview/src/fontview
g++ *.cpp --std=c++11 `pkg-config --cflags --libs harfbuzz freetype2 fribidi raqm` `wx-config --cflags --libs` -o fontview

すると、~/fontview/src/fontview/fontviewにバイナリが生成される。コンパイルコマンドはREADMEの方法と異なっているので注意。

適当にパスの通ったところにコピーしておく。

cd ~
mkdir bin
cp fontview/src/fontview/fontview bin/

再起動する。

テスト

Adobeのvariable fontのプロトタイプをダウンロードして動作を確認してみる。

cd ~
wget https://github.com/adobe-fonts/adobe-variable-font-prototype/releases/download/1.003/AdobeVFPrototype.ttf
fontview AdobeVFPrototype.ttf

f:id:nixeneko:20180406232134p:plain
Weight/Contrastを弄ると太さや細い部分がどれだけ細いかを変化させることができる。

平成の次の新元号の文字列を取得するコード

※これはネタですが、エイプリルフールとは無関係です。


まず実用性はないのだが、新元号の文字列を取得するJavascriptコードを思いついたので書いておく。

新元号 = "㋿".normalize("NFKD");

今は何も意味のあるものは得られないが、新元号が発表されてしばらくすれば、最新のブラウザで上記のコードを実行すると新元号を表す文字列が取得できるようになるはずである。

実行例:

何をやっているのか

去年の12月に、日本のNational Bodyから、(「㍾」「㍽」「㍼」「㍻」のように)新元号の合字の独立したコードポイントを、古いITシステムのためにBMP*1に確保してくれという要請が出された。

これに対し、Unicodeコンソーシアムは、U+32FFを新元号として確保するようにした。

つまり、U+32FF “㋿”は新元号が発表された後、(フォントが対応すると)新元号で表示されるようになり、Unicodeにも正式に採録されるだろうと考えられる。
一方でUnicodeは、検索などの利便性のために、Unicode正規化という仕組みを用意している。この仕組みを利用すると、例えば「平成」で検索して「㍻」をヒットさせることができる。正規化の挙動はUnicode Character Database (UCD)として提供されている。

この仕組みを利用して、"㍻"から"平成"が得られる。

heisei = "㍻".normalize("NFKD"); //"平成"が返る

実行例:

同様に新元号“㋿”についても、ブラウザの利用するUCDが新元号の分解に対応したものに更新された暁には、Unicode正規化を利用して新元号を表す文字列が取得できる様になるはずである。


とはいっても、新元号が発表されてからUCDの新版が出るまではラグがあるはずであり、結局はUCDが対応するより前に手動で対応することになるのだと思う。そもそも、UCDの更新を行っていないシステムもあるだろうので、あまり期待しない方がよさそうである。

*1:U+0000~U+FFFF。UTF-16サロゲートペアを使わずに表現できる範囲。

はてなブログ+さくらのレンタルサーバをHTTPS化する

このブログを全面的にhttpsに切り替えたので、何をやったかを書いておく。

経緯

次のページに詳しいが、ブログやWebサイトをhttpsにせずhttpのままで運用していると、不都合があるっぽい:
はてなブログSSL暗号化通信(https)対応問題、10月から起こるかもしれない問題を解りやすく書いてみました。 - 神戸グルメゲリラ


一方ではてなブログは、2017年10月から2018年初頭にかけて、ユーザーが設定することで全面HTTPS化ができるよう実装予定だとのことだった:
はてなブログへの接続をすべてHTTPSにできる機能の実装予定と、利用を検討するユーザー様に準備いただきたいこと - はてなブログ開発ブログ

そして、2018/02/22から、はてなの提供するドメインによるブログ(つまり、独自ドメインでないブログ)のhttpsによる配信ができるようになったとのこと。
はてなが提供するドメインのブログで、HTTPSで配信できる仕組みの提供を開始しました(追記あり) - はてなブログ開発ブログ


記事内でも書かれているが、HTTPSで配信されるページにHTTPで配信されるコンテンツ(CSS, Javascript, img, iframeなど)が混在している場合(mixed content)に問題になる。

ここで、私ははてなブログはてなが提供するドメインで運用しているため、HTTPS配信への移行は簡単に達成できることが予想されるが、一方でWebフォントなどのリソースをさくらのレンタルサーバ上に置いているため、そのHTTPS化を行わないとそれらのリソースは読み込むことができなくなる。

さくらのレンタルサーバSSL

という訳で、ブログで利用するリソースを置いているさくらのレンタルサーバ(ライト)のHTTPS化を行う。

一つの方法として、共有SSLというものをさくらで提供している。これは、設定をするとexample.sakura.ne.jpの形の初期ドメインであればそのままHTTPS化ができるというものである。初期ドメインのまま利用しているばあいはこれを使うのが簡単で良いと思うが、一方でさくらのサブドメインを含む独自ドメインについては共有SSLはセキュリティ的によろしくなく*1、非推奨とのことである。
共有SSL|さくらのレンタルサーバ

他の方法として、独自でSSL証明書を取得して、HTTPS化する方法があるのだが、これは独自ドメインのためのもので、さくらのサブドメインでは使うことができないようである。

結局、今回は共有SSLを設定し、example.sakura.ne.jpの形の初期ドメインで使うことにして、ブログ記事で参照しているURLを書き換えた。
SSLの設定はサーバコントロールパネルから行う:
【共有SSL】設定方法 – さくらのサポート情報

さくらの共有SSLはプロキシとして動作しているため、細やかな設定が難しい場合があるらしい:
さくらのレンタルサーバでHTTPS(SNI SSL)な独自ドメインのWordpressサイトを構築する際の注意点 - Qiita

はてなブログの設定

最終的にはてなブログHTTPS化したのは2018年3月28日であるが、Mixed contentの問題があるため、HTTPで埋め込んでいるものは事前に書き換えておいた。
特にさくらのレンタルサーバSSL化したため、そこに置いていたリソースのURLがすべて変更になったので、はてなブログの記事で参照しているリソースをすべてHTTPSのものに書き換えた。

HTTPS

f:id:nixeneko:20180328231517p:plain
はてなブログダッシュボードの設定を開いたら、HTTPS配信が利用できる様になっていたため、切り替えた。
切替は一度確認が出るくらいで一瞬だった。
f:id:nixeneko:20180328231718p:plain

Mixed content対策

さくらのレンタルサーバに置いてたリソースはHTTPSに移行したが、他に、はてな記法の[~:embed]で埋め込んだものなどがちゃんと読み込めるか記事を見ていって確認する。
Mixed contentがある場合、ブラウザのコンソールにエラーが表示されるらしい。それも参考に潰していく。

サイト自体はhttp配信であるもののoEmbedなどで埋め込まれるページはhttpsで配信しているサービスも多く、割とそのままでもなんとかなる様であった。

mixed contentの制限があるのでhttpで埋め込んでるコンテンツがないか探していく。

  • リンクを張っているのみ→そのままでよい
  • カスタマイズCSSなどで参照している外部ファイル→HTTPSへの対応が必要
  • はてなフォトライフの画像の埋め込み→はてな記法で埋め込んでる限り、はてな側でよしなにしてくれるっぽい。
  • はてなhttp記法[~:sound]で音声ファイルのプレーヤを表示するのはhttpsに対応していないので、HTML5の<audio>タグ等で置き換える。
  • はてなhttp記法[~:embed]で埋め込み→埋め込み先がhttpsに対応していない場合、困るかもしれない。
    • oEmbedによるブログカード等の埋め込みが表示されなくなっていた場合、記事の編集画面を開いて保存し直したら表示される様になったことがある。

埋め込んでいた他サイトの動画やブログカードについて次のような感じであった。次のようなサイトは、URLがhttp://~のままでもはてな記法の埋め込み[http://~:embed]でうまくいった。一旦記事の編集画面を開いて保存し直すと表示されるようになるものもあった。

  • ニコニコ動画: サイトはhttpであるが、埋め込み用のページはhttpsで配信されている。
  • はてなブログ: ブログがhttp/httpsに関わらず、oEmbedで指定された埋め込み用のページはhttpsで配信されている。
  • Qiita: httpでアクセスするとhttpsに飛ばされる。


はてなブログtex記法を使っている場合、mixed content (混在表示コンテンツ)の警告が表示されることがあった。これは、一度記事の編集画面を開いて保存し直すと直るらしい。
はてなが提供するドメインのブログで、HTTPSで配信できる仕組みの提供を開始しました(追記あり) - はてなブログ開発ブログの追記を参照。



とりあえずしばらくは様子見。とはいってもhttpでの配信に戻すことはできないのだけど。

*1:××××.comというドメインであれば、共有SSLのURLは https://secure○○.sakura.ne.jp/××××.com のようになり、他のブログと同一ドメインにまとめられてしまう。

Pleromaのお一人様インスタンスをUbuntu 16.04で立てた作業ログ

https://nixeneko.infoにPleromaのおひとり様インスタンスを立ててみた。
Mastodon等やっている方は、よければ@nixeneko@nixeneko.infoをリモートフォローしてください。
(※20181227追記: この記事は古くなってるので、多分今はそのまま使えません。)

概要

Pleromaという、GNU SocialやMastodon互換のマイクロブログSNSソフトウェアがある。機能としてはTwitterに近い。
これは自分でサーバを用意して動かす(インスタンスを立てる)こともでき、インスタンスが異なっても互いにフォローできる*1ので、自分専用のインスタンスとして使っても問題ない。
Twitterという一企業のサービスに依存しないのも良いなあと思って、VPSを借りて立ててみた。


以降は2018/3/6に作業したログという感じなので、まとまっていないし、現在では変わっている部分もあるかもしれない。

実際に立ててみたい場合には、Pleroma公式Wikiのインストールガイドや次のページなどを参照するとよいと思う。

下準備

  • ドメインを取得した(nixeneko.info)。
  • ConoHaで一番安いメモリ512MBのVPSを借りた。
    • OSはUbuntu 16.04(.4 LTS)にし、SSH用にローカルで作成した公開鍵を登録しておいた(とはいえ、別に作業用のユーザを作成したので後で削除した)。接続許可ポートはすべて許可にした。
  • VPSIPアドレスを確認し、取得したドメインVPSIPアドレスを指すようにドメインのAレコードを設定した。

作業ログ(2018/3/6)

初期設定

上のページを参考にサーバの初期設定を行った。

rootでSSHでログインして(公開鍵を設定してない場合はConoHaのコンソールから作業することになると思う)、ソフトウェアを更新する。

apt update
apt upgrade

と更新したら、設定がリポジトリでインストールしたデフォルトから変更されてるよって言われて置き換えるか聞かれたが、/etc/cloud/cloud.cfgはそのまま残した(これは初回起動時に実行されるものらしいので、たぶんどっちでもよい)。

作業ユーザの追加

rootユーザで

adduser workuser
gpasswd -a workuser sudo

とし、作業ユーザを追加しsudoできるようにした。

su workuser

rootから作業ユーザに切り替える。

sudo: unable to resolve host回避

その後、sudoする度に“sudo: unable to resolve host (ホスト名)”と表示されるので、/etc/hostsに

127.0.1.1       (ホスト名)

を追記したら表示されなくなった。
参考: sudo: unable to resolve host が表示されたら - Qiita

作業ユーザへのSSH公開鍵の設定
cd ~
mkdir .ssh
chmod 700 .ssh
cd .ssh
touch authorized_keys
chmod 600 authorized_keys
nano authorized_keys

authorized_keysにローカルで作成した公開鍵をペーストし保存した。

sshdの設定
sudo nano /etc/ssh/sshd_config

/etc/ssh/sshd_configを開き、ルートログイン禁止とsshのポートの変更を行った。
ルートログイン禁止:

PermitRootLogin no

SSHポートの変更:

Port 10022

以上のように書き換え(sudo sshd -tで構文チェックができる)、sshdを再起動。

sudo service sshd restart
rootユーザに対して追加されていた公開鍵を消す
sudo su root
rm ~/.ssh/ authorized_keys

設定が済んだら作業用ユーザでログインし直す(ポートも変更したものに合わせる)

Pleromaのインストール

公式のWikiに載ってるのに従ってやっていく。

PostgreSQL 9.6のインストール

9.6以上のバージョンが標準リポジトリにないので、PostgreSQLの公式ページに従ってインストールする。

sudo nano /etc/apt/sources.list.d/pgdg.list

以下を書いて保存する。

deb http://apt.postgresql.org/pub/repos/apt/ xenial-pgdg main

その後、次のコマンドを実行してインストールする。

wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
sudo apt update 
sudo apt install postgresql-9.6 postgresql-contrib-9.6
Elixir 1.5+

参照: Installing Elixir - Elixir

wget https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb && sudo dpkg -i erlang-solutions_1.0_all.deb
sudo apt update
sudo apt install elixir
他に必要なものをインストール

他の必要なパッケージをインストールする。

sudo apt install erlang-dev erlang-parsetools erlang-xmerl git build-essential nginx
ユーザ作成
sudo adduser pleroma
sudo usermod -aG sudo pleroma
su pleroma
ソースコードを持ってきて必要なプログラムをインストールしたり設定をする
cd ~
git clone https://git.pleroma.social/pleroma/pleroma
cd pleroma
mix deps.get

Hexをインストールするか聞かれたらyを入力。

設定ファイルを作成
mix generate_config

rebar3をインストールするか聞かれるのでy。
他にも、ドメイン名、インスタンス名、adminのEメールアドレスを入力する。
mediaproxyを有効にするか聞かれ、nとした。

作成された設定ファイルをリネームする。

mv config/generated_config.exs config/prod.secret.exs
データベースの作成・マイグレーション
sudo su postgres -c 'psql -f config/setup_db.psql'
MIX_ENV=prod mix ecto.migrate
起動テスト
MIX_ENV=prod mix phx.server

これで起動するが確かめたらCtrl-Cで停止する。

SSL証明書取得

Let's EncryptでSSL証明書を取得する。(ここらへんよくわかってない)

sudo add-apt-repository ppa:certbot/certbot
sudo apt update
sudo apt install python-certbot-nginx
sudo certbot certonly -d (ドメイン名)

すると色々聞かれるので入力すると、 /etc/letsencrypt/live/(ドメイン名)/ 以下に証明書が生成された。
(Pleromaのサイトによると証明書の取得についてより先にnginxの設定がきているので、その順番でやっていたが、certbot --nginxというふうに証明書を取得しようとしたところ、nginxの設定で指定されている証明書がないよ、とエラーが出て動かせなかった。最初は--standaloneで証明書取得を行った方が楽かもしれない)

nginxの設定

設定ファイルをコピーし、設定を変更する。

sudo cp /home/pleroma/pleroma/installation/pleroma.nginx /etc/nginx/sites-enabled/pleroma.nginx
sudo nano /etc/nginx/sites-enabled/pleroma.nginx

サーバのドメインを指定し、cert pathsも取得した証明書にあわせて修正する。

sudo systemctl restart nginx.service
サービスの設定
sudo cp /home/pleroma/pleroma/installation/pleroma.service /lib/systemd/system/pleroma.service
sudo nano /lib/systemd/system/pleroma.service

/lib/systemd/system/pleroma.serviceを開き、[Service]のところに

Environment="MIX_ENV=prod"

を書き加える。

sudo systemctl start pleroma.service

サービスを起動する。

自分用のアカウントを作る

設定したドメインにアクセスし、自分で使うためのPleromaのユーザを作成する。

登録の停止
nano ~/pleroma/config/prod.secret.exs

を編集し

  limit: 400,
  registrations_open: false

に変更して登録を停止した。またついでに投稿辺りの文字数の上限を何となく400文字とした。

設定の反映・自動起動設定

再起動してPleromaの設定を反映

sudo systemctl restart pleroma.service

Pleromaのサービスを自動起動するように設定

sudo systemctl enable pleroma.service
iptablesの設定

firewall有効化

sudo ufw enable

Ubuntuファイアウォールはデフォルトでufwなのであるが、iptablesの方が設定ファイルの流用がしやすいのでiptables使って設定ファイルを編集した。ufwコマンドで設定する方が筋がいいかもしれない。

このサイトの記述を元に設定を書いたテキストファイル(~/iptables)を作成する。sshのポートをsshd_configで設定したものに合わせて変える。(最終的に、http, https, sshの接続を許可した)

設定を反映し、永続化させる。

sudo iptables-restore < ~/iptables
sudo apt install iptables-persistent

ここで、iptablesの設定の反映は次のコマンドでできるっぽい。

sudo /etc/init.d/iptables-persistent save 

参考: Ubuntuでiptablesの設定をiptables-persistentで永続化する

let'sencryptの自動更新
/usr/bin/certbot renew --post-hook "service httpd restart"

を動かしてみてちゃんと動くか確認する。(証明書取得してすぐだと更新されないが、Cert not yet due for renewalと出れば問題ない)

cronに更新用のコマンドを設定する。

sudo nano /etc/cron.d/letsencrypt

で開き、内容は次のようにする。これは毎週火曜日16時33分に発動する設定になっている。

33 16 * * 2 root /usr/bin/certbot renew --post-hook "service httpd restart"

参考: Let&#39;s Encryptを使ってSSL証明書を自動更新する(AWS/Amazon Linux/Apache) - Qiita

こまごまとした設定

Instance specific panelの表示
nano ~/pleroma/priv/static/static/config.json

  "showInstanceSpecificPanel": true

のようにtrueに変更する。

Instance specific panelの内容の設定は~/pleroma/priv/static/instance/panel.htmlを弄るとできる。

nano ~/pleroma/priv/static/instance/panel.html

として開いて、適当に書き換える。

インスタンスのサムネイル画像の差し替え

また、 ~/pleroma/priv/static/instance/thumbnail.jpeg を置き換えると、 Pleroma Instances などで表示されるアイコンが、デフォルトの暗灰色にπλήρωμαの文字の画像から変更できる。

ロゴの変更

ロゴ、つまりブラウザでPleromaを開いたとき上部真ん中に表示される画像が標準で ~/pleroma/priv/static/static/logo.png となっているので、これを入れ替えるとPleromaフロントエンドの真ん中上部に表示される画像を変更できる。
なお、ロゴ画像ファイルの位置は ~/pleroma/priv/static/static/config.json で指定されている。

チャットの削除

チャットはお一人様インスタンスでは意味がないので消す。 ~/pleroma/config/prod.secret.exs を開き、

nano ~/pleroma/config/prod.secret.exs

次の内容を最後に書き加える。

config :pleroma, :chat,
  enabled: false

設定が終わったらPleromaを再起動する。

sudo systemctl restart pleroma.service

Pleroma最新版への更新(2018/3/17)

2018/3/8あたりでPleromaにActivityPubによるfederationが追加された。私がインストールしたのは3/6なので更新したが、やや面倒だった。更新でなくて一から入れ直すのであれば必要ない手順だと思う。

Pleromaの更新

このページに書かれているように、Pleromaのサービスを止め、最新版のコードにし、マイグレーションを行った。

sudo systemctl stop pleroma.service
cd ~/pleroma/
git pull
MIX_ENV=prod mix ecto.migrate
Nginxの設定を変える

に従って、

sudo nano /etc/nginx/sites-enabled/pleroma.nginx

と /etc/nginx/sites-enabled/pleroma.nginx に次のように書き加える。

        proxy_set_header Host $http_host;
ActivityPub対応

に従って

MIX_ENV=prod mix deps.clean --build mime

を実行し、NginxとPleromaを再起動する。

sudo systemctl restart nginx.service
sudo systemctl restart pleroma.service

感想

PleromaはRaspberryPiでも動かせる! という触れ込みだったのでメモリ512MBのVPSにインストールしたみたのだが、今のところ問題なく動いているようだ。メモリ2GB程度無いと安定動作が難しいMastodonと比べると軽さが際立つ感じがする。

リソース使用量

2018/3/20現在、11アカウントをフォローし、10アカウントからフォローされている。
基本的に、リソース使用料はインストール時を除いて安定しているように思う。しばらく様子見。

CPU

f:id:nixeneko:20180320145001p:plain

ディスクIO

f:id:nixeneko:20180320145127p:plain

転送量

f:id:nixeneko:20180320145043p:plain

*1:このようにサーバーやインスタンスが異なっても「連合」(federation)して互いにフォローすることができる。連合しているSNSネットワークのことをfediverseという。

静的なHTMLページをoEmbedで他サイトに埋め込み可能にする

YouTubeなどの動画サイトの動画や、ブログ記事の内容をブログカードとして埋め込むための規格の一つとして、oEmbedがある。はてなブログもoEmbedに対応している(埋め込む側・埋め込まれる側両方とも)。

仕様概要

oEmbedの仕様は https://oembed.com/ にある。

これを見ると、埋め込まれる側がoEmbedに対応するには、だいたい次のようになっている。

URL schemeはendpointと同じドメイン(サブドメインは違ってもよい)で、http/httpsも一致してる必要がある。

http://flickr.com/services/oembed?url=http%3A//flickr.com/photos/bees/2362225867/

のようにAPI endpointにURL schemeを渡すと、仕様に定義されているようなパラメータをもったJSONまたはXMLが返ってくる。JSONXMLのどちらを返すかは、クエリパラメータで指定することもできるし、別々のendpointを用意することもできる。

さて、これではURL schemeAPI endpointのペアを知らないとoEmbedを呼び出すことはできない。ここで、HTMLページにその情報を埋め込むことで発見できるようにしている。次の例が挙げられている。

<link rel="alternate" type="application/json+oembed"
  href="http://flickr.com/services/oembed?url=http%3A%2F%2Fflickr.com%2Fphotos%2Fbees%2F2362225867%2F&format=json"
  title="Bacon Lollys oEmbed Profile" />
<link rel="alternate" type="text/xml+oembed"
  href="http://flickr.com/services/oembed?url=http%3A%2F%2Fflickr.com%2Fphotos%2Fbees%2F2362225867%2F&format=xml"
  title="Bacon Lollys oEmbed Profile" />

静的Webページにも対応できるか

API endpointは入力されたURLに対応して動的に出力を返すことを前提としている。
しかし、適当にHTMLで書いたページを公開するのに動的なCGIを置くのも気が引けるので、ページ毎にendpointを用意したら、動的な仕組みを用意せずともoEmbed対応できるのでは? と考えて、やってみた。

以下の4ファイルは https://nixeneko.sakura.ne.jp/hatenablog/20180316_oembed/ 以下にアップロードすることを前提としている。

index.html

<!DOCTYPE html>
<html>
<head>
<title>oEmbedのテスト</title>
<link rel="alternate" type="application/json+oembed"
  href="https://nixeneko.sakura.ne.jp/hatenablog/20180316_oembed/oembed.json"
  title="oEmbed Profile of oEmbedのテスト"/>
<link rel="alternate" type="text/xml+oembed"
  href="https://nixeneko.sakura.ne.jp/hatenablog/20180316_oembed/oembed.xml"
  title="oEmbed Profile of oEmbedのテスト"/>
</head>
<body>
このページを埋め込み可能にします。
</body>
</html>

クエリパラメータのurlは固定なので省いた。Vineなんかも似た様な感じで、動画毎にJSON/XMLファイルのURLを用意してクエリ文字列を使わずに対処してるっぽい。
参考: はてなブログの貼り付けにVineが対応していた - すなばいじり

oembed.json

{
    "author_name": "nixeneko",
    "html": "<div style=\"width:100%;height:120px;border:1px solid;font-weight:bold;overflow:hidden;background-color:white;\"><img src=\"https://nixeneko.sakura.ne.jp/hatenablog/20180316_oembed/simarin.jpg\" width=120 height=120 style=\"float:left;margin-right:10px;\"/>ここをキャンプ地とする</div>",
    "url": "https://nixeneko.sakura.ne.jp/hatenablog/20180316_oembed/index.html",
    "version": "1.0",
    "height": 120,
    "width": "100%",
    "description": "おい概要食わねぇか",
    "type": "rich",
    "title": "埋め込みどうでしょう"
}

JSONXMLの情報は、oEmbed公式の説明やはてなブログの設定などを参考に書いた。ブログなどではhtmlパラメータが埋め込まれて表示されるっぽい。
また、widthに100%と指定しているがこれは仕様としては正しくなく、ピクセル単位の数値にすべきであるが、はてなブログのoEmbed情報では100%となっている。

oembed.xml

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<oembed>
  <author_name>nixeneko</author_name>
  <description>おい概要食わねぇか</description>
  <height>120</height>
  <html>&lt;div style=&quot;width:100%;height:120px;border:1px solid;font-weight:bold;overflow:hidden;background-color:white;&quot;&gt;&lt;img src=&quot;https://nixeneko.sakura.ne.jp/hatenablog/20180316_oembed/simarin.jpg&quot; width=120 height=120 style=&quot;float:left;margin-right:10px;&quot;/&gt;ここをキャンプ地とする&lt;/div&gt;</html>
  <title>埋め込みどうでしょう</title>
  <type>rich</type>
  <url>https://nixeneko.sakura.ne.jp/hatenablog/20180316_oembed/index.html</url>
  <version>1.0</version>
  <width>100%</width>
</oembed>

.htaccess

AddType application/json .json
AddType text/xml .xml

HTTPレスポンスヘッダのContent-Typeを適切に設定する必要があり、JSONはapplication/jsonXMLtext/xmlにする。

テスト

はてなブログではURL記法で:embedを指定することで、oEmbed対応サイトを記事に埋め込むことができる。

[https://nixeneko.sakura.ne.jp/hatenablog/20180316_oembed/index.html:embed]

と書くと、↓のようにoEmbedの埋め込みが表示される。

ここをキャンプ地とする
↑ここまで

いけた! htmlパラメータがそのまま埋め込まれているようである。

また、 http://iframely.com/debug などを使ってoEmbedが認識されているかを確かめてみることもできる。

備考

ブログなどでoEmbedを埋め込む側ではセキュリティ的にホワイトリスト方式をとっているものもあり、そこではこのような得体のしれないoEmbedは参照されないことになるかもしれない。

JSONを手で書くのは現実的ではないので、何らかの方法で自動生成した方がよさそう。

oEmbedの情報はキャッシュされるので、JSON/XMLに変更を加えても反映にしばらく時間がかかる可能性がある。テスト中はキャッシュの生存期間cache_age (秒数を指定)を小さく指定しておくといいかもしれないが、必ずしもcache_ageの値を使うとは限らないらしい。

(2018-03-22 追記)
今回は埋め込み用HTMLにiframeを使っていないが、oEmbedで埋め込めるようになっているページは、大抵はiframeを使って別のHTMLページを読み込ませるようになっている。このとき、iframeによって埋め込まれるページのレスポンスヘッダのContent-Security-Policyが他サイトへの埋め込みを許可するように適切に設定されていないと、読み込まれないことになる。

現在のUnicodeモンゴル文字の問題点と最近の動き

モンゴル文字は、主にモンゴル語表記のための文字*1である。縦書き専用の文字であり、日本語の場合とは反対に左から右へと行を進める。また、アラビア文字のように続け書きされ、文字が語のどの位置に来るかによって形が変わる。
モンゴル文字は現在も中国の内モンゴル自治区モンゴル語の表記に現役で使用されている。他方モンゴル国ではソ連の影響下でモンゴル語の表記をキリル文字に切り替えたので、モンゴル文字は学校で習いはするものの一般にあまり使われない。

Unicode 3.0からモンゴル文字がシベ文字・トド文字・満州文字と統合されて収録されているため、コンピュータでこの文字を入力するにあたっては、独自の符号化方式を作成するのでなければUnicodeを利用しようとするのが当然に思える。しかし、現状のUnicodeモンゴル文字は致命的な欠陥を抱えている。

このエントリでは、2017年ころからUnicode Technical Committee (UTC)で盛んに議論されているUnicodeモンゴル文字ブロックの問題点と、その改善に向けた動きを、現代モンゴル語の表記を基本として見ていく。

Unicodeのサイトに、モンゴル文字に関するUTC文書がまとめられている。この記事はその最近の文書の内容を元にしている。

致命的な欠陥: 相互運用性がない

Unicodeモンゴル文字の最大で致命的な問題点は、エンコーディングのレベルで相互運用性(interoperability)がないことである。平たく言い替えると、機種依存文字状態になっている。

喩えを用いるのは不適当かもしれないが、ラテン文字の符号化で考えると、

  • 大文字小文字は統合し同一コードポイントとする
  • 大文字小文字の区別のためのvariant selectorを用意し、文字に後置するかしないかによって大文字小文字を区別する
  • 一方、variant selectorを付けた場合と付けない場合のどちらが大文字でどちらが小文字かが未定義なため、両方式のフォントが共存していて、互いに互換性がない

といった状況である。


現状のエンコーディングでは、モンゴル文字の表示はフォント依存である。これは、Unicode公式で明文化されている規則だけではフォントを実装するには情報が足りず(underspecified)、各々のフォントベンダがそれぞれの解釈で実装を進めた結果、ベンダ間で実装が非互換となっている。あるフォントでは正しく表示されるUnicode文字列が、別のフォントでは正しく表示されないということが普通に起こっている。

一例として、「良い」という意味の単語(キリル文字表記はсайн)を挙げる。次図は、L2/17-334 On migration issues of the graphetic modelのAppendixからの引用である。
f:id:nixeneko:20180224162725p:plain
縦は3種類のコードポイントの並びを、横は8つのフォントベンダの実装を示す。黒い単語は正しく表示されているものを、グレーは単語が正しく表示されていないものを表す。フォントベンダは、左からMenksoft (中国)、Delehi (Almasとも, 中国)、IMUCS (中国)、Founder (中国)、Huaguang (中国)、Bolorsoft (モンゴル国)、Microsoft (米国)、Google (米国)である。

どのコードポイントの並びをとっても、全てのフォントで正しく表示できるものは存在しないことが分かる。

ここで挙げられている三種類のコードポイントの組み合わせについて、一体どれが正しいのかというと、Unicodeでは規定されていない。つまり、誰も「何をどう表示すれば正しく実装できたといえるのか」が分かっていないという状態である。


どうしてこうなった: 音声情報の符号化

モンゴル文字が元々複雑だからというのが一つの原因ではあるが、もう一つの原因は現状のUnicodeモンゴル文字が音声情報ベースの符号化であることである。


X3L2/96-054 Joint proposal draft on encoding Mongolian Character Setは1996年にモンゴル国と中国が共同で作成したモンゴル文字符号化の草案であるが、その中で、符号化の方針として次のような記述がある。

● To guarantee the information integrity(not to lose the information) , different characters of the same glyph are coded separately.
The main principle to abide by is “No Information loss”.

(略)
② The sound information of Mongolian is very important especially in data indexing and searching. In many cases, a letter is of different pronunciation and different meaning accordingly. It is rather necessary to encode them all . This will contribute greatly to the information processing of Mongolian script.

http://www.unicode.org/L2/L1996/96054-n1368-mongolian.pdf

という訳で、形が同じだが別の音を表すものであるなら別々の文字としてコード化すべき*2だと言い、音声情報を符号化することを強く推している。

その後の議論については読んでないので分からないが、現状のUnicodeモンゴル文字ブロックも基本的にこの方針でエンコードされている。
この音声情報を符号化することが混乱を引き起こしている。

音声情報ベースで符号化を行うと、ソートが簡単になる、また異音同綴語を区別できるなどの利点はあるが、レンダリングが複雑になり、文字の入力や照合に混乱をもたらすなどの欠点がある。

音声情報を符号化するというのは、モンゴル文字ラテン文字転写とだいたい一対一の対応がとれるということでもある。モンゴル文語の文法書においてはラテン文字転写で説明されていることも多い。
転写とは文字の音声的な特徴を写し取ったもので、形の情報を区別しないことがある。そのため、転写は、一部の文字についてはモンゴル文字で書き分けない文字を書き分けるし、別の文字についてはモンゴル文字で書き分ける文字を書き分けられないという特徴がある。これが転写ひいては符号化されたコードポイントとモンゴル文字の字形との間の対応のずれとなり、どうにか対応付けをするために複雑な仕組みを必要としている。

モンゴル文字の複雑さ

音声情報を符号化したために、モンゴル文字の形状の複雑さはシステムやフォント側が引き受けることとなった。

モンゴル文字がどのように複雑だったり、混乱を招いているのかを見ていく。

母音調和による字形変化

モンゴル文字は、語の中のどの位置にくるかによって、また母音調和等によって形が変化する。

モンゴル語における母音調和とは、男性母音(a, o, u)と女性母音(e, ö, ü)の2つの母音系列が、原則一語中で混ぜて使われないというものである。他に、どちらの系列とも共存できる中性母音(i)がある。
母音が男性母音または中性母音からなる単語を男性語、女性母音または中性母音からなる単語を女性語という。中性母音のみからなる単語は女性語となる。

子音によっては、男性語と女性語で別の形を使うものがあり、例えば、U+182D MONGOLIAN LETTER GAは、次のように7種類以上の字形に変化する(赤部分。実際には母音等の文字とリガチャになっているものもありフォントグリフとは一致していないので注意)。
f:id:nixeneko:20180302222513p:plain
このように同じコードポイントの文字を、システムとフォントによって適切な形で表示する必要があるのだが、その規則は明示されてない部分も多いため、手探りで実装することになる。

二重母音のi

母音のiは次のような形を取り得る。
f:id:nixeneko:20180303133752p:plain
語中のiは基本的に「すね」(左下に突き出る斜め線のこと; шилбэ 脛)が1本でかかれる。

一方で、本記事の冒頭で掲げた「良い」という意味の単語(キリル文字でсайн)は、「子音s + 二重母音ai + 子音n」という構成になっているのであるが、語中の二重母音の二番目のiは「すね」が2本となり、これを“i”で転写する方式と“yi”と転写する方式とがある*3。それぞれに従うと「良い」сайнの転写は順に“sain”, “sayin”となる。

他方、二重母音の2番目にくるiはすべて「すね」2本なのかというとそうではなく、数字の8(キリル文字でнайм)とその派生語については例外的にiは「すね」1本でかくため、「良い」сайнを“sain”とする場合、同じ“i”でも「すね」が1本のときと2本が存在することになる。
f:id:nixeneko:20180303151408p:plain
また、本来の文字yは基本的に「すね」の先が上に跳ね上がった形でかかれる。そのため、二重母音の「すね」2本のiを“yi”で転写するポッペ式における“sayiqan”という転写は、

  • сайхан「素晴らしい」(yはまっすぐな「すね」)
  • саяхан「つい先ほど」(yは曲がった「すね」)

のどちらの語をも表しうる*4
f:id:nixeneko:20180303151434p:plain
このように、同じ文字が単語ごとに正書法によって複数の形に書き分けられるため、文字の形を変更するvariation sequenceという仕組みが存在している。これは、形を変更したい文字にvariation selectorという専用の符号を後置することで、文字を望んだ形に変更するという仕組みである。しかし、どれを本則として、どれをバリエーションとするかについて定義が不十分であるため、混乱がある*5

まとめると、冒頭で掲げた「良い」(сайн)という単語は、

  1. 語頭・語中の二重母音aiを転写するのに“ai”と“ayi”のどちらを使うか*6。両方採用することも可能。
  2. “ayi”を採用する場合、「基本はyをまっすぐな『すね』で表示して、曲がった形にするためにvariation sequenceという仕組みを用いる」か、あるいはその逆か

という2つの分類で説明できる。
繰り返すがこれについてはどれが正しいかというものは規定されていないため、どの方式にも理があるが、互換性はない。

書き分けない文字に別々のコードポイントを当てる

他にも、同じ見た目の文字でも音が異なるならば別々にコード化するという方針により、語中のどの位置でも書き分けのないo, uに別々のコードポイントが与えられている。ö, üについても同様である。他にも書き分けのない文字はあるが省略する。
f:id:nixeneko:20180303171046p:plain
モンゴル語を理解する人は発音が分かるので、どちらを使えばいいか分かるのではないかという考えもあるかもしれない。しかし、モンゴル文字表記が作られてから時間が経っているため、綴りと発音が乖離しており、発音からo, uのどちらだとわかるとは限らない。また、モンゴル語ではアクセントの関係で、第一音節にある母音ははっきりと発音されるが、第二音節以降の短母音は弱化して曖昧に発音される。そのため、転写方法においても、モンゴル文字で形の区別のないo, uについて、oとuをすべて区別して書き分ける方法と、第一音節のみo, uを書き分け、第二音節以降はuで統一するという方式が併存している*7。転写方法も一様でないし、その転写とほぼ一対一で対応する音声情報ベースのエンコードにおいても表現が一様にならないのは当然という気もする。

結果として同じ見た目になるコードポイント列がたくさん存在し、入力する人にとっても優しくないし、検索を行うにしても、形が同じなのに引っかからないという事態が発生することになる*8
さらに、キーボードのキートップからは同じ形の文字の区別がよくわからないため、「正しい綴り」というものがもし存在したとしても、それを入力するのは難しい。結果的に人にも機械にとっても厳しい仕組みとなっているのが現状である。

現状の問題点まとめ

現状のエンコーディングモデルについて、L2/17-328 Script Ad Hoc Group Recommendations on Mongolian Text Modelでは次のような欠点が挙げられている。

  • モデルが非常に複雑であり、仕様が十分に定義されていない(undespecified)。結果としてテキスト表現が曖昧である(ambiguous)
  • フォントやレンダリングエンジンに非常に複雑な文脈依存ルール(contextual rule)を必要とするが、明確な仕様がない
  • そのルールでは求める表示にならない文字を直すために、大量のvariation sequencesを必要とする
  • フォントの実装や提供を行うことが非常に困難
  • 結果、異なる実装やフォントで事実上相互運用性がない
  • 相互運用性を“修正”するために、不安定な根拠の不安定なパッチ群を必要とする
  • 国際ドメイン名でサポートされることはない(同じ見た目を示す複数のコードポイント列が存在するため、セキュリティ上困難)
  • 標準的なユーザにとって、検索が非常に困難になる可能性がある(入力テキストが曖昧性をもつため)
  • 顕著なセキュリティ上の懸念がある
  • テキスト表現に含まれる音声情報はtext-to-speechにも言語分析にも実際効果的ではない

散々な言われようである。

改善の動き

さすがにこの現状ではまずいだろうと、Unicodeモンゴル文字改善のためのScript Ad Hoc Groupが作られ、改善に向けた動きが活発になっている。

L2/17-243 Script Ad Hoc report and recommendations on Mongolianにおいて、2種類の改善案が出されている。それぞれの特徴を挙げる。

1. 字形アプローチ(Graphetic approach)

  • 文字の形と振舞いを基準に、音でなく形をベースとして文字を特定する
  • あいまいさがなくなり、同じ見た目の語であればコード列が一通りに定まる。見たとおりに入力すればいい
  • 現状のモデルの根本的な再構成であり、非互換
  • 15程度の文字を新規に追加し、混乱の生じない文字については再利用する。既存の文字には変更を加えず、現状のモデルとの共存が可能
  • アラビア文字のようなcursive-joining modelでシンプルに実装できる
  • 現代モンゴル語の表記(Hudumという)にはvariation sequencesを必要としない(歴史的な文書や表記ミスを再現するためにvariation sequencesは必要ではある)
  • 音声情報を持たないため、適切な順番にソートすることが難しく、同綴異義語の区別ができない

2. 音声アプローチ(Phonetic approach)

  • 現状のモデルを全体としては維持する
  • 現在の中国標準規格と整合しやすい
  • 新規に文字は追加せず、現在のvariation selectorsの振舞を修正あるいは廃止して新しく追加するもので置き換えることによって、相互運用性を確保する
  • 現状のモデルの複雑さをほとんど引き継ぐ


字形アプローチについてはL2/17-335 [Draft] A graphetic approach for the Mongolian encoding modelで独立した草案が作成されている。
また、モンゴル文字は字形アプローチとし、モンゴル文字と統合されている他の文字(トド文字・シベ文字・満州文字)については大きく変更せず*9、全体の整合性を整えた案がL2/17-333 A mixed encoding scheme for the Mongolian blockである。

これから字形アプローチ策定者はフォントやシステム等の試験実装を作成し、それによってモンゴル文字の表現において問題があるかどうかを検査していくだろうということである。

各国の反応

さて、Script Ad Hoc Groupは字形アプローチを強く推しているのであるが、中国やモンゴル国はどのように思っているのだろうか。
2017年9月23-25日に中国のフフホトで開催されたWG2 ad hoc meeting on MongolianのレポートがL2/17-347 Mongolian Ad Hoc Report (Hohhot, Inner Mongolia)である。

この文書によると、The Mongolian Working Group (おそらく中国か?)はthe Phonetic modelを支持し、モンゴル国の代表たちもthe Phonetic modelを支持しているとのことである。Unicode Technical Committeeの代表たちはどちらのモデルがよいとは言わなかったが、モンゴル文字テキスト処理の現状を懸念していることを表明した。

どちらにせよ、現状のモデルには多数の問題があり、改善策としてどちらの方式がとられたとしても、長期目標としてはモンゴル文字テキストを交換可能かつ将来にわたってアクセス可能にすること(interchangeable and accessible for future generations)であると会議の出席者は合意している。また、この問題の解決に向けて情報(や知識)を共有したり、協働することに同意したとのことである。

中国・モンゴル国の両国ともに現状と地続きの音声アプローチの方を支持しているようであるが、最終的にどの方式が選ばれるにしろ、相互運用性が確保されることは期待できそうである。
標準化の会議が年一回なので、公式の規格となるのは早くても2019年のUnicode 12.0以降となる。動向に注目したい。

参考文献

モンゴル文字に関するUTCの文書
Unicodeモンゴル文字の字形(variants)について
Unicode 10.0の、現状のモンゴル文字ブロックについての説明

*1:「用字系(script)」と言った方が適切かもしれないが、記事内では基本的に「文字」で統一した。

*2:「“cake”のcと“nice”のcは発音違うから別のコード当てよう!」みたいな話で、書き分けがないのであれば同じ文字として統合する方が分かりやすいし、Unicodeの他の文字体系でもそのようになっている。

*3:「すね」2本の二重母音aiを“ai”とする方式と“ayi”とする方式がある。参考: Transliteration Schemes For Mongolian Vertical Script

*4:塩谷茂樹・中嶋善輝(2011)『大阪大学世界言語研究センター 世界の言語シリーズ3 モンゴル語』、大阪大学出版会。初版第1刷 p. 60.

*5:Variation sequenceはUnicodeのStandardizedVariants.txtである程度の標準化がなされているが、抜けがあったり、不十分であるため、ここにおいても改善の議論がある。

*6:“ayi”の方を採用するメリットとして、наймの「すね」1本のiと区別可能という面がある。

*7:第二音節以降を一律にuで転写する方式は「現代の代表的な文語辞典であるレッシング(F. D. Lessing)の辞書が採用する方式」で、一方「歴史的な経過と形態論的な配慮を紙してoとuを表記し分ける方式」は「提案者にちなんでポッペ・モスタールト(Poppe-Mostaert)方式と称され」ていて、両方式が併存しているとのことである。(河野六郎 編(2001)『言語学大辞典 別巻 世界文字辞典』、三省堂。pp. 1038-1044「蒙古文字」の項)

*8:もちろん、現状のエンコーディングで同一形状を判定できるようなルールを作る場合、そのルールはフォント依存となる。

*9:トド文字・シベ文字・満州文字モンゴル文字の派生であるが、モンゴル文字で書き分けないが異なる音を表すものについて、文字を変形したり、点等の記号を付したりして字形の区別をつくり、曖昧さをなくした(減らした)ものなので、音と文字がよく対応し、音声アプローチでも問題が少ない。