トップ 履歴 一覧 カテゴリ ソース 検索 ヘルプ RSS ログイン

OpenBSD/httpd/77(relayd+slowcgi)

INDEX

OpenBSD Webサーバ (httpd+slowcgi on OpenBSD 7.7)

OpenBSD の Webサーバ httpd(relayd) で、slowcgi(8) を使い CGI (Common Gateway Interface) を動かす。

slowcgi は、CGI を実行する FastCGIプロトコルを処理する。httpd で、CGI を実行して表示できるようにする。

httpd 自体を動かす設定は、OpenBSD/httpd/77(relayd) を参照。

slowcgi の起動設定

  自動起動

サーバが起動したときに slowcgi も実行されるように、/etc/rc.conf.localslowcgi_flags を指定する。

# FastCGI to CGI wrapper server
slowcgi_flags=

または、rcctl enable slowcgi で有効にする( /etc/rc.conf.local に slowcgi_flags= が記載される)。

  デバッグ

root ユーザのコンソールで、-dv オプションをつけて実行すると、処理の内容が表示される。

# slowcgi -dv
slowcgi: sock_user: www
slowcgi: socket: /var/www/run/slowcgi.sock
slowcgi: slowcgi_user: www
slowcgi: chroot: /var/www

Webサーバ(httpd) の設定

/etc/httpd.conf に設定する。サンプルが /etc/examples/httpd.conf にある。

OpenBSD の httpd および slowcgi は、デフォルトで /var/www に chroot されるようになっている。そのため、動的リンクされているプログラムや sh や perl などのスクリプトを実行する場合は、chroot されるディレクトリ /var/www 以下に必要なファイルを配置しておく必要がある。

  動的ドキュメント

/var/www/cgi-bin 以下のプログラムを実行し結果を表示させる(/var/www に chroot されるので、パスは /cgi-bin)。

server "default" {
	# :中略
	location "/cgi-bin/*" {
		fastcgi socket "/run/slowcgi.sock"
		directory no index
		root "/cgi-bin"
		request strip 1
	}
}

  動的ドキュメント その2

/var/www/cgi-bin 以下のうち、*.cgi をプログラムとしてを実行し結果を表示させる(/var/www に chroot されるので、パスは /cgi-bin)。ほかの *.html などは、通常のファイルをして返す。

server "default" {
	# :中略
	location "/cgi-bin/*.cgi" {
		fastcgi socket "/run/slowcgi.sock"
		directory no index
		root "/cgi-bin"
		request strip 1
	}
	location "/cgi-bin/*" {
		directory no auto index
		root "/cgi-bin"
		request strip 1
	}
}

CGI動作確認サンプル

  スタティックリンクプログラム

スタティックリンクされたプログラムを実行させる(ダイナミックリンクされたプログラムの場合、必要なライブラリも配置する必要があるため、ファイルサイズが大きくなるがスタティックリンクで作成する)。

プログラムソース

下記の C言語プログラムを保存する。「hello world!」という文字列と、動いた時刻、リクエスト元(環境変数)を表示させる。

bbb# cat /var/www/cgi-bin/test_cgi.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <time.h>

int main(){
	time_t now;
	char* env;

	puts("Content-Type: text/plain");
	puts("");

	puts("hello world!");

	now = time(NULL);
	printf("time is %s", ctime(&now));

	env = getenv("HTTP_HOST");
	printf("host is %s.\n", env);

	return 0;
}

ビルド

スタティックリンクでコンパイルする。

bbb# clang -o test_cgi -static test_cgi.c

確認1

chroot して実行できるか確認する。

bbb# # chroot -u www /var/www/ /cgi-bin/test_cgi
Content-Type: text/plain

hello world!
time is Tue Jul  8 12:06:43 2025
host is (null).

確認2

curl でローカルホストに接続して確認する。

bbb# curl -sv http://localhost/cgi-bin/test_cgi
* Host localhost:80 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:80...
* Connected to localhost (::1) port 80
* using HTTP/1.x
> GET /cgi-bin/test_cgi HTTP/1.1
> Host: localhost
> User-Agent: curl/8.13.0
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
< Connection: keep-alive
< Content-Type: text/plain
< Date: Tue, 08 Jul 2025 12:09:18 GMT
< Server: OpenBSD httpd
< Transfer-Encoding: chunked
<
hello world!
time is Tue Jul  8 12:09:18 2025
host is localhost.
* Connection #0 to host localhost left intact

 シェルスクリプト

