調査 #108
未完了CentOS 8 で Redmine 4を運用するための構築手順確立
80%
説明
- 調査目的
現在さくらVPSで、CentOS 7上にRedmine 3.4を運用している。さくらVPSをCentOS 8に更新し、合わせてRedmine 4.1に更新を計画している。さくらVPSの更新作業に先立ち、検証環境においてCentOS 8とRedmine 4.1環境を構築し、手順を確立する。
- 調査結果
Hyper-V上にCentOS 8を入れる作業をCentOS 8をHyper-V上にインストールに記載
CentOS 8上にRedmine 4.1を入れる作業を RedmineをCentOS 8上で動かすーUnicornとNginx編に記載
- 完了条件
CentOS 8のインストールおよび設定手順を作成
CentOS 8上でRedmine 4.1の構築手順を作成
さくらVPSで現在稼働しているRedmineのデータ移行を確認
ファイル
高橋 徹 さんが約5年前に更新
Redmineのbundle installでエラーに悩まさせられる。
[redmine@pan redmine-4.1-stable]$ bundle install --path vendor/bundler --without development test The dependency tzinfo-data (>= 0) will be unused by any of the platforms Bundler is installing for. Bundler is installing for ruby but the dependency is only for x86-mingw32, x64-mingw32, x86-mswin32. To add those platforms to the bundle, run `bundle lock --add-platform x86-mingw32 x64-mingw32 x86-mswin32`. The dependency ffi (>= 0) will be unused by any of the platforms Bundler is installing for. Bundler is installing for ruby but the dependency is only for x86-mingw32, x64-mingw32, x86-mswin32. To add those platforms to the bundle, run `bundle lock --add-platform x86-mingw32 x64-mingw32 x86-mswin32`. Fetching source index from https://rubygems.org/ Retrying fetcher due to error (2/4): Bundler::HTTPError Could not fetch specs from https://rubygems.org/ Retrying fetcher due to error (3/4): Bundler::HTTPError Could not fetch specs from https://rubygems.org/ Retrying fetcher due to error (4/4): Bundler::HTTPError Could not fetch specs from https://rubygems.org/ Could not fetch specs from https://rubygems.org/
このエラーメッセージでぐぐると、たくさん出てくる・・・
- ping確認
$ ping rubygems.org PING rubygems.org(2a04:4e42::70 (2a04:4e42::70)) 56 data bytes (音沙汰無)
名前解決でIPv6アドレスが返ってくるけど、rubygems.orgはIPv6での接続要求にだんまりするという問題ですね。
rubygems.orgについて、応答できないのであればDNSにIPv6アドレスを載せないようにしてほしいです。
回避方法も散見されますが、場当たり的なものを除くと次がよさそうです。
- /etc/gai.conf を作成し、IPv4の優先度を高める
gai.confは、getaddrinfo関数の設定ファイルで、複数の答えがある場合の並び順を変更する際に使用
https://linuxjm.osdn.jp/html/LDP_man-pages/man5/gai.conf.5.html
- すべてIPv4アドレス(IPv4射影IPv6アドレス)を優先
precedence ::ffff:0:0/96 100
- rubygems.org をDNSに問合せた際に返却されるIPv6アドレスの優先度を下げる
precedence 2a04:4e42::0/32 5
マシン全体が影響されてしまいますが、Redmineを稼働させる専用マシンであれば前者の回避策でもよさそうです。
/etc/gai.confを変更したら要再起動です。
高橋 徹 さんが約5年前に更新
Unicornの起動設定を見直す¶
これまでは、Unicornの設定ファイル(unicorn.rb)、Systemdのサービス化(redmine-unicorn.service)を、中身をちゃんと理解しないまま見よう見まねで作成し利用していました。今回の調査作業を機に理解を深めようと時間を少し割いて追究します。
- unicorn.rb でプロセス実行ユーザー・グループを制御している点
- pid関係どうなっているんだろう
- 絶対パス依存は回避できるか
プロセス実行ユーザー・グループ¶
RedmineをCentOS 6上で動かすーUnicornとNginx編で作成した unicorn.rb では、プロセスがフォークされたときにプロセス実行ユーザー・グループを変更する処理を記述しています。
ところで、Systemdのサービス記述の中でプロセスを実行するときのユーザー・グループを指定する機能がありました。
[Service] User=redmine Group=redmine
これを組み合わせると、unicorn.rbの記述がすっきりするのではないかと思い、試してみることにします。
→ いけた
serviceファイルのPIDFile定義要否¶
- ExecStartで指定したコマンドが実行を継続する(=メインプロセス)場合、Type=simple(デフォルト)となり、コマンド実行した時点で起動完了と判断され、このコマンドのPIDがメインプロセスのPIDとして認識され、設定ファイル内で$MAINPIDとして参照できる。
- ExecStartで指定したコマンドAからフォークされたプロセスBが実行を継続し、コマンドAは終了する場合、Type=forkingとなり、コマンドA終了時に起動完了と判断される。プロセスBのPIDはSystemdでは把握できないため、プロセスBのPIDを記載したファイルを参照する。この場合、PIDFileの定義が必要となる。
実験1 serviceからPIDFile定義削除、unicorn.rbからpid定義削除
- systemctl reload redmine-unicorn を実行すると、新旧のマスター・ワーカーが同居したままとなる
- 旧マスターにQUITを送ると新旧のマスター・ワーカーすべてが落ちてしまう
結論 unicorn にUSR2シグナルを送り、現マスターから新マスターをフォークし、旧マスターを落とすには、新マスターと旧マスターのそれぞれのPIDを識別する必要がある。よって、PIDは必要
絶対パス依存は回避できるか¶
上述より SystemdのserviceファイルにはPIDファイルのパスを指定する必要があるので、絶対パス依存は発生します。
そこで、従来通り、/var/lib/redmineをシンボリックリンクとし、バージョン毎に異なる絶対パスを吸収することとします。
高橋 徹 さんが約5年前に更新
問題¶
unicornのサービスファイルでカレントディレクトリを移動させるWorkingDirectoryを、シンボリックリンクのパスに指定すると
SELinuxでエラーとなる。
プロセスドメイン init_t が、リソース var_lib_t に chdir(チェンジディレクトリ)する際に実ファイルならOKだがシンボリックリンクだとNG。
# systemctl status redmine-unicorn ● redmine-unicorn.service - Redmine Unicorn Server Loaded: loaded (/usr/lib/systemd/system/redmine-unicorn.service; disabled; vendor preset: disabled) Active: failed (Result: exit-code) since Mon 2020-04-20 16:56:47 JST; 46s ago Process: 24154 ExecStop=/usr/bin/kill -QUIT $MAINPID (code=exited, status=200/CHDIR) Process: 24238 ExecStart=/usr/bin/bundle exec unicorn_rails -c config/unicorn.rb -E production (code=exited, status=200/CHDIR) Main PID: 24238 (code=exited, status=200/CHDIR) 4月 20 16:56:47 pan systemd[1]: Started Redmine Unicorn Server. 4月 20 16:56:47 pan systemd[1]: redmine-unicorn.service: Main process exited, code=exited, status=200/CHDIR 4月 20 16:56:47 pan systemd[1]: redmine-unicorn.service: Failed with result 'exit-code'.
Systemdのログファイルをjournalctlコマンドで確認してエラー詳細を把握します。
$ journalctl : 4月 20 16:56:47 pan sudo[24234]: babe : TTY=pts/1 ; PWD=/usr/lib/systemd/system ; USER=root ; COMMAND=/bin/systemctl start redmine-unicorn 4月 20 16:56:47 pan sudo[24234]: pam_systemd(sudo:session): Cannot create session: Already running in a session or user slice 4月 20 16:56:47 pan sudo[24234]: pam_unix(sudo:session): session opened for user root by babe(uid=0) 4月 20 16:56:47 pan systemd[1]: Started Redmine Unicorn Server. 4月 20 16:56:47 pan sudo[24234]: pam_unix(sudo:session): session closed for user root 4月 20 16:56:47 pan systemd[24238]: redmine-unicorn.service: Changing to the requested working directory failed: Permission denied 4月 20 16:56:47 pan systemd[24238]: redmine-unicorn.service: Failed at step CHDIR spawning /usr/bin/bundle: Permission denied 4月 20 16:56:47 pan systemd[1]: redmine-unicorn.service: Main process exited, code=exited, status=200/CHDIR 4月 20 16:56:47 pan systemd[1]: redmine-unicorn.service: Failed with result 'exit-code'. :
ログの中からエラーの原因と思われるメッセージは次です。
4月 20 16:56:47 pan systemd[24238]: redmine-unicorn.service: Changing to the requested working directory failed: Permission denied
ワーキングディレクトリへ移動しようとして権限がないとエラーとなっています。さらに詳しく原因を調べるため、SELinuxのログを確認します。
監査ログの中から、SELinux関連ログを抽出します。
# ausearch -i m avc type=SYSCALL msg=audit(2020年04月20日 16:56:47.788:759) : arch=x86_64 syscall=chdir success=no exit=EACCES(許可がありません) a0=0x55f64e4d8120 a1=0x7ffef178f720 a2=0x55f64e4fba4b a3=0x0 items=0 ppid=1 pid=24238 auid=unset uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=(none) ses=unset comm=(bundle) exe=/usr/lib/systemd/systemd subj=system_u:system_r:init_t:s0 key=(null) type=AVC msg=audit(2020年04月20日 16:56:47.788:759) : avc: denied { read } for pid=24238 comm=(bundle) name=redmine dev="sda3" ino=1162 scontext=system_u:system_r:init_t:s0 tcontext=unconfined_u:object_r:var_lib_t:s0 tclass=lnk_file permissive=0 ---- type=AVC msg=audit(2020年04月20日 16:56:47.790:760) : avc: denied { getattr } for pid=1 comm=systemd path=/var/lib/redmine dev="sda3" ino=1162 scontext=system_u:system_r:init_t:s0 tcontext=unconfined_u:object_r:var_lib_t:s0 tclass=lnk_file permissive=0 ---- type=AVC msg=audit(2020年04月20日 16:56:47.791:762) : avc: denied { read } for pid=1 comm=systemd name=redmine dev="sda3" ino=1162 scontext=system_u:system_r:init_t:s0 tcontext=unconfined_u:object_r:var_lib_t:s0 tclass=lnk_file permissive=0
- /var/lib/redmineディレクトリに対して、chdirシステムコールが失敗
- プロセスのコンテクスト(scontext)は、system_u:system_r:init_t
→ プロセスのドメインは init_t - アクセスされたリソースのコンテクスト(tcontext)は、unconfined_u:object_r:var_lib_t
→ リソースのタイプは var_lib_t - アクセスされたリソースのクラス(tclass)は、lnk_file
ドメイン init_t のプロセスがvar_lib_tリソースへのアクセスとして許された内容を調べると、次の通りです。
$ sesearch --allow | grep "allow init_t var_lib_t" allow init_t var_lib_t:dir { add_name create getattr ioctl lock open read relabelfrom relabelto remove_name search write }; allow init_t var_lib_t:file { append create getattr ioctl link lock open read rename setattr unlink write }; allow init_t var_lib_t:lnk_file { create write };
/var/lib/redmine はシンボリックリンクファイルなので、許されるアクセスは createとwriteだけで、readとgetattrは許されていません。
対策1 実パスでの記述¶
- redmine-unicorn.service の中でWorkingDirectoryをシンボリックリンクではなく絶対パス(実在パス)に変更する
- WorkingDirectory=/var/lib/redmine + WorkingDirectory=/var/lib/redmine-4.1-stable
対策2 カレントディレクトリをserviceでは移動させず、unicorn側で移動させる¶
ExecStart にフルパスで記述
→ NG
カレントディレクトリに.bundleがないので起動エラーとなってしまう
対策3 init_tドメインだけSELinuxの保護を無効にする¶
# semanage permissive -a init_t
未実施
対策4 SELinuxのアクセスルールを追加する¶
未実施
高橋 徹 さんが約5年前に更新
問題¶
unicorn と nginx が同一マシン上で通信するときに、UNIXドメインソケットを使っている。
CentOS 6では、/tmp/unicorn.sock を使っていたが、CentOS 7からはPrivateTmpが導入され、/tmpの下に作成したファイルはデーモンプロセス毎に実体が異なるようになり、unicornとnginxとが同じ/tmp/unicorn.sockを読み書きすることが簡単にはできなくなりました。
回避策1¶
/var/lib/redmine/tmp 下にsockファイルを生成して使う。
→ NG
SELinux でエラーになる。httpd_tドメインがvar_lib_tリソースのunix_domain_socketにアクセス許可を持たないため。追加のポリシーを定義し使用すれば回避可能。
回避策2¶
NginxのPrivateTmpを無効にする。
→ NG
SELinux でエラーになる。httpd_tドメインがtmp_tリソースのunix_domain_socketにアクセス許可を持たないため。追加のポリシーを定義し使用すれば回避可能。
type=AVC msg=audit(2020年04月21日 16:00:28.387:1485) : avc: denied { write } for pid=12791 comm=nginx name=unicorn.sock dev="sda3" ino=68515434 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:tmp_t:s0 tclass=sock_file permissive=0
回避策3¶
/var/run 下にsockファイルを生成して使う。
→ NG
SELinux でエラーになる。httpd_tドメインがvar_run_tリソースのunix_domain_socketにアクセス許可を持たないため。追加のポリシーを定義し使用すれば回避可能。
回避策4¶
回避策1~3はいずれもSELinuxにより阻まれてしまった。
回避策1~3のいずれかとSELinuxでアクセス許可を設定することをセットで対処が必要。
そこで、回避策1~3の中でSELinuxの許可が設定しやすいものを見出す。
- nginxプロセス(ドメインhttpd_t)がアクセス可能なsockファイルのタグは、httpd_tmp_t, httpd_tmpfs_t, httpd_var_run_t である。
- 回避策1 /var/lib/redmine/tmp は、シンボリックリンクのため、semanage fcontext での指定に不向き
- 回避策2 は、nginx のsystemd サービスファイルを変更し、さらに semanage fcontext で設定するので後回し
- 回避策3 で /var/run/unicorn.sock を設け、このファイルのリソースタイプをhttpd_var_run_tとする。
# semanage fcontext -a -t httpd_var_run_t '/var/run/unicorn.sock'
Unicorn起動せず。原因は、unicorn実行ユーザー(redmine)では/var/runにファイルを作成できないため。(SELinuxではない)。
そこで、/var/run/unicorn/ ディレクトリを作成し、パーミッションをredmineにして、その中にunicorn.sockファイルを作るようにする。
# semanage fcontext --deleteall # semanage fcontext -a -t httpd_var_run_t '/var/run/unicorn.sock'
/var/run はtmpfsで起動時に内容が消えてしまう。unicorn起動時に/var/run/unicornディレクトリを作成する処理を/usr/lib/systemd/system/redmine-unicorn.serviceに追加する。
/var/lib/redmine/config/unicorn.rb でソケットファイルのパスを/var/run/unicorn/unicorn.sockに変更
/etc/nginx/conf.d/redmine.conf でソケットファイルのパスを/var/run/unicorn/unicorn.sockに変更
高橋 徹 さんが約5年前に更新
TSLの設定と確認¶
以下の手順で自己署名証明書を作成し、/etc/pki/nginx以下に配置
https://www.server-world.info/query?os=CentOS_8&p=ssl&f=1
/etc/nginx/conf.d/ssl.confを新規作成、内容は/etc/nginx/nginx.confのコメントアウトされたTSLのserver設定と同じ。
- Edge, Chromeから https://pan にアクセスすると ERR_SSL_SERVER_CERT_BAD_FORMAT エラー で先には進めない
- Firefoxから https://pan にアクセスすると 「警告:潜在的なセキュリティリスクあり」で、[詳細情報] > [危険性を承知で続行] でデフォルトページが表示
Chrome 58以降は、セキュリティ更新によりCommon Name(CN)が無効となり、代わりにSubject Alternative Name(SAN)を証明書に含める必要あり。(RFC 2818)
SANを含めた自己署名証明書を作成すると、Edge、Chromeブラウザからアクセス可能となります。
高橋 徹 さんが約5年前に更新
sidebar_hide プラグインの代替調査
Toggle Sidebar プラグイン¶
https://github.com/Smile-SA/redmine_smile_togglesidebar.git
起動時エラー
plugins/redmine_smile_togglesidebar/init.rb:51:in `<top (required)>': undefined method `to_prepare' for nil:NilClass (NoMethodError) Did you mean? to_param
Rails 5.1 で、ActionDispatch::Callbacks#to_prepare が削除されたため。
修正は単純ではなかったので調査打切り。
view customize で開閉制御¶
https://github.com/onozaty/redmine-view-customize-scripts/blob/master/toggle_sidebar.js
- デフォルトテーマ時、Wikiページコンテンツ右側にサイドバーが被ってしまい、章節編集アイコンや右寄せ目次がつぶされてしまう
- gitmikeテーマ使用時、サイドバーが閉じていてもWiki領域が広がらない
sidebarプラグインの確認¶
https://gitlab.com/bdemirkir/sidebar_hide.git
ダメ元で入れてみたら、一応動いている。
が、テーマをGitmikeにしたら、サイドバーを開いたときにWiki領域が期待値より小さくなってしまった。おおよそ、サイドバーの幅2つ分左側に寄る状況
テーマ | sidebarプラグイン表示具合 | 備考 |
---|---|---|
デフォルト | 良 | |
Gitmike | 否 | サイドバー表示時、コンテンツ幅がサイドバー1個分余計に狭くなっている |
Alternate | 良 | |
Blueclair | 良 | |
Classic | 良 | |
Purplemine2 | 否 | Purplemine2は自身でサイドバーの折り畳み機能を持っており、制御が干渉する |
Red-andy | 良 |
高橋 徹 さんが約5年前に更新
- ステータス を 解決 から フィードバック に変更
- 進捗率 を 80 から 50 に変更
Apache HTTPDからGitリポジトリをアクセスする調査
- CentOS 8のSELinux設定では、Gitリポジトリを置く可能性のある次のディレクトリの定義あり。
/var/lib/git(/.*)? | git_sys_content_t |
/var/www/git(/.*)? | git_content_t |
Apache HTTPDプロセスのドメインは、httpd_t で動作するので、httpdドメインから上述ファイルリソースのタイプへの操作許可は次のようになる。
ドメイン | リソースタイプ:リソース種類 | 許可される操作 |
httpd_t | git_sys_content_t:file | getattr ioctl lock map open read |
httpd_t | git_content_t | なし |
リポジトリを読む操作は、リソースタイプ git_sys_content_t で可能だが、リポジトリへの書き込みができない。httpd_t から読み書き可能(map操作含む)なリソースタイプを調べる。
- ドメインhttpd_tからread, write, map可能なリソースタイプ
httpd_cache_t | append create getattr ioctl link lock map open read rename setattr unlink write |
httpd_tmp_t | append create getattr ioctl link lock map open read rename setattr unlink write |
httpd_tmpfs_t | append create getattr ioctl link lock map open read rename setattr unlink write |
- ドメインhttpd_tからread, write可能なリソースタイプ
git_rw_content_t | append create getattr ioctl link lock open read rename setattr unlink write | [httpd_builtin_scripting] |
httpd_sys_rw_content_t | append create getattr ioctl link lock open read rename setattr unlink write | [httpd_builtin_scripting] |
- ドメインhttpd_tからexecute可能なリソースタイプ
git_script_exec_t | execute execute_no_trans getattr ioctl map open read | [httpd_enable_cgi] |
httpd_sys_script_exec_t | execute execute_no_trans getattr ioctl map open read | [httpd_enable_cgi] |
- gitリポジトリへの書き込みが必要な操作
- refs/heads/<ブランチ名>.lock
- HEAD.lock
高橋 徹 さんが約5年前に更新
Redmine認証連携のGitへのpush動作確認でエラー
D:\work\swe.primus>git push fatal: unable to access 'http://www.torutk.com:8008/git/swe.primus.git/': The requested URL returned error: 500
/var/log/httpd/error_log を見ると
[Wed Apr 29 21:00:04.412613 2020] [authn_file:error] [pid 20116] [client xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:53535] AH01619: AuthUserFile not specified in the configuration
以下の記事にある設定には、AuthUserFile /dev/null
が記載されている。
Installation of Redmine 3.4.6 on CentOS 7.5 + MySQL 8, Apache 2.4, GIT, SVN, LDAP
この記述を/etc/httpd/conf.d/git-redmine.conf に追記し、httpdをリロードし、再度リモートからpushしたところエラーメッセージが変化した。
D:\work\swe.primus>git push fatal: Authentication failed for 'http://www.torutk.com:8008/git/swe.primus.git/'
/var/log/httpd/error_log には
[Wed Apr 29 21:10:30.076370 2020] [auth_basic:error] [pid 20351] [client xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:53353] AH01618: user xxxxxxxx not found: /git/swe.primus.git/info/refs
Basic認証なのにpush時にユーザー・パスワード入力ダイアログが表示されずエラーになってしまっていた。
エラーメッセージには指定していないはずのユーザー名でエラーになっている。
調査結果、Windowsの資格情報にこのGitサーバーで本来とは異なるアカウントが記録されており、git pushでこれを使用していたためであった。
(コマンドラインのgit for windowsでは原因がさっぱり、GUIツールのForkを使ったところ、資格情報を表示してきて判明)。
高橋 徹 さんが約5年前に更新
NginxからApacheへのリバースプロキシ設定を実験してみる。
gitリポジトリのアクセスを、apache httpdに直接ではなく、nginxを介してみるため、nginxに次の設定を追記
- /etc/nginx/conf.d/redmine.conf
server { listen 443 ssl http2 default_server; : + location ^~ /git/ { + proxy_pass http://localhost:8008; + }
SELinuxエラー「ドメインhttpd_t(Nginxプロセス)が、タイプhttp_port_tへのname_connect操作(他のプロセスへのTCP接続)を許可されていない」です。
type=AVC msg=audit(1588165087.499:6049): avc: denied { name_connect } for pid=21387 comm="nginx" dest=8008 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:http_port_t:s0 tclass=tcp_socket permissive=0
$ sesearch -A -s httpd_t -t http_port_t : allow httpd_t http_port_t:tcp_socket name_connect; [ httpd_can_network_relay ]:True allow httpd_t http_port_t:tcp_socket name_connect; [ httpd_graceful_shutdown ]:True allow httpd_t port_type:tcp_socket name_connect; [ httpd_can_network_connect ]:True :
条件付きで許可があります。条件のブール値は現時点では
$ getsebool -a | grep httpd httpd_can_network_connect --> off httpd_can_network_relay --> off httpd_graceful_shutdown --> off :
です。いずれもoffとなっています。では、どれをonにするかですが、一応目的をRHEL7のマニュアルで調べると
- httpd_can_network_relay
「httpd をフォワードプロキシまたはリバースプロキシとして使用する場合、このブール値を有効にします。」 - httpd_can_network_connect
「このブール値を無効にすると、HTTP スクリプトやモジュールがネットワークやリモートポートに接続開始することができなくなります。接続の開始を許可する場合はブール値を有効にします。」 - httpd_graceful_shutdown
「HTTPD が正しくシャットダウンするよう 80 番ポートに接続することを許可します。」
とあるので、今回の用途であればhttpd_can_network_relayが最適でしょう。
# setsebool -P httpd_can_network_relay on # getsebool httpd_can_network_relay httpd_can_network_relay --> on
これでアクセスOKです。
高橋 徹 さんがほぼ5年前に更新
マクロ{{thumnail(画像ファイル名)}}が表示されない問題。
CentOS 8ではImageMagickが削除されたため、thumbnailマクロが動作するために必要なコマンドがなく画像表示されません。thumbnailが動作するにはconvertコマンドで画像サイズを変更できる環境が必要。
ImageMagickが削除された理由はImageMagickが内在する脆弱性のため。
そこで、RHEL8のEPELリポジトリからGraphicsMagickをインストールしてみたが、コマンドがconvertからgm convertに変更となっており、Redmineがgmコマンドを認識できないため利用できなかった。
- configuration.ymlに次を記述したが認識されなかった
imagemagick_convert_command: '/usr/bin/gm convert'
シングルクォーテーションなしの設定もNG
そこで、EPELからImageMagickをインストールすることにした。(脆弱性云々はさておき)
# dnf --enablerepo=epel install ImageMagick :
/var/lib/redmine-4.1-stable/.bundler/config の修正
---
BUNDLE_PATH: "vendor/bundler"
- BUNDLE_WITHOUT: "development:test:rmagick"
+ BUNDLE_WITHOUT: "development:test"
変更後、bundle installを実行してもrmagickがインストールされない。
が、mini_magickがインストールされている。これでもよい?
⇒ thumbnailが表示されるようになった。