Files
penpot-nix/flake.nix
T
kurogeek 08b5496980 Package Penpot 2.18.3 for Nix with NixOS module; afk devShell
Vendored from debling/nix-penpot (MIT). Fixes on top:
- pnpm fetchers: drop --config.fetch-* flags (UND_ERR_INVALID_ARG on pnpm 11.27)
  and pin real store hashes (frontend x3, exporter, mcp)
- deps-lock.json: add transitive funcool/beicon2 v2.0 so fake-git resolves
  potok2's pin during the shadow-cljs classpath build
- expose frontend pnpm stores via passthru for rehashing
- x86_64-linux only; devShell ships afk, jj, git
2026-10-20 17:45:02 +00:00

198 lines
6.2 KiB
Nix

{
description = "penpot-nix — Nix packages and NixOS module for self-hosting Penpot";
nixConfig = {
extra-substituters = [ "https://nix-penpot.cachix.org" ];
extra-trusted-public-keys = [
"nix-penpot.cachix.org-1:cbXoCSnLa6QmBex5EYzUSsswqSZA6RvJWl0dR+WgOns="
];
};
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
penpot.url = "github:penpot/penpot/2.18.3";
penpot.flake = false;
# Clojure dependency locking (deps-lock.json) + eval-time dep cache
# (mk-deps-cache) + offline git shim (fake-git). Pinned to a main
# commit: the only release (0.4.0, 2024) predates our toolchain.
# Only the overlay's clojure helpers are used (mk-deps-cache, fake-git,
# deps-lock, clj-builder); clj-nix's own apps/devshells stay unevaluated.
clj-nix.url = "github:jlesquembre/clj-nix/2b1290ee56e9bbd50e9b5874c985d34ad2f1b458";
clj-nix.inputs.nixpkgs.follows = "nixpkgs";
# Onboarding template files fetched by the backend build. No tags
# upstream, so track main; the locked rev makes it immutable. Bump with
# `nix flake update penpot-files` (see builtinTemplates in
# packages/backend.nix for the rehash procedure).
penpot-files.url = "github:penpot/penpot-files/main";
penpot-files.flake = false;
# Development harness: https://github.com/DavHau/afk
afk.url = "github:DavHau/afk";
afk.inputs.nixpkgs.follows = "nixpkgs";
};
outputs =
{
self,
nixpkgs,
penpot,
penpot-files,
clj-nix,
afk,
}:
let
systems = [ "x86_64-linux" ];
forAllSystems = nixpkgs.lib.genAttrs systems;
pkgsFor =
system:
import nixpkgs {
inherit system;
overlays = [
# Provides mk-deps-cache, fake-git, deps-lock, clj-builder.
clj-nix.overlays.default
];
};
penpotVersion =
# Keep in sync with the `penpot` input pin. Upstream leaves
# package.json's version stale ("2.17.0" even for 2.18.3), so
# mkPenpotVersion's package.json read lies; pin the real release
# instead. Changing this also changes asset version-tag URLs.
"2.18.3";
in
{
lib = {
mkPenpotVersion =
src:
let
pkg = builtins.readFile (src + "/package.json");
pkgVersion = builtins.match ".*\"version\": \"([^\"]+)\".*" pkg;
in
if pkgVersion != null then
builtins.head pkgVersion
else if src ? shortRev then
src.shortRev
else
"dev";
# Restrict a source tree to a set of top-level paths (directories or
# files). `paths` entries are matched against the path relative to
# `src`, so "backend" keeps "backend" itself and everything below it.
#
# Type: Path -> [String] -> Path
subSrc =
src: paths:
nixpkgs.lib.cleanSourceWith {
src = nixpkgs.lib.cleanSource src;
filter =
path: _type:
let
rel = nixpkgs.lib.removePrefix "${toString src}/" (toString path);
in
rel == "" || nixpkgs.lib.any (p: rel == p || nixpkgs.lib.hasPrefix "${p}/" rel) paths;
};
};
overlays.default = final: _prev: {
penpot-backend = self.packages.${final.stdenv.hostPlatform.system}.penpot-backend;
penpot-frontend = self.packages.${final.stdenv.hostPlatform.system}.penpot-frontend;
penpot-exporter = self.packages.${final.stdenv.hostPlatform.system}.penpot-exporter;
penpot-mcp = self.packages.${final.stdenv.hostPlatform.system}.penpot-mcp;
};
packages = forAllSystems (
system:
let
pkgs = pkgsFor system;
callPackage = pkgs.callPackage;
penpotRenderWasm = callPackage ./packages/render-wasm.nix {
inherit penpot;
version = penpotVersion;
};
in
{
penpot-backend = callPackage ./packages/backend.nix {
inherit penpot penpot-files;
version = penpotVersion;
inherit (self.lib) subSrc;
};
penpot-render-wasm = penpotRenderWasm;
# Exposed separately so CI/flake-check keeps building the export
# flavor (nothing consumes it on the 2.17.x line).
penpot-render-wasm-export = penpotRenderWasm.passthru.export;
penpot-frontend = callPackage ./packages/frontend.nix {
inherit penpot;
version = penpotVersion;
inherit (self.lib) subSrc;
};
penpot-exporter = callPackage ./packages/exporter.nix {
inherit penpot;
version = penpotVersion;
inherit (self.lib) subSrc;
};
penpot-mcp = callPackage ./packages/mcp.nix {
inherit penpot;
version = penpotVersion;
inherit (self.lib) subSrc;
};
default = self.packages.${system}.penpot-backend;
}
);
nixosModules = {
default = self.nixosModules.penpot;
penpot = import ./modules/penpot.nix;
};
nixosConfigurations.penpot-vm = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
{ nixpkgs.overlays = [ self.overlays.default ]; }
self.nixosModules.default
./tests/vm.nix
];
};
checks = forAllSystems (
system:
let
pkgs = pkgsFor system;
in
{
# Full end-to-end VM test of the module (boots PostgreSQL, Valkey,
# backend, nginx, exporter and MCP, then probes every endpoint).
penpot-vm-test = pkgs.testers.nixosTest (
import ./tests/vm-test.nix {
inherit (pkgs) lib;
inherit self;
}
);
}
);
devShells = forAllSystems (
system:
let
pkgs = pkgsFor system;
in
{
default = pkgs.mkShell {
packages = [
afk.packages.${system}.afk
pkgs.jujutsu
pkgs.git
pkgs.nixfmt-tree
];
};
}
);
formatter = forAllSystems (system: (pkgsFor system).nixfmt-tree);
};
}