個人で開発しているウェブアプリケーションのエラー管理には Airbrake 互換の errbit を使っていたのですが、 Sentry が良いらしい、という話を聞いて、 Sentry について調べていたら、 Sentry には Self-Hosted 版があるらしいということで、さくらのVPSの CentOS 7 に Sentry の Self-Hosted 版をインストールしてみました。

Self-Hosted 版のインストール方法は Sentry のオフィシャルドキュメントが詳しいがあるので、その通りに進めていけば特に問題はないのですが、 Self-Hosted 版 Sentry は Python 2.7 + Django + PostgreSQL + Redis という構成で、特に Python と PostgreSQL はほとんど触ったことがなかっため、インストールを進める中で Ruby や MySQL との文化の違いなどで戸惑うことがわりとたくさんあったことと、 Self-Hosted 版の Sentry のインストール方法について日本語で書かれたブログ記事はなさそうだったので、これから Self-Hosted 版の Sentry をインストールしてみたい人の役に立つのではと思い、インストールの手順をまとめてみます。

各種バージョン

  • OS: CentOS 7.7
  • Python: 2.7.16
  • PostgreSQL: 12.0
  • Redis: 5.0.6
  • Sentry: 9.1.2

Python は3系ではなく 2.7 とのことです。2系のサポートっていつまでだっけ、と思いながらインストール作業をしていました。(改めて調べたら「2020年1月1日」までとのことなので、この記事の公開時点であと2ヶ月無いですね…。 Self-Hosted 版の Sentry の今後が気になります…。)

PostgreSQL は 9.6 が推奨らしいのですが、まぁバージョンが上な分には問題ないだろうと思って、記事執筆時点の最新の PostgreSQL 12.0 を使用しました。(結果、 PostgreSQL 12.0 で問題なく動きました。)

Redis は 3.2 が推奨らしいのですが、まぁバージョンが上な分には問題ないだろうと思って、記事執筆時点の最新の Redis 5.0.6 を使用しました。(結果、 Redis 5.0.6 で問題なく動きました。)

ちなみに、 docker は使いませんでした。サーバーがさくらのVPSなので、そこで docker を使いたい理由があまりなかったので。

CentOS 7 に sentry ユーザーを作成

あとで各所で利用するため、 CentOS 7 に sentry というユーザーを先に作成します。

$ useradd sentry
$ passwd sentry

PostgreSQL 12.0 のインストール

yum でインストールしたいので、 PostgreSQL のオフィシャルのドキュメントにある通り、 PostgreSQL のバージョンを選択して、プラットフォームを選択して、 CPU アーキテクチャを選択して、表示された rpm をインストールします。

$ yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm

これで postgresql12 という名前で yum でインストールできるようになります。( postgresql12 がクライアントで postgresql12-server がサーバーで、 postgresql12-contrib が拡張機能です。)

$ yum install -y postgresql12 postgresql12-server postgresql12-contrib

postgresql-12-setup initdb の実行

PostgreSQL は通常、サービスを起動する前に一度だけ、 postgresql-12-setup initdb を実行する必要があるらしいです。(私は今回、初めて知りました。)

postgresql-12-setup initdb がはじめ、どこにあるかわからなかったのですが、 /usr/pgsql-12/bin/postgresql-12-setup にあったので、 それを使って initdb を実行します。( postgresql-12-setup の場所は systemctl status postgresql-12 で調べて、なんとなくあたりをつけて見つけました。)

$ /usr/pgsql-12/bin/postgresql-12-setup initdb

postgresql-12 の起動

サービス名がわからなかったので、 systemctl list-unit-files -t service | grep postgres でサービス名を探して、 postgresql-12 であることを確認しました。サービス名がわかったので、サービスを起動して OS 起動時に自動で立ち上がるようにします。

$ sudo systemctl start postgresql-12
$ sudo systemctl enable postgresql-12

sentry ユーザーと sentry データベースの作成

続いて、Sentry で利用するためのユーザー「 sentry 」とデータベース「 sentry 」を作成します。

PostgreSQL 12.0 をインストールすると posgres というユーザーが作られていて、このユーザーが PostgreSQL に対するスーパーユーザーになっています。

なので、まずは、 sudo などで postgres ユーザーにログインシェルを変更して、

$ sudo su - postgres

postgres ユーザーで PostgreSQL 12.0 の sentry ユーザーを作成して、

$ createuser sentry

sentry データベースを作成します。

$ createdb -E utf-8 -O sentry -T template0 sentry

注意点としては、 Sentry のオフィシャルのドキュメントには createdb -E utf-8 sentry でデータベースを作る、と書かれているのですが、 template を指定しないと utf-8 で作れなかったため、 template を指定しています。( createdb -E utf-8 sentry でデータベースを作ろうとすると、「 template に tempate0 を指定しなさい」というエラーメッセージが出た気がしますが、詳しいエラーメッセージは失念しました。)

