Sync the self-hosting stack
This commit is contained in:
+146
-56
@@ -1,81 +1,146 @@
|
||||
# Jarvis — configuration. Copy to `.env` beside the compose file and fill in.
|
||||
# Jarvis — optional configuration.
|
||||
#
|
||||
# cp .env.example .env
|
||||
# THERE IS NOTHING YOU HAVE TO FILL IN. You do not need this file at all:
|
||||
#
|
||||
# Nothing here has a safe placeholder value: the four secrets must be generated, and the two URLs
|
||||
# must be yours. The compose file refuses to start rather than booting with something wrong.
|
||||
# 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
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# The address a browser reaches Jarvis on, scheme included and no trailing slash.
|
||||
#
|
||||
# This is the CORS decision. It accepts exactly ONE origin — not a list — and every request from
|
||||
# anywhere else is refused, which presents as a sign-in page that cannot sign in.
|
||||
WEB_ORIGIN=https://jarvis.example.com
|
||||
|
||||
# The address enrolled machines dial. Defaults to WEB_ORIGIN, which is right for a single-origin
|
||||
# deployment. Set it separately only if the app and the API answer on different hostnames.
|
||||
#PUBLIC_URL=https://jarvis.example.com
|
||||
|
||||
# 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.
|
||||
#
|
||||
# One is the web container's own nginx, which is always there. So: 1 if nothing else fronts it, 2 if
|
||||
# your own reverse proxy does — which is the usual case and the default. Raising it 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 the audit log and in the session list.
|
||||
TRUST_PROXY_HOPS=2
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Secrets — generate every one of these, never copy them from anywhere
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Postgres. Only ever used inside the compose network.
|
||||
# openssl rand -base64 24
|
||||
POSTGRES_PASSWORD=
|
||||
|
||||
# Session signing. Two different values, at least 16 characters each.
|
||||
# openssl rand -base64 48
|
||||
JWT_ACCESS_SECRET=
|
||||
JWT_REFRESH_SECRET=
|
||||
|
||||
# THE ONE YOU CANNOT LOSE.
|
||||
# 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.
|
||||
#
|
||||
# Must decode to exactly 32 bytes:
|
||||
# openssl rand -base64 32
|
||||
#
|
||||
# Every credential in the vault — SSH keys, API secrets, Microsoft 365 client secrets — is encrypted
|
||||
# under this key with AES-256-GCM, and so is everything Jarvis seals OUTSIDE the vault: the Microsoft
|
||||
# Graph client secret it sends its own mail with, this instance's licence identity key, every
|
||||
# authenticator-app secret, and every terminal recording. It is not stored anywhere but here.
|
||||
#
|
||||
# Change it or lose it and none of that data can be read again, by you or by anyone. A database backup
|
||||
# does not save you: the backup holds the ciphertext. Back this value up separately from the database,
|
||||
# somewhere you would still have it if this host were gone. An instance whose key has changed keeps
|
||||
# LOOKING configured — the rows are all there — and fails on every reveal.
|
||||
VAULT_MASTER_KEY=
|
||||
# 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
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# The model
|
||||
# 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.
|
||||
|
||||
# Any OpenAI-compatible endpoint: OpenAI, a self-hosted gateway, a local server.
|
||||
#OPENAI_BASE_URL=https://api.openai.com/v1
|
||||
|
||||
# Required. Jarvis will not start without it.
|
||||
OPENAI_API_KEY=
|
||||
|
||||
# Must be a model your endpoint actually serves, and it should be a good one — this model is deciding
|
||||
# what to run on production infrastructure.
|
||||
#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)
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -137,6 +202,22 @@ OPENAI_API_KEY=
|
||||
#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)
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -167,4 +248,13 @@ OPENAI_API_KEY=
|
||||
#
|
||||
# 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
|
||||
|
||||
Reference in New Issue
Block a user