NginxのユーザディレクトリでPHPを動かす

Nginx の設定ファイルの server セクションで次のように設定する。

# User dir (PHP)
location ~ ^/~([^/]+?)/(.+\.php)$ {
    alias /home/$1/public_html/$2;
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $fastcgi_script_name;
    include fastcgi_params;
}

# User dir (static)
location ~ ^/~(.+?)(/.*)?$ {
    alias /home/$1/public_html$2;
    index index.html index.htm;
    autoindex on;
}

# For PHP
location ~ \.php$ {
    root /var/www/html;
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
}

キモは User dir (PHP) のセクションを For PHP のセクションよりも前に書くこと。そうしないとブラウザで PHP のファイルにアクセスしても Not found になってしまう。なぜなら location ~ \.php$ に先にマッチしてしまってファイルが見つからないから(たぶん)。

カレントディレクトリ直下のディレクトリ一覧を得る

ls コマンドのオプションにディレクトリだけ表示するのがあればよかったのに、ないらしい。なので awk と組み合わせた。

takatoh@nightschool $ ls -l . | awk '/^d/ { print $9 }'
Desktop
Documents
Downloads
Dropbox
Music
Pictures
Public
Templates
Videos
bin
lib
tmp
w

FlaskアプリをuWSGIで動かす(2)

ユーザの作成

専用ユーザを作る。

takatoh@nightschool $ sudo adduser bruschetta
[sudo] password for takatoh: 
ユーザー `bruschetta' を追加しています...
新しいグループ `bruschetta' (1003) を追加しています...
新しいユーザー `bruschetta' (1003) をグループ `bruschetta' に追加しています...
ホームディレクトリ `/home/bruschetta' を作成しています...
`/etc/skel' からファイルをコピーしています...
新しい UNIX パスワードを入力してください: 
新しい UNIX パスワードを再入力してください: 
passwd: パスワードは正しく更新されました
bruschetta のユーザ情報を変更中
新しい値を入力してください。標準設定値を使うならリターンを押してください
	フルネーム []: bruschetta
	部屋番号 []: 
	職場電話番号 []: 
	自宅電話番号 []: 
	その他 []: 
以上で正しいですか? [Y/n] Y

sudo する権限をつける。

takatoh@nightschool $ sudo gpasswd -a bruschetta sudo
ユーザ bruschetta をグループ sudo に追加

アプリの配置と起動確認

今作った新しいユーザでログインしなおして GitHub から clone。

bruschetta@nightschool:~$ git clone https://github.com/takatoh/Bruschetta.git bruschetta
Cloning into 'bruschetta'...
remote: Counting objects: 345, done.
remote: Compressing objects: 100% (126/126), done.
remote: Total 345 (delta 231), reused 319 (delta 205), pack-reused 0
Receiving objects: 100% (345/345), 31.03 KiB | 0 bytes/s, done.
Resolving deltas: 100% (231/231), done.
Checking connectivity... done.

virtualenv の作成と必要なライブラリのインストール。

bruschetta@nightschool:~$ cd bruschetta
bruschetta@nightschool:~/bruschetta$ virtualenv env
New python executable in env/bin/python
Installing setuptools, pip, wheel...done.
bruschetta@nightschool:~/bruschetta$ source env/bin/activate
(env)bruschetta@nightschool:~/bruschetta$ pip install -r requirements.txt
Collecting Flask (from -r requirements.txt (line 1))
/home/bruschetta/bruschetta/env/local/lib/python2.7/site-packages/pip/_vendor/requests/packages/urllib3/util/ssl_.py:90: InsecurePlatformWarning: A true SSLContext object is not available. This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. For more information, see https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning.
  InsecurePlatformWarning
  Downloading Flask-0.10.1.tar.gz (544kB)
    100% |████████████████████████████████| 544kB 720kB/s 
Collecting Flask-SQLAlchemy (from -r requirements.txt (line 2))
  Downloading Flask-SQLAlchemy-2.1.tar.gz (95kB)
    100% |████████████████████████████████| 98kB 1.6MB/s 
Collecting Flask-Script (from -r requirements.txt (line 3))
  Downloading Flask-Script-2.0.5.tar.gz (42kB)
    100% |████████████████████████████████| 45kB 2.4MB/s 
Collecting Werkzeug>=0.7 (from Flask->-r requirements.txt (line 1))
  Downloading Werkzeug-0.11.2-py2.py3-none-any.whl (304kB)
    100% |████████████████████████████████| 307kB 1.1MB/s 
Collecting Jinja2>=2.4 (from Flask->-r requirements.txt (line 1))
  Downloading Jinja2-2.8-py2.py3-none-any.whl (263kB)
    100% |████████████████████████████████| 266kB 1.4MB/s 
