BikiBikiBobのチュートリアル

最もミニマリストなCMSの導入と運用

ブラウザでファイル管理

BikiBikiBobの関連ファイルをWebブラウザ上のUIで管理する方法について説明します。

BikiBikiBob Managerの機能

BikiBikiBobによるWebサイトの管理作業はsshでログインしたサーバ上で行うことを想定していますが、典型的な作業はWebブラウザから行えるように設定することもできます。具体的には、ブラウザで以下の作業ができます。

設定

Web経由のファイル管理機能を有効にするには、ファイル管理用のCGIスクリプトを設置する必要があります。ダウンロードしたリポジトリにある "bbb_manage.cgi" をCGIスクリプトが実行できるディレクトリにコピーしてください。

設置した "bbb_manage.cgi" を編集して、管理対象のファイルの置き場所のディレクトリのリストを指定します。

DATA_DIRS = [
  ("input", "/home/mikio/myblog/input", "", "/home/mikio/myblog/input/bbb.conf"),
  ("data", "/home/mikio/myblog/data", "/bikibikibob/myblog/data", ""),
]

各行で、以下の内容を書いています。管理対象のディレクトリは予め作っておき、CGIスクリプトの実行ユーザが読み書きできるパーミッションを指定してください。

典型的には、記事ファイルの置き場所のディレクトリと、画像や動画などのデータの置き場所のディレクトリを指定します。記事ファイルはWebで配信しないので第3パラメータは空文字列にします。記事ファイルを編集したらサイトに反映すべくbbb_generate.pyを実行したいので、第4パラメータには設定ファイルのパスを書きます。一方、画像などはWebサーバで配信するので、第3パラメータにはそのURLを書きます。これは管理用UIのプレビュー機能で使われます。画像などはHTMLジェネレータの対象ではないので、第4パラメータは空文字列にします。

記事に埋め込む画像のファイルは、記事のディレクトリ(myblog/input)と同じディレクトリの兄弟ディレクトリ(myblog/data)の中に置くと良いでしょう。その方がバックアップ等の管理作業が簡単になります。Webサーバの公開ディレクトリからはシンボリックリンクを貼るのが良いでしょう。

$ ln -s /home/mikio/myblog/data /home/mikio/public/bikibikibob/myblog/data

一つの管理用CGIスクリプトで複数のサイトを運営することも可能です。以下のように管理対象のディレクトリを分けて登録すれば、いくらでも対象を増やせます。Webサイトの運用と関係ない単なるアップローダとして使うことも可能です。

DATA_DIRS = [
  ("myblog-input", "/home/mikio/myblog/input", "", "/home/mikio/myblog/input/bbb.conf"),
  ("myblog-data", "/home/mikio/myblog/data", "/bikibikibob/myblog/data", ""),
  ("mywiki-input", "/home/mikio/mywiki/input", "", "/home/mikio/myblog/input/bbb.conf"),
  ("mywiki-data", "/home/mikio/mywiki/data", "/bikibikibob/mywiki/data", ""),
  ("private", "/home/mikio/private", "", ""),
]

管理用CGIスクリプトが第三者に実行されるとサイトを乗っ取られてしまうことになり、非常に危険です。よって、必ず、何らかの認証方法で管理者だけがアクセスできるように設定してください。Webサーバの機能であるBasic認証やDigest認証やPKI証明書認証を使うと良いでしょう。

使い方

まずは設置した "bbb_manage.cgi" にブラウザでアクセスしてください。認証機構を通過し、"BikiBikiBob Manager" の画面が表示されることを確認してください。

記事に埋め込む画像や動画などのファイルをWebサーバにアップロードするとして、sshやsftpでデータを送信するのが通常ですが、Webブラウザ経由でもできます。Viewコントロールで "data" ディレクトリを選んで表示してから、Uploadコントロールでファイルを指定してアップロードします。"name:assign" を選ぶと任意のファイル名をつけることもできます。

記事を更新するには、Viewコントロールで "input" ディレクトリを選んで表示してから、対象の記事の "ed" ボタンを押します。新しい記事を作るには、namingの欄で "empty file" を選んで作成してください。

記事の編集画面では、記事の書式に基づいて記事を執筆してください。事前にアップロードしておいた画像や動画のURLを指定して記事内に埋め込むのもよいでしょう。

記事を保存する際に、Generateの項目を "single" にすると、そのファイルだけを指定してHTMLジェネレータが実行されて、Webサイトが更新されます。Generateの項目を "full" にすると、全ての記事ファイルを対象にHTMLジェネレータが実行されて、Webサイトが更新されます。

編集画面の「preview」ボタンを押すと、画面が二分割されて、左側に編集用ページ、右側にプレビュー用ページが表示されます。編集用ページでGenerateを "single" または "full" にして "save" すると、右側のプレビューページも自動的に更新されます。プレビューを確認しながら編集作業を進めるにはこの方法が便利です。

