Setup

Author

gentam

Date
2017-09-06
Category

log

Tag

rst, publicfile, freebsd

Updated

2018-07-01

このサイトを書いて,Webに公開するまでの説明と作業ログ.

Updates:

Contents

Document setup

SCRIPT  = update
VPATH   = docs
SOURCES = $(wildcard $(VPATH)/*.rst)
TARGETS = $(SOURCES:.rst=.html)

%.html: %.rst style.css
        $(SCRIPT) $<

all: $(TARGETS)

push: all
        $(SCRIPT) push

(2018-07-01) シェルスクリプト内で更新が必要なファイルのチェックを行っていたのを, Makefileの依存関係へ分けた.

#!/usr/bin/env bash

usage() {
    echo "Usage: `basename "$0"` source.rst"
    echo "       `basename "$0"` (push|pull|diff) hostname"
}

[ $# -eq 0 ] && usage && exit 1

if [ $# -eq 2 ]; then
    tdir='docs'
    case $1 in
        "pull") rsync -avz  --delete $2:$tdir/ docs ;;
        "push") rsync -avz  --delete docs/ $2:$tdir ;;
        "diff") rsync -navz --delete docs/ $2:$tdir ;;
             *) usage; exit 1 ;;
    esac
    exit 0
fi

[ ! -f $1 ] && echo "No such file: $1" \
            && exit 1

cd "`dirname "$0"`/docs"
rst="`basename $1`"
html="${rst%.*}.html"

meta='1i\.. meta::\n   :viewport: width=device-width, initial-scale=1\n'
author='1,20s/^:Author:\s+gentam$/:Author: `gentam <https:\/\/gent.am\/about.html>`_/'
updated="1,20s/^:Updated:\s+(.*)\$/:Updated: \`\1 <https:\/\/github.com\/gentam\/m\/commits\/master\/docs\/${rst}>\`_/"
footer="\$a\\\n.. footer:: | \`Top <https://gent.am>\`_ / \`Twitter <https://twitter.com/_gentam>\`_ / \`GitHub <https://github.com/gentam>\`_ / \`Source <https://github.com/gentam/m/blob/master/docs/${rst}>\`_"

sed -E \
    -e "$meta" \
    -e "$author" \
    -e "$updated" \
    -e "$footer" \
    "$rst" \
  | tee ../tmp | rst2html5.py --config='../rst.conf' > "$html"

# image lazy-loading
if grep -Fxq '.. :lazyload: image' "$rst"; then
    echojs='9i\<script src="https://cdn.jsdelivr.net/npm/echo-js@1.7.3/src/echo.min.js"></script><script>echo.init()</script>'
    img='s/<img (.*)src=(".*") /<img \1src="data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-echo=\2 /g'

    sed -Ei -e "$echojs" -e "$img" "$html"
fi

(2018-05-15) 画像を多めに貼った授業ノートを作ったので,画像が画面に表示されるま では読み込まなれないようにもできるようにした. 具体的には .. lazyload: image があるファイルでは Echo.js をロードしたうえで img タグを <img src="data:image/gif;base64,..." data-echo="/path/to/file"> に書き換えるている.

ディレクトリ構成:

m
├── docs
│   ├── ...
│   ├── r
│   │   ├── ...
│   │   └── processing.min.js
│   ├── index.html
│   ├── index.rst
│   └── style.css
├── private
│   ├── ...
│   └── memo.rst
├── Makefile
└── update

こうしてファイルが単純に公開されているため,URLの *.html*.rst にすれ ば reST のソースが見られる.

reST ソースでの改行が日本語の文章中に,半角スペースとして入ってしまうのを防ぐた めに,最初は awk で pre タグ以外を改行なしで出力するみたいなハックをしていた. しかし,最近 Firefox をメインのブラウザとして使うようになってから,改行文字の前 後が日本語だったら半角スペースなしで表示してくれるようになっていることに気付いた ので,そのまま出力することにした.というわけなので読んでいて半角スペースが気にな る場合は,最新の Firefox を使ってもらえると.

将来的にメモが増えすぎたら,カテゴリーとか日付でサブディレクトリに分けることも考 えるかもしれない.そうなるとSphinx,あるいはJekyll,Hugo,Hexoみたいなのを使えば いいのだろうが,構成はミニマルにしたいし,ツールの使い方を学んだりバージョンアッ プ(開発言語含む)に対応しなければいけない時間を考えると,当分はこのスクリプトをい じりながらやっていくつもり.

Server setup

Note

GitHub Pages へ移行したので以下のメモは多分更新されません.

このサイトのホスト環境セットアップについての情報.Linux + Apache という環境のセ ットアップは過去に何度もやったことがあったので,あえてややマイナーなツールで構成 してみている.

For HTTPS:

方針として,HTTPSもちゃんと対応はするがHTTPへのリクエストをリダイレクトはせず, HTTPで返すようにする.

80番ではVarnishが待ち受け,443番ではHitchが待ち受けている.HTTPS接続した場合は, HitchがSSL終端をしてからVarnishのプロキシモードのポートにつなぎ,バックエンドの publicfileへ送られる.

以下コマンドメモ.順番は適当

FreeBSD

LinuxとFreeBSDの違いについてのブログを読んでから,なんとなくFreeBSDに惹かれてい たので,今回使ってみることにした.実際使って見てパッケージ管理システムとして, portpkg がOS標準で用意されているのはすごくいいなと思った. あと,ファイルのヒエラルキーでユーザ関連のものは /usr/local/ 下にまとまって るのもいい.

(1)
# adduser
# vi /etc/ssh/sshd_config
% mkdir .ssh
% vi .ssh/authorized_keys
    -> add public key
% vi .login.conf
    me:\
        :charset=UTF-8:\
        :lang=en_US.UTF-8:

# freebsd-version
# freebsd-update fetch
# freebsd-update install
# reboot
# crontab -e
    @daily freebsd-update cron

# portsnap fetch
# portsnap extract
# pkg install portmaster
# ...

Upgrading FreeBSD

(2017-11-19)

11.0-RELEASE が 2017-11-30にEoLになる みたいなので,11.1-RELEASEへアップグレードした. 11.1用のAMI があったので,そっちで新しいインスタンスを作るか迷ったが,11.0から問題なく アップグレードできた.

# freebsd-version
    11.0-RELEASE-p15
# freebsd-update -r 11.1-RELEASE upgrade
# freebsd-update install
# reboot
# freebsd-update install
# pkg-static upgrade -f
# portsnap auto
# portmaster -af
    Major updateのときにはABIが変更されて昔インストールしたパッケージが使え
    なくなるので,pkgとportを全て更新,再インストールする
# freebsd-update install
# reboot
# freebsd-version
    11.1-RELEASE-p4

FreeBSD Handbook: Updating details <https://www.freebsd.org/doc/handbook/updating-upgrading.html>

publicfile

publicfileはdjbによるセキュアでミニマルなHTTP/FTPファイルサーバ.名前の通り,た だファイルを公開するという機能しかない.ただ,だからこそいろんな設定や動的なファ イル関連のセキュリティのことは気にしなくていい:

(2)
# cd /usr/ports/www/publicfile
# make config
    -> change some config
# make install
    -> also installs ucspi-tcp and daemontools
# pw groupadd pubfile
# pw useradd pubfile -g pubfile -d /nonexistent -s /usr/sbin/nologin
# cat /etc/groups

(4)
# mkdir /var/public
# which configure
# configure pubfile multilog /var/public example.com 12.34.56
# chown user:user /var/public/file/0
# ln -s /var/public/file/0 /home/user/public

References:

daemontools

djbのプロセス管理ツール.自分は /var/service をrc.dの代替的にして,runスク リプトを置いている.

(3)
# pw groupadd multilog
# pw useradd multilog -g multilog -d /nonexistent -s /usr/sbin/nologin
# mkdir -p /var/multilog/httpd
# cat /var/service/httpd/log/run
    #!/bin/sh
    exec setuidgid multilog multilog t /var/multilog/httpd '-*' '+* * status: *' =status

(5)
# ln -s /var/public/httpd /var/service
# vi /etc/rc.conf
    svscan_enable="YES"
    svscan_servicedir="/var/service"
    svscan_logdir="/var/multilog"

    (svscan rc script is located in /usr/local/etc/rc.d/svscan)

# reboot
# svstat /var/service/httpd
# ps aux | grep supervise

(停止と起動)
# svc -d /var/service/httpd
# svc -u /var/service/httpd

(ログ)
# tail -F /var/multilog/httpd/current | tai64nlocal

Varnish

そもそもテキストだけのこんなサイトにキャッシュサーバを用意するのはどう考えても過 度だが,単純に使ってみたかったからやってみた.

# pkg install varnish
# cp /usr/local/share/doc/varnish/example.vcl /usr/local/etc/varnish/default.vcl
# mkdir /usr/local/etc/varnish
# vim /usr/local/etc/varnish/default.vcl

  vcl 4.0;
  backend default {
      .host = "127.0.0.1";
      .port = "8080";
  }
  sub vcl_recv {
      # Strip query string, because publicfile cannot handle it
      if (req.url ~ "\?.*$") {
        set req.url = regsub(req.url, "\?.*$", "");
      }
  }
  sub vcl_deliver {
      # Remove unnecessary headers:
      unset resp.http.Server;
      unset resp.http.X-Varnish;
      unset resp.http.Via;

      return (deliver);
  }

# mkdir /var/service/varnish
# vim /var/service/varnish/run

  #!/bin/sh
  exec varnishd -F -a :80 \
          -a localhost:81,PROXY \
          -T localhost:6082 \
          -f /usr/local/etc/varnish/default.vcl \
          -s malloc,256m

# svstat /var/service/varnish

publicfile はURLのクエリーストリングを認識できないようでページのリンクに ?ref=link-source みたいなのをつけられると404を返してしまう. そこで vcl_recv の中でストリップしている.

VCLの例は mattiasgeniar/varnish-4.0-configuration-templates が参考になる.

詳細:

後半はdaemontoolsの設定.

-F

supervise するために,forkしてバックグラウンド実行しないようにする

-a

80番ポートで動かす

-a

81番ポートでhitchのバックエンドとしてプロキシプロトコルで動かす

-T

管理用のポート.varnishadm コマンドでつながる.

-f

設定VCLファイル

-s

キャッシュストレージの設定.ファイルとかにもできる

バックエンドは -b で指定できるが -f と排他的なので.localhost:8080で動い ているpublicfileは,default.vcl で設定してある.

Let's Encrypt

Certbot か acme.sh か迷ったが,あくまで公式に推奨されているCertbotにした. 2018-04-13 時点では certbot のデフォルトエンドポイントはまだACME-v01なので,ワ イルドカード証明書を取るには手動でV2の方を設定しないといけない.

# pkg install py27-certbot
# certbot certonly --manual \
-d gent.am -d "*.gent.am" \
-m メールアドレス \
--preferred-challenges dns \
--server https://acme-v02.api.letsencrypt.org/directory \
--agree-tos \
--manual-public-ip-logging-ok

# crontab -e
  ...
  @daily python -c 'import random; import time; time.sleep(random.random() * 3600)' && certbot renew --renew-hook="/root/bin/hitch-renew-hook.sh" --post-hook="service hitch restart"

参考: Certbot documentation <https://certbot.eff.org/docs/>

(2018-07-01) 上のcrontabの設定は間違っていた.マニュアルオプションで設定した証明 書は, certbot renew できないので --manual-auth-hook を設定しないといけ ない.使ってるDNSベンダーのプラグインが存在しなくて,TXTレコードを更新できるAPI も提供していない場合は certonly のコマンドを手作業でやり直さないといけないっ ぽい.

Hitch

Varnish としてはSSLに対応していないので,HitchというSSL終端だけに特化したプロキ シサーバをかませることでHTTPS対応をする.

これで単一機能に特化したHitchとVarnish,publicfileをそれぞれ繋げて1つのシステム として機能させることができる.他のデーモンと同じくsuperviseで管理しようとしたが ,hitchが起動してすぐにバックグラウンドに入るようになっているためにsuperviseでう まく動かなかった.(fghackも使ってみたが...) そのため,普通に service コマンドで管理している.

# pkg install hitch
# openssl dhparam -rand - 2048 | tee /usr/local/etc/letsencrypt/live/gent.am/dhparams.pem
# vim ~/bin/hitch-renew-hook.sh

  #!/bin/sh
  certs=/usr/local/etc/letsencrypt/live/gent.am
  dhparams=${certs}/dhparams.pem

  umask 077
  cat ${certs}/privkey.pem \
  ${certs}/fullchain.pem \
  ${dhparams} > ${certs}/hitch-bundle.pem

# vim /usr/local/etc/hitch.conf
  ...
  frontend       = "[*]:443"
  backend        = "[127.0.0.1]:81"
  pem-file       = "/usr/local/etc/letsencrypt/live/gent.am/hitch-bundle.pem"
  write-proxy-v2 = on
  ...

# mkdir /usr/local/etc/hitch
# chmod 755 /usr/local/etc/rc.d/hitch
# vim /usr/local/etc/rc.d/hitch
  ...
  command_args="--daemon -u varnish -g varnish -s --config=${hitch_config} --ocsp-dir=/usr/local/etc/hitch"
  # このoscp-dirは指定しないとwarningが出たので,よくわからずにつけている.
  ...

# vim /etc/rc.conf
  ...
  hitch_enable="YES"

# service hitch start
# reboot

参考: Let's Encrypt with Hitch and Varnish (CentOS7) <https://docs.varnish-software.com/tutorials/hitch-letsencrypt/>