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.shwith 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 -eensures 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 statusor 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.