diff --git a/doc/openobserve.md b/doc/openobserve.md new file mode 100644 index 00000000..8e527058 --- /dev/null +++ b/doc/openobserve.md @@ -0,0 +1,62 @@ +# OpenObserve + +[OpenObserve](https://openobserve.ai) is an observability platform for logs, metrics and traces. It ships with a web UI, and stores data on local disk in single-node mode. + +## Getting Started + +```nix +# In `perSystem.process-compose.` +{ + services.openobserve."oo1".enable = true; +} +``` + +The web UI is then served at , and the ingestion and query APIs live under the same address. Log in with: + +| | | +| -------- | -------------------------- | +| Email | `admin@services-flake.com` | +| Password | `admin` | + +{#tips} + +## Tips & Tricks + +{#credentials} + +### Changing the root user + +OpenObserve refuses to start without root credentials, so this service supplies the defaults above. Override them — or set any other [`ZO_*` variable](https://openobserve.ai/docs/environment-variables/) — through `extraEnvironment`, which is merged after the module's own defaults: + +```nix +{ + services.openobserve."oo1" = { + enable = true; + extraEnvironment = { + ZO_ROOT_USER_EMAIL = "me@example.com"; + ZO_ROOT_USER_PASSWORD = "Somethingelse#456"; + }; + }; +} +``` + +The email must match OpenObserve's address pattern. If it doesn't — or if either variable is unset — the process panics on startup with a message naming both. + +{#telemetry} + +### Telemetry + +OpenObserve reports anonymous usage data by default. This service disables it. To turn it back on: + +```nix +{ + services.openobserve."oo1" = { + enable = true; + extraEnvironment.ZO_TELEMETRY = "true"; + }; +} +``` + +## Usage example + + diff --git a/doc/services.md b/doc/services.md index d4a9e57b..9a37f3be 100644 --- a/doc/services.md +++ b/doc/services.md @@ -26,6 +26,7 @@ short-title: Services - [[nginx]]# - [[ollama]]# - [[open-webui]]# +- [[openobserve]]# - [[phpfpm]]# - [[plantuml]]# - [[postgresql]]# diff --git a/nix/services/default.nix b/nix/services/default.nix index d0c18518..6ffe2123 100644 --- a/nix/services/default.nix +++ b/nix/services/default.nix @@ -15,6 +15,7 @@ in ./ollama.nix ./postgres ./open-webui.nix + ./openobserve.nix ./plantuml.nix ./redis-cluster.nix ./redis.nix diff --git a/nix/services/openobserve.nix b/nix/services/openobserve.nix new file mode 100644 index 00000000..65f2a7a2 --- /dev/null +++ b/nix/services/openobserve.nix @@ -0,0 +1,98 @@ +{ pkgs +, lib +, name +, config +, ... +}: +let + inherit (lib) types; +in +{ + options = { + package = lib.mkPackageOption pkgs "openobserve" { }; + + httpAddress = lib.mkOption { + type = types.str; + default = "127.0.0.1"; + description = "The address the HTTP server, which serves both the API and the web UI binds to"; + }; + + httpPort = lib.mkOption { + type = types.port; + default = 5080; + description = "The port the HTTP server, which serves both the API and the web UI listens on"; + }; + + grpcPort = lib.mkOption { + type = types.port; + default = 5081; + description = "The port the gRPC server listens on"; + }; + + extraEnvironment = lib.mkOption { + type = types.attrsOf types.str; + default = { }; + example = lib.literalExpression '' + { + ZO_ROOT_USER_PASSWORD = "Somethingelse#456"; + ZO_COMPACT_ENABLED = "false"; + } + ''; + description = '' + Extra `ZO_*` environment variables for OpenObserve. + + These are merged last, so they override the defaults this module sets, + including the root user credentials and telemetry. + + See for the full + list. + ''; + }; + }; + + config.outputs.settings.processes."${name}" = { + environment = { + ZO_DATA_DIR = config.dataDir; + ZO_LOCAL_MODE = "true"; + ZO_TELEMETRY = "false"; + # OpenObserve has no fallback for these and panics on startup without + # them, so the module supplies working defaults to keep `enable = true` + # sufficient. Override via `extraEnvironment`. + ZO_ROOT_USER_EMAIL = "admin@services-flake.com"; + ZO_ROOT_USER_PASSWORD = "admin"; + ZO_HTTP_ADDR = config.httpAddress; + ZO_HTTP_PORT = toString config.httpPort; + ZO_GRPC_PORT = toString config.grpcPort; + } + // config.extraEnvironment; + + command = pkgs.writeShellApplication { + name = "start-openobserve"; + runtimeInputs = [ config.package ]; + text = '' + mkdir -p ${lib.escapeShellArg config.dataDir} + exec openobserve + ''; + }; + + readiness_probe = { + http_get = { + host = config.httpAddress; + port = config.httpPort; + path = "/healthz"; + }; + initial_delay_seconds = 2; + period_seconds = 5; + timeout_seconds = 4; + success_threshold = 1; + # First boot creates the sqlite schema and its indexes before the HTTP + # listener accepts connections, so allow more failures than usual. + failure_threshold = 10; + }; + + availability = { + restart = "on_failure"; + max_restarts = 5; + }; + }; +} diff --git a/nix/services/openobserve_test.nix b/nix/services/openobserve_test.nix new file mode 100644 index 00000000..7bd25082 --- /dev/null +++ b/nix/services/openobserve_test.nix @@ -0,0 +1,24 @@ +{ pkgs, config, ... }: +{ + services.openobserve."oo1".enable = true; + + settings.processes.test = + let + cfg = config.services.openobserve."oo1"; + in + { + command = pkgs.writeShellApplication { + name = "openobserve-test"; + runtimeInputs = [ + pkgs.curl + pkgs.jq + ]; + text = '' + curl -sSfN "http://${cfg.httpAddress}:${toString cfg.httpPort}/healthz" \ + | jq -e '.status == "ok"' + ''; + }; + + depends_on."oo1".condition = "process_healthy"; + }; +} diff --git a/test/flake.nix b/test/flake.nix index dc8c60e4..6558c77f 100644 --- a/test/flake.nix +++ b/test/flake.nix @@ -54,6 +54,7 @@ "${inputs.services-flake}/nix/services/nats-server_test.nix" "${inputs.services-flake}/nix/services/nginx/nginx_test.nix" "${inputs.services-flake}/nix/services/ollama_test.nix" + "${inputs.services-flake}/nix/services/openobserve_test.nix" "${inputs.services-flake}/nix/services/pgadmin_test.nix" "${inputs.services-flake}/nix/services/plantuml_test.nix" "${inputs.services-flake}/nix/services/postgres/postgres_test.nix"