Barbarism begins at internet:2015年04月分

2015/04/01(Wed)

[www][ンッギモヂイイ X] NetBSD で nginxを使う(その1)

@N に nginx をインストールする

導入そのものは簡単です、pkgsrc から www/nginx-devel あるいは www/nginx をインストールするだけです。

今回は www/nginx-devel を入れます、なぜ開発版?と思われるかもしれませんがつーかこれパッケージ名がおかしい。

というのも nginx には mainline と stable の2バージョンがあって

  • www/nginx-devel → mainline
  • www/nginx → stable

という対応になってますが mainline はこれ開発版じゃないんです、 ここ参照。

@nginx の mainline と stable の違いを理解する

さっきのページ、mainline と stable どっちを使うべきかについては完全な答えが書いてあります。

Which version should I use?
    In general, you should deploy the NGINX mainline branch at all times.

はい、公式は「よっぽどのことが無い限りどんなときも(マッキー感) mainline を使え」といっとるわけです。

このドキュメントによると両者に違いは

  • mainline は全てのバグフィックス、機能追加、API/ABIの変更が含まれる
  • stable は重大なバグフィックスのみ

であり、ユースケース的に

  • 単なるユーザなら mainline を使うべき
  • 後方互換ではなく完全な API/ABI 互換性が必要なややこしい開発者だけが stable を使え(細かいバグは直らないこともあるので、安定性は下になる)

とゆーことなんですな。

おわかりいただけましたでしょうか、pksrcのパッケージ命名の拙さで www/nginx-devel は開発版だからと忌避し www/nginx の方を入れると逆に不安定になる可能性もあるちゅーわけです。

これ正しくは

  • www/nginx → www/nginx16
  • www/nginx-devel → www/nginx あるいは www/nginx17

ちゅー命名にすべきよね。

@インストール作業

バイナリパッケージ使うなら pkg_add

# pkg_add http://ftp.netbsd.org/pub/pkgsrc/packages/NetBSD/amd64/6.1.5/All/nginx-1.7.4.tgz

もしくは pkginを導入してれば

# pkgin install 'nginx<1.7'

です、pkgin 使ってないからこれであってるかは知らん(無責任)、そもそもバイナリ古いよ。

ソースからビルドするなら

$ cd /usr/pkgsrc/www/nginx-devel
$ make install

するだけっすね。

動かすには専用の user/group が必要です、pkg_add が nginx:nginx が無ければ勝手に追加してくれますが

  • uid/gid は1000 以上の空きで最も小さいものになるので、一般ユーザとごちゃまぜになる。特に NIS でユーザ管理してる場合などめんどいことに
  • user/group の名前に先頭にアンダースコアを含めるなどの名前空間保護をしてくれないので、既存ユーザ/グループと被った場合そっちが使われてしまう

ちゅー問題があります。

明示的に user/group を指定したい場合には pkg_add によるバイナリインストールは諦めて

NGINX_USER=		ユーザ名
NGINX_GROUP=		グループ名

PKG_UID.ユーザ名=	ユーザID
PKG_GID.グループ名=	グループID

あたりの変数を /etc/mk.conf で指定した上でソースからビルドしてくだちい。

これ pkgsrc で {user,group}add の -r オプションを使って、追加する uid/gid の最低値および最高値を

PKG_UID_MIN=5000
PKG_UID_MAX=5999

PKG_GID_MIN=5000
PKG_GID_MAN=5999

みたいに /etc/mk.conf で指定できればもうちょい楽になるんだけどねー。

それと、nginxのコンパイルオプション、options.mkをみると

PKG_SUPPORTED_OPTIONS=  dav flv gtools inet6 luajit mail-proxy memcache naxsi \
                        pcre push realip ssl sub uwsgi image-filter upload \
                        debug status nginx-autodetect-cflags spdy echo \
                        set-misc headers-more array-var encrypted-session \
                        form-input perl
PKG_SUGGESTED_OPTIONS=  inet6 pcre ssl

のように

  • IPv6サポート
  • Perl互換性器表現でJITを使う
  • SSL/TLSサポート

しか有効になってないので、他のモジュールを有効にしたい場合は PKG_OPTIONS.nginx を指定してオプションを有効にしてください。 以下の例では、apache の mod_perl に似た ngx_http_perl_moduleを有効にする例です。

PKG_OPTIONS.nginx+=		perl

インストールが終わると、ログローテーションについて newsyslog.confに追記しろと以下の指示がでます。

===========================================================================
$NetBSD: MESSAGE,v 1.2 2013/02/18 20:32:09 imil Exp $

Consider adding something like following lines to /etc/newsyslog.conf:

