httpd (3)


WSGIDaemonProcessの謎

mod_wsgiを設定してみた。
環境は FreeBSD11 + Apache24。

ハマったのは、venv のパス。

/usr/local/lib/python3.6/venv

とかに設定してもダメ。encodings というモジュールがないです、と言われてしまう。

どうも大事なのは以下のコマンド。バーチャルホストのホームディレクトリ(あるいはApacheのドキュメントルートのひとつ上あたりのディレクトリ。要するにPythonアプリケーションをインストールしたあたり)で以下を実行する。

$ python -m venv ./venv

したらば、Apacheの設定ファイルに以下のような設定を書く。

<VirtualHost 127.0.0.1:80>
    ServerName www.example.com
    DocumentRoot /path/to/www.example.com/htdocs
    WSGIDaemonProcess www.example.com python-home=/path/to/www.example.com/venv threads=5
    WSGIProcessGroup www.example.com
    WSGIScriptAlias /myapp/ /path/to/www.example.com/myapp/myapp/wsgi.py process-group=www.example.com
    WSGIScriptReloading On
    <Directory /path/to/www.example.com/pyapp/pyapp>
        <Files wsgi.py>
            Require all granted
        </Files>
    </Directory>
</VirtualHost>

python-home=/path/to/www.example.com/venv は、さっき作った venv ディレクトリの絶対パス。

これでなんとか動きました。
が…。
今度は、djangoが認識されない。アプリをウェブから叩いて動かそうとすると、「djangoモジュールが見つからないです」(意訳)とapacheのエラーログに吐き出される。

どうして!? Django公式ドキュメント通りにやってるのに!
と悩むことしばし。

ふと基本に立ち返って「rootじゃダメだよなぁ」と、バーチャルホストのユーザーに切り替えて、バーチャルホストのユーザーディレクトリであれこれコマンドを打ち込んだら、なんとかなった。

わたしがハマった最大の要因は、すべての作業を root で行ったこと。
本来はバーチャルホストのユーザーで行わなくてはいけない。
(わたしはバーチャルホストごとにユーザーを分けています)

そして、バーチャルホストのユーザーディレクトリで完結するように「環境」を整えないといけない。
さすがはPython! PHPとは違う。

$ cd www.example.com
$ python -m venv ./venv
$ ./venv/bin/pip install django
$ ./venv/bin/django-admin startproject myapp
$ ... (以下python公式ドキュメントと同じ。)

こんな感じで、バーチャルホストのディレクトリで作業を完結させる。
すると、「モジュールないですエラー」は出なくなる。

次の問題は…「myappモジュールないですエラー」
わけがわからない…。




Nginx+Apache×2+SSL(+WordPress)

獲得目標は以下の通りです。
●SSLの設定をしたNginxでリバースプロキシをさせて、バックエンドのApacheに渡す。
●Wordpressも動くようにする。

ではさっそく。

Nginx(エンジンエックスと読むそうですね!):

http {
    upstream MidgenasiaServers {
        # バックエンドサーバーの設定をします。
        server 10.0.0.80:8080; # 8080番ポートでhttp通信をListenしているIP 10.0.0.80上のApache 
        server 10.0.0.81:8080; # 8080番ポートでhttp通信をListenしているIP 10.0.0.81上のApache
    }
    upstream OtherServers {
        # こちらもバックエンドサーバーの設定です。上と同じサーバーに格納されている想定です。
        server 10.0.0.80:8081;
        server 10.0.0.81:8081;
    }
    server {
        # http通信はすべてhttpsに301リダイレクトします。
        listen 80;
        return 301 https://$host$request_uri;
    }
    server {
        listen 443 ssl;
        server_name  www.midgen.asia;
        charset utf-8;

        # SSL
        ssl_certificate      path/to/server.crt;
        ssl_certificate_key  path/to/server.key;
        ssl_session_cache  builtin:1000  shared:SSL:10m;
        ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
        ssl_prefer_server_ciphers  on;
        # server.keyにパスフレーズを指定してある場合はたぶん必要。パスフレーズだけ書いておけばOK。
        ssl_password_file path/to/server-password;

        location / {
            # upstreamの場所で指定した名称をここに書きます。
            proxy_pass          http://MidgenasiaServers;
            proxy_redirect      off;
            proxy_set_header    Host    $host;
            proxy_set_header    X-Real-IP    $remote_addr;
            proxy_set_header    X-Forwarded-Proto     https;
            proxy_set_header    X-Forwarded-Host      $host;
            proxy_set_header    X-Forwarded-Server    $host;
            proxy_set_header    X-Forwarded-For    $proxy_add_x_forwarded_for;
        }
    }

    # 2つ目のドメインの設定も続けて書きます。
    server {
        server_name  www.another.domain.com;
        charset utf-8;

        ssl_certificate      path/to/another.domain.com.crt;
        ssl_certificate_key  path/to/another.domain.com.key;
        ssl_session_cache  builtin:1000  shared:SSL:10m;
        ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
        ssl_prefer_server_ciphers  on;
        ssl_password_file path/to/another.domain.com-password;

        location / {
            # 上記と同様に、upstreamの場所で指定した名称をここに書きます。
            proxy_pass    http://OtherServers;
            proxy_redirect      off;
            proxy_set_header    Host    $host;
            proxy_set_header    X-Real-IP    $remote_addr;
            proxy_set_header    X-Forwarded-Proto     https;
            proxy_set_header    X-Forwarded-Host      $host;
            proxy_set_header    X-Forwarded-Server    $host;
            proxy_set_header    X-Forwarded-For    $proxy_add_x_forwarded_for;
        }
    }
}

※要旨に関係がないコメントや設定は削除してあります。

Apache:

Listen 8080
Listen 8081

>VirtualHost 10.0.0.80:8080<
    ServerName www.midgen.asia
    DocumentRoot "/path/to/midgen.asia.htdocs"
>/VirtualHost<

>VirtualHost 10.0.0.80:8081<
    ServerName www.gowest-comewest.net
    DocumentRoot "/path/to/another.domain.com.htdocs"
>/VirtualHost<

ここまででNginx+SSLとラウンドロビンなApacheは完成。
あとは…Wordpress。リバースプロキシ+SSLという環境下では、特殊な記述をwp-config.phpに加える必要があるようです。

WordPress(wp-config.phpの上のほうに書きます):

if (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])
    && $_SERVER['HTTP_X_FORWARDED_PROTO'] === "https") {
  $_SERVER['HTTPS'] = 'on';
}
define('FORCE_SSL_LOGIN', true);
define('FORCE_SSL_ADMIN', true);

参考: WordPressをhttps化してnginx reverse proxy配下で使うには

これでWordpressのCSSやJavaScriptが読み込まれないという状況も打破できます。

できてよかった!




Mysql5.6 on Raspberry pi 2: サーバーを落ちないようにする

mysqldが落ちて落ちてしかたがない! という状況に陥ったわたしが探し当てた解決策。

大したことではないですが、初心者には大事なこと。

http://easyramble.com/example-of-mysql-options.html

上記ウェブサイトで紹介されていた設定を以下のように変えてmy.cnfに単純に追記しただけで、落ちなくなりました。

max_connections = 3
max_user_connections = 1

単純に、接続制限をかけただけです。が、効果はてきめん!
F5攻撃を行っても、単に接続エラーが発生するだけで、落ちなくなりました。

ついでにhttpd(apache24)のmpmの設定でも接続制限をして、ひと安心。