ChainLaunch

Install ChainLaunch on a Hetzner VPS with deploy.sh

Install ChainLaunch on a Hetzner VPS with deploy.sh

David Viejo

Written by David Viejo

Self-hosting an enterprise blockchain control plane used to mean a weekend of YAML, certs, and reverse-proxy config. ChainLaunch ships a single bootstrap script — deploy.sh — that takes a clean Ubuntu VPS to a TLS-secured, systemd-managed dashboard in roughly 4 minutes. According to Hetzner's 2025 product overview, their entry-tier ARM64 cloud servers (cax11) cost around €4 per month — cheap enough that a full ChainLaunch evaluation costs less than a coffee.

This post walks the entire curl ... | bash flow on a real Hetzner cax11 instance — every prompt, the systemd unit it generates, the credentials file it leaves behind. The same script works locally on macOS or Linux for evaluation; the differences are called out at the bottom.

TL;DR: Run curl -fsSL https://chainlaunch.dev/deploy.sh | bash on a fresh Hetzner Ubuntu 24.04 VPS. The 6-step wizard installs Docker, the latest chaindeploy release (v0.3.1), TLS, and a systemd service. Total time observed on a cax11 ARM64 box: 4 minutes 1 second.

If you're new to ChainLaunch, our FabricX quickstart guide shows what to build once the platform is up. This post is the prerequisite.

What Does deploy.sh Actually Do?

deploy.sh is a 6-step bash wizard that handles everything between a bare Ubuntu image and a running ChainLaunch dashboard. According to the Hyperledger Foundation 2025 Annual Report, operational complexity is the top barrier to enterprise blockchain adoption — deploy.sh exists specifically to remove the install-day friction.

The 6 steps:

  1. Docker Engine — checks for Docker, installs from get.docker.com if missing, adds your user to the docker group
  2. Prerequisites — installs unzip and OpenJDK 21 (Besu needs Java for genesis-block generation)
  3. Install ChainLaunch — Community (free, public release) or Pro (private GitHub release, requires token)
  4. TLS Configuration — self-signed, Let's Encrypt via acme.sh, or skip
  5. Configure — pick a port, auto-generate admin password, preview config
  6. Start — Linux: register a systemd unit; macOS: foreground or background process

Behind the scenes the script writes state files to ~/.chainlaunch/.wizard-state/, downloads the platform-specific binary (chainlaunch-linux-arm64.zip for Hetzner ARM, chainlaunch-linux-amd64.zip for x86), and saves the generated credentials to ~/.chainlaunch/credentials.txt with mode 600.

The whole script is open source — read it at chainlaunch-web/public/deploy.sh before piping it to bash, especially on production boxes. According to the Linux Foundation Decentralized Trust (2026), supply-chain auditing of install scripts is now a baseline expectation for self-hosted enterprise infrastructure.

How Do You Provision a Hetzner VPS for ChainLaunch?

A Hetzner cax11 (2 ARM64 vCPU, 4 GB RAM, 40 GB SSD) costs approximately €0.005 per hour and handles a single-org Fabric or Besu testnet without breaking a sweat. According to the permissioned blockchain trends report, 61% of enterprise blockchain deployments now run BFT consensus, and most evaluation workloads fit comfortably in 4 GB of RAM during the proof-of-concept phase.

I provisioned a fresh cax11 in Hetzner's Falkenstein datacenter (fsn1) for this walkthrough — Ubuntu 24.04 LTS, hetzner SSH key pre-registered, public IPv4, default firewall (no inbound rules). Total cost for the entire test: less than one euro cent.

Three concrete steps to a ready-to-install box:

# 1. Create the server via Hetzner CLI (or the web console)
hcloud server create \
  --name chainlaunch-prod \
  --type cax11 \
  --image ubuntu-24.04 \
  --location fsn1 \
  --ssh-key your-key-name
 
# 2. SSH in (Hetzner emails you the IP, or the CLI prints it)
ssh root@<your-vps-ip>
 
# 3. Open port 8100 in the Hetzner firewall (web console -> Firewalls -> add inbound rule)
#    Or skip this if you're going to use Let's Encrypt + port 443 with a reverse proxy