sh シェルスクリプトを実行する。

プログラムソース

下記の sh シェルスクリプトを保存する。「hello world!」という文字列と、動いた時刻(date コマンド)、リクエスト元(環境変数)を表示させる。

bbb# cat /var/www/cgi-bin/test_cgi.sh
#!/bin/sh
echo "Content-Type: text/plain\n";
echo "hello world!";
echo "time is `date`";
echo "host is $HTTP_HOST";

実行環境の作成

シェルスクリプトが動くように /bin/sh と /bin/date をコピーする。

bbb# cp -p /bin/sh /var/www/bin/
bbb# cp -p /bin/date /var/www/bin/

確認1

chroot して実行できるか確認する。

bbb# # chroot -u www /var/www/ /cgi-bin/test_cgi.sh
Content-Type: text/plain

hello world!
time is Tue Jul  8 12:14:53 GMT 2025
host is

このとき、実行権限がついていないと「chroot: /cgi-bin/test_cgi.sh: Permission denied」となり、実行に必要な /bin/sh がないと「chroot: test_cgi.sh: No such file or directory」と言ったエラーメッセージが出る。また、スクリプト内で呼び出される /bin/date がないと「/cgi-bin/test_cgi.sh[4]: date: not found」と言ったワーニングメッセージがでる(スクリプトは実行される)。

確認2

curl でローカルホストに接続して確認する。

bbb# curl -sv http://localhost/cgi-bin/test_cgi.sh
* Host localhost:80 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:80...
* Connected to localhost (::1) port 80
* using HTTP/1.x
> GET /cgi-bin/test_cgi.sh HTTP/1.1
> Host: localhost
> User-Agent: curl/8.13.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Connection: keep-alive
< Content-Type: text/plain
< Date: Tue, 08 Jul 2025 12:25:30 GMT
< Server: OpenBSD httpd
< Transfer-Encoding: chunked
<
hello world!
time is Tue Jul  8 12:25:30 GMT 2025
host is localhost
* Connection #0 to host localhost left intact

 perl スクリプト

perl スクリプトを実行する。

プログラムソース

下記の perl シェルスクリプトを保存する。「hello world!」という文字列と perl ヴァージョン、動いた時刻(localtime)、リクエスト元(環境変数)を表示させる。

bbb# cat /var/www/cgi-bin/test_cgi.pl
#!/usr/bin/perl
print "Content-Type: text/plain\n\n";
print "hello world!\n";
print "perl $^V ($])\n";

my ($sec, $min, $hour, $mday, $mon, $year) = localtime;
$mon += 1;
$year += 1900;
print "time is $year-$mon-$mday $hour:$min:$sec\n";

print "host is $ENV{'HTTP_HOST'}\n";

実行環境の作成

スクリプトが動くように /usr/bin/perl と必要なライブラリ、perl モジュールをコピーする。

詳細は、下記の「CGI実行環境の作成」参照

確認1

chroot して実行できるか確認する。

bbb# chroot -u www /var/www/ ./cgi-bin/test_cgi.pl
Content-Type: text/plain

hello world!
perl v5.40.1 (5.040001)
time is 2025-7-8 12:46:4
host is
bbb#

確認2

curl でローカルホストに接続して確認する。

bbb# curl -sv http://localhost/cgi-bin/test_cgi.pl
* Host localhost:80 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:80...
* Connected to localhost (::1) port 80
* using HTTP/1.x
> GET /cgi-bin/test_cgi.pl HTTP/1.1
> Host: localhost
> User-Agent: curl/8.13.0
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
< Connection: keep-alive
< Content-Type: text/plain
< Date: Tue, 08 Jul 2025 12:46:47 GMT
< Server: OpenBSD httpd
< Transfer-Encoding: chunked
<
hello world!
perl v5.40.1 (5.040001)
time is 2025-7-8 12:46:47
host is localhost
* Connection #0 to host localhost left intact
bbb#

CGI実行環境の作成

