2026年10月27日

2026年10月27日

AnsibleでWordPressのサーバー構築を自動化する手順(Ubuntu 24.04)

Ansible は、サーバーの設定手順を YAML の「プレイブック」に書いておき、SSH 経由で何台にでも同じように適用できる構成管理ツールです。WordPress の環境を何度も作る場合や、開発・検証・本番をそろえたい場合に、手作業の漏れや差を減らせます。

この記事では、Ansible で Ubuntu 24.04 のサーバーに Apache・PHP・MariaDB を入れ、WordPress を配置するまでを自動化します。2026年11月時点の Ubuntu 24.04 の Ansible(ansible-core 2.16.3)で、ファイアウォール以外のタスクを実行し、WordPress のインストール画面が開くこと、2回目の実行で変更が0件になることを確認しています。

全体の流れ

作業 内容
1 手元の PC(操作する側)に Ansible を入れる
2 対象サーバーの一覧(インベントリ)を書く
3 変数と、Ansible Vault で暗号化したパスワードを用意する
4 wp-config.php と Apache の設定のテンプレートを書く
5 プレイブックを書く
6 実行して、ブラウザーで WordPress のインストールを済ませる

対象サーバー側に Ansible を入れる必要はありません。SSH で接続でき、sudo が使えるユーザーがあれば動きます。

手順1: Ansibleをインストールする

操作する側の PC(Ubuntu の例)に入れます。

sudo apt update
sudo apt install ansible
ansible --version

Ubuntu の ansible パッケージには、この記事で使う community.mysql と community.general のコレクションも含まれています。Ubuntu 以外では、公式ドキュメントの案内(pipx での導入など)に従ってください。

作業用のディレクトリを作ります。最終的に次の形になります。

ansible-wordpress/
├── inventory.ini
├── site.yml
├── group_vars/
│   └── wordpress.yml
├── vars/
│   └── secrets.yml
└── templates/
    ├── wp-config.php.j2
    └── wordpress.conf.j2
mkdir -p ~/ansible-wordpress/{group_vars,vars,templates}
cd ~/ansible-wordpress

手順2: インベントリを書く

inventory.ini に、対象サーバーを書きます。[wordpress] はグループ名で、プレイブックの hosts: と合わせます。

[wordpress]
web1 ansible_host=203.0.113.10 ansible_user=ubuntu

203.0.113.10 と ubuntu は、自分のサーバーの IP アドレスと SSH ユーザーに変えます。SSH 鍵でログインできる状態にしてから、接続を確かめます。

ansible -i inventory.ini wordpress -m ping

"ping": "pong" が返れば、Ansible から操作できます。

手順3: 変数とパスワードを用意する

group_vars/wordpress.yml に、wordpress グループ全体で使う変数を書きます。

---
wp_dir: /var/www/wordpress
wp_db_name: wordpress
wp_db_user: wordpress
wp_server_name: example.com

DB のパスワードは、Ansible Vault で暗号化したファイルに入れます。

ansible-vault create vars/secrets.yml

Vault のパスワードを2回入力すると編集画面が開くので、次のように書いて保存します。

---
wp_db_password: ここに英数字だけの長いパスワード

このパスワードは wp-config.php の中に '…' で囲んで書き込まれるため、英字と数字だけで作ると安全です(openssl rand -hex 24 などで作れます)。保存したファイルは暗号化されているので、Git に入れても中身は読めません。Vault のパスワード自体はリポジトリに入れないでください。

手順4: テンプレートを書く

templates/wp-config.php.j2 は、wp-config.php の元になるテンプレート(Jinja2 形式)です。{{ … }} の部分に変数が入り、{% for %} の部分は繰り返しになります。

<?php
define( 'DB_NAME', '{{ wp_db_name }}' );
define( 'DB_USER', '{{ wp_db_user }}' );
define( 'DB_PASSWORD', '{{ wp_db_password }}' );
define( 'DB_HOST', 'localhost' );
define( 'DB_CHARSET', 'utf8mb4' );
define( 'DB_COLLATE', '' );

