Okada Hiroshi の blog

typo が多いです

Mastodn API を叩くための access token を取得するコマンドラインプログラムを node.jsで書きました。

Mastodn API を叩くための OAuth2 の access token を取得する。コマンドコマンドラインツールを node.js で書いてみました。

www.npmjs.com

(途中でブラウザが立ち上がります。)

npm を公開するにのは初めてだったので、数日かかってしましましたが、これで bot を作るのが楽になったと思います。

なお、 mastodon の場合

config/initializers/doorkeeper.rb

# Access token expiration time (default 2 hours).
# If you want to disable expiration, set this to nil.
 access_token_expires_in nil

となっているので、 access_token の更新はしなくても良いようです。

mastodonインスタンスを VPS から自作サーバーに引っ越しました

今まで mastodon インスタンス toycode – Mastodon を の OVHとうい会社のVPS で運営してきましたが、結構ディスクをやメモリを食うので、自宅サーバーに引っ越すことにしました。

事前準備(VPS側)

  • 自宅サーバーに ubuntu16.04 と Docker, docker-compose 等の必要なソフトをインストールしました。
  • VPS から 自宅サーバに切り替えた時に DNS の変更が早く反映されるように TTL を 60 にしました、また VPS のホストを切替後も参照できるように old という名前を追加しました。DNSAmazon Route 53 を使っているので、比較的作業は簡単でした。

事前準備(自宅側)

  • NVR500でdns static a mastodon.toycode.com 192.168.100.200 ttl=120と入力し、自宅内からアクセスした時はLANのアドレスを返すようにしました。

停止

  • 僕以外、ほとんど使っている人はいないと思いますが、一応「止めますよ」と toot してから5分ほど待って docker-compose down でインスタンスを止めました。
  • インスタンスを停止したので、Amazon Route 53 で DNS のレコードを編集して、 mastodon.toycode.com が自宅を指すようにしました。

データの移行完了と起動

