+++ date = "2018-08-21" tags = ["heroku"] title = "herokuでsnsやらchatやらを立ててみた時の話" slug = "heroku" +++ ## 導入 この前、chat立てたい、みたいな話を耳にしたので、1,2時間ほどでherokuのほうに立ててみました。ちょっと調べたりした。 そういえば、この場合、立てた、建てた、どっちだろう。まあ、どっちでもいいか。 ## phx-chat さて、chatというと、elixirのphx(phoenix)が便利です。これは、作る場合という話ですが、exampleでも機能はないけど、シンプルなものができます。 herokuの場合、なかなか面倒ですけど、[dwyl/phoenix-chat-example](https://github.com/dwyl/phoenix-chat-example)を使えば、割と簡単にできます。 ```sh $ git clone https://github.com/dwyl/phoenix-chat-example $ cd !$:t $ heroku create $APP_NAME $ rm -rf .git $ heroku git:remote -a $APP_NAME $ echo "erlang_version=20.1 elixir_version=1.6.0 always_rebuild=false runtime_path=/app " >> elixir_buildpack.config $ echo "web: MIX_ENV=prod POOL_SIZE=2 mix ecto.migrate && mix phx.server" >> Procfile $ vim config/prod.exs config :chat, ChatWeb.Endpoint, load_from_system_env: true, url: [scheme: "https", host: "syui-chat.herokuapp.com", port: 443], force_ssl: [rewrite_on: [:x_forwarded_proto]], cache_static_manifest: "priv/static/cache_manifest.json", secret_key_base: Map.fetch!(System.get_env(), "SECRET_KEY_BASE") $ mix deps.get $ mix phx.gen.secret XXX $ heroku config:set SECRET_KEY_BASE="XXX" -a $APP_NAME $ heroku addons:create heroku-postgresql:hobby-dev -a $APP_NAME $ heroku buildpacks:set https://github.com/HashNuke/heroku-buildpack-elixir.git -a $APP_NAME $ heroku buildpacks:add --index 2 https://github.com/gjaldon/heroku-buildpack-phoenix-static.git -a $APP_NAME $ echo mix.lock >> .gitignore $ git add . $ git commit -m "first" $ git push heroku master ``` 多分、こんな感じですね。 https://github.com/dwyl/learn-heroku/blob/master/elixir-phoenix-app-deployment.md https://hexdocs.pm/phoenix/heroku.html#making-our-project-ready-for-heroku ## pleroma [pleroma](https://git.pleroma.social/pleroma/pleroma)もphxで書かれています。ただし、phx exampleであるようなディレクトリ構造とは少し違うので、heroku buildpacksも違ってきます。 具体的には、`https://github.com/gjaldon/heroku-buildpack-phoenix-static.git`は、`assets/package.json`を`npm i`するのですが、pleromaは、heroku deployする際に、npm(node)が必要ありません。`package.json`ないですし。ということで、buildpacksは`elixir`のやつだけでOKです。 大抵、srcを読めばわかりますが、`config/prod.exs`はこんな感じになってます。 > config/prod.exs ```sh use Mix.Config config :pleroma, Pleroma.Web.Endpoint, http: [port: {:system, "PORT"}], url: [scheme: "https", host: "pleroma.syui.ai", port: 443], force_ssl: [rewrite_on: [:x_forwarded_proto]], #cache_static_manifest: "priv/static/manifest.json", secret_key_base: System.get_env("SECRET_KEY_BASE") config :logger, level: :info config :logger, :console, format: "[$level] $message\n" config :phoenix, :stacktrace_depth, 20 config :pleroma, Pleroma.Repo, adapter: Ecto.Adapters.Postgres, url: System.get_env("DATABASE_URL"), pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"), ssl: true config :pleroma, :media_proxy, enabled: true, redirect_on_failure: true, base_url: "https://syui.gitlab.io/img/pleroma" ``` pleromaもそうですが、imgをuploadするserverが必要で、通常はhostingしているserverにuploadするんですけど、herokuは再起動と同時に、upload(write)されたものを消します。なので、この際にuploadしたavatarも消えます。 ということで、`media_proxy`を設定してみてどうにかならないかなってことでやってみましたが、どうにもなりませんでした。 これに関しては、srcの`lib/pleroma/upload.ex`をいじって対応しています。けど、やりたいこと事自体は単純なので上記の設定でなんとなく分かると思います(それ自体は有効ではないけど)。 heroku webは、アクセスがないとM30ごとに落ちます。多分そんな感じ。立ち上がるまで結構時間がかかるので、`scheduler`を設定してみたわけですが、`heroku logs`みてみると、`Stopping all processes with SIGTERM`したことがありました。なのでやめといたほうがいいですね。特に`process-scheduler`です。herokuに負担がかかりすぎるみたい。 ```sh $ heroku addons:add process-scheduler -a $APP_NAME $ heroku addons:create scheduler:standard -a $APP_NAME $ heroku addons:open process-scheduler -a $APP_NAME $ heroku addons:open scheduler -a $APP_NAME ``` こちらは、pleromaの初期コマンド等です。 ```sh # sing up # example : $ heroku run "mix register_user syui syui user@github.com . password123" -a pleroma $ heroku run "mix register_user " -a $APP_NAME # admin user $ heroku run "mix set_moderator $USER" -a $APP_NAME # single user mode $ vim config/config.exs + config :pleroma, :instance, registrations_open: false, + config :pleroma, :chat, enabled: false ``` https://git.pleroma.social/pleroma/pleroma/wikis/Pleroma%E3%81%AE%E5%85%A5%E3%82%8C%E6%96%B9 https://git.pleroma.social/pleroma/pleroma/wikis/Admin%20tasks pleromaにもchatありますね。chatは、web, mobileが必要ないならirc server立てればいいだけなんですけどね。 ## gnu-social [gnu-social](https://git.gnu.io/gnu/gnu-social)はphpで書かれていて、しかもcomposerすらないので、つらい感じでした。 ということで、composerを用意してるrepo(branch)から持ってくることにしました。それをカスタマイズしてheroku deployという感じですね。 なお、composer.lockもcommitする必要があります。 ```sh $ git clone https://git.gnu.io/dansup/gnu-social $ cd !$:t $ git checkout composer-autoloading $ php -v 7.2 $ composer update error # これでいけました $ vim composer.json { "require": { "ext-pgsql": "*", "ext-gd": "*", "ext-intl": "*", "php": "^7.2.0", "illuminate/contracts": "*", "illuminate/support": "*", "ramsey/uuid": "^3.0", "ezyang/htmlpurifier": "^4.10", "psy/psysh": "^0.8.17" }, "scripts": { "post-install-cmd": [ "chmod 644 config.php" ], "post-update-cmd": [ "chmod 644 config.php" ] } } $ composer update $ heroku buildpacks:add https://github.com/heroku/heroku-buildpack-php -a $APP_NAME $ heroku addons:add cleardb:ignite -a $APP_NAME # trueとかの部分はいらない $ heroku config -a $APP_NAME | grep CLEARDB_DATABASE_URL mysql://username:password@hostname/database $ rm -rf .git $ heroku git:remote -a $APP_NAME $ git add . $ git commit -m "first" $ git push heroku master $ open -a Google\ Chrome $APP_NAME.herokuapp.com/install.php ``` gnu-socialの仕組みは単純で、基本的に`install.php`が`config.php`を書き込む処理を行います。ただし、deploy後は、heroku resetの関係でそこで作った`config.php`は、一時的にしか有効ではありません。もちろん、DBに保存されるユーザー情報は別ですが。 ということで、srcにconfig.phpを用意して、deployする必要があるわけなんですけど(.gitignoreに注意)、config.phpの内容がわからないんですよね。そもそも`heroku run bash -a $APP_NAME`してもconfig.phpが見つからないし、権限を考慮してもやっぱり見当たらないので、herokuの仕組み的なものなんだと思いますが、私は、dockerでpreviewして、そのときに作成したconfig.phpをdocker cpして持ってくることを考えました。 install.phpのINSTALLDIRで設定されているはずなんですが、`lib/installer.php`の`chmod 644`を書き直したり、INSTALLDIRを`/app`にしたりしたのですが、heroku runでは見つけられなかった。 ということで、dockerを使って簡潔に行きましょー。こんな感じで持ってきます。一応、CONFIGUREを読んでもいいんですけど、これ読んでやってるほうが時間かかると思う。 ```sh $ sudo docker run -p 8000:80 rudism/gnu-social /root/start $ open -a Google\ Chrome http://localhost:8000/install.php $ sudo docker ps -q $ sudo docker cp xxx:/var/www/gnu-social/config.php . or $ sudo docker exec xxx /bin/bash cat /var/www/gnu-social/config.php $ sudo docker cp xxx:/var/www/gnu-social/config.php . or $ sudo docker commit xxx rudism/gnu-social $ sudo docker run -it rudism/gnu-social /bin/bash cat /var/www/gnu-social/config.php $ sudo docker ps -q $ sudo docker cp xxx:/var/www/gnu-social/config.php . ``` 上記コマンドを見れば、やりたいことはだいたい分かると思います。いろいろな方法があります。この他にも色々ありますね。 しかし、要点は、heroku dbの情報を入力して作成されたconfig.phpを持ってくることが重要だと思います。下記はexampleです。 > config.php ```sh nginx_app.conf ```sh location @rewriteapp { # rewrite all to index.php rewrite ^(.*)$ /index.php/$1 last; } ``` > Procfile ```sh web: vendor/bin/heroku-php-nginx -C nginx_app.conf ``` メモ ```sh fancy urls = index.php ex : /index.php/api/user -> /api/user https://github.com/hannesmannerheim/qvitter/issues/256 > nginx_app.conf location @rewriteapp { # rewrite all to index.php rewrite ^(.*)$ /index.php/$1 last; } > Procfile -C nginx_app.conf https://devcenter.heroku.com/articles/custom-php-settings ``` あと、ちょっと変な現象に遭遇して、config.phpのsite nameにqvitterを入れてると、plugins/Qvitterを呼び出せなかった気がする。多分、plugins/Qvitterのcodeか何かバッティングしたのかも。なので、サイト名変えました。 ## site そういえば、今回、適当にsnsとか立ててみたわけですが、ついでに自分のメインサイトの方にも追記しておきました。 ですが、そんな立てても使いませんよね。ということで、cssのほうもちょっと作ってみました。使わないやつは赤で表示します。 [https://mstdn.syui.ai](https://mstdn.syui.ai) [https://pleroma.syui.ai](https://pleroma.syui.ai) [http://qvitter.herokuapp.com](http://qvitter.herokuapp.com) [http://syui-chat.herokuapp.com](http://syui-chat.herokuapp.com) ```html span.blue { display: inline-block; width: 10px; height: 10px; border-radius: 50%; background: #61bdcc; margin: 0px 5px; box-shadow: 0px 0px 10px #61bdcc; } span.red { display: inline-block; width: 10px; height: 10px; border-radius: 50%; background: #f41b16b0; margin: 0px 5px; box-shadow: 0px 0px 10px #f41b16; } ``` これ、他にも使えそうだなー。