{% for key in ['AUTH_KEY', 'SECURE_AUTH_KEY', 'LOGGED_IN_KEY', 'NONCE_KEY', 'AUTH_SALT', 'SECURE_AUTH_SALT', 'LOGGED_IN_SALT', 'NONCE_SALT'] %}
define( '{{ key }}', '{{ lookup('ansible.builtin.password', '/dev/null', length=64, chars=['ascii_letters', 'digits']) }}' );
{% endfor %}

$table_prefix = 'wp_';

define( 'WP_DEBUG', false );

if ( ! defined( 'ABSPATH' ) ) {
	define( 'ABSPATH', __DIR__ . '/' );
}

require_once ABSPATH . 'wp-settings.php';

認証用キー(AUTH_KEY など8つ)は、password ルックアップで64文字のランダムな文字列を作って入れています。プレイブック側で「既に wp-config.php があれば上書きしない」設定にするので、2回目以降の実行でキーが変わってログインが切れることはありません。

templates/wordpress.conf.j2 は、Apache のサイト設定です。

<VirtualHost *:80>
    ServerName {{ wp_server_name }}
    DocumentRoot {{ wp_dir }}

    <Directory {{ wp_dir }}>
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/wordpress_error.log
    CustomLog ${APACHE_LOG_DIR}/wordpress_access.log combined
</VirtualHost>

AllowOverride All は、WordPress のパーマリンクが使う .htaccess を有効にするための設定です。

手順5: プレイブックを書く

site.yml に、構築の手順を上から順に書きます。

---
- name: WordPress サーバーを構築する
  hosts: wordpress
  become: true
  vars_files:
    - vars/secrets.yml

  tasks:
    - name: パッケージをインストールする
      ansible.builtin.apt:
        name:
          - apache2
          - mariadb-server
          - php
          - libapache2-mod-php
          - php-mysql
          - php-curl
          - php-gd
          - php-intl
          - php-mbstring
          - php-xml
          - php-zip
          - python3-pymysql
        state: present
        update_cache: true
        cache_valid_time: 3600

    - name: MariaDB を起動し、自動起動を有効にする
      ansible.builtin.service:
        name: mariadb
        state: started
        enabled: true

    - name: データベースを作る
      community.mysql.mysql_db:
        name: "{{ wp_db_name }}"
        encoding: utf8mb4
        collation: utf8mb4_unicode_ci
        state: present
        login_unix_socket: /run/mysqld/mysqld.sock

    - name: データベースのユーザーを作る
      community.mysql.mysql_user:
        name: "{{ wp_db_user }}"
        password: "{{ wp_db_password }}"
        host: localhost
        priv: "{{ wp_db_name }}.*:ALL"
        state: present
        login_unix_socket: /run/mysqld/mysqld.sock
      no_log: true

    - name: WordPress のディレクトリを作る
      ansible.builtin.file:
        path: "{{ wp_dir }}"
        state: directory
        owner: www-data
        group: www-data
        mode: "0755"

    - name: WordPress をダウンロードして展開する
      ansible.builtin.unarchive:
        src: https://wordpress.org/latest.tar.gz
        dest: "{{ wp_dir }}"
        remote_src: true
        extra_opts:
          - --strip-components=1
        owner: www-data
        group: www-data
        creates: "{{ wp_dir }}/wp-settings.php"

    - name: wp-config.php を作る(既にあれば上書きしない)
      ansible.builtin.template:
        src: templates/wp-config.php.j2
        dest: "{{ wp_dir }}/wp-config.php"
        owner: www-data
        group: www-data
        mode: "0640"
        force: false

    - name: Apache のサイト設定を置く
      ansible.builtin.template:
        src: templates/wordpress.conf.j2
        dest: /etc/apache2/sites-available/wordpress.conf
        mode: "0644"
      notify: Reload Apache

    - name: mod_rewrite を有効にする
      community.general.apache2_module:
        name: rewrite
        state: present
      notify: Restart Apache

    - name: WordPress のサイトを有効にする
      ansible.builtin.command: a2ensite wordpress
      args:
        creates: /etc/apache2/sites-enabled/wordpress.conf
      notify: Reload Apache

    - name: 既定のサイトを無効にする
      ansible.builtin.command: a2dissite 000-default
      args:
        removes: /etc/apache2/sites-enabled/000-default.conf
      notify: Reload Apache

    - name: Apache を起動し、自動起動を有効にする
      ansible.builtin.service:
        name: apache2
        state: started
        enabled: true

    - name: ファイアウォールで SSH・HTTP・HTTPS を許可する
      community.general.ufw:
        rule: allow
        port: "{{ item }}"
        proto: tcp
      loop:
        - "22"
        - "80"
        - "443"
      tags: firewall

    - name: ファイアウォールを有効にする
      community.general.ufw:
        state: enabled
      tags: firewall

  handlers:
    - name: Reload Apache
      ansible.builtin.service:
        name: apache2
        state: reloaded

    - name: Restart Apache
      ansible.builtin.service:
        name: apache2
        state: restarted

