Okada Hiroshi の blog

typo が多いです

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 くらいには減りましたが、いちいちコピペするのは全くイケていません。外部ライブラリ等を導入するのも躊躇するしみんなどうしているのだろう。

Android Javaでやっぱりフィールドにmまたは_をつけるべきではないのか。

少し前に、

gfx.hatenablog.com

という記事があって、その時は自分もブックマークで「新規に書く場合はそうすべきだと思う」とか言っていたのだけれども。最近ちょっと意見が変わりました。

m 又は _ をつけた方が良い理由は以下のとおりです。

  • 確かに IDE では、フィールドとローカル変数や、パラメータと区別がつくけどコードは必ずしも IDE 上でだけ見るわけではない。コマンドラインで git --diff することもあるし、ブログに引用されるかもしれない*1。コードのポータビリティー(どの環境でもそれなりにわかりやすくする)はそれなりに確保すべき。

  • フィールドと引数は往々にしてかぶる。その場合、 typo に弱くなる。例えば

class Product {
    private static final double RATE = 0.8;
    private int price = 1;

    public void setPrice(int price) {
        if (price >= 100) {
           this.price = (int)( RATE * (price - 100) + 100);
        } else {
           this.price = price;
        }
    }

を間違えて

class Product {
    private static final double RATE = 0.8;
    private int price = 1;

    public void setPrice(int plice) { // r と l を typo
        if (price >= 100) {
           this.price = (int)( RATE * (price - 100) + 100);
        } else {
           this.price = plice; // r と l を typo
        }
    }

としてしまった場合、間違いをみつけることが非常にむずかしくなる。

  • そもそも型についてのハンガリアン記法とちがって、無限に種類が増えるものではない、m がメンバー変数であるのは十分に java 文化圏では認知されている。

以上です。

*1:そしてそのブログの読者は色弱かもしれない

Haskell 勉強記録 35 日目

すごいHaskellたのしく学ぼう!

すごいHaskellたのしく学ぼう!

今日は、第13章:モナドがいっぱい の途中(位置6700) まで読み進めました。

今日のまとめ(復習の部分が多いです)

  • Functor 関数を文脈付きの値に適用して、文脈付きの値を得るための typeclass
    (*2) fmap Just 3
  • Applicative 文脈付きの関数を文脈付きの値に適用して、文脈付きの値を得るための typeclass
    Just (*2) <*> Just 3
    (*) <$> Just 2 <*> Just 3
  • Monad 普通の値を取るって文脈付きの値を返す関数を文脈付きの値に適用して、文脈付きの値えるための typeclass
    Just 3 >>= \x -> Just (x * 2)