### Start server with provisioning API TLS environment variables Source: https://xolo-gateway.org/main/administration/provisioning/provisioning Starts the server with the provisioning API enabled and TLS configured using the development PKI. Requires the environment variables XOLO_SECRET_KEY, XOLO_PROVISIONNING_API_ENABLED, XOLO_PROVISIONNING_API_TLS_CERT_FILE, XOLO_PROVISIONNING_API_TLS_KEY_FILE, and XOLO_PROVISIONNING_API_TLS_CLIENT_CA_FILE. The secret key is generated with openssl rand. ```bash XOLO_SECRET_KEY=$(openssl rand -hex 32) \ XOLO_PROVISIONNING_API_ENABLED=true \ XOLO_PROVISIONNING_API_TLS_CERT_FILE=dev-pki/server.crt \ XOLO_PROVISIONNING_API_TLS_KEY_FILE=dev-pki/server.key \ XOLO_PROVISIONNING_API_TLS_CLIENT_CA_FILE=dev-pki/ca.crt \ bin/server ``` -------------------------------- ### PreRequest access control example Source: https://xolo-gateway.org/main/administration/installation/plugins Example PreRequest implementation that checks time-based access using a parsed config. If not allowed, it returns a rejection reason; otherwise it allows the request. ```go func (p *Plugin) PreRequest(_ context.Context, in *proto.PreRequestInput) (*proto.PreRequestOutput, error) { cfg, err := parseConfig(in.GetCtx().GetConfigJson()) if err != nil { return &proto.PreRequestOutput{Allowed: false, RejectionReason: "config error"}, nil } allowed, _ := isAllowed(time.Now(), cfg) if !allowed { return &proto.PreRequestOutput{ Allowed: false, RejectionReason: "Accès refusé : hors des plages horaires autorisées.", }, nil } return &proto.PreRequestOutput{Allowed: true}, nil } ``` -------------------------------- ### Use structured logging Source: https://xolo-gateway.org/main/administration/installation/plugins Example of using structured logging with slog to log selected model and power level. ```go slog.InfoContext(ctx, "my-plugin: selected model", slog.String("model", selected), slog.Float64("power_level", powerLevel), ) ``` -------------------------------- ### Serve a plugin with and without HTTP UI Source: https://xolo-gateway.org/main/administration/installation/plugins Use pluginsdk.Serve to start a plugin without an HTTP UI, or pluginsdk.ServeWithUI to include an HTTP UI (config editor, analytics). The second variant takes a plugin name and a UI handler. ```go // Without HTTP UI func main() { pluginsdk.Serve(&Plugin{}) } // With HTTP UI (config editor, analytics…) func main() { pluginsdk.ServeWithUI(&Plugin{}, "my-plugin", newUIHandler()) } ``` -------------------------------- ### Parse config defensively Source: https://xolo-gateway.org/main/administration/installation/plugins Example of parsing plugin config defensively, logging a warning and failing open on error. ```go cfg, err := ParseConfig(in.GetCtx().GetConfigJson()) if err != nil { slog.WarnContext(ctx, "my-plugin: bad config, skipping") return &proto.PreRequestOutput{Allowed: true}, nil // fail open } ``` -------------------------------- ### eventql query example with selector and pipeline Source: https://xolo-gateway.org/main/concepts/eventql Shows the general syntax: a label selector followed by a pipeline of filters. The selector filters on labels (type, severity) and the pipeline filters on attributes and message. ```eventql {type="auth.login.failed", severity=~"warning|error"} | provider="oidc" |~ "timeout" ``` -------------------------------- ### ConfigSchema JSON example Source: https://xolo-gateway.org/main/administration/installation/plugins Example of a ConfigSchema JSON Schema (draft-07) for plugin configuration. It requires a 'timezone' property with a string type and a title/description in French. ```json const configSchemaJSON = `{ "type": "object", "required": ["timezone"], "properties": { "timezone": { "type": "string", "title": "Fuseau horaire", "description": "Identifiant IANA, ex: Europe/Paris, UTC" } } }` ``` -------------------------------- ### Implement Initialize to access host services Source: https://xolo-gateway.org/main/administration/installation/plugins Implement the Initialize method to receive the host service broker. Dial the broker using req.HostServiceBrokerId and create a XoloHostServiceClient to access host methods like GetConfig, SaveConfig, ListModels, GetSecret, SetSecret, DeleteSecret, and EmitEvent. ```go func (p *Plugin) Initialize(ctx context.Context, req *proto.InitializeRequest) (*proto.InitializeResponse, error) { conn, err := p.broker.Dial(req.HostServiceBrokerId) if err != nil { return nil, err } p.host = proto.NewXoloHostServiceClient(conn) return &proto.InitializeResponse{}, nil } ``` -------------------------------- ### curl Example for Chat Completions Source: https://xolo-gateway.org/main/administration/organisation/application/application Example curl command to POST to the chat completions endpoint using an API token. Replace the token and model as needed. ```bash curl -X POST https://xolo.example.com/v1/chat/completions \ -H "Authorization: Bearer xlo_abc123def456" \ -H "Content-Type: application/json" \ -d '{ "model": "mon-org/gpt-4o", "messages": [{"role": "user", "content": "Hello!"}] }' ``` -------------------------------- ### Démarrage rapide avec Docker Source: https://xolo-gateway.org/main Lance une instance locale de Xolo avec Docker, puis effectue un premier appel à l'API de chat. L'instance écoute sur le port 8080. L'appel nécessite une clé API (XOLO_KEY) et une organisation déjà créée. ```bash $ docker run -p 8080:8080 \ ghcr.io/xolo-gateway/xolo:latest # puis, une fois l'organisation créée $ curl localhost:8080/v1/chat/completions \ -H "Authorization: Bearer $XOLO_KEY" \ -d '{"model":"gpt-4o-mini","messages":[…]}' ``` -------------------------------- ### Attribute filter pipeline example Source: https://xolo-gateway.org/main/concepts/eventql Attribute filters are introduced by a vertical bar followed by an attribute name, operator, and value. This example filters events of type 'proxy.request' with model 'gpt-4o' and provider matching 'open.*'. ```eventql {type="proxy.request"} | model="gpt-4o" | provider=~"open.*" ``` -------------------------------- ### Line filter pipeline example Source: https://xolo-gateway.org/main/concepts/eventql Line filters apply to the message field and are not preceded by an attribute name. This example selects events of type 'auth.login.failed' whose message matches the regex 'timeout|refused' and does not contain 'retrying'. ```eventql {type="auth.login.failed"} |~ "timeout|refused" != "retrying" ``` -------------------------------- ### Configure named OIDC providers via XOLO_HTTP_AUTHN_OIDC_* environment variables Source: https://xolo-gateway.org/main/administration/installation/configuration Lists OIDC provider identifiers in XOLO_HTTP_AUTHN_OIDC_PROVIDERS, then defines each provider using a dedicated prefix (e.g., XOLO_HTTP_AUTHN_OIDC_PROVIDER_KEYCLOAK_*). The discovery URL is mandatory; Xolo downloads it at startup with a 10-second timeout and refuses to start if it is inaccessible or incomplete. The document must include issuer, authorization_endpoint, token_endpoint, and jwks_uri; additional endpoints must be absolute http/https URLs. ```env XOLO_HTTP_AUTHN_OIDC_PROVIDERS=keycloak,auth0 XOLO_HTTP_AUTHN_OIDC_PROVIDER_KEYCLOAK_DISCOVERY_URL=https://idp.example.com/.well-known/openid-configuration XOLO_HTTP_AUTHN_OIDC_PROVIDER_KEYCLOAK_KEY=xolo XOLO_HTTP_AUTHN_OIDC_PROVIDER_KEYCLOAK_SECRET=change-me XOLO_HTTP_AUTHN_OIDC_PROVIDER_KEYCLOAK_LABEL="Mon SSO" XOLO_HTTP_AUTHN_OIDC_PROVIDER_KEYCLOAK_SCOPES=openid,profile,email ``` -------------------------------- ### Error response envelope example Source: https://xolo-gateway.org/main/administration/provisioning/provisioning Shows the standard error envelope returned by all API errors. The 'code' field contains a machine-readable error code, and 'message' provides a human-readable description. This example illustrates a conflict error when creating an organization with a duplicate slug. ```json {"error": {"code": "conflict", "message": "organization with slug \"acme\" already exists in this tenant (id: c9m2…)"}} ``` -------------------------------- ### Commandes de développement et de test (make, go test) Source: https://xolo-gateway.org/main/projet/contribuer Commandes pour construire le serveur, générer le code (templ + tailwind), lancer le serveur de développement avec rechargement à chaud, exécuter les tests unitaires (SQLite seul) et les tests d'intégration (SQLite et PostgreSQL, Docker requis). ```bash make build # construit bin/server make generate # templ + tailwind ; requis après édition de fichiers .templ make watch # serveur de dev avec rechargement à chaud (utilise .env) go test ./... # tests unitaires, SQLite seul, pas besoin de Docker make test-integration # suite des stores sur SQLite ET PostgreSQL (Docker requis) ``` -------------------------------- ### Plugin file structure Source: https://xolo-gateway.org/main/administration/installation/plugins Recommended layout for a Xolo plugin, showing main.go, plugin.go, config.go, and ui_handler.go files. ```text my-plugin/ ├── main.go # pluginsdk.Serve(&Plugin{}) or ServeWithUI ├── plugin.go # Describe + capability methods ├── config.go # Config struct, JSON schema, parser └── ui_handler.go # HTTP UI handlers (if using ServeWithUI) ``` -------------------------------- ### Docker run avec variables d'environnement Source: https://xolo-gateway.org/main/administration/installation Commande pour lancer le conteneur Docker de Xolo avec les variables d'environnement requises, notamment XOLO_SECRET_KEY, XOLO_HTTP_BASE_URL et XOLO_HTTP_AUTHN_DEFAULT_ADMINS. Le volume xolo-data est monté sur /data pour persister la base de données. ```bash XOLO_SECRET_KEY=$(openssl rand -hex 32) # Devrait rester stable dans le temps docker run -d \ --name xolo \ -p 3002:3002 \ -e XOLO_SECRET_KEY="${XOLO_SECRET_KEY}" \ -e XOLO_HTTP_BASE_URL=https://xolo.example.com \ -e XOLO_HTTP_AUTHN_DEFAULT_ADMINS=admin@example.com \ -v xolo-data:/data \ ghcr.io/xolo-gateway/xolo-server:latest ```