Using Ansible For Automatic Deployment Of A Strapi CMS To Amazon AWS

Photo by Fabian Keller on Unsplash

Traditional Vs Headless Content Management Systems

If you want to present your content like a blog, your photo portfolio, or any kind of digital content to the public you will need a Content Management System. Basically, there are two major kinds of CMS:

Strapi — The Headless CMS

Strapi is a Github-based open source project [3] under the MIT Expat License. With more than 226k downloads per month, a big feature set, great documentation, its own slack channel, and a huge amount of video tutorials it is getting more and more popular. Strapi is a great candidate if you want to have all the flexibility for dealing with your content. For accessing your content Strapi offers a traditional REST- but also a modern GraphQL-API.

The Strapi backend.

Ansible For Automating Your DevOp Work

The open-source project Ansible [1] is for sure one of the most frequently used tools for automating tasks like installing and configuring software on a remote Linux machine. It also supports the provisioning of cloud infrastructure like compute instances or database systems. With more than 3000 modules that are extending its use for all thinkable areas, it is the DevOps swiss army knife.

Ansible — a GPL based Automation System maintained by Red Hat
sudo apt install ansible 

Deploy Your Strapi CMS on Amazon AWS

If you want to install Strapi locally on your development machine you only need Node.Js to be installed. You then can create the Strapi application with:

npx create-strapi-app my-project --quickstart
http://localhost:1337/admin
  1. Launch an EC2 virtual machine
  2. Configure and install a database (i.e. PostgreSQL on RDS)
  3. Configure S3 as an upload destination
  4. Configure the EC2 instance as a Node.js server
  5. Create and configure a Strapi application to the server
  6. Install and configure PM2 Runtime to automatically launch Strapi

Let Ansible Do The Job For You

If you are looking for an automatic way to set up all this, you can use my Ansible solution hauben/ansible-play-strapi [9] which I put on Github. With this Ansible solution, you can just run the playbooks with its roles, lay back, drink a cup of coffee, and watch how your backend gets automatically provisioned for you.

Strapi AWS Deployment

Allow Ansible To Connect To Your AWS Account

The Ansible roles VPC, RDS, EC2, and S3 need programmatic access to your AWS account. To do so generate a new IAM User and attach the corresponding policies. You may not need the FullAccess types — feel free to limit the corresponding rights by shrinking them down to a minimum. If the user is not needed anymore, delete it or just make the security key inactive.

Ansible needs the access key ID and the secret access key to connect to an AWS account.
Attach policies to allow the creation of the VPC, your instances (RDS, EC2), and the S3 bucket.
Finally, write down the generated Access key ID and the corresponding Secret access key.
Using a key pair to connect the Ansible control host via ssh to the target EC2 instance.

Configure The Ansible Variables

The Ansible solution has the following structure:

ansible-play-strapi/
├─ inventories/
│ ├─ development/
│ │ ├─ group_vars/
│ │ │ ├─ all/
│ │ │ │ ├─ credentials.yml
│ │ │ │ ├─ main.yml
│ │ ├─ production/
│ │ ├─ staging/
├─ playbooks/
│ ├─ aws_provisioning.yml
│ ├─ strapi.yml
├─ roles/
│ ├─ ec2/
│ ├─ rds/
│ ├─ s3/
│ ├─ strapi/
│ ├─ vpc/
├─ ansible.cfg
├─ site.yml
  1. ./ansible.cfg:
    - Specify which inventory you want to use (development, staging, or production)
    - Point to the private key file generated above
  2. ./inventories/<stage>/group_vars/all/credentials.yml:
    Specify the AWS credentials for the RDS database (username and password) and the generated access key and the corresponding secret. If you clone the Github repo, these variables are empty. If you then run the playbooks you will get an error saying that you have to specify these variables first.
  3. ./inventories/<stage>/group_vars/all/main.yml:
    Global variables for AWS which are used roles-wide like region, database settings, and S3 bucket name
  4. ./roles/<ec2|rds|s3|strapi|vpc>/defaults/main.yml:
    Each role has its own configuration. Check this variable definition if they fit your needs and change them if needed.