以上の手順で、基本的なWebサイトの管理がブラウザ上でできるはずです。本格的な更新作業や編集作業はsshでサーバにログインして行い、ちょっとした手直しはWeb経由で行うといった使い分けをすると良いでしょう。私の場合、記事の執筆は基本的にsshでログインしてEmacsで行います。記事内に埋め込む画像や動画は "@image (bicycles)" とか "@video (waterfall)" とかいうプレースホルダを書いておいて、とりあえず本文を完成させて保存します。その後、埋め込む画像のアップロードはWeb経由で行った上で、Web UIの編集機能で画像や動画のURLをプレースホルダの部分にコピペして記事を完成させます。公開後に気づいたちょっとした修正ならスマホからWeb UIで行うこともあります。

機能詳細

画面上部の操作用パネルにおいて、Viewの行はどのディレクトリを操作対象とするか指定するのに用います。"dir:" で始まる項目には、設定で書いたラベルが表示されます。"order:" で始まる項目では、ディレクトリの中に含まれるファイルの表示順序を指定️します。デフォルトでは最近更新されたファイルが上に来るようになっています。これらの項目の内容を変更したら、それを表示に反映させるために "view" ボタンを押してください。"view" ボタンを押すまではディレクトリを変更する効果がないことには留意してください。

Uploadの行は新しくファイルを作成する際に用います。"Choose file" の項目を押すとローカルのファイルを指定するダイアログが開くので、そこでアップロードしたいファイルを選んでください。"name:" で始まる項目は、サーバ上でのファイル名の付け方を指定します。"name:local" の場合、ローカルのファイル名が使われます。"name:date" の場合、現在時刻がファイル名として使われます。"name:assign" の場合、任意のファイル名がつけられます。"empty file" の場合、ファイルの指定は無視して、空のファイルを作ります。その際は "name:assign" と同様に、任意のファイル名をつけます。新しい記事を作成する場合には、"empty file" を指定するとともに、".art" で終わる名前のファイルを作ってください。"overwrite:" で始まる項目は、同じファイル名のファイルが存在した場合の挙動を指定します。"overwrite:stop" だと、古いファイルを更新せずに諦めます。"overwrite:rename" だと、"_2" などの接尾辞をつけて上書きを回避します。"overwirte:force" だと古いファイルを新しいファイルの内容で上書きします。

一覧表示の個々のファイル名をクリックすると、そのファイルの内容を表示します。設定で外部URLを指定したディレクトリのファイルではファイルの外部URLを使ってデータが表示されます。そうでないディレクトリのファイルの内容は "bbb_manage.cgi" がプロクシとしてデータを送信します。記事に埋め込むデータは外部URLを持つべきであり、そのアドレスをコピーして記事に書くことになるでしょう。

記事ファイルを始め、テキストファイルに関してはブラウザ上で内容を編集することができます。"ed" ボタンを押すと編集画面が開きます。".art"で終わる記事ファイルに関しては、"Generate:" という項目が現れるので、そこで "no" 以外を選ぶと、"bbb_generate.py" を動かして、記事の内容をHTMLファイルに反映します。"single" ならそのファイルだけを更新して、"full" なら全てのファイルを更新します。記事の内容の執筆中は "single" で出力を作ってプレビューをすると良いでしょう。記事が書き終わったら、"full" で出力を作ってインデックス等に反映させると良いでしょう。

"bbb.conf" で "hoard_target_url" などの項目を設定した場合、記事の編集画面に "Hoard:" という項目が現れます。記事中の@imageや@video命令で対応サービスのURLを記述した場合、"Hoard" にチェックをすると、指定したデータをサーバ上に貯蔵した上でURLを書き換えます。

ファイルを消したい場合、各ファイルの "rm" ボタンを押してください。確認画面が出るので、そこで "remove" を選択するとそのファイルはサーバ上から消されます。

Web UIでテキストファイルを編集する際には、編集前にMD5のダイジェストが取得され、書き込み時に現在のファイル内容のダイジェストと一致するかが検査されます。もし編集中に別の人が同じファイルを編集した場合は、ダイジェストが一致しないので、更新に失敗して、その旨が警告されます。その際には別ウインドウで編集画面を開いて、自分の変更をマージする作業を行なってください。

設定詳細

設置した "bbb_magage.cgi" の中の冒頭に設定すべきパラメータがいくつかあります。多くはデフォルトのままで良いでしょうが、必要に応じて適宜変更してください。

# 記事の更新で使われるジェネレータ。
# コマンド実行パスが通っていない場合は絶対パスを書くと良い。
BBB_GENERATE_COMMAND = "bbb_generate.py"

# 1ページに表示されるファイルの数。
NUM_FILES_IN_PAGE = 100