Collecting itsdangerous>=0.21 (from Flask->-r requirements.txt (line 1))
  Downloading itsdangerous-0.24.tar.gz (46kB)
    100% |████████████████████████████████| 49kB 1.8MB/s 
Collecting SQLAlchemy>=0.7 (from Flask-SQLAlchemy->-r requirements.txt (line 2))
  Downloading SQLAlchemy-1.0.9.tar.gz (4.7MB)
    100% |████████████████████████████████| 4.7MB 120kB/s 
Collecting MarkupSafe (from Jinja2>=2.4->Flask->-r requirements.txt (line 1))
  Downloading MarkupSafe-0.23.tar.gz
Building wheels for collected packages: Flask, Flask-SQLAlchemy, Flask-Script, itsdangerous, SQLAlchemy, MarkupSafe
  Running setup.py bdist_wheel for Flask
  Stored in directory: /home/bruschetta/.cache/pip/wheels/d2/db/61/cb9b80526b8f3ba89248ec0a29d6da1bb6013681c930fca987
  Running setup.py bdist_wheel for Flask-SQLAlchemy
  Stored in directory: /home/bruschetta/.cache/pip/wheels/79/20/fe/49ca207b5445eacf8f34ac4c7f2365dd344e17668cd63b8fdd
  Running setup.py bdist_wheel for Flask-Script
  Stored in directory: /home/bruschetta/.cache/pip/wheels/42/85/3d/fca6d4a04f7852ce8322be36ff8918ceff9bce568e7144c813
  Running setup.py bdist_wheel for itsdangerous
  Stored in directory: /home/bruschetta/.cache/pip/wheels/97/c0/b8/b37c320ff57e15f993ba0ac98013eee778920b4a7b3ebae3cf
  Running setup.py bdist_wheel for SQLAlchemy
  Stored in directory: /home/bruschetta/.cache/pip/wheels/f7/c3/1f/a136a98dbce9c82df10df168813df34bba6d039787e4327634
  Running setup.py bdist_wheel for MarkupSafe
  Stored in directory: /home/bruschetta/.cache/pip/wheels/94/a7/79/f79a998b64c1281cb99fa9bbd33cfc9b8b5775f438218d17a7
Successfully built Flask Flask-SQLAlchemy Flask-Script itsdangerous SQLAlchemy MarkupSafe
Installing collected packages: Werkzeug, MarkupSafe, Jinja2, itsdangerous, Flask, SQLAlchemy, Flask-SQLAlchemy, Flask-Script
Successfully installed Flask-0.10.1 Flask-SQLAlchemy-2.1 Flask-Script-2.0.5 Jinja2-2.8 MarkupSafe-0.23 SQLAlchemy-1.0.9 Werkzeug-0.11.2 itsdangerous-0.24

データベースの初期化。

(env)bruschetta@nightschool:~/bruschetta$ python manage.py init_db

起動確認。

(env)bruschetta@nightschool:~/bruschetta$ python manage.py runserver
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

OK。

uWSGIを使った起動

uWSGI 用の設定ファイル。

[uwsgi]
uid = root
gid = root
http = :9090
venv = /home/bruschetta/bruschetta/env
python-path = /home/bruschetta/bruschetta
wsgi-file = /home/bruschetta/bruschetta/manage.py
callable = app
master=true
pidfile=/var/run/bruschetta.pid
logger=file:/home/bruschetta/bruschetta/bruschetta.log

起動確認。

bruschetta@nightschool:~/bruschetta$ sudo uwsgi bruschetta.ini
[sudo] password for bruschetta: 
[uWSGI] getting INI configuration from bruschetta.ini

OK。sudo をつけてるのは、/var/run/bruschetta.pid に書き込むため。

起動用スクリプト

PATH=/sbin:/usr/local/bin:/usr/bin:/bin
APP_ROOT=/home/bruschetta/bruschetta

case "$1" in
start)
    cd ${APP_ROOT}
    uwsgi bruschetta.ini
    ;;
stop)
    PID_FILE=/var/run/bruschetta.pid
    PID=`cat ${PID_FILE}`
    kill -INT ${PID}
    rm ${PID_FILE}
    ;;
*)
    echo "Usage: bruschetta {start|stop}" >&2
    exit 1
    ;;
esac

exit 0

起動確認。

bruschetta@nightschool:~/bruschetta$ sudo service bruschetta start
[uWSGI] getting INI configuration from bruschetta.ini

あれ、デーモンにならない。
ググってみたら、ini ファイルに logger じゃなくて daemonize を書くみたい。次のように書きなおした。