VPS 側で、パーミッション等の設定をした後、もう一度 rsync で残りのデータをコピーしました、事前に殆どのデータをコピーしていたので、*(1分以内** でコピーが終わりました。 docker-compose up -d で起動し、自宅内のパソコンと(LAN内)、WiFiを切った状態のスマートフォン(外からのアクセス)で動作しているのを確認しました。

Mastodon サーバーを v1.2.2 にしました

Mastodon サーバーを v1.2.2 にしました。

mastodon.toycode.com

今回は、 docker-compose.yml を見なおして docker-compose pull だけで済むようにしました。 ( build しなくて良くしました )

version: '2'
services:

  nginx:
    image: nginx:alpine
    depends_on:
      - web
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d
      - ./nginx/ssl:/etc/ssl

  db:
    restart: always
    image: postgres:alpine
    volumes:
      - ./postgres:/var/lib/postgresql/data

  redis:
    restart: always
    image: redis:alpine
    volumes:
      - ./redis:/data

  web:
    restart: always
    image: gargron/mastodon:v1.2.2
    env_file: .env.production
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    depends_on:
      - db
      - redis
    volumes:
      - ./public/assets:/mastodon/public/assets
      - ./public/system:/mastodon/public/system

  streaming:
    restart: always
    image: gargron/mastodon:v1.2.2
    env_file: .env.production
    command: npm run start
    depends_on:
      - db
      - redis

  sidekiq:
    restart: always
    image: gargron/mastodon:v1.2.2
    env_file: .env.production
    command: bundle exec sidekiq -q default -q mailers -q pull -q push
    depends_on:
      - db
      - redis
    volumes:
      - ./public/system:/mastodon/public/system

  cron:
    restart: always
    image: gargron/mastodon:v1.2.2
    env_file: .env.production
    command: |
      sh -c 'sh -s <<EOF
        trap "break;exit" SIGHUP SIGINT SIGTERM
        while /bin/true; do
          /bin/date -Ihours 
          /usr/bin/time rake mastodon:daily 
          /bin/sleep 1439m
        done >>/var/log/cron.log 2>&1
      EOF'
    depends_on:
      - db
      - redis
    volumes:
      - ./public/assets:/mastodon/public/assets
      - ./public/system:/mastodon/public/system
      - ./cron/log:/var/log

また、 メーリングリスト(mastodon-admin@lists.ffdn.org)で教えてもらったように、日々の定期処理 rake mastodon:daily を docker-compose.yml の中で完結するようにしました。

さらにバージョンアップ毎に書き換える必要があるので、 https://github.com/HiroshiOkada/mastodon.toycode.com で管理するようにしました。

Mastodon サーバーをアップデートしました

mastodon.toycode.com

v1.2 が出ていたので、アップデートしました、途中手間取って1時間くらいかかってしまいました。

作業メモ

$ cd mastodon             # mastodn ディレクトリに移動
$ docker-compose down     # サービスをダウン
$ cd ..                   # バックアップを取るために一つ上のディレクトリに移動
$ sudo chown -R hiroshi:hiroshi mastodon       # 一部のファイルのオーナーが root になっていたのを修正
$ tar cvfz mastodon-before-update.tgz mastodon # バックアップ
$ cd mastodon                      # サイド mastodn ディレクトリに移動      
$ git checkout master              # master をチェックアウト
$ git pull                         # 変更を取り込み
$ git tag                          # タグを確認
$ git checkout toycode             # ローカルなブランチ toycode をチェックアウト
$ git merge v1.2 --no-commit       # v1.2 をマージ (commitは保留)
$ git status                       # 確認

# -- 変更箇所などをざっと確認、今回は問題なさそうなので commit することに --

$ git commit -m 'update to v1.2'   # 変更を commit する
$ docker-compose pull              # 最新版のイメージをプル
$ docker-compose build             # ビルド
$ docker-compose run --rm web rails db:migrate          # データベースのスキームが変わっているので必要
$ docker-compose run --rm web rails assets:precompile   # アセットをプリコンパイル
$ docker-compose up -d             # サービスを立ち上げ
$ docker-compose logs -f           # ログをみて正常に立ち上がっていることを確認
^C

前提条件として、 一つ前の記事 に書いたとおり、 本家を clone したあと toycode というローカルなブランチを切って、設定を書き換え、 フロントの nginx もまとめてdocker-compse で管理しています、

本家以外で参考にしたページ

Mastodon サーバーを立ててみました

ミーハーなので、流行りの Mastodon サーバーを立ててみました。

mastodon.toycode.com

基本的には、以前から自分の勉強用に借りている VPS に docker と docker-compose を入れて設定しただけです。

sslは、自宅サーバー用に *.toycode.com の ワイルド−カード ssl 証明書を取得していたのでそれを使いました。

また、メールサーバーは、契約していたけどあまり使っていなかった、さくらのメールボックスを使うことにしました。

具体的には、git clone しローカルにブランチを切った後、 nginx というディレクトリを作って、サーバー証明書documentation/Production-guide.md at master · tootsuite/documentation を元に以下のように書き換え

--- default.conf.orig    2017-04-16 19:55:26.488591836 +0900
+++ default.conf  2017-04-16 13:19:25.319053418 +0900
@@ -6,14 +6,14 @@
 server {
   listen 80;
   listen [::]:80;
-  server_name example.com;
+  server_name mastodon.toycode.com;
   return 301 https://$host$request_uri;
 }
 
 server {
   listen 443 ssl;
   listen [::]:443 ssl;
-  server_name example.com;
+  server_name mastodon.toycode.com;
 
   ssl_protocols TLSv1.2;
   ssl_ciphers EECDH+AESGCM:EECDH+AES;
@@ -21,8 +21,8 @@
   ssl_prefer_server_ciphers on;
   ssl_session_cache shared:SSL:10m;
 
-  ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
-  ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
+  ssl_certificate     /etc/nginx/server.crt;
+  ssl_certificate_key /etc/nginx/server.key;
 
   keepalive_timeout    70;
   sendfile             on;
@@ -53,7 +53,7 @@
     proxy_set_header Proxy "";
     proxy_pass_header Server;
 
-    proxy_pass http://127.0.0.1:3000;
+    proxy_pass http://web:3000;
     proxy_buffering off;
     proxy_redirect off;
     proxy_http_version 1.1;
@@ -70,7 +70,7 @@
     proxy_set_header X-Forwarded-Proto https;
     proxy_set_header Proxy "";
 
-    proxy_pass http://localhost:4000;
+    proxy_pass http://streaming:4000;
     proxy_buffering off;
     proxy_redirect off;
     proxy_http_version 1.1;
@@ -82,3 +82,4 @@
 
   error_page 500 501 502 503 504 /500.html;
 }
+

Dockerfile を作り

#
FROM nginx:alpine

MAINTAINER Hiroshi Okada <okadahiroshi@miobox.jp>

COPY server.crt server.key /etc/nginx/

COPY default.conf /etc/nginx/conf.d/

EXPOSE 443 80

元の docker-compose.yml を以下のように書き換えて

version: '2'
services:

  nginx:
    build: ./nginx
    image: okadahiroshi/nginx
    depends_on:
      - web
    ports:
      - "80:80"
      - "443:443"

  db:
    restart: always
    image: postgres:alpine
### Uncomment to enable DB persistance
    volumes:
      - ./postgres:/var/lib/postgresql/data

  redis:
    restart: always
    image: redis:alpine
### Uncomment to enable REDIS persistance
    volumes:
      - ./redis:/data

  web:
    restart: always
    build: .
    image: gargron/mastodon
    env_file: .env.production
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    depends_on:
      - db
      - redis
    volumes:
      - ./public/assets:/mastodon/public/assets
      - ./public/system:/mastodon/public/system

  streaming:
    restart: always
    build: .
    image: gargron/mastodon
    env_file: .env.production
    command: npm run start
    depends_on:
      - db
      - redis

  sidekiq:
    restart: always
    build: .
    image: gargron/mastodon
    env_file: .env.production
    command: bundle exec sidekiq -q default -q mailers -q pull -q push
    depends_on:
      - db
      - redis
    volumes:
      - ./public/system:/mastodon/public/system

残りの作業は、 https://github.com/tootsuite/mastodon#running-with-docker-and-docker-compose の通りに作業しました。

あまりむずかしい作業ではありませんでしたが、 VPS が海外サーバーで、さくらのメールに国外IPアドレスフィルタが設定してあったので、 最初メール認証がうまくいなかくて焦りました。

なお、立ち上げたサーバーはしばらく(最低一年程度)は運用するつもりです。今は自由にアカウントを作れる状態にしていますので自由にアカウントを作っていただいて OK ですが、 負荷が多いようだったら、新規のアカウントの作成はできないようにするつもりです。(spam 行為でないかぎり作成済みのアカウントを故意に消すことはないと思います。)

うそつきproxy

Webサイトのテストや開発をしていると時に DNS に登録されている名前以外の名前で Webホストをアクセスしたい事があります。

例えば、家のネットにある 192.168.100.123 という IP アドレスを持ったホストを 本番のホスト名でアクセスしたいなと思う事があります。 (name virtual host を使っている時や、正規の ssl 証明書でテストしたいけれども未だ世界にかけては公開していない場合など)

今までは、家のルーター(NVR500)の簡易 DNS サーバー機能を利用したり、クライアントマシンの hosts ファイルを書き換えていました。 クライアントマシンの hosts ファイルを書き換えるのはできりるだけ避けたいし、 NVR500 のの簡易DNS サーバー機能を使う方法も、汎用性が無い上に設定を元に戻すがめんどくさいので、何か良い方法がないかと思っていました。

そこで思いついたのは、proxy サーバーを経由してアクセスする場合は、名前解決は proxy サーバが行うので、proxy サーバーの、 名前解決の段階で嘘をついてもらうという方法です。

幸い、 docker run 時には --add-host で host→ip マッピングを追加できるので、proxy サーバーの docker イメージさえ用意すれば、 簡単に嘘つき proxy サーバーが準備できます。

早速設定がゆるゆるの docker イメージを作ってみました。 https://hub.docker.com/r/okadahiroshi/tinyproxy/

このイメージを使って例えば、192.160.100.100 という Docker ホスト上で

# docker run -p 8888:8888 --add-host honban.example.com:192.168.100.123 --rm -it okadahiroshi/tinyproxy

とかとやっておいて、web ブラウザや os の proxy 設定で 192.168.100.100:8888 を設定してやれば、 http://honban.example.com/ とか https://honban.example.com/ で 192.168.100.123 というホストをアクセスできます。

幸いにして、GUIでやった場合、proxy の設定は off にしても前の設定は残っているので、webブラウザやOSの pxoxy の設定は一回するだけで、次は ON にするだけで済みます。


おまけ

Linux(Ubuntu)のproxy設定 f:id:OkadaHiroshi:20170109145915p:plain

Windows10のproxy設定 f:id:OkadaHiroshi:20170109145932p:plain

Windows10のproxy設定(LANの設定より) f:id:OkadaHiroshi:20170109145938p:plain

MacOSのproxy設定 f:id:OkadaHiroshi:20170109145942p:plain

Firexfoxのproxy設定 (Firefox はシステムと別に proxy が設定できます。) f:id:OkadaHiroshi:20170109145925p:plain

Android 7.0 の proxy 設定 (Wifiをつなげたまま変えられないかもしれません) f:id:OkadaHiroshi:20170109152347p:plain

iOS 9.3.5 の proxy 設定 f:id:OkadaHiroshi:20170109152352p:plain

Alpine Linux でどのファイルがどの apk に含まれるか調べる Docker イメージを作りました。

小さい Docker イメージを作るためには、 Alpine Linux をベースにすると良いという事なので、 自分で作るイメージだけでなく、他人のイメージも Alpine Linux をベースにしている物が多くなってきました。

ところが、Alpine Linux の apk パッケージは普段使っている Ubuntu, Debian 等のパッケージと違って、 よく使うファイルやコマンドがどのパッケージに入っているかイマイチ分かり難いです。

そこで、車輪の再発明とはなりますが、ファイル名(の一部)を指定して、パッケージを検索する Docker イメージを 作ってみました。

https://hub.docker.com/r/okadahiroshi/apk-files/

使い方は簡単でコマンドラインで、

$ docker run --rm -it okadahiroshi/apk-files 探したいファイル名(の一部)

と入力するだけです。

中の仕組みなど

中の仕組みは簡単で

  1. apk update でキャッシュにapkファイルの一覧が入るのでそれを取り出す。
  2. 一覧のそれぞれに apk fetch で apk ファイルを取得して tar tzf でファイル一覧を取り出す。(取り出したあとは apk ファイルを削除)
  3. docker run 時に grep -F で検索して出力する。

という仕組みです。実際は build 時間を少なくするため、2 は 5スクリプトを並列で走らせています。

なお、手元の環境だと build に一時間くらいかかります。マシンのスペックにあんまり関係ないようです。 dockerhub での build は 25分ほどで終了するので、ネットワーク速度等が律速要因だと思います。