Skip to content
NebulaCtrldocs

Install NebulaCtrl

Install the NebulaCtrl control plane on one Linux host with a single command, then sign in through your OpenID Connect provider as the owner.

You'll install the control plane, the service that records what runs where and tells your clusters to run it. It runs in Docker on one Linux host. When you finish, you can sign in at your public URL as the owner.

NebulaCtrl is in beta

Upgrades migrate your data in place, and a console update that doesn't come up healthy is rolled back automatically. The HTTP API and nebula.toml may still change before 1.0. The changelog announces every change.

Before you begin

You need:

  • A Linux host, amd64 or arm64, with curl, Docker and the Docker Compose plugin. The installer doesn't install Docker. The host must meet the requirements.
  • A public URL for the control plane, for example https://nebula.example.com. The installer binds the control plane to 127.0.0.1:8080 and expects a reverse proxy to terminate TLS in front of it. Every cluster you connect dials this URL over HTTPS, so it needs a valid certificate and must be reachable from each cluster.
  • An OpenID Connect (OIDC) client at your identity provider. The issuer must serve /.well-known/openid-configuration. The provider must return an email address and must not report it as unverified. NebulaCtrl has no local accounts.
  • A user that can run docker, or passwordless sudo. The installer needs write access to /opt/nebula, or passwordless sudo to create it.

1. Register the redirect URI

In your identity provider, add this redirect URI to the OIDC client:

https://nebula.example.com/api/v1/auth/callback

Replace https://nebula.example.com with your public URL. The client uses the authorization code flow with the scopes openid profile email.

You see the redirect URI saved on the client in your provider's console.

2. Run the installer

In a terminal on the host, run:

curl -fsSL https://get.nebulactrl.dev | sh

The installer asks for each value it doesn't have and shows a summary before it changes anything:

On a first install it also asks for Sign-in button label, Database (postgres://...) (leave it blank to run the bundled PostgreSQL) and Listen address. Answer Apply? to continue.

You see seven numbered stages, then a box with the URL to open:

Open          https://nebula.example.com
Sign in with  id.example.com

Redirect URI to register with your OIDC provider:
  https://nebula.example.com/api/v1/auth/callback

What the installer does

Each stage prints a check mark when it passes.

  1. Checking your system. Confirms Linux on amd64 or arm64, curl, Docker with the Compose plugin (directly or through passwordless sudo), a writable install directory, and a free listen port. A missing requirement stops the run before the installer writes any configuration.
  2. Configuration. Collects the values, warns if the issuer doesn't answer discovery, and refuses to move an existing install to an older version. With --yes it stops here if a required value is missing.
  3. Pulling the image. Pulls ghcr.io/nebulactrl/nebula:VERSION, resolves its digest and confirms the image reports that version.
  4. Writing configuration. Writes /opt/nebula/.env (mode 600) and downloads /opt/nebula/deploy/compose.prod.yaml. It generates the master key and the database password once, and a console-updates token when the host can run the updater. It pins the image by digest. Settings you added below the marker line in .env survive every re-run.
  5. Starting containers. Runs docker compose as the project nebula. The control plane container starts with a read-only filesystem, no Linux capabilities and no new privileges, and applies pending database migrations when it boots.
  6. Waiting for the control plane to become healthy. Polls /healthz on the listen address for up to 180 seconds. On failure it prints the last 40 log lines.
  7. Setting up console updates. Copies the nebula binary out of the image to /opt/nebula/bin/nebula and installs the systemd service nebula-updater, which lets an owner update the control plane from the console. This needs systemd and root or passwordless sudo. Without them the install is still complete, and the installer prints a warning with the reason.

Re-running the installer is safe. It keeps every setting, never replaces the master key or the database password, and changes nothing when there's nothing new to apply. When it does change .env, it first backs up the old file as .env.bak-TIMESTAMP.

Back up .env now

/opt/nebula/.env holds the master key. It seals every secret in the installation: service variables, registry passwords and other stored credentials. A database restored without the key is readable, but every sealed value in it is lost, and nobody can regenerate the key. Copy .env to a safe place before you do anything else.

3. Sign in

Open your public URL and select Continue with PROVIDER, where PROVIDER is the sign-in button label you chose, which defaults to the issuer's host. After your provider authenticates you, you land in the console as the owner of the Default organization.

The first person to complete a sign-in becomes the owner, whoever they are. Sign in yourself before you share the URL. Everyone after that needs an invitation. A person without one sees "has no invitation to an organization on this installation" and is signed out. See Members and teams to invite people.

You see the setup wizard at Connect your first cluster, because the Default organization has no cluster yet.

Verify

Check that the control plane answers on the listen address:

curl -s http://127.0.0.1:8080/healthz
{"status":"ok","components":{}}

If the listen address isn't the default, use the address you chose. Any other status is unhealthy and names the failing components. Signing in at your public URL, as in step 3, confirms the reverse proxy and the OIDC client as well.

Next steps

On this page