13
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Phoenixで作ったアプリをNginxを前においた構成でサーバーにデプロイしたらChannelの機能が動かなかったことを解決した話[Elixir]

Last updated at Posted at 2020-03-05

はじめに

  • Programming Phoenix >= 1.4 という本がありまして、英語をよちよち読みながら一周しました
  • ところどころまだまだ理解できていないところがありまして、もう一周してみることにしました
  • この本は、コード例は省略がないので、二周目は説明のところはあまり読まないことにして、コードのところだけみて写してみることにしました
  • ちょっとした機能追加もしてみました
  • できあがったものをサーバーにデプロイしてみました
  • 限定公開的な感じでアクセス元のIPは絞っています
  • 本の通りにやると、Channelsを利用したチャット機能がつくれます
  • ところがこのチャット機能が、ローカルでは動いていたはずなのに、デプロイした実行環境下では、うんともすんともいいませんでした
  • こんな感じのエラーがブラウザのJavaScriptコンソールにでていました
WebSocket connection to to wss://hogehoge.com/socket/websocket?token=<token>&vsn=2.0.0' failed: Error during WebSocket handshake: Unexpected response code: 400

結論

詳細

  • 以下、もう少し詳しくかいておきます
  • それぞれ専門にかかれている良記事があるとおもいますが、ざっと流れを記録しておきます

構成

  • EC2を使いました
    • Ubuntu 18.04.3 LTS
    • PostgreSQL 10.12
    • nginx 1.14.0
    • node v12.16.1
    • Erlang 22.1.4
    • Elixir 1.9.4-otp-22
  • セキュリティグループを使ってアクセス元のIPを限定しました
  • Let's Encryptを使って証明書を取得して、httpsにします
    • アクセス元IPを絞っているので、DNS認証で取得します

1. UbuntuがインストールされたEC2をつくる

  • 省略

2. 限られたIPからのインバウンドを許可したセキュリティグループをつくってEC2に関連づける

  • 省略

3. Ubuntuにいろいろインストールする

% ssh -i ~/.ssh/secret.pem ubuntu@<サーバーのIP>

3-1. PostgreSQL

> sudo apt update
> sudo apt install postgresql postgresql-contrib
> sudo -u postgres psql postgres
\password postgres

3-2. node

3-3. Erlang と Elixir

  • asdf-vmを使ってインストールします
> git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.7.7
> echo -e '\n. $HOME/.asdf/asdf.sh' >> ~/.bashrc
> echo -e '\n. $HOME/.asdf/completions/asdf.bash' >> ~/.bashrc
> source ~/.bashrc
> sudo apt install \
  automake autoconf libreadline-dev \
  libncurses-dev libssl-dev libyaml-dev \
  libxslt-dev libffi-dev libtool unixodbc-dev \
  unzip curl
> asdf plugin add erlang
> asdf plugin add elixir
> asdf install erlang 22.1.4
> asdf global erlang 22.1.4
> asdf install elixir 1.9.4-otp-22
> asdf global elixir 1.9.4-otp-22

3-4. Let's Encrypt を使って証明書を取得する

> apt -y install certbot
> sudo certbot certonly --server https://acme-v02.api.letsencrypt.org/directory --manual --preferred-challenges dns -d hogehoge.com --email torifukukaiou@hogehoge.com
/etc/nginx/conf.d/hogehoge.conf
server {
  listen 80;
  server_name hogehoge.com;
  return 301 https://$host$request_uri;
}

server {
  listen       443 ssl http2 default_server;
  listen       [::]:443 ssl http2 default_server;
  server_name  hogehoge.com;
  root         /usr/share/nginx/html;

  ssl_certificate "/etc/letsencrypt/live/hogehoge.com/fullchain.pem";
  ssl_certificate_key "/etc/letsencrypt/live/hogehoge.com/privkey.pem";
  # It is *strongly* recommended to generate unique DH parameters
  # Generate them with: openssl dhparam -out /etc/pki/nginx/dhparams.pem 2048
  # ssl_dhparam "/etc/pki/nginx/dhparams.pem";
  ssl_session_cache shared:SSL:1m;
  ssl_session_timeout  10m;
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  ssl_ciphers HIGH:SEED:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!RSAPSK:!aDH:!aECDH:!EDH-DSS-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:!SRP;
  ssl_prefer_server_ciphers on;

  location / {
    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 https;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_redirect off;
    proxy_set_header X-Real-IP $remote_addr;
    
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_http_version 1.1;
    proxy_pass http://127.0.0.1:4000;
  }
}
> sudo nginx -t
> sudo nginx -s reload

4. Phoenixを動かす

$ mix phx.gen.secret
REALLY_LONG_SECRET
~/.bashrc
export SECRET_KEY_BASE="REALLY_LONG_SECRET"
export DATABASE_URL="ecto://postgres:postgres@localhost:5432/hello_prod"
  • ↑こういうのを書き足します
  • 公式に書いてある ecto://USER:PASS@HOST/database => これを上のように書き換えるわけですが、いわれてみれば確かになるほど! なのですが悩みました
    • ectoのところをこれもあくまでも例で、MySQLだとかわったりするのだろうと変に考えてpostgresqlにしたりして余計な変更をしていたせいです:baby_tone2:
  • いつものようにpiacere_exさんの記事に助けてもらいました
config/prod.exs
config :hello, HelloWeb.Endpoint,
  url: [host: "hogehoge.com", port: 443],
  cache_static_manifest: "priv/static/cache_manifest.json"
$ source ~/.bashrc 
$ mix deps.get --only prod
$ MIX_ENV=prod mix compile
$ MIX_ENV=prod mix ecto.create
$ MIX_ENV=prod mix ecto.migrate
$ npm run deploy --prefix ./assets
$ mix phx.digest
$ MIX_ENV=prod nohup mix phx.server &
  • /etc/nginx/conf.d/hogehoge.conf の設定が足りなくてチャット機能が動かなかったわけですが、私の実感としては、ローカルだと動いていたはずなのにー と、最後の最後のほうで右往左往していました

  • いろいろありましたが、無事動いてよかったです :rocket:

    • 時間にすると、4のところが一番時間はかかっていないのですが、なぜ動かないんだーと途方にくれていたので一番時間を使ったような気分になりました
13
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?