続いて、下記のコマンドで sentry ユーザーに対して、 sentry データベースへの全ての権限を追加します。

$ psql
postgres=# grant all privileges on database sentry to sentry;
GRANT

Sentry に必要な PostgreSQL の拡張機能のインストール

これはあとでわかったことなのですが、 Sentry には citext という PostgreSQL の拡張機能(エクステンション)が必要でした。

拡張機能のインストールはスーパーユーザーの postgres で行います。下記のように postgres ユーザーにログインシェルを変更して、

$ sudo su - postgres

下記のコマンドで PostgreSQL に接続して、

$ psql

利用するデータベースをsentry に変更して、

postgres=# \c sentry

下記の SQL で citext をインストールします。

sentry=# create extension citext;
CREATE EXTENSION

Python 2.7.16 のインストール

システムの Python 2.7 はバージョンが 2.7.5 で、2系の最新は 2.7.16 だったので、 pyenv で 2.7.16 をインストールしました。

インストール方法は pyenv の README が詳しいので、 README で説明されているままインストールを進めます。(と言いつつ、一部、アレンジしています…。)

$ git clone https://github.com/pyenv/pyenv.git ~/.pyenv
$ echo 'export PATH="$HOME/.pyenv/bin:$PATH"' >> ~/.bashrc
$ echo 'eval "$(pyenv init -)"' >> ~/.bashrc
$ exec "$SHELL"
$ pyenv -v
pyenv 1.2.13-19-gf3d008f

これで pyenv がインストールできたので、 pyenv で Python 2.7.16 をインストールします。

$ pyenv install 2.7.16
$ pyenv versions
system
* 2.7.16 (set by /home/username/.pyenv/version)

Python 2.7.16 がインストールできました。

Redis 5.0.6 のインストール

Redis の最新を yum でインストールしたくて、調べたところ PHP で有名な remi リポジトリを利用することで Redis v5 が使えるとのことだったので、まずは remi リポジトリをインストールします。

remi リポジトリを利用するために epel リポジトリが必要になるようなので、まずは epel リポジトリをインストールします。

$ yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm

次に remi リポジトリをインストールします。

$ yum install -y https://rpms.remirepo.net/enterprise/remi-release-7.rpm

remi リポジトリを有効にして redis をインストールします。

$ yum install -y redis --enablerepo=remi

これで Redis 5.0.6 がインストールできました。

$ redis-server -v
Redis server v=5.0.6 sha=00000000:0 malloc=jemalloc-5.1.0 bits=64 build=c3d7ebb6b1a2844b

Sentry のインストール

まずは適当な場所に sentry ディレクトリを作成して、

$ mkdir sentry

sentry ディレクトリに移動して、

$ cd sentry

ここで Python 2.7.16 を利用したいので、 .python-version を作成して、

$ echo 2.7.16 > .python-version

pyenv rehash を実行して、

$ pyenv rehash

念のため Python のバージョンを確認します。

$ python --version
Python 2.7.16

Python の作法がよくわかっていないですが、 virtualenv を使いたいので、 pipvirtualenv をインストールして、

$ pip install -U virtualenv

virtualenv を実行して、

$ virtualenv ./

activate を実行します。

$ source bin/activate

続いて、 pipsentry をインストールします。

$ bin/pip install -U sentry

これで sentry コマンドがインストールされました。

$ bin/sentry --version
sentry, version 9.1.2

続いて sentry init を実行して設定ファイルを生成します。設定ファイルの配置場所は、オフィシャルドキュメントでは /etc/sentry になっていますが、私は sentry ディレクトリにまとめたかったので、下記のように実行しました。

$ bin/sentry init config

上記のコマンドで config ディレクトリ以下に config.ymlsentry.conf.py が作成されるので、適宜修正します。

まずは sentry.conf.py のデータベースへの接続部分を下記のように修正します。

DATABASES = {
    'default': {
        'ENGINE': 'sentry.db.postgres',
        'NAME': 'sentry',
        'USER': 'sentry',
        'AUTOCOMMIT': True,
        'ATOMIC_REQUESTS': False
    }
}

次に、 Sentry から送信されるメールを私個人の Gmail を経由して送信するように設定します。

先に Gmail でアプリパスワードの生成を行なって、その内容にあわせて config.yml の Mail Server の設定を修正します。


mail.backend: 'smtp'  # Use dummy if you want to disable email entirely
mail.host: 'smtp.gmail.com'
mail.port: 587
mail.username: 'username@gmail.com'
mail.password: 'Gmail で発行したアプリパスワード'
mail.use-tls: true
# The email address to send on behalf of
mail.from: 'sentry@sentry.example.com'