/var/www に chroot されるので、実行バイナリや共有ライブラリなどは、/var/www/usr/bin や /var/www/usr/lib など、/var/www 以下に置いておく必要がある。また、perl モジュールなども、/var/www 以下のパスに置いておく。なお、参照される共有ライブラリは ldd コマンドで確認できる。

  perl

perl スクリプトが動くように /usr/bin/perl と必要なライブラリ、perl モジュールをコピーする。

perl のコピー

perl のバージョンと使用されている共有ライブラリの確認

bbb# whereis perl
/usr/bin/perl
bbb# /usr/bin/perl -v

This is perl 5, version 40, subversion 1 (v5.40.1) built for arm-openbsd
  :後略
bbb# ldd /usr/bin/perl
/usr/bin/perl:
        Start    End      Type  Open Ref GrpRef Name
        289e0000 28a11000 exe   1    0   0      /usr/bin/perl
        b5d23000 b6016000 rlib  0    1   0      /usr/lib/libperl.so.25.0
        a9cbe000 a9d09000 rlib  0    2   0      /usr/lib/libm.so.10.1
        ac8a8000 ac9a3000 rlib  0    2   0      /usr/lib/libc.so.100.3
        aa9a0000 aa9a0000 ld.so 0    1   0      /usr/libexec/ld.so
bbb# /usr/bin/perl -V
Summary of my perl5 (revision 5 version 40 subversion 1) configuration:
  :中略
  Built under openbsd
  @INC:
    /usr/local/libdata/perl5/site_perl/arm-openbsd
    /usr/local/libdata/perl5/site_perl
    /usr/libdata/perl5/arm-openbsd
    /usr/libdata/perl5
bbb#

プログラムと共有ライブラリをコピーする

bbb# mkdir -p /var/www/usr/{bin,lib,libexec}
bbb# cp -p /usr/bin/perl /var/www/usr/bin
bbb# cp -p /usr/lib/libperl.so.* /var/www/usr/lib
bbb# cp -p /usr/lib/libm.so.* /var/www/usr/lib
bbb# cp -p /usr/lib/libc.so.* /var/www/usr/lib
bbb# cp -p /usr/libexec/ld.so /var/www/usr/libexec

bbb# ls -lF /var/www/usr/*
/var/www/usr/bin:
total 12
-rwxr-xr-x  1 root  bin  5108 Apr 17 00:05 perl*

/var/www/usr/lib:
total 12864
-r--r--r--  1 root  bin  3232364 Jul  6 22:28 libc.so.100.3
-r--r--r--  1 root  bin   400848 Apr 16 23:54 libm.so.10.1
-r--r--r--  1 root  bin  2868348 Apr 17 00:06 libperl.so.25.0

/var/www/usr/libexec:
total 704
-r--r--r--  1 root  bin  333708 Jul  6 22:28 ld.so
bbb#
bbb# chroot -u www /var/www/ /usr/bin/perl -v

This is perl 5, version 40, subversion 1 (v5.40.1) built for arm-openbsd
  :後略
bbb#

perl モジュールのコピー

perl モジュール(と共有ライブラリ)をコピーする

bbb# mkdir -p /var/www/usr/libdata/
bbb# mkdir -p /var/www/usr/local/libdata/
bbb#
bbb# cp -p -R /usr/libdata/perl5 /var/www/usr/libdata
bbb# cp -p -R /usr/local/libdata/perl5 /var/www/usr/local/libdata
bbb#
bbb# find /var/www/usr/libdata -name \*.so -exec ldd \{\} \; | grep rlib
        b4f83000 b4fca000 rlib  0    1   0      /usr/lib/libz.so.7.1
        a64ac000 a64f7000 rlib  0    1   0      /usr/lib/libm.so.10.1
bbb# find /var/www/usr/local/libdata -name \*.so -exec ldd \{\} \; | grep rlib
bbb#
bbb# cp -p /usr/lib/libz.so.* /var/www/usr/lib

CPAN やパッケージで追加した場合、(当然だが)再度コピーし直す必要がある。

CPAN でモジュールを追加する

CPAN で、直接 /var/www 配下に入れるってどうするんだろう…

最終更新時間:2025年07月08日 21時48分42秒 指摘や意見などあればSandBoxのBBSへ。