wandboxを自前サーバに一般ユーザーで導入する方法


wandboxを使う情報はたくさん見つかるのに，導入したという情報はあまりみつからないのでメモ．

以下を参考にしました．

- [[obsolete] Wandboxを確実に導入する](http://qiita.com/cielavenir/items/4ad39f10b3b78b661526)
- [wandbox provisioner at githubgist](https://gist.github.com/cielavenir/f72ae830d3b6ad80240d)
- [wandbox chef recipe](https://github.com/melpon/chef-melpon.org/blob/master/site-cookbooks/wandbox/recipes/default.rb)
- [wandbox kennel2 README](https://github.com/melpon/wandbox/blob/master/kennel2/README.rst)

上記を参考にしたうえで，

- ポリシー１：（ほぼ）すべて一般ユーザーでビルド・インストールを行う．
仮想環境など手軽に使えるものがあるのに，一般ユーザーでクリーンに導入する意味はそんなにありません．どんな動作をするのかという勉強のためです．
- ポリシー２：手動で行う．
上記chef recipeもありますが，そのまま動かない（kennel2しかないのにkennelが残っている，とか）．ということで，これもどんな動作をするのかという勉強のためです．
- ポリシー３：最小限にする
全部のコンパイラはいらないので，Cだけ．


環境

- Ubuntu 14.04LTS on virtual box
- 前提：ユーザー名tamakiで，/home/tamaki/wandbox/以下でビルド，/home/tamaki/local/以下にいろいろインストールする．


# 準備1
```sh:準備
cd
mkdir local
mkdir wandbox
cd wandbox
```

# 準備2
```sh:必要なパッケージのインストール
sudo apt-fast install gcc cmake libpcre3-dev zlib1g-dev libgcrypt11-dev libicu-dev libsqlite3-dev libboost-all-dev libcap-dev automake libboost-all-dev git
```
とりあえずwandboxではgccだけ使いたいので，gccは入れておく．
clangなどが欲しいならそれを入れておく．


# CppDB

wandbox/cppdb/以下にclone，
wandbox/cppdb_build/以下でビルド．

```sh:cppdbのビルド・インストール
git clone https://github.com/melpon/cppdb.git
mkdir cppdb_build
cd cppdb_build
cmake ../cppdb/ -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/home/tamaki/local/ -DDISABLE_MYSQL=ON -DDISABLE_PQ=ON -DDISABLE_ODBC=ON -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ 
make -j 8
make install
cd ..
```
gcc/g++指定は，clangが入っていると曖昧になるため．


# CppCMS

wandbox/cppcms/以下にclone，
wandbox/cppcms_build/以下でビルド．

```sh:ccpcmsのインストール
git clone https://github.com/melpon/cppcms.git
mkdir cppcms_build
cd cppcms_build
cmake ../cppcms/ -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/home/tamaki/local/ -DDISABLE_SHARED=ON -DDISABLE_FCGI=ON -DDISABLE_SCGI=ON -DDISABLE_ICU_LOCALE=ON -DDISABLE_TCPCACHE=ON -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ 
make -j 8
make install
cd ..
```
gcc/g++指定は，clangが入っていると曖昧になるため．


# wandbox

wandbox/wandbox/以下にclone
wandbox/wandbox/cattleshed/以下でにcattleshedをビルド

## cattleshed

```sh:wandbox/cattleshed
git clone https://github.com/melpon/wandbox.git
cd wandbox/cattleshed
sh configure --prefix=/home/tamaki/local
aclocal
automake
make
make -k install
cd ..
```

make install時に「一般ユーザー権限ではsetcapができない」とエラーが出るので，setcapだけsudoで行う．

```sh:
sudo setcap cap_sys_admin,cap_sys_chroot,cap_mknod,cap_net_admin,cap_sys_rawio,cap_sys_module=p  /home/tamaki/local/bin/cattlegrid
```

## kennel2

```sh:wandbox/kennel2/
cd wandbox/kennel2/
./autogen.sh 
./configure --prefix=/home/tamaki/local/ --with-cppcms=/home/tamaki/local/ --with-cppdb=/home/tamaki/local/
make
make install
```

ちょっと修正．

```diff:kennel.json.diff
--- /home/tamaki/wandobox/wandobox/kennel2/kennel.json	2016-05-02 12:09:56.473766195 +0900
+++ /home/tamaki/local/etc/kennel.json	2016-04-30 22:42:17.531696000 +0900
@@ -3,7 +3,7 @@
     , "static_dir": "/home/tamaki/local/etc/static"
     , "scheme": "http"
     , "domain": "melpon.org"
-    , "map_root": "/wandbox"
+    , "map_root": ""
     , "dispatch_root": ""
     , "cattleshed":
         { "host" : "127.0.0.1"
```


# 後処理・設定

現状では，/home/tamaki/local/以下にいろいろインストールされている．

## etc/cattleshed.confの書換え

ポイント

- storedirの書き換え：
- mountディレクトリの書き換え：自分のシステムに存在しない/lib32などは削除
- `--nproc`を増やす：普通は必要ないのだろうけれども，個人的にはこれにハマった

```diff:cattleshed.conf.diff
--- /home/tamaki/wandbox/wandbox/cattleshed/cattleshed.conf	2016-04-30 22:39:06.627696000 +0900
+++ /home/tamaki/local/etc/cattleshed.conf	2016-05-01 23:15:14.755396535 +0900
@@ -3,7 +3,7 @@
   "listen-port":2012,
   "max-connections":32,
   "basedir":"/tmp/wandbox",
-  "storedir":"/var/log/wandbox/ran",
+  "storedir":"/home/tamaki/local/var/log/wandbox/ran",
  },
  "jail":{
   "":{
@@ -18,11 +18,11 @@
     "--data=134217728",
     "--fsize=134217728",
     "--nofile=256",
-    "--nproc=256",
+    "--nproc=1024",
     "--",
     "/home/tamaki/local/bin/cattlegrid",
     "--rootdir=./jail",
-    "--mount=/bin,/etc,/lib,/lib32,/lib64,/usr/bin,/usr/lib,/usr/lib64,/usr/include,/usr/local,/usr/share/perl",
+    "--mount=/bin,/etc,/lib,/lib64,/usr/bin,/usr/lib,/usr/include,/usr/local,/usr/share/perl",
     "--rwmount=/tmp=./jail/tmp,/home/jail=./store",
     "--devices=/dev/null,/dev/zero,/dev/full,/dev/random,/dev/urandom",
     "--chdir=/home/jail",
@@ -50,7 +50,7 @@
     "--",
     "/usr/local/cattleshed/bin/cattlegrid",
     "--rootdir=./jail",
-    "--mount=/bin,/etc,/lib,/lib32,/lib64,/usr/bin,/usr/lib,/usr/lib64,/usr/include,/usr/local,/usr/share/perl",
+    "--mount=/bin,/etc,/lib,/lib64,/usr/bin,/usr/lib,/usr/include,/usr/local,/usr/share/perl",
     "--rwmount=/tmp=./jail/tmp,/home/jail=./store",
     "--devices=/dev/null,/dev/zero,/dev/full,/dev/random,/dev/urandom",
     "--chdir=/home/jail",
@@ -77,7 +77,7 @@
     "--",
     "/home/tamaki/local/bin/cattlegrid",
     "--rootdir=./jail",
-    "--mount=/bin,/etc,/lib,/lib64,/usr/bin,/usr/lib,/usr/lib64,/usr/include,/usr/local",
+    "--mount=/bin,/etc,/lib,/lib64,/usr/bin,/usr/lib,/usr/include,/usr/local",
     "--rwmount=/tmp=./jail/tmp,/home/jail=./store",
     "--devices=/dev/null,/dev/zero,/dev/full,/dev/random,/dev/urandom",
     "--chdir=/home/jail",
```

storedirに設定したディレクトリの作成

```sh:storedir
mkdir /home/tamaki/local/var/log/wandbox/ran/
```


## etc/cattleshed.conf.d/compilers.defaultの書換え

必要なコンパイラだけを記述．デフォルトでは全てのコンパイラ・インタプリタがシステムにインストールされていることを前提としているので，そのままでは

- デーモン起動時にエラーになる
- 全部入れる

のどちらか．そこでcompilers.defaultを書き換える．ちょっと長いけど以下．

```ruby:local/etc/cattleshed.conf.d/compilers.default
{
    "switches": {

        "c89": {
            "conflicts": [
                "c89", 
                "c99", 
                "c11", 
            ], 
            "display-name": "C89", 
            "flags": [
                "-std=c89"
            ]
        }, 
        "c99": {
            "conflicts": [
                "c89", 
                "c99", 
                "c11", 
            ], 
            "display-name": "C99", 
            "flags": [
                "-std=c99"
            ]
        }, 
        "c11": {
            "conflicts": [
                "c89", 
                "c99", 
                "c11", 
            ], 
            "display-name": "C11", 
            "flags": [
                "-std=c11"
            ]
        }, 
        "warning": {
            "display-name": "Warnings", 
            "flags": [
                "-Wall", 
                "-Wextra"
            ]
        }, 
        "optimize": {
            "display-name": "Optimization", 
            "flags": [
                "-O2", 
                "-march=native"
            ]
        }, 
        "boost-nothing": {
            "conflicts": [
                "boost-nothing", 
                "boost-1.54" 
            ], 
            "display-name": "Don't Use Boost", 
            "flags": [], 
            "display-flags": ""
        }, 
        "boost-1.54": {
            "conflicts": [
                "boost-nothing", 
                "boost-1.54" 
            ], 
            "display-name": "Boost 1.54.0", 
            "flags": [
                "-I/usr/include", 
                "-I/usr/include/boost", 
                "-L/usr/lib", 
                "-L/usr/lib/x86_64-linux-gnu",
                "-Wl,-rpath,/usr/lib/x86_64-linux-gnu", 
                "-lboost_wserialization", 
                "-lboost_math_tr1f", 
                "-lboost_math_c99l", 
                "-lboost_math_tr1", 
                "-lboost_locale", 
                "-lboost_wave", 
                "-lboost_regex", 
                "-lboost_prg_exec_monitor", 
                "-lboost_atomic", 
                "-lboost_signals", 
                "-lboost_math_c99f", 
                "-lboost_context", 
                "-lboost_program_options", 
                "-lboost_coroutine", 
                "-lboost_serialization", 
                "-lboost_filesystem", 
                "-lboost_system", 
                "-lboost_timer", 
                "-lboost_log_setup", 
                "-lboost_random", 
                "-lboost_chrono", 
                "-lboost_exception", 
                "-lboost_iostreams", 
                "-lboost_thread", 
                "-lboost_date_time", 
                "-lboost_math_c99", 
                "-lboost_math_tr1l", 
                "-lboost_graph", 
                "-lboost_log"
            ], 
            "display-flags": "-I/usr/include/boost"
        }, 
    }, 

    "compilers": [

        {
            "switches": [
                "warning", 
                "optimize", 
                "boost-nothing",
                "boost-1.54",
                "c89", 
                "c99", 
                "c11"
            ], 
            "initial-checked": [
                "warning", 
                "c99",
                "boost-nothing"
            ], 
            "compile-command": [
                "/usr/bin/gcc", 
                "-oprog", 
                "prog.c"
            ], 
            "name": "gcc", 
            "language": "C", 
            "output-file": "prog.c", 
            "compiler-option-raw": true, 
            "displayable": true, 
            "run-command": "./prog", 
            "display-compile-command": "gcc -o prog prog.c", 
            "display-name": "gcc", 
            "version-command": [
                "/usr/bin/gcc", 
                "-dumpversion"
            ]
        }

    ]

}
```

ポイント

- 最初"switch"セクションと
- 次の"compliers"セクションを編集
 - 使わないものは削除
 - 必要なものだけを残して，コンパイラのパスを変更



## htmlのtitle変更

```diff:title変更
diff --git a/kennel2/src/root.tmpl b/kennel2/src/root.tmpl
index 4e7c34b..1e383be 100644
--- a/kennel2/src/root.tmpl
+++ b/kennel2/src/root.tmpl
@@ -12,7 +12,7 @@
   <head>
     <meta charset="UTF-8">
 
-    <title>[Wandbox]三へ( へ՞ਊ ՞)へ ﾊｯﾊｯ</title>
+    <title>[Wandbox]</title>
     <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
     <meta name="description" content="Wandbox is Online Compiler">
     <meta name="author" content="melpon, kikairoya">
diff --git a/kennel2/src/nojs_list.tmpl b/kennel2/src/nojs_list.tmpl
index 3cbca4e..0a2675c 100644
--- a/kennel2/src/nojs_list.tmpl
+++ b/kennel2/src/nojs_list.tmpl
@@ -12,7 +12,7 @@
   <head>
     <meta charset="UTF-8">
 
-    <title>[Wandbox]三へ( へ՞ਊ ՞)へ ﾊｯﾊｯ</title>
+    <title>[Wandbox]</title>
     <meta name="description" content="Wandbox is Online Compiler">
     <meta name="author" content="melpon, kikairoya">
 
diff --git a/kennel2/src/nojs_root.tmpl b/kennel2/src/nojs_root.tmpl
index bf6bfe4..c2b18b0 100644
--- a/kennel2/src/nojs_root.tmpl
+++ b/kennel2/src/nojs_root.tmpl
@@ -12,7 +12,7 @@
   <head>
     <meta charset="UTF-8">
 
-    <title>[Wandbox]三へ( へ՞ਊ ՞)へ ﾊｯﾊｯ</title>
+    <title>[Wandbox]</title>
     <meta name="description" content="Wandbox is Online Compiler">
     <meta name="author" content="melpon, kikairoya">
 
```


# 実行！

## デーモンの起動

cattle shedとkennelの2つを起動する．

```sh:起動1
$ export LD_LIBRARY_PATH=/home/tamaki/local/lib
$ /home/tamaki/local/bin/cattleshed &
reading /home/tamaki/local/etc/cattleshed.conf
reading compilers.default
load compiler gcc
start listening at 0.0.0.0:2012
```

```sh:起動2
$ export LD_LIBRARY_PATH=/home/tamaki/local/lib
$ /home/tamaki/local/bin/kennel -c /home/tamaki/local/etc/kennel.json 
```

これでだいたい準備完了．



## wandboxにアクセス

http://127.0.0.1:3500/
にアクセスすると，wandbox！

![スクリーンショット 2016-05-02 12.17.14.png](https://qiita-image-store.s3.amazonaws.com/0/44835/186f48a7-b5a6-6cf3-3502-4ddcc26b1f4a.png)


## 保存場所

- /home/tamaki/local/var/log/wandbox/ran/yyyymmdd/wandbox****** 以下に，すべてのコードが保存されている．




# 分かったこと

- 英語
 - cattle shed（[牛小屋](http://ejje.weblio.jp/content/cattle+shed)）
 - cattle grid（[家畜脱出防止の溝](http://ejje.weblio.jp/content/cattle+grid)）
 - kennel（[犬小屋](http://ejje.weblio.jp/content/kennel)）
- 仕組み
 - cattleshedがデーモン（たぶん）
 - prlimitでリソースを制限，cattlegridを呼び出す（cattleshed.confの記述）
 - cattlegridが，chrootして，主なパス(/bin, /libなど）とデバイスをmountし，storeディレクトリを作ってそれをrwmount，してからchdirする（cattleshed.confの記述）
 - compiler.defaultに記述したコマンドが実行される
- ハマったこと
 - デーモン起動まで行って，sandboxにアクセスできたのに，Runすると計算結果のの代わりに`g++: vfork: resource temporarily unavailable`というエラーメッセージが表示されるだけ．．．．まさかデフォルトでリソースが足りないとは思わなかったため，四苦八苦．結果的に`--nproc`を増やすことで解決．
- その他
 - Vigrantとかchefとか，知らなかった最先端スキルを身につけた