| 71 | } |
| 72 | |
| 73 | func Load() Config { |
| 74 | cfg := Config{ |
| 75 | Bind: "127.0.0.1:7878", |
| 76 | MaxAssetBytes: defaultMaxAssetBytes, |
| 77 | MaxNoteBytes: defaultMaxNoteBytes, |
| 78 | VaultFileMode: defaultVaultFileMode, |
| 79 | VaultDirMode: defaultVaultDirMode, |
| 80 | } |
| 81 | if raw, err := os.ReadFile(configFilePath()); err == nil { |
| 82 | var stored Config |
| 83 | if json.Unmarshal(raw, &stored) == nil { |
| 84 | if stored.VaultPath != "" { |
| 85 | cfg.VaultPath = stored.VaultPath |
| 86 | } |
| 87 | if stored.Bind != "" { |
| 88 | cfg.Bind = stored.Bind |
| 89 | } |
| 90 | if stored.BasePath != "" { |
| 91 | cfg.BasePath = stored.BasePath |
| 92 | } |
| 93 | if stored.AuthToken != "" { |
| 94 | cfg.AuthToken = stored.AuthToken |
| 95 | cfg.AuthTokenSource = AuthTokenSourceConfig |
| 96 | } |
| 97 | } |
| 98 | } |
| 99 | if v := os.Getenv("ZENNOTES_VAULT_PATH"); v != "" { |
| 100 | cfg.VaultPath = v |
| 101 | } |
| 102 | if v := os.Getenv("ZENNOTES_DEFAULT_VAULT_PATH"); v != "" { |
| 103 | cfg.DefaultVaultPath = v |
| 104 | } |
| 105 | cfg.BrowseRoots = parseListEnv("ZENNOTES_BROWSE_ROOTS") |
| 106 | cfg.AllowedOrigins = parseListEnv("ZENNOTES_ALLOWED_ORIGINS") |
| 107 | if v := os.Getenv("ZENNOTES_BIND"); v != "" { |
| 108 | cfg.Bind = v |
| 109 | } |
| 110 | if v := os.Getenv("ZENNOTES_BASE_PATH"); v != "" { |
| 111 | cfg.BasePath = v |
| 112 | } |
| 113 | cfg.BasePath = NormalizeBasePath(cfg.BasePath) |
| 114 | if v := os.Getenv("ZENNOTES_AUTH_TOKEN"); v != "" { |
| 115 | cfg.AuthToken = v |
| 116 | cfg.AuthTokenSource = AuthTokenSourceEnv |
| 117 | } else if path := os.Getenv("ZENNOTES_AUTH_TOKEN_FILE"); path != "" { |
| 118 | // The token comes from a file (the Docker/Kubernetes "*_FILE" secrets |
| 119 | // convention). A set-but-unreadable or empty file is a misconfiguration |
| 120 | // the user meant to work — surface it clearly instead of silently |
| 121 | // falling through to the generic "missing ZENNOTES_AUTH_TOKEN" error. |
| 122 | if raw, err := os.ReadFile(path); err != nil { |
| 123 | log.Printf("config: ZENNOTES_AUTH_TOKEN_FILE is set to %q but it could not be read: %v", path, err) |
| 124 | } else if token := strings.TrimSpace(string(raw)); token == "" { |
| 125 | log.Printf("config: ZENNOTES_AUTH_TOKEN_FILE %q is empty — no auth token loaded", path) |
| 126 | } else { |
| 127 | cfg.AuthToken = token |
| 128 | cfg.AuthTokenSource = AuthTokenSourceFile |
| 129 | } |
| 130 | } |