プライベートのタスク管理用にOpenprojectを試す

## 経緯

半年ほど前からタスク管理にNextcloudの[Tasks](https://apps.nextcloud.com/apps/tasks)を使っていた。
結構便利に使えていたのだが、飽き性なせいで保留中のタスクの量が増えすぎてソート機能が物足りなくなったのと、だらだら時間を浪費するのを減らすために作業時間の記録もしたくなってきた。ということでより高機能なプロジェクト管理アプリに移行することにした。

### なぜRedmineではなくOpenProjectにしたのか（Nextcloud tasksと比べて）

OSSのプロジェクト管理アプリだとRedmineが有名なので、当初はそっちに移行するつもりで試した。 しかし、今まで使っていたNextcloud tasksとくらべ、ページ遷移が多いのがストレスだった。

具体的には

*   検索
    *   Nextcloud Tasksはヘッダーの検索欄からTaskも含めた串刺し検索ができ、検索結果が画面を映る前から見れる
    *   Redmineは検索結果を見るのに画面遷移が必要な上、右上のメニューからでは検索対象のプロジェクトを選べない（今のプロジェクトからの検索になる）ため、プロジェクトを跨いだ検索だとさらに手間がかかる
*   タスク一覧と詳細の同時表示
    *   Nextcloud Tasksは一覧のなかから項目を選ぶと右のサイドバーに詳細が表示されるため、画面の遷移が必要ない。
    *   一方のRedmineはそういった機能がないので基本的にリストと詳細を見るのに画面遷移を繰り返す必要になる。

そこでOpenProjectはどうかというと、少なくとも上記の2点についてはNextcloudと同じような操作感だった。そのためこちらを採用することにした。消費メモリは大きいが動かすのはVPSではなくメモリのある程度余裕のある自宅サーバなので問題ないと判断した。

## OpenProjectについて

改めてOpenProjectについて。

Redmineの派生であるChilProjectからの派生ということで、機能的にはRedmineとだいたい同じ感じな模様。

Redmineとの違いはモダンなUIと、要求スペックの高さだろう。最小構成でメモリ4GBということなので、VPSの最小プランで動かすのは難しそう。

## 構成

```
$ uname -a
Linux fox 4.19.204-1-MANJARO #1 SMP Sun Aug 15 11:52:55 UTC 2021 x86_64 GNU/Linux
$ nginx -version
nginx version: nginx/1.20.1
$ psql --version
psql (PostgreSQL) 13.3
$ ruby --version
ruby 2.7.4p191 (2021-07-07 revision a21a3b7d23) [x86_64-linux]
$ node --version
v14.17.0
```

## インストール

おおむね公式のインストール手順に従う。 [Manual installation guide](https://www.openproject.org/docs/installation-and-operations/installation/manual/)
英語だけだが、基本的にはコードブロックのコピペで行けるので難しくはないので、本記事では上記のマニュアル通りの個所は省略し、手順を変えた個所のみ書いておく。

### バージョン関係
上記のページでは~~記事を投稿した~~作業していた2021年8月時点で`stable-9`となっているが、実際の最新のバージョンは11まで出ている。
`stable-9`はモジュールの情報が更新されていないらしく、ビルドできなかったのでバージョンを11にした。

```
git clone https://github.com/opf/openproject.git --branch stable/11 --depth 1
```


それに伴い`nodejs`のバージョンを`14.17`に変える

公式の手順の時点で`rbenv`や`nodenv`を使っており、簡単にバージョンを切り替えられる形でインストールしているのでバージョンの切り替え自体は簡単にできる。

```
nodenv install 14.17.0
nodenv rehash
nodenv global 14.17.0

node --version
v14.17.0
```

## アプリケーションサーバーの設定（Unicorn）

公式ではApache http server にPassengerというプラグインを使う様なのだが、今回は過去にも使ったことがあったUnicornを使った。[^passenger][^puma]

[Ruby on Rails - ArchWiki](https://wiki.archlinux.jp/index.php/Ruby_on_Rails#Unicorn)を参考にしつつ設定していく

Unicornのインストール

```
$ gem install unicorn
$ unicorn --version
unicorn v6.0.0
```

Unicornの設定

すでに一度動かしていたRedmineのを参考に設定した。

```/etc/unicorn/openproject.ru
listen 63408

stderr_path "/var/log/openproject.err.log"
stdout_path "/var/log/openproject.log"

working_directory "/srv/openproject/openproject"
pid "/tmp/openproject.pid"

preload_app true
timeout 60
worker_processes 4

GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true

after_fork do |server, worker|
        # 63408 からワーカーの数だけそれぞれポートを割り当てる。
        addr = "0.0.0.0:#{63408 + worker.nr}"
        server.listen(addr, :tries => -1, :delay => -1, :backlog => 128)

        #Drop privileges if running as root
        worker.user('nobody', 'nobody') if Process.euid == 0
end

```

以下のコマンドで起動できることを確認する。

```
$ ~/.rbenv/shims/bundle exec unicorn -E production -c /etc/unicorn/openproject.ru
```

絶対パスで試しているのはのちのちsystemd.serviceで設定する際に絶対パスが必要になるため。

### nginxの設定

こちらもRedmineの例などを参考にしつつ設定していく。


```nginx:/etc/nginx/sites-enabled/openproject
upstream openproject {
    server 127.0.0.1:63408 fail_timeout=0;
    server 127.0.0.1:63409 fail_timeout=0;
    server 127.0.0.1:63410 fail_timeout=0;
    server 127.0.0.1:63411 fail_timeout=0;
}

server {
    listen 80;
    listen [::]:80;
    # 以下省略
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name openproject.example.net;

    # let'sencryptで作った証明書。取得の手順は省略。
    ssl_certificate /etc/letsencrypt/live/openproject.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/openproject.example.com/privkey.pem;
    access_log /var/log/nginx/access.openproject.log main;

    # 最初に起動したときにjavascriptなどの静的ファイルへのアクセスに失敗していたため、
    # Unicornではなくnginx側で取得させる
    location ~ ^/assets/(.*) {
        alias /srv/openproject/openproject/public/assets/$1;
    }

    location / {
        root                    /srv/openproject/openproject/public;
        proxy_set_header Host   $http_host;
        proxy_redirect          off;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Ssl on;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Frame-Options SAMEORIGIN;
        proxy_pass              http://openproject;
    }
}
```

ここまででアクセスができることが確認できた。

### Systemdの設定

問題なさそうであればSystemdで起動できるようserviceファイルを用意する

```/etc/systemd/system/openproject.service
[Unit]
Description=Unicorn application server for OpenProject
After=network.target

[Service]
Type=forking
User=openproject
WorkingDirectory=/srv/openproject/openproject
# 初回設定時に.profileにSECRET_KEY_BASEという環境変数が設定され、起動時にこれが必要になる
# systemdでは.profileは読み込まないので代わりにここで指定
Environment="SECRET_KEY_BASE=********************"
ExecStart=/srv/openproject/.rbenv/shims/bundle exec unicorn -D -E production -c /etc/unicorn/openproject.ru

[Install]
WantedBy=multi-user.target
```

serviceファイルを読み込んで起動する

```
sudo systemctl daemon-reload
sudo systemctl enable --now redmine.service
```

## 使用感

2週間ぐらい使った段階での使用感について。[^review]

### 検索や一覧表示での編集

ページを移動しなくても検索ができたり、リスト表示のサイドに詳細を表示できたり、前述したNextcloud TasksでできてRedmineでできなかった機能は問題なく使えて快適。

### Redmineと比べて

ページ遷移が少ない分使い勝手はいいが、完全に上位互換かというとそうでもない。
たとえばAssigneeはRedmineではデフォルトのユーザーが設定できるがOpenprojectではできなかったり（そもそも今回は使うの自分だけなので担当者の設定はする必要はないが）、設定できる項目がちょこちょこ違っている感じ。
グラフ表示やテーマの変更など、有料じゃないとできない項目も多いのも気になるところ。

とはいえページ遷移がすくないのは非常に楽だし、（メモリが足りているなら）レスポンスも悪くないので個人的にはかなり満足している。

### WYSIWYGエディタは日本語入力の挙動が怪しい

OpenprojectはリッチなWYSIWYGエディタを持っている[^wysiwyg]、のだが、この日本語入力での挙動が怪しい。
自分の環境（Firefox, Linux, fcitx-mozc, KDE）では変換確定した時にカーソルが返還対象の手前に移動するという謎の挙動があり、日本語入力は使い物にならないといってもいい。
職場からはWindows上のChromeで使っていて、これだと不具合がなく使えている、かと思いきやまれに別の不具合が発生するので、Windowsなら、Chromeなら問題ないとも言い切れない感じ。 

自分はもともと変換のミスが多くて面倒、漢字書くのも面倒ということでプライベートでのメモなどは英語へ移行している最中だったのでいいのだが、[^english]日本語メインで使うのはおすすめできない印象。







[^passenger]: Nginxにも入れられるのだが、コンパイルしなおす必要があるとかで影響範囲が広そうなので単体で動くUnicornにした。

[^puma]: 最近はPumaが後継として普及しているということはインストール後に知った。

[^review]: 運用方法が定まってきて書くことたまったら改めて別記事にするかもしれない

[^wysiwyg]: そもそも個人的にはRedmineのようにWYSIWYGエディタに頼らずマークダウン直書きができたほうがいいのだが、これについては（デフォルトのトラッカーの違いから推測するに）Openprojectが（Redmineと比べて）開発以外でのプロジェクトも想定している（≒開発者以外のユーザーも想定している）ようなので仕方がない。

[^english]: なお英語力はまだまだ足りていないなのでdeeplに頼りまくっている模様。