Skip to content

Configuration

Geass has no single configuration file. Settings live in six places: environment variables for the installer, flags and environment variables for the operator (which also serves the dashboard), a Secret for dashboard users, the GeassPlatformConfig and GeassCluster resources for platform behavior, the settings of each service, database and bucket, and a flags, variables and login file for the geass command line. This page lists them, with defaults, and says which take effect at once and which need a restart.

Surface Where Changes take effect
Installer variables Environment of the geass installer, once At install time only
Operator flags Arguments of the geass-controller-manager Deployment After the operator restarts
Operator environment variables Environment of that Deployment After the operator restarts
Dashboard users and sessions Secret geass-dashboard-auth At once
Platform settings GeassPlatformConfig named platform Within seconds, no restart
Cluster add-ons and region GeassCluster named default Within seconds; add-on installs take minutes
Resource settings Each service, database and bucket Live, or at the next deploy
Command line Flags, GEASS_* variables and config.json on the machine that runs geass The next time you run it

The installer is a single binary, geass, that you run as root on the first server. It takes no command-line flags. It reads these environment variables (see Install for the whole procedure):

Variable Default Meaning
GEASS_ACME_EMAIL none The contact address for the cluster’s Let’s Encrypt account. Checked at the first step (it must look like name@host.tld, with no spaces and at most 254 characters), then written to the GeassCluster as spec.addons.certManager.acmeEmail. Without it Geass creates no certificate issuer and no HTTPS certificate is issued. Let’s Encrypt refuses placeholder domains such as example.com. HTTPS certificates
GEASS_MULTI_SITE off 1, true, yes or on builds a cluster whose nodes are at different providers: an encrypted WireGuard overlay instead of VXLAN. Chosen at install time because changing it later means restarting every node. Multi-provider clusters
GEASS_NODE_EXTERNAL_IP none This node’s public IP address. Required when GEASS_MULTI_SITE is on; must be a valid IP. Workers join on it
GEASS_INSTALL_LOG geass-install-<UTC timestamp>.log in the current directory Where the installer writes its log. If that path is not writable it falls back to the system temp directory
GEASS_INSTALL_TRACE off 1, true, yes or on runs the downloaded K3s installer script with shell tracing (sh -x)
GEASS_INSTALL_ROOT detected A directory with installer assets. The installer binary embeds everything it needs and never asks for an override, so setting it has no effect on a normal install

The installer passes its whole environment to the K3s install script, so K3s’s own INSTALL_K3S_* variables reach it. Geass itself sets INSTALL_K3S_EXEC to server --cluster-init and, if a version was set, INSTALL_K3S_VERSION. The installer binary does not set a version, so K3s picks its default release.

The convenience script scripts/install.sh reads two variables of its own: GEASS_REPO (default degoke/geass) and GEASS_VERSION (default latest). It downloads geass-linux-amd64 or geass-linux-arm64 from that repository’s releases and runs it.

What the installer does, in order: checks the system (Linux, amd64 or arm64, at least 2 GB of memory and 10 GB free on /, and GEASS_ACME_EMAIL if you set it); opens ports 6443/tcp, 10250/tcp and the overlay port (8472/udp, or 51820/udp for multi-site) if it finds an active ufw, firewalld or iptables; removes an existing K3s installation; installs the iSCSI initiator that Longhorn needs; installs K3s as a server with embedded etcd (--cluster-init); imports the operator image; applies the operator manifests; stores the K3s join token in the Secret geass-token; and creates the GeassCluster named default. When GEASS_ACME_EMAIL is not set it prints a warning at that last step and creates the cluster without an acmeEmail.

Files it writes on the server:

Path Content
/etc/rancher/k3s/config.yaml K3s server settings: the kubelet log limits (below) and, for multi-site, the WireGuard backend, external IP and certificate name
/etc/rancher/k3s/k3s.yaml The admin kubeconfig K3s writes
/var/lib/rancher/k3s/server/node-token The join token, also copied to the Secret geass-token

