Ansible Role hetzner_vm

This role creates and manages servers (virtual machines) and volumes at the Hetzner console

  • Installs the VM with the provided t-shirt-size / flavor / server-type (or removes it)

  • Rescales the VM (for this the VM must be stopped before changing type)

  • Turns Hetzner backups on/off

  • Selects the image to install

  • Selects the location

  • Deploys the SSH keys from the Hetzner portal

  • Upgrades disks

  • Manages additional volumes (just attaches/removes them to/from the VM, but does not mount/unmount them in any way)

  • Manages networks, subnets and routes

  • Manages firewall rules

This role does not configure the VM’s network interfaces.

Mandatory Requirements

  • Install the Python library hcloud on the Ansible control node (use pip install --user --upgrade hcloud).

  • Import your public SSH-key into Hetzner (your project > Security > SSH Keys).

Optional Requirements

Tags

hetzner_vm

  • Creates and manages the server.

  • Triggers: none.

hetzner_vm:firewalls

  • Manages the provider firewalls of the host.

  • Triggers: none.

Mandatory Role Variables

hetzner_vm__api_token

  • Set the Hetzner API token. API tokens can be managed in your project > Security > API Tokens. The API token requires read and write permissions.

  • Type: String.

hetzner_vm__image

  • The Hetzner image to use for the server. The possible options can be obtained using hcloud image list.

  • Type: String.

hetzner_vm__location

  • The Hetzner location the instance should run in. The possible options can be obtained using hcloud location list.

  • Type: String.

hetzner_vm__server_type

  • The Hetzner server type. This defines the number of CPU cores, the CPU type, the disk space and the memory size. The possible options can be obtained using hcloud server-type list. Note that you cannot upgrade a running instance (otherwise you’ll get server must be stopped before changing type). Either stop the instance using hetzner_vm__state: 'stopped' or set hetzner_vm__force: true. Also have a look at hetzner_vm__upgrade_disk.

  • Type: String.

You also need ONE of these:

hetzner_vm__enable_public_ipv4

  • Choose if the VM should have a public IPv4 address.

  • Type: Bool.

  • Default: false

hetzner_vm__enable_public_ipv6

  • Choose if the VM should have a public IPv6 address.

  • Type: Bool.

  • Default: false

hetzner_vm__networks

  • A list of dictionaries defining which networks should be attached to this instance. It also allows the creation of new internal networks, or setting a fixed IP for the instance.

  • Type: List of dictionaries.

  • Default: []

  • Subkeys:

    • name:

      • Mandatory. The name of an existing network, or the network which should be created.

      • Type: String.

    • cidr:

      • Optional. If this is given, a new network with this cidr is created.

      • Type: String.

    • fixed_ip:

      • Optional. The fixed IP of this instance. This can be used for attach to an existing network, or when creating a new one.

      • Type: String.

    • state:

      • Optional. State of the network attachment.

      • Type: String.

      • Default: 'present'

    • routes:

      • Optional. Routes for this network, with destination and gateway subkeys.

      • Type: List.

      • Default: []

Example:

# mandatory
hetzner_vm__api_token: 'V5bg8DsrWxgbydkiS6RrE2Jcbcw1eWEZxh26Oms2t6ZhTWfg25r60ua9upCZgt79ui'
hetzner_vm__image: 'rocky-8'
hetzner_vm__location: 'nbg1'
hetzner_vm__server_type: 'cx11'

# one of these
hetzner_vm__enable_public_ipv4: false
hetzner_vm__enable_public_ipv6: false
hetzner_vm__networks:
  - name: 'net-test01'
    cidr: '10.126.219.0/24'
    fixed_ip: '10.126.219.12'
    state: 'present'
    routes:
      - destination: '0.0.0.0/0'
        gateway: '10.126.219.2'

Optional Role Variables

hetzner_vm__backups

  • Choose if Hetzner itself should make backups of the volumes. Note that backups cost an additional 20% of the server price. Volumes are not included in backups.

  • Type: Bool.

  • Default: false

hetzner_vm__firewall_rules

  • List of firewall rules that should be applied to the server.

  • Type: List of dictionaries.

  • Default: []

  • Subkeys:

    • direction:

      • Mandatory. Either in or out.

      • Type: String.

    • port:

      • Mandatory. Single port or range, in the form of 1024-5000.

      • Type: Number or String.

    • protocol:

      • Mandatory. Either tcp, udp, icmp.

      • Type: String.

    • source_ips:

      • Mandatory. List of allowed CIDR source addresses.

      • Type: List.

hetzner_vm__force

  • Force the update of the server. This may power off the server. The rescaling process will usually take just a few minutes. Also have a look at hetzner_vm__upgrade_disk.

  • Type: Bool.

  • Default: false

hetzner_vm__name

  • The name of the server. By default, it uses the Ansible inventory name.

  • Type: String.

  • Default: '{{ inventory_hostname }}'

hetzner_vm__ssh_keys

  • List of SSH-key names that should be placed on the server. The names have to match the SSH-keys deposited in Hetzner.

  • Type: List.

  • Default: []

hetzner_vm__state

  • The state of the server. Possible options: absent, present, rebuild, restarted, started, stopped.

  • Type: String.

  • Default: 'started'

hetzner_vm__upgrade_disk

  • Resize the disk when resizing the server. This will prevent downgrades to a hetzner_vm__server_type with a smaller disk later on, as the disk cannot be shrunk.

  • Type: Bool.

  • Default: false

hetzner_vm__volumes

  • Dictionary of volumes that should be managed and attached to this server.

  • Type: List of dictionaries.

  • Default: []

  • Subkeys:

    • name:

      • Mandatory. The name of the volume.

      • Type: String.

    • size:

      • Mandatory. The size in GBs. Has to be higher than 10. Note that shrinking of volumes is not supported.

      • Type: Number.

    • format:

      • Optional. The format of the volume. Possible options: xfs, ext4.

      • Type: String.

      • Default: 'xfs'

    • state:

      • Optional. The state of the volume. Possible options: present, absent.

      • Type: String.

      • Default: 'present'

Example:

# optional
hetzner_vm__backups: false
hetzner_vm__firewall_rules:
  - direction: 'in'
    port: 22
    protocol: 'tcp'
    source_ips:
      - 0.0.0.0/0
      - ::/0
hetzner_vm__force: false
hetzner_vm__name: '{{ inventory_hostname }}'
hetzner_vm__ssh_keys:
  - 'alice'
  - 'bob'
hetzner_vm__state: 'started'
hetzner_vm__upgrade_disk: false
hetzner_vm__volumes:
  - name: '{{ inventory_hostname }}-data'
    size: '100'

Known Limitations

It is currently not possible to start a server with only an internal network and a fixed IP (see https://github.com/ansible-collections/hetzner.hcloud/issues/172). As a workaround, the server can be created with hetzner_vm__state: 'stopped' and then started:

ansible-playbook --inventory=inventory linuxfabrik.lfops.hetzner_vm --extra-vars="hetzner_vm__state='stopped'"
ansible-playbook --inventory=inventory linuxfabrik.lfops.hetzner_vm --extra-vars="hetzner_vm__state='started'"

License

The Unlicense

Author Information

Linuxfabrik GmbH, Zurich