One installation per project, and no login to reach it

Two things a local install should not have asked for.

`fluksio serve` now signs you in. Logging in to your own machine was a
formality — the password was printed by the same process that would have
checked it, and the database it authenticates against sits in the directory
the token goes into — so `serve` mints the token itself and says where it put
it. `fluksio login` is left for an engine somewhere else.

And an installation is `.fluksio` beside the code, found the way `.git` is,
rather than one `~/.fluksio` for the machine. A repository with its own venv
was already getting its own engine; it now gets its own flows, run history and
token too, instead of three repositories sharing one database and fighting
over one port. `--global` asks for the shared one, `--data-dir` still names
any directory, and when both exist the banner says which you are looking at
and how to reach the other.

The directory ignores itself from within — a `.gitignore` of `*`, the way uv
writes one into `.venv` — because it holds a credential and a database, and
neither belongs in anybody's history. The token is written mode 600. A login
an older version wrote to ~/.config/fluksio is still read, so nothing that
worked stops working.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ue1tkFWB1bcGy3aWhCKpU
This commit is contained in:
2026-08-24 16:13:35 +02:00
co-authored by Claude Fable 5
parent e2b25c9d5a
commit 99f6530698
9 changed files with 405 additions and 57 deletions
+26 -8
View File
@@ -15,6 +15,18 @@ The command is two things at once: `serve`, `enroll` and `worker` *are* an
installation, while `login`, `sync`, `run` and `runs` talk to one that may be
anywhere.
## Where an installation lives
`.fluksio` beside your code, found the way `.git` is: from the working
directory, or any directory above it. Two repositories on one machine are
therefore two engines, with their own flows, runs and token. `fluksio serve`
makes one where there is none, and it ignores itself from within — a
`.gitignore` of `*`, so a database and a credential cannot be committed by
accident.
`--global` uses `~/.fluksio` instead, shared by every directory. `--data-dir`
(or `FLUKSIO_HOME`) names any directory outright and wins over both.
## `fluksio serve`
Runs the engine.
@@ -29,7 +41,7 @@ Docker.
| Option | Default | What it does |
|---|---|---|
| `--data-dir PATH` | `~/.fluksio` (or `$FLUKSIO_HOME`) | where this installation keeps everything |
| `--data-dir PATH` | `./.fluksio` (or `$FLUKSIO_HOME`) | where this installation keeps everything |
| `--host HOST` | `127.0.0.1` | what to bind |
| `--port PORT` | `8000` | what to listen on |
| `--log-level LEVEL` | `info` | uvicorn's log level |
@@ -112,13 +124,17 @@ address an engine over its API rather than being one.
### `fluksio login`
```sh
fluksio login --url http://127.0.0.1:8000
fluksio login --url https://api.example.com
```
Asks for an email and password, and keeps the token it gets in
`~/.config/fluksio/client.json` (`$XDG_CONFIG_HOME` is honoured). Everything
below reads it from there, or from `FLUKSIO_URL` and `FLUKSIO_TOKEN`, or from
its own `--url` and `--token`.
For an engine somewhere *else*. One you started yourself needs no login:
`fluksio serve` writes the token as it comes up and says where it put it.
The token goes in this project's `.fluksio/client.json`, or with `--global` in
`~/.fluksio/client.json`. Every command below reads it from there — nearest
first, walking up from the working directory — or from `FLUKSIO_URL` and
`FLUKSIO_TOKEN`, or from its own `--url` and `--token`. A token an older
version wrote to `~/.config/fluksio/client.json` is still read.
### `fluksio sync`
@@ -164,7 +180,9 @@ commit of the repository it came from, and its parameters.
## What lives in the data directory
```text
~/.fluksio/
.fluksio/ (or ~/.fluksio, with `--global`)
├── client.json the token `serve` wrote, mode 600
├── .gitignore `*` — a database and a credential, ignored from within
├── fluksio.db SQLite: users, runs, metrics, observability, agents
├── flows/ a git repository — one directory per flow
│ ├── house/
@@ -203,7 +221,7 @@ directory. The ones you are most likely to touch:
| Variable | Default | What it does |
|---|---|---|
| `DATA_DIR` | `~/.fluksio` via the CLI | everything below it derives from this |
| `DATA_DIR` | `./.fluksio` via the CLI; `~/.fluksio` with `--global` | everything below it derives from this |
| `DATABASE_URL` | SQLite in the data dir | any SQLAlchemy URL |
| `NODE_VENV` | `auto` | which interpreter node code runs on: `auto` adopts the venv Fluksio was installed into, `managed` builds one of its own, or name an interpreter |
| `REDIS_HOST` | unset | flow state in Redis instead of memory; survives a restart |
+58 -22
View File
@@ -6,36 +6,74 @@ answer to "what was the learning rate on the run that got 94%?", and the
This page adds Fluksio to what you already have. It takes about five minutes,
installs one Python package, and does not ask you to restructure anything.
## Install
```sh
cd my-research
pip install fluksio
fluksio serve
```
That is the whole installation. No Docker, no database server, no ports to
open. The first run prints something like:
open, and no login. The first run prints something like:
```text
Created the admin account admin@example.com
password: k3Qm-8vTpLdX
Shown once. Change it from the dashboard.
Fluksio 0.1.0 — data in /home/you/.fluksio
Fluksio 0.1.0 — data in /home/you/my-research/.fluksio
API http://127.0.0.1:8000/api/v1
Nodes /home/you/my-research/.venv/bin/python
your environment, adopted. Add packages with pip.
No portal. Pair this installation with:
fluksio enroll <code> --portal https://hub.example.com
Signed in as admin@example.com
token in /home/you/my-research/.fluksio/client.json
```
**Write that password down.** It is shown once and it is how you authenticate
from here on.
Read the last two lines: you are already signed in. Signing in to your own
machine is a formality — the password was printed by the same process that
would have checked it — so `serve` writes the token itself and every command
below just works. `fluksio login` is for an engine somewhere *else*.
Everything the installation owns lives in `~/.fluksio`: a SQLite database, a
git repository holding your flows, the artifact store, and a virtual
environment your node code runs in. Move it with `--data-dir`, which is worth
doing on a cluster where `$HOME` is a network filesystem — SQLite's
write-ahead log does not work on NFS, and `fluksio serve` warns you when it
notices.
**Write that password down** anyway. It is shown once, and it is what the
dashboard asks for.
### One installation per project
`.fluksio` sits beside your code, and is found the way `.git` is — from the
directory you are standing in, or any directory above it. So two repositories
on one machine are two engines: separate flows, separate run history,
separate token, and no chance of one experiment's graph turning up in the
other's.
```text
~/research/protein-fold/
.venv/ torch, fluksio
.fluksio/ its own database, flows, artifacts, token
myresearch/
~/research/climate-sim/
.venv/ jax, fluksio
.fluksio/ its own everything
climate/
```
It holds a database and a credential, so it ignores itself from within — a
`.gitignore` of `*`, the same thing `uv` writes into `.venv`. Nothing to add
to your project's own.
Give them different ports (`--port`) if you want two running at once.
!!! tip "One engine for the machine instead"
`fluksio serve --global` uses `~/.fluksio` — shared by every directory,
which is what you want for a personal server rather than a project. When
both exist, the banner says which one you are looking at and how to reach
the other. `--data-dir` still names any directory outright, which is worth
doing on a cluster where `$HOME` is a network filesystem: SQLite's
write-ahead log does not work on NFS, and `fluksio serve` warns you when
it notices.
!!! tip "Keep it running"
@@ -44,25 +82,23 @@ notices.
orchestrator spends before it does anything. Leave it in a `tmux` window,
or write a small `systemd --user` unit for it.
## Log in
```sh
fluksio login --url http://127.0.0.1:8000
```
It asks for the email and password printed above and keeps the token in
`~/.config/fluksio/client.json`, so nothing below needs credentials again.
## Talking to it over HTTP
Everything the commands do is the HTTP API, and some of this page shows it
directly. For that, grab the same token as a shell variable:
directly. For that, take the token `serve` already wrote:
```sh
export FLUKSIO=http://127.0.0.1:8000/api/v1
export TOKEN=$(jq -r .token ~/.config/fluksio/client.json)
export TOKEN=$(jq -r .token .fluksio/client.json)
```
While you are experimenting, the interactive schema at
<http://127.0.0.1:8000/docs> is the fastest way to see what is available.
For an engine on another machine, `fluksio login --url https://…` asks for a
password and stores the token the same way — in this project's `.fluksio`, or
with `--global` in `~/.fluksio`.
## Your packages are already there
If you installed Fluksio into the environment you work in — the venv that
@@ -492,7 +528,7 @@ every version of this thing I keep tweaking", note that **your flows are
already a git repository**:
```sh
cd ~/.fluksio/flows
cd .fluksio/flows
git log --oneline
```
+1 -1
View File
@@ -14,7 +14,7 @@ Anything already exported wins over the file.
| Variable | Default | Notes |
|---|---|---|
| `DATA_DIR` | `flow-data` (`~/.fluksio` via the CLI) | everything below derives from this |
| `DATA_DIR` | `flow-data` (`./.fluksio` via the CLI; `~/.fluksio` with `--global`) | everything below derives from this |
| `DATABASE_URL` | SQLite in `DATA_DIR` | any SQLAlchemy URL |
| `FLOWS_DIR` | `$DATA_DIR/flows` | the git repository holding flows |
| `SECRETS_FILE` | `$DATA_DIR/secrets.enc` | encrypted credentials, deliberately outside the repo |