diff --git a/reporter/main.go b/reporter/main.go index 69ef43d7..8ee0cefe 100644 --- a/reporter/main.go +++ b/reporter/main.go @@ -19,6 +19,7 @@ type ReportData struct { Hostname string `json:"hostname"` Timeout int `json:"timeout"` // if service receive after timeout second, its means client are offline Payload utils.ReportDataPayload `json:"payload"` + Secret *string `json:"secret,omitempty"` // optional secret for server status } var ( @@ -29,6 +30,7 @@ var ( Interval = flag.Int("interval", 5.0, "Input the INTERVAL, seconed") IsVnstat = flag.Bool("vnstat", false, "Use vnstat for traffic statistics, linux only") Verbose = flag.Bool("verbose", false, "Enable verbose logging to show full payload content") + Secret = flag.String("secret", "", "The server status secret, optional") ) var version = "1.0.0" @@ -77,6 +79,7 @@ func main() { Hostname: hostname, Timeout: interval * 10, Payload: utils.GetReportDataPaylod(interval, *IsVnstat), + Secret: Secret, } if *Mode == "udp" { diff --git a/scripts/start-tianji-container.sh b/scripts/start-tianji-container.sh index 09f10e61..cba03ab4 100644 --- a/scripts/start-tianji-container.sh +++ b/scripts/start-tianji-container.sh @@ -7,7 +7,11 @@ pnpm start:docker & sleep 10 # Start reporter with default workspace -/usr/local/bin/tianji-reporter --url "http://localhost:12345" --workspace "clnzoxcy10001vy2ohi4obbi0" --name "tianji-container" > /dev/null & +if [ -n "$SERVER_STATUS_SECRET" ]; then + /usr/local/bin/tianji-reporter --url "http://localhost:12345" --workspace "clnzoxcy10001vy2ohi4obbi0" --name "tianji-container" --secret "$SERVER_STATUS_SECRET" > /dev/null & +else + /usr/local/bin/tianji-reporter --url "http://localhost:12345" --workspace "clnzoxcy10001vy2ohi4obbi0" --name "tianji-container" > /dev/null & +fi # Wait for any process to exit wait -n diff --git a/src/client/components/server/AddServerStep.tsx b/src/client/components/server/AddServerStep.tsx index 3de9be40..b4968d99 100644 --- a/src/client/components/server/AddServerStep.tsx +++ b/src/client/components/server/AddServerStep.tsx @@ -40,7 +40,7 @@ export const AddServerStep: React.FC = React.memo(() => { } }); - const command = `./tianji-reporter --url ${window.location.origin} --workspace ${workspaceId}`; + const command = `./tianji-reporter --url ${window.location.origin} --workspace ${workspaceId} [--secret ]`; return ( { return Object.keys(serverMap).length; } -export async function getServerStatusHistory( +export async function getPublicServerStatusHistory( workspaceId: string, name: string ): Promise { - return await getServerHistoryFromCache(workspaceId, name); + const serverStatus = await getServerHistoryFromCache(workspaceId, name); + return serverStatus.map((item: ServerStatusInfo) => { + // we remove sensitive datas + const { secret, ...rest } = item; + const { top_cpu_processes, top_memory_processes, docker, ...restPayload } = + rest.payload; + return { + ...rest, + payload: restPayload, + }; + }); } diff --git a/src/server/router/serverStatus.ts b/src/server/router/serverStatus.ts index 4557661a..6de8e1e5 100644 --- a/src/server/router/serverStatus.ts +++ b/src/server/router/serverStatus.ts @@ -15,6 +15,7 @@ serverStatusRouter.post( header('x-tianji-report-version').isSemVer(), body('workspaceId').isString(), body('name').isString(), + body('secret').optional().isString(), body('hostname').isString(), body('timeout').optional().isInt(), body('payload').isObject() diff --git a/src/server/trpc/routers/serverStatus.ts b/src/server/trpc/routers/serverStatus.ts index 451f6df3..0996e306 100644 --- a/src/server/trpc/routers/serverStatus.ts +++ b/src/server/trpc/routers/serverStatus.ts @@ -7,7 +7,7 @@ import { } from '../trpc.js'; import { clearOfflineServerStatus, - getServerStatusHistory, + getPublicServerStatusHistory, getServerMapFromCache, } from '../../model/serverStatus.js'; import { OPENAPI_TAG } from '../../utils/const.js'; @@ -57,7 +57,17 @@ export const serverStatusRouter = router({ const filteredServerMap: Record = {}; serverNames.forEach((name) => { if (serverMap[name]) { - filteredServerMap[name] = serverMap[name]; + const { secret, ...rest } = serverMap[name]; + const { + top_cpu_processes, + top_memory_processes, + docker, + ...restPayload + } = rest.payload; + filteredServerMap[name] = { + ...rest, + payload: restPayload, + }; } }); @@ -84,6 +94,6 @@ export const serverStatusRouter = router({ ) .query(async ({ input }) => { const { workspaceId, name } = input; - return getServerStatusHistory(workspaceId, name); + return getPublicServerStatusHistory(workspaceId, name); }), }); diff --git a/src/server/utils/env.ts b/src/server/utils/env.ts index a38a66e1..3616d84c 100644 --- a/src/server/utils/env.ts +++ b/src/server/utils/env.ts @@ -137,6 +137,7 @@ export const env = { debugAIFeature: checkEnvTrusty(process.env.DEBUG_AI_FEATURE), // debug ai feature debugInsights: checkEnvTrusty(process.env.DEBUG_INSIGHTS) || isDev, // debug insights enableFunctionWorker: checkEnvTrusty(process.env.ENABLE_FUNCTION_WORKER), + serverStatusSecret: process.env.SERVER_STATUS_SECRET, // an optional secret for server monitoring }; export function checkEnvTrusty(env: string | undefined): boolean { diff --git a/src/types/server.ts b/src/types/server.ts index 39b7a7f3..7250a7bb 100644 --- a/src/types/server.ts +++ b/src/types/server.ts @@ -7,6 +7,7 @@ export interface ServerStatusInfo { timeout: number; updatedAt: number; payload: ServerStatusInfoPayload & ServerStatusRequestContext; + secret?: string; // optional secret } export interface ServerStatusInfoPayload { diff --git a/website/docs/install/environment.md b/website/docs/install/environment.md index d3455d97..d3dc6582 100644 --- a/website/docs/install/environment.md +++ b/website/docs/install/environment.md @@ -8,86 +8,92 @@ Tianji supports various environment variables to customize its behavior. You can ## Basic Configuration -| Variable | Description | Default | Example | -| --- | --- | --- | --- | -| `PORT` | Server port | `12345` | `3000` | -| `JWT_SECRET` | Secret for JWT tokens | Random Text | `your-secret-key` | -| `ALLOW_REGISTER` | Enable user registration | `false` | `true` | -| `ALLOW_OPENAPI` | Enable OpenAPI access | `true` | `false` | -| `WEBSITE_ID` | Website identifier | - | `your-website-id` | -| `DISABLE_AUTO_CLEAR` | Disable automatic data cleanup | `false` | `true` | -| `DISABLE_ACCESS_LOGS` | Disable access logs | `false` | `true` | -| `DB_DEBUG` | Enable database debugging | `false` | `true` | +| Variable | Description | Default | Example | +| --------------------- | ------------------------------ | ----------- | ----------------- | +| `PORT` | Server port | `12345` | `3000` | +| `JWT_SECRET` | Secret for JWT tokens | Random Text | `your-secret-key` | +| `ALLOW_REGISTER` | Enable user registration | `false` | `true` | +| `ALLOW_OPENAPI` | Enable OpenAPI access | `true` | `false` | +| `WEBSITE_ID` | Website identifier | - | `your-website-id` | +| `DISABLE_AUTO_CLEAR` | Disable automatic data cleanup | `false` | `true` | +| `DISABLE_ACCESS_LOGS` | Disable access logs | `false` | `true` | +| `DB_DEBUG` | Enable database debugging | `false` | `true` | ## Authentication -| Variable | Description | Default | Example | -| --- | --- | --- | --- | -| `DISABLE_ACCOUNT` | Disable account-based authentication | `false` | `true` | -| `AUTH_SECRET` | Authentication secret | MD5 of JWT secret | `your-auth-secret` | -| `AUTH_RESTRICT_EMAIL` | Restrict registration to specific email domains | - | `@example.com` | +| Variable | Description | Default | Example | +| --------------------- | ----------------------------------------------- | ----------------- | ------------------ | +| `DISABLE_ACCOUNT` | Disable account-based authentication | `false` | `true` | +| `AUTH_SECRET` | Authentication secret | MD5 of JWT secret | `your-auth-secret` | +| `AUTH_RESTRICT_EMAIL` | Restrict registration to specific email domains | - | `@example.com` | ### Email Authentication and Email Invitation -| Variable | Description | Default | Example | -| --- | --- | --- | --- | -| `EMAIL_SERVER` | SMTP server for email | - | `smtp://user:pass@smtp.example.com:587` | -| `EMAIL_FROM` | Email sender address | - | `noreply@example.com` | +| Variable | Description | Default | Example | +| -------------- | --------------------- | ------- | --------------------------------------- | +| `EMAIL_SERVER` | SMTP server for email | - | `smtp://user:pass@smtp.example.com:587` | +| `EMAIL_FROM` | Email sender address | - | `noreply@example.com` | ### GitHub Authentication -| Variable | Description | Default | Example | -| --- | --- | --- | --- | -| `AUTH_GITHUB_ID` | GitHub OAuth client ID | - | `your-github-client-id` | -| `AUTH_GITHUB_SECRET` | GitHub OAuth client secret | - | `your-github-client-secret` | +| Variable | Description | Default | Example | +| -------------------- | -------------------------- | ------- | --------------------------- | +| `AUTH_GITHUB_ID` | GitHub OAuth client ID | - | `your-github-client-id` | +| `AUTH_GITHUB_SECRET` | GitHub OAuth client secret | - | `your-github-client-secret` | ### Google Authentication -| Variable | Description | Default | Example | -| --- | --- | --- | --- | -| `AUTH_GOOGLE_ID` | Google OAuth client ID | - | `your-google-client-id` | -| `AUTH_GOOGLE_SECRET` | Google OAuth client secret | - | `your-google-client-secret` | +| Variable | Description | Default | Example | +| -------------------- | -------------------------- | ------- | --------------------------- | +| `AUTH_GOOGLE_ID` | Google OAuth client ID | - | `your-google-client-id` | +| `AUTH_GOOGLE_SECRET` | Google OAuth client secret | - | `your-google-client-secret` | ### Custom OAuth/OIDC Authentication -| Variable | Description | Default | Example | -| --- | --- | --- | --- | -| `AUTH_CUSTOM_ID` | Custom OAuth/OIDC client ID | - | `your-custom-client-id` | -| `AUTH_CUSTOM_SECRET` | Custom OAuth/OIDC client secret | - | `your-custom-client-secret` | -| `AUTH_CUSTOM_NAME` | Custom provider name | `Custom` | `Enterprise SSO` | -| `AUTH_CUSTOM_TYPE` | Authentication type | `oidc` | `oauth` | -| `AUTH_CUSTOM_ISSUER` | OIDC issuer URL | - | `https://auth.example.com` | +| Variable | Description | Default | Example | +| -------------------- | ------------------------------- | -------- | --------------------------- | +| `AUTH_CUSTOM_ID` | Custom OAuth/OIDC client ID | - | `your-custom-client-id` | +| `AUTH_CUSTOM_SECRET` | Custom OAuth/OIDC client secret | - | `your-custom-client-secret` | +| `AUTH_CUSTOM_NAME` | Custom provider name | `Custom` | `Enterprise SSO` | +| `AUTH_CUSTOM_TYPE` | Authentication type | `oidc` | `oauth` | +| `AUTH_CUSTOM_ISSUER` | OIDC issuer URL | - | `https://auth.example.com` | ## AI Features -| Variable | Description | Default | Example | -| --- | --- | --- | --- | -| `SHARED_OPENAI_API_KEY` | OpenAI API key | - | `your-openai-api-key` | -| `SHARED_OPENAI_BASE_URL` | Custom OpenAI API URL | - | `https://api.openai.com/v1` | -| `SHARED_OPENAI_MODEL_NAME` | OpenAI model to use | `gpt-4o` | `gpt-3.5-turbo` | -| `DEBUG_AI_FEATURE` | Debug AI features | `false` | `true` | +| Variable | Description | Default | Example | +| -------------------------- | --------------------- | -------- | --------------------------- | +| `SHARED_OPENAI_API_KEY` | OpenAI API key | - | `your-openai-api-key` | +| `SHARED_OPENAI_BASE_URL` | Custom OpenAI API URL | - | `https://api.openai.com/v1` | +| `SHARED_OPENAI_MODEL_NAME` | OpenAI model to use | `gpt-4o` | `gpt-3.5-turbo` | +| `DEBUG_AI_FEATURE` | Debug AI features | `false` | `true` | ## Sandbox Configuration -| Variable | Description | Default | Example | -| --- | --- | --- | --- | -| `USE_VM2` | Use VM2 for sandbox execution | `false` | `true` | -| `SANDBOX_MEMORY_LIMIT` | Memory limit for sandbox (MB) | `16` | `32` | -| `PUPPETEER_EXECUTABLE_PATH` | Custom path to Puppeteer executable | - | `/usr/bin/chromium` | +| Variable | Description | Default | Example | +| --------------------------- | ----------------------------------- | ------- | ------------------- | +| `USE_VM2` | Use VM2 for sandbox execution | `false` | `true` | +| `SANDBOX_MEMORY_LIMIT` | Memory limit for sandbox (MB) | `16` | `32` | +| `PUPPETEER_EXECUTABLE_PATH` | Custom path to Puppeteer executable | - | `/usr/bin/chromium` | ## Maps Integration -| Variable | Description | Default | Example | -| --- | --- | --- | --- | -| `AMAP_TOKEN` | AMap (Gaode) API token | - | `your-amap-token` | -| `MAPBOX_TOKEN` | Mapbox API token | - | `your-mapbox-token` | +| Variable | Description | Default | Example | +| -------------- | ---------------------- | ------- | ------------------- | +| `AMAP_TOKEN` | AMap (Gaode) API token | - | `your-amap-token` | +| `MAPBOX_TOKEN` | Mapbox API token | - | `your-mapbox-token` | ## Telemetry -| Variable | Description | Default | Example | -| --- | --- | --- | --- | -| `DISABLE_ANONYMOUS_TELEMETRY` | Disable anonymous telemetry | `false` | `true` | -| `CUSTOM_TRACKER_SCRIPT_NAME` | Custom tracker script name | - | `custom-tracker.js` | +| Variable | Description | Default | Example | +| ----------------------------- | --------------------------- | ------- | ------------------- | +| `DISABLE_ANONYMOUS_TELEMETRY` | Disable anonymous telemetry | `false` | `true` | +| `CUSTOM_TRACKER_SCRIPT_NAME` | Custom tracker script name | - | `custom-tracker.js` | + +## Server Status Reporting + +| Variable | Description | Default | Example | +| ---------------------- | ---------------------------------- | ------- | --------------------------- | +| `SERVER_STATUS_SECRET` | Secret for server status reporting | - | `your-server-status-secret` | ## Setting Environment Variables