From f59ba49618e487b820b4fe7c0fa02f98347e6320 Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Fri, 10 Oct 2025 16:43:01 +0200 Subject: [PATCH 1/5] Initial hetzner deployment instructions --- documentation/deployment/hetzner.md | 307 ++++++++++++++++++++++++++++ 1 file changed, 307 insertions(+) create mode 100644 documentation/deployment/hetzner.md diff --git a/documentation/deployment/hetzner.md b/documentation/deployment/hetzner.md new file mode 100644 index 000000000..3afa745cc --- /dev/null +++ b/documentation/deployment/hetzner.md @@ -0,0 +1,307 @@ +--- +title: Deploying to Hetzner Cloud +sidebar_label: Hetzner +description: + This document explains what hardware to use, and how to provision QuestDB on Hetzner Cloud. +--- + +import FileSystemChoice from "../../src/components/DRY/_questdb_file_system_choice.mdx" +import MinimumHardware from "../../src/components/DRY/_questdb_production_hardware-minimums.mdx" +import InterpolateReleaseData from "../../src/components/InterpolateReleaseData" +import CodeBlock from "@theme/CodeBlock" + + +## Hardware Recommendations + + + +### Hetzner Cloud servers and Block Storage Volumes + + +It is recommended to select a server with at least 8gb of RAM, for example the `CPX31`. + + +Hetzner Block Storage Volumes only supports ext4 or xfs so ext4. + + +Hetzner does not provide any guarantees on the block storage volume performance, but a simple measurement using `fio` reveals performance in the order of 300MBps and 4700 IOPS with a 64k block size, measured using +`fio --name=write_throughput --directory=/questdb/fiotest --numjobs=8 --size=10G --time_based --runtime=60s --ramp_time=2s --ioengine=libaio --direct=1 --verify=0 --bs=64k --iodepth=64 --rw=write --group_reporting=1` + + +## Creating the Hetzner resources + +Create the server and storage volume using the `hcloud` cli. You should pick a desired location near your other services, e.g. `nbg`. +The named `ssh-key` should be created in advance through the hetzner cloud console. During the creation of the server, the public key will be copied to `/root/.ssh/authorized_keys` so that it is possible to login to the server right after creation. + +``` +hcloud server create --type cpx41 --name questdb01 --image ubuntu-24.04 --ssh-key --location --label questdb +hcloud volume create --size 50 --name questdb01-storage --server questdb01 --format ext4 +``` + +The above will create a 50gb storage volume. This can be resized later. +Now try and login to the server: + +``` +hcloud server ssh questdb01 +``` + + +It is a good idea to put a firewall in front of the server. +The following commands will create a `questdb` firewall that applies to the `questdb` label which was attached the created server previously. +`ssh` on port 22 and icmp/echo is allowed as the only rules from anywhere. + +``` +hcloud firewall create --name questdb +hcloud firewall apply-to-resource questdb --type label_selector --label-selector questdb +hcloud firewall add-rule --direction in --source-ips 0.0.0.0/0 --source-ips ::/0 --protocol tcp --port 22 questdb +hcloud firewall add-rule --direction in --source-ips 0.0.0.0/0 --source-ips ::/0 --protocol icmp questdb +hcloud firewall add-rule --direction in --source-ips 1.2.3.4/32 --protocol tcp --port 9000 questdb +``` + +Replace `1.2.3.4` with your own ip. + +## Mounting the storage volume +Now obtain the linux device for the storage volume: + +``` +hcloud volume describe questdb01-storage +``` + +This will output something like: +``` +ID: 103719107 +Name: questdb01-storage +Created: Fri Oct 10 11:56:38 CEST 2025 (1 hour ago) +Size: 50 GB +Linux Device: /dev/disk/by-id/scsi-0HC_Volume_103719107 +Location: + Name: nbg1 + Description: Nuremberg DC Park 1 + Country: DE + City: Nuremberg + Latitude: 49.452102 + Longitude: 11.076665 +Server: + ID: 110531131 + Name: questdb01 +Protection: + Delete: yes +Labels: + No labels +``` + +Now ssh into the server and mount the volume: + +``` +hcloud server ssh questdb01 +questdb01$ mkdir /questdb +questdb01$ mount -o discard,defaults /dev/disk/by-id/scsi-0HC_Volume_103719107 /questdb +questdb01$ echo "/dev/disk/by-id/scsi-0HC_Volume_103719107 /questdb ext4 discard,nofail,defaults 0 0" >> /etc/fstab +``` + + +## Launching QuestDB using Docker + +Once you have provisioned your server with the attached storage volume, you can simply +follow the setup instructions for a [Docker](docker.md) or [systemd](systemd.md) installation. +You can also keep it simple - just [download](https://questdb.com/download/) the binary and run it directly. +QuestDB is a single self-contained binary and easy to deploy + +In the following we will go with a Docker setup. +You can find guides for installing Docker on Ubuntu on the +[official docker documentation](https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository). + + +Now run docker with forwarning of relevant ports and a volume mount to the mounted block storage volume: + +``` +docker run -d --name questdb \ + --restart unless-stopped \ + -p 9000:9000 -p 9009:9009 -p 8812:8812 -p 9003:9003 \ + -v "/questdb/qdbroot:/var/lib/questdb" \ + questdb/questdb:9.1.0 +``` + +All ports are optional, you can pick only the ones you need. For example, it is +enough to expose `8812` if you only plan to use +[Postgres wire protocol](/docs/reference/api/postgres/). + +To verify that the QuestDB deployment is operating as expected: +Copy the External IP of the instance. This can be found by running `ip -4 a s` on the server. +Navigate to `http://:9000` in a browser. + +## Upgrading QuestDB + +Stop the questdb docker service +``` +docker stop questbdb +docker rm questdb +``` + +And then re-run the `docker run ...` from above with a different questdb version. + + +:::note + +- Check the [release notes](https://github.com/questdb/questdb/releases) and + ensure that necessary [backup](/docs/operations/backup/) is completed. + +::: + +## Backup + +A Hetzner Block Storage Volume can only be attached at a single server at a time, so backups must be run directly from the server itself. +As an example of a on-prem backup, we will use [Borg Backup](https://www.borgbackup.org/). +Hetzner has [Storage Boxes](https://www.hetzner.com/storage/storage-box/) which provide cheap storage and it natively supports Borg Backup which makes the backup run reasonably fast. + +### Create Storage Box + +We start by creating a storage box using the `hcloud` cli: + +TODO: Not yet supported through hcloud (https://github.com/hetznercloud/hcloud-go/issues/675) +``` +hcloud storage-box create questdb-backup --type bx11 --name questdb-backup --ssh-key --location --with-ssh-support --external-reachable --label questdb +``` + +It is a good idea to pick a location that is geographically separated from the server itself. + + +When the storage box it will get a name like: `uXXXXX.your-storagebox.de`, and is accessible with a limited ssh shell on port 23: + +``` +ssh -p 23 uXXXXX@uXXXXX.your-storagebox.de +``` + +### Setting up SSH keys + +We need to generate a keypair for accessing the storage box from the questdb server instance. +From the [official Hetzner instructions](https://docs.hetzner.com/storage/storage-box/backup-space-ssh-keys/) we first generate a keypair on our local machine (no passphrase needed): + +``` +ssh-keygen -f questdb-backup +``` + +Copy the private key to the questdb server and modify the file permissions: +``` +scp questdb-backup.pub root@:/root/.ssh/ +hcloud server ssh questdb01 -- chmod 400 /root/.ssh/questdb-backup +``` + +Copy the public key to the questdb-backup storage box: +``` +cat questdb-backup.pub | ssh -p 23 uXXXXX@uXXXXX.your-storagebox.de install-ssh-key +``` + +The questdb server should now be able to connect to the backup storage box using the keypair. +Lets see if the works; ssh to the questdb server and run the following: + +``` +hcloud server ssh questdb01 +questdb01$ ssh -p 23 -i ~/.ssh/questdb-backup uXXXXX@uXXXXX.your-storagebox.de +``` + +It should login to the storagebox without requesting a password. + +### Setting up Borg Backup Repository + +It is now time to actually [setup borg backup](https://docs.hetzner.com/storage/storage-box/access/access-ssh-rsync-borg#borgbackup), now that the questdb server and the backup storage box can connect to each other. + +From the questdb server run +``` +questdb01$ apt install borgbackup borgmatic +questdb01$ export BORG_RSH="ssh -p 23 -i ~/.ssh/questdb-backup" +questdb01$ borg init --encryption=repokey --remote-path=borg-1.4 ssh://uXXXXX@uXXXXX.your-storagebox.de:23/./questdb01 +``` + +It will request a passphrase. This passphrase is used to encrypt the backup, and is used when doing a restore. + +### Create a backup configuration + +Create the borgmatic configuration file `/etc/borgmatic/config.yaml` with the following content: + +``` +source_directories: +- /questdb/qdbroot +repositories: +- path: ssh://uXXXXX@uXXXXX.your-storagebox.de:23/./questdb01 +keep_daily: 30 +keep_monthly: 12 +keep_yearly: 10 +``` + +### Run the first backup + +QuestDB [needs a checkpoint](https://questdb.com/docs/operations/backup/) to be created and released during backup. +We therefore need the postgresql-client to be installed on the server: + +``` +questdb01$ apt install postgresql-client +``` + +Try and run the client so that it connects to the questdb service: + +``` +questdb01$ psql postgresql://admin:quest@localhost:8812 -c "SELECT 1" +``` + +If this succeeds, then prepare for the first backup by creating a checkpoint, run the backup, and release the checkpoint: + +``` +questdb01$ psql postgresql://admin:quest@localhost:8812 -c "CHECKPOINT CREATE" +questdb01$ borgmatic --progress --stats -v 2 +questdb01$ psql postgresql://admin:quest@localhost:8812 -c "CHECKPOINT RELEASE" +``` + +If it reports success then we are ready to configure automatic backup. + +### Setup automatic backup using cron + +Create a `/root/.borg.env` on the `questdb01` server with the following: +``` +BORG_RSH="ssh -p 23 -i ~/.ssh/questdb-backup" +BORG_PASSPHRASE="" +``` + +Ensure that the file is only readable by root: +``` +questdb01$ chmod 400 .borg.env +``` + +Now create a shell script `/root/borg-run.sh` with the following: +``` +#!/bin/bash + +function finally { + echo "Releasing checkpoint" + psql postgresql://admin:quest@localhost:8812 -c "CHECKPOINT RELEASE" +} + +source /root/.borg.env + +# Create a consistent checkpoint before backup and release it afterwards +# See https://questdb.com/docs/operations/backup/ + +echo "Creating checkpoint" +psql postgresql://admin:quest@localhost:8812 -c "CHECKPOINT CREATE" + +# Ensure that the checkpoint is released when the script exits +trap finally EXIT + +echo "Running borgmatic backup" +borgmatic --progress --stats -v 0 2>&1 +``` + +The script first creates a checkpoint, it the runs the backup, and finishes by releasing the checkpoint. +Add execution permissions to the script: +``` +chmod +x borg-run.sh +``` + +It is now time to configure cron to run the borg-run script. +Run `crontab -e` and add the following line + +``` +0 4 * * * /root/borg-run.sh +``` + +It will run the backup every night at 04:00. \ No newline at end of file From 4e344157c6ce990452a95159e7072b2fdd6c2bf4 Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Mon, 13 Oct 2025 09:45:38 +0200 Subject: [PATCH 2/5] Various fixes and updates --- documentation/deployment/hetzner.md | 81 +++++++++++++++++++++-------- 1 file changed, 59 insertions(+), 22 deletions(-) diff --git a/documentation/deployment/hetzner.md b/documentation/deployment/hetzner.md index 3afa745cc..731527567 100644 --- a/documentation/deployment/hetzner.md +++ b/documentation/deployment/hetzner.md @@ -21,16 +21,16 @@ import CodeBlock from "@theme/CodeBlock" It is recommended to select a server with at least 8gb of RAM, for example the `CPX31`. -Hetzner Block Storage Volumes only supports ext4 or xfs so ext4. +Hetzner Block Storage Volumes only supports ext4 or xfs so we will use ext4 which is supported by questdb. Hetzner does not provide any guarantees on the block storage volume performance, but a simple measurement using `fio` reveals performance in the order of 300MBps and 4700 IOPS with a 64k block size, measured using -`fio --name=write_throughput --directory=/questdb/fiotest --numjobs=8 --size=10G --time_based --runtime=60s --ramp_time=2s --ioengine=libaio --direct=1 --verify=0 --bs=64k --iodepth=64 --rw=write --group_reporting=1` +`fio --name=write_throughput --directory=/questdb/fiotest --numjobs=8 --size=10G --time_based --runtime=60s --ramp_time=2s --ioengine=libaio --direct=1 --verify=0 --bs=64k --iodepth=64 --rw=write --group_reporting=1`. ## Creating the Hetzner resources -Create the server and storage volume using the `hcloud` cli. You should pick a desired location near your other services, e.g. `nbg`. +Create the server and storage volume using the Hetzner `hcloud` cli. You should pick a desired location near your other services, e.g. `nbg`. The named `ssh-key` should be created in advance through the hetzner cloud console. During the creation of the server, the public key will be copied to `/root/.ssh/authorized_keys` so that it is possible to login to the server right after creation. ``` @@ -47,7 +47,7 @@ hcloud server ssh questdb01 It is a good idea to put a firewall in front of the server. -The following commands will create a `questdb` firewall that applies to the `questdb` label which was attached the created server previously. +The following commands will create a `questdb` firewall that applies to servers with the `questdb` label which was attached the created server previously. `ssh` on port 22 and icmp/echo is allowed as the only rules from anywhere. ``` @@ -108,14 +108,14 @@ You can also keep it simple - just [download](https://questdb.com/download/) the QuestDB is a single self-contained binary and easy to deploy In the following we will go with a Docker setup. -You can find guides for installing Docker on Ubuntu on the +You can find guides for installing Docker on Ubuntu in the [official docker documentation](https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository). Now run docker with forwarning of relevant ports and a volume mount to the mounted block storage volume: ``` -docker run -d --name questdb \ +questdb01$ docker run -d --name questdb \ --restart unless-stopped \ -p 9000:9000 -p 9009:9009 -p 8812:8812 -p 9003:9003 \ -v "/questdb/qdbroot:/var/lib/questdb" \ @@ -130,12 +130,26 @@ To verify that the QuestDB deployment is operating as expected: Copy the External IP of the instance. This can be found by running `ip -4 a s` on the server. Navigate to `http://:9000` in a browser. +## Configuring QuestDB +Now is probably a good time to do some basic questdb configuration. Open `/questdb/qdbroot/conf/server.conf` and set a password: + +``` +pg.password= +``` + +Since the configuration file contains the admin password it is a good idea to restrict the access permissions to the file: + +``` +questdb01$ chmod 600 /questdb/qdbroot/conf/server.conf +``` + + ## Upgrading QuestDB Stop the questdb docker service ``` -docker stop questbdb -docker rm questdb +questdb01$ docker stop questbdb +questdb01$ docker rm questdb ``` And then re-run the `docker run ...` from above with a different questdb version. @@ -151,7 +165,7 @@ And then re-run the `docker run ...` from above with a different questdb version ## Backup A Hetzner Block Storage Volume can only be attached at a single server at a time, so backups must be run directly from the server itself. -As an example of a on-prem backup, we will use [Borg Backup](https://www.borgbackup.org/). +As an example of an on-prem backup, we will use [Borg Backup](https://www.borgbackup.org/). Hetzner has [Storage Boxes](https://www.hetzner.com/storage/storage-box/) which provide cheap storage and it natively supports Borg Backup which makes the backup run reasonably fast. ### Create Storage Box @@ -166,7 +180,7 @@ hcloud storage-box create questdb-backup --type bx11 --name questdb-backup --ssh It is a good idea to pick a location that is geographically separated from the server itself. -When the storage box it will get a name like: `uXXXXX.your-storagebox.de`, and is accessible with a limited ssh shell on port 23: +When the storage box is created it will get a name like: `uXXXXX.your-storagebox.de`, and is accessible with a limited ssh shell on port 23: ``` ssh -p 23 uXXXXX@uXXXXX.your-storagebox.de @@ -193,7 +207,7 @@ cat questdb-backup.pub | ssh -p 23 uXXXXX@uXXXXX.your-storagebox.de install-ssh- ``` The questdb server should now be able to connect to the backup storage box using the keypair. -Lets see if the works; ssh to the questdb server and run the following: +Lets see if it works; ssh to the questdb server and run the following: ``` hcloud server ssh questdb01 @@ -204,7 +218,7 @@ It should login to the storagebox without requesting a password. ### Setting up Borg Backup Repository -It is now time to actually [setup borg backup](https://docs.hetzner.com/storage/storage-box/access/access-ssh-rsync-borg#borgbackup), now that the questdb server and the backup storage box can connect to each other. +It is now time to actually [setup borg backup](https://docs.hetzner.com/storage/storage-box/access/access-ssh-rsync-borg#borgbackup), now that the questdb server can connect to the backup storage. From the questdb server run ``` @@ -229,7 +243,7 @@ keep_monthly: 12 keep_yearly: 10 ``` -### Run the first backup +### Install and configure the postgresql client QuestDB [needs a checkpoint](https://questdb.com/docs/operations/backup/) to be created and released during backup. We therefore need the postgresql-client to be installed on the server: @@ -238,18 +252,35 @@ We therefore need the postgresql-client to be installed on the server: questdb01$ apt install postgresql-client ``` +We now create an environment file in where we can store the admin password. +Create a `/root/.psql.env` file on the server with the following: +``` +PGUSER="admin" +PGPASSWORD="" +``` + +Ensure that the file is only readable by root: +``` +questdb01$ chmod 600 .psql.env +``` + Try and run the client so that it connects to the questdb service: ``` -questdb01$ psql postgresql://admin:quest@localhost:8812 -c "SELECT 1" +questdb01$ set -a && source .psql.env && set +a +questdb01$ psql postgresql://localhost:8812 -c "SELECT 1" ``` -If this succeeds, then prepare for the first backup by creating a checkpoint, run the backup, and release the checkpoint: +This should run the `SELECT 1` command successfully and output the result to the terminal. + +### Run the first backup + +It is now time to run the first backup. The backup sequence is as follows: 1) Create a checkpoint, 2) run the backup, and 3) release the checkpoint: ``` -questdb01$ psql postgresql://admin:quest@localhost:8812 -c "CHECKPOINT CREATE" +questdb01$ psql postgresql://localhost:8812 -c "CHECKPOINT CREATE" questdb01$ borgmatic --progress --stats -v 2 -questdb01$ psql postgresql://admin:quest@localhost:8812 -c "CHECKPOINT RELEASE" +questdb01$ psql postgresql://localhost:8812 -c "CHECKPOINT RELEASE" ``` If it reports success then we are ready to configure automatic backup. @@ -257,32 +288,38 @@ If it reports success then we are ready to configure automatic backup. ### Setup automatic backup using cron Create a `/root/.borg.env` on the `questdb01` server with the following: + ``` BORG_RSH="ssh -p 23 -i ~/.ssh/questdb-backup" BORG_PASSPHRASE="" ``` Ensure that the file is only readable by root: + ``` -questdb01$ chmod 400 .borg.env +questdb01$ chmod 600 .borg.env ``` Now create a shell script `/root/borg-run.sh` with the following: -``` + +```bash #!/bin/bash function finally { echo "Releasing checkpoint" - psql postgresql://admin:quest@localhost:8812 -c "CHECKPOINT RELEASE" + psql postgresql://localhost:8812 -c "CHECKPOINT RELEASE" } +set -a +source /root/.psql.env source /root/.borg.env +set +a # Create a consistent checkpoint before backup and release it afterwards # See https://questdb.com/docs/operations/backup/ echo "Creating checkpoint" -psql postgresql://admin:quest@localhost:8812 -c "CHECKPOINT CREATE" +psql postgresql://localhost:8812 -c "CHECKPOINT CREATE" # Ensure that the checkpoint is released when the script exits trap finally EXIT @@ -291,7 +328,7 @@ echo "Running borgmatic backup" borgmatic --progress --stats -v 0 2>&1 ``` -The script first creates a checkpoint, it the runs the backup, and finishes by releasing the checkpoint. +The script first creates a checkpoint, it then runs the backup, and finishes by releasing the checkpoint. Add execution permissions to the script: ``` chmod +x borg-run.sh From f809458a4602efd54761d2567d4cb0b299cd2d3c Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Mon, 13 Oct 2025 10:08:44 +0200 Subject: [PATCH 3/5] Greatly improve readability and reference questdb and hetzner docs --- documentation/deployment/hetzner.md | 658 +++++++++++++++++++++------- 1 file changed, 497 insertions(+), 161 deletions(-) diff --git a/documentation/deployment/hetzner.md b/documentation/deployment/hetzner.md index 731527567..040db4e25 100644 --- a/documentation/deployment/hetzner.md +++ b/documentation/deployment/hetzner.md @@ -2,7 +2,7 @@ title: Deploying to Hetzner Cloud sidebar_label: Hetzner description: - This document explains what hardware to use, and how to provision QuestDB on Hetzner Cloud. + This document explains what hardware to use, and how to provision QuestDB on Hetzner Cloud with storage volumes and automated backups. --- import FileSystemChoice from "../../src/components/DRY/_questdb_file_system_choice.mdx" @@ -10,64 +10,142 @@ import MinimumHardware from "../../src/components/DRY/_questdb_production_hardwa import InterpolateReleaseData from "../../src/components/InterpolateReleaseData" import CodeBlock from "@theme/CodeBlock" +This guide covers deploying QuestDB on Hetzner Cloud infrastructure, including server provisioning, storage configuration, and backup setup. + +## Prerequisites + +- Hetzner Cloud account with API access +- `hcloud` CLI tool installed and configured +- SSH key created in Hetzner Cloud Console ## Hardware Recommendations -### Hetzner Cloud servers and Block Storage Volumes +### Hetzner Cloud Server Specifications +For production deployments, we recommend selecting a server with at least 8GB of RAM. The `CPX31` or `CPX41` instances provide good balance of CPU and memory for most QuestDB workloads. -It is recommended to select a server with at least 8gb of RAM, for example the `CPX31`. +### Storage Considerations +Hetzner Block Storage Volumes support both ext4 and xfs filesystems. This guide uses ext4, which is fully supported by QuestDB and provides excellent performance characteristics. -Hetzner Block Storage Volumes only supports ext4 or xfs so we will use ext4 which is supported by questdb. +**Performance benchmarks**: While Hetzner doesn't provide specific performance guarantees for Block Storage Volumes, testing with `fio` typically shows: +- **Throughput**: ~300 MB/s +- **IOPS**: ~4700 with 64k block size +
+Benchmark command used -Hetzner does not provide any guarantees on the block storage volume performance, but a simple measurement using `fio` reveals performance in the order of 300MBps and 4700 IOPS with a 64k block size, measured using -`fio --name=write_throughput --directory=/questdb/fiotest --numjobs=8 --size=10G --time_based --runtime=60s --ramp_time=2s --ioengine=libaio --direct=1 --verify=0 --bs=64k --iodepth=64 --rw=write --group_reporting=1`. +```bash +fio --name=write_throughput --directory=/questdb/fiotest --numjobs=8 \ + --size=10G --time_based --runtime=60s --ramp_time=2s \ + --ioengine=libaio --direct=1 --verify=0 --bs=64k \ + --iodepth=64 --rw=write --group_reporting=1 +``` +
+For more guidance on storage requirements, see the [Capacity Planning](/docs/operations/capacity-planning/) documentation. -## Creating the Hetzner resources -Create the server and storage volume using the Hetzner `hcloud` cli. You should pick a desired location near your other services, e.g. `nbg`. -The named `ssh-key` should be created in advance through the hetzner cloud console. During the creation of the server, the public key will be copied to `/root/.ssh/authorized_keys` so that it is possible to login to the server right after creation. +## Provisioning Resources -``` -hcloud server create --type cpx41 --name questdb01 --image ubuntu-24.04 --ssh-key --location --label questdb -hcloud volume create --size 50 --name questdb01-storage --server questdb01 --format ext4 -``` +### Step 1: Create the Server and Storage Volume -The above will create a 50gb storage volume. This can be resized later. -Now try and login to the server: +Use the Hetzner Cloud CLI to provision your infrastructure. Choose a location (`nbg`, `fsn`, `hel`) closest to your other services for optimal latency. -``` +```bash +# Create the QuestDB server +hcloud server create \ + --type cpx41 \ + --name questdb01 \ + --image ubuntu-24.04 \ + --ssh-key \ + --location \ + --label questdb + +# Create and attach storage volume (50GB, expandable later) +hcloud volume create \ + --size 50 \ + --name questdb01-storage \ + --server questdb01 \ + --format ext4 +``` + +:::tip +Replace `` with the SSH key name from your Hetzner Cloud Console. Replace `` with your preferred data center location (e.g., `nbg1`, `fsn1`, `hel1`). +::: + +### Step 2: Verify Server Access + +Test SSH connectivity to ensure the server is properly configured: + +```bash hcloud server ssh questdb01 ``` +### Step 3: Configure Firewall Rules -It is a good idea to put a firewall in front of the server. -The following commands will create a `questdb` firewall that applies to servers with the `questdb` label which was attached the created server previously. -`ssh` on port 22 and icmp/echo is allowed as the only rules from anywhere. +Implement security best practices by creating a firewall with minimal required access: -``` +```bash +# Create firewall hcloud firewall create --name questdb -hcloud firewall apply-to-resource questdb --type label_selector --label-selector questdb -hcloud firewall add-rule --direction in --source-ips 0.0.0.0/0 --source-ips ::/0 --protocol tcp --port 22 questdb -hcloud firewall add-rule --direction in --source-ips 0.0.0.0/0 --source-ips ::/0 --protocol icmp questdb -hcloud firewall add-rule --direction in --source-ips 1.2.3.4/32 --protocol tcp --port 9000 questdb -``` -Replace `1.2.3.4` with your own ip. +# Apply to servers with 'questdb' label +hcloud firewall apply-to-resource questdb \ + --type label_selector \ + --label-selector questdb + +# Allow SSH access (port 22) +hcloud firewall add-rule \ + --direction in \ + --source-ips 0.0.0.0/0 \ + --source-ips ::/0 \ + --protocol tcp \ + --port 22 \ + questdb + +# Allow ICMP for ping/connectivity tests +hcloud firewall add-rule \ + --direction in \ + --source-ips 0.0.0.0/0 \ + --source-ips ::/0 \ + --protocol icmp \ + questdb + +# Allow QuestDB Web Console access (restrict to your IP) +hcloud firewall add-rule \ + --direction in \ + --source-ips /32 \ + --protocol tcp \ + --port 9000 \ + questdb +``` + +:::warning Security Note +Replace `` with your actual public IP address. For production deployments, consider restricting access to specific IP ranges or implementing additional security measures. +::: -## Mounting the storage volume -Now obtain the linux device for the storage volume: +**Default QuestDB Ports:** +- `9000`: [Web Console](/docs/web-console/) and [REST API](/docs/reference/api/rest/) +- `8812`: [PostgreSQL wire protocol](/docs/reference/api/postgres/) +- `9009`: [InfluxDB line protocol](/docs/reference/api/ilp/overview/) (TCP) +- `9003`: [Health monitoring](/docs/operations/logging-metrics/#minimal-http-server) and Prometheus metrics -``` +Add firewall rules for additional ports as needed for your specific use case. + +## Storage Volume Configuration + +### Step 1: Identify the Storage Device + +Get the Linux device path for your storage volume: + +```bash hcloud volume describe questdb01-storage ``` -This will output something like: +Example output: ``` ID: 103719107 Name: questdb01-storage @@ -90,255 +168,513 @@ Labels: No labels ``` -Now ssh into the server and mount the volume: +### Step 2: Mount the Storage Volume -``` +Connect to your server and configure the storage: + +```bash +# SSH into the server hcloud server ssh questdb01 -questdb01$ mkdir /questdb + +# Create mount point directory +questdb01$ mkdir -p /questdb + +# Mount the volume with optimized settings questdb01$ mount -o discard,defaults /dev/disk/by-id/scsi-0HC_Volume_103719107 /questdb + +# Add to fstab for persistent mounting questdb01$ echo "/dev/disk/by-id/scsi-0HC_Volume_103719107 /questdb ext4 discard,nofail,defaults 0 0" >> /etc/fstab + +# Verify the mount is successful +questdb01$ df -h /questdb ``` +:::note Mount Options Explained +- `discard`: Enables TRIM support for better SSD performance +- `nofail`: Prevents boot failure if volume is unavailable +- `defaults`: Uses standard mount options (rw,suid,dev,exec,auto,nouser,async) +::: -## Launching QuestDB using Docker +The QuestDB [root directory structure](/docs/concept/root-directory-structure/) will be created automatically on first startup. -Once you have provisioned your server with the attached storage volume, you can simply -follow the setup instructions for a [Docker](docker.md) or [systemd](systemd.md) installation. -You can also keep it simple - just [download](https://questdb.com/download/) the binary and run it directly. -QuestDB is a single self-contained binary and easy to deploy -In the following we will go with a Docker setup. -You can find guides for installing Docker on Ubuntu in the -[official docker documentation](https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository). +## Installing and Running QuestDB +### Installation Options -Now run docker with forwarning of relevant ports and a volume mount to the mounted block storage volume: +Once you have provisioned your server with attached storage, you have several installation options: -``` -questdb01$ docker run -d --name questdb \ - --restart unless-stopped \ - -p 9000:9000 -p 9009:9009 -p 8812:8812 -p 9003:9003 \ - -v "/questdb/qdbroot:/var/lib/questdb" \ - questdb/questdb:9.1.0 -``` +- **[Docker](docker.md)** - Containerized deployment (recommended for this guide) +- **[systemd](systemd.md)** - Native Linux service +- **Binary** - Direct execution of the [QuestDB binary](https://questdb.com/download/) + +### Docker Installation + +This guide uses Docker for its simplicity and portability. Install Docker on Ubuntu following the [official Docker documentation](https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository). + +#### Quick Docker installation: +```bash +questdb01$ curl -fsSL https://get.docker.com -o get-docker.sh +questdb01$ sudo sh get-docker.sh +questdb01$ sudo usermod -aG docker $USER +``` + +### Running QuestDB Container + +Start QuestDB with persistent storage mounted from your Block Storage Volume: + + ( + +{`questdb01$ docker run -d --name questdb \\ + --restart unless-stopped \\ + -p 9000:9000 -p 9009:9009 -p 8812:8812 -p 9003:9003 \\ + -v "/questdb/qdbroot:/var/lib/questdb" \\ + questdb/questdb:${release.name}`} + +)} +/> + +**Port mappings explained:** +- `-p 9000:9000`: [Web Console](/docs/web-console/) and [REST API](/docs/reference/api/rest/) +- `-p 9009:9009`: [InfluxDB line protocol](/docs/reference/api/ilp/overview/) (TCP) +- `-p 8812:8812`: [PostgreSQL wire protocol](/docs/reference/api/postgres/) +- `-p 9003:9003`: [Health monitoring](/docs/operations/logging-metrics/#minimal-http-server) and Prometheus metrics + +:::tip Port Selection +You can expose only the ports you need. For example, if you only plan to use PostgreSQL wire protocol, you can use `-p 8812:8812` exclusively. +::: + +### Verification -All ports are optional, you can pick only the ones you need. For example, it is -enough to expose `8812` if you only plan to use -[Postgres wire protocol](/docs/reference/api/postgres/). +Verify your QuestDB deployment: -To verify that the QuestDB deployment is operating as expected: -Copy the External IP of the instance. This can be found by running `ip -4 a s` on the server. -Navigate to `http://:9000` in a browser. +```bash +# Get the server's external IP +questdb01$ curl -s ifconfig.me -## Configuring QuestDB -Now is probably a good time to do some basic questdb configuration. Open `/questdb/qdbroot/conf/server.conf` and set a password: +# Check container status +questdb01$ docker ps +# View logs +questdb01$ docker logs questdb ``` -pg.password= + +Navigate to `http://:9000` in your browser to access the [Web Console](/docs/web-console/). + +## QuestDB Configuration + +### Basic Security Setup + +Configure essential security settings by editing the QuestDB configuration file: + +```bash +# Edit the configuration file +questdb01$ nano /questdb/qdbroot/conf/server.conf ``` -Since the configuration file contains the admin password it is a good idea to restrict the access permissions to the file: +**Essential configurations:** + +```ini title="/questdb/qdbroot/conf/server.conf" +# PostgreSQL authentication +pg.user=admin +pg.password= +# Optional: Web Console authentication +http.user=admin +http.password= ``` + +### Secure Configuration File + +Protect sensitive configuration data by restricting file permissions: + +```bash +# Restrict access to configuration file questdb01$ chmod 600 /questdb/qdbroot/conf/server.conf + +# Verify permissions +questdb01$ ls -la /questdb/qdbroot/conf/server.conf ``` +### Apply Configuration Changes -## Upgrading QuestDB +Restart the container to apply configuration changes: -Stop the questdb docker service -``` -questdb01$ docker stop questbdb -questdb01$ docker rm questdb +```bash +questdb01$ docker restart questdb ``` -And then re-run the `docker run ...` from above with a different questdb version. +### Additional Configuration Options +For comprehensive configuration options, see the [Configuration reference](/docs/configuration/) documentation. Common production settings include: -:::note +- **Connection limits**: `pg.connection.pool.size` +- **Memory settings**: `shared.worker.count` +- **Security**: [TLS configuration](/docs/operations/tls/) +- **Authentication**: [RBAC setup](/docs/operations/rbac/) -- Check the [release notes](https://github.com/questdb/questdb/releases) and - ensure that necessary [backup](/docs/operations/backup/) is completed. +The QuestDB [root directory structure](/docs/concept/root-directory-structure/) contains all configuration files and data. -::: -## Backup +## Upgrading QuestDB -A Hetzner Block Storage Volume can only be attached at a single server at a time, so backups must be run directly from the server itself. -As an example of an on-prem backup, we will use [Borg Backup](https://www.borgbackup.org/). -Hetzner has [Storage Boxes](https://www.hetzner.com/storage/storage-box/) which provide cheap storage and it natively supports Borg Backup which makes the backup run reasonably fast. +### Pre-upgrade Checklist -### Create Storage Box +Before upgrading, always: -We start by creating a storage box using the `hcloud` cli: +1. Check the [release notes](https://github.com/questdb/questdb/releases) for breaking changes +2. Complete a [backup](/docs/operations/backup/) of your data (see instruction later) +3. Test the upgrade in a staging environment if possible -TODO: Not yet supported through hcloud (https://github.com/hetznercloud/hcloud-go/issues/675) -``` -hcloud storage-box create questdb-backup --type bx11 --name questdb-backup --ssh-key --location --with-ssh-support --external-reachable --label questdb -``` +### Upgrade Process + + ( +<> +

