Okada Hiroshi の blog

typo が多いです

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

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

https://mastodon.toycode.com/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 サーバーをアップデートしました

https://mastodon.toycode.com/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 サーバーを立ててみました。

https://mastodon.toycode.com/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分ほどで終了するので、ネットワーク速度等が律速要因だと思います。

System76 の ノートパソコンを買いました

最近は外出時は Chromebook を常用していたした。 そこそこ使えていたのですが重いページで固まりやすかったり細かいところが不満だったので以前から注目していた System76 https://system76.com/Ubuntu プリインスールのノートパソコンを注文して購入しました。 今は円安で輸入にはあまり良い時期ではなかったのですが...

f:id:OkadaHiroshi:20161228183418j:plain

f:id:OkadaHiroshi:20161228183134p:plain

スペックは上記の通りで、あまり大したものではないのですが、買って大正解で、いつも家ではデスクトップ PC に Ubuntu をインストールして使っているのですが、ノートPCでも同じ環境が使えてとても快適です。

( Windows マシンはもちろん Mac OS X でも、例えば inotifywait と同等のコマンドって何だったかな? などと一々調べなくてはならなく二度手間でストレスを感じていました。 )

またこれでようやく、喫茶店等で使っているのを自由ソフトウエア主義者の人たちに見られて軽蔑されるのではという不安から解消されます :-)

注文したのが 12月14日で、届いたのが 12月25日なので 11日ほどかかりました。

途中、クレジットカードの請求書に届いた5桁の文字を入力しないと注文処理が進まない部分があり、幸い反映の早いカードだったので OK でしたが、そうでないカードの時は注意が必要かもしれません。

f:id:OkadaHiroshi:20161228190106p:plain


f:id:OkadaHiroshi:20161228191440j:plain

f:id:OkadaHiroshi:20161228191513j:plain:w200:right ACアダプタは比較的小型の一般的なもので、それは良かったんですが残念ながらプラグがアースがあるタイプのものでした、たまたま変換プラグを持っていたので今はそれで凌いでいます。

f:id:OkadaHiroshi:20161228193133j:plain

残念ながら BIOS は自由なソフトウエアではありません、やっぱり自由ソフトウエア主義者の人たちには怒られるかも。

INotifyPropertyChanged の実装が面倒くさい (Google Apps Script を使ってスニペットを生成したけどそれでも面倒くさい)

久しぶりに Windows アプリケーションを C# で書いているのですが、INotifyPropertyChanged の実装が非常に面倒くさいです。正直言って非人間的だと思います。

仕方がないので、Google Apps Script でコードの断片を自動生成することにしました。

具体的な方法としては

(1) Google スプレッドシートを開いて、さらにスクリプトエディタを開いて以下のスクリプトを作成しました。

gistd911b45aa32a99e5c0be

(2) スプレッドシートを閉じて開いて、以下のように f:id:OkadaHiroshi:20160314175648p:plain のように入力しました。

(3) メニューからスニペット作成→INotifyPropertyChangedスニペットを実行し、以下のような文書が作成されるのでこれをコピーしてプログラムにペーストしました。

        private int testOne = 0;
        private string testTwo = "";

       /// <summary>テスト1</summary>
        public int TestOne        {
            get { return testOne; }
            set
            {
                if (value != testOne) {
                    testOne = value;
               }
               NotifyPropertyChanged("TestOne");
            }
        }


        public string TestTwo        {
            get { return testTwo; }
            set
            {
                if (value != testTwo) {
                    testTwo = value;
               }
               NotifyPropertyChanged("TestTwo");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

面倒臭さが 100 から 50 くらいには減りましたが、いちいちコピペするのは全くイケていません。外部ライブラリ等を導入するのも躊躇するしみんなどうしているのだろう。