Help us understand the problem. What is going on with this article?

LinuxでHTTPサーバー lighttpdを動かす。ビルド~cgi作成まで

More than 1 year has passed since last update.

HTTPサーバー、特にlighttpdで色々試したいことがあったので環境構築しました。
メジャーなOSSのHTTPサーバーは普及率シェア1位のApache, Nginx等ですが、何故かlighttpd。組み込み向け(?)に軽量化された面白いサーバーです。

以下3点に記事を分けて紹介していきたいと思います。今回は導入~cgiまで。
HTTPS導入によるセキュリティ強化についてはこちらの方が紹介されているので、どちらかというとQualys SSL LabsのSSL Server Testの深堀記事になると思います。

  • 導入~cgi
  • プラグイン導入の紹介
  • HTTPS導入によるセキュリティ強化

lighttpdとは

Wikipediaより

lighttpd (ライトティーピーディー; "Lighty"とも呼ばれる)は高速性の重視される環境に最適化された、安全・高速で標準に準拠し、柔軟であることを指向して設計されたWebサーバである。
メモリ消費量が少なく、CPU負荷の少ない高速動作が目的となっているため、負荷が問題な場合や、静的コンテンツを動的コンテンツと区別して送信する場合などに適しているとされる。

高機能がため肥大化しやすいHTTPサーバーにあって、安全・高速・軽量 Lightyをうたうサーバー。組み込み系の製品との通信をパケットで覗くと、たまーに見かけることがあります。

また、こちらで軽く紹介したように、Chain of Responsibilityの考え方や、FD登録によるイベント駆動があったり、マクロの使い方が面白かったリ、コードを覗くと結構面白いです。
しかも確かシングルスレッドで実現してるんですよ。それで高速が売りとなっている要素はなんだろう?その辺りも興味深いです。

公式wikiもありますので、興味がある方はどうぞ。

構築環境

Ubuntu 18.04 デスクトップ

インストール

なんと、apt installでデフォルトインストールできます!

apt install lighttpd

ただ今回はソースからインストール。バージョンはlighttpd-1.4.48にします。

ビルド~インストール

1 . ダウンロード ここから。
2 . 必要なアプリをインストール。※1

sudo apt-get install libpcre3-dev bzip2

3 . コード内で以下を実行

./configure
make
make install

結果、/usr/local/以下にアプリがインストールされます。lighttpd本体は/usr/local/sbin/にあります。
インストールはこれでOK

※1どちらも--withoutオプションで無効化は出来ますが、これで動かなかったら嫌なので今回は必要アプリも導入です。

注意:
1.4.48からかな?最新版だとopenssl用のモジュール、mod_opensslが導入されています。
ただし、こちらはデフォルト無効なのでご注意を。

起動

こんな感じ。-fで設定ファイルを指定。-Dはフォアグラウンド実行です。

sudo /usr/local/sbin/lighttpd -f /usr/local/www//lighttpd.conf -D

設定

設定ファイルのサンプルはソースのlighttpd-1.4.48/doc/config/, lighttpd-1.4.48/doc/config/conf.dに色々あります。
今回の設定をざっと説明。

最初の設定:ドキュメントルートを用意してトップページを開く

lighttpdを便利に使うための機能の一つ、プラグイン。導入方法等は別途しますが、デフォルトでも色々なプラグインが用意されています。
設定は以下のような形。最低限この二つがあればTOPページは表示できます。

lighttpd.conf
server.modules = (
        "mod_access",
        "mod_alias",
)

ドキュメントルートはserver.document-rootで設定します。

lighttpd.conf
var.server_root = "/usr/local/www/"

server.document-root        = server_root + "/html"
server.upload-dirs          = ( "/var/cache/lighttpd/uploads" )
server.errorlog             = "/var/log/lighttpd/error.log"
server.pid-file             = "/var/run/lighttpd.pid"
server.username             = "www-data"
server.groupname            = "www-data"
server.port                 = 80

index-file.names            = ( "index.php", "index.html" )

とりあえずHello Worldレベルのシンプルなものならindex.htmlが開くと思います。
でもこれだけだとindex.htmlの中にpngやjavascript等があると動作しません。

mimetypeの設定が無いと、面白いページは作れません。
コードのサンプルからそのまま持ってきましょう。

lighttpd.conf
## mimetype mapping
include "conf.d/mime.conf"
mime.conf
mimetype.assign = (
        ".pcf.Z" => "application/x-font-pcf",
        ".tar.bz2" => "application/x-gtar-compressed",
        ".tar.gz" => "application/x-gtar-compressed",
中略...
        "README" => "text/plain; charset=utf-8",
        "Makefile" => "text/x-makefile; charset=utf-8",

        # enable caching for unknown mime types:
        "" => "application/octet-stream"
)

用意されているサンプル、トータル552行分のmimetype定義!
もうmimetype定義はlighttdのmime.confで調べよう!ってレベルですね。

こちらを読み込めば、画像でもjsでもなんでも来いです!
後は設定した/usr/local/www/html配下にページを持ってくればTOPページはOK!
自分はDoxgen出力ファイルでTOPの確認しました。

cgiの設定

手軽にHTTPサーバーを活用しよう!となったらまずはcgiじゃないでしょうか?
スクリプト言語のプログラムをhttp経由で実行が可能にする機能です。

まずは設定。以下3点でOK。こちらも用意されているサンプルのconfから引っ張ってきました。

  • server.modulesにmod_cgiプラグインを導入(デフォルトで用意されています)
  • alias.urlhttp://IP/cgi-binと環境内のフォルダを紐づけ
  • cgi.assign⇒使用できる拡張子を指定