/var/log/nginx/access.log nginx:nginx 640 7 * 24 Z  /var/run/nginx.pid SIGUSR1
/var/log/nginx/error.log  nginx:nginx 640 7 * 24 Z  /var/run/nginx.pid SIGUSR1

===========================================================================

ですが

  • ログの出力場所
  • ログを残したい期間
  • ログのアクセス権限

など運用の要件次第で設定なんぞいくらでも変わりますので、とりま後回し。

@次回予告

nginx のインストールまでしか書けなかった orz

[(余計なもの)][NetBSD] NetBSD のバージョン管理について

前の記事で nginx の mainline と stable の違いを説明しましたが、実はこのへんの事情はNetBSDでも同じです。

NetBSDのバージョン番号は

X(メジャー番号) . Y(マイナー番号) . Z(リビジョン番号)

の3つのパートから成っとりまして、CVS 上では

という対応になってます。

判りにくいので具体的に例を上げると、CVS上には現在

の4つの枝 *1が存在し、最新のリリースタグには

の2つが存在しとります。

よって同じメジャー番号に対して複数のリリースが存在し、初めてNetBSDをインストールする人は、どれ選べばいいのかか迷うかと思いますが

という整理になりますので、ただの一般ユーザであればこの場合 6.1.5 を使うべきちゅーことになります。

@新しいバージョンがでたらどうなるの?

さらに今後

  • 6.0.7-RELEASE (netbsd-6-0 枝からの新しいリリース、6.0との完全互換)
  • 6.1.6-RELEASE (netbsd-6-1 枝からの新しいリリース、6.1との完全互換)
  • 6.2-RELEASE (netbsd-6 枝から新規に netbsd-6-2枝が分岐して最初のリリース)
  • 7.0-RELEASE (netbsd-7 枝からはじめてのリリース)

がリリースされる可能性があるわけですが、さっき 6.1.5 を選んだ一般ユーザは、その時々で最大のメジャ-・マイナー・リビジョンを選んでけばいいわけです。

ただしメジャー番号が変わるときには

  • pc532playstation2のように移植(port)ごと消されたり
  • もう誰も使っておらず動作確認もできないハードウェアのサポートが消えたり
  • コンパイラのターゲットCPが変更になって、命令をサポートしないCPU上で動かないバイナリがデフォルトになったり

などそもそもアップデートできないケースもあるので、リリースノートには注意。

@セキュリティ修正はどうなるの?

残念ながら N は Linux とか FreeBSD のようなバイナリアップデートというナウい機能がないので、セキュリティ修正は アドバイザリの指示に従って

  • Daily binary snapshotsから修正のあった日以降のスナップショットを持ってきて、問題のあるモジュール手動で置換する or アップデートインストールを実行する
  • 修正の入ったソースの差分あるいは全体を CVS あるいは上のスナップショットの src tarball から取得して、問題のあるモジュールあるいは全体を再ビルドしてインストールする

という悲惨な手順を踏むことになります、これで満足な人しかいないからちかたないね。

@どのバージョンにアップデートすればいいのか

スナップショットを使う場合、今インストールしているNのバージョンが 6.0.6-RELEASE であれば

のいずれかにアップデートが可能です、まー netbsd-7 はまだ BETA ですけどね。

勘違いしてはならないのは netbsd-6(6.1_STABLE) の方が netbsd-6-1(6.1.5_PATCH) より ABI 的に上位のバージョンになるということです。

netbsd-7(7.0_BETA) > netbsd-6(6.1_STABLE) > netbsd-6-1(6.1.5_PATCH) > netbsd-6-0(6.0.6_PATCH)

ちゅー順序になります、6.1_STABLE でなく 6.2_BETA という名前にすれば大小関係判りやすいんですが、それだと安定版に見えない問題もあるし。

CVSでソースを追いかける場合、最新リリースのメジャーだけの枝、つまり netbsd-6 枝を追いかけるのが一番安定してるはず。まぁ実際には releng がろくすっぽ動作確認してないので netbsd-5枝がピンポイントで壊れてるケースも存在しますが。

要するに枝が多過ぎるんですわ、例えば OpenSSL にセキュリティホール出たなんて時に面倒見なきゃならない枝が本日時点で

  • HEAD
  • netbsd-7
  • nebbsd-6
  • nebbsd-6-1
  • nebbsd-6-0
  • nebbsd-5
  • nebbsd-5-2
  • nebbsd-5-1
  • nebbsd-5-0

と 9 もありゃそらリリースエンジニアリングなんぞ破綻するよって話。しかもパッチリリースなんて必要になる人間なんて世界に3人もいないだろうに。

