Jupyterを真っ当にサーバ上で運用しようと思ったので、それ関連の情報を調べる。
OSはCentOS7を利用。せっかくなのでPythonのインストールから手順を残す。
CentOS7ならyumでそれほど面倒なく入れられる。
$ sudo yum install zlib-devel bzip2-devel openssl-devel sqlite-devel readline-devel gcc-gfortran atlas atlas-devel blas blas-devel lapack lapack-devel libpng-devel freetype-devel tk-devel
CentOS7だとEPELでyumから入れられるらしい。
$ sudo yum install epel-release $ sudo yum install python34 python34-devel
pipを入れてnumpyとかscipyとかを入れる。
$ wget https://bootstrap.pypa.io/get-pip.py $ sudo python3.4 get-pip.py $ sudo pip3.4 install numpy scipy scikit-learn pandas ipython jupyter matplotlib
これで概ね必要なものは入った。
まずは普通に立ち上げる。
$ jupyter notebook
これだとローカルからの通信しかできない。
--ipでIPを指定すれば通信はできるようになる。
$ jupyter notebook --ip=0.0.0.0
これだとリモートから任意のPythonコードを実行できる状態なので、自宅のLAN内で使うくらいならまあ良いかもしれないけど、外向けに使うのは危うい。
ローカルからのアクセスだけにしてSocks経由なら安全だと思うし、正直それでいいと思っていたんだ。
$ ssh example-host -D 1082 $ jupyter notebook --port=18888
あとはブラウザのアドオンとかで localhost:18888 をproxy通すようにすれば出来上がり。
けどこれだとhttpで通信されてしまっている点は気になる。
SSLで通信して認証を行うようにしてみる。
やり方は下記資料に載っている。
http://jupyter-notebook.readthedocs.org/en/latest/public_server.html
Jupyterコンソール立ち上げ(iPythonでも可)。
$ jupyter console
下記でパスワードのハッシュを出力される。
from notebook.auth import passwd passwd() #=> sha1:********************************************
SSL通信用の鍵作成。
$ openssl req -x509 -nodes -newkey rsa:2048 -keyout mycert.key -out mycert.pem
jupyter_notebook_config.pyを編集(まだ作成してなければ新規作成)。
$ vi ~/.jupyter/jupyter_notebook_config.py
下記の内容を記述。passwordのところは先ほど表示された内容をコピペ。certfileは上で作ったファイルのパスを指定。ポートは適当に好きな番号を。
c = get_config() c.NotebookApp.certfile = u'/absolute/path/to/your/certificate/mycert.pem' c.NotebookApp.ip = '*' c.NotebookApp.password = u'sha1:********************************************' c.NotebookApp.open_browser = False c.NotebookApp.port = 18888
サーバ起動。これで外部からも接続できてパスワード認証も付く。
$ jupyter notebook --certfile=/home/user/.jupyter/mycert.pem --keyfile /home/user/.jupyter/mycert.key
Jupyterのようなクリティカルなサービスをパスワードだけでガードというのも危険なので、SOCKSなりiptablesなりでガードしておく。
iptablesの場合は、/etc/sysconfig/iptables に下記を追加して、service iptables restartしておく。$your_addressに自身のIPアドレスを、port名は適当。
-A INPUT -p tcp -s $your_address --dport 18888 -j ACCEPT