├── .gitignore ├── LICENSE ├── README.md ├── Vagrantfile ├── development ├── group_vars ├── development └── wordpress ├── roles ├── common │ ├── defaults │ │ └── main.yml │ └── tasks │ │ └── main.yml ├── mysql │ └── tasks │ │ └── main.yml ├── nginx │ ├── defaults │ │ └── main.yml │ ├── handlers │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ └── templates │ │ └── default ├── php │ └── tasks │ │ └── main.yml └── wordpress │ ├── defaults │ └── main.yml │ ├── tasks │ ├── database.yml │ ├── db_import.yml │ ├── main.yml │ └── plugins.yml │ └── templates │ └── wp-config.php └── site.yml /.gitignore: -------------------------------------------------------------------------------- 1 | *.sql* 2 | .vagrant 3 | production 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Richard Käll (richardkall.se) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE.ITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ansible-wordpress 2 | 3 | > Ansible playbook for configuring development and production servers with WordPress. 4 | 5 | This playbook will install and configure MySQL, WordPress, Nginx, and PHP-FPM. Vagrant is used to provision development servers and this comes with a basic Vagrantfile for an easy setup. 6 | 7 | ## Requirements 8 | 9 | - [Ansible](http://www.ansible.com) 10 | - [Vagrant](http://www.vagrantup.com) 11 | - [VirtualBox](http://www.virtualbox.org) 12 | 13 | ## Usage 14 | 15 | ### Development 16 | 17 | Install [vagrant-vbguest](https://github.com/dotless-de/vagrant-vbguest) to always keep VirtualBox Guest Additions up-to-date (optional): 18 | 19 | ```bash 20 | $ vagrant plugin install vagrant-vbguest 21 | ``` 22 | 23 | Add hostname to `/etc/hosts`. 24 | 25 | Run `vagrant up` to create and provision virtual machine. 26 | 27 | ### Production 28 | 29 | Create an inventory file and a group vars file, both named `production`. See development files for details. 30 | 31 | Provision Amazon EC2 instances with: 32 | 33 | ```bash 34 | $ ansible-playbook site.yml --private-key -i production -u ubuntu 35 | ``` 36 | 37 | If you want to run specific tasks, add `--tags ` when running `ansible-playbook`. 38 | 39 | ## Config 40 | 41 | All Ansible configration is done in [YAML](http://www.yaml.org). 42 | 43 | The following must always be defined as group variables: 44 | 45 | - `env` *development* 46 | - `host` *example.dev* 47 | - `site_name` *Example Site* 48 | - `wp_admin_email` *admin@example.dev* 49 | - `wp_admin_password` *password* 50 | - `wp_db_password` *password* 51 | - `wp_root` */srv/example.com/wordpress* 52 | 53 | ### Import database 54 | 55 | A database can be imported by specifying the dump path as `wp_db_import`. Ansible will automatically replace site URL with `hostname` and all user passwords to `wp_admin_password`. 56 | 57 | ```yaml 58 | # group_vars/development 59 | wp_db_import: database.sql.gz 60 | ``` 61 | 62 | ### WordPress Plugins 63 | 64 | Plugins can be installed automatically by defining `wp_plugins`. 65 | 66 | ```yaml 67 | # group_vars/wordpress 68 | wp_plugins: 69 | - { name: akismet, version: 3.0.1 } 70 | - { name: jetpack, version: 3.0.2 } 71 | ``` 72 | 73 | ### Delete sample content 74 | 75 | Delete all WordPress content (sample comments, posts etc.) with: 76 | 77 | ```yaml 78 | # group_vars/development 79 | wp_delete_content: true 80 | ``` 81 | 82 | **Important:** Remember to remove the `wp_delete_content` variable or set it to `false` before provisioning the server again. 83 | 84 | More role defaults can be found in `roles//defaults/main.yml` and easily overwritten using group variables. 85 | 86 | ### Synced folders 87 | 88 | Enable virtual machine [folder sync](https://docs.vagrantup.com/v2/synced-folders/) in your Vagrantfile. 89 | 90 | ```ruby 91 | # Vagrantfile 92 | Vagrant.configure("2") do |config| 93 | config.vm.synced_folder "../example-theme", "/srv/example.com/wordpress/wp-content/themes/example-theme", nfs: true 94 | end 95 | ``` 96 | 97 | ## License 98 | 99 | MIT © [Richard Käll](http://richardkall.se) 100 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | Vagrant.configure("2") do |config| 2 | config.vm.box = "ubuntu/trusty64" 3 | config.vm.network :private_network, ip: "10.10.10.10" 4 | 5 | # config.vm.synced_folder "../example-theme", "/srv/example.com/wordpress/wp-content/themes/example-theme", nfs: true 6 | 7 | config.vm.provider :virtualbox do |v| 8 | v.memory = 1024 9 | v.name = "wordpress" 10 | end 11 | 12 | config.vm.provision :ansible do |a| 13 | a.inventory_path = "development" 14 | a.limit = "all" 15 | a.playbook = "site.yml" 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /development: -------------------------------------------------------------------------------- 1 | [wordpress] 2 | 10.10.10.10 3 | 4 | [development:children] 5 | wordpress 6 | -------------------------------------------------------------------------------- /group_vars/development: -------------------------------------------------------------------------------- 1 | --- 2 | env: development 3 | host: example.dev 4 | wp_admin_email: admin@example.dev 5 | wp_admin_password: password 6 | wp_db_password: password 7 | wp_delete_content: true 8 | # wp_db_import: database.sql.gz 9 | -------------------------------------------------------------------------------- /group_vars/wordpress: -------------------------------------------------------------------------------- 1 | --- 2 | site_name: example.com 3 | wp_root: /srv/example.com/wordpress 4 | wp_db_name: example_com 5 | wp_db_user: example_user 6 | # wp_plugins: 7 | # - { name: akismet, version: 3.2 } 8 | -------------------------------------------------------------------------------- /roles/common/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | cache_valid_time: 9600 3 | -------------------------------------------------------------------------------- /roles/common/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Update APT cache 3 | apt: update_cache=yes cache_valid_time={{ cache_valid_time }} 4 | -------------------------------------------------------------------------------- /roles/mysql/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install MySQL 3 | apt: name={{ item }} state=present 4 | with_items: 5 | - mysql-server 6 | - python-mysqldb 7 | 8 | - name: Start MySQL service 9 | service: name=mysql state=started enabled=true 10 | -------------------------------------------------------------------------------- /roles/nginx/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | client_max_body_size: 64M 3 | -------------------------------------------------------------------------------- /roles/nginx/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Reload Nginx 3 | service: name=nginx state=reloaded 4 | -------------------------------------------------------------------------------- /roles/nginx/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install Nginx 3 | apt: name=nginx state=present 4 | 5 | - name: Disable default site 6 | file: path=/etc/nginx/sites-enabled/default state=absent 7 | notify: Reload Nginx 8 | 9 | - name: Add Nginx config 10 | template: src=default dest=/etc/nginx/sites-available/{{ site_name }} 11 | notify: Reload Nginx 12 | 13 | - name: Enable site 14 | file: src=/etc/nginx/sites-available/{{ site_name }} dest=/etc/nginx/sites-enabled/{{ site_name }} state=link 15 | notify: Reload Nginx 16 | 17 | - name: Start Nginx service 18 | service: name=nginx state=started enabled=true 19 | -------------------------------------------------------------------------------- /roles/nginx/templates/default: -------------------------------------------------------------------------------- 1 | server { 2 | charset utf-8; 3 | 4 | listen 80 default_server; 5 | server_name {{ host }}; 6 | root {{ wp_root }}; 7 | 8 | client_max_body_size {{ client_max_body_size }}; 9 | 10 | location ~ \.php$ { 11 | try_files $uri =404; 12 | fastcgi_pass unix:/var/run/php5-fpm.sock; 13 | fastcgi_index index.php; 14 | include fastcgi_params; 15 | } 16 | 17 | location / { 18 | index index.php index.html; 19 | try_files $uri $uri/ /index.php?$args; 20 | } 21 | 22 | location ~ /\. { 23 | deny all; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /roles/php/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install PHP 3 | apt: name={{ item }} state=present 4 | with_items: 5 | - php5-cli 6 | - php5-curl 7 | - php5-fpm 8 | - php5-gd 9 | - php5-mysql 10 | 11 | - name: Start PHP5-FPM service 12 | service: name=php5-fpm state=started enabled=true 13 | -------------------------------------------------------------------------------- /roles/wordpress/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | wp_admin_user: admin 3 | wp_cli_bin: /usr/bin/wp 4 | wp_cli_url: https://raw.github.com/wp-cli/builds/gh-pages/phar/wp-cli.phar 5 | wp_db_host: localhost 6 | wp_db_import: false 7 | wp_debug: false 8 | wp_delete_content: false 9 | wp_lang: en_US 10 | wp_table_prefix: wp_ 11 | wp_version: 4.6.1 12 | -------------------------------------------------------------------------------- /roles/wordpress/tasks/database.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Create WordPress database 3 | mysql_db: name={{ wp_db_name }} state=present 4 | tags: database 5 | 6 | - name: Create WordPress database user 7 | mysql_user: name={{ wp_db_user }} password={{ wp_db_password }} priv={{ wp_db_name }}.*:ALL state=present 8 | tags: database 9 | 10 | - name: Install WordPress tables 11 | command: wp core install 12 | --url={{ host }} 13 | --title={{ site_name }} 14 | --admin_user={{ wp_admin_user }} 15 | --admin_password={{ wp_admin_password }} 16 | --admin_email={{ wp_admin_email }} 17 | --allow-root 18 | chdir={{ wp_root }} 19 | notify: Reload Nginx 20 | tags: database 21 | -------------------------------------------------------------------------------- /roles/wordpress/tasks/db_import.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Copy database dump 3 | copy: src={{ wp_db_import }} dest=/tmp 4 | 5 | - name: Reset database 6 | command: wp db reset --yes --allow-root chdir={{ wp_root }} 7 | 8 | - name: Import database 9 | command: wp db import /tmp/{{ wp_db_import }} --allow-root chdir={{ wp_root }} 10 | 11 | - name: Replace site URL in database 12 | command: wp option update siteurl "http://{{ host }}" --allow-root chdir={{ wp_root }} 13 | 14 | - name: Replace home URL in database 15 | command: wp option update home "http://{{ host }}" --allow-root chdir={{ wp_root }} 16 | 17 | - name: Reset user passwords 18 | command: wp db query "UPDATE wp_users SET user_pass=MD5('{{ wp_admin_password }}');" --allow-root chdir={{ wp_root }} 19 | 20 | - name: Delete database dump 21 | file: path=/tmp/{{ wp_db_import }} state=absent 22 | -------------------------------------------------------------------------------- /roles/wordpress/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install WP-CLI 3 | get_url: url={{ wp_cli_url }} dest={{ wp_cli_bin }} mode=0755 4 | 5 | - name: Download WordPress 6 | command: wp core download --path={{ wp_root }} --locale={{ wp_lang }} --version={{ wp_version }} --allow-root creates={{ wp_root }} 7 | 8 | - name: Fetch random salts for WordPress config 9 | command: curl http://api.wordpress.org/secret-key/1.1/salt/ 10 | register: wp_salt 11 | 12 | - name: Add WordPress config file 13 | template: src=wp-config.php dest={{ wp_root }} 14 | 15 | - include: database.yml 16 | - include: plugins.yml 17 | 18 | - name: Delete content 19 | command: wp site empty --yes --allow-root chdir={{ wp_root }} 20 | when: wp_delete_content 21 | 22 | - include: db_import.yml tags=import 23 | when: wp_db_import|default(False) 24 | 25 | - name: Change ownership of WordPress installation 26 | file: path={{ wp_root }} owner=www-data group=www-data state=directory recurse=yes 27 | 28 | - name: Change upload permissions 29 | file: path={{ wp_root }}/wp-content/uploads mode=775 state=directory recurse=yes 30 | -------------------------------------------------------------------------------- /roles/wordpress/tasks/plugins.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Delete Hello Dolly plugin 3 | command: wp plugin delete hello --allow-root chdir={{ wp_root }} 4 | tags: plugins 5 | 6 | - name: Install WordPress plugins 7 | command: wp plugin install {{ item.name }} --version={{ item.version }} --activate --force --allow-root chdir={{ wp_root }} 8 | with_items: "{{ wp_plugins }}" 9 | when: wp_plugins is defined 10 | tags: plugins 11 | -------------------------------------------------------------------------------- /roles/wordpress/templates/wp-config.php: -------------------------------------------------------------------------------- 1 |