Hi everyone,
This is a tutorial I am going to walk through how to deploy Appwrite to AWS EC2 instance using Terraform and Ansible.
Appwrite is a self-hosted solution that provides developers with a set of easy-to-use and integrate REST APIs to manage their core backend needs.
We will use Terraform to provision the underlying infrastructure and manage configurations and deploy appwrite using Ansible.
code for this tutorial can be found in
Hi everyone,
This is a tutorial I am going to walk through how to deploy Appwrite to AWS EC2 instance using Terraform and Ansible.
Appwrite is a self-hosted solution that provides developers with a set of easy-to-use and integrate REST APIs to manage their core backend needs.
We will use Terraform to provision the underlying infrastructure and manage configurations and deploy appwrite using Ansible.
code for this tutorial can be found in
{% github RizkyRajitha/appwriteiac %}
prerequisites
- aws account AWS free tier
- Terraform installed Terraform official tutorial and setup with aws credentials Terraform official tutorial
- Ansible installed Ansible official installation guide
- AWS Key pair for SSH connection AWS UserGuide
Provisioning infrastructure with Terraform
we'll start by provisioning the infrastructure needed to deploy appwrite using terraform.
in this tutorial, we will be provision
- VPC and subnet to run EC2 instance
- Internet gateway to expose subnet to internet
- route table and…
prerequisites
- aws account AWS free tier
- Terraform installed Terraform official tutorial and setup with aws credentials Terraform official tutorial
- Ansible installed Ansible official installation guide
- AWS Key pair for SSH connection AWS UserGuide
Provisioning infrastructure with Terraform
we'll start by provisioning the infrastructure needed to deploy appwrite using terraform.
in this tutorial, we will be provision
- VPC and subnet to run EC2 instance
- Internet gateway to expose subnet to internet
- route table and route table association to associate route table with subnet
- EC2 instance to deploy appwrite
- security groups to allow inbound(
http
,https
) and outbound web traffic to EC2 instance to expose appwrite
first, create a folder of your choice and then create providers.tf
file . this file will hold information about the cloud provider. next, initialize terraform project using terraform init
. this will allow terraform to download necessary binaries and initiate terraform.
providers.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.27"
}
}
required_version = ">= 0.14.9"
}
provider "aws" {
profile = "default"
region = "us-east-1"
}
after that, we need to create our first component, AWS VPC . VPC
stands for Virtual Private Cloud, which is like a complete network infrastructure layer for your cloud applications. next, we need to create a subnet in our VPC
. this is where our EC2 instance is placed in the network.
To expose this subnect to the internet we need to provision an Internet Gateway and also route table and route table associations to associate the route table with this subnet.
network.tf
# VPC
resource "aws_vpc" "vpcappwriteiacdemo" {
cidr_block = "10.0.0.0/16"
tags = {
"Name" = "vpc_appwriteiacdemo"
}
}
# Public subnet
resource "aws_subnet" "publicsubnetappwriteiacdemo" {
vpc_id = aws_vpc.vpcappwriteiacdemo.id
cidr_block = "10.0.1.0/24"
map_public_ip_on_launch = true
}
#IGW
resource "aws_internet_gateway" "igwappwriteiacdemo" {
vpc_id = aws_vpc.vpcappwriteiacdemo.id
tags = {
"Name" = "igw_appwriteiacdemo"
}
}
resource "aws_route_table" "crtpublicappwriteiacdemo" {
vpc_id = aws_vpc.vpcappwriteiacdemo.id
route {
cidr_block = "0.0.0.0/0"
# directs to IGW
gateway_id = aws_internet_gateway.igwappwriteiacdemo.id
}
tags = {
"Name" = "custom_public_route_table_appwriteiacdemo"
}
}
resource "aws_route_table_association" "racappwriteiacdemo" {
subnet_id = aws_subnet.publicsubnetappwriteiacdemo.id
route_table_id = aws_route_table.crtpublicappwriteiacdemo.id
}
after that, we need to specify the security groups to allow web traffic to the EC2 instance we are provisioning. for that create securitygroups.tf
file.
here we provision 4 security groups.
allow http ingress traffic (allow inbound http traffic to EC2) : port
80
allow https ingress traffic (allow inbound https traffic to EC2) : port
443
allow ssh ingress traffic (allow inbound ssh traffic to EC2) : port
22
allow all egress traffic (allow all outbound traffic to EC2)
securitygroups.tf
resource "aws_security_group" "sg_allow_http_ingress_appwriteicademo" {
name = "sg_allow_http_ingress_appwriteicademo"
vpc_id = aws_vpc.vpcappwriteiacdemo.id
ingress {
description = "http"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
}
resource "aws_security_group" "sg_allow_https_ingress_appwriteicademo" {
name = "sg_allow_https_ingress_appwriteicademo"
vpc_id = aws_vpc.vpcappwriteiacdemo.id
ingress {
description = "http"
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
}
resource "aws_security_group" "sg_allow_ssh_ingress_appwriteicademo" {
name = "sg_allow_ssh_ingress_appwriteicademo"
vpc_id = aws_vpc.vpcappwriteiacdemo.id
ingress {
description = "http"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
}
resource "aws_security_group" "sg_allow_all_egress_appwriteicademo" {
name = "sg_allow_all_egress_appwriteicademo"
vpc_id = aws_vpc.vpcappwriteiacdemo.id
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
}
now we are almost there, just need to create our main.tf
file where we specify EC2 instance to provision.
in this tutorial, we will provision t2 small
EC2 instance to the public subnet we created in our previous steps.
I choose t2 small
instance type because the minimum requirements to run Appwrite is 1 CPU core and 2GB of RAM which matches with t2 small instance type.
AMI we use here is Ubuntu Server 20.04 LTS (HVM)
.security groups we created earlier also have specified to our EC2 instance along with the subnet.
Make sure you added your key pair name in key_name
value.
main.tf
resource "aws_instance" "appwrite-demo" {
ami = "ami-09e67e426f25ce0d7" # ubuntu 20 image
instance_type = "t2.small"
tags = { Name : "appwrite-ec2" }
key_name = "your-key-pair-name"
vpc_security_group_ids = [aws_security_group.sg_allow_all_egress_appwriteicademo.id,
aws_security_group.sg_allow_http_ingress_appwriteicademo.id ,
aws_security_group.sg_allow_https_ingress_appwriteicademo.id
]
subnet_id = aws_subnet.publicsubnetappwriteiacdemo.id
}
# log public-ip after privisioning
output "public-ip" {
value = aws_instance.appwrite-demo.public_ip
}
now we have all the elements we need, let's apply this configuration using terraform apply
command.
terraform output
make sure you can connect to the EC2 instance using the key pair you specified before proceeding to the next steps.
aws network diagram
Manage configurations and deploy appwrite using Ansible
First, create an inventory file named hosts
and add EC2 instance public ip
hosts
your-ec2-public-ip-address
our newly provisioned EC2 instance has a fresh copy of ubuntu, so we need need to install docker and docker-compose to deploy appwrite.
We can start by creating main.yml
file as the ansible playbook . in this file, we will have all the tasks we need to execute deploy appwrite.
First, we will update apt packages, and install dependency packages for docker and docker-compose .
Next we will install docker and docker-compose.
Finally, we will copy the docker-compose.yml
and .env
files (which we will download in the next step) to EC2 instance deploy appwrite using docker-compose.
main.yml
- become: yes
hosts: all
name: deploy-appwrite
user: ubuntu
tasks:
- name: Update all packages
apt:
upgrade: dist
update_cache: yes
cache_valid_time: 3600
- name: Install a list of common dependancy packages
apt:
pkg:
- apt-transport-https
- ca-certificates
- software-properties-common
# install docker
- name: docker gpg setup
apt_key:
url: https://download.docker.com/linux/ubuntu/gpg
state: present
- name: add docker apt repository
apt_repository:
repo: deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable
update_cache: yes
state: present
- name: Update repositories cache
apt:
update_cache: yes
- name: Install docker-ce
apt:
name: docker-ce
- name: add ubuntu to docker
user:
name: ubuntu
group: docker
# install docker-compose
- name: get platform
shell: "uname -s"
args:
executable: /bin/bash
register: platform
- name: get architecture
shell: "uname -m"
args:
executable: /bin/bash
register: arch
- name: install docker-compose
get_url:
url: https://github.com/docker/compose/releases/download/1.27.4/docker-compose-{{platform.stdout}}-{{arch.stdout}}
dest: /usr/local/bin/docker-compose
mode: "u+x,g+x"
- name: Install Docker SDK for Python
apt:
pkg:
- python3
- python3-pip
- name: Update repositories cache
apt:
update_cache: yes
- name: Install Docker SDK for Python
pip:
name: "docker<5"
become: yes
- name: Install docker-compose SDK for Python
pip:
name: "docker-compose"
become: yes
# deploy appwrite
- name: Create appwrite directory
file:
path: /home/ubuntu/appwrite/
state: directory
- name: Copy docker-compose.yml
copy:
src: templates/docker-compose.yml
dest: /home/ubuntu/appwrite/docker-compose.yml
- name: Copy .env
copy:
src: templates/.env
dest: /home/ubuntu/appwrite/.env
- name: docker compose up
docker_compose:
project_src: /home/ubuntu/appwrite
Now create templates
directory and add docker-compose.yml
and .env
files to templates
directory from this GitHub gist.
final folder structure
Now we have all the pieces in hand, let's run ansible playbook using the following command.
In this command, we pass main.yml
as our playbook
-i
flag to pass our inventory file hosts
--private-key
flag to pass the key pair, to ssh EC2 instance.
ansible-playbook main.yml -i hosts --private-key [path-to-your-key]
Let's run ansible playbook and watch the magic happens 🪄.
After successfully running ansible playbook now you can visit your EC2 public ip address and view the appwrite signup page.
Now we can use appwrite and start building applications.
Top comments (7)
Hi Rajitha, really great article, thanks!
I was trying to deploy to AWS now, I updated the versions, everything works fine up until very last Ansible step "Docker compose up", there I get an error: "kwargs_from_env() got an unexpected keyword argument 'ssl_version'"
Also in your example, when you do manage to set up Appwrite, do you access it using public IP? Thanks.
If somebody else is also struggling with same error, the solution to the problem is to fixate the version of the Docker SDK for Python in Ansible main.yml to 6.1.3. To do that change the line 84 to
Have you tried to update the version of the packages? Especially the Appwrite itself. It has some breaking changes, that I can't seem to figure it out how to configure. I'm no Devops guy, so I'm struggling.
Congratz! Great work. I have been considering Appwrite as BaaS, but a little hesitant due to the lack of information about the cloud providers support.
Perhaps have you tried to deploy Appwrite in GCP/Kubernetes? or MS Azure?
Any reference would be much appreciated. Thanks!
Hi luis ,
Thanks ✌, i haven't tried appwrite on GCP / K8 .
you can try appwrite discord server , they are active in discord. appwrite.io/discord
I always wanted to experiment with Appwrite, but was not able recently. This article piqued that interest and now I'm going to try it with AWS and Terraform. Thanks for writing✌️
Glad you liked it 🤞