Geass sets container-log-max-size=50Mi and container-log-max-files=5 on every node’s kubelet, so a service’s recent logs stay on the node. Workers get the same settings plus their labels and taints when they join.

The operator and the dashboard are one process, /manager. The installed Deployment geass-controller-manager in geass-system runs it with four flags:

Installed arguments
--metrics-bind-address=:8443
--leader-elect
--health-probe-bind-address=:8086
--dashboard-bind-address=:8085
Flag Default Meaning
--dashboard-bind-address :8085 Where the dashboard and API listen (plain HTTP). 0 turns the dashboard off
--health-probe-bind-address :8086 Where /healthz and /readyz are served
--metrics-bind-address 0 (off) Where operator metrics are served. The installed manifest sets :8443
--metrics-secure true Serve metrics over HTTPS with Kubernetes authentication and authorization. --metrics-secure=false serves plain HTTP
--metrics-cert-path, --metrics-cert-name, --metrics-cert-key none, tls.crt, tls.key A certificate for the metrics endpoint. Without one, a self-signed certificate is generated
--leader-elect false Elect one active operator among replicas. The installed manifest turns it on
--enable-http2 false Allow HTTP/2 on the metrics server. Off to avoid the known HTTP/2 reset attacks
--kubeconfig in-cluster Path to a kubeconfig, for running outside the cluster
--webhook-cert-path, --webhook-cert-name, --webhook-cert-key none, tls.crt, tls.key Scaffolding for a certificate for an admission webhook server. The operator registers no admission webhooks, so these do nothing
--zap-devel true Development logging: console format and debug level. Set --zap-devel=false for JSON and info level
--zap-encoder, --zap-log-level, --zap-stacktrace-level, --zap-time-encoding per --zap-devel Log format, verbosity, stack trace threshold and timestamp format

Change a flag by editing the Deployment. The container is the first and only one, called manager:

Turn on info-level JSON logs
kubectl -n geass-system patch deployment geass-controller-manager --type json \
-p '[{"op":"add","path":"/spec/template/spec/containers/0/args/-","value":"--zap-devel=false"}]'
kubectl -n geass-system rollout status deployment/geass-controller-manager

The pod itself runs on a control plane node, with a request of 10m CPU and 128Mi memory and a limit of 500m and 512Mi, as a non-root user with a read-only root filesystem.

Besides the standard controller-runtime series (reconcile counts and durations, work queue depth, requests to the Kubernetes API), the metrics endpoint serves these Geass series. With the monitoring add-on on, Geass scrapes them and defines alert rules on them (see Security).

Series Labels Meaning
geass_apiserver_client_request_duration_seconds verb, resource, code How long the Kubernetes API server took to answer the operator (a histogram)
geass_apiserver_client_requests_in_flight none Requests sent to the API server that have not been answered yet
geass_reconcile_not_ready_total reason Reconciles that ended with a resource not ready
geass_provision_duration_seconds phase How long a deploy of a service, database or bucket took, start to outcome (a histogram)
geass_status_writes_total kind, result Status updates the controllers considered: written, skipped (nothing changed) or failed

These are read by the operator process, so set them on the Deployment, and restart it afterwards.