書き方のポイントは次のとおりです。

  • パッケージは一覧で渡す: apt の name には、パッケージを YAML のリストで渡します。python3-pymysql は、community.mysql のモジュールが対象サーバーで DB を操作するために必要です。
  • DB へは root のソケット認証で入る: Ubuntu の MariaDB は、root ユーザーが OS の root からパスワード無しで入れる設定になっています。login_unix_socket でソケットを指定し、become: true(root 権限)で実行することで、root のパスワードを扱わずに DB とユーザーを作れます。
  • 2回目以降も安全に流せる: unarchive の creates、template の force: false、command の creates・removes によって、既に済んでいる作業は飛ばされます。WordPress 本体を管理画面から更新したあとに実行しても、古い版で上書きしません。
  • SSH を先に許可してから ufw を有効にする: 順番を逆にすると、ファイアウォールを有効にした時点で SSH が切れ、サーバーに入れなくなります。SSH のポートを変えている場合は 22 を書き換えてください。
  • パスワードをログに出さない: no_log: true で、DB ユーザーを作るタスクの内容が画面やログに表示されないようにしています。

手順6: 実行する

まず文法を確認します。

ansible-playbook -i inventory.ini site.yml --syntax-check

問題がなければ実行します。--ask-vault-pass を付けると、Vault のパスワードを聞かれます。

ansible-playbook -i inventory.ini site.yml --ask-vault-pass

SSH ユーザーが sudo にパスワードを求められる設定の場合は、--ask-become-pass も付けて sudo のパスワードを入力します。

最後に表示される PLAY RECAP で failed=0 になっていれば成功です。続けてもう一度実行すると、すべてのタスクが済んでいるため changed=0 になります。設定を変えたときは、プレイブックを直して同じコマンドを流せば、差分だけが適用されます。

ブラウザーで http://サーバーのIPアドレス/(DNS を向けていればドメイン名)を開くと、WordPress のインストール画面に進みます。サイトのタイトルと管理者アカウントを入力して、インストールを完了してください。

運用の注意

  • HTTPS 化: このプレイブックは HTTP(80番)までです。DNS をサーバーに向けたあとで、Certbot などで証明書を取得して HTTPS にします。
  • ファイアウォールのタスクだけ飛ばす: クラウドのセキュリティグループなどで通信を制限していて ufw を使わない場合は、--skip-tags firewall を付けて実行します。
  • 本番の前に検証環境で: インベントリに検証用のサーバーを別のグループとして書き、先にそちらで流して確かめてから本番に適用します。
  • MariaDB を外部に公開しない: このプレイブックの DB ユーザーは localhost からの接続だけを許可しています。DB を別サーバーに分ける場合は、接続元を限定し、ファイアウォールも合わせて設定します。

まとめ

  • インベントリは INI 形式なら inventory.ini に書き、ansible -m ping で接続を確かめる
  • DB のパスワードは Ansible Vault で暗号化し、wp-config.php はテンプレートから作る
  • community.mysql には対象サーバーの python3-pymysql と、Ubuntu ではソケット認証の指定が必要
  • creates・force: false などで、2回目以降に流しても既存の環境を壊さない書き方にする
  • ufw は SSH を許可してから有効にする

関連記事:

お気軽にご相談ください

お見積りへ お問い合わせへ
▲