This is the architecture of our small cluster:
It creates two servers: web
where our application lives and accessories
where our dependencies like databases and caches live.
web
exposes ports 80, 22 and 443, while accessories
is not accessible from the outside. Root access is disabled on both machines and only the kamal
user can SSH into them.
You can create more servers by updating web_servers_count
or accessories_count
in variables.tf
. If there is more than one web server, a load balancer will be created and all the web servers will be added to it.
In case multiple servers of different types are created, the naming will be web-1
, web-2
, accessories-1
, and accessories-2
, as opposed to web
, accessories
, the default naming convention.
Important
If you are copying this workflow, you should change the SSH keys in cloudinit/base.yml
to your own.
It is defined on ssh_import_id
and imports the SSH keys from your GitHub account.
After running terraform apply
, the script will output an SSH configuration that can be copied to your ~/.ssh/config
file. This is to help you connect to servers since accessory servers are not accessible from the outside, you need to use the web server as a jump host. It looks like this:
ssh_01_web_config = <<EOT
Host web-1
HostName 167.235.61.121
User kamal
Host web-2
HostName 5.75.160.210
User kamal
EOT
ssh_02_accessories_config = <<EOT
Host accessories-1
HostName 78.46.225.17
User kamal
ProxyJump web-1
Host accessories-2
HostName 167.235.156.173
User kamal
ProxyJump web-1
Host accessories-3
HostName 128.140.70.80
User kamal
ProxyJump web-1
EOT
All machines are CX22
: 2 AMD vCPUs, 2 GB of RAM and 40 GB of SSD storage, running Ubuntu 24.04. See variables.tf
for more details and how to change them.
The default setup of 1 web server and 1 accessory server will cost you around 9 EUR/month.
- Clone
- Create a file
terraform.tfvars
with your credentials, it will look like this:
hetzner_api_key = "your-api-key"
- Update the
cloudinit/base.yml
file with your SSH keys (line #23) - Run
terraform init
- Run
terraform plan
(optional) - Run
terraform apply