Drupal VM can be made to manage a production environment. The security of your servers is your responsibility, and such usage should be considered experimental and unsupported.
(See companion blog post to this documentation: Soup to Nuts: Using Drupal VM to build local and prod.)
If you want to try managing a production environment (or other non-local environments) with Drupal VM, please see the following suggestions for making these servers more secure and easier to manage.
Note: As of Drupal VM 5.0.0, the example production configuration files are no longer included with Drupal VM. You would need to download Drupal VM 4.9.1 and copy the
examples/proddirectory into your Drupal VM codebase to make the example commands work with a newer version of Drupal VM.
Production specific overrides.¶
Drupal VM supports loading configuration files depending on the environment variable
DRUPALVM_ENV and using this feature you can have different configurations between development and production environments.
# Loads vagrant.config.yml if available (default). vagrant provision # Loads prod.config.yml if available. DRUPALVM_ENV=prod vagrant provision --provisioner=aws
If you're issuing a provision directly through
ansible-playbook as you would do for most production environments you can either set the
DRUPALVM_ENV variable on your host, or on the remote production machine.
# By default it doesn't try to load any other config file. ansible-playbook -i examples/prod/inventory provisioning/playbook.yml --become --ask-become-pass # Loads prod.config.yml if available. DRUPALVM_ENV=prod ansible-playbook -i examples/prod/inventory provisioning/playbook.yml --become --ask-become-pass
If you add
DRUPALVM_ENV=prod to the
/etc/environment file on your production environment:
# Loads prod.config.yml if available. ansible-playbook -i examples/prod/inventory provisioning/playbook.yml --become --ask-become-pass
Note: Having the variable set locally takes precedence over having it on the remote machine.
As a precaution not to accidentally provision a production server with insecure configurations, you should set your security hardening configurations in
config.yml, your local development overrides in
vagrant.config.yml and finally any additional production specific overrides in
prod.config.yml. This way, a production environment will never be provisioned with development tools, even if the
prod.config.yml is not read.
Ansible Vault support¶
Drupal VM will include a
secrets.yml file included in your VM's configuration directory (alongside
local.config.yml, etc.) that you can use to store sensitive variables (e.g. MySQL's root password, Drupal's admin password). For extra security, you can encrypt this file, and require a password whenever the variable is used.
First, you'd create an Ansible Vault encrypted file:
$ ansible-vault create secrets.yml
Create the file inside your VM's configuration directory, and save the following inside (replacing the actual passwords with your own secure ones!):
drupal_account_pass: add-your-secure-password-1-here drupal_db_password: add-your-secure-password-2-here mysql_root_password: add-your-secure-password-3-here
Ansible Vault will encrypt the file, and you can edit the file using
vagrant commands, make sure you tell the Ansible provisioner to use
DRUPALVM_ANSIBLE_ARGS='--ask-vault-pass' vagrant [command]
And if you need to override one of the secrets stored in that file, you can do so through an environment-specific config file, for example:
vagrant.config.yml prod.config.yml [etc.]
Example: Drupal VM on DigitalOcean¶
examples/prod 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 guide contains instructions for how you can build a Drupal environment with Drupal VM on DigitalOcean.
Create a DigitalOcean Droplet¶
Make sure you have an SSH key you can use to connect to your DigitalOcean droplets, and if you don't already have one set up, or if you need to add your existing key to your account, follow the instructions in this guide: How to use SSH keys with DigitalOcean Droplets.
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:
- Image: Choose
Ubuntu 18.04.x x64
- Size: 1 GB / 1 CPU (currently $5/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)
- Add SSH Keys: Select the SSH key you added to your account earlier.
- Hostname: Choose a hostname for your site (e.g.
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:
(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.
config.yml for production¶
config.yml, and by looking at
default.config.yml add any other overrides you'd like. Whatever variables you have set in
config.yml will override the defaults set by
The changes outlined in the example
prod.config.yml disable development-environment tools (like Adminer) and add extra security hardening configuration (via the
You now have Drupal VM configured for production by default. This is the recommended and safest way, so that you can't accidentally provision a production server with development tools. If desired you can also use the environment variable
DRUPALVM_ENV to load an additional
<ENV>.config.yml with production specific overrides. In most cases this is not needed though.
vagrant.config.yml for local development¶
To re-use the same setup for local development, copy
vagrant.config.yml and configure it so that you override the security hardening configurations that were added in
config.yml. Read about how configuration files are read under Configuring Drupal VM
inventory for production¶
The only other thing you need to do is copy the inventory file
inventory (so it is located at
prod/inventory). By default, it reads:
[drupalvm] 22.214.171.124 ansible_ssh_user=my_admin_username
Change the host
126.96.36.199 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 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).
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
Then, run the following command within Drupal VM's root directory (the folder containing the
ansible-playbook -i examples/prod/inventory examples/prod/bootstrap/init.yml -e "ansible_ssh_user=root"
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
Provision Drupal VM on the Droplet¶
Run the following command within Drupal VM's root directory (the folder containing the
DRUPALVM_ENV=prod ansible-playbook -i examples/prod/inventory provisioning/playbook.yml --become --ask-become-pass
Note: If you have installed Drupal VM as a Composer dependency you also need to specify the path of the config directory where you have your
DRUPALVM_ENV=prod ansible-playbook -i config/prod/inventory vendor/geerlingguy/drupal-vm/provisioning/playbook.yml -e "config_dir=$(pwd)/config" --become --ask-become-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.
- You may need to manually create the
drupal_core_pathdirectory on the server at this time; it's not always created automatically due to permissions errors.
filesfolder 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 the following two commands after provisioning is complete:
$ sudo chown -R www-data /var/www/drupalvm/drupal/sites/default/files $ sudo chmod -R 0700 /var/www/drupalvm/drupal/sites/default/files
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 the site via Git, using the
geerlingguy.drupalrole's git deployment options.
- 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!
You can use Ubuntu Ubuntu 18.04, Debian 10, or CentOS 8 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 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 will give you a great introduction to using Ansible to make Drupal VM and the included Ansible configuration do exactly what you need!