PowerDNS を PostgreSQL バックエンドでインストールして、PowerDNS Admin を動かしたいということで、 順を追って手順を記録していきます。
もくじ
- PostgreSQL をインストールする
- PowerDNS をインストールする
- PowerDNS Admin をインストールする
- h2o + Gunicorn で実行する ← 今回
Gunicorn の設定と実行
WSGI の実装でよく使われているものは uWSGI と Gunicorn があるそうなのですが、PowerDNSAdmin の requirements.txt に Gunicorn が入っていてインストールされているので、そちらを使います。
Gunicorn を経由するため、Flask を 127.0.0.1 にのみ bind するように変更します。 前回作成した standalone.py を production.py にコピーして以下を変更します。
BIND_ADDRESS="127.0.0.1"
また、PowerDNSAdmin に付属の run.py は Gunicorn からの実行に使えないので、それ用の web.py を powerdns-admin ディレクトリ(run.py と同じ)に作成します。
from powerdnsadmin import create_app app = create_app()
/usr/home/pdnsadm/gunicorn_config.py を作成し、次のように Gunicorn の設定を記述します。基本的には自分しか使わないので、workers と threads は控えめに。また、h2o との接続には Unix ソケットを使います。
chdir = "/usr/home/pdnsadm/powerdns-admin" raw_env = [ "FLASK_CONF=/usr/home/pdnsadm/powerdns-admin/configs/production.py", "FLASK_APP=powerdnsadmin/__init__.py", ] bind = "unix:/tmp/pdnsadmin.sock" backlog = 2048 workers = 1 threads = 3 worker_class = "sync" worker_connections = 1000 timeout = 30 keepalive = 2 max_requests = 512 spew = False daemon = False pidfile = None umask = 0 user = "pdnsadm" group = "pdns" tmp_upload_dir = None access_log_format = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"' loglevel = "info"
pdnsadmin のホームディレクトリで以下を実行し、Gunicorn が実行できることを確認します。
$ ./webpy39/bin/gunicorn
/usr/local/etc/rc.d/pdnsadmin
service コマンドから Gunicorn が実行できるように、次のような rc.d ファイルを作成します。
できたら実行権限を chmod 555 pdnsadmin
でつけるのを忘れずに。
sleep 3 をつけたのは、そうしないと restart 時に、シグナルが発行されてから Gunicorn が終了するまでに時間がかかり、その前に start_cmd が実行されてしまって restart がうまくいかないからです。
#!/bin/sh # PROVIDE: pdnsadmin # REQUIRE: DAEMON pdns fluent-bit # KEYWORD: shutdown # # Add the following line to /etc/rc.conf to enable pdnsadmin: # pdnsadmin_enable (bool): Set to "NO" by default. # Set it to "YES" to enable pdnsadmin. # . /etc/rc.subr name=pdnsadmin desc="PowerDNS Admin web UI daemon" rcvar=${name}_enable load_rc_config ${name} command="/usr/home/pdnsadm/webpy39/bin/gunicorn" config="/usr/home/pdnsadm/gunicorn_config.py" pidfile="/var/run/pdnsadmin.pid" command_interpreter="/usr/home/pdnsadm/webpy39/bin/python" start_cmd=start_cmd stop_cmd='pkill -TERM -U pdnsadm -F ${pidfile}; sleep 3' pdnsadmin_enable=${pdnsadmin_enable:-NO} start_cmd() { check_startmsgs && echo "Starting ${name}." daemon -f -u pdnsadm -p ${pidfile} ${command} web:app --config ${config} --log-syslog } run_rc_command $1
h2o の設定と実行
関係ありそうなところはこんな感じです。
hosts: www.example.net: paths: "/": proxy.reverse.url: http://[unix:/tmp/pdnsadmin.sock]/ proxy.preserve-host: ON "/static": file.dir: /usr/home/pdnsadm/powerdns-admin/powerdnsadmin/static
サブディレクトリで実行する
ここまでの設定だと http(s)://www.example.net/ のルートを取られてしまうので、できればサブディレクトリを切ってそこで実行するようにしたいです。http(s)://www.example.net/powerdns/ とか。
変更点は2箇所あって、まず web.py で SCRIPT_NAME を設定します。
import os from powerdnsadmin import create_app os.environ["SCRIPT_NAME"] = "/powerdns" app = create_app()
次に、h2o.conf を次のように変更します。
hosts: www.example.net: paths: "/powerdns/static": file.dir: /usr/home/pdnsadm/powerdns-admin/powerdnsadmin/static "/powerdns": proxy.reverse.url: http://[unix:/tmp/pdnsadmin.sock]/powerdns proxy.preserve-host: ON
これで、http(s)://www.example.net/powerdns/ で PowerDNSAdmin を使えるようになりました。