Skip to content

Feature request: Nix build and NixOS module for self-hosting #2400

Closed

Description

@artile

Use case

We self-host Maple on a VPS next to our own app. Our hosts are moving to NixOS for declarative config and atomic rollback. Today Maple is the only part of that setup we must run as Docker containers.

This is related to #352 (self-host outside Cloudflare) and to the goal stated there of an easy, one-click self-host. Nix would be one more way to get there, not a replacement for Docker.

How self-host looks today (as we read the repo)

  • docker-compose.yml runs postgres (17, wal_level=logical), electric, api, web, ingest (Rust), alerting, scraper and otel-collector. ClickHouse is external (docs/self-hosted-clickhouse.md).
  • The app images build from the monorepo with turbo prune + bun install (e.g. apps/api/Dockerfile). Self-hosting the full stack outside Cloudflare — working Miniflare-based deployment, offering fixes upstream #352 reports that some of these Docker paths have drifted from the Workers-based runtime.
  • deploy/docker-agent, deploy/k8s-infra and deploy/maple-otel cover the collector side, not the app services.

Please correct us if any of this is wrong.

Proposal (your choice)

(a) Nix in the repo

  • A flake.nix with packages for each deployable app: the Bun apps (for example with bun2nix from bun.lock), apps/ingest with the Rust tooling, the collector, and maybe the maple CLI.
  • A nixosModules.maple with options such as: listen ports, Postgres URL, Electric URL, ClickHouse URL, OTLP ingest endpoint, and secrets read from files (MAPLE_INGEST_KEY_ENCRYPTION_KEY, MAPLE_INGEST_KEY_LOOKUP_HMAC_KEY, …) instead of env values in the Nix store.
  • A NixOS VM test (nixosTests) that starts the stack and checks /health, so CI catches drift.

(b) Clear build and run steps only

  • You publish, per service, the build command, the run command, the required env vars and the required backing services.
  • The community packages Maple in nixpkgs from those steps. You maintain no Nix code.

We can help test either path on a real NixOS 26.05 host.

Questions that decide it

  1. Would you accept and maintain a flake.nix (and a NixOS module) in the tree, or do you prefer (b)?
  2. Which services are required for a minimal self-host? For example: are electric, scraper and alerting optional, and is a single-org MAPLE_AUTH_MODE=self_hosted setup with Postgres + ClickHouse enough?
  3. Are the app images built from stable commands we could mirror (the turbo prune + bun install steps in the Dockerfiles), or is the Workers/alchemy runtime the only supported way to run api, alerting and electric-sync now?

Activity

  1. Makisuo commented on Nov 9, 2026

    @Makisuo
    Collaborator

    Shipped in #2410: the repo is now a Nix flake with a NixOS module.

    {
      inputs.maple.url = "github:MapleTechLabs/maple";
      # modules = [ maple.nixosModules.maple ];
    }
    services.maple = {
      enable = true;
      host = "127.0.0.1";   # put a TLS proxy in front, or 0.0.0.0 on a private network
      ingestKeyFile = "/run/secrets/maple-ingest-key";
      accessTokenFile = "/run/secrets/maple-access-token";
    };

    Docs: https://maple.dev/docs/self-hosting/platforms/nixos

    Your three questions

    1. Flake in the tree or build steps only? In the tree, option (a). packages.<system>.maple, nixosModules.maple and a NixOS VM test (nix/test.nix) that CI runs on every change to the flake. After each stable release, the release workflow opens a PR that re-pins the flake.
    2. Minimal self-host? Smaller than the compose file suggests. The self-hosted product is Maple Local: one maple binary with OTLP ingest, an embedded ClickHouse (chDB), the query API and the dashboard on one port. No Postgres, Electric, external ClickHouse, scraper or alerting. It is the same server as ghcr.io/mapletechlabs/maple, single tenant, guarded by an ingest key and an access token.
    3. Stable build commands for api/alerting/electric-sync? No. Those now run only as Cloudflare Workers (queues, R2, KV, Durable Objects, Workflows), and the Docker files for them in docker-compose.yml have drifted (Self-hosting the full stack outside Cloudflare — working Miniflare-based deployment, offering fixes upstream #352). The flake does not package them; it packages Maple Local.

    What the module does

    • Secrets are read from files through systemd LoadCredential, so they never enter the Nix store. Both are required off loopback, and an empty file refuses to start (exit 78) instead of serving without auth.
    • Runs as a static maple user with its store in /var/lib/maple. Store-changing commands: sudo -u maple HOME=/var/lib/maple maple checkpoint.
    • Same crash policy as the image: restore the last checkpoint after an unclean stop, start fresh before the first one. A stop waits for an in-flight checkpoint.
    • maple update is disabled; upgrade with nix flake update maple.

    Maple is FSL-1.1-ALv2, which nixpkgs counts as unfree. The flake's own package and the module default build without any setting; overlays.default needs maple in your allowUnfreePredicate.

    The VM test covers ingest, auth, CLI reads, a checkpoint and a restart, but it has not run on a real NixOS 26.05 host yet. We would gladly take you up on testing it on yours; please open an issue with anything that breaks.

  2. added a commit that references this issue on Nov 10, 2026
    044f463
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions