エロサイトの作り方

2013年11月から勉強しながらエロサイトを作っています。

Ansibleで環境構築(4) - OS環境を整える

前回まででベストプラクティスな構成になったので、今回から中身を埋めていきます。

commonロールでやること

まずはcommonロールの中で、OS設定を変えていきたいと思います。

やりたいのはだいたい以下のこと。

  • Ansible依存の設定
  • システム更新(aptitude update/upgrade)
  • ログイン用ユーザー作成
  • SSHの設定変更(ポート変更や証明書認証)
  • よく使うコマンドを入れる

意外といっぱいある。

main.yml

main.ymlにはタスクは記述せず、別のファイルを読み出すだけにします。

./roles/common/tasks/main.yml

---
- include: ssh.yml
- include: ansible.yml
- include: system.yml
- include: user.yml
- include: utility.yml

なお、各ファイル名内のタスクには同名のタグをつけるようにしており、ansible-playbook site.yml -t utilityなどとやれば特定のファイルのものだけ実行できるようにしています。

ansible.yml

Ansibleを使う上で依存しているものを設定する場所です。

./roles/common/tasks/ansible.yml

---
- name: install python-pycurl
  apt: pkg=python-pycurl state=latest
  tags: ansible

一つしかないのですが、予めpython-pycurlを入れておかないと、apt_repositoryモジュールなどでエラーになるので、ここで入れておきます。

system.yml

システム全体の更新をかけるところです。

./roles/common/tasks/system.yml

---
- name: update package-list
  action: apt update_cache=yes
  tags: system

- name: upgrade package
  apt: upgrade=dist
  tags: system

鬼時間がかかるので、ここに書くのは適切じゃないような気がしている。

cron設定にして、勝手にupgradeかけさせるのがいいのかな?

ssh.yml

SSHのポート設定変更などを行う部分です。

すごく苦労したが、まだ欠点がある。

~/.ssh/config

Host 192.168.33.*
  IdentityFile ~/.vagrant.d/insecure_private_key
  User vagrant
  Port 11122
  StrictHostKeyChecking no
  UserKnownHostsFile=/dev/null

最初にSSHの設定に追加しておきます。

ポート番号は任意ですが、変更後のポートを書く関係上、最初に実行されるタスクがssh.ymlになるようにしておかないと動かなくなります。

./roles/common/tasks/ssh.yml

---
- name: test default ssh port
  local_action: wait_for timeout={{ ssh_timeout }} port={{ ssh_port }} host={{ inventory_hostname }}
  sudo: false
  register: test_ssh
  ignore_errors: True
  tags: ssh

- debug: var=test_ssh

- name: set ansible_ssh_port to default
  set_fact: ansible_ssh_port=22
  when: test_ssh.elapsed == ssh_timeout
  tags: ssh

- name: ensure public key is in authorized_keys
  authorized_key: user={{ ansible_ssh_user }} key="{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
  when: test_ssh.elapsed == ssh_timeout
  tags: ssh

- name: be sure ssh is configured
  template: src=etc/ssh/sshd_config.j2 dest=/etc/ssh/sshd_config owner=root group=root
  when: test_ssh.elapsed == ssh_timeout
  tags: ssh

- name: restart ssh
  service: name=ssh state=restarted
  when: test_ssh.elapsed == ssh_timeout
  tags: ssh

- name: be sure ssh is running and enabled
  service: name=ssh state=running enabled=yes
  when: test_ssh.elapsed == ssh_timeout
  tags: ssh

やっていることとしては、変更後のポート(ssh_port変数)へ接続しにいき、接続できなかったらauthorized_keyとSSHdの設定変更を行ってサービスの再起動をする、というものです。

終わってみるとなんて事ない行数だけど、1週間位あれこれ悩んだり放置したりしてた……

なお、変数とテンプレートファイルを外だししています。

./roles/common/vars/main.yml

---
ssh_port: 11122
ssh_timeout: 3

外だしの変数です。

リモート接続前提ならタイムアウト時間は長くしたほうがいいかも。

./roles/common/templates/etc/ssh/ssh_config.j2

# changed
# - Port {{ ssh_port }}
# - PermitRootLogin no
# - PasswordAuthentication no
# - PubkeyAuthentication yes
# - UsePAM no

# Package generated configuration file
# See the sshd_config(5) manpage for details