続いて sentry ユーザーで sentry upgrade を実行して、データベースのスキーマ定義を読み込んだり、初期設定を実行したりします。( sentry ユーザーで実行するのは、 sentry データベースに接続できるのが OS の sentry ユーザーのみであるためです。)

$ sudo su sentry -c "SENTRY_CONF=/home/username/sentry/config bin/sentry upgrade"

上記コマンドを実行すると、最後にユーザーを作るか聞かれるので、私は自分のユーザーを作成しました。

Would you like to create a user account now? [Y/n]:

Sentry を systemd に登録して起動する

Sentry を systemd に登録して起動する方法がオフィシャルのドキュメントに記載されているので、ほぼその通りに進めていきます。(ただし、ディレクトリなどは適宜、自分の環境にあわせて修正します。)

まずは sentry-web.service を下記のように作成します。

$ sudo vi /etc/systemd/system/sentry-web.service
[Unit]
Description=Sentry Main Service
After=network.target
Requires=sentry-worker.service
Requires=sentry-cron.service

[Service]
Type=simple
User=sentry
Group=sentry
WorkingDirectory=/home/username/sentry
Environment=SENTRY_CONF=/home/username/sentry/config
ExecStart=/home/username/sentry/bin/sentry run web

[Install]
WantedBy=multi-user.target

次に sentry-worker.service を下記のように作成します。

$ sudo vi /etc/systemd/system/sentry-worker.service
[Unit]
Description=Sentry Background Worker
After=network.target

[Service]
Type=simple
User=sentry
Group=sentry
WorkingDirectory=/home/username/sentry
Environment=SENTRY_CONF=/home/username/sentry/config
ExecStart=/home/username/sentry/bin/sentry run worker

[Install]
WantedBy=multi-user.target

最後に sentry-cron.service を下記のように作成します。

$ sudo vi /etc/systemd/system/sentry-cron.service
[Unit]
Description=Sentry Beat Service
After=network.target

[Service]
Type=simple
User=sentry
Group=sentry
WorkingDirectory=/home/username/sentry
Environment=SENTRY_CONF=/home/username/sentry/config
ExecStart=/home/username/sentry/bin/sentry run cron

[Install]
WantedBy=multi-user.target

以上、3つのサービスを作成しましたが、 sentry-web を起動すると sentry-workersentry-cron も起動するので、通常、コマンドで起動させるのは sentry-web だけです。(ただ、 sentry-web を止めても sentry-workersentry-cron は止まらなかったので、全て止めたい場合は、それぞれを止めるコマンドを実行する必要がありました。)

$ sudo systemctl start sentry-web

上記のコマンドで sentry-web を起動すると、 service-workerservice-cron も起動していることが確認できます。

$ sudo systemctl status sentry-worker
$ sudo systemctl status sentry-cron

最後に sentry-web を自動起動するように設定しておきます。

$ sudo systemctl enable sentry-web

Nginx の設定

Nginx のインストール方法と、私は SSL 認証書に Let’s Encrypt を使ったのですが、その辺りの話は本題と外れる気がするので、省きます。

Nginx の設定の書き方もオフィシャルのドキュメントに書かれているほぼそのままで、私は下記のように記述しました。( Sentry とあまり関係ない箇所は省いています。)

server {
    listen 443 ssl;
    server_name sentry.example.com;

    proxy_set_header Host               $host;
    proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Host   $host;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded_Proto  $scheme;
    proxy_set_header X-Real-IP          $remote_addr;

    location / {
        proxy_redirect off;
        proxy_pass http://localhost:9000;
    }
}

また、 SSL の設定として、 config/sentry.conf.py のコメントアウトされていた行のコメントを削除して有効化しました。

SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True

ブラウザで Sentry を開く

ブラウザで https://sentry.example.com を開いて、下記のような画面が表示されれば完了です。

Sentry の管理画面の使い方は、使ってみたらなんと無くわかりました。 errbit よりもモダンな感じで、画面遷移などがサクサク動くのが素敵です。

とりあえず、個人で運用している Rails 5 用の Project を作って、そうすると gem のインストール方法と設定の書き方の説明ページが表示されるので、その通りに gem をインストールして、設定を書いて、

Rails アプリで検証用の例外を発生させて、 Sentry にエラーの詳細が送られていることを確認しました。

errbit に比べて情報量が多い気がするけど、ちゃんときれいに整理されてデザインされているので、慣れると使いやすそうです。


以上、 Self-Hosted 版 Sentry を CentOS 7 にインストールした話でした。どなたかのご参考になれば幸いです。

参考サイト

途中、 PostgreSQL をアンインストールした際に下記のサイトが参考になりました。

Red Hat Enterprise Linux 7でのPostgreSQLのアンインストール