uWSGI
uWSGI は高速で自己回復機能のある、開発者とシステム管理人に優しいアプリケーションコンテナサーバーです。C だけで書かれています。
目次
インストール
公式リポジトリの uwsgi パッケージをインストールしてください。パッケージをコンパクトにするために、プラグインは付属していません。外部プラグインは別にインストールする必要があります。C で書かれているためとても効率的なソフトウェアです。gunicorn など Python で書かれた代替も存在しますが、どうしても動作は遅くなってしまいます。
サービスの起動
スタートアップ時にデフォルトで uwsgi サービスを有効にするには、次を実行:
# systemctl enable uwsgi@helloworld
これで /etc/uwsgi/helloworld.ini
設定されたアプリケーションのサービスが有効になります。また、以下のコマンドを使ってソケットインターフェイスで有効にすることも可能です:
# systemctl enable uwsgi@helloworld.socket
もしくは、Emperor モード サービスを実行することができます。このモードを使うと uwsgi インスタンスで (emperor と呼ばれる) メインスーパーバイザーを使って様々なアプリ (vassal と呼ばれます) が動くようになります。有効にするには、次を入力:
# systemctl enable emperor.uwsgi
ソケットを使うこともできます:
# systemctl enable emperor.uwsgi.socket
Emperor の設定は /etc/uwsgi/emperor.ini
にあります。
設定
uWSGI によって提供される ウェブアプリケーション は、/etc/uwsgi/
で設定されており、それぞれに独自の構成ファイル (ini 形式) が必要です。詳細については、uWSGI ドキュメント をご覧ください。
あるいは、エンペラーモード (/etc/uwsgi/emperor.ini
で設定) して uWSGI を実行することもできます。これにより、単一の uWSGI インスタンスが、単一のメインスーパーバイザー (エンペラーと呼ばれる) を使用して、一連の異なるアプリ (家臣と呼ばれる) を実行できるようになります。
Web アプリケーション
uWSGI はさまざまな言語をサポートしているため、多くの Web アプリケーションもサポートしています。
例として、設定ファイル /etc/uwsgi/example.ini
と、Web アプリケーションに必要なプラグインが事前にインストールされていることを前提としています。
Python
以下は、Python アプリケーションの簡単な例です。
/etc/uwsgi/example.ini
[uwsgi] chdir = /srv/http/example module = example plugins = python
たとえば、次の構文を使用して uWSGI を個別に実行することもできます。
$ uwsgi --socket 127.0.0.1:3031 --plugin python2 --wsgi-file ~/foo.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191 --uid --gid
このコマンドを root として実行することは避けてください。
PHP
以下は、PHP ベースの Web サイトの簡単な例です。
/etc/uwsgi/example.ini
[uwsgi] ; maximum number of worker processes processes = 4 ; the user and group id of the process once it’s started uid = http gid = http socket = /run/uwsgi/%n.sock master = true chdir = /srv/http/%n ; php plugins = php ; jail our php environment php-docroot = /srv/http/%n php-index = index.php ; clear environment on exit vacuum = true
Web サーバー
uWSGI は、アクセスの転送をサポートする多くの Web サーバーのバックエンドとして使用できます。以下に構成例を示します。
Nginx
nginx は、Web アプリケーションに応じて、UNIX ソケットまたはポート (ローカルホストまたはリモートマシン上) にアクセスをリダイレクトできます。
/etc/nginx/example.conf
# ... # forward all access to / towards location / { root /usr/share/nginx/html; index index.html index.htm; include uwsgi_params; # this is the correct uwsgi_modifier1 parameter for a php based application uwsgi_modifier1 14; # uncomment the following if you want to use the unix socket instead # uwsgi_pass unix:/var/run/uwsgi/example.sock; # access is redirected to localhost:3031 uwsgi_pass 127.0.0.1:3031; } # ...
Nginx (chroot 内)
まず、アプリケーションを指す ini ファイルを作成します。
/etc/uwsgi/application1.ini
[uwsgi] chroot = /srv/http chdir = /www/application1 wsgi-file = application1.py plugins = python socket = /run/application1.sock uid = http gid = http threads = 2 stats = 127.0.0.1:9191 vacuum = true
上記の設定では /srv/http
に chroot しているため、次のような UNIX ソケットが作成されます /srv/http/run/application1.sock
サービスファイル内で通知を無効にする必要があります。
/etc/systemd/system/multi-user.target.wants/uwsgi\@application1.service
[Unit] Description=uWSGI service unit After=syslog.target [Service] PIDFile=/run/%I.pid RemainAfterExit=yes ExecStart=/usr/bin/uwsgi --ini /etc/uwsgi/%I.ini ExecReload=/bin/kill -HUP $MAINPID ExecStop=/bin/kill -INT $MAINPID Restart=always StandardError=syslog KillSignal=SIGQUIT [Install] WantedBy=multi-user.target
変更後は必ず 再起動 を行って、新しいユニットまたは変更されたユニットを組み込んでください。
その後、uwsgi@application1.service
を 有効化 および 起動 して下さい。
/srv/http/etc/nginx/nginx.conf
を編集し、その中に少なくとも以下を含む新しい server
セクションを追加します。
/srv/http/etc/nginx/nginx.conf
... server { listen 80; server_name 127.0.0.1; location / { root /www/application1; include uwsgi_params; uwsgi_pass unix:/run/application1.sock; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } } ...
application1
が 127.0.0.1
で提供されるように、nginx.service
を 再起動 してください。
uWSGI の実行
Web アプリケーションを (オンデマンドでアクティブ化せずに) 常に使用する予定がある場合は、単に 起動 および 有効化 uwsgi@example
を実行できます。
Web アプリケーションをオンデマンドで開始する予定の場合は、起動 および 有効化 uwsgi@example.socket
を実行できます。
エンペラーモードを使用するには、emperor.uwsgi.service
を 起動 および 有効化 します。
このモードのソケットアクティベーションを使用するには、emperor.uwsgi.socket
を 起動 および 有効化 します。
ヒントとテクニック
uWSGI が提供する一部の機能は、公式リポジトリ で提供される systemd サービスファイルを使用してアクセスすることはできません。 これらの変更点については、次のセクションで説明します。詳細については、[2] を参照してください。
ソケットのアクティブ化
ソケットアクティベーションを使用して、次のことを行います。
- Web サーバーを unix ソケットに誘導し、アプリケーションを実行している uWSGI インスタンスを起動します。
- アイドリング時間が経過すると、uWSGI によってアプリケーションがクローズされます。
- アプリケーションがアクセスされた後、ウェブサーバが再びアプリケーションを起動できるようにしたい。
uWSGI には、インスタンスにアプリケーションを閉じるための設定が用意されています。
/etc/uwsgi/example.ini
[uwsgi] # ... # set idle time in seconds idle = 600 # kill the application after idle time was reached die-on-idle = true # ...
しかし、現在の uwsgi@.service
ファイルはこれを許さない。なぜなら、systemd はゼロ以外の終了コードを失敗として扱い、それによってユニットを失敗としてマークするからであり、さらに Restart=always
ディレクティブはアイドル時間後に終了することを無意味にしてしまうからです。
これを修正するには、終了コードを追加します。終了コードは、アプリケーションを単独で閉じた後に uWSGI がリストに提供する可能性があり、systemd が SuccessExitStatus
ディレクティブを使用して成功として処理します (詳細については、[3] を参照)
/etc/systemd/system/uwsgi-socket@.service
[Unit] Description=uWSGI service unit After=syslog.target [Service] ExecStart=/usr/bin/uwsgi --ini /etc/uwsgi/%I.ini ExecReload=/bin/kill -HUP $MAINPID ExecStop=/bin/kill -INT $MAINPID Type=notify SuccessExitStatus=15 17 29 30 StandardError=syslog NotifyAccess=all KillSignal=SIGQUIT [Install] WantedBy=multi-user.target
これにより、アイドル後の Kill 機能を使用してソケットを適切にアクティブ化できるようになります。
uWSGI サービスの強化
Web アプリケーションは実際に公開されており、その品質と基礎となる言語のセキュリティに応じて、実行するのが他のアプリケーションよりも危険なものもあります。 安全でない可能性のある Web アプリケーションへの対処を始める良い方法は、それらを刑務所に入れることです。 systemd には、使用できる機能がいくつかあります。 次の例を見てください (詳細については、systemd.exec(5) および [4] を参照してください。)
/etc/systemd/system/uwsgi-secure@.service
[Unit] Description=uWSGI service unit After=syslog.target [Service] ExecStart=/usr/bin/uwsgi --ini /etc/uwsgi/%I.ini ExecReload=/bin/kill -HUP $MAINPID ExecStop=/bin/kill -INT $MAINPID Type=notify SuccessExitStatus=15 17 29 30 StandardError=syslog NotifyAccess=all KillSignal=SIGQUIT PrivateDevices=yes PrivateTmp=yes ProtectSystem=full ReadWritePaths=/etc/webapps /var/lib/ ProtectHome=yes NoNewPrivileges=yes [Install] WantedBy=multi-user.target
uWSGI ソケットのアクセシビリティ
uwsgi のデフォルト (アプリケーションごと) ソケットユニット (uwsgi@.socket
) では、システム上のすべてのユーザーに読み取りおよび書き込みアクセスが許可されます。
ただし、systemd では、より細かく粒度の高いアクセス管理が可能です (systemd.socket(5) を参照) これにより、UNIX ソケットへのアクセスをより制限することができます。
(事前に tmpfiles を使って作成する必要があります。参考は ウェブアプリケーションパッケージガイドライン を参照してください)、その グループ とファイルの パーミッション を変更することで、ソケットは root と ウェブサーバー だけがアクセスできるようになり、Web アプリケーションを独自のユーザーとして実行できるようになります:
/etc/systemd/system/uwsgi-secure@.socket
[Unit] Description=Socket for uWSGI %I [Socket] ListenStream=/run/%I/%I.sock SocketGroup=http SocketMode=0660 [Install] WantedBy=sockets.target
トラブルシューティング
Apache httpd
AH00957: uwsgi: attempt to connect to 127.0.0.1:0 (*) failed
デフォルトの uWSGI ポート (3031) は、(現時点では?) Apache httpd サーバーでは機能しません。詳細については、[5] を参照してください。