Okada Hiroshi の blog

typo が多いです

RawGit が終了するそうです。

RawGit という githubgithub gists のファイルを CDN で配布してくれる便利なサービスがあるのですが残念なことに終了するそうです。

rawgit.com

( マルウエアと戦うのに労力を使いたくないそうです、不毛な作業をしたくない気持ちはよく理解できます。)

少し前に書いた 自動リロード - Okada Hiroshi の blog も gist を RawGit 経由で配信していたので、 この際なので github page で配信することにしました。

大したアクセスもないのに RawGit を使っていたのは、gist では .js ファイルのヘッダーが Content-Type: text/plain; charset=utf-8 になってしまうためです、githbub page ではContent-Type: application/javascript; charset=utf-8 と正しくセットされます 。

新しい URL は https://hiroshiokada.github.io/shortcodes/poor-mans-autoreload.js です。

ついでに js の minify もしてみました。 GitHub - HiroshiOkada/shortcodes: A collection of short codes

ロートルなのでタスクランナーではなく Makefile を使っています。

自宅で実行している Jupyter Notebook を外からアクセスしたかったので、リバースプロキシを設定しました

Jupyter Nodebook が便利なので、最近は自宅のデスクトップで立ち上げっぱなしにして、外出先からは ssh protfowarding で接続していました。

けれども、ブラウザだけでアクセスできたほうが便利な事も多いので、nginx の reverse proxy の経由でアクセスできるように設定をしました。

JupyterHub という複数の Jupyter Notebook を reverse proxy 経由で配信する設定の文書は以下にありました。

Using a reverse proxy — JupyterHub 0.9.4 documentation

単一の Jupyter Notebook Server でも大きな違いはないと思いますので、それを参考に僕の環境で必要だった調整加えた設定を以下に記述します。

(以下、 jupXXXX.toycode.com は仮の名前です、実際には少し違う名前で運用しています。)

自宅のネットワーク構成

f:id:OkadaHiroshi:20181010141822p:plain

  • デスクトップ PC (192.168.100.100) の 8888番ポートで Jupyter Notebook を実行しています。
  • 有線ルータの簡易DNS機能で自宅ネットワークの内部では jupXXXX.toycode.com を名前解決すると 192.168.100.200 (HP ProLiant) を返すようになっています。
  • 外部のインターネット上では、*.toycode.comは自宅のグローバルIPに結び付けられているので、jupXXXX.toycode.com を名前解決すると自宅のグローバルIPアドレスが返ってきます。
  • 有線ルータの静的NAT機能で外から来た 443 (https) ポートは Ubuntu 16.04 Server がインストールされている 192.168.100.200 (HP ProLiant) の 443 (https) ポートに届くようになっています。

192.168.100.200 (HP ProLiant) 上で実行している nginx の Dockerfile

nginx は Docker コンテナ上で実行しています。SNI (名前ベースのバーチャルホスト) になっています。

Dockerfile はこんな感じです。

FROM nginx:mainline-alpine

RUN apk update -q && apk add openssl
RUN openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096

