playbookは
https://github.com/hnakamur/ansible-playbooks/tree/master/roles/mysql
にあります。mysql/serverロールはサーバのインストールで、mysqlロールを指定するとそれに加えて日時バックアップの設定も行います。
以下は試行錯誤のメモです。
MySQL 5.6ではrootの初期パスワードが設定済みで期限切れになっているのでまず変更しないと使えない
手動の場合はmysql_secure_installationを実行して変更すれば良いのでしょうが、Ansibleから自動で実行したいのでmysql_secure_installationの中身を読んで、等価な処理を書きました。
こういうスクリプトを作るときは対話方式だけではなくて、コマンドラインオプションで指定すれば対話不要になるようにしていただけるとありがたいですね。
なお、対話方式のスクリプトに対してexpectを使って動かす記事がchefですけどあったので、貼っておきます。
Codrspace - Automate the non-automated with expect and Chef by glenbot
個人的にはexpectを使うのは、依存する部品が増えるので最後の手段かなと思っています。
本題に戻すと、今回キモとなるのはmysqlの--connect-expired-passwordオプションです。
MySQL :: MySQL 5.6 Reference Manual :: 4.5.1.1 mysql Options
これを指定してmysqlに接続して以下の様なSQLでパスワードを変更します。
SET PASSWORD FOR root@localhost=PASSWORD('新しいパスワード');
初期パスワードは/root/.mysql_secretの中に書かれています。
mysqlのドキュメントには--passwordオプションでパスワードを指定するのは、psで他のユーザにパスワードを見られてしまうので安全ではないと書かれています。
MySQL :: MySQL 5.6 Reference Manual :: 6.1.2.1 End-User Guidelines for Password Security
代わりに~/.my.cnfというファイルに以下の様な設定を書くのがお勧めらしいです。
[client]
password=パスワード
また--defaults-file=/path/to/my.cnfのように指定すれば、~/.my.cnf以外のパスも設定できます。
--connect-expired-passwordオプションも以下のように書くことで~/my.cnfに含めることが出来ます。
[client]
password=パスワード
connect-expired-password
これで--defaults-file=/root/.tmp.my.cnfと指定してmysqlに接続して、パスワードを変更し、新しいパスワードで~/.my.cnfを作るようにしました。するとその後はコマンドラインでパスワードを指定しなくても接続できます。
他のユーザに見せたくないファイルを作るときは作成後にchmodより先にumask 0077を実行するのがお勧め
なお、my.cnfは他のユーザから見えないように0400とか0600といったパーミションにします。ファイルを作成してからchmodで変更する手もありますが、変更までの間に読まれる危険があります。ので、先にumask 0077を実行してから作成するほうが良いです。この場合はchmodは不要です。