さて、新しくOpenVPNのサーバを構築する事があったのでCentOS6での作業を記録。2.3.1を使うとsslが無いとか言って怒られる(OpenVPN 2.3.1のreadme等を見るに、このsslとはPolarSSLの事のようだ)のでCentOSなら当然最初から入っているOpenSSLだよねという事でさくっと2.2.2を使う事にした(手抜き)。
→2014/04/21 追記 PolarSSLだと思ったがそんな事は無かったぜ。OpenVPN 2.3.3でだが普通にCentOS6のopenssl-develでもconfigure通った。
→2017/02/07 追記 EPELにコンパイル済みのOpenVPN 2.3.14がある現在では自前で2.2.2をコンパイルする事よりそちらの使用をお勧めする。

CentOS6ではOpenVPN 2.2.2を入れるのはとっても簡単だ。yumでgccとopenssl-develとlzo-develを入れると必要なものは全部依存で入るのでその後は普通にconfigure→make→make installだ。私の好みとして/usr/local/srcにOpenVPN 2.2.2のTARボールを解凍して、/usr/local/src/openvpn-2.2.2の中でconfigure、make、make installする。rootで(手抜き)。といってもOpenVPN-2.2.2のmake installは/usr/local/sbin/openvpnコマンド、/usr/local/share/doc/openvpn、/usr/local/share/man/man8/openvpn.8の3ファイルが置かれるだけのようだ。/usr/local/src/にTARボールを解凍するのは後でmake uninstallをするかも知れないから。

デーモン化(/etc/init.d/openvpn)やeasy-rsaや設定ファイル(/etc/openvpnなどが一般的だと思う)は他にいくらでも参考サイトがあるので割愛。今回はトンネル(TUNデバイス)を用いるごく普通のVPNを構築した。

さて、肝心なところをすっ飛ばしたように見えるかも知れないが、今回この記事をしたためたのはログについて言及したかったからだ。今回も多くのサイトを参考にさせていただいたが、そこで気になったのが、大体どこもlogrotateのpostrotateでデーモンを再起動している事だ(/etc/init.d/openvpn restart)。これだとログローテートのタイミングでセッションが切れてしまうのでは? 実際試してないので分からないけれども。なので、こちらも私の好みとしてコピーして空っぽにするという方式でローテートさせる例を示す。当然logrotateやcron等は入っている事が前提。後、ログの場所は/var/log/openvpn.(/etc/openvpnの中にあるconfファイルたちの名前).logという想定。/etc/logrotate.d/openvpnという名前のファイルを作る。

/var/log/openvpn.*.log {
 copytruncate
 weekly
 rotate 10
 compress
 missingok
 create 0600 root root
}

このcopytruncateというオプションが今回の主題で、このオプションをつけると、現在デーモンがつかんでいるログファイルを別ファイル(openvpn.server.logであればopenvpn.server.log.0)にコピー(cp)した後、openvpn.server.logの中身を空にする(echo > openvpn.server.log)という動きになる。
さて、copytruncateをつけない場合だが、openvpn.server.logをopenvpn.server.log.0にリネーム(mv)した後、新たにファイルサイズが0のopenvpn.server.logを作成(touch openvpn.server.log)する。ここで何が問題になるかというと、リネームの場合、元々openvpn.server.logだったファイルのi-nodeが変わらないのだ。つまり、openvpn.server.logがopenvpn.server.log.0になるが、/usr/local/sbin/openvpnはリネームされたopenvpn.server.log.0の方にログをはき続ける。新たに作られたopenvpn.server.logはサイズが0のまま誰にも相手にされない。
すなわち、copytruncateはi-nodeを保ったままローテートしてくれるというわけだ。
CentOS6のtomcat6パッケージで導入される/etc/logrotate.d/tomcat6もこのcopytruncateでローテートしている。TomcatのネイティブデーモンであるApache Commons Daemonのバイナリjsvcは、(一般的にcatalina.outという名前で作成される)Tomcat本体のログをjsvc再起動かHUPシグナルを送るタイミングでのみつかみなおすが、どちらを選んでも全Webアプリケーションがデプロイしなおしになる。24時間動き続けるシステムの場合はこれは極めて不都合なのでこの形になっているのであろう。Redhatの人かも知れないけど、このTomcatパッケージを作った人は偉い。
ただ、copytruncateを使った時にログの取りこぼしが起きないのかは詳しく調べてない。cpとtruncateがアトミックに実行されないと、cp→ログ出力1→truncateってなったら、ログ出力1の内容がロストする理屈だよなぁ。