Deploying WordPress with Terraform

Terraform is an open source Infrastructure as Code (IaC) tool developed by HashiCorp and it supports most major public cloud platforms such as AWS, Google Cloud, Azure, DigtialOcean, and so on.

What makes Infrastructure as Code special? It enables you to automatically deploy and manage the infrastructure needed to run technology stacks, such as WordPress, through software instead of manual processes. IaC enables one to deploy and manage cloud servers, create sub nets, update DNS and more with code that is stored in a version control system such as Git. In fact, this website was deployed using both Terraform and Ansible. Terraform provisioned the DigitalOcean cloud server, configured firewall rules that only allow HTTPS traffic though CloudFlare, and configured the DNS records on CloudFlare for this website. Ansible was then used to configure the cloud server with WordPress. Here is the GitHub repository for those of you who are interested: HauptJ/WordPress-CloudFlare-Terraform

One useful feature of Terraform is the fact that it keeps track of the resources it created in a state file. This makes managing those resources easier later on in case you ever want add, update or destroy resources.

First you need to declare your service providers. In this example, I am using DigitalOcean for their Infrastructure as a Service (IaaS) offerings and CloudFlare for their DNS and Software as a Service (SaaS) offerings. Terraform interacts with the service providers API, so you will need have the required API tokens readily available. For security reasons, storing hard coded credentials such as API tokens in a repository is a terrible practice. One safe method of passing in credentials is to set them as temporary environment variables.

After you declare your providers, you can start creating resources such as servers. Terraform provides provisioners to configure servers after they are deployed. Unfortunately, it does not support Ansible out of the box. However, Adam Mckaig created a Golang project that utilizes the Terraform inventory file to generate a dynamic inventory for Ansible. Here is the GitHub repository for his tool. adammck/terraform-inventory

As shown below, you will notice the local exec provisioner that executes Ansible with a specified Terraform state file. The state file is used to generate a dynamic inventory for Ansible that contains the wordpress server as a member of the wordpress group.

Terraform can also configure firewall policies, or security groups as they are called in AWS, with may cloud service providers. Below is an example of a firewall policy that only allows incoming HTTPS traffic from CloudFlare’s IPv6 address ranges. The idea with this is to prevent rouge actors from trying to bypass the Web Application Firewall (WAF) protecting this site. This also demonstrates a cool feature that a few WAF providers offer, which is the ability to proxy incoming IPv4 requests over IPv6 to the end host server. For this website, Nginx is only configured to listen for HTTPS connections over IPv6 and CloudFlare is not only proxying IPv4 connections, it is also redirecting HTTP requests to use HTTPS.

In order to associate this firewall policy with the DigitalOcean cloud server, you need to specify the droplet id which is generated as the server is deployed. You can see this on line 4.

After the server is deployed, the DNS records are updated so CloudFlare can proxy HTTPS requests to the server. For management purposes, I also configured an IPv6 AAAA record and an IPv4 A record to point directly to the server, bypassing CloudFlare. This is to make logging into the server with SSH easier in the rare event it is necessary for troubleshooting purposes or to inspect anomalies caused by malicious actors.

You will want to make sure that DNS records are created after the server is deployed. To do so, you can specify a the resources that need to be created beforehand using depends_on as demonstrated on lines 9, 18, and 27 of the code snippet below.

Once you have all the resources defined, you deploy them. To do so, you first need to initialize Terraform by running terraform init. Then you need to generate the a deployment plan by running terraform plan -out=wordpress.tfplan. After the plan file has been generated, you can use it to deploy everything by running terraform apply wordpress.tfplan.

If you wish to destroy everything you can generate a plan to destroy the resources you created by running terraform plan -destroy -out=wordpress_down.tfplan. Then you can destroy everything by running terraform apply “wordpress_down.tfplan”.

Installing Infinoted on Debian and Ubuntu

Note: This is an old post from 2016, that was recovered from the database of my old website.

Overview: Gobby is a cross-platform collaborative text editor that enables Google Docs style editing. Unlike Etherpad, Gobby is more focused toward editing code with its support for syntax highlighting as demonstrated below.

Gobby Syntax Highlighting
Gobby Syntax Highlighting

I have used this program for multiple group projects and everyone found it very beneficial as it allowed us all to work on the same file(s) at once even when we were not in the same room. The built-in chat box enabled us to easily communicate while we worked on the project remotely. As an added bonus, the server used by Gobby, Infinoted, can be used with other text editors such as gedit. Hosting the server does not require a very powerful machine as a simple Raspberry PI 2 will suffice. You can download the Gobby client from the project’s website.

Installation:

