261 lines
15 KiB
Bash
261 lines
15 KiB
Bash
# Jarvis — optional configuration.
|
|
#
|
|
# THERE IS NOTHING YOU HAVE TO FILL IN. You do not need this file at all:
|
|
#
|
|
# docker compose up -d
|
|
#
|
|
# then open the address in a browser and the install screen asks the questions. It creates the first
|
|
# administrator, checks the deployment, and stores the address, the model and everything else as
|
|
# settings you can change later from a screen.
|
|
#
|
|
# THIS FILE USED TO BE MANDATORY, and that is the change. It asked for six values before the
|
|
# container would start, four of them secrets to be generated with `openssl` — and it failed in the
|
|
# worst available way, because an invalid one made the API exit 1 and the restart policy turned a
|
|
# typo into a crash loop, with the reason on line 40 of a log nobody had a reason to open.
|
|
#
|
|
# What is left below is for deployments that prefer to state things in writing: pinning image
|
|
# versions, running the agent overlay, choosing a host port. Every value here is optional, and the
|
|
# ones that overlap with the install screen SEED it — they are read once, when nothing is stored
|
|
# yet, and never again. Change them afterwards and nothing happens; change the setting instead.
|
|
#
|
|
# cp .env.example .env # only if you want any of this
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Where your instance lives
|
|
# ---------------------------------------------------------------------------
|
|
|
|
# Host port the web container publishes. Put your TLS terminator in front of it.
|
|
#
|
|
# The one value on this page that genuinely cannot move to a screen: it is a Docker fact, decided
|
|
# before anything in the application is running.
|
|
JARVIS_PORT=8080
|
|
|
|
# The address a browser reaches Jarvis on. ASKED BY THE INSTALL SCREEN, which pre-fills it with the
|
|
# address you are already reading it at — so setting it here is only useful if you want it stated in
|
|
# writing, or if you are upgrading a stack that already had it.
|
|
#
|
|
# It decides CORS, what enrolled machines dial, the base of every invitation link, and the WebAuthn
|
|
# relying party. Changing it later orphans every passkey already enrolled, so the screen warns you.
|
|
#WEB_ORIGIN=https://jarvis.example.com
|
|
|
|
# PUBLIC_URL IS GONE. It was a second address for the same thing, kept separate for a split-hostname
|
|
# deployment nobody ran; the install screen asks once and every consumer reads that one value. An
|
|
# instance that still sets it is not broken — it is simply ignored.
|
|
|
|
# How many proxies rewrite X-Forwarded-For before a request reaches the API.
|
|
#
|
|
# ASKED BY THE INSTALL SCREEN, which is the only place this can honestly be answered: it shows you
|
|
# the header chain your own request actually carried and the address the API resolved from it, and
|
|
# you confirm what you see. Nobody knows this number in advance.
|
|
#
|
|
# One is the web container's own nginx, which is always there; two if your own reverse proxy fronts
|
|
# it, which is the usual case. Raising it past the real number is the dangerous direction, because
|
|
# the API then trusts that many hops of a header the client can forge — and a caller can choose the
|
|
# address that lands in your audit log and in the session list.
|
|
#TRUST_PROXY_HOPS=2
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Secrets — there is nothing to fill in here any more
|
|
# ---------------------------------------------------------------------------
|
|
#
|
|
# This section used to hold four values and four `openssl rand` invocations. They are generated for
|
|
# you now, on your first `docker compose up`, by the `init` service — into the `jarvis_secrets` volume,
|
|
# where the database password, the two session-signing secrets and the vault master key live.
|
|
#
|
|
# WHY THEY LEFT THIS FILE. A vault key is not a preference. Asking for one put the single most
|
|
# consequential value in the deployment — everything in the vault is encrypted under it — in front of
|
|
# whoever was least equipped to look after it, at the moment they were least interested in it, in a
|
|
# file they were trying to get through. Nobody ever chose a better key than `openssl rand` would have.
|
|
#
|
|
# WHAT YOU STILL HAVE TO DO, AND IT IS THE IMPORTANT ONE:
|
|
#
|
|
# BACK UP THE `jarvis_secrets` VOLUME, SEPARATELY FROM THE DATABASE.
|
|
#
|
|
# The vault key is in there and NOWHERE ELSE. A database backup does not save you — the backup holds
|
|
# the ciphertext. An instance whose key is gone keeps LOOKING configured, with every row in place,
|
|
# and fails on every reveal. It is a separate volume from `postgres_data` precisely so that the two
|
|
# can be, and must be, backed up to different places: a dump that travelled with the key that opens
|
|
# it is a dump that opens itself.
|
|
#
|
|
# The setup screen shows you the key once, on your first visit, and will not let you finish until you
|
|
# have put it somewhere. That is the moment to do this.
|
|
#
|
|
# UPGRADING FROM A .env THAT ALREADY HAS THESE? Leave them exactly where they are. The generator
|
|
# ADOPTS an existing value rather than replacing it, and never overwrites a secret it has already
|
|
# written — so your instance keeps its own keys and nothing about your vault changes. You can delete
|
|
# them from this file once the stack has come up once, or leave them; they are read only when the
|
|
# corresponding file does not exist yet.
|
|
#
|
|
# Pointing at secrets of your own instead? Every one of them also accepts a `_FILE` variable
|
|
# (VAULT_MASTER_KEY_FILE, JWT_ACCESS_SECRET_FILE, …), which is the convention the postgres image and
|
|
# most others already use — so a `docker secret` can be mounted at those paths with nothing else
|
|
# changing.
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# The model — asked by the install screen, with a test button
|
|
# ---------------------------------------------------------------------------
|
|
#
|
|
# All four moved. The install screen asks for the endpoint and the key, lists the models the endpoint
|
|
# actually serves, and ASKS THE MODEL FOR A TOKEN before it saves anything — so a key that is
|
|
# well-formed and wrong, an account out of credit or a model id the provider does not serve is a
|
|
# sentence on screen instead of a fault in somebody's first conversation.
|
|
#
|
|
# The key is stored encrypted under this instance's vault key, exactly like the outbound mail secret,
|
|
# and is never shown again. Change any of it later under Settings -> Platform -> Model.
|
|
#
|
|
# Setting them here still works and seeds an instance that has nothing stored — for a deployment
|
|
# that would rather state its model in a file. They are read once and never again.
|
|
|
|
#OPENAI_BASE_URL=https://api.openai.com/v1
|
|
#OPENAI_API_KEY=
|
|
#OPENAI_MODEL=gpt-4o
|
|
# minimal | low | medium | high. Higher costs latency and tokens and is worth it for real work.
|
|
#OPENAI_THINKING_LEVEL=medium
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Unattended installation (for fleets and for CI)
|
|
# ---------------------------------------------------------------------------
|
|
#
|
|
# Everything above is optional because the install screen asks for it. This is the other direction:
|
|
# somebody rolling out fifty instances from a template has answered those questions once already,
|
|
# and making them answer each one in a browser is exactly what this product stopped doing to people.
|
|
#
|
|
# Set this and the instance installs itself at boot from whatever the variables above provide, marks
|
|
# itself installed, and never shows the wizard.
|
|
#
|
|
#JARVIS_UNATTENDED=on
|
|
#
|
|
# The first administrator. REQUIRED when JARVIS_UNATTENDED is on and the database is empty; the
|
|
# password must be at least 12 characters.
|
|
#
|
|
# If they are missing or too short the instance says so loudly in its logs and leaves setup
|
|
# OUTSTANDING rather than completing — an instance marked installed with no account is one nobody
|
|
# can ever get into, and the claim window is gated on setup being unfinished, so there would be no
|
|
# way back. Falling through to the ordinary install screen is strictly better than that.
|
|
#
|
|
#JARVIS_ADMIN_EMAIL=
|
|
#JARVIS_ADMIN_PASSWORD=
|
|
#JARVIS_ADMIN_NAME=Administrator
|
|
#
|
|
# Worth setting alongside them, since nobody will be there to be asked: WEB_ORIGIN, OPENAI_API_KEY
|
|
# and OPENAI_MODEL above, and JARVIS_LICENSE_KEY below. Each is optional even here — an unattended
|
|
# instance with no model comes up and reports that it has none, rather than refusing to start.
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Channels and pinning (optional, recommended in production)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
# Every image tracks the `stable` channel unless you set these, so `docker compose pull && up -d`
|
|
# upgrades you to whatever has most recently been promoted. `stable` moves only after a build has
|
|
# run on the publisher's own instance; `dev` moves on every build and nothing has tried it yet.
|
|
# `latest` is a second name for `stable`, kept so nothing that already used it has to change.
|
|
#
|
|
# Which channel you are on is yours to state, because nothing in the image knows it — a channel is
|
|
# decided after a build and moves afterwards. Set it and the app shows it beside the version
|
|
# numbers; leave it empty if you pin below, because then you follow no channel.
|
|
#JARVIS_CHANNEL=stable
|
|
|
|
# Pinning makes an upgrade a decision instead of a side effect of pulling. The app reports its real
|
|
# version either way — a channel tag is a second name on the same image, not a build that forgot
|
|
# its number.
|
|
#
|
|
# THERE IS NO EXAMPLE NUMBER HERE ON PURPOSE. Pin the version you are ALREADY RUNNING, which the app
|
|
# footer shows as `web … · api …`. Nothing in the publishing path bumps a number written into this
|
|
# file, so any number printed here is one that went stale while nobody was looking — and moving the
|
|
# api pin BACKWARDS runs an old build against a schema that has already been migrated forward.
|
|
#JARVIS_IMAGE_API=git.luxit.be/luxit/jarvis-api:<the api version in your footer>
|
|
#JARVIS_IMAGE_WEB=git.luxit.be/luxit/jarvis-web:<the web version in your footer>
|
|
|
|
# Only read when the agent overlay is enabled, just below. Its version is the AGENT's, and moves
|
|
# independently of the two above — a Jarvis release usually does not change the agent at all.
|
|
#
|
|
# PIN THIS ONE FIRST if you pin only one. The two above change what your own server runs; this one
|
|
# changes what runs on every machine you administer. Pinning it decides which build your instance
|
|
# publishes; a separate UPDATE POLICY decides when a machine takes it, and its default is "let the
|
|
# agent decide" — which in practice means the next time its service starts. Set that policy
|
|
# instance-wide under Settings → Platform → General, per organization under Settings → Organization →
|
|
# Agent updates. An enrolled agent also refuses any version that is not strictly newer, so moving
|
|
# this back stops a rollout rather than reversing it on machines that already took the update.
|
|
#
|
|
# The app footer does not carry this number. Each enrolled machine reports the build it runs, on the
|
|
# Agents page — that is the one to pin.
|
|
#JARVIS_IMAGE_AGENT=git.luxit.be/luxit/jarvis-agent-dist:<version>
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# The Jarvis agent (optional)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
# Enrolling a machine downloads a compiled binary, which the api serves from a directory it can
|
|
# only read. `docker-compose.agent.yml` supplies that directory as a pullable image, so the release
|
|
# arrives the same way the rest of the stack does. Uncomment this and every later `docker compose`
|
|
# command picks up both files with no extra flags:
|
|
#
|
|
#COMPOSE_FILE=docker-compose.yml:docker-compose.agent.yml
|
|
#
|
|
# Leaving it off is a supported state, not a broken one: everything except the agent works, and the
|
|
# installer answers 503 saying no build is published. The SSH, Proxmox, Microsoft 365 and MikroTik
|
|
# connectors all reach machines without it.
|
|
#
|
|
# AGENT_RELEASE_DIR is set by that overlay and should NOT be set here — a value in this file would
|
|
# point the api at a path nothing populates, turning the honest 503 into a 404 per platform.
|
|
|
|
#AGENT_HEARTBEAT_INTERVAL_SEC=30
|
|
#RUN_SHUTDOWN_GRACE_SEC=25
|
|
|
|
# How long a sign-in lasts, in seconds. Both were fixed in the compose file until now, which made
|
|
# them the only tuning values on this page you could read about and not change.
|
|
#
|
|
# JWT_ACCESS_TTL is how long an access token stays valid — and therefore how long a revoked session
|
|
# keeps working before it notices. Lower it if that window matters to you; the cost is a refresh
|
|
# round trip more often.
|
|
#
|
|
# JWT_REFRESH_TTL IS AN IDLE TIMEOUT, NOT A SESSION LIFETIME, and the difference will matter to you
|
|
# if you are here because of a policy. The refresh token rotates on every use and the new one starts
|
|
# its full term from that moment, so nothing anywhere measures how old a sign-in is: somebody who
|
|
# keeps a tab open stays signed in indefinitely. What this value really sets is how long a session
|
|
# survives being left alone. Fourteen days is the default. To end sessions by age rather than by
|
|
# idleness, revoke them — Settings → Security lists them and kills them individually.
|
|
#JWT_ACCESS_TTL=900
|
|
#JWT_REFRESH_TTL=1209600
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Licence (optional — without one you get the community edition)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
# Leave this empty and the instance runs the COMMUNITY EDITION: 1 organization, 3 users, 5 agents,
|
|
# 10 assets, no expiry and nothing to renew. Every feature works inside
|
|
# those numbers. A full limit refuses the NEXT thing of that kind and touches nothing already there.
|
|
#
|
|
# A key raises the limits — ask antoine@luxit.be for one. It is verified offline, on this machine. A
|
|
# licensed instance then reports counts and its own address to your provider; the README lists every
|
|
# field it sends. A key that expires or is withdrawn drops back to the allowances above, never to
|
|
# nothing.
|
|
#
|
|
# This value SEEDS the database on first boot and does not govern it afterwards: a renewal arrives
|
|
# through the check-in and is stored, so leaving an old key here cannot roll you back. To replace a
|
|
# key, use Settings → Licence.
|
|
#JARVIS_LICENSE_KEY=
|
|
|
|
# Whether an instance WITHOUT a licence reports to your provider. On unless you say otherwise.
|
|
#
|
|
# It sends the same fields a licensed instance does — counts, the version it runs, its contract
|
|
# checksum and its public address — to checkin.luxit.be. No names, no conversation content, nothing
|
|
# about what you administer. The README lists every field.
|
|
#
|
|
# Set it to off and nothing leaves this network at all. You keep every community allowance and every
|
|
# feature; what stops working is the licence request form in Settings → Licence, which needs the same
|
|
# channel. Accepted values for off: off, false, 0, no.
|
|
#
|
|
# A LICENSED instance reports regardless — that is part of what a licence is, and this variable does
|
|
# not change it.
|
|
# NOTE, 24 August 2026: this line did nothing before that date, and we are sorry. Compose reads
|
|
# this file to fill in placeholders INSIDE the compose file — it does not hand it to the services —
|
|
# and the api service never listed this variable, so the API saw nothing and applied its default of
|
|
# "on". An instance that had opted out reported anyway. Pull the repository again and
|
|
# `docker compose up -d`: the fix is in the compose file, not in the images.
|
|
#
|
|
# Do not trust this file to tell you whether it took. Ask the instance:
|
|
# docker compose exec api printenv JARVIS_TELEMETRY
|
|
# Settings -> Licence answers the same question from what the API actually resolved.
|
|
#JARVIS_TELEMETRY=on
|