Ansibleでnginxを構築

Ansibleで、vagrant２台にnginxをインストールし、セキュアな通信ができるように設定します。

# 準備

## vagrant

```shell-session
$ mkdir ansible_nginx
$ cd ansible_nginx
$ vagrant init ubuntu/trusty64
```

```shell-session
$ vi Vagrantfile
```
```rb
Vagrant.configure(2) do |config|

  # すべてのマシンで同じ鍵を使う
  config.ssh.insert_key = false
  
  config.vm.define "vagrant1" do |vagrant1|
    vagrant1.vm.box = "ubuntu/trusty64"
    vagrant1.vm.network "forwarded_port", guest: 80, host: 8080
    vagrant1.vm.network "forwarded_port", guest: 443, host: 8443
  end
  config.vm.define "vagrant2" do |vagrant2|
    vagrant2.vm.box = "ubuntu/trusty64"
    vagrant2.vm.network "forwarded_port", guest: 80, host: 8081
    vagrant2.vm.network "forwarded_port", guest: 443, host: 8444
  end
end
```
```shell-session
$ vagrant up
```

## ansible.cfg

```shell-session
$ vi ansible.cfg
```
```ini
[defaults]
hostfile = hosts
remote_user = vagrant
private_key_file = ~/.vagrant.d/insecure_private_key
host_key_checking = False
```
```shell-session
$ vi hosts
```
```ini
[webservers]
vagrant1 ansible_ssh_host=127.0.0.1 ansible_ssh_port=2222
vagrant2 ansible_ssh_host=127.0.0.1 ansible_ssh_port=2200
```

## サーバー接続確認

```shell-session
$ ansible webservers -m ping
vagrant2 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
vagrant1 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
```

# Playbookの設定

## nginxのplaybook

```shell-session
$ vi web-tls.yml
```
```yaml
- name: Configure webserver with nginx and tls
  hosts: webservers
  become: True
  vars:
    key_file: /etc/nginx/ssl/nginx.key
    cert_file: /etc/nginx/ssl/nginx.crt
    conf_file: /etc/nginx/sites-available/default
    server_name: localhost
  tasks:
    - name: install nginx
      apt: name=nginx update_cache=yes cache_valid_time=3600

    - name: create directories for ssl certificates
      file: path=/etc/nginx/ssl state=directory

    - name: copy TLS key
      copy: src=files/nginx.key dest={{ key_file }} owner=root mode=0600
      notify: restart nginx

    - name: copy TLS certificate
      copy: src=files/nginx.crt dest={{ cert_file }}
      notify: restart nginx

    - name: copy nginx config file
      template: src=templates/nginx.conf.j2 dest={{ conf_file }}
      notify: restart nginx

    - name: enable configuration
      file: dest=/etc/nginx/sites-enabled/default src={{ conf_file }} state=link
      notify: restart nginx

    - name: copy index.html
      template: src=templates/index.html.j2 dest=/usr/share/nginx/html/index.html mode=0644

  handlers:
    - name: restart nginx
      service: name=nginx state=restarted
```

### Play

+ playbookはplayのリスト
+ playは、ホストとタスクを結びつけるもの
    + 設定するホストの集合
    + ホスト上で実行するタスクのリスト

#### name

+ playの内容を示すコメント

#### become(sudo)

+ rootユーザとしてsudoした上ですべてのタスクを実行

#### vars

+ 変数と値のリスト


### タスク

+ web-tls.ymlのplaybookでいうと、７つのタスクを持つ１つのplayが含まれている

### モジュール

#### apt

+ パッケージマネージャーのaptを使ってインストールや削除を行う

#### copy

+ ファイルをローカルマシンからホストにコピー

#### file

+ ファイル、シンボリックリンク、ディレクトリの属性を設定

#### service

+ サービスの起動、停止、再起動を行う

#### template

+ ファイルをテンプレートから生成し、そのファイルをホストにコピー
+ テンプレートエンジンとしてJinja2を採用

### ハンドラ

+ Ansibleがサポートしている条件つき処理の１つ
+ タスクから通知されたときにのみ実行される。タスクは、タスクによってシステムの状態を変化させたとAnsibleが認識したときにのみ、通知を送る。
+ ハンドラが実行されるのは、タスクがすべて実行された後であり、通知が複数送られていても、実行されるのは一度限り。
+ ハンドラは、通知が送られた順序ではなく、必ずplay中に書かれた順序で実行される。

## nginxの設定テンプレート

### nginx.conf

```shell-session
$ vi templates/nginx.conf.j2
```
```
server {
  listen 80 default_server;
  listen [::]:80 default_server ipv6only=on;
  listen 443 ssl;

  root /usr/share/nginx/html;
  index index.html index.htm;

  server_name {{ server_name }};
  ssl_certificate {{ cert_file }};
  ssl_certificate_key {{ key_file }};

  location / {
          try_files $uri $uri/ =404;
  }
}
```

### index.html

```shell-session
$ vi templates/index.html.j2
```
```html
<html>
  <head>
    <title>Welcome to ansible</title>
  </head>
  <body>
    <h1>nginx, configured by Ansible</h1>
    <p>If you can see this, Ansible successfully installed nginx.</p>
    
    <p>{{ ansible_managed }}</p>
  </body>
</html>
```

# Playbookの実行

```shell-session
$ ansible-playbook web-tls.yml
```
```shell-session
PLAY [Configure webserver with nginx and tls] **********************************

TASK [setup] *******************************************************************
ok: [vagrant2]
ok: [vagrant1]

TASK [install nginx] ***********************************************************
changed: [vagrant2]
changed: [vagrant1]

TASK [create directories for ssl certificates] *********************************
changed: [vagrant1]
changed: [vagrant2]

TASK [copy TLS key] ************************************************************
changed: [vagrant2]
changed: [vagrant1]

TASK [copy TLS certificate] ****************************************************
changed: [vagrant1]
changed: [vagrant2]

TASK [copy nginx config file] **************************************************
changed: [vagrant1]
changed: [vagrant2]

TASK [enable configuration] ****************************************************
ok: [vagrant1]
ok: [vagrant2]

TASK [copy index.html] *********************************************************
changed: [vagrant2]
changed: [vagrant1]

RUNNING HANDLER [restart nginx] ************************************************
changed: [vagrant2]
changed: [vagrant1]

PLAY RECAP *********************************************************************
vagrant1                   : ok=9    changed=7    unreachable=0    failed=0
vagrant2                   : ok=9    changed=7    unreachable=0    failed=0
```