That's the only manual setup. Everything else deploy.sh handles. If you want a click-through experience, ChainLaunch's managed cloud tier provisions the same Hetzner shape automatically — but for self-hosted users, the CLI flow above is faster.

Free resource

87% of Blockchain Projects Die Before Production — Readiness Scorecard

Score your project across 5 dimensions: infrastructure, key management, monitoring, DR, and team readiness. Know exactly where the gaps are before they kill your timeline.

No spam. Unsubscribe anytime.

Walkthrough: Running deploy.sh on the Live VPS

SSH into your Hetzner box as root and pipe the script:

curl -fsSL https://chainlaunch.dev/deploy.sh | bash

The script prints an ASCII banner and starts Step 1. Here's the actual session output from the cax11 box, with every prompt and answer:

Step 1: Docker Engine

   STEP 1/6   Docker Engine
  ────────────────────────────────────────────────────────────────────

  ! Docker is not installed
  • Docker is required for running blockchain nodes (Fabric peers,
  • orderers, CAs, Besu validators).

  → Install Docker now? [Y/n]: y

  • Installing Docker via https://get.docker.com...
  ✓ Downloading and installing Docker
  ✓ Docker installed and running
  • Docker version 29.4.1, build 055a478

The script invokes curl -fsSL https://get.docker.com | sh, then runs systemctl enable docker && systemctl start docker. On Ubuntu 24.04 ARM64, this took 47 seconds end to end. If you re-run deploy.sh later (e.g., to upgrade), it sees the existing Docker and skips the install.

Step 2: Prerequisites

   STEP 2/6   Prerequisites
  ────────────────────────────────────────────────────────────────────

  • Installing unzip (needed to extract ChainLaunch)...
  ✓ Installing unzip
  ✓ unzip installed
  • Installing Java (required for Besu blockchain nodes)...
  ✓ Updating package lists
  ✓ Installing OpenJDK 21 JRE
  ✓ Java installed
  • openjdk version "21.0.10" 2026-01-20

unzip extracts the ChainLaunch release archive. Java is needed because Besu's genesis-block generation runs in the JVM — even if you only plan to deploy Fabric, the JRE is installed so platform support stays uniform across deployments.

Step 3: Install ChainLaunch

The wizard offers Community (free) or Pro (requires a GitHub token tied to the private chainlaunch/chainlaunch-pro repo):

   STEP 3/6   Install ChainLaunch
  ────────────────────────────────────────────────────────────────────

  Which edition would you like to install?

    1)  ChainLaunch Community  — free, open-source (Fabric + Besu, REST API, CLI)
    2)  ChainLaunch Pro        — enterprise features (RBAC, SSO, backups, federation)

  → Enter choice [1-2]: 1

  ✓ Downloading ChainLaunch Community
  ✓ ChainLaunch installed: Version: v0.3.1
  • Binary: /root/.chainlaunch/bin/chainlaunch

Community pulls from the public LF-Decentralized-Trust-labs/chaindeploy releases. The script auto-detects architecture — on the Hetzner cax11 it picked linux-arm64; on an x86 box (e.g. cpx11) it would grab linux-amd64. Alpine systems get the -musl variant automatically.

The binary is dropped at ~/.chainlaunch/bin/chainlaunch and symlinked into /usr/local/bin/chainlaunch so the CLI is on your PATH without further configuration.

Step 4: TLS Configuration

   STEP 4/6   TLS Configuration
  ────────────────────────────────────────────────────────────────────

  How would you like to secure ChainLaunch with TLS?

    1)  Self-signed certificate  — generate locally, suitable for internal/dev use
    2)  Let's Encrypt (acme.sh)  — free trusted certificate, requires a domain and port 80
    3)  Skip TLS                 — run on plain HTTP (not recommended for production)

  → Enter choice [1-3]: 1

Three TLS modes, and the choice has real consequences:

