2018-08-21 /
@syui
heroku
herokuでsnsやらchatやらを立ててみた時の話
導入
この前、chat立てたい、みたいな話を耳にしたので、1,2時間ほどでherokuのほうに立ててみました。ちょっと調べたりした。
そういえば、この場合、立てた、建てた、どっちだろう。まあ、どっちでもいいか。
phx-chat
さて、chatというと、elixirのphx(phoenix)が便利です。これは、作る場合という話ですが、exampleでも機能はないけど、シンプルなものができます。
herokuの場合、なかなか面倒ですけど、dwyl/phoenix-chat-exampleを使えば、割と簡単にできます。
$ 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も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
use Mix.Config
config :pleroma, Pleroma.Web.Endpoint,
http: [port: {:system, "PORT"}],
url: [scheme: "https", host: "pleroma.syui.cf", 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に負担がかかりすぎるみたい。
$ 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の初期コマンド等です。
# sing up
# example : $ heroku run "mix register_user syui syui [email protected] . password123" -a pleroma
$ heroku run "mix register_user <name> <username> <email> <bio> <password>" -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はphpで書かれていて、しかもcomposerすらないので、つらい感じでした。
ということで、composerを用意してるrepo(branch)から持ってくることにしました。それをカスタマイズしてheroku deployという感じですね。
なお、composer.lockもcommitする必要があります。
$ 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を読んでもいいんですけど、これ読んでやってるほうが時間かかると思う。
$ 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
<?php
if (!defined('GNUSOCIAL')) { exit(1); }
$config['site']['name'] = 'gnusocial';
$config['site']['server'] = 'app.herokuapp.com';
$config['site']['path'] = false;
$config['site']['ssl'] = 'never';
$config['db']['database'] = 'mysql://username:password@hostname/database';
$config['db']['type'] = 'mysql';
// Uncomment below for better performance. Just remember you must run
// php scripts/checkschema.php whenever your enabled plugins change!
//$config['db']['schemacheck'] = 'script';
gnu-socialをdocker等で試行錯誤した結果、ssl
とpgsql
はどうやっても機能しませんでした。特に、pgsql
はバグってると思います。lib/installer.php
みたいなファイルから書き直したんですが、docker上でもheroku上でもまともに動きませんでした。正直、よくわからない。
https://suriyadeepan.gitbooks.io/mesh-guide/content/gnu_social.html
あと、config.phpを置いたのはいいんですが、本来は、644でchmodされるファイルですから、そのパーミッションで行きたいんですけど、なぜかheroku run bash
, ls -l config.php
で確かめてみると、意図した権限じゃないんですよね。危険ですよ。composerでscript実行してるはずなんですけどね。(これはherokuの問題だと思う)
その他、gnu-socialはqvitterというpluginがあるのですが、qvitter+pleroma-feでdual bootできるっぽいので、今度試してみようかなーと思っています。(herokuでどこまでできるかわからないけど。directory構造とかnginx設定とかが来ると、ちょっと面倒なことになりそうですね…)
https://git.pleroma.social/pleroma/pleroma-fe/wikis/dual-boot-with-qvitter
追記
qvitter+pleroma-feできた。
ちょっとハマったところとかを解説。
qvitterは、urlに/index.phpを付けずにapiを呼び出すため、fancy urlsをenableにしていない場合、url間違いでapiを呼び出せない。そのためエラーを出すのだけど、herokuなどのPaaSは、nginxなどを直接操作できないため、なかなか面倒でした。
具体的には、nginx_app.conf
を作って、Procfileのオプションで指定してやればOKでした。
nginx_app.conf
location @rewriteapp {
# rewrite all to index.php
rewrite ^(.*)$ /index.php/$1 last;
}
Procfile
web: vendor/bin/heroku-php-nginx -C nginx_app.conf
メモ
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.cf
https://pleroma.syui.cf
http://qvitter.herokuapp.com
http://syui-chat.herokuapp.com
<span class="blue"></span>
span.blue {
display: inline-block;
width: 10px;
height: 10px;
border-radius: 50%;
background: #61bdcc;
margin: 0px 5px;
box-shadow: 0px 0px 10px #61bdcc;
}
<span class="red"></span>
span.red {
display: inline-block;
width: 10px;
height: 10px;
border-radius: 50%;
background: #f41b16b0;
margin: 0px 5px;
box-shadow: 0px 0px 10px #f41b16;
}
これ、他にも使えそうだなー。