RUN rm /etc/nginx/conf.d/*

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

EXPOSE 80 443

nginx.conf

 user  nginx;
 worker_processes  1;

 error_log  /var/log/nginx/error.log warn;
 pid        /var/run/nginx.pid;


 events {
     worker_connections  1024;
 }


 http {
     include       /etc/nginx/mime.types;
     default_type  application/octet-stream;

     log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                       '$status $body_bytes_sent "$http_referer" '
                       '"$http_user_agent" "$http_x_forwarded_for"';

     access_log  /var/log/nginx/access.log  main;

     sendfile    on;

     keepalive_timeout  65;

     gzip  on;

     server {
         listen 80 default_server;
         server_name  _;
         return 444;
     }

     server {
       listen 443 ssl default_server;
       server_name  _;
       ssl_certificate      /etc/nginx/server.crt;
       ssl_certificate_key  /etc/nginx/server.key;
       return 444;
     }

+    map $http_upgrade $connection_upgrade {
+        default upgrade;
+        ''      close;
+    }
+
+    ssl_session_timeout 5m;
+    ssl_session_cache shared:SSL:1m;
+
     include /etc/nginx/conf.d/*.conf;
 }
  • +が元の nginx:mainline-alpine の nginx.conf に追記した部分です。
  • Using a reverse proxy — JupyterHub 0.9.4 documentation に記述してあった内容を一部 http セクションに移動しました。
  • 特に ssl_session_cache shared:SSL: はバーチャルホスト間で共用するので server セクションではなくてここに書くべきだと思います。
  • 有効期間等は、自分一人で使うので負荷も大したことはないし、間違えた場合にキャッシュ等が長時間残ってしまうのを避けるため短めに設定しまました。

conf.d/jupXXXX.conf

server {
    listen 80;
    server_name jupXXXX.toycode.com;

    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl;

    server_name jupXXXX.toycode.com;

    charset UTF-8;

    ssl_certificate /etc/nginx/server.crt;
    ssl_certificate_key /etc/nginx/server.key;

    ssl_protocols TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_dhparam /etc/ssl/certs/dhparam.pem;
    ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';

    add_header Strict-Transport-Security max-age=3600;

    location / {
        proxy_http_version 1.1;

        proxy_pass http://192.168.100.100:8888;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_read_timeout 300;

        # websocket headers
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }

}
  • return 301 https://$server_name$request_uri; http は恒久的に使う予定がないので 302 ではなくて 301 にしました。
  • listen 443 ssl; nginx公式サイトのngx_http_ssl_module によると ssl on; という書き方は obsolete だそうです。
  • ssl_protocols TLSv1.2; 僕の使っているブラウザは全て TLSv1.2 をサポートしているので TLSv1.1 等は記述しませんでした。
  • proxy_http_version 1.1; 必要なので追加しました。
  • ssl_stapling の設定は resolver の設定が必要で、僕の場合は LAN 内では外側とは別なIPアドレスを返しているので削除しました。
  • ここでも有効期間等を短めに設定しています。
  • ssl の証明書は以前の記事 で取得したワイルドカード証明書を利用しています。

結論

いまの所、これで上手く動いています。正直いって暗号のアルゴリズム ssl_ciphers についてはコピペしただけので自信がありません。

(SSL Server Test は一応 A になりました。)

中間証明書の連結

8月29日に購入したワイルドカード証明書ですが、僕が普段使っている環境では問題がなかったのですが、一部の環境※1では中間証明書がインストールされていないようなので、中間証明書を連結しました。

www.ssl2buy.com

上記のページの New AlphaSSL / Wildcard Intermediate certificateAlphaSSL Root CA certificateintermediate.crtroot.crt という名前で保存して。

$ mv toycode.crt toycode1.crt
$ cat toycode1.crt intermediate.crt root.crt > toycode.crt

で連結した証明書ファイルを作成しました。

※1 python やそれを使っている aws ツール

自動リロード

静的なサイトでも開発中には自動リロードして欲しいこともあるので、自動リロードするスクリプトを書いてみました。

poor man's autoreload

以下のスニペットを HTML 文書の head や body の内側に挿入すると 800ミリ秒ごとにHTML文書を(内部的に読み込んで)変化があったらリロードします。

<script src="https://cdn.rawgit.com/HiroshiOkada/6344f094955f3fc31deeffeec2718ff6/raw/4578f0948fa86cff08302a43aea1d913798ce23f/poor-mans-autoreload.js"></script>

追記

10分間変化がなかったらチェックを停止するようにしました。

追記 (2018-10-14)

使っていた RawGit というサービスが終了するので、gist でなく github page を使うことにしました。上記の代わりに以下を使ってください。

 <script src="https://hiroshiokada.github.io/shortcodes/poor-mans-autoreload.js"></script>

RawGit が終了するそうです。 - Okada Hiroshi の blog

GoogleニュースのRSS URL 組み立て

一時期 RSS リーダから遠ざかっていたのですが。最近また Miniflux という RSS インストールして使っています。

Google ニュースRSS 経由で 読みたいので、RSS フィードの URL を生成する簡単な Webアプリを CodePen で書いてみした。

入力欄にキーワードを(空白区切りで)いれて作成ボタンを押してください。

ちなみに URL の仕様は下記の記事を参考にしました。

www.yoshiteru.net

anond.hatelabo.jp

Google スプレッドシートにテキストを貼りつける

Google スプレッドシートにタブやカンマ区切りのテキストを貼り付けるると、貼りつけた直後は列が一つになってしまいます。 けれども貼付け後、テキストを列に分割を選択すると、期待したとおりに列に分割されます。

こういうのは知っている人にとっては当たり前なのでしょうが、僕は今日初めて知ったので書いてみました。

f:id:OkadaHiroshi:20180831162721g:plain

参考: セルのテキストを複数の列に分割する - パソコン - ドキュメント エディタ ヘルプ