Docs / docs (push) Successful in 27s
Playwright Tests / test-playwright (1, 2) (push) Failing after 17s
Playwright Tests / test-playwright (2, 2) (push) Failing after 12s
pre-commit / pre-commit (push) Failing after 1m59s
Test Backend / test-backend (push) Failing after 2m30s
Compose Smoke Test / test-compose (push) Failing after 13s
Playwright Tests / merge-reports (push) Failing after 2m19s
serve: refuse a second engine for one data directory whatever port it was asked for, using the pidfile and a token this directory signed. The check runs before the database is touched and before the credential is written, which is what left every later CLI call pointing at a dead port. The terminal dashboard is three tabs (Overview, Runs, Logs) with the toolbar following the focused pane, the engine's output goes to serve.log rather than down a pipe, and closing the screen stops both reader threads so the prompt comes back. It adopts a running engine on every start, so stop/start and restart work on one it did not start, and a stop waits for the process to be gone before the next start. Enrolment reports itself in the modal. enroll: a new claim code replaces the pairing instead of being refused. The code is redeemed before anything is written, mappings to a portal being left are cleared, and a running engine redials when the stored enrolment changes. runs: an engine re-queues the runs left `queued` by the one before it, and `fluksio retry <id>` / `retry --group <sweep>` submits an interrupted run again with the same inputs and group, recorded through Run.parent_id. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U9BoNGq6V9MdRWAte7JBuC
119 lines
5.0 KiB
Markdown
119 lines
5.0 KiB
Markdown
# Accounts and the portal
|
|
|
|
Fluksio is self-hosted by default. An instance runs offline, keeps its data
|
|
on its own disk, and never contacts anything unless you tell it to.
|
|
|
|
The **portal** is optional, and it exists to solve two specific problems:
|
|
|
|
1. **Your machine has no inbound route.** A homelab behind CGNAT, a cluster
|
|
node with no open ports, a laptop. Opening one is work, and often not
|
|
allowed.
|
|
2. **You want a browser on it anyway.** A `pip install fluksio` instance
|
|
has no web server for the dashboard at all.
|
|
|
|
An enrolled instance dials *out* to the portal and holds one websocket
|
|
open. The portal serves the dashboard from its own side, and only the API calls
|
|
travel down the tunnel, so the interface loads at portal speed and your
|
|
machine stays unreachable from the internet.
|
|
|
|
## Enrolling
|
|
|
|
Two halves: whoever performs the second step decides what the instance's owner
|
|
gets.
|
|
|
|
**On the portal** (`hub.${DOMAIN}`, or [fluksio.com](https://fluksio.com) for
|
|
the hosted one): **Instances → Add instance**, give it a name, and copy
|
|
the code.
|
|
|
|
**On the instance**, either from the dashboard:
|
|
|
|
> **Settings → Remote access**, enter the portal URL and the code, press
|
|
> **Connect**.
|
|
|
|
or from the command line, which is the path for an instance with no web
|
|
interface of its own:
|
|
|
|
```sh
|
|
fluksio enroll ABCD-1234 --portal https://hub.fluksio.com
|
|
```
|
|
|
|
The code is single-use and expires in fifteen minutes. A fresh code on an
|
|
instance that is already paired replaces the pairing, so moving an instance to
|
|
another portal is one command rather than a disconnect and a reconnect.
|
|
|
|
A portal session then arrives as *that local account*, which the settings screen
|
|
states plainly. Use `--as someone@example.com` to enrol as a specific local
|
|
account when the instance has several superusers.
|
|
|
|
Once enrolled, the instance appears under **Instances** with its
|
|
status, when it was last seen and its version. **Open** takes you to its
|
|
dashboard at `${DOMAIN}/i/{instance-id}`.
|
|
|
|
## What the portal can and cannot do
|
|
|
|
The portal holds one credential for your instance and proxies requests down
|
|
the tunnel. What those requests may do is decided **on the instance**, by
|
|
the same checks a local session passes.
|
|
|
|
The trust anchor is a signing keypair on the portal. Every instance pins
|
|
its public half at enrolment and rejects anything else, which is what stops a
|
|
hijacked DNS entry or a mis-issued certificate from impersonating the portal.
|
|
|
|
## Letting someone else in
|
|
|
|
Anyone else on the portal reaches your instance only if a superuser there
|
|
admits them, and they arrive as a local user of their own rather than as you.
|
|
|
|
1. **They**: **Instances → Join an instance**, and copy the code. It is
|
|
bound to their portal account and expires in fifteen minutes.
|
|
2. **You**, on the instance: **Settings → Remote access → Add remote
|
|
user**, and enter the code.
|
|
3. They now see the instance under **Instances**, marked *Shared by*,
|
|
with **Open** and nothing else. Renaming, re-keying and removing stay with
|
|
you.
|
|
|
|
The instance redeems that code against the portal using its own credential.
|
|
A portal session cannot do this, which is what stops somebody you let in from
|
|
letting others in.
|
|
|
|
On the instance they appear under **Admin → Users**, badged *Portal*, never
|
|
a superuser and with no password.
|
|
|
|
## Cutting it off
|
|
|
|
| From | Action | Effect |
|
|
|---|---|---|
|
|
| The portal | **New code** | rotates the credential and drops the current link |
|
|
| The portal | **Remove** | deletes the registration and cuts the connection |
|
|
| The instance | **Disconnect** | unilateral and immediate — the portal's tokens stop verifying here whatever the portal still has on file |
|
|
| The instance | delete a user under **Admin → Users** | that one person, immediately, independent of the portal |
|
|
|
|
**New code** also cuts every credential the portal minted for this instance,
|
|
including [wall panels paired through it](dashboards.md#a-screen-somewhere-you-cannot-reach).
|
|
|
|
The instance's own **Disconnect** is the one to reach for if you are ever
|
|
unsure: it does not need the portal's cooperation.
|
|
|
|
## Running your own portal
|
|
|
|
The portal is the `index` stack's `hub` service: accounts, the registry of
|
|
connected instances, and the websocket each one dials in on. Two things
|
|
about it are load-bearing:
|
|
|
|
- **It runs a single process.** It keeps its attached instances in the
|
|
memory of the process holding their sockets, so a second worker would answer
|
|
for links it does not hold. Scaling out needs a routing layer first.
|
|
- **Back up the signing keypair with the database.** Replacing it forces every
|
|
instance to be enrolled again.
|
|
|
|
Websocket upgrades must be enabled on the `hub` hostname in whatever proxy
|
|
fronts it. Without them every instance sits in a reconnect loop and the
|
|
portal shows them all offline.
|
|
|
|
## See also
|
|
|
|
- [The `fluksio` command](../code/cli.md) — `fluksio enroll`, and what it writes
|
|
- [Dashboards and panels](dashboards.md) — pairing a wall screen through the portal
|
|
- [Getting started: data science](../getting-started/data-science.md) — the
|
|
shortest path from a pip install to a browser
|