Automatic Nginx Installation
Technical Background
In modern cloud environments, infrastructure automation is essential to minimize manual work and to ensure consistent system configuration. Cloud-init is a widely used tool for initializing Linux cloud instances on first boot. It supports configuration through a user_data
script passed during instance creation, which allows package installation, user creation, and service configuration automatically.
In this exercise, you use Terraform to provision a Hetzner Cloud server and configure it with a user_data
script. This script installs the Nginx web server, ensures it is started, and configures it to start automatically on every reboot. Using Terraform’s user_data
mechanism eliminates manual SSH setup and ensures your infrastructure is reproducible and reliable.
Info
The provided image (Debian 12) already has cloud-init
support enabled, so the user_data
script will be executed at boot time. Using apt
or apt-get
is generally recommended in cloud-init scripts instead of aptitude
, as minimal cloud images often do not have aptitude
installed by default.
Warning
The server needs access / privileges to reach external repositories for aptitude
.
Solution
Prerequisits
Create a main.tf
, outputs.tf
, variables.tf
, network.tf
,providers.tf
and secrets.auto.tfvars
like in 1 Incrementally Creating A Base System.
Preparing the user_data script
- Create a file
myinit.sh
with the following content:
#!/bin/bash
set -e
Failure
- Make sure to use the correct syntax and formatting
- Update package index and upgrade existing packages:
apt update && apt -y upgrade
- Install nginx:
apt -y install nginx
- Start nginx immediately:
systemctl start nginx
- Enable nginx to start on boot
systemctl enable nginx
Note
set -e
ensures that the script stops if any command fails.- If you want to test this before running Terraform, you can manually copy the script to an existing VM and run
sudo bash myinit.sh
.
Allow HTTP traffic in the firewall
- Modify (or create) a firewall resource in your
network.tf
:
resource "hcloud_firewall" "ssh" {
name = "allow-ssh"
rule {
direction = "in"
protocol = "tcp"
port = "22"
source_ips = ["0.0.0.0/0"]
}
rule {
direction = "in"
protocol = "tcp"
port = "80"
source_ips = ["0.0.0.0/0"]
}
}
Warning
Opening ports to 0.0.0.0/0
means anyone on the internet can access your server. In production, restrict the source IPs.
Configure Terraform to use the script
- Add the server resource in
main.tf
:
resource "hcloud_server" "web" {
name = "web"
image = "debian-12"
server_type = "cx22"
firewall_ids = [hcloud_firewall.sshFw.id]
ssh_keys = [hcloud_ssh_key.loginUser.id]
user_data = file("myinit.sh")
}
- Apply the configuration:
terraform init
terraform apply
Verify Nginx installation
- After Terraform finishes, open a browser and go to:
http://<your-server-ip>
Success
You should see the default Nginx Welcome Page.
Failure
- Check if port 80 is open:
sudo ufw status
or verify your firewall. - Check cloud-init logs on the VM:
sudo cat /var/log/cloud-init-output.log
. - Manually check service status:
systemctl status nginx
.