Skip to content

Repository files navigation

n8n student provisioning

Bulk-provision Hetzner Cloud VMs, Cloudflare DNS records, and Docker on each host (n8n, Caddy, external task runners) from a CSV of students. Each student gets https://<student_id>.n8n.irn.hk/ (zone root irn.hk; override with DOMAIN_SUFFIX if you fork this).

Successful runs append rows to provisioned.csv (or a path you set). That file is the source of truth for deprovision (delete server + remove DNS).


What you need installed

Tool Role
hcloud Hetzner Cloud CLI — create/delete servers
curl, python3, openssl Cloudflare API, templating, secrets
ssh, scp Post-boot install on each VM

First-time setup

1. Repo files

cp secrets.env.example secrets.env
cp students.csv.example students.csv

Edit students.csv: keep the header student_id,first_name,last_name, one student per line. student_id drives the hostname and DNS label.

2. Hetzner Cloud

  1. In the console, create a project (e.g. one per cohort).
  2. Security → SSH keys: upload the public key you will use to SSH as student@ on new servers. The label in Hetzner must match what the script passes to hcloud server create (default hetzner_macbook_pro_rudy). If yours differs, set HCLOUD_SSH_KEY_NAME in secrets.env.
  3. Security → API tokens: create a token in that project and put it in secrets.env as HCLOUD_TOKEN.

There is no project ID in this repository. The API token is scoped to a project, so that token alone decides where servers are created and deleted.

Local key file: the script embeds your public key in cloud-init from SSH_KEY_PATH (default ~/.ssh/hetzner_macbook_pro_rudy). That file’s .pub must exist when you run provision.

3. Cloudflare

In secrets.env set:

  • CLOUDFLARE_ZONE_ID for the irn.hk zone
  • CLOUDFLARE_API_TOKEN with permission to edit DNS for that zone

DNS records are created as A records for <student_id>.n8n under that zone (full name <student_id>.n8n.irn.hk with default suffix).

4. Optional: hcloud context instead of HCLOUD_TOKEN

If you prefer not to store the token in secrets.env, run hcloud context create <name> once with a token from the right project. If HCLOUD_TOKEN is set in secrets.env, it overrides the active context for that script run. Check:

hcloud context active

Provision

Defaults (repo root): reads students.csv, secrets.env, appends to provisioned.csv.

./provision_students.sh

Cohort folder (separate list and log, same secrets):

STUDENTS_CSV=AC_FT_26_12/students.csv \
PROVISIONED_CSV=AC_FT_26_12/provisioned.csv \
./provision_students.sh

Other overrides

Variable Meaning
SECRETS_ENV Path to env file (default ./secrets.env)
STUDENTS_CSV Input CSV (default ./students.csv)
PROVISIONED_CSV Output/skip list (default ./provisioned.csv)
SSH_KEY_PATH Private key used for ssh/scp (default ~/.ssh/hetzner_macbook_pro_rudy)
DOMAIN_SUFFIX DNS suffix (default n8n.irn.hk)

Any student_id already present in provisioned.csv is skipped so you can re-run safely after partial failures.


Deprovision

Deletes the Hetzner server named in each row and removes the matching Cloudflare A record. Uses the same secrets.env (and HCLOUD_TOKEN / context rules) as provision.

./deprovision_students.sh

With an explicit list:

./deprovision_students.sh AC_FT_26_12/provisioned.csv

Equivalent:

PROVISIONED_CSV=AC_FT_26_12/provisioned.csv ./deprovision_students.sh

Configuration beyond the minimum

secrets.env.example documents optional variables: server type/region (HCLOUD_TYPE, HCLOUD_LOCATION), IPv4 toggle, HCLOUD_COHORT_LABEL, N8N_IMAGE_TAG, task-runner token, timezone, etc. Defaults for VM shape and image are set at the top of provision_students.sh.

n8n / runners version: if you change N8N_IMAGE_TAG, align n8n-task-runners.json with the upstream file for that release (see comments in provision_students.sh). On existing VMs after a tag bump: docker compose pull && docker compose up -d in the deployed directory.


Troubleshooting (short)

  • server location disabled: set HCLOUD_LOCATION in secrets.env (e.g. nbg1, fsn1, ash) per Hetzner availability.
  • URLs not loading immediately: allow a minute or two for DNS and TLS after the first boot.
  • SSH / cloud-init: ensure the Hetzner SSH key name matches HCLOUD_SSH_KEY_NAME and that ${SSH_KEY_PATH}.pub exists locally.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages