From f7386e174128f3cf8227551e99148e1bf581ecde Mon Sep 17 00:00:00 2001 From: Briquet Date: Mon, 14 Sep 2026 18:46:15 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A7(dev)=20add=20a=20devenv=20shell=20?= =?UTF-8?q?for=20nix-based=20workstations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the minimal requirements to build and run the project locally on NixOS - `devenv update` update devenv using NixOS 26.05 stable repositories - `devenv shell` activates the devenv - `devenv --profile ` shell uses additional packages when activated (profile=agent|summary|k8s) --- .gitignore | 3 + devenv.lock | 47 ++++++++++ devenv.nix | 258 ++++++++++++++++++++++++++++++++++++++++++++++++++++ devenv.yaml | 5 + 4 files changed, 313 insertions(+) create mode 100644 devenv.lock create mode 100644 devenv.nix create mode 100644 devenv.yaml diff --git a/.gitignore b/.gitignore index 4f5dbf293..0fb07cfaf 100644 --- a/.gitignore +++ b/.gitignore @@ -86,3 +86,6 @@ docker/livekit/rootCA.pem # Frontend rollup-plugin-visualizer /src/frontend/rollup-plugin-visualizer/* + +# NixOS +.devenv diff --git a/devenv.lock b/devenv.lock new file mode 100644 index 000000000..81f597ef3 --- /dev/null +++ b/devenv.lock @@ -0,0 +1,47 @@ +{ + "nodes": { + "devenv": { + "locked": { + "dir": "src/modules", + "lastModified": 1778705847, + "narHash": "sha256-EQnZCy7r4VMO6KDoytxHBa0mFbM1D9g1kaDfs/s0YZA=", + "ref": "refs/tags/v2.1.2", + "rev": "ea3d94ac9d6bf6a1313773170122ca4e2ef5a0be", + "revCount": 6569, + "type": "git", + "url": "https://github.com/cachix/devenv" + }, + "original": { + "dir": "src/modules", + "ref": "refs/tags/v2.1.2", + "type": "git", + "url": "https://github.com/cachix/devenv" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1789542786, + "narHash": "sha256-ajQuqcxnj6RYnwCjA/9FTCnrdR2+BDzstE8UembXf60=", + "ref": "nixos-26.05", + "rev": "4c7870105e7f1fdf9c48688c8d7efc21abf0688a", + "shallow": true, + "type": "git", + "url": "https://github.com/NixOS/nixpkgs" + }, + "original": { + "ref": "nixos-26.05", + "shallow": true, + "type": "git", + "url": "https://github.com/NixOS/nixpkgs" + } + }, + "root": { + "inputs": { + "devenv": "devenv", + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} \ No newline at end of file diff --git a/devenv.nix b/devenv.nix new file mode 100644 index 000000000..060a29396 --- /dev/null +++ b/devenv.nix @@ -0,0 +1,258 @@ +# ============================================================================= +# devenv.nix — La Suite Meet ("Visio") developer environment +# ============================================================================= +{ + pkgs, + lib, + config, + ... +}: + +let + python = pkgs.python313; + nodejs = pkgs.nodejs_22; + + backendDir = "src/backend"; + agentsDir = "src/agents"; + summaryDir = "src/summary"; + frontendDir = "src/frontend"; + + readDotEnv = + file: + let + lines = lib.splitString "\n" (builtins.readFile file); + unquote = + v: + let + len = builtins.stringLength v; + in + if len >= 2 && lib.hasPrefix "\"" v && lib.hasSuffix "\"" v then + builtins.substring 1 (len - 2) v + else if len >= 2 && lib.hasPrefix "'" v && lib.hasSuffix "'" v then + builtins.substring 1 (len - 2) v + else + v; + parseLine = + line: + let + m = builtins.match "[ \t]*([A-Za-z_][A-Za-z0-9_]*)[ \t]*=[ \t]*(.*)" line; + in + if m == null then null else { name = builtins.elemAt m 0; value = unquote (builtins.elemAt m 1); }; + in + builtins.listToAttrs (builtins.filter (x: x != null) (map parseLine lines)); + + # Reuse existing .env + dotEnv = + (readDotEnv ./env.d/development/common.dist) + // (readDotEnv ./env.d/development/postgresql.dist); + + sharedEnv = builtins.removeAttrs dotEnv [ "PYTHONPATH" ]; # only makes sense inside the backend container. +in +{ + options.meet = { + agents.enable = lib.mkEnableOption "tooling for the LiveKit agents in src/agents"; + summary.enable = lib.mkEnableOption "tooling for the summary service in src/summary"; + k8s.enable = lib.mkEnableOption "Kubernetes dev utilities"; + }; + + config = { + # Profile can be activated with devenv --profile shell + profiles = { + agents.module = { + meet.agents.enable = true; + }; + summary.module = { + meet.summary.enable = true; + }; + k8s.module = { + meet.k8s.enable = true; + }; + }; + languages.python = { + enable = true; + package = python; + directory = backendDir; + manylinux.enable = pkgs.stdenv.hostPlatform.isLinux; + + libraries = [ + "${config.devenv.dotfile}/profile" + pkgs.file + pkgs.zlib + pkgs.libffi + pkgs.openssl + ]; + + uv.enable = true; + uv.sync.enable = false; + venv.enable = false; + lsp.enable = true; + }; + + languages.javascript = { + enable = true; + package = nodejs; + directory = frontendDir; + + npm.enable = true; + yarn.enable = true; + corepack.enable = false; + }; + + languages.typescript.enable = false; + languages.nix.enable = true; + + packages = + with pkgs; + [ + gnumake + file + shared-mime-info + gettext + postgresql_16 + git + curl + jq + podman + podman-compose + docker-client + ] + + # -- LiveKit agents + ++ lib.optionals config.meet.agents.enable [ + glib + portaudio + livekit-cli + ] + + # -- summary service + ++ lib.optionals config.meet.summary.enable [ + redis + ] + + # -- Kubernetes tools + ++ lib.optionals config.meet.k8s.enable [ + kubectl + kubernetes-helm + helmfile + tilt + kind + mkcert + ]; + + env = sharedEnv // { + UV_LINK_MODE = "copy"; + + PYTHONDONTWRITEBYTECODE = "1"; + PYTHONUNBUFFERED = "1"; + + UV_PROJECT_ENVIRONMENT = lib.mkForce ".venv"; + + COMPOSE_PROJECT_NAME = "meet"; + + DJANGO_DATA_DIR = "${config.devenv.root}/data"; + + # Database / Pgsql + DB_HOST = "127.0.0.1"; + DB_PORT = "15432"; + PGHOST = "127.0.0.1"; + PGPORT = "15432"; + PGDATABASE = sharedEnv.DB_NAME; + PGUSER = sharedEnv.DB_USER; + PGPASSWORD = sharedEnv.DB_PASSWORD; + + REDIS_URL = "redis://127.0.0.1:6379/1"; + CELERY_BROKER_URL = "redis://127.0.0.1:6379/0"; + + # S3 / MinIO + AWS_S3_ENDPOINT_URL = "http://127.0.0.1:9000"; + + # OIDC + OIDC_OP_JWKS_ENDPOINT = "http://localhost:8083/realms/meet/protocol/openid-connect/certs"; + OIDC_OP_TOKEN_ENDPOINT = "http://localhost:8083/realms/meet/protocol/openid-connect/token"; + OIDC_OP_USER_ENDPOINT = "http://localhost:8083/realms/meet/protocol/openid-connect/userinfo"; + OIDC_OP_INTROSPECTION_ENDPOINT = "http://localhost:8083/realms/meet/protocol/openid-connect/token/introspect"; + + # summary service + SUMMARY_SERVICE_ENDPOINT = "http://127.0.0.1:8001/api/v2/async-jobs/transcribe/"; + SUMMARY_SERVICE_VERSION = "2"; + + # Mail + DJANGO_EMAIL_HOST = "127.0.0.1"; + }; + + scripts = { + + meet-venv = { + description = "Create/refresh meet uv virtualenvs for backend, agents and summary"; + exec = '' + set -euo pipefail + cd "$DEVENV_ROOT" + + echo "==> ${backendDir} (uv sync --locked, dependency-groups)" + ( cd "${backendDir}" && uv sync --locked --all-groups ) + + echo "==> ${agentsDir} (uv sync --locked --all-extras)" + ( cd "${agentsDir}" && uv sync --locked --all-extras ) + + echo "==> ${summaryDir} (uv sync --locked --all-extras)" + ( cd "${summaryDir}" && uv sync --locked --all-extras ) + + echo + echo "Synced the following virtualenvs successfully:" + echo " ${backendDir}/.venv" + echo " ${agentsDir}/.venv" + echo " ${summaryDir}/.venv" + ''; + }; + }; + + enterShell = '' + # Make podman socket accessible in order to launch regular docker commands. + # Set MEET_PODMAN_SOCKET=0 to keep the DOCKER_HOST of the calling environment. + case "''${MEET_PODMAN_SOCKET:-1}" in + 0|false|no|off) ;; + *) + _rundir="''${XDG_RUNTIME_DIR:-/run/user/$(id -u)}" + export DOCKER_HOST="unix://$_rundir/podman/podman.sock" + unset _rundir + ;; + esac + + # Compose files to merge + _compose_files="${config.devenv.root}/compose.yml" + + export DOCKER_USER="$(id -u):$(id -g)" + + case "''${DOCKER_HOST:-}" in + *podman*) + _compose_files="$_compose_files:${config.devenv.root}/compose.podman.yml" + + # Build images with Podman/Buildah rather than BuildKit. `docker + # compose build` otherwise has buildx boot a moby/buildkit container, + # and that container lands in its own network namespace with neither + # the proxy in its environment nor any route to it. + # Buildah has neither problem: base images are resolved by the Podman systemd + # service, which inherits the proxy from its systemd socket activated unit, and + # RUN steps execute in the *host* network namespace + + export DOCKER_BUILDKIT=0 + export COMPOSE_BAKE=false + ;; + esac + + export COMPOSE_FILE="$_compose_files" + unset _compose_files + + # Make binaries accessible + for _d in \ + "$DEVENV_ROOT/${backendDir}/.venv/bin" \ + "$DEVENV_ROOT/${agentsDir}/.venv/bin" \ + "$DEVENV_ROOT/${summaryDir}/.venv/bin" \ + "$DEVENV_ROOT/${frontendDir}/node_modules/.bin" + do + [ -d "$_d" ] && export PATH="$_d:$PATH" + done + unset _d + ''; + }; +} diff --git a/devenv.yaml b/devenv.yaml new file mode 100644 index 000000000..60520eef5 --- /dev/null +++ b/devenv.yaml @@ -0,0 +1,5 @@ +inputs: + nixpkgs: + url: git+https://github.com/NixOS/nixpkgs?ref=nixos-26.05&shallow=1 + devenv: + url: git+https://github.com/cachix/devenv?ref=refs/tags/v2.1.2&dir=src/modules