Note: items marked in red indicate they may vary based on how you decide to install this service. Whenever you want to install something on a Debain based Linux distribution, you want to, first of all, make sure your package manager, apt, it up to date. To do so, run the following command. sudo apt-get update After you update your package manager, it is always a good idea to make sure all your packages are up to date. sudo apt-get upgrade Now it is safe to install Infinoted using the package manager. sudo apt-get install infinoted Once you have finished installing Infinoted using the package manager, you need to configure it. For security reasons, it is recommended to run a service with a specific user and group. You can choose any username and / or group you want, but it is recommended to chose something that will be easy to recognize for example gobby or infinoted. The following instructions use gobby for both the user and the group. The following command will create a new system user and group named gobby with no login access and home directory:

/home/services/gobby sudo adduser --system --gecos "Infinoted Service" --disabled-password --group --home /home/services/gobby gobby

If you prefer, you could use /var/lib/gobby as the home directory. You should now set the directory permissions for the gobby home directory. You should recursively set the home directory and all other following directories to 770. Setting the permission level to 770 allows only the owner and those in the group to read, write and execute files.

sudo chmod -R 770 /home/services/gobby

The following command should be optional but is very useful if encounter ownership problems in the gobby home directory. It recursively sets both the directory owner and group to gobby. Both the directory owner and group should have been set when you created the gobby user.

sudo chown -R gobby:gobby /home/services/gobby

Now you need to add the users you wish to be easily able to access the files edited on the server to the gobby group. To do so, use the following command as a template by replacing “username” with the desired username without quotes.

sudo adduser "username" gobby

Next, you need to add the keys, data and export directories under the gobby home directory. If you set the directory permissions correctly you should not have to use sudo to create these directories.

mkdir /home/services/gobby/keys

mkdir /home/services/gobby/data

mkdir /home/services/gobby/export

Now it is time to create the Infinoted configuration file, infinoted.conf, in which you specify your desired settings. First, create the file using touch.

sudo touch /etc/xdg/infinoted.conf

Note: the configuration must be located in either /etc/xdg/ or $HOME/.config/ as infinoted looks for the configuration file in the following order.

  1. /etc/xdg/infinoted.conf
  2. $HOME/.config/infinoted.conf

You can use Nano, or your favorite Linux text editor to edit infinoted.conf. sudo nano /etc/xdg/infinoted.conf You should add the following to the file.

Note: you should set your own password, so don’t just blindly copy this.

[infinoted]
security-policy=require-tls
key-file=/home/services/gobby/keys/infinoted-key.pem
certificate-file=/home/services/gobby/keys/infinoted-cert.pem
password=strong_password
autosave-interval=5
root-directory=/home/services/gobby/data
sync-directory=/home/services/gobby/export
sync-interval=25

After you save the configuration file, you should set its permissions. This step should be optional, but it is recommended if you encounter permission errors. sudo chown gobby:gobby /etc/xdg/infinoted.conf sudo chmod 550 /etc/xdg/infinoted.conf Now you can generate the certificate and key files and test Infinoted. infinoted --create-certificate --create-key If everything worked correctly, you should see this:

Infinoted Generate Cert and Key
Infinoted Generate Cert and Key

 

Once you see the output above, close Infinoted with crtl-c. To run Infinoted on startup, need to create a systemd startup script. Note: this only applies if you are running Debian version 8 or Ubuntu version 15.04 or later. If you are using an earlier version, you will have to improvise with Upstart or init (obsolete). Create a file called /etc/systemd/system/infinoted.service which should contain the following:
[Unit]
Description=Infinoted Daemon
After=network-online.target
[Service]
Type=simple
User=gobby
Group=gobby
UMask=007 ExecStart=/usr/bin/infinoted &
Restart=on-failure # Configures the time to wait before service is stopped forcefully.
TimeoutStopSec=300
[Install] WantedBy=multi-user.target

Now start the service using systemctl start infinoted and to verify the service is running, use systemctl status infinoted. If Infinoted is running correctly you should see this:

Systemd Infinoted Running
Systemd Infinoted Running

 

Finally, enable Infinoted to startup on boot. systemctl enable infinoted

References: Gobby project website

Affordable Public Openstack Cloud Providers

While reading through the Chris Parin’s outstanding course notes, I came across a list of public OpenStack cloud providers. While going through the list, I noticed two of them that accepted USD and were quite affordable compared to RackSpace. You have to consider the fact that you get what you pay for, however, if you are in the market for an environment to learn the platform, they are great.

OVH Public Cloud

  • Pros:
    • Most affordable
    • IPv6 support
    • GPU instances flavors
  • Cons:
    • API tends to run slow at times
    • Occasional outages
    • No US regions, closest is in Canada, near Montreal
    • Images are not IPv6 ready by default, you will have to configure it manually, or with a provisioner

Internap AgileCloud / AgileServer

  • Pros:
    • US regions
    • Free Dedicated IPv4 subnet
    • Bare metal instance flavors
  • Cons:
    • A tad bit pricer
    • No IPv6 support, yet IPv6 is available by request