lighttpd.conf
## cgi.assign
server.modules += ( "mod_cgi" )
alias.url = ( "/cgi-bin" => "/usr/local/www/cgi-bin" )
$HTTP["url"] =~ "^/cgi-bin" {
        cgi.assign                 = ( ".cgi" => "/bin/sh",
                                       ".py"  => "/usr/bin/python3.6")
}

これでhttp://IP/cgi-bin/スクリプト名で、"/usr/local/www/cgi-bin/スクリプト名"の全スクリプトが実行されます。
(間違っても/binとかを指定しないでくださいね。)

cgi仕様

HTTPリクエスト

  • クエリ⇒環境変数のQUERY_STRINGに格納されます。
  • ボディ⇒標準入力に入力されます。

HTTPレスポンス

ヘッダー
\r\n
ボディ

の形式で標準出力すればOKです。ヘッダーを省略しても、勝手にlighttpdがContent-Type:text/plainでヘッダー追加してくれます。
簡単ですね!

サンプル1. QUERY_STRINGの使い方

※Python3.6でのサンプルです。

QUERY_STRINGは環境変数に設定されるので、こんな感じで取れます。
このサンプルではクエリをkey => valueの形式で表示させてます。
(別cgi用にhelpを出力できるようにしてます。)

show_query.py
import sys, os

query_string=os.environ.get("QUERY_STRING")

sys.path.append('..')
from util.command import show_help
command=[""]
help_str='Show query string'

if show_help([help_str] + command):
    sys.exit()

result=''
if not query_string:
    print('Empty query')
else:
    queries=query_string.split("&")
    for i, query in enumerate(queries):
        print(i,  '=>' , query)

例えば
http://IP/cgi-bin/show_query.py?test=1&test2=2でアクセスすると、こんな感じになります。

0 => test=1
1 => test2=2

サンプル2. テキスト以外のContent-Typeも使えます!

また、テキストだけではなくて別のContent-Typeも指定できます。
例えばhtmlを表示させてContent-Type: text/htmlを指定するスクリプトを書けば、html形式になります
こちらのサンプルでは、導入しているcgiのヘルプを--helpで取得して、htmlのテーブルにして返します。

help.py
import sys, re
#テーブルを作る
def create_table(fname, help_list):
    result='<tr>\n'
    result+='  <td>' + fname + "</td>\n"
    result+='  <td>' + help_list[0] + "</td>\n"
    result+='  <td> '
    for i, cmd in enumerate(help_list):
        if i == 0:
            continue
        result+=cmd + ' '
    result+='  </td>\n'
    result+='</tr>\n'
    return result

中略

help.py
#htmlべた書き
html='''<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    </head>
    <style>
    table{
      border-collapse:collapse;
      margin:0 auto;
    }
    td,th{
      padding:10px;
      border-bottom:solid #ccc;
    }
    th{
      border-bottom:5px solid #ccc;
    }
    table tr th:nth-child(odd),
    table tr td:nth-child(odd){
      background:#e6f2ff;
    }
    </style>
    <body>
      <table>
        <thead>
        <tr>
         <th>cgi name</td>
         <th>usage</td>
         <th>use system command</td>
       </tr>
       </thead>
'''
#cgi分のヘルプメッセージをテーブル化
for cgi, help_list in help_dict.items():
    html+=create_table(cgi, help_list)

html+='''
       </table>
    </body>
</html>'''

#HTTPヘッダーを表示
print("Content-Length: " , len(html))
print("Content-Type: text/html")
print("")
#HTTPボディとして作成したhtmlを表示
print(str(html))

出力はこんな感じになります。
help.png

UI関連はド素人ですが、せっかくのhtmlサンプルなのでこちらのデザインを丸パク参考にしました。
オシャレなTableデザインサンプル15点

設定・cgiサンプル

ヘルプで出しているcgiサンプル、設定ファイルは以下にコミットしています。
https://github.com/developer-kikikaikai/lighttpd_setting

導入についての感想

環境構築系はハマるイメージがあるんですが、ソース内のdoc/config/conf.dが充実している為、すんなり導入出来ました。
元々知ってるってのもありますが。lighttpdのwikiが意外とメンテされていない部分があったりするので、この充実度合いは意外でした。

また、minetypeの記載が凄い!まとめサイトでは表現しきれない充実度がありました。
いつもググって調べてたんですが、これからはこのlighttpdの設定ファイルを覗くようにしよう。

python、超楽しい!
これでクラス設計も出来るしCや他の言語との親和性もいいと聞くので、なかなか興味深いですね。

参考

参考がpython初心者の導入tipsみたいになってます

インストール時
インストール時の参考

一部cgi化した便利コマンド一覧
Linuxリソースの監視・確認に関するコマンド逆引きメモ

htmlの参考
オシャレなTableデザインサンプル15点

Pythonの参考達
・文字列、配列等基本的な情報
【Python入門】split関数で文字列の分割の仕方
Pythonらしいコードの書き方
Pythonでリスト(配列)に要素を追加するappend, extend, insert

・ファイル操作
Pythonでのファイル操作
Pythonでファイル、ディレクトリ(フォルダ)のサイズを取得

・標準コマンド実行系
python上でunixコマンドを実行する
python3のbytes型とstr型の比較と変換方法

・別pythonファイルインクルード
Pythonのimportについてまとめる

・バイナリデータ入出力(cgiでのmp4動画配信を試してみた際に調査)
バイナリデータ読み書きなど、詳細
標準出力へのバイナリモード出力(linux)

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away