Secure Your Credentials Using Ansible-vault (optional but recommended)

The AWS credentials access key/access secret and the RDS database username and password are stored as mentioned in ./inventories/<stage>/group_vars/all/credentials.yml. It is strongly recommended to create an Ansible vault and encrypt this file instead of having the credentials in cleartext laying around. Below you can see an encrypted and a decrypted version of the credentials.yml file.

username: rds_db_admin
password: <your-secure-db-password>
aws_access_key: <your-access-key-id>
aws_secret_key: <your-secret-key>
$ANSIBLE_VAULT;1.1;AES256326134386238666438613061313161306262303331336362613739623565303066323432376432613736343166383161326133353937363738640a326533303564386461376534383833623665396431626564396631656664613539663364323533303634656162363331316362320a643263666634323465373635666463666430373534646633363630316666396662386530376237376334353935656139333765303266346134633664376331653864383363653031316136653966626236666534663361376238623765356132363166613234646266653565616564646364653438333330613730666561383962616662366238326161386332313231346236623134663339643132643430386239663130306261653430303232363332353033323664313832376266633366656366653632356565396630363036323037303335303835376534613034303764386332643438373032326266643930343839646662

Finally, Run The Play

If you have followed the above steps you can run the play with the following command:

./site.yml --ask-vault-pass
You will reach the strapi application backend via http://<public-ec2-ip-address>:1337
DATABASE_HOST={{ hostvars[‘localhost’].rds.endpoint.address }}
DATABASE_PORT=”{{ db_port }}”
DATABASE_NAME=”{{ db_name }}”
DATABASE_SSL=”{{ db_ssl_enabled}}”
DATABASE_USERNAME=”{{ username }}”
DATABASE_PASSWORD=”{{ password }}”
AWS_ACCESS_KEY_ID=”{{ aws_access_key}}”
AWS_ACCESS_SECRET=”{{ aws_secret_key }}”
UPLOAD_S3_BUCKET_REGION=”{{ s3_region }}”
UPLOAD_S3_BUCKET=”{{ s3_bucket_name }}”
STRAPI_HOST=”{{ strapi_host }}”
STRAPI_PORT=”{{ strapi_port }}”
ADMIN_JWT_SECRET=”{{ token }}”

Summary

The presented Ansible solution hauben/ansible-play-strapi for automatic deployment of Strapi on AWS is for sure not perfect. If you have ideas, comments, or suggestions on how to improve it please do not hesitate to write issues on Github or contribute in any way you like. If you like it, share this article and give your thumbs up.

References

  1. [Ansible] https://www.ansible.com
  2. [Strapi.io] https://strapi.io
  3. [Strapi Github] https://github.com/strapi/strapi
  4. [Ansible Module Community AWS] https://docs.ansible.com/ansible/latest/collections/community/aws/index.html
  5. [Ansible Module Amazon AWS Collection] https://docs.ansible.com/ansible/latest/collections/amazon/aws/index.html#plugins-in-amazon-aws
  6. [ansible-modules-pm2] https://pypi.org/project/ansible-modules-pm2/
  7. [MIT Expat License] https://en.wikipedia.org/wiki/MIT_License
  8. [Tutorial: Create an Amazon VPC for use with a DB instance] https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_Tutorials.WebServerDB.CreateVPC.html
  9. [Ansible Play To Deploy Strapi on AWS] https://github.com/hauben/ansible-play-strapi

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Frank Haubenschild

Frank Haubenschild

53 Followers

Dad, Software Engineer, Photographer, Reef- & Bee-Keeper, Founder, Drone Pilot — 🤓 💻 📷 🐝 🐠 💡👨‍✈️