Add API endpoint to retrieve sanitized server configuration

This commit is contained in:
2025-11-14 18:57:03 +01:00
parent 91d8a9008f
commit 623e258a2a
6 changed files with 779 additions and 1 deletions

View File

@@ -256,6 +256,34 @@ const docTemplate = `{
}
}
},
"/api/v1/config": {
"get": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "Returns the current server configuration (sanitized)",
"tags": [
"System"
],
"summary": "Get server configuration",
"responses": {
"200": {
"description": "Sanitized configuration",
"schema": {
"$ref": "#/definitions/config.AppConfig"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"type": "string"
}
}
}
}
},
"/api/v1/instances": {
"get": {
"security": [
@@ -1475,6 +1503,247 @@ const docTemplate = `{
}
},
"definitions": {
"config.AppConfig": {
"type": "object",
"properties": {
"auth": {
"$ref": "#/definitions/config.AuthConfig"
},
"backends": {
"$ref": "#/definitions/config.BackendConfig"
},
"buildTime": {
"type": "string"
},
"commitHash": {
"type": "string"
},
"instances": {
"$ref": "#/definitions/config.InstancesConfig"
},
"localNode": {
"type": "string"
},
"nodes": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/config.NodeConfig"
}
},
"server": {
"$ref": "#/definitions/config.ServerConfig"
},
"version": {
"type": "string"
}
}
},
"config.AuthConfig": {
"type": "object",
"properties": {
"inferenceKeys": {
"description": "List of keys for OpenAI compatible inference endpoints",
"type": "array",
"items": {
"type": "string"
}
},
"managementKeys": {
"description": "List of keys for management endpoints",
"type": "array",
"items": {
"type": "string"
}
},
"requireInferenceAuth": {
"description": "Require authentication for OpenAI compatible inference endpoints",
"type": "boolean"
},
"requireManagementAuth": {
"description": "Require authentication for management endpoints",
"type": "boolean"
}
}
},
"config.BackendConfig": {
"type": "object",
"properties": {
"llamaCpp": {
"$ref": "#/definitions/config.BackendSettings"
},
"mlx": {
"$ref": "#/definitions/config.BackendSettings"
},
"vllm": {
"$ref": "#/definitions/config.BackendSettings"
}
}
},
"config.BackendSettings": {
"type": "object",
"properties": {
"args": {
"type": "array",
"items": {
"type": "string"
}
},
"command": {
"type": "string"
},
"docker": {
"$ref": "#/definitions/config.DockerSettings"
},
"environment": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"responseHeaders": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
}
},
"config.DockerSettings": {
"type": "object",
"properties": {
"args": {
"type": "array",
"items": {
"type": "string"
}
},
"enabled": {
"type": "boolean"
},
"environment": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"image": {
"type": "string"
}
}
},
"config.InstancesConfig": {
"type": "object",
"properties": {
"autoCreateDirs": {
"description": "Automatically create the data directory if it doesn't exist",
"type": "boolean"
},
"dataDir": {
"description": "Directory where all llamactl data will be stored (instances.json, logs, etc.)",
"type": "string"
},
"defaultAutoRestart": {
"description": "Default auto-restart setting for new instances",
"type": "boolean"
},
"defaultMaxRestarts": {
"description": "Default max restarts for new instances",
"type": "integer"
},
"defaultOnDemandStart": {
"description": "Default on-demand start setting for new instances",
"type": "boolean"
},
"defaultRestartDelay": {
"description": "Default restart delay for new instances (in seconds)",
"type": "integer"
},
"enableLRUEviction": {
"description": "Enable LRU eviction for instance logs",
"type": "boolean"
},
"instancesDir": {
"description": "Instance config directory override",
"type": "string"
},
"logsDir": {
"description": "Logs directory override",
"type": "string"
},
"maxInstances": {
"description": "Maximum number of instances that can be created",
"type": "integer"
},
"maxRunningInstances": {
"description": "Maximum number of instances that can be running at the same time",
"type": "integer"
},
"onDemandStartTimeout": {
"description": "How long to wait for an instance to start on demand (in seconds)",
"type": "integer"
},
"portRange": {
"description": "Port range for instances (e.g., 8000,9000)",
"type": "array",
"items": {
"type": "integer"
}
},
"timeoutCheckInterval": {
"description": "Interval for checking instance timeouts (in minutes)",
"type": "integer"
}
}
},
"config.NodeConfig": {
"type": "object",
"properties": {
"address": {
"type": "string"
},
"apikey": {
"type": "string"
}
}
},
"config.ServerConfig": {
"type": "object",
"properties": {
"allowedHeaders": {
"description": "Allowed headers for CORS (e.g., \"Accept\", \"Authorization\", \"Content-Type\", \"X-CSRF-Token\")",
"type": "array",
"items": {
"type": "string"
}
},
"allowedOrigins": {
"description": "Allowed origins for CORS (e.g., \"http://localhost:3000\")",
"type": "array",
"items": {
"type": "string"
}
},
"enableSwagger": {
"description": "Enable Swagger UI for API documentation",
"type": "boolean"
},
"host": {
"description": "Server host to bind to",
"type": "string"
},
"port": {
"description": "Server port to bind to",
"type": "integer"
},
"responseHeaders": {
"description": "Response headers to send with responses",
"type": "object",
"additionalProperties": {
"type": "string"
}
}
}
},
"instance.Instance": {
"type": "object",
"properties": {
@@ -1494,6 +1763,13 @@ const docTemplate = `{
"description": "Auto restart",
"type": "boolean"
},
"command_override": {
"type": "string"
},
"docker_enabled": {
"description": "Execution context overrides",
"type": "boolean"
},
"environment": {
"description": "Environment variables",
"type": "object",

View File

@@ -249,6 +249,34 @@
}
}
},
"/api/v1/config": {
"get": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "Returns the current server configuration (sanitized)",
"tags": [
"System"
],
"summary": "Get server configuration",
"responses": {
"200": {
"description": "Sanitized configuration",
"schema": {
"$ref": "#/definitions/config.AppConfig"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"type": "string"
}
}
}
}
},
"/api/v1/instances": {
"get": {
"security": [
@@ -1468,6 +1496,247 @@
}
},
"definitions": {
"config.AppConfig": {
"type": "object",
"properties": {
"auth": {
"$ref": "#/definitions/config.AuthConfig"
},
"backends": {
"$ref": "#/definitions/config.BackendConfig"
},
"buildTime": {
"type": "string"
},
"commitHash": {
"type": "string"
},
"instances": {
"$ref": "#/definitions/config.InstancesConfig"
},
"localNode": {
"type": "string"
},
"nodes": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/config.NodeConfig"
}
},
"server": {
"$ref": "#/definitions/config.ServerConfig"
},
"version": {
"type": "string"
}
}
},
"config.AuthConfig": {
"type": "object",
"properties": {
"inferenceKeys": {
"description": "List of keys for OpenAI compatible inference endpoints",
"type": "array",
"items": {
"type": "string"
}
},
"managementKeys": {
"description": "List of keys for management endpoints",
"type": "array",
"items": {
"type": "string"
}
},
"requireInferenceAuth": {
"description": "Require authentication for OpenAI compatible inference endpoints",
"type": "boolean"
},
"requireManagementAuth": {
"description": "Require authentication for management endpoints",
"type": "boolean"
}
}
},
"config.BackendConfig": {
"type": "object",
"properties": {
"llamaCpp": {
"$ref": "#/definitions/config.BackendSettings"
},
"mlx": {
"$ref": "#/definitions/config.BackendSettings"
},
"vllm": {
"$ref": "#/definitions/config.BackendSettings"
}
}
},
"config.BackendSettings": {
"type": "object",
"properties": {
"args": {
"type": "array",
"items": {
"type": "string"
}
},
"command": {
"type": "string"
},
"docker": {
"$ref": "#/definitions/config.DockerSettings"
},
"environment": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"responseHeaders": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
}
},
"config.DockerSettings": {
"type": "object",
"properties": {
"args": {
"type": "array",
"items": {
"type": "string"
}
},
"enabled": {
"type": "boolean"
},
"environment": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"image": {
"type": "string"
}
}
},
"config.InstancesConfig": {
"type": "object",
"properties": {
"autoCreateDirs": {
"description": "Automatically create the data directory if it doesn't exist",
"type": "boolean"
},
"dataDir": {
"description": "Directory where all llamactl data will be stored (instances.json, logs, etc.)",
"type": "string"
},
"defaultAutoRestart": {
"description": "Default auto-restart setting for new instances",
"type": "boolean"
},
"defaultMaxRestarts": {
"description": "Default max restarts for new instances",
"type": "integer"
},
"defaultOnDemandStart": {
"description": "Default on-demand start setting for new instances",
"type": "boolean"
},
"defaultRestartDelay": {
"description": "Default restart delay for new instances (in seconds)",
"type": "integer"
},
"enableLRUEviction": {
"description": "Enable LRU eviction for instance logs",
"type": "boolean"
},
"instancesDir": {
"description": "Instance config directory override",
"type": "string"
},
"logsDir": {
"description": "Logs directory override",
"type": "string"
},
"maxInstances": {
"description": "Maximum number of instances that can be created",
"type": "integer"
},
"maxRunningInstances": {
"description": "Maximum number of instances that can be running at the same time",
"type": "integer"
},
"onDemandStartTimeout": {
"description": "How long to wait for an instance to start on demand (in seconds)",
"type": "integer"
},
"portRange": {
"description": "Port range for instances (e.g., 8000,9000)",
"type": "array",
"items": {
"type": "integer"
}
},
"timeoutCheckInterval": {
"description": "Interval for checking instance timeouts (in minutes)",
"type": "integer"
}
}
},
"config.NodeConfig": {
"type": "object",
"properties": {
"address": {
"type": "string"
},
"apikey": {
"type": "string"
}
}
},
"config.ServerConfig": {
"type": "object",
"properties": {
"allowedHeaders": {
"description": "Allowed headers for CORS (e.g., \"Accept\", \"Authorization\", \"Content-Type\", \"X-CSRF-Token\")",
"type": "array",
"items": {
"type": "string"
}
},
"allowedOrigins": {
"description": "Allowed origins for CORS (e.g., \"http://localhost:3000\")",
"type": "array",
"items": {
"type": "string"
}
},
"enableSwagger": {
"description": "Enable Swagger UI for API documentation",
"type": "boolean"
},
"host": {
"description": "Server host to bind to",
"type": "string"
},
"port": {
"description": "Server port to bind to",
"type": "integer"
},
"responseHeaders": {
"description": "Response headers to send with responses",
"type": "object",
"additionalProperties": {
"type": "string"
}
}
}
},
"instance.Instance": {
"type": "object",
"properties": {
@@ -1487,6 +1756,13 @@
"description": "Auto restart",
"type": "boolean"
},
"command_override": {
"type": "string"
},
"docker_enabled": {
"description": "Execution context overrides",
"type": "boolean"
},
"environment": {
"description": "Environment variables",
"type": "object",

View File

@@ -1,5 +1,173 @@
basePath: /api/v1
definitions:
config.AppConfig:
properties:
auth:
$ref: '#/definitions/config.AuthConfig'
backends:
$ref: '#/definitions/config.BackendConfig'
buildTime:
type: string
commitHash:
type: string
instances:
$ref: '#/definitions/config.InstancesConfig'
localNode:
type: string
nodes:
additionalProperties:
$ref: '#/definitions/config.NodeConfig'
type: object
server:
$ref: '#/definitions/config.ServerConfig'
version:
type: string
type: object
config.AuthConfig:
properties:
inferenceKeys:
description: List of keys for OpenAI compatible inference endpoints
items:
type: string
type: array
managementKeys:
description: List of keys for management endpoints
items:
type: string
type: array
requireInferenceAuth:
description: Require authentication for OpenAI compatible inference endpoints
type: boolean
requireManagementAuth:
description: Require authentication for management endpoints
type: boolean
type: object
config.BackendConfig:
properties:
llamaCpp:
$ref: '#/definitions/config.BackendSettings'
mlx:
$ref: '#/definitions/config.BackendSettings'
vllm:
$ref: '#/definitions/config.BackendSettings'
type: object
config.BackendSettings:
properties:
args:
items:
type: string
type: array
command:
type: string
docker:
$ref: '#/definitions/config.DockerSettings'
environment:
additionalProperties:
type: string
type: object
responseHeaders:
additionalProperties:
type: string
type: object
type: object
config.DockerSettings:
properties:
args:
items:
type: string
type: array
enabled:
type: boolean
environment:
additionalProperties:
type: string
type: object
image:
type: string
type: object
config.InstancesConfig:
properties:
autoCreateDirs:
description: Automatically create the data directory if it doesn't exist
type: boolean
dataDir:
description: Directory where all llamactl data will be stored (instances.json,
logs, etc.)
type: string
defaultAutoRestart:
description: Default auto-restart setting for new instances
type: boolean
defaultMaxRestarts:
description: Default max restarts for new instances
type: integer
defaultOnDemandStart:
description: Default on-demand start setting for new instances
type: boolean
defaultRestartDelay:
description: Default restart delay for new instances (in seconds)
type: integer
enableLRUEviction:
description: Enable LRU eviction for instance logs
type: boolean
instancesDir:
description: Instance config directory override
type: string
logsDir:
description: Logs directory override
type: string
maxInstances:
description: Maximum number of instances that can be created
type: integer
maxRunningInstances:
description: Maximum number of instances that can be running at the same time
type: integer
onDemandStartTimeout:
description: How long to wait for an instance to start on demand (in seconds)
type: integer
portRange:
description: Port range for instances (e.g., 8000,9000)
items:
type: integer
type: array
timeoutCheckInterval:
description: Interval for checking instance timeouts (in minutes)
type: integer
type: object
config.NodeConfig:
properties:
address:
type: string
apikey:
type: string
type: object
config.ServerConfig:
properties:
allowedHeaders:
description: Allowed headers for CORS (e.g., "Accept", "Authorization", "Content-Type",
"X-CSRF-Token")
items:
type: string
type: array
allowedOrigins:
description: Allowed origins for CORS (e.g., "http://localhost:3000")
items:
type: string
type: array
enableSwagger:
description: Enable Swagger UI for API documentation
type: boolean
host:
description: Server host to bind to
type: string
port:
description: Server port to bind to
type: integer
responseHeaders:
additionalProperties:
type: string
description: Response headers to send with responses
type: object
type: object
instance.Instance:
properties:
created:
@@ -13,6 +181,11 @@ definitions:
auto_restart:
description: Auto restart
type: boolean
command_override:
type: string
docker_enabled:
description: Execution context overrides
type: boolean
environment:
additionalProperties:
type: string
@@ -216,6 +389,23 @@ paths:
summary: Parse vllm serve command
tags:
- Backends
/api/v1/config:
get:
description: Returns the current server configuration (sanitized)
responses:
"200":
description: Sanitized configuration
schema:
$ref: '#/definitions/config.AppConfig'
"500":
description: Internal Server Error
schema:
type: string
security:
- ApiKeyAuth: []
summary: Get server configuration
tags:
- System
/api/v1/instances:
get:
description: Returns a list of all instances managed by the server

View File

@@ -610,3 +610,20 @@ func getDefaultConfigLocations() []string {
return locations
}
// SanitizedCopy returns a copy of the AppConfig with sensitive information removed
func (cfg *AppConfig) SanitizedCopy() AppConfig {
// Create a copy of the config
sanitized := *cfg
// Clear sensitive information
sanitized.Auth.InferenceKeys = []string{}
sanitized.Auth.ManagementKeys = []string{}
for nodeName, node := range sanitized.Nodes {
node.APIKey = ""
sanitized.Nodes[nodeName] = node
}
return sanitized
}

View File

@@ -20,3 +20,20 @@ func (h *Handler) VersionHandler() http.HandlerFunc {
writeText(w, http.StatusOK, versionInfo)
}
}
// ConfigHandler godoc
// @Summary Get server configuration
// @Description Returns the current server configuration (sanitized)
// @Tags System
// @Security ApiKeyAuth
// @Produces application/json
// @Success 200 {object} config.AppConfig "Sanitized configuration"
// @Failure 500 {string} string "Internal Server Error"
// @Router /api/v1/config [get]
func (h *Handler) ConfigHandler() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// Return a sanitized copy of the configuration
sanitizedConfig := h.cfg.SanitizedCopy()
writeJSON(w, http.StatusOK, sanitizedConfig)
}
}

View File

@@ -42,7 +42,9 @@ func SetupRouter(handler *Handler) *chi.Mux {
r.Use(authMiddleware.AuthMiddleware(KeyTypeManagement))
}
r.Get("/version", handler.VersionHandler()) // Get server version
r.Get("/version", handler.VersionHandler())
r.Get("/config", handler.ConfigHandler())
// Backend-specific endpoints
r.Route("/backends", func(r chi.Router) {