Flux.

Installing Flux

From zero to your first printer in the app in about fifteen minutes. Applies to the closed beta.

1. What you need

Try it without a server: the app's sign-in screen offers "Demo ausprobieren" (try the demo). It runs entirely inside the app with sample data and no network. Nothing is sent to real devices.

Important first: the server speaks plain, unencrypted HTTP and is meant for your home network only. Do not forward the port in your router. For access on the go use a VPN (for example Tailscale or WireGuard) or a reverse proxy with HTTPS. In that case also set FLUX_LOCAL_PAIRING=false in a .env file.

2. Install the server

Flux is distributed as a ready-made Docker image: ghcr.io/schallerje/flux-server (tag beta). You do not need the source code and nothing is built on your machine.

  1. Create a folder and save the following file in it as docker-compose.yml:
    # Flux server - self-hosting from the public image (no source code, no build).
    #
    #   mkdir flux && cd flux
    #   (save this file as docker-compose.yml)
    #   mkdir -p data && sudo chown 1000:1000 data     # Linux: the container user has UID 1000
    #   docker compose up -d
    #   docker compose logs flux | grep "Setup token"  # one-time setup token for the first owner
    #
    # Update: docker compose pull && docker compose up -d
    # Beta: only linux/amd64 (x86_64). Raspberry Pi / ARM follows.
    # Requires Docker Compose v2.24 or newer. See SELF-HOSTING.md.
    services:
      flux:
        image: ghcr.io/schallerje/flux-server:beta
        container_name: flux-backend
        restart: unless-stopped
        ports:
          # host:container - the app inside the container listens on 3020.
          # Reverse proxy on the same machine in front? Bind to loopback only so the plain-HTTP
          # port is not reachable from the network: - "127.0.0.1:${FLUX_PORT:-3021}:3020"
          - "${FLUX_PORT:-3021}:3020"
        volumes:
          - ./data:/app/data
        # Optional settings from .env (APNs, Home Assistant, secrets, ...) are
        # passed through; the file may be absent. The explicit values below win.
        env_file:
          - path: .env
            required: false
        environment:
          PORT: "3020"
          FLUX_DATA_PATH: /app/data
          FLUX_SHADOW_MODE: "false"
          FLUX_ACTIVE_JOBS: "true"
          # true: any client whose connection comes from a private address (typical home-network addresses)
          # may request a one-time pairing code without signing in. Behind a reverse proxy every
          # visitor arrives from the proxy's private address and would look local, so set
          # FLUX_LOCAL_PAIRING=false in .env there (or when Flux is reachable from outside your LAN).
          FLUX_LOCAL_PAIRING: ${FLUX_LOCAL_PAIRING:-true}
        healthcheck:
          test:
            - CMD
            - node
            - -e
            - "fetch('http://127.0.0.1:3020/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"
          interval: 30s
          timeout: 5s
          start_period: 15s
          retries: 3
  2. Linux only: make the data folder writable for the container user (UID 1000):
    mkdir -p data
    sudo chown 1000:1000 data
  3. Behind a reverse proxy, or reachable from outside your LAN? Before the first start:
    echo 'FLUX_LOCAL_PAIRING=false' > .env
  4. Start it (no .env and no keys needed; they are generated on first start):
    docker compose up -d
    docker compose ps          # STATUS should become "healthy"
    curl http://localhost:3021/health
    The server listens on host port 3021 (change it with FLUX_PORT in .env).
  5. Get the setup token from the log:
    docker compose logs flux | grep "Setup token"
    It looks like 7K2QX-9M4VD-BH3TN and prevents someone else on the network from taking over your fresh server.
  6. Open http://<your-server-ip>:3021/ in a browser (on the server itself http://localhost:3021/ works too). Enter the setup token, accept the beta terms of use and press "Claim this server". Your browser is now the owner.
  7. The setup assistant starts. Every step can be skipped and restarted later under Settings › General:
    • Add a printer and use Test connection. The test only reads the status; nothing is sent. Passwords and access codes are write-only and never shown again.
    • Home Assistant (optional): address and access token, then one outlet per printer. Flux suggests one and only saves it after you press "Apply suggestion".
    • Notifications (optional), see section 4.
    • Pair the app: creates the QR code, see section 3.

Stop: docker compose down (data in ./data stays). Update: docker compose pull && docker compose up -d.

Backup: the data/ folder contains your keys (data/secrets.json). Treat backups like a password and never paste them into bug reports. If secrets.json is lost, all paired devices are signed out.

2a. Installing on Unraid

Alternative to Docker Compose: on Unraid there is a ready-made Docker template "Flux-Server". As above you need a 64-bit Intel/AMD machine (linux/amd64).

  1. Prepare the data folder (Unraid terminal). The container runs as UID 1000, while Unraid creates folders as nobody (99:100). Without this step the server cannot save anything:
    mkdir -p /mnt/user/appdata/flux-server
    chown -R 1000:1000 /mnt/user/appdata/flux-server
  2. Under Docker › Template Repositories add https://github.com/SchallerJe/flux-unraid-templates and save. (The repository is still to be published. Until then, ask for the template in the Discord beta channel.)
  3. Add Container and pick the template "Flux-Server". The defaults fit a home network (host port 3021). Behind a reverse proxy set Local pairing to false. Then Apply.
  4. Get the setup token: container icon › Logs, look for Setup token.
  5. Open container icon › WebUI, enter the token, accept the beta terms and press "Claim this server". Continue with the setup assistant (section 2 from step 7) and section 3.

Update: container icon › Force update. Back up the appdata/flux-server folder, it contains your keys.

3. Install and pair the app

  1. Install TestFlight and open the beta link: <TESTFLIGHT-LINK> (you receive it in the Discord beta channel).
  2. The first owner has to be set up in the web portal first (see section 2). Then you pair your iPhone.

Option A: QR code

  1. In the assistant under Pair the app, enter your server's address as your iPhone can reach it (not localhost) and press "Create code".
  2. In the app, scan the QR code by pointing the camera at the code in the browser (allow camera access).
  3. The app asks whether to pair with the server. Confirm with "Pair".

The code is valid only briefly and only once. You can create a new one at any time.

Option B: enter the code by hand

Enter the server address in the app and use the one-time code from the web portal ("Pair with code"). This is also the way to go if scanning does not work.

Further devices

After the first owner, no device is paired without approval:

  1. The new device taps "Request pairing" and shows a 4-digit verification code.
  2. On an already paired device (web portal › Devices › open pairing requests) the request appears with device name, address and the same code. Compare the codes, then press Allow or Deny.
  3. After approval the new device receives its session automatically. Unanswered requests expire after 5 minutes.

Alternatively a paired device can create a code for the new one directly (web portal › Devices › "Create a code for a new device").

Behind Docker NAT or a reverse proxy all devices look like one address. Use pairing with a code from a paired device in that case.

4. Push notifications

Apple push needs a key that does not belong on your server. That is why there is an optional Flux relay, operated by Jens Schaller and available by invitation only:

  1. Web portal › Settings › Notifications › "Push via Flux relay".
  2. Enter the invitation code: <EINLADUNGSCODE> (you receive it in the Discord beta channel). It is stored on your server and never shown again.
  3. Tick the consent box and press Activate.

What is transmitted: printer name, job name, event (for example "print finished"), your device's push token and a random identifier. For pairing requests additionally the device name, address and verification code; for print photos the address of your server. The recipient is Jens Schaller as operator, then Apple. Details: privacy notice of the push relay.

Without the relay (no invitation code needed) under Settings › Notifications:

Events: print finished, print failed, paused, pairing request. Use "Send test" to check each channel.

5. Feedback

6. Known limitations