> For the complete documentation index, see [llms.txt](https://docs.rumi.systems/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.rumi.systems/rumi-cli/commands/cloud/hetzner.md).

# hetzner

The `rumi cloud hetzner` commands provision and manage Rumi private clouds in [Hetzner Cloud](https://www.hetzner.com/cloud).

## Overview

Hetzner commands provide lifecycle management for Rumi private clouds on Hetzner Cloud:

* **Catalog Inspection** - List the SSH keys, server types, system images, and locations available in a project
* **Network Infrastructure** - Create a private network and the per-role cloud firewalls that secure the fleet
* **Platform Services** - Launch the Bastion, Admin, Monitor, and messaging broker nodes
* **Service Instances** - Launch application workers and open their app ports
* **HTTPS** - Terminate TLS on the bastion with a Let's Encrypt wildcard certificate
* **Lifecycle Management** - Launch a whole platform in one step, and tear a deployment down

## The Hetzner deployment model

Hetzner uses a **prebaked-snapshot** model (the same shape as the AWS AMI model): each role's software is baked once into a Hetzner **snapshot**, and every launch boots a node from that snapshot. Launches select the right snapshot by label, so before you can launch, the role snapshots must exist in the project.

The topology is **public-only**: every node has a public IP and also joins a private network (`10.0.0.0/16`). Internal names resolve through **BIND on the bastion** (the `rumi.local` zone → private IPs); each launched node's resolver is pointed at the bastion. Only the **bastion** is reachable from the internet (its firewall opens `22`/`80`/`443` to the world); every other role opens its ports only to the network CIDR, so all fleet operations flow through the bastion.

> A managed public-DNS + NAT / private-only topology is on the roadmap; today every node is public and on the private net.

## Prerequisites

Before using Hetzner commands, you must:

1. **Have a Hetzner Cloud project API token** - Supply it with `-k, --api-key` or the `HCLOUD_TOKEN` environment variable (matching the official `hcloud` CLI convention).
2. **Have the role snapshots baked into the project** - Launches boot from per-role snapshots discovered by label (`rumi-role=<role>`). Non-worker roles are baked *from* the service (Worker base) snapshot, so the service snapshot is baked first.
3. **Have an SSH key pair** - Referenced by `-K, --key-pair`; the private key lives at `~/.ssh/<key-pair>` and its public half is uploaded to the project (generated and uploaded automatically if absent).

## Commands

All three providers (AWS, Hetzner, Civo) now share one command vocabulary: per-component lifecycle verbs (`start-admin`, `stop-solace`, `terminate-monitor`, …), an env-wide `start`/`stop`, and `deprovision`.

### Catalog

| Command                                                                    | Description                                      |
| -------------------------------------------------------------------------- | ------------------------------------------------ |
| [list-sshkeys](/rumi-cli/commands/cloud/hetzner/list-sshkeys.md)           | List the SSH keys uploaded to the project        |
| [list-server-types](/rumi-cli/commands/cloud/hetzner/list-server-types.md) | List the available server types (instance sizes) |
| [list-images](/rumi-cli/commands/cloud/hetzner/list-images.md)             | List the available system (OS) images            |
| [list-locations](/rumi-cli/commands/cloud/hetzner/list-locations.md)       | List the available locations (regions)           |

### Network Management

| Command                                                              | Description                                                          |
| -------------------------------------------------------------------- | -------------------------------------------------------------------- |
| [create-network](/rumi-cli/commands/cloud/hetzner/create-network.md) | Create a private network and the per-role firewalls                  |
| [list-networks](/rumi-cli/commands/cloud/hetzner/list-networks.md)   | List the networks provisioned in the project                         |
| [delete-network](/rumi-cli/commands/cloud/hetzner/delete-network.md) | Delete a network + its firewalls (refuses if instances are attached) |
| [deprovision](/rumi-cli/commands/cloud/hetzner/deprovision.md)       | Tear down a network (servers, firewalls, network)                    |

{% hint style="info" %}
[delete-network](/rumi-cli/commands/cloud/hetzner/delete-network.md) is the granular inverse of [create-network](/rumi-cli/commands/cloud/hetzner/create-network.md): it removes the network and its firewalls but **refuses if any instance is still attached**. To tear a whole environment down (instances and network together), use [deprovision](/rumi-cli/commands/cloud/hetzner/deprovision.md) — `delete-network` is the scalpel, `deprovision` the sledgehammer.
{% endhint %}

### Bastion

The bastion is the network's public entry point and internal DNS server. It fronts the fleet's nginx reverse proxies and is the SSH entry point; it must be launched before any other role.

| Command                                                                    | Description                                                                 |
| -------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
| [launch-bastion](/rumi-cli/commands/cloud/hetzner/launch-bastion.md)       | Launch the bastion (DNS + public entry point)                               |
| [start-bastion](/rumi-cli/commands/cloud/hetzner/start-bastion.md)         | Start the bastion                                                           |
| [stop-bastion](/rumi-cli/commands/cloud/hetzner/stop-bastion.md)           | Stop the bastion                                                            |
| [terminate-bastion](/rumi-cli/commands/cloud/hetzner/terminate-bastion.md) | Terminate the bastion                                                       |
| [add-proxy](/rumi-cli/commands/cloud/hetzner/add-proxy.md)                 | Reverse-proxy a service publicly at `<service>.<domain>`                    |
| [enable-https](/rumi-cli/commands/cloud/hetzner/enable-https.md)           | Issue a Let's Encrypt wildcard certificate and terminate TLS on the bastion |

### Admin Service

| Command                                                                | Description                                                                        |
| ---------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
| [launch-admin](/rumi-cli/commands/cloud/hetzner/launch-admin.md)       | Launch the Admin node (agent + admin server + discovery broker + InfluxDB/Grafana) |
| [start-admin](/rumi-cli/commands/cloud/hetzner/start-admin.md)         | Start the Admin node                                                               |
| [stop-admin](/rumi-cli/commands/cloud/hetzner/stop-admin.md)           | Stop the Admin node                                                                |
| [terminate-admin](/rumi-cli/commands/cloud/hetzner/terminate-admin.md) | Terminate the Admin node                                                           |

### Monitor Service

| Command                                                                    | Description                       |
| -------------------------------------------------------------------------- | --------------------------------- |
| [launch-monitor](/rumi-cli/commands/cloud/hetzner/launch-monitor.md)       | Launch the Monitor node (Grafana) |
| [start-monitor](/rumi-cli/commands/cloud/hetzner/start-monitor.md)         | Start the Monitor node            |
| [stop-monitor](/rumi-cli/commands/cloud/hetzner/stop-monitor.md)           | Stop the Monitor node             |
| [terminate-monitor](/rumi-cli/commands/cloud/hetzner/terminate-monitor.md) | Terminate the Monitor node        |

### Message Brokers

| Command                                                                                                                                                                                                                                                                           | Description                        |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- |
| [launch-solace](/rumi-cli/commands/cloud/hetzner/launch-solace.md) / [start-solace](/rumi-cli/commands/cloud/hetzner/start-solace.md) / [stop-solace](/rumi-cli/commands/cloud/hetzner/stop-solace.md) / [terminate-solace](/rumi-cli/commands/cloud/hetzner/terminate-solace.md) | Solace broker                      |
| [launch-kafka](/rumi-cli/commands/cloud/hetzner/launch-kafka.md) / [start-kafka](/rumi-cli/commands/cloud/hetzner/start-kafka.md) / [stop-kafka](/rumi-cli/commands/cloud/hetzner/stop-kafka.md) / [terminate-kafka](/rumi-cli/commands/cloud/hetzner/terminate-kafka.md)         | Kafka broker                       |
| [launch-amq](/rumi-cli/commands/cloud/hetzner/launch-amq.md) / [start-amq](/rumi-cli/commands/cloud/hetzner/start-amq.md) / [stop-amq](/rumi-cli/commands/cloud/hetzner/stop-amq.md) / [terminate-amq](/rumi-cli/commands/cloud/hetzner/terminate-amq.md)                         | ActiveMQ (`rumi-messaging`) broker |

### Platform

| Command                                                                      | Description                                                  |
| ---------------------------------------------------------------------------- | ------------------------------------------------------------ |
| [launch-platform](/rumi-cli/commands/cloud/hetzner/launch-platform.md)       | Launch a standard platform (bastion, admin, monitor, solace) |
| [start-platform](/rumi-cli/commands/cloud/hetzner/start-platform.md)         | Start every platform instance (bastion first)                |
| [stop-platform](/rumi-cli/commands/cloud/hetzner/stop-platform.md)           | Stop every platform instance (bastion last)                  |
| [terminate-platform](/rumi-cli/commands/cloud/hetzner/terminate-platform.md) | Terminate every platform instance (bastion last)             |

### Service Instances

| Command                                                                      | Description                                               |
| ---------------------------------------------------------------------------- | --------------------------------------------------------- |
| [launch-instance](/rumi-cli/commands/cloud/hetzner/launch-instance.md)       | Launch a service (worker) instance and open its app ports |
| [start-instance](/rumi-cli/commands/cloud/hetzner/start-instance.md)         | Start a service instance                                  |
| [stop-instance](/rumi-cli/commands/cloud/hetzner/stop-instance.md)           | Stop a service instance                                   |
| [terminate-instance](/rumi-cli/commands/cloud/hetzner/terminate-instance.md) | Terminate a service instance                              |
| [resize-instance](/rumi-cli/commands/cloud/hetzner/resize-instance.md)       | Resize a service instance to a new server type            |
| [list-instances](/rumi-cli/commands/cloud/hetzner/list-instances.md)         | List the platform + service instances in a network        |

### Remote Execution

| Command                                                                  | Description                                   |
| ------------------------------------------------------------------------ | --------------------------------------------- |
| [run-command](/rumi-cli/commands/cloud/hetzner/run-command.md)           | Run a shell command on a service instance     |
| [run-admin-script](/rumi-cli/commands/cloud/hetzner/run-admin-script.md) | Run an admin script against a deployed system |

### High-Level Lifecycle

| Command                                                        | Description                                           |
| -------------------------------------------------------------- | ----------------------------------------------------- |
| [provision](/rumi-cli/commands/cloud/hetzner/provision.md)     | Provision a complete environment (network + platform) |
| [deploy](/rumi-cli/commands/cloud/hetzner/deploy.md)           | Deploy a XAR system to an environment                 |
| [configure](/rumi-cli/commands/cloud/hetzner/configure.md)     | Add/update/remove a controller config property        |
| [start](/rumi-cli/commands/cloud/hetzner/start.md)             | Start every instance in a network                     |
| [stop](/rumi-cli/commands/cloud/hetzner/stop.md)               | Stop every instance in a network                      |
| [deprovision](/rumi-cli/commands/cloud/hetzner/deprovision.md) | Tear down an environment                              |

## Common Options

Most Hetzner commands support these common options:

| Option       | Short | Description                                                                   | Default               |
| ------------ | ----- | ----------------------------------------------------------------------------- | --------------------- |
| `--api-key`  | `-k`  | The Hetzner Cloud project API token (or set `HCLOUD_TOKEN`)                   | Required              |
| `--region`   | `-r`  | The Hetzner location to operate in                                            | `fsn1`                |
| `--network`  | `-n`  | Name of the Rumi network                                                      | Required              |
| `--key-pair` | `-K`  | The SSH key pair to launch with (note: capital `-K`, since `-k` is the token) | Required for launches |

## Typical Workflow

```bash
# 1. Create the private network + per-role firewalls
rumi cloud hetzner create-network --api-key $HCLOUD_TOKEN --network my-cloud

# 2. Launch a standard platform (bastion -> admin -> monitor -> solace)
rumi cloud hetzner launch-platform \
  --api-key $HCLOUD_TOKEN --network my-cloud --key-pair rumi

# 3. Launch an application worker and open its app port
rumi cloud hetzner launch-instance \
  --api-key $HCLOUD_TOKEN --network my-cloud --key-pair rumi \
  --service myapp --ports 9000

# 4. (optional) Terminate TLS on the bastion
rumi cloud hetzner enable-https \
  --api-key $HCLOUD_TOKEN --network my-cloud --key-pair rumi \
  --domain example.com --dns-provider hetzner --dns-credentials $HETZNER_DNS_TOKEN --email ops@example.com

# 5. Tear it all down
rumi cloud hetzner deprovision --api-key $HCLOUD_TOKEN --network my-cloud
```

## Getting Help

Use `--help` (or `-h`) on any command:

```bash
rumi cloud hetzner --help
rumi cloud hetzner create-network --help
rumi cloud hetzner launch-instance --help
```

## Related Documentation

* [**Cloud Commands**](/rumi-cli/commands/cloud.md) - The standardized Rumi private cloud model
* [**AWS Commands**](/rumi-cli/commands/cloud/aws.md) - The equivalent commands on AWS
* [**Installation**](/rumi-cli/installation.md) - Install the Rumi CLI
