Metadata-Version: 2.4
Name: flux-config-tui
Version: 0.3.3
Summary: The Flux node console, and flux-node: CLI, local gateway and library for nodes over SSH
Author: David White
Author-email: David White <david@runonflux.io>
License-Expression: GPL-3.0-or-later
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: System Administrators
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: System :: Systems Administration
Classifier: Topic :: System :: Monitoring
Requires-Dist: flux-config-shared[identity]>=0.33.0,<1.0
Requires-Dist: flux-networking-shared>=0.14.0,<1
Requires-Dist: textual>=8.1.1,<9
Requires-Dist: textual-fspicker>=0.6.0
Requires-Dist: qrcode>=8.2,<9
Requires-Dist: pyperclip>=1.9.0,<2
Requires-Dist: setproctitle>=1.3.7,<1.4
Requires-Dist: yarl>=1.18.3
Requires-Dist: asyncssh>=2.23.0,<3
Requires-Dist: websockets>=17.3,<18
Requires-Dist: pyyaml>=6.0
Requires-Dist: pyte>=0.8.2,<0.9
Requires-Dist: typer>=0.27.3,<0.28
Requires-Dist: aiohttp>=3.14.5,<4
Requires-Dist: flux-config-shared[x11] ; extra == 'node'
Requires-Python: >=3.13, <4
Provides-Extra: node
Description-Content-Type: text/markdown

# flux-config-tui

The Flux node's console, and `flux-node`: the same program as a command line, a local HTTP
gateway and a Python library for working on ArcaneOS nodes over SSH.

```sh
uv tool install flux-config-tui     # or: pip install flux-config-tui
```

## The console

`flux-config-tui` (or `flux-node` with no command) opens the console: system monitoring,
services, logs, network settings, installation and configuration. On the node it talks to
configd's operate socket; from your machine it logs in over SSH as `fluxtui` with an operate
key the node was installed with, and keeps the nodes you add in `~/.config/flux-config/`.

## flux-node

Each command works on `--host <address>` (with `--key`, `--port`), on a saved node
(`--node <name>`), or on your default saved node, and prints configd's answer as JSON. A saved
node is `operate` or `status`; `--status` logs in with a status key, which can read but not act.

```sh
flux-node status                      # install state, fluxd's node status, fluxbench's status
flux-node benchmarks
flux-node logs fluxd --lines 200
flux-node service restart fluxd
flux-node reboot                      # asks first; the node drains its apps
flux-node call network.get_change     # any method the key's tier answers
flux-node events benchmarks system    # live events, one JSON object a line
flux-node trust <node>                # after a reinstall: trust the node's new host key
```

The first connection to a node trusts its SSH host key and prints its fingerprint; compare it
with the one on the node's own console. A different key later is refused until you `trust` it.

### Network changes

```sh
flux-node network show
flux-node network static ens18 192.168.1.50/24 --gateway 192.168.1.1 --dns 1.1.1.1
flux-node network dhcp ens18
flux-node network vlan-add ens18 148
```

A change asks the node to roll itself back unless `flux-node` reaches it again with a new login
within two minutes, at the new address when the change moves the one you use. Once reached, the
change is kept and saved, and a saved node follows its new address. Ctrl-C reverts at once.

### The gateway

```sh
flux-node serve                       # http://127.0.0.1:8640
flux-node token                       # the bearer token every request needs
```

`GET /nodes`, `GET /nodes/{name}`, `GET /nodes/{name}/benchmarks`,
`POST /nodes/{name}/call` (`{"method": …, "params": {…}}`) and
`GET /nodes/{name}/events?topics=…` (server-sent events) for your saved nodes, one SSH
connection each. It listens on loopback only and refuses a request without the token, with a
Host other than localhost, from a browser (any `Origin`), or a POST that is not JSON.
`flux-node token --new` replaces the token at once.

### The library

```python
from flux_config_tui.node import Node

async with Node("192.168.1.50", key="~/.ssh/operator_ed25519") as node:
    print(await node.state())
    async for event in node.events(["benchmarks"]):
        print(event.type, event.data)
```

## On the node

The node's image installs `flux-config-tui[node]`, whose extra brings what only the node's own
screen needs (`flux-best-resolution`).