Set an operator variable
kubectl -n geass-system set env deployment/geass-controller-manager GEASS_PROMETHEUS_URL=http://prometheus.example.internal:9090
Variable Default Meaning
GEASS_DASHBOARD_USERS none Dashboard users, as a JSON array or as username:password:role entries separated by commas. Used only while the Secret has no users
GEASS_DASHBOARD_PASSWORD none A single admin password. Used only if no users are set. The user is named by GEASS_DASHBOARD_USERNAME
GEASS_DASHBOARD_USERNAME admin The name of the user created from GEASS_DASHBOARD_PASSWORD
GEASS_DASHBOARD_SESSION_KEY generated The key that signs session cookies, at least 16 bytes (or hex: followed by hex). Overrides the key in the Secret
GEASS_PROMETHEUS_URL http://geass-kube-prometheus-stac-prometheus.monitoring.svc:9090 Where the dashboard queries metrics, unless the platform configuration sets prometheusURL
GEASS_LOGS_URL http://geass-victorialogs.geass-logging.svc:9428 Where the dashboard reads stored log history (the logging add-on’s VictoriaLogs server)
GEASS_WEBHOOKS_ALLOW_PRIVATE_NETWORKS false true lets project webhooks reach private network addresses (RFC 1918 and shared address space). Loopback and link-local stay blocked
GEASS_GITHUB_APP_ID, GEASS_GITHUB_APP_CLIENT_ID, GEASS_GITHUB_APP_CLIENT_SECRET, GEASS_GITHUB_APP_SLUG, GEASS_GITHUB_APP_PRIVATE_KEY, GEASS_GITHUB_WEBHOOK_SECRET none GitHub App credentials, used only when the platform configuration has no githubAppRef (that is, nothing was saved in Settings → Connectors)
GEASS_PUBLIC_URL none The dashboard’s public address for the GitHub App, overridden by the dashboard URL once you set a domain
GOMEMLIMIT 400MiB in the installed Deployment The Go runtime’s soft memory limit. It sits below the container’s 512Mi limit, so the runtime collects harder near the limit instead of being killed for it

The default Prometheus address depends on the monitoring add-on. A prometheusURL set on the platform configuration wins over GEASS_PROMETHEUS_URL, which wins over the default. Standard Kubernetes variables such as KUBECONFIG also apply, because the operator uses controller-runtime.

Dashboard sign-in reads the Secret geass-dashboard-auth in geass-system, on every request, so edits apply at once. The sample is config/samples/geass_dashboard_auth.yaml.

geass-dashboard-auth.yaml
apiVersion: v1
kind: Secret
metadata:
name: geass-dashboard-auth
namespace: geass-system
type: Opaque
stringData:
users: |
[{"username":"admin","password":"replace-with-a-long-passphrase","role":"admin"}]
Key Content
users A JSON array of {"username","password","role"}. Roles are admin and viewer (observer is a token role, not a user role). Plain passwords are replaced by bcrypt hashes the first time they are read
session-key The key that signs sessions, as hex: plus 64 hex characters. Generated on first use. Delete it to sign everyone out
session-epochs A JSON object of per-user counters that Geass increments on sign-out
login-lockouts A JSON object of failed sign-in counters and lock times, per configured username. Expired records are removed and at most 256 are kept

Geass writes the last three keys; you only need users. The full story is in Users and API tokens.

The geass command line runs on your own machine, not in the cluster. It combines, from highest to lowest precedence, a flag, an environment variable and the saved login. Every command also takes --json and --yes; the full list is in the CLI reference.

Variable Flag Meaning
GEASS_URL --url The dashboard’s address, such as https://geass.example.com
GEASS_TOKEN --token An API token. geass login also takes the token to save from it
GEASS_PROJECT -p, --project The default project, by its proj-... ID
GEASS_ENVIRONMENT -e, --environment The default environment, such as production
GEASS_CONTEXT --context Which saved login to use
GEASS_CONFIG none The path of the login file. Default: config.json in the geass folder of your user configuration directory (~/.config/geass/config.json on Linux)

geass login saves what it signed in to as a named login (its name is the dashboard’s host name unless you pass --name) and makes it the current one. The file is JSON; the folder is created with mode 0700 and the file with mode 0600, and the token is stored in plain text:

~/.config/geass/config.json
{
"current": "geass.example.com",
"contexts": {
"geass.example.com": {
"url": "https://geass.example.com",
"token": "gsw_1a2b3c4d_0123456789abcdef0123456789abcdef01234567",
"user": "token:CLI: geass CLI on laptop",
"role": "observer",
"project": "proj-1a2b3c4d",
"environment": "production"
}
}
}

geass config get-contexts lists the saved logins (without tokens), geass config use-context NAME switches, and geass config set-context --project ... --environment ... sets the default project and environment for a login. geass logout clears the saved token only.

The installer script for the command line, scripts/install-cli.sh, is separate from the cluster installer. It downloads geass-cli-<os>-<arch> (Linux and macOS, amd64 and arm64) from a release and saves it as geass. It reads three variables:

Variable Default Meaning
GEASS_VERSION latest A release tag to install
GEASS_INSTALL_DIR /usr/local/bin when you can write to it, otherwise ~/.local/bin Where to put the binary
GEASS_REPO degoke/geass The GitHub repository whose releases to download, for a fork

On Windows, download geass-cli-windows-amd64.exe from the release page. The MCP server (geass mcp) has no configuration of its own: it uses the same login, flags and variables, plus --read-only, --allow-delete and --listen; see MCP server.

Platform behavior is stored in two resources that Geass creates for you. You can edit them with kubectl; most of their fields also have a screen in Settings.

There is one, named platform, in geass-system. See GeassPlatformConfig for the schema.

Field Meaning Edited in the dashboard at
rootDomain Your apex domain, such as example.com Settings → Domain
dashboardURL The dashboard’s public HTTPS address; https://<subdomain>.<rootDomain> Settings → Domain (Subdomain, default geass)
dashboardExposure ingress (the default) or cloudflare-tunnel Settings → Domain (Publish via)
tunnelCNAMETarget The tunnel’s <id>.cfargotunnel.com name; Geass sets it when it manages the tunnel Settings → Domain
cloudflareConnectionRef, cloudflareZoneID The Cloudflare Secret and DNS zone Settings → Connectors → Cloudflare
githubAppRef The Secret holding the GitHub App Settings → Connectors → GitHub
prometheusURL Where to query metrics kubectl only
defaultClusterRef The cluster new projects use when there are several kubectl only
registry.repository, registry.credentialRef The image destination and login for repository builds when a service sets none. The login is also what the nodes pull the built image with The REST API (/api/settings/registry/save) or kubectl. The dashboard has no form for it yet
defaultDomain, traefikAccessLogs Present in the schema; no code reads them Not used

Changes apply as soon as the controller sees them. Verifying a new dashboard domain polls every 5 seconds for 15 minutes, then every 5 minutes, so a late DNS fix still heals. The status shows DashboardDomainReady and CloudflareReady.

The installer creates one, named default. See GeassCluster.

Field Default Meaning
spec.addons.certManager.enabled true Install cert-manager. When false, Geass removes the cert-manager it installed and manages no issuer
spec.addons.certManager.acmeEmail empty (the installer sets it from GEASS_ACME_EMAIL) The Let’s Encrypt contact address, at most 254 characters, in the form name@host.tld. When set, Geass creates and keeps the letsencrypt-prod ClusterIssuer that every HTTPS Ingress asks for. Empty means no issuer is created
spec.addons.monitoring.enabled true Install the monitoring stack (Prometheus). While it is on, Geass also scrapes the operator’s own metrics and adds alert rules for the operator’s health
spec.addons.monitoring.profile lite lite or full footprint
spec.addons.longhorn.enabled false (the installer sets true) Install Longhorn for database volumes. It needs iSCSI on every node
spec.addons.logging.enabled false (the installer sets true) Install log collection and the VictoriaLogs store
spec.addons.logging.retentionDays 7 (1 to 90) How long stored logs are kept
spec.addons.serverless.enabled false (the installer does not set it) Install the scale-to-zero add-on, so services can sleep when idle: KEDA and its HTTP add-on (charts geass-keda and geass-keda-http, namespace keda). It also creates a K3s HelmChartConfig named traefik that lets Traefik route to the add-on’s proxy, unless Traefik already has one, which it leaves alone and logs what to add. Turning it off stops services from sleeping and wakes the ones that are asleep, but never uninstalls KEDA. See Scale to zero
spec.network.multiSite false Nodes are at different providers. Set by the installer; changing it later does not rebuild nodes
spec.defaultRegion empty The region for projects that do not choose one. Edited in Settings → Usage (Default region)
spec.serverURL The control plane’s own address on its default route, for a single-site install The address workers join. The installer fills it in with the address its default route uses (a private address on most cloud servers), and a multi-site install writes the public address. A loopback address is never used: workers join on the control plane node’s own address instead. Set it only to use a different address. See Add servers
spec.tokenSecretRef, spec.version geass-token in geass-system, and v1 The Secret with the join token, and a label that is not a K3s version