# 個々のファイルの最大サイズの制限。
MAX_FILE_SIZE = 1024 * 1024 * 256

# 個々のディレクトリのファイルサイズの合計の制限。
MAX_TOTAL_FILE_SIZE = 1024 * 1024 * 1024 * 16

# 個々のディレクトリの中におけるファイル数の制限。
MAX_NUM_FILES = 8192

# Web上で編集するテキストファイルの最大文字数。
MAX_TEXT_SIZE = 1024 * 1024 * 4

# 表示も更新も削除もできないファイル名の正規表現のリスト。
# 間違って更新すると困るファイルはここで指定すると良い。
IGNORE_FILENAME_REGEXES = [
  r"^\.", r"\.(cgi)$", r"^(bbb)\.",
]

繰り返しになりますが、これらの制限を施したところで、"bbb_manage.cgi" が悪意の第三者に実行されると壊滅的なことになります。よって、Webサーバの設定で保護することが絶対に必要です。また、一連の設定がうまく働いていることを確認するために、適当にサンドボックス的なサイトを運用してみてから、本番のサイト運用に着手した方が良いでしょう。

Webサーバの設定

CGIスクリプトが実行できるWebサーバであれば、その実行ユーザを任意のユーザに変更する機能がついていますが、その設定は若干面倒くさいことが多いです。それよりは、Webサーバ自体の実行ユーザをそのサイト専用のもの(wwwとか)にした方が楽です。また、個別のディレクトリに設定ファイルを置いて細かいアクセス制御ができるようにした方が楽です。Apache2であれば、設定ファイル(/var/apache2/apache2.confとか)に以下のように書きます。

User www
Group www

AddHandler cgi-script .cgi

AccessFileName .htaccess
<FilesMatch "^\.ht">
  Require all denied
</FilesMatch>
<Directory />
  Options FollowSymLinks
  AllowOverride None
  Require all denied
</Directory>

"bbb_manage.cgi" を設置するディレクトリには、以下のような内容の ".htaccess" ファイルを置いて、認証されたユーザしかアクセスできないようにします。ここで使うBasic認証はパスワードを平文で流すので、必ずSSL(HTTPS)でサーバを運用してください。

<Files "bbb_manage.cgi">
  AuthType Basic
  AuthName "Private"
  AuthUserFile /home/www/.htpasswd
  Require valid-user
</Files>

パスワードファイルを作るには、以下のようなコマンドを実行します。これは "admin" という認証ユーザのパスワードを "/home/www/.htpasswd" に保存します。パスワードの文字列はコマンド実行時に聞かれます。

$ sudo -u www htpasswd -c /home/www/.htpasswd admin

Apache2以外のWebサーバでも、考え方は一緒です。Webサーバの実行ユーザを専用のものにして、CGIを実行可能にして、ディレクトリ毎にアクセス制御ができるようにして、そして "bbb_manage.cgi" に認証によるアクセス制御をかけるということです。

データのバックアップ

Web経由でのファイル管理に限ったことではありませんが、システム管理では、必ず運用ミスや故障などの不測の事態が発生するものです。よって、絶対に絶対に絶対に、定期的にバックアップを取りながら運用しましょう。BikiBikiBobのデータは全て単なるファイルなので、バックアップ作業は極めて単純です。対象のディレクトリの中身をtar.gzに固めてからどこぞに転送するか、面倒なら単にscpやsftpで転送すればコマンド一発で済みます。

世に公開しても大丈夫なデータであれば、GitHub上のリポジトリとして管理するという手もあります。sshでもWeb経由でも普通にファイルを管理した上で、区切りの良い頃合いで差分を全部コミットしてしまえば良いでしょう。

$ cd /home/mikio/myblog
$ git add input/*.art
$ git rm $(git ls-files input --deleted)
$ git add data/*
$ git rm $(git ls-files data --deleted)
$ git commit -m "periodical update."
$ git push

コメントファイルには投稿者のIPアドレスが書いてあるので、そのままGitHubに上げると問題が起こるかもしれません。敢えてGitHubで管理するなら、IPアドレスをダミーに置換したデータを作ってそれを上げるのが無難です。

$ mkdir -p comment-annon
$ rm -f comment-annon/*.cmt
$ ls comment/*.cmt | sort |
  while read old_file
  do
    new_file="comment-annon/$(basename $old_file)"
    sed -e 's/^\(.*\)\t\(.*\)\t\(.*\)\t\(.*\)$/\1\t-\t\3\t\4/' "$old_file" > "$new_file"
  done
$ git add comment-annon/*.cmt
$ git commit -m "periodical comment update."
$ git push

一連のコマンドをシェルスクリプトにしてしまえば、やはりコマンド一発でバックアップが完了します。バックアップ用のストレージ環境を別途用意しなくて済むというのは大きな利点です。

チュートリアル インストール
comments
----
name:
text: