-
Notifications
You must be signed in to change notification settings - Fork 1
feat: seed nix-happier with full Nix packaging #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
04f0b12
c10bee4
fe98f11
0dae6dc
1e9fb98
6cb0ec5
7e4bcb1
8911b06
3431d43
b564a6b
e59ca9b
a1c0f93
8c3f982
e10ede5
df299d7
94a05c8
385000c
be7a27b
dcf0f17
111c3ad
3941742
77be10a
6415421
3e03c2e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| name: CI — Nix Builds | ||
|
|
||
| on: | ||
| pull_request: | ||
| push: | ||
| branches: | ||
| - main | ||
|
|
||
| concurrency: | ||
| group: ${{ github.workflow }}-${{ github.ref }} | ||
| cancel-in-progress: true | ||
|
|
||
| jobs: | ||
| nix-build-x86_64-linux: | ||
| name: Nix Build (x86_64-linux) | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 60 | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Install Nix | ||
| uses: DeterminateSystems/nix-installer-action@main | ||
|
|
||
| - name: Nix flake check | ||
| run: nix flake check | ||
|
|
||
| - name: Check formatting | ||
| run: nix fmt -- --fail-on-change | ||
|
|
||
| nix-build-aarch64-darwin: | ||
| name: Nix Build (aarch64-darwin) | ||
| runs-on: macos-latest | ||
| timeout-minutes: 60 | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Install Nix | ||
| uses: DeterminateSystems/nix-installer-action@main | ||
|
|
||
| - name: Nix flake check | ||
| run: nix flake check | ||
|
|
||
| nix-build-aarch64-linux: | ||
| name: Nix Build (aarch64-linux) | ||
| runs-on: ubuntu-24.04-arm | ||
| timeout-minutes: 60 | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Install Nix | ||
| uses: DeterminateSystems/nix-installer-action@main | ||
|
|
||
| # KVM is not available on GitHub ARM runners, so the NixOS VM | ||
| # integration test cannot run here. Build packages and run linters | ||
| # only; the full VM test runs in the x86_64-linux job. | ||
| - name: Build packages | ||
| run: | | ||
| nix build .#packages.aarch64-linux.happier-server | ||
| nix build .#packages.aarch64-linux.happier-cli | ||
|
|
||
| - name: Lint | ||
| run: | | ||
| nix build .#checks.aarch64-linux.deadnix | ||
| nix build .#checks.aarch64-linux.statix | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| # nix-happier — Agent Guidelines | ||
|
|
||
| This file provides guidance for AI coding agents (Claude Code, Copilot, Codex, etc.) working in this repo. | ||
|
|
||
| ## What this repo is | ||
|
|
||
| A Nix flake that builds and deploys [Happier](https://github.com/happier-dev/happier) Server and CLI. It does **not** contain application source code — the happier monorepo is fetched as a flake input. This repo only has Nix expressions, NixOS modules, and supporting config. | ||
|
|
||
| ## Repo layout | ||
|
|
||
| ``` | ||
| flake.nix # Flake entrypoint (inputs, systems, imports) | ||
| packages.nix # happier-server + happier-cli derivations | ||
| checks.nix # deadnix, statix, NixOS VM integration test | ||
| devshell.nix # Dev shell (fmt, update commands) | ||
| modules/nixos/happier-server.nix # NixOS service module | ||
| packages/prisma-engines-prebuilt.nix # Prebuilt Prisma engine binaries | ||
| examples/happier-server-tailscale.nix # Recommended production setup (Tailscale + Caddy) | ||
| examples/happier-server-light.nix # Minimal config (used by CI VM test) | ||
| ``` | ||
|
Comment on lines
+11
to
+20
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add a language to the fenced code block. The repo layout block should specify a language (e.g., Proposed fix-```
+```text
flake.nix # Flake entrypoint (inputs, systems, imports)
packages.nix # happier-server + happier-cli derivations
checks.nix # deadnix, statix, NixOS VM integration test
devshell.nix # Dev shell (fmt, update commands)
modules/nixos/happier-server.nix # NixOS service module
packages/prisma-engines-prebuilt.nix # Prebuilt Prisma engine binaries
examples/happier-server-tailscale.nix # Recommended production setup (Tailscale + Caddy)
examples/happier-server-light.nix # Minimal config (used by CI VM test)🧰 Tools🪛 markdownlint-cli2 (0.21.0)[warning] 11-11: Fenced code blocks should have a language specified (MD040, fenced-code-language) 🤖 Prompt for AI Agents |
||
|
|
||
| ## Language and tooling | ||
|
|
||
| - **All code is Nix.** There is no TypeScript, Python, or other source code here. | ||
| - **Formatter**: `nixfmt-tree` (the flake's `formatter`). Run `nix fmt` to format. | ||
| - **Linters**: `deadnix` (unused bindings) and `statix` (anti-patterns). Both run via `nix flake check`. | ||
| - **statix config**: `statix.toml` disables `repeated_keys` (W20) — NixOS modules idiomatically use separate top-level assignments with `lib.mkIf` guards. | ||
|
|
||
| ## Nix style conventions | ||
|
|
||
| - Use `nixfmt-tree` style (the RFC-style formatter). Do not manually reformat — run `nix fmt`. | ||
| - Prefer `lib.mkIf` / `lib.mkOption` / `lib.optional` over raw `if-then-else` in NixOS modules. | ||
| - Use `let ... in` for local bindings. Keep `let` blocks close to where they're used. | ||
| - Avoid `with pkgs;` at module scope — use it only in narrow scopes (e.g. inside `buildInputs` lists). | ||
| - `flake-parts` is used for per-system logic. New per-system outputs go in dedicated `.nix` files imported by `flake.nix`. | ||
| - Comments should explain *why*, not *what*. Nix expressions are usually self-documenting. | ||
|
|
||
| ## Key patterns | ||
|
|
||
| ### Flake structure | ||
|
|
||
| The flake uses [flake-parts](https://github.com/hercules-ci/flake-parts). Per-system outputs (packages, checks, devshell, apps) are split into separate files and imported in `flake.nix`. Flake-level outputs (`nixosModules`) are defined in the `flake = { ... }` attrset. | ||
|
|
||
| ### NixOS module | ||
|
|
||
| `modules/nixos/happier-server.nix` defines `services.happier-server` options. It supports two modes: | ||
| - **full**: PostgreSQL + Redis + MinIO (production stack) | ||
| - **light**: SQLite-only, no external deps | ||
|
|
||
| The module provisions supporting services (PostgreSQL, Redis, MinIO) when `createLocally = true` and handles migrations, WAL mode, and secret loading via `systemd` `LoadCredential`. | ||
|
|
||
| Both modes require an `environmentFile` containing `HANDY_MASTER_SECRET` for production use. The only exception is the CI VM test, which omits it. | ||
|
|
||
| ### Package builds | ||
|
|
||
| Both `happier-server` and `happier-cli` are built from the happier monorepo source (`inputs.happier`). Prisma engines come from `packages/prisma-engines-prebuilt.nix` which fetches prebuilt binaries by hash. | ||
|
|
||
| ### Updating dependencies | ||
|
|
||
| When the happier monorepo updates `@prisma/client`, the engine hashes here must also be updated: | ||
|
|
||
| ```sh | ||
| nix run .#update # updates flake inputs + Prisma hashes | ||
| nix run .#update-prisma-hashes # updates only Prisma hashes | ||
| ``` | ||
|
|
||
| ## Verification | ||
|
|
||
| Always verify changes with: | ||
|
|
||
| ```sh | ||
| nix fmt # format | ||
| nix flake check # lint (deadnix, statix) + VM integration test (Linux) | ||
| nix build .#happier-server # build the server package | ||
| ``` | ||
|
|
||
| `nix flake check` runs the NixOS VM integration test on Linux — it boots a VM with the light-mode example and verifies the server starts and responds on port 3005. | ||
|
|
||
| ## Do's and don'ts | ||
|
|
||
| - **Do** run `nix fmt` after every change. | ||
| - **Do** run `nix flake check` before considering work done (or at minimum `nix build`). | ||
| - **Do** keep the NixOS module options in sync with the README's "Module options" table. | ||
| - **Do** add examples to `examples/` for new configurations and reference them in checks if testable. | ||
| - **Don't** modify `flake.lock` by hand — use `nix flake update` or `nix run .#update`. | ||
| - **Don't** add packages, commands, or dependencies that belong in the happier monorepo, not here. | ||
| - **Don't** introduce `with pkgs;` at module or file scope. | ||
| - **Don't** create migrations or modify Prisma schemas — that happens in the happier monorepo. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| AGENTS.md |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,195 @@ | ||
| # nix-happier | ||
|
|
||
| Nix flake for building and deploying [Happier](https://github.com/happier-dev/happier) Server and CLI. | ||
|
|
||
| > **Pre-release notice:** The `happier` flake input currently tracks the `main` branch. This will be pinned to tagged releases once Happier reaches a stable version. Updates to this flake are made manually for now — run `nix run .#update` to pull the latest. | ||
|
|
||
| ## Flake outputs | ||
|
|
||
| | Output | Description | | ||
| |--------|-------------| | ||
| | `packages.happier-server` | Happier Server (full + light mode binaries) | | ||
| | `packages.happier-cli` | Happier CLI | | ||
| | `nixosModules.happier-server` | NixOS module for running Happier Server as a systemd service | | ||
| | `checks.deadnix` | Unused binding detection | | ||
| | `checks.statix` | Nix anti-pattern linting | | ||
| | `checks.nixos-happier-server-light` | NixOS VM integration test (Linux only) | | ||
| | `apps.update-prisma-hashes` | Update Prisma engine binary hashes | | ||
| | `apps.update` | Update all flake inputs + Prisma hashes | | ||
| | `devShells.default` | Dev shell with git and nixfmt | | ||
|
|
||
| Supported systems: `aarch64-darwin`, `aarch64-linux`, `x86_64-linux` | ||
|
|
||
| ## Secrets | ||
|
|
||
| All deployment modes require an **environment file** containing secrets. At minimum: | ||
|
|
||
| ```sh | ||
| HANDY_MASTER_SECRET=<your-secret> | ||
| ``` | ||
|
|
||
| Pass it to the module via `environmentFile`. Use [agenix](https://github.com/ryantm/agenix), [sops-nix](https://github.com/Mic92/sops-nix), or a plain file with restricted permissions — whatever fits your secrets workflow. | ||
|
|
||
| ## Quick start | ||
|
|
||
| Add the flake input and import the NixOS module: | ||
|
|
||
| ```nix | ||
| { | ||
| inputs = { | ||
| nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11"; | ||
| nix-happier.url = "github:happier-dev/nix-happier"; | ||
| }; | ||
|
|
||
| outputs = { nixpkgs, nix-happier, ... }: { | ||
| nixosConfigurations.myhost = nixpkgs.lib.nixosSystem { | ||
| system = "x86_64-linux"; | ||
| modules = [ | ||
| nix-happier.nixosModules.happier-server | ||
| { | ||
| services.happier-server = { | ||
| enable = true; | ||
| package = nix-happier.packages.x86_64-linux.happier-server; | ||
| mode = "light"; | ||
| environmentFile = "/run/secrets/happier-env"; | ||
| }; | ||
| } | ||
| ]; | ||
| }; | ||
| }; | ||
| } | ||
| ``` | ||
|
|
||
| ### Recommended: Tailscale + Caddy | ||
|
|
||
| The most common setup serves Happier over your Tailscale network with automatic TLS via Caddy. See [`examples/happier-server-tailscale.nix`](examples/happier-server-tailscale.nix) for a complete configuration that includes: | ||
|
|
||
| - Happier Server in light mode on `localhost:3005` | ||
| - Tailscale for private networking | ||
| - Caddy reverse proxy with automatic TLS cert provisioning | ||
|
|
||
| ### Light mode (minimal) | ||
|
|
||
| See [`examples/happier-server-light.nix`](examples/happier-server-light.nix) for the bare minimum. This is what the CI integration test uses — it omits `environmentFile` and networking, so it's useful as a starting point but not production-ready on its own. | ||
|
|
||
| ### Full mode (PostgreSQL + Redis + MinIO) | ||
|
|
||
| With `createLocally = true` (the default), PostgreSQL, Redis, and MinIO are all provisioned on the same host as single-node instances. This is convenient for small deployments but comes with no built-in replication or backups — **you are responsible for setting up your own backup strategy** (e.g. `pgBackRest`, `restic`, or filesystem snapshots). | ||
|
|
||
| ```nix | ||
| { | ||
| services.happier-server = { | ||
| enable = true; | ||
| package = nix-happier.packages.x86_64-linux.happier-server; | ||
| mode = "full"; | ||
| port = 3005; | ||
| environmentFile = "/run/secrets/happier-env"; | ||
|
|
||
| database = { | ||
| name = "happier"; | ||
| user = "happier"; | ||
| createLocally = true; # provisions PostgreSQL 15 | ||
| }; | ||
|
|
||
| redis.createLocally = true; | ||
|
|
||
| minio = { | ||
| createLocally = true; | ||
| bucket = "happier"; | ||
| rootCredentialsFile = "/run/secrets/minio-creds"; # MINIO_ROOT_USER + MINIO_ROOT_PASSWORD | ||
| }; | ||
| }; | ||
| } | ||
| ``` | ||
|
|
||
| ## Module options | ||
|
|
||
| ### Core | ||
|
|
||
| | Option | Type | Default | Description | | ||
| |--------|------|---------|-------------| | ||
| | `enable` | bool | `false` | Enable Happier Server | | ||
| | `package` | package | — | The `happier-server` package to use | | ||
| | `port` | port | `3005` | Port to listen on | | ||
| | `mode` | `"full"` \| `"light"` | `"full"` | `full` = PostgreSQL + Redis + MinIO; `light` = SQLite only | | ||
| | `environmentFile` | path \| null | `null` | **Required for production.** Secrets file (`KEY=value`) — must contain `HANDY_MASTER_SECRET` | | ||
|
|
||
| ### Database (full mode) | ||
|
|
||
| | Option | Type | Default | Description | | ||
| |--------|------|---------|-------------| | ||
| | `database.name` | string | `"happier"` | PostgreSQL database name | | ||
| | `database.user` | string | `"happier"` | PostgreSQL user | | ||
| | `database.createLocally` | bool | `true` | Provision PostgreSQL locally | | ||
|
|
||
| ### Redis (full mode) | ||
|
|
||
| | Option | Type | Default | Description | | ||
| |--------|------|---------|-------------| | ||
| | `redis.createLocally` | bool | `true` | Provision Redis locally | | ||
|
|
||
| ### MinIO (full mode) | ||
|
|
||
| | Option | Type | Default | Description | | ||
| |--------|------|---------|-------------| | ||
| | `minio.createLocally` | bool | `true` | Provision MinIO locally for S3-compatible storage | | ||
| | `minio.bucket` | string | `"happier"` | MinIO bucket name | | ||
| | `minio.rootCredentialsFile` | path \| null | `null` | File with `MINIO_ROOT_USER` and `MINIO_ROOT_PASSWORD` | | ||
|
|
||
| ## Examples | ||
|
|
||
| The [`examples/`](examples/) directory contains NixOS configurations: | ||
|
|
||
| | Example | Description | | ||
| |---------|-------------| | ||
| | [`happier-server-tailscale.nix`](examples/happier-server-tailscale.nix) | Recommended production setup — light mode + Tailscale + Caddy TLS | | ||
| | [`happier-server-light.nix`](examples/happier-server-light.nix) | Bare minimum for CI — tested via `nix flake check` VM integration test | | ||
|
|
||
| ## Development | ||
|
|
||
| Enter the dev shell: | ||
|
|
||
| ```sh | ||
| nix develop | ||
| ``` | ||
|
|
||
| Available commands inside the shell: | ||
|
|
||
| | Command | Description | | ||
| |---------|-------------| | ||
| | `fmt` | Format Nix files | | ||
| | `update` | Update flake inputs + Prisma hashes | | ||
|
|
||
| Run linting and integration tests: | ||
|
|
||
| ```sh | ||
| nix flake check | ||
| ``` | ||
|
|
||
| Update all inputs and refresh Prisma engine hashes: | ||
|
|
||
| ```sh | ||
| nix run .#update | ||
| ``` | ||
|
|
||
| ## Repo structure | ||
|
|
||
| ``` | ||
| . | ||
| ├── flake.nix # Flake entrypoint | ||
| ├── flake.lock | ||
| ├── packages.nix # happier-server + happier-cli derivations | ||
| ├── checks.nix # deadnix, statix, NixOS VM test | ||
| ├── devshell.nix # Dev shell with commands | ||
| ├── modules/ | ||
| │ └── nixos/ | ||
| │ └── happier-server.nix # NixOS module | ||
| ├── packages/ | ||
| │ └── prisma-engines-prebuilt.nix # Prebuilt Prisma engine binaries | ||
| ├── examples/ | ||
| │ ├── happier-server-tailscale.nix # Production setup with Tailscale + Caddy | ||
| │ └── happier-server-light.nix # Minimal config (used by CI) | ||
| └── .github/ | ||
| └── workflows/ | ||
| └── nix-build.yml # CI workflow | ||
| ``` | ||
|
Comment on lines
+177
to
+195
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Specify a language for the repo-structure code fence. This block should declare a language ( Proposed fix-```
+```text
.
├── flake.nix # Flake entrypoint
├── flake.lock
├── packages.nix # happier-server + happier-cli derivations
├── checks.nix # deadnix, statix, NixOS VM test
├── devshell.nix # Dev shell with commands
├── modules/
│ └── nixos/
│ └── happier-server.nix # NixOS module
├── packages/
│ └── prisma-engines-prebuilt.nix # Prebuilt Prisma engine binaries
├── examples/
│ ├── happier-server-tailscale.nix # Production setup with Tailscale + Caddy
│ └── happier-server-light.nix # Minimal config (used by CI)
└── .github/
└── workflows/
└── nix-build.yml # CI workflowVerify each finding against the current code and only fix it if needed. In |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: happier-dev/nix-happier
Length of output: 2212
Pin workflow actions to immutable commit SHAs instead of mutable refs.
Using version tags (
@v4) or branch refs (@main) allows upstream changes to alter CI behavior without review. Pin eachuses:to a commit SHA for reproducibility and security.This workflow uses:
actions/checkout@v4(lines 20, 37, 51) — version tag is mutableDeterminateSystems/nix-installer-action@main(lines 23, 40, 54) — branch ref is explicitly mutable🤖 Prompt for AI Agents