このブログは2015年2月18日に更新を停止しました。すべての記事は https://chroju.github.io へ移行されています。

chefでさくらVPSの初期構築を全部自動化してみた

Chefでサーバー構築を全部自動化して、借りているさくらVPSに当ててみた。意地でも手作業はまったく入れない完全自動構築設定。これはよい。毎回手作業やらずに済むというのは、抜け漏れをなくすという点でも、構築時間を短縮するという面でも本当に楽。

前提

今回構築するサーバーの前提は次の通り。

  • CentOS 6.4環境で試行
  • vagrantを使って試験後、さくらVPSに対して適用
  • 基本の設定として以下を実施
    • 構築用のユーザーを作成
    • 構築用ユーザーにsudo権限を付与
    • 構築用ユーザーを秘密鍵認証でsshログイン許可
    • rootによるsshログインを禁止
    • パスワード認証によるログインを禁止
    • sshのポート番号を変更
    • ssh, http以外のアクセスをiptablesでシャットアウト
  • nginxを導入
  • 将来的にunicornを入れるための設定を準備
  • 極力サードパーティクックブックは使わない(ブラックボックス化が嫌)

レシピ

まず「どんなサーバーだろうとまず実行するだろうセキュリティ上の設定」はdefault_tasksというレシピにまとめた。

default_tasks

# sshdサービスの有効化
service "sshd" do
  supports :status => true, :restart => true, :reload => true
  action [ :enable, :start ]
end

# sshd_configの配置
template "sshd_config" do
  path "/etc/ssh/sshd_config"
  source "sshd_config.erb"
  owner "root"
  group "root"
  mode 0600
  notifies :restart, "service[sshd]"
end

# iptablesの設定
iptables_rule "iptables"

sshdの有効化と、templateを使ったsshd_configの配置、そしてiptablesの設定。このうちiptablesについてはサードパーティ・クックブックを使っている。

opscode-cookbooks/iptables

iptablesに挿入したい内容をtemplateで用意し、iptables_rule "template name"の形でレシピ内に書き込んでおくと、templateの内容がそのままiptablesに追加されるというシンプルなレシピ。まぁ、これぐらいはサードパーティ使ってもよいかな、と。iptablesを丸ごとtemplate化してアップロードするという手もあるにはあるのだが。

sshd_configはCentOSから引っ張ってきたものをそのまま流用し、Attributesを使っていろいろと書き換えられるように仕込んだ。長いので割愛するけど、設定可能なAttributesはこんな感じ。

  "sshd" : {
    "Port" : 22,
    "MaxStartups" : 10,
    "PermitRootLogin" : "yes",
    "RSAAuthentication" : "yes",
    "PubkeyAuthentication" : "yes",
    "AuthorizedKeysFile" : ".ssh/authorized_keys",
    "PasswordAuthentication" : "yes"
  },

よく編集する箇所を中心にAttributesとしてみた。他に設定したい項目が増えたら随時足していけば良いかなと。

users

ユーザーの作成は別のレシピに切り分け。

# wheelグループの作成
group "wheel" do
  gid 10
  action :create
end

# data bagsよりユーザーを作成
data_ids = data_bag('users')

data_ids.each do |id|
  # ユーザー作成
  u = data_bag_item('users', id)
  user u['username'] do
    password u['password']
    supports :manage_home => true, :non_unique => false
    group u['group']
    action [:create]
  end

  # ssh公開鍵配置用のディレクトリ作成
  directory "/home/#{id}/.ssh" do
    owner u["id"]
    group u["id"]
    mode 0700
    action :create
  end

  # ssh公開鍵の配置
  file "/home/#{id}/.ssh/authorized_keys" do
    owner u["id"]
    mode 0600
    content u["key"]
    action :create_if_missing
  end
end

sudoを許可するユーザーをwheelグループに入れるという定番設定。wheelを実際にsudo許可するのはまた別のレシピの仕事で、ここではグループとユーザーの作成のみ。

ユーザー作成にはdata_bagを使った。こちらを参考として作っている。ポイントとしては公開鍵まで登録させていること。fileリソースを使って実にシンプルな配置の仕方だけど、非常に楽ではある。

あまり詳しくは知らないのだが、data_bagについては暗号化する方法があるみたいなので、公開鍵を生でべろっと貼っとくのが気になる場合はそのへんも仕掛けておくと良さそう。

nginx

一番苦労した気がするし、あまり美しくない。。。

# nginxインストール
package "nginx" do
  action :install
end

# nginx有効化
service "nginx" do
  supports :status => true, :restart => true, :reload => true
  action [ :enable, :start ]
end

# templateからnginx.confを配置
template "nginx" do
  path "/etc/nginx/nginx.conf"
  source "nginx.conf.erb"
  owner "root"
  group "root"
  mode 0644
  notifies :reload, "service[nginx]"
end

# ディレクトリ作成
directories = ["/etc/nginx/sites-available","/etc/nginx/sites-enabled","/var/www","/var/www/#{node['nginx']['root']}","/var/www/#{node['unicorn']['root']}"]
directories.each do |directory_name|
  directory "#{directory_name}" do
    owner "root"
    group "root"
    mode 0644
    action :create
  end
end

# sites設定をtemplateごとに実行
node['nginx']['nginx_sites'].each do |site|
  # templateからsites-available配下に設定ファイルを配置
  template "nginx_sites_available" do
    path "/etc/nginx/sites-available/#{site}"
    source "nginx/#{site}.erb"
    owner "root"
    group "root"
    mode 0644
  end

  # sites-enabled配下へシンボリックリンクを配置
  link "/etc/nginx/sites-enabled/#{site}" do
    to "/etc/nginx/sites-available/#{site}"
    link_type :symbolic
    action :create
    notifies :reload, "service[nginx]"
  end

end

インストール、サービス有効化、templateからのnginx.confアップロードまでは良いとして。ディレクトリ作成がなんか。。。汚い。。。

/var/wwwを掘って、その中にウェブサイトのルートを置いたり、バーチャルホストの設定でsites-availableとかその辺を使っているもんで、ディレクトリ作成の量が多くなってしまった。いずれも設定は同じなので配列でやるのがベターだとは思うのだが、どうにも汚い。なんとかしたいとこではある。

あとはsites-availableにtemplateから設定ファイルを配置して、linkリソースでsites-enabledにシンボリックリンクを貼って終了。nginxの使い方はsites-availableを使うパターンだけではないので、もう少しスッキリさせることはできそう。

サードパーティ・クックブック

サードパーティとして導入したのはさっきのiptablesと、sudoの2つ。

opscode-cookbooks/sudo

sudoはvisudoをexecuteで走らせるってのも怖いし、その後ファイル編集をどうやったらいいのかよくわからんなってのと、sudoresファイルをtemplateで上げるってのもちょっと怖いという感覚的な問題からサードパーティ採用とした。

使い方としては簡単なもので、変数でsudoを許可するユーザーやグループを指定して、passwordlessとするかどうかを設定するぐらいで終わり。

  "authorization" : {
    "sudo" : {
      "groups" : ["wheel"],
      "passwordless" : "true"
    }
  },

冒頭でも書いた通り、なるべくサードパーティを使わない方針で行きたいんだけど、自力でレシピを書けないor書く自信がないところは已むなく実績のあるサードパーティを使ったという感じ。まぁサードパーティと言っても結局は人の手で書かれたレシピなので、自分でchef力上げれば相応なレシピは自力で書けるはず。このあたりは結局「どこまでchef力の向上に時間を割くか」という部分とトレードオフになるのかと。

今後やりたいこと

最終的にこのサーバーではRails動かしたいので、Rubypostgresqlのインストールを今後実装したい。あと「取りあえず動けばいいや」路線で一度作ってしまったので、もう少しメンテナンス性の高いもの、読みやすいレシピには育てたいところ。

汎用的に誰でもどんな用途でも使えるって感じではないと思うが、とりあえずGitHubには上げてみた。秘伝のタレのようにこれをじわじわ育てていくというのは良いなぁ。Linuxの勉強をするごとにきっと強靭なレシピとなっていくのだろう。まさに「レシピ」だな、これは。

まずは静的なページをってことで、近日中にプロフィールでも置いて公開する予定。

https://github.com/chroju/chef_web_server

参考