The purpose of this module is to provide ready to use user-data file for Hetzner cloud servers with multiple network managers.
All actions taken to create user-data file are based on Hetzner server configuration documentation, Hetzner static ip documentation, cloud-init documentation and my own experience/experiments.
- Generating private networks configuration for instance after initial boot ( only dhcp - no support for static interface configuration ). This module use three different ways of managing networks
interfaces.d
config file - for images:debian-10
debian-11
Netplan
config file - for images:ubuntu-20.04
ubuntu-22.04
NetworkManager keyfile
script - for images:fedora-36
fedora-37
centos-stream-8
centos-stream-9
rocky-8
rocky-9
- Adding additional users with ssh keys and
sudo
configuration - Writing additional entries in
/etc/hosts
file - Writing additional files on instance (ex. cron jobs)
- Running additional shell commands on initial boot (ex. docker instalation)
- Adding additional packages to VM
- Setting instance Timezone
- Upgrading all packages
- Rebooting after finishing all cloud-init tasks
System image | Routing Configuration | DNS ip addresses | DNS search domains | /etc/hosts file writing |
Creating additional users | Writing additional Files | Running additional commands | Upgrading packages | Rebooting instance |
---|---|---|---|---|---|---|---|---|---|
Ubuntu 20.04 | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
Ubuntu 22.04 | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
Debian 10 | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
Debian 11 | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
Fedora 36 | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
Fedora 37 | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
Centos Stream 8 | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
Centos Stream 9 | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
Rocky 8 | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
Rocky 9 | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
Please take a look at Known Issues section to read why some of the features are not working on described images.
I have tested this module on below instances types:
- CX11
- CPX11
This module should also work on the rest of standard machines with Local SSD based on avaliable documentation.
This module will not work on:
- Dedicated instances (CCXxx)
Example for Debian/Ubuntu with few packages installation:
module "cloud_config_file" {
source = "git::git@github.com:wszychta/terraform-module.hcloud-user-data?ref=tags/2.2.0"
server_type = "cpx11"
server_image = "ubuntu-20.04"
additional_users = [
{
username = "local"
sudo_options = "ALL=(ALL) NOPASSWD:ALL"
ssh_public_keys = [
"ssh-rsa ..................."
]
}
]
additional_hosts_entries = [
{
ip = "192.168.0.4"
hostnames = [
"host1.lab.net",
"host1"
]
},
{
ip = "192.168.0.5"
hostnames = [
"host2.lab.net",
"host2"
]
},
]
private_networks_settings = [
{
routes = {
"192.168.0.1" = [
"192.168.0.0/24",
"192.168.1.0/24"
"0.0.0.0/0" # To enable access to public network via NAT
]
}
nameservers = {
addresses = [
"192.168.0.3"
]
search = [
"lab.net",
]
}
}
]
additional_run_commands = [
"echo 'test command'"
]
additional_run_commands = [
"htop",
"telnet",
"nano"
]
}
There are no Known Issues
known to me for now - please let me know if you will find any.
To enable access to the internet from instance without public ip addresses there are several things to do:
- Prepare NAT instance with public IP address or PFsense/Opnsense which will have rules for NAT-ing
- Add in Hetzner Cloud Console or via hcloud/terraform tool route
0.0.0.0/0
to previously prepared NAT instance/router - Add route
0.0.0.0/0
to one of the interfaces defined inprivate_networks_settings
- take a look at the example above - Add one or more DNS servers to
nameservers
inprivate_networks_settings
(They can be public ones or private) - take a look at the example above
Variable name | variable type | default value | Required variable | Description |
---|---|---|---|---|
server_type | string |
empty |
Yes | Hetzner server type (ex. cpx11) |
server_image | string |
empty |
Yes | Instance system image |
additional_users | list(object({ |
[] |
No | List of additional users with their options |
private_networks_only | bool |
false |
No | Set to true when there are no public IP addresses defined for the instance |
private_networks_settings | list(object({ |
[] |
No | List of configuration for all private networks. Note: Routes are defined as map(list(string)) where key is a gateway ip address and list contains all network destinations. Example: "192.168.0.1" = ["192.168.0.0/24","192.168.1.0/24"] |
additional_write_files | list(object({ |
[] |
No | List of additional files to create on first boot. Note: inside content value please provide plain text content of the file (not the path to the file).You can use terraform to generate file from template or to read existing file from local machine |
additional_hosts_entries | list(object({ |
[] |
No | List of entries for /etc/hosts file. There is possibility to define multiple hostnames per single ip address |
additional_run_commands | list(string) |
[] |
No | List of additional commands to run on boot |
additional_packages | list(string) |
[] |
No | List of additional pckages to install on first boot |
timezone | string |
Europe/Berlin |
No | Timezone for the VM |
upgrade_all_packages | bool |
true |
No | Set to false when there is no need to upgrade packages on first boot |
reboot_instance | bool |
true |
No | Set to false when there is no need for instance reboot after finishing cloud-init tasks |
yq_version | string |
v4.6.3 |
No | Version of yq script used for merging netplan script |
yq_binary | string |
yq_linux_amd64 |
No | Binary of yq script used for merging netplan script |
Output name | Description |
---|---|
result_file | Result cloud-config file which will be used by instance (depending on provided server_image variable) |
result_hosts_file | Result host entries file which will be injected into /etc/hosts file |
packages_install_script | Result packages install script if there are no public network addresses defined for this instance |
result_interfacesd_file_map | Result cloud-config for interfaces.d compatible instance |
interfaced_network_config_file | Result interfaces.d network file |
interfaced_nameservers_file | Result resolvconf file for interfaces.d compatible instance |
result_netplan_cloud_config_file_map | Result cloud-config for Netplan compatible instance |
netplan_network_file | Result netplan network file which will be merged to main netplan file |
netplan_network_merge_script | Result netplan merge script file |
result_ifcfg_cloud_config_map | Result cloud-config for ifcfg network compatible instance |
ifcfg_network_config_files_map | Result ifcfg network config files map |
ifcfg_network_routes_files_map | Result ifcfg network routes files map |
result_keyfile_cloud_config_map | Result cloud-config for Network manager keyfile compatible instance |
keyfile_network_config_files_map | Result Network manager keyfiles map |
Please use the issues tab to report any bugs or feature requests.
I can't guarantee that I will work on every bug/feature, because this is my side project, but I will try to keep an eye on any created issue.
So if somebody will discover any error please look into Developing section
If you like this module and you haven't started working in Hetzner Cloud you can use my PERSONAL REFERRAL LINK to start working with Hetzner cloud. You will get 20 Euro on start and after spending additional 10 Euro I will get the same amount of money.
If you have and idea how to improve this module please:
- Fork this module from
master
branch - Work on your changes inside your fork
- Create Pull Request on this respository.
- In my spare time I will look at proposed changes
Copyright © 2023 Wojciech Szychta
GNU GENERAL PUBLIC LICENSE Version 3