WiseHosting

Getting started

Bring up the control plane locally and point a worker at it.

This page walks you through bringing up the control plane locally and pointing a worker at it.

What you'll have at the end

A control plane running on your laptop that signs you in with Google, plus a remote Linux host configured as a worker that can build and run a containerised app. Five steps, maybe 20 minutes if you have everything ready.

If a term feels unfamiliar (PaaS, WSS, WireGuard…), check the Glossary first.

Prerequisites

  • Go 1.23+
  • Docker / Docker Compose (for local Postgres)
  • A Google OAuth client (Console → APIs & Services → Credentials)
  • One Linux host with root access for the worker (Ubuntu/Debian/Fedora/Arch)
  • A DNS zone you control on Cloudflare (one per worker)

1. Bring up Postgres

docker compose up -d

Compose starts Postgres on the port from docker-compose.yml. The Go process runs golang-migrate on startup against internal/database/migrations/*.sql, so no manual SQL needs to be applied. A schema_migrations row tracks the applied version.

2. Configure

cp config.yaml.example config.yaml

Set at minimum:

SectionKeyWhy
api_serversecretUsed for AES-GCM encryption keys + worker register
databasepasswordPostgres password
googleoauth_client_id / oauth_client_secretRequired for sign-in
platformdomainPublic domain (used in URLs and CSP)
webappurlHTTPS URL where the dashboard is served

See Configuration for the full schema.

HTTPS is mandatory for cookies

webapp.url must be HTTPS in production — the wh_session cookie is Secure. In dev you can tunnel through ngrok/cloudflared or run plain HTTP on localhost.

3. Run the control plane

go run .

This single binary spins up:

  • The HTTP/REST API and worker WSS endpoint
  • The scheduler (poll loop + worker-health monitor)
  • The alert manager + threshold poller
  • The usage recorder (per-app 5-min samples)
  • The webhook dispatcher (HTTPS + 22 Shoutrrr channels)
  • The dashboard (embedded SPA)

4. Add a worker

Workers reach the control plane over a self-hosted WireGuard mesh (10.50.0.0/24, UDP 51821). On the control-plane host first:

sudo ./scripts/wireguard-setup.sh control

The script prints the CP public key and the CP public IPv4 — copy both. Then on the worker host:

sudo ./scripts/wireguard-setup.sh worker \
  --cp-pubkey   '<CP public key>' \
  --cp-public-ip '<CP public IPv4>' \
  --worker-id    2

curl -fsSL https://raw.githubusercontent.com/Krinali12/hostingbot/master/scripts/worker-setup.sh | sudo bash

--worker-id 2 puts this worker at 10.50.0.3 (formula: 10.50.0.{ID+1}). After the worker side runs, paste its public key as a [Peer] block on the CP and reload with sudo wg syncconf wg0 <(wg-quick strip wg0) — see WireGuard mesh for the full key-exchange dance.

The installer downloads the worker binary, installs Podman 5 (alvistack OBS repo on Ubuntu 22.04 / Debian 12), prompts for config on /dev/tty, writes /etc/wisehosting/config.yaml, installs wisehosting-worker.service, creates the wisehosting-build Podman network for build-time DNS, runs Traefik on :8080, and applies iptables egress hardening. Point api_server.url at http://10.50.0.1:8081 (plain HTTP is permitted because the WireGuard tunnel already encrypts every byte; :8081 is the control-plane HTTP port).

For the full wire-up (DNS, Cloudflare Tunnel, custom domains, TLS) see Worker deployment.

5. Verify

# On the control plane host:
journalctl -u wisehosting -f | grep "hub: worker"
# Expect: hub: worker <ID> (<name>) connected via WSS

Then open the dashboard at https://<your domain>/, sign in with Google, link a git provider under Git Integrations, and deploy a test repo. 2FA is opt-in under Account → Security.

On this page