Option When to use Trade-off
Self-signed Internal networks, evaluation, CI Browsers show a warning; fine for ops behind a VPN
Let's Encrypt (HTTP-01) Public-facing prod with a domain Needs port 80 free for the ACME challenge
Let's Encrypt (DNS manual) Behind a firewall, or wildcard certs You add a TXT record by hand
Skip Localhost evaluation only Auth credentials travel in cleartext — never use on a VPS

For this walkthrough I picked self-signed. The script generated a 4096-bit RSA cert valid for 365 days with subjectAltName=DNS:chainlaunch-blog-demo,DNS:localhost,IP:127.0.0.1:

  • Generating self-signed certificate...
  → Certificate Common Name (hostname or IP) [chainlaunch-blog-demo]:

  ✓ Self-signed certificate generated
  • Certificate: /root/.chainlaunch/tls/server.crt
  • Key:         /root/.chainlaunch/tls/server.key
  • Valid for:   365 days
  ! Browsers will show a security warning for self-signed certificates.

For a production VPS with a real domain (say chainlaunch.acme.com), pick Let's Encrypt option 2. The wizard installs acme.sh, asks for an email, then either uses the HTTP-01 challenge (requires port 80) or DNS manual mode (you paste a TXT record into your DNS provider). Certificate auto-renewal is wired through acme.sh's cron job — no further action needed.

Step 5: Configure

   STEP 5/6   Configure ChainLaunch
  ────────────────────────────────────────────────────────────────────

  → HTTP port [8100]:

  ✓ Admin credentials generated automatically
  • Detecting server IP address...
  ✓ Server IP: 178.104.217.129

  Configuration Preview

  Edition:               COMMUNITY
  Port:                  8100
  Admin user:            admin
  Admin password:        REDACTED-24-HEX-CHARS
  Data directory:        /root/.chainlaunch/data
  Database:              /root/.chainlaunch/chainlaunch.db
  TLS:                   self-signed
  Certificate:           /root/.chainlaunch/tls/server.crt
  Key:                   /root/.chainlaunch/tls/server.key
  Dashboard:             https://178.104.217.129:8100

  → Proceed with this configuration? [Y/n]: y

The admin password is auto-generated as 24 hex characters from openssl rand -hex 12. The wizard saves it to the state directory; you'll see it again in the final summary and in ~/.chainlaunch/credentials.txt. Don't pick a custom password here — auto-generated entropy beats whatever you'll type at 11pm on a Friday.

Step 6: Start

