Introduction
Quickly upload any raw disk images into your Hetzner Cloud projects!
About
The Hetzner Cloud API does not support uploading disk images directly, and it only provides a limited set of default images. The only option for custom disk images that users have is by taking a "snapshot" of an existing servers root disk. These can then be used to create new servers.
To create a completely custom disk image, users have to follow these steps:
- Create server with the correct server type
- Enable rescue system for the server
- Boot the server
- Download the disk image from within the rescue system
- Write disk image to servers root disk
- Shut down the server
- Take a snapshot of the servers root disk
- Delete the server
This is an annoyingly long process. Many users have automated this with Packer &
packer-plugin-hcloud
before, but Packer offers a lot of
additional complexity to wrap your head around.
This repository provides a simple CLI tool & Go library to do the above.
Getting Started
CLI
Binary
We provide pre-built deb
, rpm
and apk
packages. Alternatively we also provide the binaries directly.
Check out the GitHub release artifacts for all of these files and archives.
Arch Linux
You can get hcloud-upload-image-bin
from the AUR.
Use your preferred wrapper to install:
yay -S hcloud-upload-image-bin
go install
If you already have a recent Go toolchain installed, you can build & install the binary from source:
go install github.com/apricote/hcloud-upload-image@latest
Docker
There is a docker image published at ghcr.io/apricote/hcloud-upload-image
.
docker run --rm -e HCLOUD_TOKEN="<your token>" ghcr.io/apricote/hcloud-upload-image:latest <command>
Usage
export HCLOUD_TOKEN="<your token>"
hcloud-upload-image upload \
--image-url "https://example.com/disk-image-x86.raw.bz2" \
--architecture x86 \
--compression bz2
To learn more, you can use the embedded help output or check out the CLI help pages in this repository.:
hcloud-upload-image --help
hcloud-upload-image upload --help
hcloud-upload-image cleanup --help
Go Library
The functionality to upload images is also exposed in the library hcloudimages
! Check out the reference documentation for more details.
Install
go get github.com/apricote/hcloud-upload-image/hcloudimages
Usages
package main
import (
"context"
"fmt"
"net/url"
"github.com/hetznercloud/hcloud-go/v2/hcloud"
"github.com/apricote/hcloud-upload-image/hcloudimages"
)
func main() {
client := hcloudimages.NewClient(
hcloud.NewClient(hcloud.WithToken("<your token>")),
)
imageURL, err := url.Parse("https://example.com/disk-image-x86.raw.bz2")
if err != nil {
panic(err)
}
image, err := client.Upload(context.TODO(), hcloudimages.UploadOptions{
ImageURL: imageURL,
ImageCompression: hcloudimages.CompressionBZ2,
Architecture: hcloud.ArchitectureX86,
})
if err != nil {
panic(err)
}
fmt.Printf("Uploaded Image: %d", image.ID)
}
Contributing
If you have any questions, feedback or ideas, feel free to open an issue or pull request.
License
This project is licensed under the MIT license, unless the file explicitly specifies another license.
Support Disclaimer
This is not an official Hetzner Cloud product in any way and Hetzner Cloud does not provide support for this.
Uploading Images
Check out these docs from other projects to learn how to use hcloud-upload-image
:
Fedora CoreOS ↗
Flatcar Container Linux ↗
Talos Linux ↗
hcloud-upload-image
Manage custom OS images on Hetzner Cloud.
Synopsis
Manage custom OS images on Hetzner Cloud.
Options
-h, --help help for hcloud-upload-image
-v, --verbose count verbose debug output, can be specified up to 2 times
SEE ALSO
- hcloud-upload-image cleanup - Remove any temporary resources that were left over
- hcloud-upload-image upload - Upload the specified disk image into your Hetzner Cloud project.
hcloud-upload-image upload
Upload the specified disk image into your Hetzner Cloud project.
Synopsis
This command implements a fake "upload", by going through a real server and snapshots. This does cost a bit of money for the server.
Image Size
The image size for raw disk images is only limited by the servers root disk.
The image size for qcow2 images is limited to the rescue systems root disk. This is currently a memory-backed file system with 960 MB of space. A qcow2 image not be larger than this size, or the process will error. There is a warning being logged if hcloud-upload-image can detect that your file is larger than this size.
hcloud-upload-image upload (--image-path=<local-path> | --image-url=<url>) --architecture=<x86|arm> [flags]
Examples
hcloud-upload-image upload --image-path /home/you/images/custom-linux-image-x86.bz2 --architecture x86 --compression bz2 --description "My super duper custom linux"
hcloud-upload-image upload --image-url https://examples.com/image-arm.raw --architecture arm --labels foo=bar,version=latest
hcloud-upload-image upload --image-url https://examples.com/image-x86.qcow2 --architecture x86 --format qcow2
Options
--architecture string CPU architecture of the disk image [choices: x86, arm]
--compression string Type of compression that was used on the disk image [choices: bz2, xz]
--description string Description for the resulting image
--format string Format of the image. [choices: qcow2]
-h, --help help for upload
--image-path string Local path to the disk image that should be uploaded
--image-url string Remote URL of the disk image that should be uploaded
--labels stringToString Labels for the resulting image (default [])
--server-type string Explicitly use this server type to generate the image. Mutually exclusive with --architecture.
Options inherited from parent commands
-v, --verbose count verbose debug output, can be specified up to 2 times
SEE ALSO
- hcloud-upload-image - Manage custom OS images on Hetzner Cloud.
hcloud-upload-image cleanup
Remove any temporary resources that were left over
Synopsis
If the upload fails at any point, there might still exist a server or ssh key in your Hetzner Cloud project. This command cleans up any resources that match the label "apricote.de/created-by=hcloud-upload-image".
If you want to see a preview of what would be removed, you can use the official hcloud CLI and run:
$ hcloud server list -l apricote.de/created-by=hcloud-upload-image
$ hcloud ssh-key list -l apricote.de/created-by=hcloud-upload-image
This command does not handle any parallel executions of hcloud-upload-image and will remove in-use resources if called at the same time.
hcloud-upload-image cleanup [flags]
Options
-h, --help help for cleanup
Options inherited from parent commands
-v, --verbose count verbose debug output, can be specified up to 2 times
SEE ALSO
- hcloud-upload-image - Manage custom OS images on Hetzner Cloud.
Go Library
You can find the documentation at pkg.go.dev/github.com/apricote/hcloud-upload-image/hcloudimages ↗.
Changelog CLI
1.0.1 (2025-05-09)
Bug Fixes
1.0.0 (2025-05-04)
Features
- deps: require Go 1.23 (#70) (f3fcb62)
- docs website (#80) (d144b85)
- publish container image (#82) (91df729)
- upload qcow2 images (#69) (ac3e9dd)
0.3.1 (2024-12-07)
Bug Fixes
0.3.0 (2024-06-23)
Features
- set server type explicitly (#36) (42eeb00), closes #30
- update default x86 server type to cx22 (#38) (ebe08b3)
Bug Fixes
0.2.1 (2024-05-10)
Bug Fixes
0.2.0 (2024-05-09)
Features
- packaging for deb, rpm, apk, aur (#17) (139761c)
- upload local disk images (#15) (fcea3e3)
- upload xz compressed images (#16) (1c943e4)
Bug Fixes
0.1.1 (2024-05-04)
Bug Fixes
0.1.0 (2024-05-04)
Features
- cli: docs grouping and version (847b696)
- cli: hide redundant log attributes (9e65452)
- cli: upload command (b6ae95f)
- documentation and cleanup command (c9ab40b)
- initial library code (4f57df5)
- log output (904e5e0)
Changelog Library
1.0.1 (2025-05-09)
Bug Fixes
1.0.0 (2025-05-04)
Features
0.3.1 (2024-12-07)
Bug Fixes
0.3.0 (2024-06-23)
Features
- set server type explicitly (#36) (42eeb00), closes #30
- update default x86 server type to cx22 (#38) (ebe08b3)