Set the server's public URL from KEEPORG_EXTERNAL_URL
The image passes neither -config nor -url, so a deployment had no way to set external_url and the server built invite links, device-approval pages and the OIDC redirect URI on http://localhost:8765. The variable overrides the configuration file and -url overrides it. The deployment values set it to https://keeporg.tiredsysadmin.cc. Also document every environment variable the server reads, and the standard proxy and CA variables it honours for OIDC. Server version 0.8.0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
ead82dc777
commit
ef6598fa15
@@ -122,6 +122,19 @@ can no longer merge. `KEEPORG_MASTER_KEY` takes the base64 key directly if
|
|||||||
your secret store injects variables instead of files. See
|
your secret store injects variables instead of files. See
|
||||||
[packaging/docker/compose.yaml](packaging/docker/compose.yaml).
|
[packaging/docker/compose.yaml](packaging/docker/compose.yaml).
|
||||||
|
|
||||||
|
Server environment variables:
|
||||||
|
|
||||||
|
| Variable | Meaning |
|
||||||
|
| --- | --- |
|
||||||
|
| `KEEPORG_MASTER_KEY` | the master key, base64; overrides the other two sources |
|
||||||
|
| `KEEPORG_MASTER_KEY_FILE` | path to a file holding the master key (base64 or 32 raw bytes); never created, and if it is missing the server runs but cannot create or merge vaults |
|
||||||
|
| `KEEPORG_EXTERNAL_URL` | the public base URL (`external_url`); `-url` overrides it |
|
||||||
|
| `KEEPORG_ADMIN_PASSWORD` | the first `admin` password, read only on an empty server and by `-reset-admin` |
|
||||||
|
|
||||||
|
Everything else is configured in `server.json` or by flag. The details,
|
||||||
|
including the standard proxy and CA variables, are in
|
||||||
|
[docs/HANDOVER.md](docs/HANDOVER.md#environment-variables).
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
- [docs/HANDOVER.md](docs/HANDOVER.md) — architecture, the decisions behind
|
- [docs/HANDOVER.md](docs/HANDOVER.md) — architecture, the decisions behind
|
||||||
|
|||||||
+11
-1
@@ -17,6 +17,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -26,6 +27,9 @@ import (
|
|||||||
"cc.tiredsysadmin.keeporg/internal/store"
|
"cc.tiredsysadmin.keeporg/internal/store"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// externalURLEnv sets external_url, between the configuration file and -url.
|
||||||
|
const externalURLEnv = "KEEPORG_EXTERNAL_URL"
|
||||||
|
|
||||||
// Version is stamped at build time from versions.mk.
|
// Version is stamped at build time from versions.mk.
|
||||||
var Version = "dev"
|
var Version = "dev"
|
||||||
|
|
||||||
@@ -82,7 +86,7 @@ func main() {
|
|||||||
configPath = flag.String("config", "", "path to a JSON configuration file")
|
configPath = flag.String("config", "", "path to a JSON configuration file")
|
||||||
addr = flag.String("addr", "", "listen address (overrides the config file)")
|
addr = flag.String("addr", "", "listen address (overrides the config file)")
|
||||||
dataDir = flag.String("data", "", "data directory (overrides the config file)")
|
dataDir = flag.String("data", "", "data directory (overrides the config file)")
|
||||||
extURL = flag.String("url", "", "externally reachable base URL (overrides the config file)")
|
extURL = flag.String("url", "", "externally reachable base URL (overrides $"+externalURLEnv+" and the config file)")
|
||||||
masterKey = flag.String("master-key-file", "",
|
masterKey = flag.String("master-key-file", "",
|
||||||
"file holding the master key that wraps the vault keys, created if "+
|
"file holding the master key that wraps the vault keys, created if "+
|
||||||
"absent; $"+secret.MasterKeyEnv+" and $"+secret.MasterKeyFileEnv+
|
"absent; $"+secret.MasterKeyEnv+" and $"+secret.MasterKeyFileEnv+
|
||||||
@@ -121,6 +125,12 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
cfg := fc.toConfig()
|
cfg := fc.toConfig()
|
||||||
|
// The public URL is the one setting a deployment usually knows only at
|
||||||
|
// deploy time, so it can come from the environment as well. A flag
|
||||||
|
// still wins.
|
||||||
|
if v := strings.TrimSpace(os.Getenv(externalURLEnv)); v != "" {
|
||||||
|
cfg.ExternalURL = v
|
||||||
|
}
|
||||||
if *addr != "" {
|
if *addr != "" {
|
||||||
cfg.Addr = *addr
|
cfg.Addr = *addr
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ namespace: "apps"
|
|||||||
environment:
|
environment:
|
||||||
- name: "KEEPORG_MASTER_KEY_FILE"
|
- name: "KEEPORG_MASTER_KEY_FILE"
|
||||||
value: "/etc/keeporg/config.txt"
|
value: "/etc/keeporg/config.txt"
|
||||||
|
- name: "KEEPORG_EXTERNAL_URL"
|
||||||
|
value: "https://keeporg.tiredsysadmin.cc"
|
||||||
image:
|
image:
|
||||||
name: "repo.rcmd.space/keeporg"
|
name: "repo.rcmd.space/keeporg"
|
||||||
version: "v0.1.0"
|
version: "v0.1.0"
|
||||||
|
|||||||
+43
-1
@@ -599,9 +599,51 @@ things.
|
|||||||
```
|
```
|
||||||
|
|
||||||
`external_url` must be what a browser sees: invite links, device approval
|
`external_url` must be what a browser sees: invite links, device approval
|
||||||
pages and the OIDC redirect URI are built from it. Terminate TLS in front of
|
pages and the OIDC redirect URI are built from it. `KEEPORG_EXTERNAL_URL`
|
||||||
|
sets it too, for a deployment that knows the address only at deploy time. Terminate TLS in front of
|
||||||
the server, or set `tls_cert` and `tls_key`.
|
the server, or set `tls_cert` and `tls_key`.
|
||||||
|
|
||||||
|
### Environment variables
|
||||||
|
|
||||||
|
The server reads four variables of its own: the public URL, and secrets or
|
||||||
|
first-run material. Everything else — address, data directory, OIDC,
|
||||||
|
limits — is set only in `server.json` or by flag, with flags winning; there
|
||||||
|
is no environment equivalent for those. An empty or whitespace-only value
|
||||||
|
counts as unset.
|
||||||
|
|
||||||
|
| Variable | Read by | Meaning |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `KEEPORG_MASTER_KEY` | every start | The master key itself, base64 of 32 bytes. Takes precedence over everything below. Never written anywhere. A value that does not decode has the same effect as a missing key file. |
|
||||||
|
| `KEEPORG_MASTER_KEY_FILE` | every start, when `KEEPORG_MASTER_KEY` is unset | Path to a file holding the key, as base64 text or exactly 32 raw bytes. The file must exist and is never created, since a new key would open none of the existing vaults. If it is missing or malformed the server logs `no master key, so this server cannot create or merge vaults` and runs without one: key-less strategies keep working, vault creation and merging are refused. Takes precedence over `master_key_file` / `-master-key-file`. |
|
||||||
|
| `KEEPORG_EXTERNAL_URL` | every start | The base URL a browser reaches the server at, as `external_url`. Overrides the file; `-url` overrides it. Invite links, the device-approval page every client sign-in uses, and the OIDC redirect URI are built from it, and without any of the three it is `http://localhost<addr>`, which is wrong behind any proxy. |
|
||||||
|
| `KEEPORG_ADMIN_PASSWORD` | first start on an empty state, and `-reset-admin` | The password for the built-in `admin` account instead of a generated one, which is then not logged. Ignored once any account exists, so leaving it set is harmless but pointless; unset it after the first start. |
|
||||||
|
|
||||||
|
With neither master-key variable set, the key comes from `master_key_file`
|
||||||
|
(default `/etc/keeporg/master.key`), which *is* created if missing. See
|
||||||
|
[Key custody](#key-custody-and-encryption-at-rest) for why the three sources
|
||||||
|
behave differently.
|
||||||
|
|
||||||
|
The server also honours the Go runtime's standard variables, which matter
|
||||||
|
only for its outbound calls to an OIDC provider:
|
||||||
|
|
||||||
|
| Variable | Effect |
|
||||||
|
| --- | --- |
|
||||||
|
| `HTTPS_PROXY`, `HTTP_PROXY`, `NO_PROXY` | proxy for the discovery, token and userinfo requests |
|
||||||
|
| `SSL_CERT_FILE`, `SSL_CERT_DIR` | CA bundle to trust instead of the system's (Linux and BSD), for an identity provider behind a private CA; in the container the bundle is `/etc/ssl/certs/ca-certificates.crt` |
|
||||||
|
|
||||||
|
`packaging/docker/compose.yaml` additionally uses `KEEPORG_VERSION` to pick
|
||||||
|
the image tag and build argument. That is read by compose, not by the
|
||||||
|
server.
|
||||||
|
|
||||||
|
In the deployment under `config/variables/server.values.yaml`, the master
|
||||||
|
key arrives as the Kubernetes secret `keeporg-encryption` mounted on
|
||||||
|
`/etc/keeporg`, and `KEEPORG_MASTER_KEY_FILE=/etc/keeporg/config.txt` points
|
||||||
|
at it. `KEEPORG_EXTERNAL_URL=https://keeporg.tiredsysadmin.cc` matches the
|
||||||
|
nginx `server_name`; the image's command passes neither `-config` nor
|
||||||
|
`-url`, so this variable is the only thing that sets it there.
|
||||||
|
`KEEPORG_ADMIN_PASSWORD` is not set there, so the first start logs a
|
||||||
|
generated password once.
|
||||||
|
|
||||||
Back up `/var/lib/keeporg` **and** `/etc/keeporg/master.key`, separately.
|
Back up `/var/lib/keeporg` **and** `/etc/keeporg/master.key`, separately.
|
||||||
The data directory is the whole server: `state.json` plus the blobs. The
|
The data directory is the whole server: `state.json` plus the blobs. The
|
||||||
master key is what turns the wrapped vault keys in it back into vault
|
master key is what turns the wrapped vault keys in it back into vault
|
||||||
|
|||||||
@@ -1,3 +1,11 @@
|
|||||||
|
keeporgd (0.8.0) unstable; urgency=medium
|
||||||
|
|
||||||
|
* The public base URL can be set with the KEEPORG_EXTERNAL_URL
|
||||||
|
environment variable. It overrides external_url in the configuration
|
||||||
|
file; -url overrides it.
|
||||||
|
|
||||||
|
-- Azer Abdullaev <github@reactorcoremeltdown.anonaddy.com> Mon, 02 Nov 2026 12:37:29 +0100
|
||||||
|
|
||||||
keeporgd (0.7.0) unstable; urgency=medium
|
keeporgd (0.7.0) unstable; urgency=medium
|
||||||
|
|
||||||
* Deleting a database now requires the caller's own account password
|
* Deleting a database now requires the caller's own account password
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
# Single source of truth for all platform versions (semver).
|
# Single source of truth for all platform versions (semver).
|
||||||
# Bump with: make bump PLATFORM=<server|linux|macos|windows|bsd|android> PART=<major|minor|patch>
|
# Bump with: make bump PLATFORM=<server|linux|macos|windows|bsd|android> PART=<major|minor|patch>
|
||||||
VERSION_SERVER := 0.7.0
|
VERSION_SERVER := 0.8.0
|
||||||
VERSION_LINUX := 0.5.0
|
VERSION_LINUX := 0.5.0
|
||||||
VERSION_MACOS := 0.5.0
|
VERSION_MACOS := 0.5.0
|
||||||
VERSION_WINDOWS := 0.5.0
|
VERSION_WINDOWS := 0.5.0
|
||||||
|
|||||||
Reference in New Issue
Block a user