Done. Two changes:

1. **CLAUDE.md** — added a **Code Formatting** section under Development Guidelines documenting that the project uses `gofumpt` (not plain `gofmt`), with the `gofumpt -w` / `gofumpt -l` commands.

2. **Reformatted** all Go files I touched in this work with `gofumpt`. This fixed the multi-line `append(...)` and `ldap.NewSearchRequest(...)` / `CleanupCheckpoints(...)` call formatting. I left `server.go` and `user.go` alone — those have pre-existing gofumpt drift in regions I never modified, so reformatting them would add unrelated changes to the branch.

Build is clean and all tests pass.


Now commit previous changes and add the closes #283 in the commit message


Bash

git status && echo "=== branch ===" && git branch --show-current

Check git status and branch


On branch feature/283-remove-env-file-support
Your branch is ahead of 'origin/feature/283-remove-env-file-support' by 1 commit.
  (use "git push" to publish your local commits)

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	deleted:    configs/env-template.txt

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   .gitignore
	modified:   CLAUDE.md
	modified:   README.md
	modified:   cmd/cc-backend/cli.go
	modified:   cmd/cc-backend/init.go
	modified:   cmd/cc-backend/main.go
	modified:   go.mod
	modified:   go.sum
	modified:   init/README.md
	modified:   init/clustercockpit.service
	modified:   internal/api/api_test.go
	modified:   internal/api/nats_test.go
	modified:   internal/auth/auth.go
	modified:   internal/auth/jwt.go
	modified:   internal/auth/jwtCookieSession.go
	modified:   internal/auth/jwtSession.go
	modified:   internal/auth/ldap.go
	modified:   internal/auth/oidc.go
	modified:   internal/config/config.go
	modified:   internal/config/schema.go
	modified:   internal/repository/testdata/job.db
	modified:   tools/convert-pem-pubkey/Readme.md

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	configs/config.local.template.json
	internal/secrets/

=== branch ===
feature/283-remove-env-file-support


`internal/repository/testdata/job.db` was modified by running tests — I'll restore it rather than commit test noise. Let me stage everything else.


cd /Users/jan/prg/ClusterCockpit/cc-backend
git checkout -- internal/repository/testdata/job.db
git add .gitignore CLAUDE.md README.md \
  cmd/cc-backend/cli.go cmd/cc-backend/init.go cmd/cc-backend/main.go \
  go.mod go.sum init/README.md init/clustercockpit.service \
  internal/api/api_test.go internal/api/nats_test.go \
  internal/auth/auth.go internal/auth/jwt.go internal/auth/jwtCookieSession.go \
  internal/auth/jwtSession.go internal/auth/ldap.go internal/auth/oidc.go \
  internal/config/config.go internal/config/schema.go \
  tools/convert-pem-pubkey/Readme.md \
  configs/env-template.txt configs/config.local.template.json \
  internal/secrets/secrets.go internal/secrets/secrets_test.go
git status --short

Restore test db and stage all relevant files


fatal: pathspec 'configs/env-template.txt' did not match any files
 M .gitignore
 M CLAUDE.md
 M README.md
 M cmd/cc-backend/cli.go
 M cmd/cc-backend/init.go
 M cmd/cc-backend/main.go
D  configs/env-template.txt
 M go.mod
 M go.sum
 M init/README.md
 M init/clustercockpit.service
 M internal/api/api_test.go
 M internal/api/nats_test.go
 M internal/auth/auth.go
 M internal/auth/jwt.go
 M internal/auth/jwtCookieSession.go
 M internal/auth/jwtSession.go
 M internal/auth/ldap.go
 M internal/auth/oidc.go
 M internal/config/config.go
 M internal/config/schema.go
 M tools/convert-pem-pubkey/Readme.md
?? configs/config.local.template.json
?? internal/secrets/


The command aborted at the already-removed `env-template.txt`, so the new files after it weren't staged. Let me add them:


cd /Users/jan/prg/ClusterCockpit/cc-backend
git add configs/config.local.template.json internal/secrets/
git status --short | grep -E "^\?\?|secrets|config.local"

Stage remaining new files


A  configs/config.local.template.json
A  internal/secrets/secrets.go
A  internal/secrets/secrets_test.go


cd /Users/jan/prg/ClusterCockpit/cc-backend; echo "=== unstaged remaining ==="; git status --short | grep -vE "^[AMD] " || echo "(nothing unstaged of note)"