[uwsgi]
uid = root
gid = root
http = :9090
venv = /home/bruschetta/bruschetta/env
python-path = /home/bruschetta/bruschetta
wsgi-file = /home/bruschetta/bruschetta/manage.py
callable = app
master=true
pidfile=/var/run/bruschetta.pid
#logger=file:/home/bruschetta/bruschetta/bruschetta.log
daemonize=/home/bruschetta/bruschetta/bruschetta.log

今度は OK。

Ubuntu 起動時に自動的に起動するように設定。sysv-rc-conf を使う。

bruschetta@nightschool:~/bruschetta$ sudo sysv-rc-conf
buschetta-service

Nginxの設定

upstream uwsgi-bruschetta {
    server 127.0.0.1:9090;
}

server {
    # port
    listen 80;

    # server name
    server_name bruschetta;

    # document root
    root /home/bruschetta/bruschetta;

    # index
    #index index.php index.html index.htm;

    # log files
    access_log /var/log/nginx/bruschetta/access.log combined;
    error_log /var/log/nginx/bruschetta/error.log warn;

    keepalive_timeout 60;
    proxy_connect_timeout 60;
    proxy_read_timeout 60;
    proxy_send_timeout 60;

    #client_max_body_size 20M;

    location / {
        #root /home/bruschetta/bruschetta;

        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_pass http://uwsgi-bruschetta;
    }

}

sites-enabled から sites-available へリンクを張る。

bruschetta@nightschool:/etc/nginx/sites-enabled$ sudo ln -s ../sites-available/bruschetta bruschetta

/etc/hosts に次の行を挿入。

127.0.0.1 bruschetta

ログファイル用のディレクトリを作成。

bruschetta@nightschool:~$ sudo mkdir /var/log/nginx/bruschetta

Nginx を再起動。

bruschetta@nightschool:/etc/nginx/sites-enabled$ sudo service nginx restart
 * Restarting nginx nginx

これで完了。

wikiの引越し

昨日は MySQL をインストールするところから始めて、MediaWiki を動かすところまで書いたけど、そのあと Windows マシンで運用している既存の wiki の引越しもしたのだった。今日はその手順について、(うろ覚えで)書く。

データベースとファイルのバックアップ

まずはデータベースの中身をファイルに吐き出させる。msqldump をいうコマンドを使うんだけど、パスが通ってなかったのでフルパスで指定。

^o^ > C:\VertrigoServ\Mysql\bin\mysqldump -u root -p wiki > wiki.sql

それから、アップロードしたファイルが保存されているフォルダを zip で固める。

^o^ > cd \www\wiki
^o^ > zip -r images.zip images

2つのファイルを持って、Ubuntu のマシンに移動。

データベースの更新とファイルの配置

Windows マシンから持ってきた wiki.sql ファイルを MySQL に読み込ます。

takatoh@nightschool $ mysql -u root -p wiki < wiki.sql

それから、images.zip を展開。すでに images フォルダがあるけどそのまま上書きする。

takatoh@nightschool $ cd /var/www/html/wiki
takatoh@nightschool $ unzip images.zip

これで一応完了。

エラー発生

ところがブラウザでアクセスしてみると、エラーが発生した。画面には「A database query error has occurred. This may indicate a bug in the software.」とか出ている。どうもデータベースのエラーのよう。ググってみたら↓このページを見つけた。

 cf. [RESOLVED] Database error in upgrading from 1.18 to 1.22

どうやら、mw-config/index.php にアクセスしてインストールをやり直せってことらしい。そのとおりにする。インストールの画面になり、進めていくとLocalSettings.php の中の $wgUpgradeKey の値を入力しろと促されるので入力する。そしたら何やらデータベースをアップグレードしているようになり、完了。
再度ブラウザでアクセスすると、ちゃんと表示された。

画像が表示されない

これは単にファイルのパーミッションの問題だった。images フォルダを展開、上書きした時に所有者が takatoh になってしまって、wiki のユーザーからアクセスできないようになっていた。なので、次のようにして解決。

takatoh@nightschool $ sudo chown -R 2246:500 images
takatoh@nightschool $ sudo chmod -R 755 images

Windowsマシンからだと表示がおかしい

Ubuntu マシンから、localhost でアクセスするぶんには問題は解決したけど、Windows マシンからアクセスすると表示がおかしい。おかしいというのは、本文は表示されるんだけど、スタイルシートなんかが読み込まれていない感じ。
ググって見つけたページがここのコメント欄。

 cf. XAMPP1.81が社内のLANに公開できない – QA@IT

