| Filename | Latest commit message | Latest commit date |
|---|---|---|
Outline will not boot:
Environment configuration is invalid, please check the following:
- SSL_CERT cannot be used without SSL_KEY.
Nothing here sets SSL_CERT. The cluster injects
SSL_CERT_FILE=/etc/ssl/cluster-trust/ca-bundle.crt into every pod, which
to OpenSSL means "the trust store is here" -- which certificates to
BELIEVE. Outline reads its environment through a Docker-secrets proxy
(server/utils/environment.ts): reading NAME when it is `undefined` returns
the contents of the file named by NAME_FILE. So Outline loaded the cluster
CA bundle and concluded the operator had supplied a TLS SERVER certificate
to terminate with. There is no SSL_KEY to go with it, and
@CannotUseWithout("SSL_KEY") ends the process before it serves.
Two conventions, one name. The proxy falls back only when the value is
strictly `undefined`, so declaring SSL_CERT at all -- even empty -- stops
the fallback, and Outline's own toOptionalString("") turns it back into
`undefined` for validation. Node still trusts the bundle through
NODE_EXTRA_CA_CERTS, the variable Node actually reads; SSL_CERT_FILE was
never doing that job here.
Any other application in this cluster that implements the `_FILE`
convention meets the same collision, so the reason is written down in both
the manifest and the README rather than left as an empty value someone
will tidy away.
Claude-Session: https://claude.ai/code/session_01JGe4pyhQ36AhgDfPJry4d3
|
||
| apps | ||
| manifests/outline | ||
| README.md | ||
outline
Outline, the team wiki at https://outline.sean.farm.
This repository holds the workload ONLY. Everything Outline depends on is owned elsewhere, on purpose: a prune here can never reach the data.
| piece | owner |
|---|---|
| namespace, ArgoCD AppProject, root Application | sean/seanfarm kubernetes/flux/infrastructure/outline-argocd/ |
| Hydra OIDC client, S3 credential delivery | same |
| Valkey (the BullMQ queues, on a ZFS volume) | sean/seanfarm kubernetes/flux/infrastructure/valkey-outline/ |
| Postgres database + rotating owner role | sean/seanfarm kubernetes/flux/infrastructure/tenantdatabase/outline.yaml |
| RustFS key | sean/seanfarm kubernetes/flux/infrastructure/rustfs-identities/outline.yaml |
| RustFS bucket + policy | sean/binjovi-plans object-store.json |
| TLS certificate, gateway listener, portal card | sean/seanfarm kubernetes/flux/infrastructure/portal/ |
Layout
apps/outline.yaml the child ArgoCD Application
manifests/outline/ the workload it syncs
The app-of-apps root in sean/seanfarm syncs apps/; that Application syncs
manifests/outline.
Things that are not obvious
The DNS record comes from the HTTPRoute. external-dns runs with
--source=gateway-httproute, so outline.sean.farm resolves only once
manifests/outline is on main. The gateway listener and its certificate exist
already and are not enough on their own.
SECRET_KEY must be exactly 64 hexadecimal characters (@IsHexadecimal()
and @Length(64, 64) in server/env.ts). External Secrets cannot emit hex, so
the generator is asked for 64 characters of which 64 are digits -- digits are a
subset of hex. Allowing letters would produce g-z and Outline would refuse to
boot. It is frozen (refreshInterval: "0") because it encrypts stored data:
changing it locks every user out.
DATABASE_URL is assembled from a rotating credential, and the password is
urlquery-encoded. OpenBao rotates it hourly under a policy this repository does
not control; one @ or / in a generated value would re-point the connection at
another host.
The queues need maxmemory-policy noeviction. Outline drives Valkey through
bull, where an evicted key is a silently dropped job, not an error. That
setting lives with the Valkey in sean/seanfarm.
SSL_CERT is declared empty on purpose. The cluster injects
SSL_CERT_FILE=/etc/ssl/cluster-trust/ca-bundle.crt into every pod, meaning
"the trust store is here". Outline reads its environment through a
Docker-secrets proxy where NAME_FILE supplies NAME, so it read that bundle
as a TLS server certificate, found no SSL_KEY, and exited before serving.
The proxy falls back only on a strictly undefined value, so the empty
declaration stops it. Node still trusts the bundle through
NODE_EXTRA_CA_CERTS. Any other app here that implements the _FILE
convention will hit the same collision.
This repository has a ** tag protection although it publishes no tags.
Forgejo.Authority.check/2 reads trunk, then main, then the tag protections,
and requires all three of every provider-guarded project: the check proves that
nobody but binjovi-bot can move a ref here, which is a different claim from
"this project ships tags". Onboarding left the tag rule out on the second
reading, and binjovictl authority outline answered blocked · invalid_tag_protection_response while every release died 503 (2026-09-14). The
declaration is sean/binjovi's ForgejoServiceBindings; the scoped legacy-CR
absence read is sean/seanfarm's service-legacy-access.yaml.
Changes
Through the release train, like every other project:
binjovictl status outline
binjovictl builds outline
binjovictl release outline --build BUILD_ID --wait
Work pull requests target trunk. main is what ArgoCD syncs.