Guide for installing Cradle CMS on Hetzner hosting provider.
Create Hetzner account
- Login or signup for a new Hetzner account here.
- Then enable two-factor authentication by navigating to "Administration" » "Settings" » "Two-factor authentication" in the left menu bar.
After that open Hetzner Cloud and go to Cloud projects
via services
menu on the top right, next to the user profile icon.
Create a new project (or use the existing one) where to deploy the cradle-cms service.
Firewall
Setup a Firewall for the Hetzner project you created previously according to this table;
Source |
Protocol |
Port |
Description |
---|---|---|---|
<YOUR_IP_ADDRESS> |
TCP | 22 | Allow SSH |
0.0.0.0/0 |
TCP | 80 | Allow HTTP |
0.0.0.0/0 |
TCP | 443 | Allow HTTPS |
You can find out your IP-address
by using Hetzners IP lookup service.
curl -4 https://ip.hetzner.com
Add server
Click Add server
to start configuring a new cloud server.
Operating system
Click the Apps
tab and select the Docker CE
which is based on Ubuntu 24.04
Linux.
You can also use
Debian 12
and then installdocker
orpodman
manually.
Architecture
Select server architecture Amd64
or Arm64
according to your own preference. In this guide we selected Arm64
Ampere.
Then you can select the smallest possible CPU size and scale it up when needed. We'll go for the CAX11
having `2 shared vCPU:s` with `4GB RAM` and `40GB SSD` disk.
Network
For networking we only need to have a public `IPv4` address.
SSH key
Earlier we setup a firewall rule that accepts ssh connections from a single IP address. To be able to log in to your server using `ssh` you need to generate a new keypair.
You can generate a hetzner.key
using the ssh-keygen
utility.
cd ~/.ssh
ssh-keygen -t rsa -b 4096 -f hetzner.key
Open or create the file ~/.ssh/config
and add configuration for accessing the server with the hetzner key.
Host <YOUR SERVER IP>
IdentitiesOnly yes
IdentityFile ~/.ssh/hetzner.key
Copy the contents of the public key hetzner.key.pub
to the clipboard and paste it into the Hetzner cloud `SSH-key` dialog.
Volume
Create a Hetzner Volume
for persistent storage with the smallest available size 10GB
and select XFS
as a file system which can be utilised for backup purposes later (XFS snapshots).
Firewall
Select the Firewall you created earlier.
You can leave rest of the cloud options unselected i.e backup, placement, groups, labels etc.
On the right side you can review the whole setup and also see a monthly cost of around €4 per month.
Click on Create and buy
and wait for the server to spin up.
Login to server
When the server is up and running you should be able to login using ssh.
On windows, unless running WSL, you need to install a different ssh utility like
putty
from https://putty.org.
Login
ssh root@<server-hostname-or-ip-address>
Start with some basic maintenance and update the server packages.
apt update
apt upgrade
For good measure you can
reboot
the server and login using ssh after it has restarted. Take a note of the information displayed when you login.
Configure storage
On the server create a /storage
directory where the cradle-cms files are going to be persisted.
mkdir /storage
Then edit the /etc/fstab
configuration and point Volume to the /storage
directory.
vi /etc/fstab
If you don't know how to edit using
vi
(orVim
) it's good to learn as it's installed per default on most linux distributions. See https://vimsheet.com
Now edit the line containing the Volume
and change the mount point to our /storage
directory.
before any changes (yours might look a bit different).
/dev/disk/by-id/scsi-0HC_Volume_100701234 /mnt/HC_Volume_100701234 xfs discard,nofail,defaults 0 0
after where we changed the mount point to /storage
/dev/disk/by-id/scsi-0HC_Volume_100701234 /storage xfs discard,nofail,defaults 0 0
Then save the file and re-mount the file system using the updated fstab configuration.
mount -a
Validate using the mount
command, you should see that /storage
has been mounted. Also check with df -H
that the Volume size in GB is correct.
mount
df -H
Deployment
Login to the cradle registry with podman
or docker
cli using your cradle-cms license-key
as username and your account password.
docker login registry.cradlecms.com
Initialise a docker swarm, even though we're using a single server, it simplifies deployment and updates later on.
docker swarm init
Download the latest cradle-cms image.
docker pull registry.cradlecms.com/cradle-cms:latest
Then we create and start a docker service
for cradle-cms using the latest release, all in one go.
Start service with automatic certificates
To start cradle-cms with letsencrypt certificates you need to register and configure a domain name pointing its `A RECORD` to your server ip. Your domain name should be configured using the -e DOMAIN_NAME=<domain>
option otherwise the server uses a wildcard `*`domain setting. More configuration options: site, frontend and admin.
docker service create --name cradle-cms --mount type=bind,source=/storage,destination=/storage --publish published=443,target=4040,mode=host -p 80:8080 --replicas 1 -e DOMAIN_NAME=your.site.domain -e ADMIN_PASS=your-password registry.cradlecms.com/cradle-cms
When you browse the server using the domain name, cradle-cms negotiates a certificate from letsencrypt. You can also get certificates from other ACME compatible providers by using -e ACME_DIRECTORY
configuration option.
On a production server you should use docker secrets for the configuration.
Start service (without letsencrypt)
To start cradle-cms without a domain name we use the -e ACME=false
environment option. It disables automatic letsencrypt certificates and defaults to a self-signed certificate. However, you can install your own default certificate in /storage/certs/cert.pem
.
docker service create --name cradle-cms --mount type=bind,source=/storage,destination=/storage --publish published=443,target=4040,mode=host -p 80:8080 --replicas 1 -e ACME=false -e ADMIN_PASS=your-password registry.cradlecms.com/cradle-cms
You can run the container as a low privileged system user with the docker option
--user
. It requires that the user exists both on the docker host and in the container. You also need to change ownership of the /storage directory to the same user. Debian based Linux, such as Ubuntu, have awww-data
user (with uid 33) that you may use.
Now you can check the docker service logs.
docker service logs cradle-cms
When the service is up and running you can reach the admin web interface at https:///admin
. Login with username admin
and the password you configured with -e ADMIN_PASS
.
Logs
The system log is written to standard out in json
format so you can use tools such as jq
to filter log messages. To see the log output you need to use docker logs
as shown in the example.
docker logs -f <container id>
You can also subscribe to a log event stream using the nats
client.
nats subscribe "logs.>"
[#6] Received on "logs.frontend" {"time":"2024-09-28T08:54:26.176Z","level":"INFO","service":"frontend","msg":"render","host":"localhost:5000","site":"17427f63-e498-4654-bcaa-a6f24afabeef","path":"/","type":"index","handle":"","lang":"en"}
Use the log stream if you want to store the log on another server or monitor it in real time.