To upgrade to the latest version ({release.name}):

+ +{`# Stop the current container +questdb01$ docker stop questdb + +# Remove the container (data persists in mounted volume) +questdb01$ docker rm questdb + +# Pull the latest image +questdb01$ docker pull questdb/questdb:${release.name} -It is a good idea to pick a location that is geographically separated from the server itself. +# Start with the new version +questdb01$ docker run -d --name questdb \\ + --restart unless-stopped \\ + -p 9000:9000 -p 9009:9009 -p 8812:8812 -p 9003:9003 \\ + -v "/questdb/qdbroot:/var/lib/questdb" \\ + questdb/questdb:${release.name}`} + + +)} +/> +### Verification -When the storage box is created it will get a name like: `uXXXXX.your-storagebox.de`, and is accessible with a limited ssh shell on port 23: +After upgrading, verify the deployment: +```bash +# Check container status +questdb01$ docker ps + +# View startup logs +questdb01$ docker logs questdb + +# Test connectivity +questdb01$ curl -f http://localhost:9000/status ``` + +:::warning Data Safety +Your data remains safe during upgrades as it's stored on the persistent Block Storage Volume. However, always maintain regular backups as described in the backup section below. +::: + +## Backup Strategy + +Since Hetzner Block Storage Volumes can only be attached to a single server, backups must be performed directly from the QuestDB server. This section demonstrates automated backup using [Borg Backup](https://www.borgbackup.org/) with [Hetzner Storage Box](https://www.hetzner.com/storage/storage-box/). + +### Storage Box Setup + +Hetzner Storage Boxes provide cost-effective remote storage with native Borg Backup support for efficient incremental backups. + +:::note Storage Box Creation +Storage Box creation via `hcloud` CLI is not yet supported ([tracking issue](https://github.com/hetznercloud/hcloud-go/issues/675)). Create through the [Hetzner Cloud Console](https://console.hetzner.cloud/) instead. +::: + +**Storage Box configuration:** +- **Type**: BX11 or higher based on data size requirements +- **SSH support**: Enable for Borg Backup access +- **Location**: Choose a different geographic region than your server for disaster recovery + +After creation, your Storage Box will have a hostname like `uXXXXX.your-storagebox.de` and is accessible via SSH on port 23: + +```bash ssh -p 23 uXXXXX@uXXXXX.your-storagebox.de ``` -### Setting up SSH keys +For detailed QuestDB backup concepts, see the [Backup Operations](/docs/operations/backup/) documentation. -We need to generate a keypair for accessing the storage box from the questdb server instance. -From the [official Hetzner instructions](https://docs.hetzner.com/storage/storage-box/backup-space-ssh-keys/) we first generate a keypair on our local machine (no passphrase needed): +### SSH Key Configuration -``` -ssh-keygen -f questdb-backup -``` +Set up secure authentication between your QuestDB server and Storage Box following [Hetzner's SSH key documentation](https://docs.hetzner.com/storage/storage-box/backup-space-ssh-keys/). + +#### Step 1: Generate SSH Key Pair + +Create a dedicated SSH key pair for backup operations (no passphrase required for automation): -Copy the private key to the questdb server and modify the file permissions: +```bash +# Generate key pair on your local machine +ssh-keygen -t rsa -b 4096 -f questdb-backup -N "" ``` -scp questdb-backup.pub root@:/root/.ssh/ + +#### Step 2: Deploy Private Key + +Copy the private key to your QuestDB server with secure permissions: + +```bash +# Copy private key to server +scp questdb-backup root@:/root/.ssh/ + +# Set secure permissions via SSH hcloud server ssh questdb01 -- chmod 400 /root/.ssh/questdb-backup ``` -Copy the public key to the questdb-backup storage box: -``` +#### Step 3: Install Public Key + +Add the public key to your Storage Box: + +```bash +# Install public key on Storage Box cat questdb-backup.pub | ssh -p 23 uXXXXX@uXXXXX.your-storagebox.de install-ssh-key ``` -The questdb server should now be able to connect to the backup storage box using the keypair. -Lets see if it works; ssh to the questdb server and run the following: +#### Step 4: Test Connection -``` +Verify SSH connectivity from your QuestDB server: + +```bash +# SSH to QuestDB server hcloud server ssh questdb01 + +# Test Storage Box connection questdb01$ ssh -p 23 -i ~/.ssh/questdb-backup uXXXXX@uXXXXX.your-storagebox.de ``` -It should login to the storagebox without requesting a password. +The connection should succeed without prompting for a password. + +### Borg Backup Repository Setup -### Setting up Borg Backup Repository +Configure Borg Backup following [Hetzner's Borg documentation](https://docs.hetzner.com/storage/storage-box/access/access-ssh-rsync-borg#borgbackup). -It is now time to actually [setup borg backup](https://docs.hetzner.com/storage/storage-box/access/access-ssh-rsync-borg#borgbackup), now that the questdb server can connect to the backup storage. +#### Install Backup Tools -From the questdb server run +```bash +# Install Borg Backup and Borgmatic +questdb01$ apt update && apt install -y borgbackup borgmatic ``` -questdb01$ apt install borgbackup borgmatic + +#### Initialize Backup Repository + +```bash +# Set SSH configuration for Borg questdb01$ export BORG_RSH="ssh -p 23 -i ~/.ssh/questdb-backup" -questdb01$ borg init --encryption=repokey --remote-path=borg-1.4 ssh://uXXXXX@uXXXXX.your-storagebox.de:23/./questdb01 + +# Initialize encrypted repository +questdb01$ borg init --encryption=repokey --remote-path=borg-1.4 \ + ssh://uXXXXX@uXXXXX.your-storagebox.de:23/./questdb01 ``` -It will request a passphrase. This passphrase is used to encrypt the backup, and is used when doing a restore. +:::warning Passphrase Security +You'll be prompted for an encryption passphrase. **Store this securely** - it's required for backup restoration. Consider using a password manager or secure vault. +::: -### Create a backup configuration +#### Create Borgmatic Configuration -Create the borgmatic configuration file `/etc/borgmatic/config.yaml` with the following content: +Create `/etc/borgmatic/config.yaml` with retention policies and source directories: -``` +```yaml title="/etc/borgmatic/config.yaml" +# Source directories to backup source_directories: -- /questdb/qdbroot + - /questdb/qdbroot + +# Backup repository location repositories: -- path: ssh://uXXXXX@uXXXXX.your-storagebox.de:23/./questdb01 -keep_daily: 30 -keep_monthly: 12 -keep_yearly: 10 -``` + - path: ssh://uXXXXX@uXXXXX.your-storagebox.de:23/./questdb01 -### Install and configure the postgresql client +# Retention policy +retention: + keep_daily: 30 + keep_monthly: 12 + keep_yearly: 10 -QuestDB [needs a checkpoint](https://questdb.com/docs/operations/backup/) to be created and released during backup. -We therefore need the postgresql-client to be installed on the server: +# Consistency checks +checks: + - repository + - archives -``` -questdb01$ apt install postgresql-client +# Borg-specific options +borg_ssh_command: ssh -p 23 -i /root/.ssh/questdb-backup ``` -We now create an environment file in where we can store the admin password. -Create a `/root/.psql.env` file on the server with the following: +### PostgreSQL Client Setup + +QuestDB requires [checkpoint management during backup operations](/docs/operations/backup/) to ensure data consistency. Install the PostgreSQL client for checkpoint commands: + +```bash +# Install PostgreSQL client +questdb01$ apt update && apt install -y postgresql-client ``` + +#### Configure Database Credentials + +Create secure credential storage for automated backup operations: + +```bash +# Create credentials file +questdb01$ cat > /root/.psql.env << EOF PGUSER="admin" -PGPASSWORD="" -``` +PGPASSWORD="" +PGHOST="localhost" +PGPORT="8812" +PGDATABASE="qdb" +EOF -Ensure that the file is only readable by root: -``` -questdb01$ chmod 600 .psql.env +# Secure the credentials file +questdb01$ chmod 600 /root/.psql.env ``` -Try and run the client so that it connects to the questdb service: +#### Test Database Connection -``` -questdb01$ set -a && source .psql.env && set +a -questdb01$ psql postgresql://localhost:8812 -c "SELECT 1" +Verify PostgreSQL connectivity: + +```bash +# Load environment variables +questdb01$ set -a && source /root/.psql.env && set +a + +# Test connection +questdb01$ psql -c "SELECT version();" ``` -This should run the `SELECT 1` command successfully and output the result to the terminal. +Expected output should show QuestDB version information, confirming successful database connectivity. -### Run the first backup +For more details on QuestDB's PostgreSQL compatibility, see the [PostgreSQL wire protocol](/docs/reference/api/postgres/) documentation. -It is now time to run the first backup. The backup sequence is as follows: 1) Create a checkpoint, 2) run the backup, and 3) release the checkpoint: +### Manual Backup Test -``` -questdb01$ psql postgresql://localhost:8812 -c "CHECKPOINT CREATE" +Perform a test backup to verify the complete backup pipeline. The backup process follows QuestDB's [recommended backup sequence](/docs/operations/backup/): + +1. **Create checkpoint** - Ensures consistent state +2. **Run backup** - Copy data to remote storage +3. **Release checkpoint** - Resume normal operations + +```bash +# Load database credentials +questdb01$ set -a && source /root/.psql.env && set +a + +# Step 1: Create checkpoint for consistent backup +questdb01$ psql -c "CHECKPOINT CREATE" + +# Step 2: Execute backup with progress monitoring questdb01$ borgmatic --progress --stats -v 2 -questdb01$ psql postgresql://localhost:8812 -c "CHECKPOINT RELEASE" + +# Step 3: Release checkpoint +questdb01$ psql -c "CHECKPOINT RELEASE" ``` -If it reports success then we are ready to configure automatic backup. +#### Verify Backup Success -### Setup automatic backup using cron +Check backup completion and repository status: -Create a `/root/.borg.env` on the `questdb01` server with the following: +```bash +# List backup archives +questdb01$ borg list ssh://uXXXXX@uXXXXX.your-storagebox.de:23/./questdb01 -``` -BORG_RSH="ssh -p 23 -i ~/.ssh/questdb-backup" -BORG_PASSPHRASE="" +# Check repository info +questdb01$ borg info ssh://uXXXXX@uXXXXX.your-storagebox.de:23/./questdb01 ``` -Ensure that the file is only readable by root: +If the backup reports success, proceed to automated backup configuration. +### Automated Backup Configuration + +Set up automated nightly backups using cron scheduling. + +#### Create Borg Environment Configuration + +Store Borg-specific environment variables securely: + +```bash +# Create Borg environment file +questdb01$ cat > /root/.borg.env << EOF +BORG_RSH="ssh -p 23 -i ~/.ssh/questdb-backup" +BORG_PASSPHRASE="" +EOF + +# Secure the environment file +questdb01$ chmod 600 /root/.borg.env ``` -questdb01$ chmod 600 .borg.env -``` -Now create a shell script `/root/borg-run.sh` with the following: +#### Create Backup Script + +Create an automated backup script that implements [QuestDB's checkpoint-based backup](/docs/operations/backup/): ```bash +questdb01$ cat > /root/borg-run.sh << 'EOF' #!/bin/bash -function finally { - echo "Releasing checkpoint" - psql postgresql://localhost:8812 -c "CHECKPOINT RELEASE" +# Exit on any error +set -e + +# Logging function +log() { + echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" +} + +# Cleanup function - always release checkpoint +function cleanup { + log "Releasing checkpoint" + psql -c "CHECKPOINT RELEASE" || log "WARNING: Failed to release checkpoint" } +# Load environment variables set -a source /root/.psql.env source /root/.borg.env set +a -# Create a consistent checkpoint before backup and release it afterwards -# See https://questdb.com/docs/operations/backup/ +# Ensure checkpoint is released on script exit +trap cleanup EXIT -echo "Creating checkpoint" -psql postgresql://localhost:8812 -c "CHECKPOINT CREATE" +log "Starting QuestDB backup process" -# Ensure that the checkpoint is released when the script exits -trap finally EXIT +# Create consistent checkpoint before backup +log "Creating database checkpoint" +psql -c "CHECKPOINT CREATE" -echo "Running borgmatic backup" +# Execute backup with minimal logging for cron +log "Running Borgmatic backup" borgmatic --progress --stats -v 0 2>&1 -``` -The script first creates a checkpoint, it then runs the backup, and finishes by releasing the checkpoint. -Add execution permissions to the script: -``` -chmod +x borg-run.sh +log "Backup completed successfully" +EOF + +# Make script executable +questdb01$ chmod +x /root/borg-run.sh ``` -It is now time to configure cron to run the borg-run script. -Run `crontab -e` and add the following line +#### Schedule Automated Backups + +Configure nightly backups at 4:00 AM: +```bash +# Add to crontab +questdb01$ (crontab -l 2>/dev/null; echo "0 4 * * * /root/borg-run.sh >> /var/log/questdb-backup.log 2>&1") | crontab - + +# Verify crontab entry +questdb01$ crontab -l ``` -0 4 * * * /root/borg-run.sh + +#### Monitor Backup Operations + +Track backup execution through logs: + +```bash +# View recent backup logs +questdb01$ tail -f /var/log/questdb-backup.log + +# Check backup history +questdb01$ borg list ssh://uXXXXX@uXXXXX.your-storagebox.de:23/./questdb01 | tail -10 ``` -It will run the backup every night at 04:00. \ No newline at end of file +:::tip Monitoring Best Practices +- Monitor backup logs regularly for failures +- Test backup restoration procedures periodically +- Consider setting up alerting for failed backups +- Verify backup integrity with `borg check` monthly +::: + +Your QuestDB instance on Hetzner Cloud is now fully configured with automated backups. For additional operational guidance, see the [Operations](/docs/operations/) documentation. \ No newline at end of file From c088b307043717dfaa8dc75ffc34e6713e2cb5ce Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Mon, 13 Oct 2025 10:12:01 +0200 Subject: [PATCH 4/5] Add additional settings for storage box --- documentation/deployment/hetzner.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/documentation/deployment/hetzner.md b/documentation/deployment/hetzner.md index 040db4e25..5cb0200bf 100644 --- a/documentation/deployment/hetzner.md +++ b/documentation/deployment/hetzner.md @@ -389,6 +389,7 @@ Storage Box creation via `hcloud` CLI is not yet supported ([tracking issue](htt - **Type**: BX11 or higher based on data size requirements - **SSH support**: Enable for Borg Backup access - **Location**: Choose a different geographic region than your server for disaster recovery +- **Additional settings**: Enable SSH support and mark the storage box as external reachable After creation, your Storage Box will have a hostname like `uXXXXX.your-storagebox.de` and is accessible via SSH on port 23: @@ -408,7 +409,7 @@ Create a dedicated SSH key pair for backup operations (no passphrase required fo ```bash # Generate key pair on your local machine -ssh-keygen -t rsa -b 4096 -f questdb-backup -N "" +ssh-keygen -f questdb-backup -N "" ``` #### Step 2: Deploy Private Key From 1cf3d1a447c49bd75c77500c160e40f90a5607e5 Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Tue, 21 Oct 2025 09:29:46 +0200 Subject: [PATCH 5/5] Add memory allocation guidelines --- documentation/deployment/hetzner.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/documentation/deployment/hetzner.md b/documentation/deployment/hetzner.md index 5cb0200bf..51b6c4a82 100644 --- a/documentation/deployment/hetzner.md +++ b/documentation/deployment/hetzner.md @@ -230,6 +230,7 @@ renderText={(release) => ( --restart unless-stopped \\ -p 9000:9000 -p 9009:9009 -p 8812:8812 -p 9003:9003 \\ -v "/questdb/qdbroot:/var/lib/questdb" \\ + -e JVM_PREPEND="-Xmx12g" \\ questdb/questdb:${release.name}`} )} @@ -245,6 +246,16 @@ renderText={(release) => ( You can expose only the ports you need. For example, if you only plan to use PostgreSQL wire protocol, you can use `-p 8812:8812` exclusively. ::: +**Memory allocation guidelines:** + +For production workloads, configure JVM memory allocation based on your server's available RAM. +In the example command above for a CPX41 (16GB RAM) instance we allocate ~12GB to QuestDB. For other instances consider these memory allocations: + +- Leave 25-30% of total RAM for the operating system and other processes +- For 16GB server: Use `-Xmx12g` +- For 32GB server: Use `-Xmx24g` +- For 64GB server: Use `-Xmx48g` + ### Verification Verify your QuestDB deployment: @@ -343,11 +354,12 @@ questdb01$ docker rm questdb # Pull the latest image questdb01$ docker pull questdb/questdb:${release.name} -# Start with the new version +# Start with the new version (include memory configuration) questdb01$ docker run -d --name questdb \\ --restart unless-stopped \\ -p 9000:9000 -p 9009:9009 -p 8812:8812 -p 9003:9003 \\ -v "/questdb/qdbroot:/var/lib/questdb" \\ + -e JVM_PREPEND="-Xmx12g" \\ questdb/questdb:${release.name}`}