LocalSettings.php の中の $wgServer の値が localhost になっているのが原因らしい。次のようにホスト名に変えた。

$wgServer = "http://nightschool";

これで、無事 Windows マシンからもちゃんと使えるようになった。

UbuntuでMediaWikiを動かす

関連パッケージをインストール。

takatoh@nightschool $ sudo -s
root@nightschool # apt-get install php5-intl php5-gd texlive php5-xcache

MediaWiki を公式サイトからダウンロード。

root@nightschool # wget http://releases.wikimedia.org/mediawiki/1.24/mediawiki-1.24.2.tar.gz

ファイルを展開して、出来たフォルダの名前を変更。

root@nightschool # tar zxvf mediawiki-1.24.2.tar.gz
root@nightschool # mv mediawiki-1.24.2 wiki

あとはブラウザで http://localhost/wiki/ にアクセスするとセットアップ画面になるので、Wiki の名前とかデータベースとかを促されるとおりに入力して行けばOK。最後に LocalSettings.php をダウンロードして、/var/www/html/wiki にコピー。

root@nightschool # cp /home/takatoh/Downloads/LocalSettings.php wiki

これでインストールは完了。Wiki のページにアクセスするとちゃんとできていた。

wiki-mainpage

[追記]

ついでにちょっと設定をかえておく。
まずはロゴ。$wgLogo を設定しろと表示されてるんではかっこ悪いので、標準で付属しているロゴを表示するようにする。LocalSettings.php の $wgLogo を変更。

wgLogo = "$wgScriptPath/skins/MonoBook/wiki.png";

ファイルのアップロードを有効にする。LocalSettings.php の $wgEnableUploads を true にする。

$wgEnableUploads = true;

それから、アップロード可能なファイルサイズを変更。これは MediaWiki じゃなくて PHP の設定。/etc/php5/fpm/php.ini を次のように変更。

upload_max_filesize = 8M

phpMyAdminをインストール

昨日、PHP をインストールしたので、MySQL のついでに phpMyAdmin をインストールしてみた。

参考ページ:

 cf. UbuntuにphpMyAdminをインストールするには – 初心者がWEB開発に挑戦

takatoh@nightschool $ sudo apt-get install phpmyadmin

インストールの途中で、Webサーバを聞いてくるけど Apache と Lighttpd しか選択肢がないので、Esc キーを押して続行。少しすると今度は phpmyadmin を設定するかと訊かれるので、YES。ユーザーとパスワードを設定しただけであとは何やらやっているよう。しばらくすると終わる。

これで http://localhost/phpmyadmin にアクセスすると行けるようだけど…あれ?だめだ。やっぱりさっきの Webサーバ選択のところで Nginx がなかったからか。ググってみた結果、/usr/share/phpmyadmin のシンボリックリンクを Nginx のドキュメントルートに作ればいいようだ。

takatoh@nightschool $ sudo ln -s /usr/share/phpmyadmin /var/www/html

今度はどうだ。
phpmyadmin

うまくいったようだ。

UbuntuにMySqlをインストール

apt-get でインストール。

takatoh@nightschool $ sudo apt-get install mysql-server

途中で root ユーザーのパスワードを入力するように促されるので、入力する(2回)。
バージョンの確認。

takatoh@nightschool $ mysql --version
mysql  Ver 14.14 Distrib 5.5.41, for debian-linux-gnu (x86_64) using readline 6.3

/etc/mysql に移動して、設定ファイル my.cnf に文字コードなど追記。…の前にバックアップをとっておく。

takatoh@nightschool $ sudo cp my.cnf my.cnf.orig
takatoh@nightschool $ sudo vim my.cnf

以下を追記。

[client]
default-character-set = utf8

[mysqld]
skip-character-set-client-handshake
character-set-server = utf8
collation-server = utf8_general_ci
init-connect = SET NAMES utf8

MySQL を再起動。

takatoh@nightschool $ sudo service mysql restart
mysql stop/waiting
mysql start/running, process 30969

MySQL にログイン。

takatoh@nightschool $ mysql -u root -p

ステータスを確認。

mysql> status
--------------
mysql  Ver 14.14 Distrib 5.5.41, for debian-linux-gnu (x86_64) using readline 6.3

Connection id:		36
Current database:	
Current user:		root@localhost
SSL:			Not in use
Current pager:		stdout
Using outfile:		''
Using delimiter:	;
Server version:		5.5.41-0ubuntu0.14.04.1 (Ubuntu)
Protocol version:	10
Connection:		Localhost via UNIX socket
Server characterset:	utf8
Db     characterset:	utf8
Client characterset:	utf8
Conn.  characterset:	utf8
UNIX socket:		/var/run/mysqld/mysqld.sock
Uptime:			1 min 48 sec

