How to work with multiple projects in Hetzner Cloud
Posted on April 16, 2021 by Adrian Wyssmann ‐ 3 min read
In Hetzner Cloud you can have multiple projects. As you can have different members per group, it really makes sense to have different projects for different purposes. I will explain in this article on how I work with multiple projects in Ansible, as well when using the cli
Multiple projects in Hetzner Cloud
A project in Hetzner Cloud has a dedicated set of members and resources, whereas each member has a role, which determines what they are allowed to do. In my case I have two projects, to separate productive systems from my playground/development resources:

How to access projects using the cli
Access to projects is controlled by the API token, which you have to create via the Cloud Console:

You can set the token as environment variable HCLOUD_TOKEN
which can be used for both, ansible and the hcloud cli. However as you can have only one environment variable with this name, this may cause undesired side effect, as depending on the value set, you access either one or the other project. Luckily hcloud cli has context
. You can define contexts
by giving it a name and the project-specific token for example:
$ hcloud context create development
Token:
Context development created and activated
$ hcloud context create production
Token:
Context production created and activated
$ hcloud context list
ACTIVE NAME
development
* production
Let’s see how this works
$ hcloud context active
production
$ hcloud server list
ID NAME STATUS IPV4 IPV6 DATACENTER
9830839 ttrss running x.x.x.x aa:aa:aa:aa::/64 hel1-dc2
$ hcloud context use development
$ hcloud server list
ID NAME STATUS IPV4 IPV6 DATACENTER
11309447 dev0001 running x.x.x.x aa:aa:aa:aa::/64 hel1-dc2
Dynamic inventory in Ansible with multiple projects
I already wrote in one of my recent posts how manage inventory with inventory plugins using the hcloud inventory plugin and hetzner robot inventory plugin. If you use Hetzner Cloud. So far I started with a single inventory file inventory.hcloud.yml
which looked like this:
plugin: hcloud
keyed_groups:
- key: location
prefix: hcloud_location
- key: image_os_flavor
separator: ""
- key: status
prefix: server_status
- key: labels
separator: ""
compose:
server_ipv4: ipv4
server_ipv6: ipv6
ansible_host: name ~ ".example.com"
So far I always had HCLOUD_TOKEN
set but when removing this will not work anymore:
$ ansible-inventory -i inventory.hcloud.yml --graph
[WARNING]: * Failed to parse /home/aedu/Workspaces/example.com/infrastructure/inventory.hcloud.yml with auto plugin: Invalid Hetzner Cloud API Token.
[WARNING]: * Failed to parse /home/aedu/Workspaces/example.com/infrastructure/inventory.hcloud.yml with yaml plugin: Plugin configuration YAML file, not YAML inventory
[WARNING]: * Failed to parse /home/aedu/Workspaces/example.com/infrastructure/inventory.hcloud.yml with ini plugin: Invalid host pattern 'plugin:' supplied, ending in ':' is not allowed, this character is
reserved to provide a port.
[WARNING]: Unable to parse /home/aedu/Workspaces/example.com/infrastructure/inventory.hcloud.yml as an inventory source
[WARNING]: No inventory was parsed, only implicit localhost is available
@all:
|--@ungrouped:
If you check carefully in the docu of hcloud inventory plugin you can see that one can set the token
. So let`s do that - obviously using an encrypted string:
token: !vault |
$ANSIBLE_VAULT;1.1;AES256
xxxxxx
And see, it’s working
$ ansible-inventory -i inventory.hcloud.yml --graph
@all:
|--@debian:
| |--dev0001
|--@dev:
| |--dev0001
|--@hcloud:
| |--dev0001
|--@hcloud_location_hel1:
| |--dev0001
|--@k8smaster:
| |--dev0001
|--@server_status_running:
| |--dev0001
|--@ungrouped:
As I have configured inventory
in the ansible.cfg
the above also works without the -i
parameter. So as I have 2 projects, I also need 2 inventory files - inventory.dev.hcloud.yml
and inventory.prd.hcloud.yml
- both with the same configuration, but different token
. I also update ansible.cfg
as follows:
inventory = ./inventory.yml,./inventory.dev.hcloud.yml,./inventory.prd.hcloud.yml
This is sufficient so that I can use the inventory of both projects - dev0001
runs in development
whereas ttrss
runs in production
:
$ ansible-inventory --graph
@all:
|--@debian:
| |--dev0001
| |--ttrss
|--@dev:
| |--dev0001
|--@hcloud:
| |--dev0001
| |--ttrss
|--@hcloud_location_hel1:
| |--dev0001
| |--ttrss
|--@k8smaster:
| |--dev0001
|--@prod:
| |--ttrss
|--@rss:
| |--ttrss
|--@server_status_running:
| |--dev0001
| |--ttrss
|--@ungrouped: