Docs

Install

These instructions target Janus Edge v2026.9.2, not an unpublished latest tag.

Linux installer (recommended evaluation path)

Requires Linux amd64 (x86_64) or arm64 and Python 3.9+. Download and review the installer before running it; no root privileges are needed.

curl -fL https://github.com/Torvanis/janus/releases/download/v2026.9.2/install.py -o install.py
python3 install.py --version 2026.9.2
python3 ~/.local/share/janus/run-local.py --binary ~/.local/bin/janus

The installer downloads the matching architecture archive, verifies it against SHA256SUMS, and installs the binary under ~/.local/bin and supporting files under ~/.local/share/janus. Checksums detect corruption, not a compromised publisher. It does not create a service, a service user, TLS configuration, or a database server. --prefix changes the installation prefix; use the corresponding paths when launching.

The local launcher binds to 127.0.0.1:8080, disables dev authentication, and generates a private encryption key once. Open that URL and create the first administrator. Keep both janus.db and encryption.key in the launcher's data directory (by default ${XDG_DATA_HOME:-$HOME/.local/share}/janus); never generate a replacement key for an existing database. See backups.

Release files:

Docker (evaluation)

The release image is ghcr.io/torvanis/janus:2026.9.2. Anonymous registry access has not been verified; if pulling is denied, use the Linux installer or build from the tagged source below. Do not substitute latest.

Create a private environment file once, before creating a new database volume. The released helper refuses to overwrite an existing file:

curl -fL https://raw.githubusercontent.com/Torvanis/janus/v2026.9.2/scripts/init-env.py -o init-env.py
python3 init-env.py --output janus.env

Retain janus.env for every subsequent run and back it up securely with janus-data. If it is lost while the volume exists, restore the original key rather than running initialization again.

docker run --name janus -p 127.0.0.1:8080:8080 \
  -v janus-data:/data --env-file janus.env \
  -e JANUS_DATABASE_URL=sqlite:///data/janus.db \
  -e JANUS_LISTEN_ADDR=:8080 \
  -e JANUS_PUBLIC_URL=http://127.0.0.1:8080 \
  -e JANUS_DEV_AUTH=false -e JANUS_ENV=production \
  -e JANUS_COOKIE_SECURE=false \
  ghcr.io/torvanis/janus:2026.9.2

Open the loopback URL and create the first administrator. The insecure-cookie setting is only for this loopback HTTP example. Do not expose it as a production endpoint.

Compose (source-built evaluation)

Requires Git and Docker with the Compose plugin. Use the tagged Compose example:

git clone --branch v2026.9.2 --depth 1 https://github.com/Torvanis/janus.git
cd janus
python3 scripts/init-env.py
docker compose --env-file deploy/.env -f deploy/compose.yaml up --build -d

This builds the gateway locally and uses SQLite with a persistent volume and loopback-only port. It does not provision PostgreSQL, Prometheus, Grafana, or Alertmanager. Keep deploy/.env with the database backups; do not regenerate it when recreating containers.

Kubernetes and production

Install Helm chart 0.1.1 for application 2026.9.2 directly from the GitHub release asset. This is a chart archive, not an OCI registry chart. Requires Helm 3, Kubernetes 1.25+, namespace permissions, and a filesystem StorageClass supporting fsGroup permissions. See the README and values.yaml inside the archive, or the chart source (main may advance beyond this chart version).

Choose one database mode before first installation:

  • Bundled PostgreSQL (default): one PostgreSQL 16 instance with persistent storage; this is not a highly available database.
  • Local SQLite — EVALUATION ONLY: one gateway replica, not a production database option.
  • Existing external PostgreSQL: an operator-managed database; managed HA is recommended for critical systems.

First installation: bundled PostgreSQL

Keep setup private until you create the first administrator. ClusterIP does not isolate Janus from other cluster workloads: restrict access with your CNI/network controls. Anyone who reaches an unclaimed instance can create its first administrator. Local accounts are available; OIDC is optional and development authentication is disabled.

For a new installation only, run the following in a shell without tracing. It stops on errors, creates private temporary files, and uses create (not apply) so existing Secrets are never overwritten. An existing namespace also stops this example: inspect it and any retained data/Secrets before proceeding. Never rerun generation for an existing database, including after a partial installation; restore/reuse the original key. Back up both generated files in your approved secret manager before leaving this shell; the temporary copies are deleted on exit.

set -eu
kubectl create namespace janus
umask 077
secret_dir=$(mktemp -d)
trap 'rm -rf "$secret_dir"' EXIT
openssl rand -hex 32 > "$secret_dir/key-with-newline"
tr -d '\n' < "$secret_dir/key-with-newline" > "$secret_dir/encryption-key"
openssl rand -base64 48 > "$secret_dir/password-with-newline"
tr -d '\n' < "$secret_dir/password-with-newline" > "$secret_dir/password"
# Back up encryption-key and password securely before continuing.
kubectl -n janus create secret generic janus-key \
  --from-file=JANUS_ENCRYPTION_KEY="$secret_dir/encryption-key"
kubectl -n janus create secret generic janus-db \
  --from-file=password="$secret_dir/password"

Save this non-secret configuration as janus-values.yaml (bundled default):

encryptionKey:
  existingSecret: janus-key
database:
  type: postgresql
postgresql:
  enabled: true
  existingSecret: janus-db
replicaCount: 1
publicURL: http://127.0.0.1:8080

The chart pins the gateway image digest for ghcr.io/torvanis/janus:2026.9.2. Anonymous registry access has not been verified. If denied, authenticate with an entitled account and reference an existing registry credential Secret in namespace janus, or build the public tagged source and push it to a registry your cluster can access. Creating registry credentials is an operator prerequisite; do not put passwords in Helm values. Merge these optional settings into your chosen values file as needed:

imagePullSecrets:
  - name: janus-registry
# For your own source-built image, override the repository/tag AND clear digest:
# image:
#   repository: registry.example.com/your-team/janus
#   tag: "2026.9.2"
#   digest: ""

Install using the saved values, then bootstrap through loopback:

helm upgrade --install janus https://github.com/Torvanis/janus/releases/download/v2026.9.2/janus-0.1.1.tgz \
  --namespace janus --values janus-values.yaml --wait --timeout 10m
kubectl -n janus port-forward --address 127.0.0.1 service/janus-janus 8080:8080

Open http://127.0.0.1:8080 and create the first administrator before exposing access. The default public URL and non-secure cookies are for loopback HTTP only. Missing Secrets or keys must be repaired using the original credentials, not replaced with newly generated keys.

Existing external PostgreSQL

Instead of the bundled values, save the following as janus-values.yaml. Create/reuse janus-key as above and provision an external database/user with migration permissions. Create an existing janus-external-db Secret with key password from a private file containing the database's actual password (no trailing newline), using kubectl -n janus create secret generic janus-external-db --from-file=password=/secure/path/password. Do not generate a new password unless it is also configured on the database. If needed, create janus-postgres-ca with key ca.crt containing the PEM CA bundle.

encryptionKey:
  existingSecret: janus-key
database:
  type: postgresql
postgresql:
  enabled: false
externalPostgresql:
  host: postgres.example.com
  port: 5432
  database: janus
  username: janus
  existingSecret: janus-external-db
  passwordKey: password
  sslMode: verify-full
  caSecret: janus-postgres-ca
  caKey: ca.crt
publicURL: http://127.0.0.1:8080

Replace the example host and database settings. Omit caSecret only when the server chain is already trusted by the gateway image. Credentials use separate PG variables, not password interpolation into a URI. Use the same GitHub Helm command and private bootstrap above. Bundled PostgreSQL uses unencrypted in-cluster connections and initializes a superuser; choose external PostgreSQL with verified TLS and a least-privilege role for stricter isolation.

Local SQLite — EVALUATION ONLY

For a new evaluation instance, create only janus-key and use this alternative janus-values.yaml with the same install command. No PostgreSQL password Secret is required.

# EVALUATION ONLY — not a production database option.
encryptionKey:
  existingSecret: janus-key
database:
  type: sqlite
postgresql:
  enabled: false
replicaCount: 1
sqlite:
  persistence:
    size: 10Gi
publicURL: http://127.0.0.1:8080

SQLite uses a persistent /data/janus.db, ReadWriteOnce storage, and Recreate upgrades. Never share the claim with another writer. More than one replica is rejected; RWO alone is not a multiwriter guard.

Production exposure, backups and upgrades

After private bootstrap, production deployments must use PostgreSQL, HTTPS, persistent encryption-key storage, backups, and appropriate authentication. For ingress, merge the following into your PostgreSQL values file; install the ingress controller and supply a real TLS Secret separately:

publicURL: https://janus.example.com
ingress:
  enabled: true
  className: nginx
  host: janus.example.com
  tls:
    - secretName: janus-tls
      hosts: [janus.example.com]

The HTTPS public URL enables secure cookies. Configure trusted proxy CIDRs explicitly via extraEnv and controller-specific streaming timeouts/body limits via ingress.annotations. Protect the unauthenticated /metrics endpoint at the network/proxy layer. The chart installs neither a certificate issuer nor a monitoring stack; ServiceMonitor is opt-in and requires its CRD. Additional gateway replicas require the appropriate license and do not make bundled PostgreSQL HA.

Reuse the complete values file and unchanged Secrets on every upgrade. Back up the database, PostgreSQL password, and Janus encryption key together and test restores; never generate a replacement key for an existing database. See backup guidance and the packaged chart README. Single-replica upgrades have brief downtime. Changing database mode is not a migration; changing a Secret does not rotate a password in an initialized PostgreSQL volume. Helm rollback does not reverse schema migrations. Retained PVCs and existing Secrets can survive uninstall: preserve release identity and plan storage reuse rather than starting key generation again.

Air-gapped installation

Transfer install.py, the matching architecture archive, and SHA256SUMS from the release to the Linux host, then run (amd64 example):

python3 install.py --archive janus_2026.9.2_linux_amd64.tar.gz --checksums SHA256SUMS

Use the arm64 filename on arm64. Set JANUS_OFFLINE=true in managed gateway deployments to disable online update checks and license sync. This does not block network traffic to configured providers or replace a network egress policy. The local launcher clears ambient JANUS_* settings and leaves online checks disabled; it is not a general production environment loader.

First sign-in

  1. Open the local URL and create the first administrator before exposing the gateway.
  2. Admin → Upstreams: add a provider and run discovery.
  3. Admin → Models: grant models to people, groups, or everyone.
  4. Admin → System → License: paste your key if applicable.