Cloud-init is the industry standard multi-distribution method for cross-platform cloud instance initialization. It is supported across all major public cloud providers, provisioning systems for private cloud infrastructure, and bare-metal installations.
This repository provides an easy way to generate a cloud-config
.
This is just an initial rough state. May change fundamentally.
# go to your git repo
cd your-project
# wherever you want the submodule
mkdir vendors
# add submodule - or just copy scripts you need
# or git clone https://github.com/lanisce/cloud-init.git vendors/cloud-init && sudo rm -r $_/.git
git submodule add https://github.com/lanisce/cloud-init.git vendors/cloud-init
# create a cloud-init folder containing all configuration
mkdir cloud-init
cd cloud-init
The cloud-init
folder structure should look roughly like this
.
βββ hetzner.json
βββ nameservers
βββ packages
βββ README.md
βββ source.list
β βββ docker.list
βββ write_files
βββ etc
βΒ Β βββ network
βΒ Β βββ interfaces.d
βΒ Β βββ 60-floating-ip.cfg
βΒ Β βββ 60-floating-ip.cfg.stat
βββ bootstrap
βββ initialize.sh
βββ initialize.sh.stat
You can any cloud-init apt configuration into the apt
file.
Also every file within source.list
will be added as apt source.
# example docker.list
source: "deb [arch=amd64] https://download.docker.com/linux/ubuntu $RELEASE stable"
# content of
# curl -s https://download.docker.com/linux/ubuntu/gpg | xclip -selection clipboard
key: |
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBFit2ioBEADhWpZ8/wvZ6hUTiXOwQHXMAlaFHcPH9hAtr4F1y2+OYdbtMuth
[...]
-----END PGP PUBLIC KEY BLOCK-----
This folder will be completly synced over the target instance.
Every file can (optional) have a companion file *.stat
descibing the file
owner: <user name>:<group name>
: default is${CLOUD_USER}:${CLOUD_GROUP}
permissions: <octal permission>
: default is0655
execute: true
: this will execute the given file instead of fetching it's contentruncmd: true
: if set, the file will be executed on the first boot (!permissions
has to be executable)envsubst: true
: this will substitute environment variables within the file- You can also set a specific variable (e.g.
envsubst: $HOME
)
- You can also set a specific variable (e.g.
You can set options as environment variables.
CLOUD_USER
: default userCLOUD_GROUP
: default groupCLOUD_PATH_PUB
: ssh public keys to use (default:${HOME}/.ssh
)- It will search for all
*.pub
files within this folder.
- It will search for all
All server parameters, within the hetzner.json
, will be exposed within the cloud-config
generater.
e.g.
{ "name": "myserver", "location": "hel1" }
will be availible as${NAME}
and${LOCATION}
.
You can also expose envs into the cloud-config
generater like ${CLOUD_ENV_*}
. CLOUD_ENV_
will be stripped.
e.g.
CLOUD_ENV_FOO=bar cloud-config
will be available as${FOO}
.
If you have to generate different cloud-config
's you can create the following folder structure.
.
βββ apt
βββ hetzner.json
βββ nameservers
βββ packages
βββ README.md
βββ write_files
βββ etc
βΒ Β βββ ...
βββ cloud.d
Β Β βββ <cloud.d name>
βββ packages
Β Β Β Β βββ write_files
βββ etc
Β Β βββ ...
You can add <cloud.d name(s)>
either as environment variable
CLOUD_PATHD="<cloud.d name 1>[:<cloud.d name 2>:<cloud.d name 3>]"
or reference them within your hetzner.json
with
{ ..., "#cloud.d": "<cloud.d name 1>[:<cloud.d name 2>:<cloud.d name 3>]" }
It will go through every cloud.d
configurations and finally use default.
cloud-config
will only use the first occurence of a file and ignore duplicates.
Yet, another cloud provisioning tool. Well yeah, but really minimalistic, to get started.
You can configure your hetzner cloud environment simply by one json file (hetzner.json
).
{
"ssh-key": [
{ "name": "user", "public-key-from-file": "${HOME}/.ssh/id_rsa.pub" }
],
"floating-ip": [
{ "name": "rancher.lanisce.si", "type": "ipv4", "home-location": "nbg1" }
],
"server": [
{ "name": "rancher", "type": "cx21", "image": "ubuntu-20.04", "location": "hel1", "ssh-key": 0, "network": 0, "#floating-ip": 0 }
],
"volume": [
{ "name": "rancher", "size": "10", "server": 0 }
],
"network": [
{ "name": "kubernetes", "ip-range": "10.98.0.0/16", "#subnets": [
{ "network-zone": "eu-central", "type": "server", "ip-range": "10.98.0.0/16" }
] }
]
}
You can reference resources by setting the row number of the given resource.
So e.g. .volume
has a .server
reference to .server[0]
. This value will be replaced by the resource id.
You can also specify multiple references like "ssh-key": [0, 1, 4]
.
All fields will just be handed over to hcloud. Only exception are fields beginning with #
. These will be ignored.
When deploy
(or directly ./provider/hetzner
) is executed it will try to create all resources.
$ deploy
π· found hetzner.json
β fetching floating-ip...
β fetching network...
β fetching server...
β fetching ssh-key...
β fetching volume...
π¦ skip ssh-key user (2420225)
β fetching ssh-key...
π¦ skip floating-ip rancher.lanisce.si (369823)
β fetching floating-ip...
π¦ skip network kubernetes (459431)
β fetching network...
π¦ skip server rancher (8713152)
β fetching server...
π¦ create volume rancher
$ hcloud volume create --name rancher --size 10 --server 8713152
5s [=====================================] 100.00%
Waiting for volume 8168226 to have been attached to server 8713152
... done
Volume 8168226 created
β fetching volume...
direnv is an extension for your shell. It augments existing shells with a new feature that can load and unload environment variables depending on the current directory.
#!/bin/bash
set -euo pipefail
: "${PATH_BASE:="$(git rev-parse --show-toplevel)"}"
set::path() {
# easy access to cloud-init scripts
PATH_add "${PATH_BASE}/vendors/cloud-init"
# easy access to needed binaries
PATH_add "${PATH_BASE}/vendors/cloud-init/.bin"
}
main() {
set::path
}
[ -z "${DIRENV_IN_ENVRC}" ] || main
Just execute deploy
or cloud-config
.
- https://cloudinit.readthedocs.io/en/latest/index.html
- https://cloudinit.readthedocs.io/en/latest/topics/examples.html
This project is licensed under the MIT license, see LICENSE
.