AR ホームベーカリー

オイラのアウトプット用ホームベーカリー!

530 Must issue a STARTTLS command first (Net::SMTPAuthenticationError)

自前運用の SMTP サーバから AWS SES に切り替える作業があったんだけど、表題のエラーが出て「!?」となっていた。

Must issue a STARTTLS command first

答えは全部ここに書いてあるんですが、ちゃんと暗号化して送信しろ、という話です。

エラー時の該当 smtp_settings がこちら。

    config.action_mailer.smtp_settings = {
      :enable_starttls_auto => false,
      :address => 'SMTP エンドポイント',
      :port => 587,
      :domain => 'SES で検証済みドメイン',
      :user_name => 'ユーザ名',
      :password => 'パスワードクレデンシャル'
    }

:enable_starttls_auto => false ハイ、そうですね。 ということで、こうする。

    config.action_mailer.smtp_settings = {
      :enable_starttls_auto => true,
      :address => 'SMTP エンドポイント',
      :port => 587,
      :domain => 'SES で検証済みドメイン',
      :user_name => 'ユーザ名',
      :password => 'パスワードクレデンシャル'
    }

これでオッケー!

送信できる暗号化の組み合わせ

調べてたら以下を見つけた。

2018-04-30-rails-and-aws-ses.md · GitHub

もし「暗号化利用できる環境なのに送信できない!」という場合は、ポート番号を 587 465 あたりで切り替えるとうまく行くかもしれません。

CloudFront にとりあえずの Basic 認証

dev.classmethod.jp

Lambda@Edge に function 配置してたおじさんだった (node v6 とか v8 の時代マン) ので、えらいお手軽に出来るようになったなー、という感じだった。

いやまあ Basic 認証くらい CloudFront 標準機能で用意しとけよ、という感じはある。

M1 への homebrew パッケージ移行

MBP 2019 (13inch, Core i-5) から MBP 2021 (14inch, M1Pro) に移行しよーっと、という感じで作業している。

アーキテクチャIntel から AppleSilicon に変更になるので、 TimeMachine から環境復旧せずにイチから作成するなどしている。 2015 年あたりから引き継いでいるので、実に 7 年ぶりという感じ。

秘伝のタレが結構多くなっており、「あれが動かないこれが動かない」みたいになっている。

brewfile

今まで手動で Applications に配置したり homebrew でインストールしたり、とわりと自由にやっていたけど、コレを機に homebrew に存在するものは brew 経由でインストールに統一することにした。

差し当たっては、現時点で MBP 2019 にインストールしている brew 管理のパッケージ一覧を書き出す。

brew bundle dump

これで ~/brewfile というのが生成される。 あとは Airdrop なり GoogleDrive・NAS などを用いて、 MBP 2021 側へ持っていく。

brew bundle

以下のコマンドで、 ~/brewfile の内容からパッケージを再インストールできる。

brew bundle

僕の環境では、利用していたもののうち gcc@4.9 python@2 mysql-shell がインストールできなかった。

gcc@4.9 はたしか rbenv でインストールする古い Ruby で OpenSSL ext の設定時にうまくいかなく、色々やる時に入れたヤツな気がする。 今の rbenv はインストールする Ruby バージョンに応じた OpenSSL も (rbenv 内で) 用意してくれるので、まあ不要でしょう。

python@2 は (開発・)保守・運用に関わってる製品の、 i18n 的なファイルを出力するのに必要で未だに利用している。 これは anyenv に pyenv 追加して解決した。

mysql-shell はなにかの記事を見てインストールしたけど、結局おま環だけ便利になっても他人 (社外含む) や商用環境に導入しづらいので使わなくなった。 のでこれはインストールできなくても問題ない。

ということで

以外となんとか移行できそうだな、という感じです。 Windows がすごい稀に必要になるんだけど、それはもう物理マシン用意してなんとかやっていき、というトコで。

puma.sock failed (111: Connection refused) while connecting to upstream

Nginx で puma の unix socket を参照するように設定した所、 502 が連続するので「何事……?」となっていた。

integration という RAILS_ENV を増やしていたのが原因かと思っていたけど、単純なミスだった。

しらべる

Rails 側のログには何も記録されていないので、Nginx の error.log を確認する。

2022/08/22 22:59:28 [crit] 23808#23808: *66 connect() to unix:///var/www/example/tmp/sockets/puma.sock failed (2: No such file or directory) while connecting to upstream, client: 169.254.169.254, server: *.example.com, request: "GET / HTTP/1.1", upstream: "http://unix:///var/www/example/tmp/sockets/puma.sock:/", host: "www.example.com"