The Linux path offers two run modes — system service or foreground. Pick System service for any VPS deployment:

   STEP 6/6   Start ChainLaunch
  ────────────────────────────────────────────────────────────────────

  How would you like to run ChainLaunch?

    1)  System service  — starts on boot, runs in background (recommended)
    2)  Foreground      — run in current terminal session

  → Enter choice [1-2]: 1

  • Creating systemd service...
  • Starting ChainLaunch service...
  [############################################] 100% Waiting for ChainLaunch...
  ✓ ChainLaunch is running as a system service
  • Manage with: systemctl [start|stop|restart|status] chainlaunch

The wizard writes this systemd unit to /etc/systemd/system/chainlaunch.service:

[Unit]
Description=ChainLaunch Blockchain Infrastructure Platform
After=network.target docker.service
Requires=docker.service
 
[Service]
Type=simple
User=root
Environment=CHAINLAUNCH_USER=admin
Environment=CHAINLAUNCH_PASSWORD=REDACTED-24-HEX-CHARS
ExecStart=/root/.chainlaunch/bin/chainlaunch serve \
  --data=/root/.chainlaunch/data \
  --db=/root/.chainlaunch/chainlaunch.db \
  --port=8100 \
  --tls-cert=/root/.chainlaunch/tls/server.crt \
  --tls-key=/root/.chainlaunch/tls/server.key
Restart=on-failure
RestartSec=5
 
[Install]
WantedBy=multi-user.target

Requires=docker.service ensures Docker is up before ChainLaunch starts (so peer/orderer containers can launch). Restart=on-failure with a 5-second backoff handles crash recovery without flapping. The whole flow took 4 minutes 1 second on the cax11 ARM64 box, from curl ... | bash to SETUP COMPLETE.

Free resource

87% of Blockchain Projects Die Before Production — Readiness Scorecard

Score your project across 5 dimensions: infrastructure, key management, monitoring, DR, and team readiness. Know exactly where the gaps are before they kill your timeline.

No spam. Unsubscribe anytime.

How Do You Verify the Install Worked?

Three commands give you full confidence the install is healthy. According to my measurements on the cax11 box, all three return within 200 ms:

# 1. systemd thinks the service is running
systemctl status chainlaunch --no-pager
#   ● chainlaunch.service - ChainLaunch Blockchain Infrastructure Platform
#        Active: active (running) since Wed 2026-04-29 06:33:03 UTC; 16s ago
#      Main PID: 6025 (chainlaunch)
#         Tasks: 7 (limit: 4481)
#        Memory: 26.5M (peak: 26.9M)
 
# 2. The API answers an authenticated request
curl -sk -u admin:$(cat ~/.chainlaunch/.wizard-state/admin_password) \
  https://localhost:8100/api/v1/nodes
#   {"items":[],"total":0,"page":1,"pageCount":0,"hasNextPage":false}
 
# 3. The journal shows a clean startup sequence
journalctl -u chainlaunch --no-pager -n 10
#   Apr 29 06:33:03 chainlaunch[6025]: Starting server on port 8100...
#   Apr 29 06:33:03 chainlaunch[6025]: HTTPS server listening on :8100
#   Apr 29 06:33:03 chainlaunch[6025]: Created initial user with username: admin

Memory usage is impressively low — 26.5 MB resident on a freshly started instance, well within the 4 GB the cax11 provides. ChainLaunch only inflates when you start launching Fabric peers or Besu validators, which run as separate Docker containers and don't count against the control-plane's footprint.

The credentials file at ~/.chainlaunch/credentials.txt is mode 600 and exports environment variables for the CLI. Source it (source ~/.chainlaunch/credentials.txt) before running chainlaunch testnet fabric or any other API-driven command — this is the single biggest gotcha for first-time users.

How Do You Open the Dashboard from Your Laptop?

Point your browser at https://<your-vps-ip>:8100. With self-signed TLS, you'll see a browser warning — click "Advanced" then "Proceed to the IP address" (Chrome) or "Accept the Risk and Continue" (Firefox). You only do this once; the cert is pinned for 365 days.

For a production VPS, use Let's Encrypt mode in Step 4 with a domain pointing at the box. After the cert issues, the dashboard URL becomes https://chainlaunch.acme.com:8100 — no warning, no manual exception, and the Hetzner DNS Console makes the A-record setup a one-minute job.

Once in, log in with admin plus the 24-character password from the install summary. The first thing you'll see is the empty Nodes view — exactly what localhost:3100 shows on a fresh dev environment.

How Do You Run This Locally Instead of on a VPS?

The same deploy.sh works on macOS and on a local Linux box. Two differences worth knowing:

On macOS. The wizard detects Darwin and routes through Homebrew. Instead of apt-get, it runs brew install --cask docker and starts Docker Desktop via open -a Docker. Java comes from brew install openjdk@21. Step 6 swaps the systemd choice for "Background" or "Foreground" — there's no systemd on Mac, so the script either spawns a nohup background process or hands you the running server in your terminal.

On a local Linux dev machine. It works identically to the VPS path. You can pick "Foreground" in Step 6 if you'd rather see the logs in your terminal than register a system service — useful for tail -f-style debugging during early evaluation.

For evaluation only, you can skip TLS in Step 4 (option 3). The dashboard then runs on plain HTTP at http://localhost:8100, which is fine for trying things out — but never do this on anything reachable from the internet.

If you want to run the React frontend on a custom port (the chaindeploy dev environment defaults to port 3100 for the web UI and 8100 for the backend), use the chaindeploy-dev skill or the project's bun run devdeploy.sh is for installing pre-built releases, not for running source-code dev mode.

What Do You Do After the Install Succeeds?

Three concrete next steps, ranked by how much value they unlock per minute spent:

  1. Spin up your first network — follow the FabricX quickstart guide to create a 4-party Arma BFT network in 60 seconds. Or use chainlaunch testnet fabric for the classic Fabric flow.
  2. Wire up backups — ChainLaunch's backup provider system supports S3, EBS snapshots, and VMware. A daily restic snapshot to S3 costs pennies and turns your VPS from a single-point-of-failure into a recoverable production setup.
  3. Add a real domain + Let's Encrypt — re-run deploy.sh, pick option 2 in Step 4, point your domain's A record at the VPS. Auto-renewal is handled by acme.sh's cron job; you'll never touch it again.

For longer-term operations (upgrading, log rotation, multi-instance federation), the ChainLaunch deployment guide covers the runbook in detail.

Frequently Asked Questions

How long does deploy.sh take end to end?

On a fresh Hetzner cax11 (ARM64, 2 vCPU, 4 GB RAM) running Ubuntu 24.04 LTS, the whole script ran in 4 minutes 1 second from curl ... | bash to SETUP COMPLETE. About half that time is the Docker install via get.docker.com; the rest is OpenJDK 21, the ChainLaunch binary download, and the systemd unit setup. On x86 cpx11 boxes the timing is similar.

Is curl ... | bash safe?

The script itself is open source and lives at chainlaunch-web/public/deploy.sh. For production installs, the safer pattern is curl -fsSL https://chainlaunch.dev/deploy.sh -o deploy.sh && less deploy.sh && bash deploy.sh — review before executing. The script enforces set -euo pipefail, validates every download, and uses checksum-verified releases.

What's the difference between Community and Pro?

ChainLaunch Community is free and open source — Fabric + Besu nodes, REST API, CLI, web UI, all the core infrastructure features. Pro adds enterprise capabilities: RBAC roles (Admin/Operator/Viewer), OIDC/SSO integration, automated backups with S3 scheduling, multi-instance federation, audit logging, and the Smart Contract AI assistant. Pro requires a GitHub token tied to the private chainlaunch/chainlaunch-pro repo. See the pricing page for details.

How do I upgrade ChainLaunch later?

Re-run deploy.sh. The wizard sees the existing install, prompts "Re-install / upgrade? [y/N]", downloads the latest release, replaces the binary, and (because the script detects an active systemd service) automatically calls systemctl restart chainlaunch. State and data in ~/.chainlaunch/data and ~/.chainlaunch/chainlaunch.db are preserved across upgrades.

Can I install on Debian, RHEL, or Alpine?

Yes — deploy.sh detects the package manager (apt-get, dnf, yum, apk) and routes installs accordingly. On Alpine, the binary picks the -musl variant automatically. The systemd service unit only writes if systemctl is available, so Alpine + OpenRC users will need to wrap the binary in their own service definition (template available in the chaindeploy docs).

Conclusion

deploy.sh removes the install-day friction that has historically blocked teams from self-hosting blockchain control planes. Four minutes, one bash command, and you have a TLS-secured ChainLaunch dashboard backed by a properly-configured systemd service that survives reboots, restarts on failure, and waits for Docker before starting. On a Hetzner cax11 the monthly bill stays under €4 — less than half a dinner.

Three things to do next:

  • Run the script on your own VPS now: curl -fsSL https://chainlaunch.dev/deploy.sh | bash
  • Open https://your-vps-ip:8100 and create your first network with the FabricX quickstart guide
  • Read the deploy.sh source to understand exactly what it does on your machine — auditability is a feature, not a footnote

If you'd rather not manage the VPS yourself, ChainLaunch's managed cloud tier provisions the same Hetzner shape automatically and handles upgrades, backups, and TLS renewal on your behalf. Either way, the platform stays the same.

Free resource

87% of Blockchain Projects Die Before Production — Readiness Scorecard

Score your project across 5 dimensions: infrastructure, key management, monitoring, DR, and team readiness. Know exactly where the gaps are before they kill your timeline.

No spam. Unsubscribe anytime.

Related Articles

Ready to Deploy?

Deploy Fabric & Besu in minutes. Self-host for free or let us handle the infrastructure.

David Viejo, founder of ChainLaunch

Not sure which option?

Book a free 15-min call with David Viejo

No commitment. Cancel anytime.