Launchbox

Server Setup Guide

Complete guide to setting up a fresh Ubuntu server and installing Launchbox. You'll go from a blank VPS to a fully running deployment platform in about 15 minutes.

Your server username

All commands below will use this name

Do you already have a VPS?

Skip server setup steps if your VPS is ready

01

Create SSH Key (on your local PC)

The SSH key replaces password authentication — you'll use it to securely log into your server without typing a password each time.

ssh-keygen -t ed25519 -C "your-email@example.com"

Press Enter 3 times (default path, no passphrase). Then add the contents of ~/.ssh/id_ed25519.pub to your VPS provider's SSH key settings.

02

Create the Server

Create an Ubuntu server at your VPS provider (e.g. Hetzner, DigitalOcean) and select your SSH key. Create a firewall with the following inbound rules:

PortProtocolPurpose
22TCPSSH access
80TCPHTTP — Launchbox Dashboard + Domain Routing
443TCPHTTPS (SSL via Let's Encrypt)

You can also allow ICMP (for ping). Outbound rules: none needed (allow all).

03

Log into the Server

Connect as root — your SSH key will be used automatically.

ssh root@SERVER-IP
04

Update the System

Brings all pre-installed packages up to date. Always do this first on a fresh server.

apt update && apt upgrade -y
05

Create a New User

Never work as root — a typo could destroy your entire system. The new user gets sudo privileges so they can still run admin commands when needed.

adduser USER
usermod -aG sudo USER
06

Set Up SSH Key for the New User

Copies the SSH key from root to the new user so you can also log in as USER via SSH.

mkdir -p /home/USER/.ssh
cp ~/.ssh/authorized_keys /home/USER/.ssh/
chown -R USER:USER /home/USER/.ssh
chmod 700 /home/USER/.ssh
chmod 600 /home/USER/.ssh/authorized_keys
Test the login before continuing! Open a new terminal and verify ssh USER@SERVER-IP works. If it does, proceed to step 7.
07

Secure SSH

Disables root login and password authentication. After this, you can only log in with an SSH key as a normal user — much more secure.

Disable root login + password auth
# Disable root login
sed -i 's/^PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
sed -i 's/^PermitRootLogin prohibit-password/PermitRootLogin no/' /etc/ssh/sshd_config

# Disable password login
sed -i 's/^#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
sed -i 's/^PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config

systemctl restart ssh
Do NOT close your current SSH session until you've tested ssh USER@SERVER-IP in a second terminal. Otherwise you could lock yourself out.
08

Server Firewall (optional)

Second layer of protection directly on the server. If the provider's firewall is accidentally deleted, your server is still protected.

ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
09

Install Node.js

Launchbox needs Node.js to build and run Next.js and Node apps.

curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
apt install -y nodejs
10

Install Git

Required to clone repos from GitHub.

apt install -y git
11

Create Launchbox Directory

Creates the directory where Launchbox and all app data will live.

mkdir -p /opt/launchbox/data
chown -R USER:USER /opt/launchbox
12

Verify Everything is Installed

Quick check that all tools are available.

node -v
npm -v
git --version
Log out as root now. From this point on, only work as your regular user.
exit
ssh USER@SERVER-IP
13

Build & Upload Launchbox

On your local machine, build the Linux binary and copy it to the server. Go can cross-compile — you don't need Linux to build.

Build on your local machine
cd /path/to/launchbox

# 1. Install frontend dependencies (first time only)
cd frontend && npm install && cd ..

# 2. Build the frontend (React → HTML/JS/CSS)
cd frontend && npm run build && cd ..

# 3. Build the Go binary for Linux (embeds the frontend)
# Windows:
set GOOS=linux
set GOARCH=amd64
go build -o launchbox-linux .

# Mac/Linux:
GOOS=linux GOARCH=amd64 go build -o launchbox-linux .

# 4. Upload to server
scp launchbox-linux USER@SERVER-IP:/opt/launchbox/launchbox

Then on the server, make it executable:

ssh USER@SERVER-IP
chmod +x /opt/launchbox/launchbox
14

Allow Port 80/443 Binding

Launchbox needs to listen on port 80 (and 443 for SSL) so domains are directly reachable. Linux only allows root to bind ports below 1024 — this command grants permission to your binary.

sudo setcap cap_net_bind_service=+ep /opt/launchbox/launchbox
Run this command again after every update— a new binary doesn't inherit the permission.
15

Set Up systemd Service

Makes Launchbox start automatically — even after a server reboot or crash. Running apps are automatically restored on restart.

/etc/systemd/system/launchbox.service
sudo tee /etc/systemd/system/launchbox.service << 'EOF'
[Unit]
Description=Launchbox PaaS
After=network.target

[Service]
Type=simple
User=USER
WorkingDirectory=/opt/launchbox
ExecStart=/opt/launchbox/launchbox
Environment=LAUNCHBOX_PORT=80
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now launchbox

Optional: Add GitHub OAuth and login credentials as environment variables (add under [Service]):

Environment=GITHUB_CLIENT_ID=your-client-id
Environment=GITHUB_CLIENT_SECRET=your-client-secret
Environment=LAUNCHBOX_USER=your-username
Environment=LAUNCHBOX_PASS=your-password

After editing the service file:

sudo systemctl daemon-reload
sudo systemctl restart launchbox
16

Check if it's Running

Shows the service status. Should display "active (running)".

sudo systemctl status launchbox

Open in your browser: http://SERVER-IP

Default login: admin / admin — change immediately in Settings!

Reference

Useful commands, update process, domain setup, and troubleshooting.

Useful Commands

CommandDescription
sudo systemctl status launchboxCheck status
sudo systemctl restart launchboxRestart
sudo systemctl stop launchboxStop
sudo journalctl -u launchbox -fLive logs
sudo journalctl -u launchbox -n 50Last 50 log lines

Deploy an Update

When you've made changes to the code, rebuild locally and upload the new binary.

1. Build locally (Windows example)
cd D:\path\to\launchbox

# Rebuild frontend (only if UI changed)
cd frontend
npm run build
cd ..

# Build Linux binary (includes new frontend)
set GOOS=linux
set GOARCH=amd64
go build -o launchbox-linux .
2. Upload and restart
# Stop the service
ssh USER@SERVER-IP
sudo systemctl stop launchbox
exit

# Upload new binary
scp launchbox-linux USER@SERVER-IP:/opt/launchbox/launchbox

# Set port permission + start
ssh USER@SERVER-IP
sudo setcap cap_net_bind_service=+ep /opt/launchbox/launchbox
sudo systemctl start launchbox

# Verify
sudo systemctl status launchbox

Domain Setup

To make an app reachable under a custom domain:

  1. Set a DNS A record at your domain provider: subdomain.yourdomain.comSERVER-IP
  2. Wait for DNS propagation (1–30 minutes, check with nslookup)
  3. In Launchbox → DomainsAdd Domain → enter domain, select app
  4. DNS status is shown on the Domains page (green = connected)
  5. Your app is now reachable at http://subdomain.yourdomain.com

Enable SSL (HTTPS)

  1. Ensure the DNS A record is correct (green status)
  2. Add the domain in Launchbox with SSL enabled
  3. Restart Launchbox: sudo systemctl restart launchbox
  4. Let's Encrypt automatically provisions a certificate
  5. HTTP requests are automatically redirected to HTTPS
  6. Certificates are stored in ./data/certs/ and auto-renewed

Troubleshooting

"permission denied" on port 80/443

sudo setcap cap_net_bind_service=+ep /opt/launchbox/launchbox
sudo systemctl restart launchbox

"EADDRINUSE: address already in use"

An old Node process is still running. Kill all and restart:

sudo killall -9 node
sudo systemctl restart launchbox

"parse apps.json: unexpected..."

The apps.json is corrupted. Reset it:

echo '[]' > /opt/launchbox/data/apps.json
sudo systemctl restart launchbox

SSL not working / TLS handshake errors

Delete old certificates and let Launchbox fetch new ones:

rm -rf /opt/launchbox/data/certs/*
sudo systemctl restart launchbox

App deployed but not reachable via domain

  1. Check if the app is actually running (Dashboard → Status "Running"?)
  2. Check DNS: nslookup your-domain.com → correct server IP?
  3. Check if Launchbox is listening on port 80: sudo ss -tlnp | grep :80
  4. Check logs: sudo journalctl -u launchbox -n 30

Service won't start after update

Usually missing setcap or wrong permissions:

chmod +x /opt/launchbox/launchbox
sudo setcap cap_net_bind_service=+ep /opt/launchbox/launchbox
sudo systemctl restart launchbox
sudo journalctl -u launchbox -n 20

Full reset (delete all apps and repos)

sudo killall -9 node 2>/dev/null
rm -rf /opt/launchbox/data/repos/*
echo '[]' > /opt/launchbox/data/apps.json
sudo systemctl restart launchbox

Directory Structure on Server

/opt/launchbox/
├── launchbox              ← The binary (contains frontend + backend)
├── data/
│   ├── apps.json          ← App configurations
│   ├── domains.json       ← Domain mappings
│   ├── github.json        ← GitHub OAuth token
│   ├── auth.json          ← Login credentials
│   ├── repos/             ← Cloned git repos
│   │   ├── a1b2c3.../     ← App 1 (e.g. Next.js project)
│   │   ├── d4e5f6.../     ← App 2
│   │   └── ...
│   └── certs/             ← SSL certificates (Let's Encrypt)