うちで動いているRaspberry PiをMastodonインスタンスにしようと試行錯誤しているのは先日書いたとおりなのですが、トップページを確認できるとこまでいったので手順を公開します。でも最終的にはやっぱり失敗していますので不完全です。
手順は入れたばかりのまっさらなRaspbian Liteを想定しています。
手順の概要
用意するもの
- Raspberry Pi 2 Model B
(検証にはPi2B・Pi3Bを併用しました)
動作確認環境
- Raspbian GNU/Linux 8.0 Lite (Jessie)
- Docker 17.04.0-ce ※今回導入します
- docker-compose 1.13.0dev ※今回導入します
- Mastodon ※今回導入します
他の人のやり方との相違点
- Dockerを使用します
- docker-composeをビルドします(イメージ取ってくる方法だとダメだった)
- forkされたrpi-mastodonを使います(公式の方法だとダメだった)
- Let’s Encryptを使用します(オレオレ証明書じゃないよ)
- 最小構成を目指しました(リバースプロキシなどのスケールさせるための要素は除いています)
手順
インストールを始める前に、スワップ領域を拡大しておきます。スワップ領域を使うとSDカードの寿命を縮めますので、やりたくない方は飛ばしてください。
swapon -s
おそらく初期状態ではこのように表示されます。(Raspberru Pi 2の場合)
$ swapon -s
Filename Type Size Used Priority
/var/swap file 102396 0 -1
設定ファイルを編集します。
sudo systemctl stop dphys-swapfile sudo vi /etc/dphys-swapfile
このように変更します。
CONF_SWAPSIZE=2048
変更されたことを確認します。
sudo systemctl start dphys-swapfile swapon -s
サイズが増えていればOKです。
$ swapon -s
Filename Type Size Used Priority
/var/swap file 2097148 0 -1
Dockerをインストールします。こちらを参考にしました。
curl -sSL https://get.docker.com/ | sh
これで処理が15分ほど走ります。
バージョンは5/1現在、このように表示されました。
$ docker version
Client:
Version: 17.04.0-ce
API version: 1.28
Go version: go1.7.5
Git commit: 4845c56
Built: Mon Apr 3 18:22:23 2017
OS/Arch: linux/arm
Server:
Version: 17.04.0-ce
API version: 1.28 (minimum version 1.12)
Go version: go1.7.5
Git commit: 4845c56
Built: Mon Apr 3 18:22:23 2017
OS/Arch: linux/arm
Experimental: false
続いて、自分がroot権限がなくてもdockerコマンドを使えるようにしておきます。
(ユーザ名は仮にpiとしています)
sudo gpasswd -a pi docker
一度ログアウトし再度ログインします。
docker-composeをインストールします。Raspbianなのでそのままではインストールできません。なのでこちらを参考にしました。
git clone https://github.com/docker/compose.git cd compose docker build -t docker-compose:armhf -f Dockerfile.armhf . docker run --rm --entrypoint="script/build/linux-entrypoint" -v $(pwd)/dist:/code/dist -v $(pwd)/.git:/code/.git "docker-compose:armhf"
docker buildのところは気を付けて下さい。Raspberry Pi 2(swapなし)だと処理するのに1時間、Pi 3(swapあり)だと40分ほどかかりました。
docker-composeファイルができたことを確認します。
ls -l dist/
このように表示されます。
$ ls -l dist/
total 6844
-rwxr-xr-x 1 pi pi 7004340 Apr 29 18:15 docker-compose-Linux-armv7l
docker-composeファイルを/usr/local/bin/に配置します。
sudo cp dist/docker-compose-Linux-armv7l /usr/local/bin/docker-compose sudo chown root:root /usr/local/bin/docker-compose sudo chmod 0755 /usr/local/bin/docker-compose docker-compose version
バージョンは5/1現在、このように表示されました。
$ docker-compose version
docker-compose version 1.13.0dev, build baf457c
docker-py version: 2.2.1
CPython version: 2.7.13
OpenSSL version: OpenSSL 1.0.1t 3 May 2016
Mastodonをインストールします。こちらを参考にしましたが、公式の方法だとうまくいかないのでforkされたラズパイ専用のものを使います。
cd .. git clone https://github.com/gilir/rpi-mastodon cd rpi-mastodon
docker-compose.ymlの永続化設定は初めからされているので不要です。
続いて、.env.productionを編集します。
cp .env.production.sample .env.production vi .env.production
LOCAL_DOMAINの部分を自分の所持するドメインに変えます。私は「m.yagi.tc」にしました。
メールアドレスは設定しなくても済む方法がありますが、私は個人用にGoogle Apps(GSuite)を使っているのでアカウントを払い出して設定しました。
# Federation
LOCAL_DOMAIN=m.yagi.tc
LOCAL_HTTPS=true
...省略...
DEFAULT_LOCALE=ja
...省略...
SMTP_SERVER=smtp.gmail.com
SMTP_PORT=587
SMTP_LOGIN=mastodon@yagi.tc
SMTP_PASSWORD=********************************
SMTP_FROM_ADDRESS=mastodon@yagi.tc
ビルドします。1時間ほどかかります。
docker-compose build
ネットワークとボリュームを作成します。
docker network create proxy-network docker volume create --name=mastodon_public_assets docker volume create --name=mastodon_public_system docker volume create --name=mastodon_postgres docker volume create --name=mastodon_redis docker-compose run --rm web rake secret docker-compose run --rm web rake secret docker-compose run --rm web rake secret
数分かかります。
3回繰り返した”docker-compose run –rm web rake secret”の結果得られたキーを.env.productionに追記します。
vi .env.production
以下のように編集します。
PAPERCLIP_SECRET= 取得できたキー1
SECRET_KEY_BASE= 取得できたキー2
OTP_SECRET= 取得できたキー3
データベースのマイグレーションとフロントエンドのプリコンパイルを行います。30分ぐらいかかります。
docker-compose run --rm web rails db:migrate docker-compose run --rm web rails assets:precompile
立ち上げます。
docker-compose up -d
続いて、Let’s Encryptをインストールします。
cd .. git clone https://github.com/letsencrypt/letsencrypt.git cd letsencrypt/ ./letsencrypt-auto --help
nginxをインストールします。
sudo aptitude install nginx
証明書を取得します。
./letsencrypt-auto certonly --webroot -d m.yagi.tc --webroot-path /var/www/html(nginxで指定するルート)
メールアドレスを入力し、利用規約を読んだ上で同意します。
nginxの設定を編集します。
sudo vi /etc/nginx/sites-available/m.yagi.tc
MastodonのGitHubドキュメントを丸コピーして必要なところだけ編集します。
編集箇所は矢印で示した6箇所です。
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
listen [::]:80;
server_name m.yagi.tc; ←ホスト名
# Useful for Let's Encrypt
location /.well-known/acme-challenge/ { allow all; }
location / { return 301 https://$host$request_uri; }
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name m.yagi.tc; ←ホスト名
ssl_protocols TLSv1.2;
ssl_ciphers EECDH+AESGCM:EECDH+AES;
ssl_ecdh_curve prime256v1;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_certificate /etc/letsencrypt/live/m.yagi.tc/fullchain.pem; ←鍵の場所
ssl_certificate_key /etc/letsencrypt/live/m.yagi.tc/privkey.pem; ←鍵の場所
ssl_dhparam /etc/ssl/certs/dhparam.pem;
keepalive_timeout 70;
sendfile on;
client_max_body_size 0;
root /var/www/html; ←ルートディレクトリ
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
add_header Strict-Transport-Security "max-age=31536000";
location / {
try_files $uri @proxy;
}
location /assets {
add_header Cache-Control "public, max-age=31536000, immutable";
try_files $uri @proxy; ←この行を追加
}
location @proxy {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Proxy "";
proxy_pass_header Server;
proxy_pass http://127.0.0.1:3000;
proxy_buffering off;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
tcp_nodelay on;
}
location /api/v1/streaming {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Proxy "";
proxy_pass http://localhost:4000;
proxy_buffering off;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
tcp_nodelay on;
}
error_page 500 501 502 503 504 /500.html;
}
DH鍵を作成し、設定を有効化する準備をします。
sudo openssl dhparam 2048 -out /etc/ssl/certs/dhparam.pem sudo ln -s /etc/nginx/sites-available/m.yagi.tc /etc/nginx/sites-enabled/m.yagi.tc
準備ができたら事前テストをかけます。
sudo nginx -t
このような結果が出たら大丈夫です。
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
nginxを再起動し、設定を有効化します。
sudo service nginx restart
これでローカルIPアドレスを指定してHTTPSで接続すればこのようなページが表示されます。(ローカルIPアドレスだと証明書とURLが異なるのでブラウザの警告が出ます)
ところが……
ここまで来たんですけど、いざサインアップしてみるとログイン後にグレーの画面になったまま何も表示されません。どうやらトップページのHTMLだけは読めているのに、そこから先のリソースが足りてない(読み込まれてない?)ようです。ここで力尽きました。今日はここまで。
個人的にはこのあたりが怪しいと思っているdocker-compose.ymlの内容を貼っておきます。
$ cat docker-compose.yml
version: '2'
services:
db:
restart: always
image: armhf/postgres:9.6-alpine
networks:
- proxy-network
volumes:
- mastodon_postgres:/var/lib/postgresql/data
redis:
restart: always
image: armhf/redis
networks:
- proxy-network
volumes:
- mastodon_redis:/data
web:
restart: always
build: .
image: gilir/rpi-mastodon
env_file: .env.production
command: bundle exec rails s -p 3000 -b '0.0.0.0'
ports:
- "3000:3000"
depends_on:
- db
- redis
networks:
- proxy-network
volumes:
- mastodon_public_assets:/mastodon/public/assets
- mastodon_public_system:/mastodon/public/system
labels:
- "traefik.frontend.rule=Host:mastodon.lavergne.online"
# - "traefik.frontend.passHostHeader=true"
- "traefik.port=3000"
environment:
- WEB_CONCURRENCY=1
- MAX_THREADS=5
streaming:
restart: always
build: .
image: gilir/rpi-mastodon
env_file: .env.production
command: npm run start
ports:
- "4000:4000"
depends_on:
- db
- redis
networks:
- proxy-network
sidekiq:
restart: always
build: .
image: gilir/rpi-mastodon
env_file: .env.production
command: bundle exec sidekiq -q default -q mailers -q pull -q push
depends_on:
- db
- redis
volumes:
- mastodon_public_system:/mastodon/public/system
networks:
- proxy-network
networks:
proxy-network:
external:
name: proxy-network
volumes:
mastodon_postgres:
external: true
mastodon_redis:
external: true
mastodon_public_assets:
external: true
mastodon_public_system:
external: true
以上。