Ubuntuで oTree を動かす
Linuxマシンを用意する
以下のいずれかの方法で.
- 実機を使う場合,isoファイルを公式WebページからダウンロードしてUSBメモリに(ブータブルな形式で)コピーし,それを使ってインストール.
- VPS(ConoHa)やIaaS(Amazon EC2)を契約してインスタンスを作成.
- Ubuntuの仮想環境の構築
Linux(Ubuntu)をインストールした後にやっておくこと
以下は備忘録.一度も以下のような作業を経験したことがなければ,より詳しい文献に当たるべし.
ユーザーの作成
- 作業用のユーザー(たとえば
lab)を作成する.sudo adduser lab - sudo権限を付与する.
sudo usermod -aG sudo lab
- 作業用のユーザー(たとえば
SSHの設定
- SSH公開鍵認証で接続できるように準備する.
- (Ubuntuサーバー上ではなく)ローカルのPCで鍵を作成する.
ssh-keygen -t ed25519 - 生成した秘密鍵(たとえば
id_ed25519)の権限を600にする.chmod 600 id_ed25519 - 生成した公開鍵(
*.pub,たとえばid_ed25519.pub)を,Ubuntuサーバーに転送する.*.pubファイルを何らかの方法で(実機があればUSBメモリを使う,すでにSSH接続できるのであればscpコマンドを使うなどして)Ubuntuサーバーの自分のホームディレクトリかどこかに転送しておく.- ホームディレクトリの中に
.sshディレクトリを(無ければ)作成. .sshディレクトリにauthorized_keysなるテキストファイルを作成し,そこに公開鍵の中身を書く.authorized_keysファイルが存在していなければ,*.pubファイルをauthorized_keysにリネームしてしまう.mv id_ed25519.pub authorized_keysauthorized_keysファイルが存在していれば,追記する.cat id_ed25519.pub >> authorized_keys rm id_ed25519.pub
authorized_keysの権限は600にする.chmod 600 authorized_keys
- (Ubuntuサーバー上ではなく)ローカルのPCで鍵を作成する.
/etc/ssh/sshd_configを編集する.sudo vim /etc/ssh/sshd_config- SSH用のポートをデフォルト(
22)から変更する.Port 2222- 「
Port 22」と書かれている行はコメントアウトしておく.
- 「
- SSHでrootにログインできないようにする.
PermitRootLogin no - パスワードでログインできないようにする.
PasswordAuthentication no - 公開鍵でログインできるようにする.
PubkeyAuthentication yes
- SSH用のポートをデフォルト(
- 諸々の設定の終了後,シェルから出たりマシンを再起動したりする前に,SSHでアクセスできるかどうか確認しておく.SSHの設定が間違っているとアクセスできなくなってしまう.
- アドレスが
133.1.112.999, ユーザー名がlab, ポート番号が2222, 秘密鍵が~/.ssh/id_ed25519の場合,以下のコマンドでログインできる.ssh -i ~/.ssh/id_ed25519 -p 2222 lab@133.1.112.999
- アドレスが
- SSH公開鍵認証で接続できるように準備する.
ファイアウォールの設定
- ufwを起動する.
sudo ufw enable - すべてのポートを閉じる(
denyにする... デフォルトの設定rejectでも良いけど).sudo ufw default deny - SSHのデフォルトのポート番号(
22)を削除する.
またはsudo ufw delete allow 22sudo ufw delete allow "OpenSSH" - 自分で設定したSSHのポート番号(たとえば
2222)を許可する.sudo ufw allow 2222 - oTree 用のポート番号(たとえば
8000)を許可しておいても良い.sudo ufw allow 8000 - 設定が終わったら反映させる.
sudo ufw reload - 諸々の設定の終了後,シェルから出たりマシンを再起動したりする前に,SSHでアクセスできるかどうか確認しておく.ファイアウォールの設定が間違っているとアクセスできなくなってしまう.
- ufwを起動する.
Python を pyenv (+ virtualenv) で導入
- UbuntuはシステムにデフォルトでPythonが入っているので,それを使っても良いが,おすすめしない.
- Pythonを導入するのに pyenv + virtualenv を必ず使わなければならないわけではない.
- Pythonを(直接入れるのではなく)pyenvを使って入れるメリット:
- pythonのバージョンをすぐに切り替えられる( oTree 3 はPython3.8まででしか動かない).
- ホームディレクトリにPythonを入れるので,システムのデフォルトのPythonに干渉しない.
- virtualenvを使うメリット:
- oTree 専用(あるいは特定のプロジェクト専用)の環境を構築できる(Pythonのパッケージをいろいろ入れるとわけが分からなくなる).
- pyenv自体はPythonのバージョンの切り替えをするもの.virtualenvは同一バージョンで複数の環境を構築できる.
- Pythonを(直接入れるのではなく)pyenvを使って入れるメリット:
- Pythonのビルド環境(build-essential等)をaptでインストール
https://github.com/pyenv/pyenv/wikisudo apt-get update sudo apt-get install make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev - pyenvを導入
https://github.com/pyenv/pyenvgit clone https://github.com/pyenv/pyenv.git ~/.pyenv cd ~/.pyenv && src/configure && make -C src echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc echo 'eval "$(pyenv init -)"' >> ~/.bashrc echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.profile echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.profile echo 'eval "$(pyenv init -)"' >> ~/.profile- 導入が終わったら,いったんシェルを開き直す.
- pyenvのプラグインpyenv-virtualenvを導入
https://github.com/pyenv/pyenv-virtualenvgit clone https://github.com/pyenv/pyenv-virtualenv.git $(pyenv root)/plugins/pyenv-virtualenv echo 'eval "$(pyenv virtualenv-init -)"' >> ~/.bashrc- 導入が終わったら,いったんシェルを開き直す.
- pyenvでPythonをインストール
pyenv install 3.9.11 - pyenv-virtualenvでoTree専用の環境(myotree5と名付ける)を作成
pyenv virtualenv 3.9.11 myotree5 - 用意した環境myotree5を使うように切り替える
pyenv global myotree5python -Vでインストールしたバージョン(3.9.11)が表示されたら,ちゃんと設定できている.
pipで oTree のインストール
- (PostgreSQLが必要な場合)パッケージpsycopg2を入れるために必要なライブラリlibpq-devをインストール
https://www.psycopg.org/docs/sudo apt-get install libpq-dev - pipで oTree (とpsycopg2)をインストール
pip install otree psycopg2- パッケージのバージョンを特定する場合は
otree==5.8.1などとする. which otreeでパスが表示されたら,ちゃんとインストールできている.- 何か必要なものが入っていないと,あるいは依存関係の問題で,psycopg2のインストールは失敗するかも.
- 根気強くエラーを読んで,検索して,必要なものを入れてから再チャレンジ.
- psycopg2のバージョンを少し古いものに固定してみる.
- PostgreSQLを使う予定がない場合にはpsycopg2は入れる必要なし.とりあえず諦める.
- パッケージのバージョンを特定する場合は
- oTree を動かしてみる
- まずはシェルでoTreeのバージョンを確認.
otree --version - 試しに新規プロジェクトの作成(たとえば新規プロジェクトの名前を
my_oTreeとする).otree startproject my_oTree- とりあえずサンプルゲームも入れる(「Include sample games?」聞かれたら
yと答える).
- とりあえずサンプルゲームも入れる(「Include sample games?」聞かれたら
my_oTreeなるディレクトリが作成されるので,その中に入る.# my_oTree に入る cd my_oTree # my_oTreeの中身を確認する ls -la- oTreeがサーバーとして動くのか確認.
otree prodserver- ブラウザで
http://localhost:8000にアクセスできるか?- WSL2上で動かしている場合はlocalhostでアクセスできるはず.
(何となれば... https://docs.microsoft.com/ja-jp/windows/wsl/networking#accessing-linux-networking-apps-from-windows-localhost) - Vagrantで入れたUbuntuや,遠隔地のサーバー(SSHで接続中)で動かしている場合は,localhostではなく動かしているサーバーのIPアドレスを陽に指定してアクセスしてみる.
- WSL2上で動かしている場合はlocalhostでアクセスできるはず.
- ブラウザで
- まずはシェルでoTreeのバージョンを確認.
本番としてoTreeを動かすために必要なこと
データベースサーバーソフトウェアの PostgreSQL を導入
- oTree公式はPostgreSQLを使うことを推奨
- PostgreSQLを使わない場合,SQLite3を使う.
- SQLite3でもパフォーマンスは悪くない?(要検証)
- Herokuでの動作環境を再現するにはPostgreSQLを使う(HerokuはPostgreSQL必須).
Redis は不要
- oTreeの以前のバージョンではRedisの導入が必須だったが,v3.3.4以降(しれっと)不要になった.
環境変数の設定
(Bashを使っている場合は).bashrcに環境変数を設定.
# oTree実験者画面へのパスワードをたとえば000999にしてみる.本当はもっと複雑なものにする. # ユーザー名のデフォルトは admin export OTREE_ADMIN_PASSWORD=000999 # OTREE_AUTH_LEVEL=STUDY とするとパスワード保護が有効になる. # パスワードをOTREE_ADMIN_PASSWORDで設定していないのにOTREE_AUTH_LEVEL=STUDYとするとログインできなくなる. export OTREE_AUTH_LEVEL=STUDY # OTREE_PRODUCTIONが未定義であったり値が0であったりするとDEBUGモードになり,デバッグ用の情報が表示される. # OTREE_PRODUCTION=1 とすることでデバッグ用の情報を非表示にする. export OTREE_PRODUCTION=1 # PostgreSQL が設定済みであれば, # データベースにアクセスするロール名(たとえばuser01) # パスワード(たとえば0099) # アドレス(oTreeと同じマシンで動かす場合はlocalhost) # データベース名(たとえばotreedb) # を oTree に環境変数DATABASE_URLで教える. export DATABASE_URL=postgres://user01:0099@localhost/otreedb # DATABASE_URLを設定しなければ oTree はSQLiteを使う.- Vim(vi)を使って.bashrcを編集できるようにしておいた方が良い.nanoでも良いが.
- PostgreSQLのURL(
DATABASE_URL)にパスワード(例では0099)を書いても良い.そのときはPostgreSQLのパスワードファイル.pgpassが不要. - oTree の公式ドキュメントでは言及されていないが,settings.pyの
SECRET_KEYも環境変数から受け取るように変えた方が良い気がする.
インターネット(LAN外)からアクセスできるようにする
- oTreeが動いているマシンにグローバルIPアドレスが割り当てられていて,oTreeのポート(8000)がインターネットに開放されていれば,特別な設定をしなくてもインターネットからoTreeにアクセスできる.
しかし,そのような状況は稀である.
- 何も設定していないのにインターネットから接続できてしまっている場合は逆に改めたほうが良い.
WSL2のUbuntuを使っている場合は設定が難しそうなので,ここでは諦める.
- LAN内でアクセスできるようにするだけでもポートフォワーディングの設定が必要.
参考: https://otreecb.netlify.app/reference/ubuntu_server_setup.html#step-3-install-nginx
グローバルIPアドレスの確保
- インターネットからアクセスするためには固定されたグローバルIPアドレスが必要.
- 自宅サーバーで固定されたグローバルIPアドレスが無い場合はDDNSを契約する.
- 学内サーバーの場合は担当者(計算機室,情報基盤センター的な部局の窓口)にお願いする.
- グローバルIPアドレスが割り当てられているマシンの下にLANがあり(要するに,LANのゲートウェイにグローバルIPアドレスが割り当てられている),そのLAN内のマシンを oTree のサーバーにする場合は,ポートフォワーディングの設定が必要.
ドメインの取得
- HTTPS通信をするためにはSSL証明書が必要.SSL証明書を発行するためにはドメインが必要.
- 学内サーバーの場合は担当者(計算機室,情報基盤センター的な部局の窓口)にお願いする.
- Amazon EC2 を使う場合,Amazon Route 53 でドメインを取得すると良い.
- ドメインを取得後,DNSにグローバルIPアドレスとドメインの対応関係を登録する.
- 以下では
myotree.iser.osaka-u.ac.jpなる(サブ)ドメインを取得したとする.
Nginx の設定
- Nginx とは Webサーバーアプリケーション.「エンジンエックス」と読む.「エヌジンクス」と読むとバカにされる.
- そもそも oTree には Webサーバーの機能が含まれているものの,HTTP通信しかできない.
- Nginx をリバースプロキシとして使い, oTree サーバーとクライアント(ブラウザ)がHTTPS通信できるようにする.
- インターネットから oTree サーバーが動いているマシンまでのHTTPS通信を,一旦 Nginx が受け取り,それを oTree に(
localhost:8000に)渡す.
- インターネットから oTree サーバーが動いているマシンまでのHTTPS通信を,一旦 Nginx が受け取り,それを oTree に(
Nginx のインストール
sudo apt install nginxNginx が自動起動するように設定
sudo systemctl enable nginxNginx の通信のポートを開放する.
sudo ufw allow 'Nginx Full' sudo ufw reloadNginx のデフォルトの設定を削除する.
sudo unlink /etc/nginx/sites-enabled/default- シンボリックリンクを削除しているだけで,設定ファイル自体は
/etc/nginx/sites-available/defaultに残っているので安心して良い.
- シンボリックリンクを削除しているだけで,設定ファイル自体は
Nginx の設定ファイルを作成する.
sudo vim /etc/nginx/sites-available/otree-reverse-proxy.conf内容は以下.コピペすれば良い.
map $http_upgrade $connection_upgrade { default upgrade; '' close; } server { access_log /var/log/nginx/otree-reverse-access.log; error_log /var/log/nginx/otree-reverse-error.log; ## 取得したドメインを設定する. server_name myotree.iser.osaka-u.ac.jp; location / { proxy_buffering off; proxy_pass http://localhost:8000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_set_header HOST $host; proxy_set_header X-Real-Ip $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $server_name; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Port $server_port; } }作成した設定ファイルをアクティブにする(
/etc/nginx/sites-enabledディレクトリにシンボリックリンクを張る).sudo ln -s /etc/nginx/sites-available/otree-reverse-proxy.conf /etc/nginx/sites-enabled/otree-reverse-proxy.conf作成した設定ファイルを反映させる. まず作成した設定ファイルに問題がないかテストする.
sudo nginx -t問題がなければ Nginx を再起動して設定を反映させる.
sudo systemctl restart nginx
SSL の設定
- HTTPS通信のためにSSL証明書を取得する.
- Let's Encrypt を使って,無料のTLS/SSL証明書を取得する.
Cerbotのインストール
sudo apt install certbot python3-certbot-nginxSSL証明書の取得
sudo certbot --nginx -d myotree.iser.osaka-u.ac.jp- コマンド実行後,同意を求められたら同意する(
Aを入力してEnter). - メールアドレスを聞いてもよいか質問されたらNoを返す(
Nを入力してEnter)で良い. - "Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access." が出たら Redirect を選ぶ(
2を入力してEnter).- 自動的に 先ほど作成した Nginx の設定ファイルを良きに計らって書き換えてくれる.
- コマンド実行後,同意を求められたら同意する(
Nginx を再起動して設定を反映させる.
sudo systemctl restart nginxLet’s Encryptの証明書の有効期限は90日間.期限が残り30日になったタイミングでcertbotは自動的に証明書を更新してくれる.特に設定は必要ないが,念の為,改めて自動更新を有効にしておく.
sudo systemctl enable certbot.timer
oTree の起動
- Nginxの設定が終わったら,通常通り, oTree のプロジェクトディレクトリに移動して, oTree を起動する.
otree prodserver 8000 - ブラウザで
https://myotree.iser.osaka-u.ac.jpにアクセスして,いつもの oTree の画面が表示されれば成功.- Chrome であれば,アドレスバーの左側に南京錠のアイコンが表示されていれば正しくHTTPS通信ができている.
- SSH接続していて oTree を
otree prodserverコマンドで起動している場合,SSH接続が切断してしまうと oTree も終了してしまう.これを防ぐために,nohupコマンドで oTree をバックグラウンドで実行する.nohup otree prodserver 8000 &- 終了するときには
psコマンドで oTree のプロセスID(PID)を探し,killコマンドで終了させる.
- 終了するときには
- MTurkでの実験など,一定期間 oTree を起動したままほったらかしにする場合には,より高度なプロセス管理が必要.
- SupervisorやCircusを使うのが良い,らしい.