金もあってユーザも居る Red Hat ですら

  • Fedora 21 (HEADに相当)
  • Fedora 20 (HEADに相当)
  • RHEL 7 (netbsd-7に相当)
  • RHEL 6 (nebbsd-6に相当)
  • RHEL 5 (nebbsd-5に相当)

の 5 つなんだからパッチリリースなんて切り捨てていいと思うんだけどね、まぁワイはもう無関係ですが。

*1:正確にはまだ7枝からリリースが出てないので5枝も生きてるけど、ここでは割愛

2015/04/07(Tue)

[www][ンッギモヂイイ X] NetBSD で nginxを使う(その2)

@nginx で CGI アプリケーションを動かす

軽量 httpd にありがちな話ですが、そもそも nginx には CGI で外部プログラムを動かす機能はありまへん。

しかしそのかわりに ngx_http_fastcgi_module が有効(デフォルト)であれば FastCGI を実装するアプリケーションの Proxy として動かすことができますので、今回はそれを使ってチラシの裏を動かします。

本家ドキュメントの 設計例でも説明のあるとおり、nginx は FastCGIアプリを自動実行する機能を持ちませんので、事前にプロセスを起動しておく必要があります。

この設定例では PHP の CGI 版に -b オプションをつけて FastCGI Server モードで daemon として起動するように SysV Init に登録してます。

$ /usr/pkg/libexec/cgi-bin/php --help
Usage: php [-q] [-h] [-s] [-v] [-i] [-f <file>]
       php <file> [args...]
  -a               Run interactively
  -b <address:port>|<port> Bind Path for external FASTCGI Server mode
  …

ですがワイのチラシの裏は PHP ではなく Perl で動いてたので、この設定例じゃ役立たんのよね。

@PHP 以外の FastCGI Server 実装をインストールする

まず最初に spawn-fcgi をインストールします、こいつは daemon として常駐しリクエストに応じてアプリケーションを裏で自動実行してくれるサービスです。

ちな pkgsrc からの導入は

を入れて設定をするだけなんですが、設定方法がめんどくさい上にいつものノードキュメントなので今の時点では /etc/rc.conf に

spawnfcgi=NO

だけ設定して無効にしておきます、これについてはまた後日詳しい説明します。

@spawn-fcgi だけでは動作しない

そんでここ要注意なのですが

  • 自動実行できるのは FastCGI アプリだけ
  • Perl Script などの外部アプリケーションを直接実行する機能は持ってない

ちゅーとこ、さっきのPHPのように自分でサーバーになることができるのであれば不要なサービスでもあります。

ですがここで敢えて spawn-fcgi を導入するのにもメリットがあります、特にセキュリティ面で

  • setuid/setgid によって権限分離することができる(Apache でいうところの suexec の機能)
  • 実行時ディレクトリを指定できる、chroot(2) によって監獄の中で動作させることも可能

があるので、PHP も自身の FastCGI Server 機能を使わずに、spawn-fcgi 経由で呼び出すのが一般的のようですな。

@次回予告

引き続き nginx で CGI を動作させるためのアプリケーションの導入と設定について説明します。

2015/04/11(Sat)

[www][ンッギモヂイイ X] NetBSD で nginxを使う(その3)

@外部アプリケーションを FastCGI プロセスとして実行する wrapper を用意する

おあつらえむきに fcgiwrapというものがあります、ただこれ pkgsrc にはまだ無いので pkgsrc-wip(Work In Progress)から導入する必要があります。よってバイナリパッケージは用意されてないので pkgin とか pkg_add ではなく、自分でビルドしないとダメ。

@pkgsrc-wipの導入

導入方法は pkgsrc と pkgsrc-wip を CVS からか snapshot の tarball を拾ってきて、pkgsrc/wip として配置するだけで後は普通の pkgsrc と同様にビルドできます。

$ cvs -d:pserver:anoncvs@anoncvs.netbsd.org:/cvsroot get -P pkgsrc
$ cvs -d:pserver:anoncvs@pkgsrc-wip.cvs.sourceforge.net:/cvsroot/pkgsrc-wip checkout -P wip
$ mv wip pkgsrc
$ mv pkgsrc /usr

詳しくは 読め

ちなみに pkgsrc は4半期ごとに pkgsrc-2015Q1( リリースノート) のようにリリースと呼んでいいのかスナップショットなのかちゅーものを世に出しますが、pkgsrc-wip は基本的に pkgsrc-currentでしか依存関係その他の動作確認してないはずなんで、そっち使ってください。

@wip/fcgiwrap のインストール

この

のビルドには別途 FastCGI SDK が必要ですが、こっちは pkgsrc にすでに存在します。

まぁ pkgsrc は依存関係にあるパッケージが未インストールなら勝手にインストールするので

$ cd /usr/pkgsrc/wip/fcgiwrap
$ make install