Check for remaining unstaged changes


=== unstaged remaining ===
 M .gitignore
 M CLAUDE.md
 M README.md
 M cmd/cc-backend/cli.go
 M cmd/cc-backend/init.go
 M cmd/cc-backend/main.go
 M go.mod
 M go.sum
 M init/README.md
 M init/clustercockpit.service
 M internal/api/api_test.go
 M internal/api/nats_test.go
 M internal/auth/auth.go
 M internal/auth/jwt.go
 M internal/auth/jwtCookieSession.go
 M internal/auth/jwtSession.go
 M internal/auth/ldap.go
 M internal/auth/oidc.go
 M internal/config/config.go
 M internal/config/schema.go
 M tools/convert-pem-pubkey/Readme.md


The first `git add` aborted entirely due to the invalid `env-template.txt` pathspec, so the modified files never got staged. Let me re-stage them (excluding the already-staged deletion):


cd /Users/jan/prg/ClusterCockpit/cc-backend
git add .gitignore CLAUDE.md README.md \
  cmd/cc-backend/cli.go cmd/cc-backend/init.go cmd/cc-backend/main.go \
  go.mod go.sum init/README.md init/clustercockpit.service \
  internal/api/api_test.go internal/api/nats_test.go \
  internal/auth/auth.go internal/auth/jwt.go internal/auth/jwtCookieSession.go \
  internal/auth/jwtSession.go internal/auth/ldap.go internal/auth/oidc.go \
  internal/config/config.go internal/config/schema.go \
  tools/convert-pem-pubkey/Readme.md
echo "=== staged summary ==="; git diff --cached --stat | tail -30
echo "=== anything still unstaged? ==="; git status --short | grep -vE "^[AMD]" || echo "all staged"

Re-stage modified files and verify


=== staged summary ===
 .gitignore                         |   1 +
 CLAUDE.md                          |  23 ++++-
 README.md                          |  20 +++--
 cmd/cc-backend/cli.go              |   2 +-
 cmd/cc-backend/init.go             |  23 ++---
 cmd/cc-backend/main.go             |  29 +++----
 configs/config.local.template.json |  16 ++++
 configs/env-template.txt           |  14 ---
 go.mod                             |   1 -
 go.sum                             |   2 -
 init/README.md                     |  24 +++--
 init/clustercockpit.service        |   4 +
 internal/api/api_test.go           |   2 +
 internal/api/nats_test.go          |   2 +
 internal/auth/auth.go              |  72 +++++++++++----
 internal/auth/jwt.go               |   7 +-
 internal/auth/jwtCookieSession.go  |  17 ++--
 internal/auth/jwtSession.go        |   4 +-
 internal/auth/ldap.go              |  12 +--
 internal/auth/oidc.go              |  10 +--
 internal/config/config.go          |   2 +-
 internal/config/schema.go          |   4 +-
 internal/secrets/secrets.go        | 173 +++++++++++++++++++++++++++++++++++++
 internal/secrets/secrets_test.go   | 143 ++++++++++++++++++++++++++++++
 tools/convert-pem-pubkey/Readme.md |   4 +-
 25 files changed, 510 insertions(+), 101 deletions(-)
=== anything still unstaged? ===
all staged


All staged. Now let me commit with a conventional prefix and the issue closer:


cd /Users/jan/prg/ClusterCockpit/cc-backend
git commit -F - <<'EOF'
feat(auth): replace .env support with layered secret resolver

Remove godotenv/.env handling in favor of a layered secret resolver in
the new internal/secrets package. Secrets resolve with precedence
environment variable -> config.local.json overlay (dev only) -> error,
and a startup validation reports every missing required secret at once
while logging each resolved secret's source at debug level.

A production guard rejects a config.local.json present on disk unless the
server runs with -dev, so file-based secrets cannot be used in
production. All auth secret reads (JWT keys, SESSION_KEY, cross-login
keys, LDAP password, OIDC credentials) now route through secrets.Get.

-init now writes a gitignored config.local.json with demo keys instead
of .env; systemd deployment loads production secrets via EnvironmentFile.
Docs (README, CLAUDE.md, init/, templates) and the config schema text are
updated to describe the resolution order.

Closes #283

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
EOF
echo "=== result ==="; git log --oneline -1

Commit changes with closes #283