# What ports, IPs and protocols we listen for
Port {{ ssh_port }}
# Use these options to restrict which interfaces/protocols sshd will bind to
#ListenAddress ::
#ListenAddress 0.0.0.0
Protocol 2
# HostKeys for protocol version 2
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_dsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
#Privilege Separation is turned on for security
UsePrivilegeSeparation yes

# Lifetime and size of ephemeral version 1 server key
KeyRegenerationInterval 3600
ServerKeyBits 768

# Logging
SyslogFacility AUTH
LogLevel INFO

# Authentication:
LoginGraceTime 120
PermitRootLogin no
StrictModes yes

RSAAuthentication yes
PubkeyAuthentication yes
#AuthorizedKeysFile %h/.ssh/authorized_keys

# Don't read the user's ~/.rhosts and ~/.shosts files
IgnoreRhosts yes
# For this to work you will also need host keys in /etc/ssh_known_hosts
RhostsRSAAuthentication no
# similar for protocol version 2
HostbasedAuthentication no
# Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication
#IgnoreUserKnownHosts yes

# To enable empty passwords, change to yes (NOT RECOMMENDED)
PermitEmptyPasswords no

# Change to yes to enable challenge-response passwords (beware issues with
# some PAM modules and threads)
ChallengeResponseAuthentication no

# Change to no to disable tunnelled clear text passwords
PasswordAuthentication no

# Kerberos options
#KerberosAuthentication no
#KerberosGetAFSToken no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes

# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes

X11Forwarding yes
X11DisplayOffset 10
PrintMotd no
PrintLastLog yes
TCPKeepAlive yes
#UseLogin no

#MaxStartups 10:30:60
#Banner /etc/issue.net

# Allow client to pass locale environment variables
AcceptEnv LANG LC_*

Subsystem sftp /usr/lib/openssh/sftp-server

# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the ChallengeResponseAuthentication and
# PasswordAuthentication.  Depending on your PAM configuration,
# PAM authentication via ChallengeResponseAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
UsePAM no
UseDNS no

長いですが、変更しているところは上の方にコメントで書いてあるところだけです。

{{ ssh_port }}は勝手にバインドしてくれます。便利。

user.yml

ユーザーを追加する部分です。

./roles/common/tasks/user.yml

---
- name: create shell user.
  user:
    name={{ user_name }}
    uid={{ user_uid }}
    groups={{ user_groups }}
    password={{ user_password }}
    shell=/bin/bash
  tags: user

- name: ensure public key is in authorized_keys
  authorized_key: user={{ user_name }} key="{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
  tags: user

こちらも変数にしました。

./roles/common/vars/main.yml

user_name: hentai-kun
user_groups: sudo,www-data

./host_vars/192.168.33.10

user_uid: 1100
user_password: $1$SomeSalt$/jbIwfYCu0MxPBND2EtRH.

production/stageのようなInventory File単位で切り替えたかったのですが、記載場所が無かったのでhost_varsに書いています。

サーバーが増えると破綻する場所なので、後で変更したい。

なお、パスワードは暗号化済みのを渡さないといけないらしく、事前にコマンドで作っておきます。

$ python -c 'import crypt; print crypt.crypt("password", "$1$SomeSalt$")'

utility.yml

良く使うものを入れているだけです。

./roles/common/tasks/utility.yml

---
- name: update package-list
  action: apt update_cache=yes
  tags: utility

- name: install unzip
  apt: pkg=unzip state=latest
  tags: utility

- name: install curl
  apt: pkg=curl state=latest
  tags: utility

- name: install vim
  apt: pkg=vim state=latest
  tags: utility

- name: install git
  apt: pkg=git state=latest
  tags: utility

- name: install dstat
  apt: pkg=dstat state=latest
  tags: utility

特にUbuntuはカーソル移動ができないvimがデフォルトで使われててわーーってなる。

ところで……

SSHポート変更を行うと、vagrant sshで接続できなくなるんですよね。

==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2222
    default: SSH username: vagrant
    default: SSH auth method: private key
    default: Warning: Remote connection disconnect. Retrying...
    default: Warning: Remote connection disconnect. Retrying...
    default: Warning: Remote connection disconnect. Retrying...

起動時にも何やらエラーが出ているし。

Vagrantの設定は、

config.ssh.port = 2222
config.ssh.guest_port = 11122
config.vm.network :forwarded_port, guest: 11122, host: 2222, id: "ssh", auto_correct: true

あたりで動きそうな気がするんですが、変更しても効果なさそうなんですよね。

まあ、sshコマンドなら接続できるので、そんなに実害はないんですが。