The dashboard has no switch for the serverless add-on. Turn it on with kubectl:

Turn on the scale-to-zero add-on
kubectl -n geass-system patch geasscluster default --type merge \
-p '{"spec":{"addons":{"serverless":{"enabled":true}}}}'

The add-on takes a few minutes to come up; until it does, a service that asks to sleep keeps running, and its ScaleToZero condition says why.

The GeassCluster also carries a ClusterIssuerReady condition that says whether the letsencrypt-prod issuer exists and works. It is informational and does not change the cluster’s Ready; Geass removes it when cert-manager is turned off. Its reasons are IssuerReady, ACMEEmailMissing, WaitingForCertManager, IssuerRegistering, IssuerNotReady, ExternallyManaged, ManagedByAnotherCluster, IssuerApplyFailed and IssuerAccessDenied. The same message is added to the dashboard domain’s status (PendingHTTPS) while its HTTPS is unreachable. Each reason is explained in HTTPS certificates.

Read the issuer condition
kubectl -n geass-system get geasscluster default \
-o jsonpath='{.status.conditions[?(@.type=="ClusterIssuerReady")].reason}{": "}{.status.conditions[?(@.type=="ClusterIssuerReady")].message}{"\n"}'
What Value
Dashboard session 12 hours, not extended
Sign-in lockout 5 failures in a minute lock a username for a minute
API tokens At most 100; names up to 60 characters; lifetime 1 to 3650 days or none
Command-line sign-in A request lives 10 minutes; the CLI polls every 5 seconds; at most 100 pending, and 10 started a minute per address. The token it hands out lasts 30 days unless the admin chooses 7 or 90
/api/v1 request body At most 2 MiB
Webhooks At most 20 per project; 3 delivery attempts; 10 second timeout; the last 20 deliveries are kept
Pull request environments At most 25 open; default 5
New service size 0.1 CPU and 128 MB; allowed CPU 100m, 250m, 500m, 1, 2; allowed memory 128Mi to 4Gi
New database size 250m CPU, 512Mi memory; 10Gi volume (1Gi for SQLite)
Autoscaling Target CPU 50 percent by default
Replica count 0 to 1000
Sleep when idle Idle time 30 seconds to 24 hours, 300 seconds by default; 1 to 100 copies when awake, 3 by default
Function schedules At most 8 per function, in UTC cron syntax; a run times out after 120 seconds, is skipped if it cannot start within 5 minutes, and never overlaps the previous run
Function code At most 256 KiB
Compliance At most 8 required tags per project; at most 16 tags per node
Environments At most 100 per project
Backup retention 7 days by default, 1 to 365; a deleted database’s backups stay for 7 days
Deploy history The last 12 deploys per service
Stored logs 7 days by default (1 to 90)
Terminal session 5 minutes
Domain verification 15 minutes of polling every 5 seconds

Live settings and settings that need a deploy

Section titled “Live settings and settings that need a deploy”

For a service, database or bucket, Geass applies some edits at once and holds the rest until you deploy.

Applied at once Waits for a deploy
A service’s replica count, autoscaling and sleep-when-idle settings; host, path and TLS; metrics scraping; log retention; failure threshold and the pause and rollback flags; repository watch patterns A service’s source (a function’s code, mode and schedules included), port, variables and secrets, command and arguments, resources, probes and build settings
A database’s backup settings A database’s version, volume size, CPU and memory
none for buckets Every bucket setting

