From e9c5cefd32cdff73e021c21929e38591294e8759 Mon Sep 17 00:00:00 2001 From: Jeff Geerling Date: Sat, 20 Feb 2016 22:37:06 -0600 Subject: [PATCH] Fixes #84: Make Drupal VM prod-ready (with a DigitalOcean guide). --- .gitignore | 1 + examples/prod/README.md | 55 ++++++++++++++++++------ examples/prod/bootstrap/example.vars.yml | 15 +++++++ examples/prod/bootstrap/init.yml | 30 +++++++++++++ examples/prod/example.inventory | 2 +- examples/prod/prod.overrides.yml | 7 ++- provisioning/tasks/build-makefile.yml | 11 ++++- 7 files changed, 103 insertions(+), 18 deletions(-) create mode 100644 examples/prod/bootstrap/example.vars.yml create mode 100644 examples/prod/bootstrap/init.yml diff --git a/.gitignore b/.gitignore index b48a04283..c864bfad7 100644 --- a/.gitignore +++ b/.gitignore @@ -8,5 +8,6 @@ config.yml drupal.make.yml Vagrantfile.local examples/prod/inventory +examples/prod/bootstrap/vars.yml scripts/ roles/ diff --git a/examples/prod/README.md b/examples/prod/README.md index cb31e308e..71a8bd413 100644 --- a/examples/prod/README.md +++ b/examples/prod/README.md @@ -1,10 +1,12 @@ # Drupal VM Production Configuration Example +> **Important**: This feature is currently in 'experimental' status, and the security of your servers is _your_ responsibility. + This directory contains an example production configuration for Drupal VM which can be used to deploy Drupal VM to a production environment on a cloud provider like DigitalOcean, Linode, or AWS. -This README file contains instructions for how you can use this configuration file to build a Drupal environment on DigitalOcean. +This README file contains instructions for how you can use this configuration file to build a Drupal environment with Drupal VM on DigitalOcean. -## Creating a DigitalOcean Droplet +## Create a DigitalOcean Droplet If you don't already have a DigitalOcean account, create one (you can use geerlingguy's [affiliate link](https://www.digitalocean.com/?refcode=b9c57af84643) to sign up, otherwise, visit the normal [DigitalOcean Sign Up form](https://cloud.digitalocean.com/registrations/new). @@ -12,24 +14,24 @@ Make sure you have an SSH key you can use to connect to your DigitalOcean drople Once you are logged into DigitalOcean and have added your SSH key, click the 'Create Droplet' button on your Droplets page. For the Droplet, choose the following options: - - **Hostname**: Choose a hostname for your site (e.g. `example.drupalvm.com`) + - **Image**: Choose `Ubuntu 14.04.x x64` - **Size**: 1 GB / 1 CPU (currently $10/month; you can choose a higher plan if needed) - **Region**: Choose whatever region is geographically nearest to you and your site visitors - **Settings**: (Nothing here affects how Drupal VM works, choose what you'd like) - - **Image**: Choose `Ubuntu 14.04 x64` - **Add SSH Keys**: Select the SSH key you added to your account earlier. + - **Hostname**: Choose a hostname for your site (e.g. `example.drupalvm.com`) Click 'Create Droplet', and wait a minute or so while the Droplet is booted. Once it's booted, make sure you can log into it from your local computer: - ssh root@[droplet-hostname] + ssh root@[droplet-hostname-or-ip] -(Make sure you replace `[droplet-hostname]`) with the hostname or IP address of your Droplet!) +(Make sure you replace `[droplet-hostname-or-ip]`) with the hostname or IP address of your Droplet!) If you get a warning like "the authenticity of the host can't be established", answer yes to the prompt and hit enter. You should now be logged into the Droplet. Log back out by typing `exit` at the prompt and hitting return. Your DigitalOcean Droplet is booted and ready to have Drupal VM installed on it. -## Customizing `config.yml` and `inventory` for production +## Customize `config.yml` and `inventory` for production Just like you would with the normal `example.config.yml`, you need to copy the file to `config.yml`, then go through `prod.overrides.yml` (in this directory), and make sure to update your `config.yml`, making sure all the variables are set to match `prod.overrides.yml`. @@ -38,18 +40,43 @@ The changes outlined in `prod.overrides.yml` disable development-environment too The only other thing you need to do is copy the inventory file `example.inventory` to `inventory` (so it is located at `prod/inventory`). By default, it reads: [drupalvm] - 1.2.3.4 ansible_ssh_user=root + 1.2.3.4 ansible_ssh_user=my_admin_username + +Change the host `1.2.3.4` to either the IP address or the hostname of your DigitalOcean Droplet. Remember that if you would like to use a hostname, you need to make sure the hostname actually resolves to your Droplet's IP address, either in your domain's public DNS configuration, or via your local hosts file. + +## Initialize the server with an administrative account + +> Note: This guide assumes you have Ansible [installed](http://docs.ansible.com/ansible/intro_installation.html) on your host machine. + +The first step in setting up Drupal VM on the cloud server is to initialize the server with an administrative account (which is separate from the `root` user account for better security). -Change the host `1.2.3.4` to either the IP address or the hostname of your DigitalOcean Droplet. Remember that if you would like to use a hostname, you need to make sure that hostname actually resolves to your Droplet's IP address, either in your domain's public DNS configuration, or via your local hosts file. +Inside the `examples/prod/bootstrap` folder, copy the `example.vars.yml` file to `vars.yml` and update the variables in that file for your own administrative account (make sure especially to update the `admin_password` value!). -## Provisioning Drupal VM on the Droplet +Then, run the following command within Drupal VM's root directory (the folder containing the `Vagrantfile`): -Run the following command within this project's root directory (the folder containing the `Vagrantfile`): + ansible-playbook -i examples/prod/inventory examples/prod/bootstrap/init.yml -e "ansible_ssh_user=root" - ansible-playbook -i examples/prod/inventory provisioning/playbook.yml --sudo +Once the initialization is complete, you can test your new admin login with `ssh my_admin_username@droplet-hostname-or-ip`. You should be logged in via your existing SSH key. Log back out with `exit`. + +## Provision Drupal VM on the Droplet + +Run the following command within Drupal VM's root directory (the folder containing the `Vagrantfile`): + + ansible-playbook -i examples/prod/inventory provisioning/playbook.yml --sudo --ask-sudo-pass + +Ansible will prompt you for your admin account's `sudo` password (the same as the password you encrypted and saved as `admin_password`). Enter it and press return. After a few minutes, your Drupal-VM-in-the-cloud Droplet should be fully configured to match your local development environment! You can visit your Droplet and access the fresh Drupal site just like you would locally (e.g. `http://example.drupalvm.com/`). -## Going Further +## Known issues + + - The `files` folder that is generated during the initial Drupal installation is set to be owned by the admin account; to make it work (and to allow Drupal to generate stylesheets and files correctly), you have to manually log into the server and run `sudo chown -R www-data:www-data /var/www/drupalvm/drupal/sites/default/files` after initial provisioning is complete. + - You can't synchronize folders between your host machine and DigitalOcean (at least not in any sane way); so you'll need to either have Drupal VM install a site from a given Drush make file or composer.json, or deploy your site yourself. + - The way you build a production Drupal VM instance (vs. a local instance) is a little bit of a kludge. Follow https://github.com/geerlingguy/drupal-vm/issues/455 to track progress on a more streamlined process. + - Drupal VM doesn't include any kind of backup system. You should use one if you have any kind of important data on your server! + +## Go Further + +You can use Ubuntu 12.04, Ubuntu 14.04, CentOS 6 or CentOS 7 when you build the DigitalOcean Droplet. Just like with Drupal VM running locally, you can customize almost every aspect of the server! -You may want to customize your configuration further, to make sure Drupal VM is tuned for your specific Drupal site's needs, or you may want to change things and make the server configuration more flexible, etc. For all that, the book [Ansible for DevOps](http://ansiblefordevops.com/) will give you a great introduction to using Ansible to make Drupal VM and the included Ansible configuration do exactly what you need! +You may want to customize your configuration even further, to make sure Drupal VM is tuned for your specific Drupal site's needs, or you may want to change things and make the server configuration more flexible, etc. For all that, the book [Ansible for DevOps](http://ansiblefordevops.com/) will give you a great introduction to using Ansible to make Drupal VM and the included Ansible configuration do exactly what you need! diff --git a/examples/prod/bootstrap/example.vars.yml b/examples/prod/bootstrap/example.vars.yml new file mode 100644 index 000000000..ac61fef4e --- /dev/null +++ b/examples/prod/bootstrap/example.vars.yml @@ -0,0 +1,15 @@ +--- +admin_user: my_admin_username + +# On RHEL/CentOS, 'wheel'; on Debian/Ubuntu, 'root'. +admin_group: root + +# IMPORTANT: Configure your own password for the admin user account. To generate +# a password hash, use either of the following commands: +# - `openssl passwd -1 [password]` +# - `mkpasswd --method=SHA-512`. +admin_password: $1$HgT69GsW$qZ8FUJHafZZWD76KXgAZO/ + +# Configuration for copying local public SSH key to admin's authorized_keys. +admin_copy_ssh_pubkey: true +admin_pubkey: ~/.ssh/id_rsa.pub diff --git a/examples/prod/bootstrap/init.yml b/examples/prod/bootstrap/init.yml new file mode 100644 index 000000000..5bdfc3bdf --- /dev/null +++ b/examples/prod/bootstrap/init.yml @@ -0,0 +1,30 @@ +--- +- hosts: drupalvm + + vars_files: + - vars.yml + + tasks: + - name: Create admin user account. + user: + name: "{{ admin_user }}" + createhome: yes + home: "/home/{{ admin_user }}" + generate_ssh_key: yes + ssh_key_comment: "ansible-{{ inventory_hostname }}" + password: "{{ admin_password }}" + groups: "{{ admin_group }}" + shell: /bin/bash + + - name: Add local SSH public key to admin account authorized_keys. + authorized_key: + user: "{{ admin_user }}" + key: "{{ lookup('file', '{{ admin_pubkey }}') }}" + manage_dir: yes + + - name: Disable requiretty. + lineinfile: + dest: /etc/sudoers + regexp: '^Defaults.+requiretty' + line: 'Defaults !requiretty' + state: present diff --git a/examples/prod/example.inventory b/examples/prod/example.inventory index a5967b064..9a10cfe60 100644 --- a/examples/prod/example.inventory +++ b/examples/prod/example.inventory @@ -1,2 +1,2 @@ [drupalvm] -1.2.3.4 ansible_ssh_user=root +1.2.3.4 ansible_ssh_user=my_admin_username diff --git a/examples/prod/prod.overrides.yml b/examples/prod/prod.overrides.yml index 40b3e9b4a..d93b55a22 100644 --- a/examples/prod/prod.overrides.yml +++ b/examples/prod/prod.overrides.yml @@ -11,10 +11,14 @@ mysql_root_password: root # Only install extras that you will need/use on your site, and don't install # development-related software on production environments! installed_extras: - - memcached + # - memcached + # - redis # - solr - varnish +# Disable the dashboard page. Also remove any unneeded virtualhosts. +dashboard_install_dir: '' + # Enable a more hardened security configuration. extra_security_enabled: true @@ -23,7 +27,6 @@ firewall_allowed_tcp_ports: - "22" - "80" - "443" - - "8983" firewall_log_dropped_packets: true # Set Apache to listen on port 81 (internal only), and Varnish on 80. diff --git a/provisioning/tasks/build-makefile.yml b/provisioning/tasks/build-makefile.yml index b41cf5774..838c602f8 100644 --- a/provisioning/tasks/build-makefile.yml +++ b/provisioning/tasks/build-makefile.yml @@ -9,8 +9,17 @@ file: path: "{{ drupal_core_path }}" state: directory + recurse: yes + mode: 0775 + when: drupal_site.stat.exists == false + +- name: Ensure drupal_core_path directory is owned by ssh user. + file: + path: "{{ drupal_core_path }}" + state: directory + owner: "{{ ansible_ssh_user }}" + group: "{{ ansible_ssh_user }}" mode: 0775 - become: no when: drupal_site.stat.exists == false - name: Generate Drupal site with drush makefile.