# Self-Hosting Quickstart

From nothing to a running server.

> **Note**
>
> Trying ShellHub rather than committing to it? Cloud takes a few clicks and we run the server. The agents and the daily workflow are identical, so nothing you learn there is wasted if you self-host afterwards.
>
> [Try it on Cloud →](https://cloud.shellhub.io/)

## Requirements

Docker and Docker Compose, and a host with a stable address that your devices can reach. The composition is four services plus PostgreSQL.

## 1. Clone

```bash
$ git clone -b v0.30.0 https://github.com/shellhub-io/shellhub.git
$ cd shellhub
```

Every release is on the [releases page](https://github.com/shellhub-io/shellhub/releases) if you need a different one.

## 2. Generate keys

```bash
$ make keygen
```

This creates three secrets — the API key pair and the SSH host key — which are mounted as Docker secrets.

**Back these up.** Regenerating the SSH host key changes the server’s host key, and every SSH client that has connected before will refuse to connect until its known-hosts entry is cleared.

## 3. Configure

Never edit `.env` — it carries the defaults and an upgrade will overwrite it. Put your settings in `.env.override`, which is read last and wins:

```bash
$ touch .env.override
```

```bash
# .env.override
SHELLHUB_DOMAIN=shellhub.example.com
SHELLHUB_AUTO_SSL=true
SHELLHUB_POSTGRES_PASSWORD=<something-that-is-not-admin>
```

At minimum, set the domain and change the database password. Every variable is in [Environment Variables](https://docs.shellhub.io/selfhosted/environment-variables).

## 4. Start

```bash
$ make start
```

This runs `keygen` if you have not, then brings the stack up detached.

> **Careful**
>
> Always use `./bin/docker-compose`, never bare `docker compose`. The wrapper assembles the compose file list and the environment file chain. Running plain `docker compose` skips the PostgreSQL overlay entirely, and the server comes up with no database.

## 5. Create the first account

The stack comes up with no users. The first one is created in the browser:

![The ShellHub initial setup page](https://docs.shellhub.io/img/selfhosted/setup.png)

1. Open the server’s address. Until the first account exists every path redirects to `/setup`.
2. Enter a name, a username and an email. This user is the instance’s superadmin.
3. Keep the suggested namespace or click **Edit**. Lowercase, no dots — it appears in every SSHID.
4. Enter a password of at least 5 characters, and click **Complete setup**.

You are signed in. On Community that namespace is **the** namespace — Community is single-namespace, and the server refuses to create another. See [Editions](https://docs.shellhub.io/about/editions).

> **On Community the first step is a short survey**
>
> Setup opens with a short onboarding survey loaded from an external form service. When the browser cannot reach it, setup skips the survey and goes straight to the account. Leave `SHELLHUB_ONBOARDING_URL=` empty in `.env.override` to turn it off.

> **Note**
>
> `/setup` only exists while no users do. Once the first account is created it is gone, and `/info` reports `"setup": true`.

## 6. Connect a device

Nothing from here on is specific to self-hosting. The [Quickstart](https://docs.shellhub.io/get-started) installs the agent, accepts the device, opens a terminal on it and gives your team access to it.

Skip its account section — the setup screen just did that — and use your own address wherever it says `cloud.shellhub.io`.

## Managing the stack

```bash
$ make start           # bring it up
$ make stop            # stop it
$ make restart         # stop then start
$ ./bin/docker-compose ps
$ ./bin/docker-compose logs -f
```

## What you just deployed

- A **server**, carrying the gateway that terminates TLS, the API and the SSH endpoint in one process
- The **web console**
- **PostgreSQL**, holding everything that matters
- A cache and task queue

The server publishes the HTTP, HTTPS and SSH ports, but only HTTP and HTTPS go through the gateway. That matters if you put a load balancer in front. See [Ports and Connectivity](https://docs.shellhub.io/about/ports-and-connectivity).

## Before you depend on it

1. Decide who owns the server, by name.
2. Decide where the database backup goes, and restore it once to prove it works. See [Backup](https://docs.shellhub.io/selfhosted/backup).
3. Decide whether an outage is acceptable, or whether you need more than one host.
4. Read [Ports and Connectivity](https://docs.shellhub.io/about/ports-and-connectivity), so the network conversation happens once rather than during an incident.

## Where to go next

- [Running on Your Own Infrastructure](https://docs.shellhub.io/about/self-hosted-vs-cloud) — What you now own.
- [Environment Variables](https://docs.shellhub.io/selfhosted/environment-variables) — Everything configurable.
- [Backup](https://docs.shellhub.io/selfhosted/backup) — Do this before you need it.