Variables and secrets always need a deploy. See Projects and environments.

Geass installs these add-ons and images at fixed versions, through HelmChart resources that K3s’s Helm controller installs in kube-system. You cannot choose other versions from the dashboard.

Component Version Namespace
cert-manager (chart) v1.17.2 cert-manager
kube-prometheus-stack (chart) 69.8.2 monitoring
Longhorn (chart) 1.12.1 longhorn-system
CloudNativePG operator (chart) 0.23.2 cnpg-system
Victoria Logs (chart) 0.13.10 geass-logging
Fluent Bit (chart) 0.58.3 geass-logging
MySQL (Bitnami chart) 12.3.3 the project environment
Redis (Bitnami chart) 20.7.1 the project environment
MinIO (chart) 5.4.0, image RELEASE.2025-02-18T16-25-55Z geass-system (cluster server)
rqlite for SQLite databases 8.36.16 the project environment
KEDA (chart), for sleep when idle 2.21.0 keda
KEDA HTTP add-on (chart), for sleep when idle 0.16.0 keda
Kaniko for repository builds v1.23.2 geass-system
cloudflared 2024.10.0 geass-system

Postgres runs the ghcr.io/cloudnative-pg/postgresql image at the major version in the database’s version field (default 16).

Secret Holds
geass-dashboard-auth Dashboard users and session state
geass-api-tokens API token records (hashes)
geass-token The K3s join token, read when a worker joins
platform-github-app The GitHub App credentials
platform-cloudflare, geass-cloudflared-token The Cloudflare API token, and the tunnel connector token
<name>-credentials An AWS or PlanetScale connection
geass-backup-storage-<bucket> The key for a backup bucket
<project>-webhooks, <project>-shared-secrets Webhook signing secrets, and secret shared variables
<app>-secrets A service’s own secrets
<project>-github, <project>-github-token A project’s GitHub link (<project>-github is a connection resource; the token is its Secret)

Saved templates are ConfigMaps named template-<id> with the label geass.dev/template=true. A function’s schedule token is the Secret <app>-trigger, which lives in the service’s environment namespace, not in geass-system.

Port Component Protocol
8085 Dashboard and API (Service geass-geass-dashboard) HTTP
8086 Operator health probes HTTP
8443 Operator metrics (Service geass-controller-manager-metrics-service) HTTPS
8080 The scale-to-zero proxy (keda-add-ons-http-interceptor-proxy in keda), in the cluster only, when that add-on is on HTTP
6443 Kubernetes API HTTPS
10250 kubelet HTTPS
8472 or 51820 Overlay network (VXLAN, or WireGuard for multi-site) UDP

The operator does not pick up a flag. Check the argument is on the manager container (kubectl -n geass-system get deployment geass-controller-manager -o yaml) and that the pod restarted (rollout status).

A dashboard user change has no effect. Environment users are used only while the Secret has none. Edit the Secret, which wins once it has a users key.

Metrics are empty. Check spec.prometheusURL on the platform configuration and GEASS_PROMETHEUS_URL; then that the monitoring add-on is enabled and Prometheus answers at that address. See Observability.

Log history says “not set up”. The logging add-on is off in spec.addons.logging.enabled. The installer turns it on for clusters it builds.

A multi-site install stops with “needs this node’s public address”. Set GEASS_NODE_EXTERNAL_IP to the node’s public IP.

A service never sleeps after you turn on sleep when idle. The ScaleToZero condition on the service says why. The usual causes are that spec.addons.serverless.enabled is not true on the GeassCluster, that the add-on in keda is still coming up, or that the service has no public host or still has CPU autoscaling on. See Scale to zero.

geass says “not signed in”. No saved login, GEASS_URL or GEASS_TOKEN was found. Run geass login --url https://geass.example.com, or check GEASS_CONFIG points at the file you expect.