Threads: 1  Questions: 109  Slow queries: 0  Opens: 171  Flush tables: 1  Open tables: 41  Queries per second avg: 1.009
--------------

うまくいってるっぽい?
プロセスの確認。

takatoh@nightschool $ ps aux | grep mysqld
mysql    30969  0.0  1.0 484440 42984 ?        Ssl  21:44   0:00 /usr/sbin/mysqld
takatoh  31111  0.0  0.0  16904   932 pts/4    S+   21:47   0:00 grep --color=auto mysqld

参考にしたページ:

 cf. UbuntuにMySQLをインストール – うまとま君の技術めも

Nginxにデフォルトのバーチャルホストを設定する

家庭内 LAN 向けにバーチャルホストをたてようというのが動機。現状では、サーバに HTTP でアクセスすると Sinatra アプリが応答してしまっていた。
設定方法は↓このページが参考になった。

 cf. nginxでデフォルトのバーチャルホストを設定する方法 – Linux入門

答えは簡単で、listen ディレクティブに default_server と書き足すだけでいい。これがないと、最初に読み込まれたバーチャルホストがデフォルトになるので、今まで Sinatra アプリのサーバが応答していたってわけだ。

/etc/nginx/sites-available に nightschool という名前で設定ファイルを作って、/etc/nginx/sites-enabled 以下にシンボリックリンクを作成。作った設定ファイルはこれ。

server {
    # port
    listen 80 default_server;

    # server name
    server_name nightschool;

    # document root
    root /var/www/html;

    # index
    index index.php index.html index.htm;

    # log files
    access_log /var/log/nginx/nightschool/access.log combined;
    error_log /var/log/nginx/nightschool/error.log warn;
}

ドキュメントルートとログファイルのためのディレクトリを作って、ドキュメントルートには index.html ファイルをおいた。

<html>
  <body>
    <h1>Hello, welcome!</h1>
    This is nightschool.
  </body>
</html>

あとは Nginx を再起動して完了。

takatoh@nightschool $ sudo service nginx stop
takatoh@nightschool $ sudo service nginx start

確認のために Windows PC からアクセスしたところ、ちゃんと index.html の内容が表示された。

default-vhost

Sinatraアプリのログをローテーションする(2)

logrotate の設定をして1日待ってみたけど、ログファイルがローテーションされていない。仕方がないので、-f オプションを使って強制的に行ってみたら、次のようなメッセージが出た。

takatoh@nightschool $ sudo logrotate -f -v sombrero
reading config file sombrero

Handling 1 logs

rotating pattern: /home/sombrero/sombrero/unicorn.log  forced from command line (60 rotations)
empty log files are rotated, old logs are removed
considering log /home/sombrero/sombrero/unicorn.log
error: skipping "/home/sombrero/sombrero/unicorn.log" because parent directory has insecure permissions (It's world writable or writable by group which is not "root") Set "su" directive in config file to tell logrotate which user/group should be used for rotation.

なんだかよくわからないけど、親ディレクトリのパーミッションがセキュアじゃないといってる?設定ファイルに su ディレクティブをセットしろともいってる。

ちょっと調べてみると、次のページが見つかった。

 cf. logrotate(8) の create と su ディレクティブについて – はてダ

読んでもよくわからないんだけど、とにかく次の1行を設定ファイルに追加した。

su root root

これでどうだ。

takatoh@nightschool $ sudo logrotate -f -v sombrero
reading config file sombrero

Handling 1 logs

rotating pattern: /home/sombrero/sombrero/unicorn.log  forced from command line (60 rotations)
empty log files are rotated, old logs are removed
considering log /home/sombrero/sombrero/unicorn.log
  log needs rotating
rotating log /home/sombrero/sombrero/unicorn.log, log->rotateCount is 60
dateext suffix '-20150409'
glob pattern '-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
glob finding logs to compress failed
glob finding old rotated logs failed
renaming /home/sombrero/sombrero/unicorn.log to /home/sombrero/sombrero/unicorn.log-20150409
running postrotate script

今度はうまくいった?

takatoh@nightschool $ ls /home/sombrero/sombrero
CHANGES       bin                 lib        unicorn.conf          views
Gemfile       boot.rb             public     unicorn.log
Gemfile.lock  config.yaml         rakefile   unicorn.log-20150409
app.rb        config.yaml.sample  start.cmd  unicorn.pid
app.ru        db                  tmp        version.rb

おお、ちゃんとローテートされたファイル(unicorn.log-20150409)ができて、新しいログファイル(unicorn.log)もできている。
これでOKかな。