diff --git a/docs/tips/nix.md b/docs/tips/nix.md new file mode 100644 index 000000000..755df6494 --- /dev/null +++ b/docs/tips/nix.md @@ -0,0 +1,62 @@ +# Using on Nix/NixOS + +Emanote can be easily built using the Nix expressions provided in its source repo. + +You will need [Nix](https://nixos.org/download.html) version 2.4 or greater. + +## Installing with Nix Flakes + +This will provide the `emanote` command in your environment. + +```sh-session +$ nix profile install github:srid/emanote +``` + +## Using Emanote as a Home Manager service + +[Home Manager][home-manager] is a +Nix-based personal configuration manager. If you use Home Manager, +then Emanote has a [module][] that can be imported into your +configuration. + +Merge or import this config into your `~/.config/nixpkgs/home.nix`: +```nix +{ config, ... }: +let + emanote = import (builtins.fetchTarball "https://github.com/srid/emanote/archive/master.tar.gz"); +in { + imports = [ emanote.homeManagerModule ]; + services.emanote = { + enable = true; + # host = "127.0.0.1"; # default listen address is 127.0.0.1 + # port = 7000; # default http port is 7000 + notes = [ + "/home/user/notes" # add as many layers as you like + ]; + package = emanote.defaultPackage.${builtins.currentSystem}; + }; +} +``` + +Re-apply your home-manager configuration the usual way (e.g. `home-manager switch`). + +You will then have an `emanote` command in your profile, and a systemd +user service running a live-preview of your notes. + +```sh-session +$ home-manager switch +... +$ systemctl --user status emanote.service +● emanote.service - Emanote web server + Loaded: loaded (/nix/store/i1af5hdydwcf7y0r55n7fd67dnw5habd-home-manager-files/.config/systemd/user/emanote.service; enabled; vendor preset: enabled) + Active: active (running) since Tue 2021-11-02 17:17:04 AWST; 17h ago + Main PID: 1705303 (emanote) + Tasks: 26 (limit: 38220) + Memory: 38.3M + CPU: 2.884s + CGroup: /user.slice/user-1000.slice/user@1000.service/app.slice/emanote.service + └─1705303 /nix/store/9hj2cwk1jakfws0d1hpwa221kcni3j45-emanote-0.3.12.1/bin/emanote --layers /nix/store/hr7wp1xvqn48b8gy16sdq6k2csrvr8c1-emanote-config;/home/user/notes +``` + +[home-manager]: https://github.com/nix-community/home-manager +[module]: https://github.com/srid/emanote/blob/master/home-manager-module.nix diff --git a/flake.nix b/flake.nix index 497e7eb24..95734de25 100644 --- a/flake.nix +++ b/flake.nix @@ -80,5 +80,8 @@ # Used by `nix develop` devShell = project true; - }); + }) // + { + homeManagerModule = import ./home-manager-module.nix; + }; } diff --git a/home-manager-module.nix b/home-manager-module.nix new file mode 100644 index 000000000..155d8ab21 --- /dev/null +++ b/home-manager-module.nix @@ -0,0 +1,116 @@ +{ config, lib, pkgs, ... }: let + + cfg = config.services.emanote; + + yamlFormat = pkgs.formats.yaml { } // { + generateDir = name: path: value: + (yamlFormat.generate path value).overrideAttrs (attrs: { + inherit name; + buildCommand = '' + mkdir -p $out + out="$out/${path}" + ${attrs.buildCommand} + ''; + }); + }; + + extraConfig = lib.recursiveUpdate cfg.extraConfig { + template.baseUrl = cfg.baseUrl; + }; + configLayer = yamlFormat.generateDir "emanote-config" "/index.yaml" extraConfig; + layers = map toString ([configLayer] ++ cfg.notes); + +in { + options = { + services.emanote = with lib; { + enable = mkEnableOption '' + Enable the Emanote service, to create beautiful websites -- + such as your personal webpage, blog, wiki, Zettelkasten, + notebook, knowledge-base, documentation, etc. from + future-proof plain-text notes and arbitrary data -- with a + live preview that updates in real-time. + ''; + + package = mkOption { + type = types.package; + default = pkgs.emanote; + defaultText = "pkgs.emanote"; + description = "Emanote derivation to use"; + }; + + notes = mkOption { + type = types.nonEmptyListOf (types.either types.path types.str); + default = [ "${config.home.homeDirectory}/Documents/Notes" ]; + defaultText = literalExample ''[ ''${config.home.homeDirectory}/Documents/Notes" ]''; + description = '' + List of notebook folders to 'union mount', with earlier + paths in the list taking priority over later paths. + ''; + }; + + host = mkOption { + type = types.str; + default = "127.0.0.1"; + description = "The hostname or IP address the HTTP server should listen to"; + }; + + port = mkOption { + type = types.port; + default = 7000; + description = "The port on which the HTTP server listens."; + }; + + baseUrl = mkOption { + type = types.str; + description = "Base href for hyperlinks on the site."; + default = "/"; + example = "/emanote/"; + }; + + extraConfig = mkOption { + inherit (yamlFormat) type; + default = { }; + example = { + template.urlStrategy = "pretty"; + }; + description = '' + Config that will be layered over the default notes configs. + + See https://note.ema.srid.ca/demo/yaml-config for + information about the format. + ''; + }; + + systemdTarget = mkOption { + type = types.str; + default = "graphical-session.target"; + description = '' + The systemd user unit which + emanote.service should be a part of. + ''; + }; + }; + }; + + config = lib.mkIf cfg.enable { + home.packages = [ cfg.package ]; + + systemd.user.services.emanote = { + Unit = { + Description = "Emanote web server"; + PartOf = [ cfg.systemdTarget ]; + After = [ cfg.systemdTarget ]; + }; + Install.WantedBy = [ cfg.systemdTarget ]; + Service = { + Environment = [ + "PORT=${builtins.toString cfg.port}" + "HOST=${cfg.host}" + ]; + ExecStart = '' + ${cfg.package}/bin/emanote --layers "${lib.concatStringsSep ";" layers}" + ''; + }; + }; + }; +}