feat: generate a random prometheus token on startup

This commit is contained in:
MohamedBassem 2025-08-22 18:15:06 +03:00
parent f1662b820f
commit a64307e8ac
4 changed files with 11 additions and 37 deletions

View File

@ -12,7 +12,7 @@ The app is mainly configured by environment variables. All the used environment
| MEILI_MASTER_KEY | Only in Prod and if search is enabled | Not set | The master key configured for meilisearch. Not needed in development environment. Generate one with `openssl rand -base64 36 \| tr -dc 'A-Za-z0-9'` |
| MAX_ASSET_SIZE_MB | No | 50 | Sets the maximum allowed asset size (in MB) to be uploaded |
| DISABLE_NEW_RELEASE_CHECK | No | false | If set to true, latest release check will be disabled in the admin panel. |
| PROMETHEUS_AUTH_TOKEN | No | Not set | If set, will enable a prometheus metrics endpoint at `/api/metrics`. This endpoint will require this token being passed in the Authorization header as a Bearer token. If not set, that endpoint will return 404. |
| PROMETHEUS_AUTH_TOKEN | No | Random | Enable a prometheus metrics endpoint at `/api/metrics`. This endpoint will require this token being passed in the Authorization header as a Bearer token. If not set, a new random token is generated everytime at startup. |
| RATE_LIMITING_ENABLED | No | false | If set to true, API rate limiting will be enabled. |
| DB_WAL_MODE | No | false | Enables WAL mode for the sqlite database. This should improve the performance of the database. There's no reason why you shouldn't set this to true unless you're running the db on a network attached drive. This will become the default at some time in the future. |
| SEARCH_NUM_WORKERS | No | 1 | Number of concurrent workers for search indexing tasks. Increase this if you have a high volume of content being indexed for search. |

View File

@ -1,33 +0,0 @@
import { createMiddleware } from "hono/factory";
import { HTTPException } from "hono/http-exception";
import serverConfig from "@karakeep/shared/config";
export const prometheusAuthMiddleware = createMiddleware(async (c, next) => {
const { metricsToken } = serverConfig.prometheus;
// If no token is configured, deny access (safe default)
if (!metricsToken) {
throw new HTTPException(404, {
message: "Not Found",
});
}
const auth = c.req.header("Authorization");
if (!auth || !auth.startsWith("Bearer ")) {
throw new HTTPException(401, {
message: "Unauthorized",
});
}
const token = auth.slice(7); // Remove "Bearer " prefix
if (token !== metricsToken) {
throw new HTTPException(401, {
message: "Unauthorized",
});
}
await next();
});

View File

@ -3,15 +3,20 @@ import "@karakeep/trpc/stats";
import { prometheus } from "@hono/prometheus";
import { Hono } from "hono";
import { bearerAuth } from "hono/bearer-auth";
import { register } from "prom-client";
import { prometheusAuthMiddleware } from "../middlewares/prometheusAuth";
import serverConfig from "@karakeep/shared/config";
export const { printMetrics, registerMetrics } = prometheus({
registry: register,
prefix: "karakeep_",
});
const app = new Hono().get("/", prometheusAuthMiddleware, printMetrics);
const app = new Hono().get(
"/",
bearerAuth({ token: serverConfig.prometheus.metricsToken }),
printMetrics,
);
export default app;

View File

@ -1,3 +1,4 @@
import crypto from "node:crypto";
import path from "path";
import { z } from "zod";
@ -278,7 +279,8 @@ const serverConfigSchema = allEnv.transform((val, ctx) => {
},
},
prometheus: {
metricsToken: val.PROMETHEUS_AUTH_TOKEN,
metricsToken:
val.PROMETHEUS_AUTH_TOKEN ?? crypto.randomBytes(64).toString("hex"),
},
rateLimiting: {
enabled: val.RATE_LIMITING_ENABLED,