Create a Kamal-ready VPS on Hetzner using Terraform
These days, I deploy all my side projects using Kamal and GitHub Actions on Hetzner. Once you get the hang of it, it’s easy to maintain, fast, and cheap.
You can run your app with a database (SQLite), caching (Redis), background jobs (Celery), and SSL certificates (Let’s Encrypt) for roughly €5/month. Plus, if you feel the need, you can easily scale up to a more powerful Virtual Private Server (VPS).
But setting up a VPS with the right configuration takes a bit of time. You have to:
- Manually create the VPS using the UI.
- Create the necessary SSH keys.
- Create and apply the firewall rules.
- Create a new non-root user.
- Install Docker and other necessary software.
- Configure unattended-upgrades.
- Create a directory and set permissions for Let’s Encrypt SSL certificates.
- Reboot the system to apply all changes.
I already had a small script to do most of these steps, but I wanted to automate it to a single command. So I created a Terraform script to do it for me.
I took terraform-hetzner and modified it to work with a single VPS instance. My updated version is available here.
Set up
First, set up an API key with read and write permissions in Hetzner Cloud.
Second, install terraform.
Third, clone the repo:
Fourth, create a terraform.tfvars
file with the following variables:
hetzner_api_key = "your-api-key"
ssh_vps_root_key = "<your-ssh-root-public-key>"
ssh_vps_kamal_key = "<your-ssh-kamal-public-key>"
The ssh_vps_root_key
and ssh_vps_kamal_key
are the public keys for the root and kamal users, respectively. You can generate them with the make generate-ssh-key USER_NAME=root
or make generate-ssh-key USER_NAME=kamal
commands I added to the repo.
Store your SSH keys in a secure location. You’ll need them to access the VPS.
Run the script
Once the terraform.tfvars
file is set up, you can see what changes will be applied with the following command:
This will show in detail what changes will be applied to create a Kamal-ready VPS. If you’re happy with it, you can apply the changes with the following command:
This will create a VPS with the following configuration:
- Ubuntu 22.04 LTS
- 2 VCPU
- 2 GB RAM
- 40 GB SSD
It’ll cost you roughly €5/month and will be located in Nuremberg (Germany).
In addition, after the VPS is created, it will automatically:
- Create a non-root user (kamal) with sudo privileges.
- Install the required software (Git, Docker, curl, etc.)
- Create a directory for Let’s Encrypt SSL certificates.
- Create a firewall rule to allow HTTP, HTTPS, and SSH traffic.
- Create a directory for the database (SQLite) and the cache (Redis) (
db/
anddata/
)
Customizing the script
You can customize the script to fit your needs. Here are a couple of things you can change:
Change the software to install
If you want to change the software to install, you can modify the packages
section in cloudinit/vps.yml
.
Run other commands after the VPS is created
If you want to run other commands after the VPS is created, you can add them to the runcmd
section in the cloudinit/vps.yml
file.
Use already existing firewall rules
If you want to use already existing firewall rules, you can modify how the firewalls are attached in cloud.tf
. Take a look at this section of cloud.tf
.
Use a different server type, operating system, or region
If you want to use a different server type, operating system, or region, you can modify the server_type
, region
, operating_system
variables in variables.tf
.
Conclusion
This script is a great way to create a Kamal-ready VPS on Hetzner using Terraform. It’s easy to maintain, fast, and cheap.
All the code is available in the repo.
Hope you find this useful!