# Running a hub

A hub lets several tablets and phones work as one shop. A waiter's phone opens a table that the
counter tablet charges, held orders show on every device, and the menu and staff are shared.
Every device keeps selling when the hub is down, and catches up when it is back.

One hub can serve several separate shops. Each shop's data stays in its own file, and devices
only ever see their own shop.

## Start a hub

Install it with Docker, the Linux installer or a hosting platform: see
[Self-hosting](https://docs.openkedai.com/self-hosting/). For example, on a Linux machine at the shop:

```sh
curl -fsSL https://raw.githubusercontent.com/OpenKedai/openkedai/main/deploy/install.sh | sudo sh
```

From a clone of the repository, with Node.js 22: `pnpm install`, `pnpm build`, then
`node apps/server/dist/main.js` (data in `./data`).

The hub listens on port 8080. Its log prints a **setup code**:

```text
To add a shop to this hub, open it in a browser and choose Set up a new shop, or on the shop's
POS app go to Settings → Hub → Move this shop to a hub. Setup code: K7QM-2XPA
```

The setup code is the hub owner's key for adding shops, so keep it to yourself.

## Set up a new shop in the browser

Open the hub's address (for example `http://192.168.1.20:8080`) in a browser and choose **Set up
a new shop**. The wizard asks for the setup code, the shop's details and the owner's email and
password, then shows a QR code to pair the first device. See [the back office](https://docs.openkedai.com/back-office/).

## Move a shop to the hub

On the shop's existing device (the one with its menu and sales):

1. Open **Settings → Hub**.
2. Enter the hub's address, for example `192.168.1.20` (port 8080 is assumed), and the setup
   code.
3. Tap **Move this shop to a hub**.

The device uploads its menu, staff and settings, then its sales, and keeps a copy of everything.
**Settings → Hub** then shows "Up to date" and "Live updates on".

## Add more devices

1. In the back office, open **Devices → Pair a device**, or on a device already on the hub, an
   owner or manager opens **Settings → Hub → Pair a device**. A QR code and a code such as
   `JY29-G2ZN` appear. The code works once, for 10 minutes.
2. On the new device, on the first screen, choose **Join an existing hub instead**. Scan the QR
   code, or type the hub's address and the code, and give the device a name. Hubs found on the
   network are listed under **Hubs on this network**; tap one to fill in its address.
3. Sign in with an existing staff PIN. The device gets its own code (T2, T3…) for receipt
   numbers.

A device that already has sales of its own can't join another shop's hub. Use a new device, or
one that has never sold.

## Remove a device

In the back office, open **Devices**, pick the device and choose **Remove**; or on another device,
an owner or manager opens **Settings → Hub → Devices**. The removed device stops syncing at once
and says so. Its sales stay, and it can be paired again with a new code from **Settings → Hub**
on that device.

## When the hub's address changes

Devices find their hub again on their own. When the hub stops answering, each device looks for
it on the shop's network (over mDNS) and follows it to its new address, usually within half a
minute of the hub coming back. **Settings → Hub** says "Looking for the hub on this network…"
meanwhile. Sales made in the meantime are sent once it's found.

A device only follows its own hub:
- each hub has an id, announced with it on the network;
- before sending its key, the device checks that the hub there really holds it.

Another hub on the same network, or something pretending to be the hub, is ignored (ADR 0022).

This needs the devices and the hub on the same network. mDNS doesn't cross routers or VLANs, and
some guest Wi-Fi blocks it. In those cases, or for a hub at an `https://` address, open
**Settings → Hub → Change hub address** on each device and enter the new address. Hubs found
nearby are listed there to tap. Before sending its key, the device checks that the hub there
already holds it (and has the same hub id, when the device knows it), then that the hub knows it
as this shop's device. It keeps its pairing. A fixed address in your router (a "DHCP reservation") still saves
devices the search.

## When the hub or the network is down

Devices sell, print and close shifts as usual. **Settings → Hub** shows what is waiting to be
sent, and the register shows a **Hub offline** button. When the hub is back, devices send what
they have and fetch what they missed. Nothing is lost and nothing is counted twice.

Menu and staff changes made on two devices while offline can overwrite each other: the first to
reach the hub wins. Sales never do.

## Settings and backups

Every setting is an environment variable with a safe default; see
[Configuration](https://docs.openkedai.com/self-hosting/configuration/). The hub takes a snapshot of every shop each day
and can copy it to S3-compatible storage; see [Backups](https://docs.openkedai.com/self-hosting/backups/).

## Security

- Devices hold a token the hub gave them when they paired. The hub stores only a hash of it.
- On a shop LAN the hub speaks plain HTTP, so anyone on the same network could watch the
  traffic. Keep the hub on the shop's own network. To reach a hub over the internet, put HTTPS
  in front of it and set `OPENKEDAI_PUBLIC_URL` to the HTTPS address; see
  [HTTPS and remote access](https://docs.openkedai.com/self-hosting/https/).
- Too many wrong setup or pairing codes from one address are refused for a while.
