Install Cloudgate on your own server

One script turns a fresh Ubuntu 24.04 server into a Cloudgate instance. This page covers what the server needs, what the script sets up, the first sign-up, and what to do after.

Applies to: Self-hosted onlyRoot on the server

Cloudgate installs natively: two Node services under systemd (the console and the API), PostgreSQL on the same machine, Docker as a Swarm of one, and a Traefik container that serves the apps you deploy. It is not shipped as a container image. The Self-host page has the short version; this page is the full one. The source is public at github.com/octabyte-io/cloudgate, so a plain clone is all it takes to get it; Self-hosting Cloudgate covers the licence.

What the server needs

Operating system Ubuntu 24.04, freshly installed
Processor x86-64 (amd64). The script stops on anything else.
Size 2 vCPU, 4 GB memory, 40 GB disk. The install was proved on this size.
Access root over SSH
Ports open inbound 22 (SSH), 80 and 443 (your apps), 3000 (console), 4000 (API)
DNS None to start
Outbound access get.docker.com, nodejs.org, the npm registry, Docker Hub, github.com and release-assets.githubusercontent.com

Install Cloudgate

  1. Run the install command

    Run one command on the server, as a user who can sudo:

    curl -fsSL https://cloudgate.octabyte.io/install.sh | sudo sh

    It checks the server is Ubuntu 24.04 on x86-64, clones the public repository into /opt/cloudgate (the systemd units expect that path), finds the server’s public IPv4 address and hands over to deploy/install.sh, which does the install. The script is the repository’s install.sh; download it with -o install.sh instead of | sudo sh to read it first.

    The address the console is built for is CLOUDGATE_PUBLIC_HOST. To use a hostname, or an address other than the detected one, name it. It is built into the console, so changing it later means a rebuild, not a restart.

    curl -fsSL https://cloudgate.octabyte.io/install.sh | sudo CLOUDGATE_PUBLIC_HOST=cloud.example.com sh

    CLOUDGATE_REF installs another branch than main. The installer takes no subcommands. It prints each stage as ==> Swap, ==> Docker and so on, then a verification block.

  2. Check that it finished

    A good install ends like this:

    ==> Verification
    {"status":"ok"}
    {"open":true}
    console /sign-up: 200
    traefik  :80    : 404  (404 = listening)
    swarm: active
    network: overlay attachable=true
    traefik: true traefik:v3.6.7
    
    ==> Done. Open http://<host>:3000/sign-up — the first account owns the instance.

    A 404 from Traefik on port 80 is the success case: it is listening and has no app to serve yet.

  3. Claim the instance

    Open http://<server>:3000/sign-up and create an account. The first account owns the instance, and sign-up closes behind it. Everyone after that joins by invitation, from Settings > Members > Invite someone. Without mail set up, the console gives you the invitation link to send yourself.

  4. Add this machine as a Server

    Cloudgate can deploy onto the machine it runs on from the start. To also see its shell, Docker and setup on screen, open Servers, press Add a Server and point it at the machine’s own address with a key Cloudgate generates. Running setup on the already-installed machine is safe; every step checks before it acts. See Servers.

What the installer sets up

  • Swap, and the packages builds need (including build-essential and python3).
  • Node from nodejs.org, checksum-verified, and pnpm.
  • Docker, docker swarm init (a Swarm of one), and the cloudgate-network overlay network.
  • PostgreSQL, with a generated role and password.
  • Nixpacks for builds, and OpenTofu with pinned AWS and Google Cloud providers for Cloud accounts (about 255 MB to download).
  • A cloudgate service user, the folder /etc/cloudgate, and Traefik’s configuration.
  • The cloudgate-traefik container on ports 80 and 443.
  • Two systemd units, cloudgate-backend and cloudgate-console, that restart on their own.
  • ufw, allowing SSH, 80, 443, 3000 and 4000.

Secrets are generated once and kept in /etc/default/cloudgate-secrets (readable only by root); a second run reads them back instead of making new ones.

Deploy at an sslip.io address first

You do not need DNS to start. An Application’s Domains tab can Generate one for me: an sslip.io host such as web.203.0.113.24.sslip.io, which resolves to the server’s IP. It is served over plain HTTP until you add a domain of your own. See Domains.

Add a domain later

There are two kinds of domain on a self-hosted instance:

  • Your apps’ domains. Point a DNS record at the server, then add the host on the Service’s Domains tab with Serve over HTTPS and Let’s Encrypt. Traefik gets the certificate.
  • The console’s own domain. Settings > Instance > Console domain serves the console on a hostname, over HTTPS. Sign-in there is refused until that origin is trusted: add it under Settings > Single sign-on > Trusted origins (needs an Enterprise license) or in TRUSTED_ORIGINS in /etc/default/cloudgate-backend, then restart cloudgate-backend. Live screens (logs, shells) also need the API on the same hostname, which means rebuilding the console. See Instance settings.

Upgrade an instance

Run the install command again. It fast-forwards /opt/cloudgate to the latest main, reuses the address the last install was built for, migrates the database, rebuilds, and restarts both services, keeping your secrets.

curl -fsSL https://cloudgate.octabyte.io/install.sh | sudo sh

An instance installed before the repository was public may still fetch over SSH. If the upgrade says it could not fetch, point it at HTTPS and run the command again: git -C /opt/cloudgate remote set-url origin https://github.com/octabyte-io/cloudgate.git.

Read the What to do on upgrade lines in the repository’s changelog before you upgrade: most releases need nothing, and the ones that do say exactly what. Settings > Instance > This instance shows the version an instance runs. The CLI needs 0.1.0 or newer, and uploads only the changed files to 0.2.0 or newer.

The console’s Update and restart button does not work on a native install, and Restart Cloudgate is refused there: use systemctl restart cloudgate-backend cloudgate-console. A queued Deployment survives a restart; one that was building is cut off and ends as an error.

Back up the instance itself

Cloudgate backs up what you deploy, not itself. Keep these four off the server:

  • the PostgreSQL database cloudgate
  • /etc/default/cloudgate-backend
  • /etc/default/cloudgate-secrets
  • the folder /etc/cloudgate
su - postgres -c 'pg_dump -Fc cloudgate' > /root/cloudgate-$(date -u +%FT%TZ).dump
tar -czf /root/cloudgate-etc-$(date -u +%FT%TZ).tar.gz /etc/cloudgate /etc/default/cloudgate-*

What the install does not do

Questions

Do I need a domain name to install Cloudgate?

No. The installer works with the server's IP address, and the apps you deploy can use free sslip.io addresses that point at it. Add a domain later.

Can I run the installer again?

Yes. Every step checks before it acts, so a second run changes nothing that is already in place. Running the same command again is also how you upgrade.

Can I install it on ARM or another Linux?

No. The installer is tested on Ubuntu 24.04 on x86-64 and stops on any other processor architecture.

I lost my password and no mail is set up. What now?

There is no console path to reset it. Whoever has root on the server sets MAIL_PROVIDER and its settings in /etc/default/cloudgate-backend, restarts cloudgate-backend, and asks for the reset link again.

Something missing or wrong on this page? Email support@octabyte.io, or start a free trial and try it in the console.