upstream を http でアクセスしとるやんけ、なんやこいつ……。 と思ったが、よく見たら No such file or directory が出ている。

確認したところ、 /var/www/example/tmp/ までは存在するが、更に配下の /sockets/ が存在していなかった。

mkdir -p /var/www/example/tmp/sockets/

これで解決、と思ったら次はこう。

2022/08/22 23:03:33 [error] 23808#23808: *102 connect() to unix:///var/www/example/tmp/sockets/puma.sock failed (111: Connection refused) while connecting to upstream, client: 169.254.169.254, server: *.example.com, request: "GET / HTTP/1.1", upstream: "http://unix:///var/www/example/tmp/sockets/puma.sock:/", host: "www.example.com"

Connection refused ……? もうわかなんなくなってしまったので、 systemd から起動をやめて直接 puma を起動してみた。

/bin/bash -lc 'RAILS_ENV=integration bundle exec puma -C config/puma.integration.rb'
Puma starting in single mode...
* Puma version: 5.6.4 (ruby 3.1.0-p0) ("Birdie's Version")
*  Min threads: 5
*  Max threads: 5
*  Environment: integration
*          PID: 9447
* Listening on unix:///var/www/example/tmp/sockets/puma.sock
bundler: failed to load command: puma (/var/www/example/vendor/bundle/ruby/3.1.0/bin/puma)
/var/www/example/vendor/bundle/ruby/3.1.0/gems/puma-5.6.4/lib/puma/launcher.rb:248:in `write': No such file or directory @ rb_sysopen - tmp/pids/server.pid (Errno::ENOENT)

今度は tmp/pids/ が無いんけワレ!

mkdir -p /var/www/example/tmp/pids/

これで無事 puma が起動できたので、改めて systemd からも起動することを確認して、ブラウザ側からも閲覧できることを確認して終了。

利用していた IaC コードの実装に問題があって、コンテナ環境から素朴な Rails のウェブ三層アプリケーション環境に突貫で移行したけど、久しぶりすぎて結構忘れていた。

RHEL 系の eth と ens の違い

eth は RHEL6 やそのクローンまで、 ens | eno は RHEL7 以降やそのクローン、というざっくりとした理解だったんだけど、いい加減アレだな、と思って調べてみた。

enakai00.hatenablog.com

はえーなるほど、 ensPCI-Express 接続で enoオンボードだったのか。 基本的にサーバってなると ens 割り振られてるからそんなもんだと思ってた。

ワイヤレス、は見たこと無いっすね……。 一度ためしてみるか。

Access-Control-Allow-Headers のワイルドカード

認証情報付きのリクエストでは、特別な意味のない "*" というヘッダー名として扱われます。

developer.mozilla.org

へー知らなかった。たくさんヘッダを追加する機会があって「これ開発環境だし * にできねえの?」と思って調べたら見つけた次第。

ちなみに似たような CORS 兄弟の Access-Control-Allow-Origin だと、ワイルドカードを指定した時、認証情報付きだとエラーになるとのこと。

資格情報がある時にワイルドカードを使用すると、エラーを返します。

developer.mozilla.org

純粋に似た名前の値をたくさん設定しないといけないのと、無効化する、という設定がないこと、 CORS 自体の動作がわかりづらくてこのあたり本当苦手である。

セキュリティが大事なのはわかるけど、もうちょっとなんとかならんかったのか。

Route53 の A レコードは A レコードだけど A レコードじゃない (ので CNAMEAlreadyExists したら使え) という話

普通「A レコード!」っていうと、 IP アドレスと関連付くアレを想像する。

ただ AWS だと A は A でも A(LIAS) ということらしい。 よくよく Route53 で A レコード選択時の項目を見ると、 IPv4 アドレスと一部の AWS リソースにトラフィックをルーティングしますと書かれている。

A

今まであんまり気にせず「IP 関連付けるときは A! 既存のドメインに転送するときは CNAME!」って感じで使ってきていたのだけど、 Terraform でリソース管理しはじめて CNAMEAlreadyExists エラーが発生して、ようやく調べて理解した次第。

dev.classmethod.jp

クラスメソッド大先生のこのあたりの記事を読んで、「あーこれ A 指定でサジェスト出てくるリソース選べばえんやな……、出ないけど該当の CloudFront ドメイン突っ込んだらいけたわ! ガハハ!」みたいになっていた。今まで CloudFront に転送する時、 CNAME ばっかり設定していたので Route53 を使う時は A を設定するように改めたい気持ちになった。

AWS むずくねー?

参考

prograshi.com

yohei-a.hatenablog.jp