と叩くだけではあります。

@www/spawn-fcgi の起動方法

まず基本的な使い方を確認します、spawn-fcgi の manual をみると syntax は以下のとおり。

spawn-fcgi [options] [ -- <fcgiapp> [fcgi app arguments]]

-- に続けて起動対象の FastCGI アプリケーションおよび引数を指定します。

さらに spawn-fcgi には以下のオプションを指定可能です *1

  • -d <path> … FastCGI アプリの使うカレントディレクトリを指定
  • -a <address> … TCP/IP でプロセス間通信を行う、引数にはバインドする IP アドレスを指定 (-s とは排他)
  • -p <port> … 〃 ポート 〃
  • -s <path> … UNIX ドメインソケットでプロセス間通信を行う、引数にはソケットファイルを指定 (-a とは排他)
  • -u <user> … 引数で指定したユーザに setuid(2) する
  • -g <group> … 引数で指定したグループに setgid(2) する
  • -U <user> … UNIX ドメインソケットの所有権を引数のユーザに変更する
  • -G <user> … UNIX ドメインソケットの所有権を引数のグループに変更する
  • -M <mode> … UNIX ドメインソケットのパーミッションを指定する

デフォルトの nginx.conf にある設定例では

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        /usr/pkg/etc/nginx/fastcgi_params;
        #}

と、nginx と spawn-fcgi + php-cgi の通信を TCP/IP(127.0.0.1:9000)で行うようになってますが、この設定に対応するよう spawn-fcgi + php-cgi を起動するには

$ spawn-fcgi -a 127.0.0.1 -p 9000 -- /usr/pkg/libexec/cgi-bin/php

ちゅー感じで起動すればおk、TCP/IPなら nginx と spawn-fcgi を同じサーバで動かす必要もありまへん。

まぁ性能面ではUNIXドメインソケットの方が勝るので、複数台でスケールアウトする必要がなければこっちですな。

fastcgi_pass 127.0.0.1:9000;

fastcgi_pass unix:/var/run/foo.sock;

のようにソケットへのパスに書き換えるだけです、この場合 spawn-fcgi は

$ spawn-fcgi -s /var/run/foo.sock -- /usr/pkg/libexec/cgi-bin/php	

になります。

なお UNIX ドメインソケットの場合、nginx は nginx.confで

user nginx nginx;

と指定したユーザグループにsetuid/setgidしてますので、この権限で読み書きできる必要があります。

# spawn-fcgi -s /var/run/foo.sock -u nginx -g nginx -- /usr/pkg/libexec/cgi-bin/php	

とユーザグループを同じにして起動すればおk。

より安全に *2動かすため spawn-fcgi をさらに特権分離し別ユーザグループ(以下の例では spawnfcgi:spawnfcgiとする)で起動するのなら

# spawn-fcgi -s /var/run/foo.sock -u spawnfcgi -g spawnfcgi -U nginx -G nginx -- /usr/pkg/libexec/cgi-bin/php	

とする、あるいは nginx ユーザを spawnfcgi グループに所属させて

# spawn-fcgi -s /var/run/foo.sock -u spawnfcgi -g spawnfcgi -M 0660 -- /usr/pkg/libexec/cgi-bin/php	

とするなどしてグループにも読み書き権限を許可してやってください。

@spawn-fcgi + fcgiwrap の設定例

基本的にはさっきの起動方法で説明した PHP の設定例と同じです。

location ~ \.cgi$ {
	root		html;
	fastcgi_pass	127.0.0.1:9000;
	#fastcgi_pass	unix:/var/run/foo.sock;
	fastcgi_index	index.cgi;
	fastcgi_param	SCRIPT_FILENAME  /scripts$fastcgi_script_name;
	include		/usr/pkg/etc/nginx/fastcgi_params;
}

単に拡張子を .php から .cgi に変更しただけです。

起動方法も同じ、FastCGI アプリを php から fcgiwrap に変えただけです。

$ spawn-fcgi -a 127.0.0.1 -p 9000 -- /usr/pkg/sbin/fcgiwrap
$ spawn-fcgi -s /var/run/foo.sock -- /usr/pkg/sbin/fcgiwrap

@次回予告

今回は spawn-fcgiのオプションをあっさり目に説明しましたが、次はを手動でなく起動時に自動実行するようにスクリプトを設定する方法を説明します。

*1:他にも -c/-S/-C/-Fがありますが回を改めて説明します。
*2:より安全にと書きましたが、セキュリティに関する話はまた回を改めて書きます。

2015/04/26(Sun)

[NetBSD] getopt(3)

おそらく lib/17248を修正した時に、 lib/6762が再発してたことに気づいたので 直した

やはりregression testは書かないとアカンね。