Getting started: reach the app by address, without DNS
The guide asked for a hostname and served the interface on
`app.${DOMAIN}` with the API on `api.${DOMAIN}` — which is not what
someone with a box in a cupboard sets up, and could not be made to work
by typing an address into a browser. `compose.lan.yml` already solves it
for the dev stack; the same file layers onto the production one, so the
guide now opens with that and keeps the hostname as the other option.
The reference gained the setting behind it. `VITE_API_URL` is a build
argument of the frontend image rather than something the stack reads,
which is worth saying once: empty means the interface addresses the API
relative to whatever origin served it, so one image answers on an
address, a hostname and an ssh tunnel alike, and no CORS list has to be
kept in step.
Verified against the production compose layered with `compose.lan.yml`:
the page, `/api` on the same port, a cross-origin-free login, the flow
websocket upgrading through nginx, and `/docs` still refused there.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -27,28 +27,28 @@ all part of the same process, editing the same graph.
|
|||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
- Docker and Compose v2 on the host
|
- Docker and Compose v2 on the host
|
||||||
- A hostname you can point at it. `fluksio.local`, a subdomain, or just
|
- The address you will type into a browser. On a home network that is the
|
||||||
`localhost` if you only ever reach it from that machine
|
server's own address — `192.168.1.50` — and nothing else is needed. A
|
||||||
|
hostname is optional, and covered below
|
||||||
- Optionally: an MQTT broker and an InfluxDB you already run. If not, the stack
|
- Optionally: an MQTT broker and an InfluxDB you already run. If not, the stack
|
||||||
can start both for you
|
can start both for you
|
||||||
|
|
||||||
## Bring up the stack
|
## Configure it
|
||||||
|
|
||||||
Clone the app repository and start it:
|
Clone the app repository and write its one configuration file:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
git clone https://git.stroblme.de/Fluksio/app.git ~/fluksio
|
git clone https://git.stroblme.de/Fluksio/app.git ~/fluksio
|
||||||
cd ~/fluksio
|
cd ~/fluksio
|
||||||
cp .env.example .env
|
cp .env.example .env
|
||||||
$EDITOR .env # DOMAIN, FIRST_SUPERUSER, ENVIRONMENT=production
|
$EDITOR .env # FIRST_SUPERUSER, ENVIRONMENT=production
|
||||||
make up
|
|
||||||
```
|
```
|
||||||
|
|
||||||
`.env` is the whole configuration. The four settings that matter on day one:
|
`.env` is the whole configuration. The four settings that matter on day one:
|
||||||
|
|
||||||
| Setting | What it does |
|
| Setting | What it does |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `DOMAIN` | the hostname everything is served under; the SPA lands on `app.${DOMAIN}` and the API on `api.${DOMAIN}` |
|
| `DOMAIN` | the hostname everything is served under, if you use one. Left alone it only names the issuer that agents authenticate against |
|
||||||
| `FIRST_SUPERUSER` | the account you sign in with |
|
| `FIRST_SUPERUSER` | the account you sign in with |
|
||||||
| `FIRST_SUPERUSER_PASSWORD` | leave it as `changethis` and one is generated for you |
|
| `FIRST_SUPERUSER_PASSWORD` | leave it as `changethis` and one is generated for you |
|
||||||
| `ENVIRONMENT` | `production` closes the interactive API schema; `local` leaves it open |
|
| `ENVIRONMENT` | `production` closes the interactive API schema; `local` leaves it open |
|
||||||
@@ -57,14 +57,6 @@ Everything the installation owns — the database, your flows, secrets,
|
|||||||
artifacts, the packages your node code imports — is on one Docker volume.
|
artifacts, the packages your node code imports — is on one Docker volume.
|
||||||
Backing that volume up is backing up the installation.
|
Backing that volume up is backing up the installation.
|
||||||
|
|
||||||
!!! tip "Reverse proxy"
|
|
||||||
|
|
||||||
The stack emits Traefik labels and ships a Traefik you can bring up
|
|
||||||
alongside it (`docker/compose.traefik.yml`). If you already run Nginx
|
|
||||||
Proxy Manager or Caddy, attach it to the `proxy` network instead and
|
|
||||||
forward `app.${DOMAIN}` → `fluksio-app:80` and `api.${DOMAIN}` →
|
|
||||||
`fluksio-api:8000`.
|
|
||||||
|
|
||||||
??? note "Even smaller: no Docker at all"
|
??? note "Even smaller: no Docker at all"
|
||||||
|
|
||||||
`pip install fluksio && fluksio serve` gives you the same engine with no
|
`pip install fluksio && fluksio serve` gives you the same engine with no
|
||||||
@@ -74,8 +66,61 @@ Backing that volume up is backing up the installation.
|
|||||||
serves the dashboard for you. Good for a Raspberry Pi that only runs flows;
|
serves the dashboard for you. Good for a Raspberry Pi that only runs flows;
|
||||||
less good as your main instance.
|
less good as your main instance.
|
||||||
|
|
||||||
Open `http://app.${DOMAIN}` and sign in. You should be looking at Home: an
|
## Reach it from another machine
|
||||||
empty brain graph, a health summary, and a flow list with nothing in it.
|
|
||||||
|
Start it one of two ways, depending on whether you have a hostname to point at
|
||||||
|
it. Neither is more supported than the other.
|
||||||
|
|
||||||
|
### On your own network, by address
|
||||||
|
|
||||||
|
The usual case: the box is in a cupboard at `192.168.1.50` and you open it from
|
||||||
|
a laptop. Layer `docker/compose.lan.yml` on, which publishes the interface on a
|
||||||
|
port and serves the API from that same origin:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
APP_PORT=8080 docker compose -p fluksio-app --env-file .env \
|
||||||
|
-f docker/compose.yml -f docker/compose.lan.yml up -d --build
|
||||||
|
```
|
||||||
|
|
||||||
|
Open `http://192.168.1.50:8080`. That one address is the whole application —
|
||||||
|
the interface, the API under `/api`, and the websocket that puts live values on
|
||||||
|
the canvas.
|
||||||
|
|
||||||
|
Nothing in that URL is configured anywhere. The interface is built to address
|
||||||
|
the API relative to whatever origin served the page, so the same containers
|
||||||
|
answer to the machine's address, to a hostname you add later, and through an
|
||||||
|
ssh tunnel, without being rebuilt. It is also why no CORS list needs
|
||||||
|
maintaining: the browser is talking to one origin.
|
||||||
|
|
||||||
|
!!! danger "This is your network, not the internet"
|
||||||
|
|
||||||
|
A published port is plain HTTP with no certificate. Between your own
|
||||||
|
machines that is fine, and it is not something to forward from a router. To
|
||||||
|
reach the house from outside, put a reverse proxy with TLS in front of it —
|
||||||
|
or [pair it with a portal](../interface/portal.md), which needs no inbound
|
||||||
|
route at all.
|
||||||
|
|
||||||
|
### With a hostname, behind a reverse proxy
|
||||||
|
|
||||||
|
If you have DNS — or want certificates — set `DOMAIN` and run `make up`
|
||||||
|
instead. The interface is then served on `app.${DOMAIN}` and the API on
|
||||||
|
`api.${DOMAIN}`, and nothing is published on a host port.
|
||||||
|
|
||||||
|
The stack emits Traefik labels and ships a Traefik you can bring up alongside
|
||||||
|
it (`docker/compose.traefik.yml`). With Nginx Proxy Manager or Caddy instead,
|
||||||
|
attach it to the `proxy` network and forward `app.${DOMAIN}` →
|
||||||
|
`fluksio-app:80` and `api.${DOMAIN}` → `fluksio-api:8000`.
|
||||||
|
|
||||||
|
!!! tip "Developing on the same machine"
|
||||||
|
|
||||||
|
`make dev-lan` is the same idea for the integrated dev stack — the app on
|
||||||
|
`http://<host-ip>:8080`, `APP_PORT` to move it. `make dev` rebuilds without
|
||||||
|
the published port, so re-run `make dev-lan` after one.
|
||||||
|
|
||||||
|
## Sign in
|
||||||
|
|
||||||
|
Open whichever address you chose. You should be looking at Home: an empty brain
|
||||||
|
graph, a health summary, and a flow list with nothing in it.
|
||||||
|
|
||||||
## Your first flow
|
## Your first flow
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,26 @@ on.
|
|||||||
| `FRONTEND_HOST` | `http://localhost:5173` | used in mails, OAuth metadata and panel pairing links |
|
| `FRONTEND_HOST` | `http://localhost:5173` | used in mails, OAuth metadata and panel pairing links |
|
||||||
| `BACKEND_CORS_ORIGINS` | `[]` | comma-separated; `FRONTEND_HOST` is always allowed |
|
| `BACKEND_CORS_ORIGINS` | `[]` | comma-separated; `FRONTEND_HOST` is always allowed |
|
||||||
|
|
||||||
|
## Where the interface looks for the API
|
||||||
|
|
||||||
|
The dashboard is a static bundle, so this one is a **build** argument of the
|
||||||
|
`frontend` image rather than a setting the running stack reads.
|
||||||
|
|
||||||
|
| Argument | Used by | Effect |
|
||||||
|
|---|---|---|
|
||||||
|
| `VITE_API_URL` | `frontend` at build time | the address the interface calls |
|
||||||
|
|
||||||
|
Empty is the useful value: the interface then addresses the API relative to
|
||||||
|
whichever origin served the page, so one image answers on a hostname, on a
|
||||||
|
`http://<host-ip>:<port>`, and through an ssh tunnel alike — and no origin has
|
||||||
|
to be added to `BACKEND_CORS_ORIGINS`, because there is only one.
|
||||||
|
`docker/compose.lan.yml` builds it that way and puts an `/api` proxy in front
|
||||||
|
of the backend to complete it; see
|
||||||
|
[getting started](../getting-started/facility-automation.md#on-your-own-network-by-address).
|
||||||
|
|
||||||
|
Set it to an absolute URL only when the API genuinely lives somewhere else, and
|
||||||
|
remember it is fixed at build time: changing it means rebuilding that image.
|
||||||
|
|
||||||
!!! danger "Rotating `SECRET_KEY`"
|
!!! danger "Rotating `SECRET_KEY`"
|
||||||
|
|
||||||
The secrets store is encrypted with a key derived from it. Change it and
|
The secrets store is encrypted with a key derived from it. Change it and
|
||||||
|
|||||||
Reference in New Issue
Block a user