Skip to content
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

nixos/doc: render option values using lib.generators.toPretty #199363

Merged
merged 5 commits into from
Dec 8, 2022

Conversation

ncfavier
Copy link
Member

@ncfavier ncfavier commented Nov 3, 2022

Fixes #195562, see discussion there.

A nice side effect is that we can leverage toPretty's allowPrettyValues feature to make scrubbed derivations pretty-print as pkgs.foo. This should allow us to mostly get rid of the

default = pkgs.foo;
defaultText = lib.literalExpression "pkgs.foo";

pattern which is so easy to get wrong (though instances like cfg.package would still require it).

Note that if this approach works out, we can maybe turn it into a promise that optionAttrSetToDocList does not output non-rendered Nix values, so that we can eventually get rid of all the other Nix rendering code, in-tree and out-of-tree.

Regarding the first commit, I am aware that most of these issues would be avoided by adding proper type checks to defaults and examples. I'll try to look into this next.

@@ -286,6 +286,7 @@ in {
log_config = mkOption {
type = types.path;
default = ./synapse-log_config.yaml;
defaultText = lib.literalExpression "nixos/modules/services/matrix/synapse-log_config.yaml";
Copy link
Member Author

@ncfavier ncfavier Nov 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is to avoid the "manual depends on nixpkgs location" error. I'm not sure what should be done here. Maybe toPretty should somehow be made aware of pkgs.path so that it can render internal paths independently of where nixpkgs is located? Previously the path would just get copied to the store and rendered as a string, which seems worse.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation generator already needs to deal with paths for the declaration and definition locations. The logic for this is a bit strewn about. It'd make sense to make the generic doc generation take ownership of that functionality and then reuse that logic by passing it to toPretty.

Copy link
Contributor

@pennae pennae left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks reasonable, but we'd still rather not convert everything to text in nix. the generated manual does look a lot better on composite defaults though, so that's a big plus. might be worth it to make the average docs better, even if more advanced systems would have to re-parse examples.

This should allow us to mostly get rid of the [defaultText for packages]

not really, since pkgs is a throw thunk in the lazy module docs build. might be better to use mkPackageOption instead for options referring to packages since that takes care of the duplication.

nixos/modules/virtualisation/qemu-vm.nix Outdated Show resolved Hide resolved
Comment on lines 54 to 59
// optionalAttrs (isDerivation value) {
outPath = "\${${wholeName}}";
drvPath = wholeName;
__pretty = _: wholeName; val = null;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure this is very useful. scrubDerivations has kind of outlived its purpose with mkPackageOption and the lazy docs build, it may be better to try and remove it entirely or replace it with a stub that doesn't reconstruct the path.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I agree. My main concern are things like default = "... ${pkgs.foo} ..." without a defaultText. The "\${${wholeName}}" hack currently makes this render "nicely" but this is arguably a bug with toPretty: the interpolation should be escaped, so that it doesn't look nice anymore. I think I'd like to do something like

// optionalAttrs (isDerivation value) {
  outPath = throw "attempt to use a derivation in options documentation";
  drvPath = # same
}

It's a bit annoying that this has to be decided at the level of the evaluation, rather than in the generic make-options-doc, so that out-of-tree projects have to make their own decision. But probably fine.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that throw is pretty much what already happens for in-tree modules. in keeping with the more-or-less official deprecation policy we could emit a warning during the build for bit and turn it into an always-throw a while later.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "\${${wholeName}}" hack currently makes this render "nicely" but this is arguably a bug with toPretty:

I agree that this is a bug, but is it a reason to drop easy pkgs.foo interpolation from the docs?

It could be made to work well by

  • fixing the escaping first
  • making the escaping customizable (function passed to toPretty)
  • pass a custom escaping function, which at the end replaces a special syntax like $$${{{ to ${ so that antiquotations are representable without stealing too much from the normal string literals.
  • make pkgs.foo.outPath = "\$\$\${{{pkgs.foo}"
  • toPretty will print the right expression

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Considering that this feature is not used by anything in-tree (manual still builds with a throw), I think it's worth trying to move in the direction of least hackiness, which IMO is something like NixOS/nix#1474.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright. Then let's keep using the least hacky option available with the Nix we have today:

{
  defaultText = lib.literalExpression ''
    "''${pkgs.foo}/bin/foo"
  '';
}

@ncfavier
Copy link
Member Author

ncfavier commented Nov 6, 2022

more advanced systems would have to re-parse examples.

What do you have in mind?

@pennae
Copy link
Contributor

pennae commented Nov 6, 2022

more advanced systems would have to re-parse examples.

What do you have in mind?

you know the kind of example boxes multi-language frameworks tend to have, with one example in many different languages? that kind of thing. it's sufficiently out there to not optimize for, and less fancy but more useful things like syntax highlighting or crosslinking between options don't work with literal examples anyway, so those have to be reparsed no matter what.

@ncfavier
Copy link
Member Author

ncfavier commented Nov 10, 2022

Alright, I got a bit carried away... see commits.

Notes

  • This PR changes the format of options.json (declarations can now be {path, url} instead of strings), which breaks nixos-search. This should be fixed before merging.
    Users of optionAttrSetToDocList should not get too broken (e.g. the home-manager manual still looks fine).
  • After merging, the release wiki should be updated to mention lib.trivial.manualRevision.
  • After merging, morph can undo most of Employ new documentation.nixos.extraModuleSources option DBCDK/morph#108 and instead set documentation.nixos.extraModuleSources = [ { name = "morph"; prefix = ../.; urlFor = m: ...; }]. cc @bb010g
  • Lazy trees nix#6530 (comment) will break lazy-options.json because we now filter the nixpkgs source based on relative paths.
  • An alternative to the moduleSources argument would be to add a _module.sources option so that modules can define their own sources. This could work either by also passing config to optionsToDocTemplate, or by making a modulesToDocTemplate wrapper which calls evalModules. I haven't thought this through, just throwing ideas around.
  • I removed all the special logic for nixops since it wasn't used anymore.

Copy link
Contributor

@pennae pennae left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks mostly reasonable. rendered options seem to fine judging by the limited number of checks we've done.

toPretty { searchPath = [ { name = "foo"; prefix = "/path/to/foo"; } ]; } /path/to/foo/bar/qux
==> "<foo/bar/qux>"
Type: [ { name = string; prefix = string or path; } ] */
searchPath ? []
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
searchPath ? []
searchPath ? {}

multiple paths for the same name don't make sense, better encode that in the type

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess semantically this should be a mapping from names to paths, but technically it should be a mapping from paths to names (because that's the direction of the transformation we're doing), so I went the neutral route and picked neither.

I'm fine with going the semantic route though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the issue is mostly that the generated paths look like nix could process them, given correct flags. arguably stripping paths entirely instead of replacing them with some name/placeholder is somewhat misleading (which is the most relevant thing for the extraModuleSources case). if we can make paths without names or with duplicated names obviously not-directly-parseable that's also fine, maybe even render the search path into option docs somewhere?

nixos/lib/make-options-doc/default.nix Outdated Show resolved Hide resolved
Comment on lines 66 to 75
filteredNixpkgs = builtins.path {
name = "filtered-nixpkgs";
path = pkgs.path;
filter = let dirs = [ "lib/" "pkgs/pkgs-lib/" "nixos/" ]; in
path: type: let p = lib.removePrefix (toString pkgs.path + "/") (toString path); in
cleanSourceFilter path type && (
if type == "directory" then
baseNameOf path != "tests" && lib.any (dir: lib.hasPrefix dir (p + "/") || lib.hasPrefix (p + "/") dir) dirs
else
p == ".version" || lib.any (dir: lib.hasPrefix dir p) dirs);
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

won't this now also copy all of nixos/doc? the .nix suffix filter was in there specifically to not copy large amounts of documentation that aren't necessary for the options build.

Copy link
Member Author

@ncfavier ncfavier Nov 14, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The .nix filtering never worked, because the check was t == "file" instead of t == "regular", and in fact excluding non-nix files isn't possible currently because of e.g.

default = builtins.readFile ./nscd.conf;

We could still make it work by adding a defaultText there, or marking that module non-cacheable, or we could just filter out directories named doc

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

adding a defaultText sounds like the most reasonable approach. merely excluding doc/ directories won't do quite what was expected since it'd still copy module docs files (both xml and possibly the md file they were generated from). i guess if we moved all of those to doc/ dirs instead of having them side by side with their module filtering by dirs alone would also be fine, but that may be a bit too intrusive? dunno.

(but in the end, if the filter never worked we won't be making anything worse so it doesn't even matter that much)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should avoid bothering module authors with this implementation detail as much as possible, so I went with excluding doc. The resulting store path weighs 13.5 MiB, of which 12.6 MiB are .nix files.

};
name = mkOption {
type = with types; nullOr (strMatching "[a-zA-Z0-9._+-]+");
default = null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does it make sense to not specify a name for any of these? merely dropping the prefix might be misleading since it makes the first remaining path component look like an include path name. (and if names are mandatory this may as well be an attrsOf)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is compatibility: previously extraModuleSources only accepted paths to be stripped, so the question is what to do with those. Currently they are mapped to a nameless source, I don't see a better alternative short of throwing an error, but that seems a bit brutal.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<_unknown/*> may be a good default?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps baseNameOf config.prefix and maybe strip off a store path hash part, if there is one.
I guess that will effectively be "source" in many cases.

What do the angle brackets, underscore, slash and asterisk mean? It seems a bit excessive.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@roberth Imagine a NixOS module source under version control, checked out in a home directory. If there's a module at the top level, e.g. $CHECKOUT/configuration.nix, the base name of $CHECKOUT isn't necessarily stable between checkouts. We should avoid looking at parents of the top-level. If we don't provide a default module source name, this path renders in documentation as <configuration.nix>. If the source then imports a module from $CHECKOUT/nixpkgs/nixos/system/build.nix, its path then renders as <nixpkgs/nixos/system/build.nix>, which is the path of an existing Nixpkgs module. (This example is contrived, but the situation can reasonably occur if multiple external module sets use simple paths.) On the other hand, if we provide a default module source name of _unknown/, then the former path renders as <_unknown/configuration.nix> and the latter path renders as <_unknown/nixpkgs/nixos/system/build.nix>.

This approach can still result in collisions, but a default name of _unknown sticks out and looks ugly enough that anyone who notices will change it, and the leading underscore is conventional for internal Nix & Nixpkgs names.

If we wanted the name to stick out more and be easier to search, _unknown-module-source could work really well (<_unknown-module-source/configuration.nix>).

On the …/configuration.nix note from earlier, we may want to add config.nixos.extraModuleSources = [ { name = "nixos-config"; prefix = ./.; } ]; to the /etc/nixos/configuration.nix template.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lookup key in the logical sense. I think prefix has to be a linear search, not an attrset key, because it can be a path value, and we may not want to toString those because of lazy trees.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the mirror discussion for searchPath. Technically you're right, but I think it makes sense to have module sources indexed by their name. We might find more use cases for them later than just stripping prefixes.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could use name as an extra key that's an actual key and have a displayName option for the cases where we don't have enough info.

Copy link
Contributor

@bb010g bb010g Nov 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this will break if someone has two paths named source, which is quite likely...

We could leave the store hash be, which sort of defeats the point extraModuleSources was originally intended for, but at least users will be warned?

The current behavior is that the parent directory context gets completely dropped and mislabeled (it renders as <nixpkgs/$src.nix>), so clearly marking non-Nixpkgs paths as such by default is an improvement. People who care about custom docs builds shouldn't have a hard time migrating. This also avoids possible unexpected churn from unstable parent directories.

Actually, here's an alternative: introduce a new moduleSources option with the "ideal" type (attrsOf {prefix, urlFor}), and add a mkChangedOptionModule that maps paths from extraModuleSources to attributes in moduleSources using the mechanism proposed by @roberth (basename of prefix minus store hash), which comes with a warning. Seems like the best of all worlds?

If we're considering new attributes, I might as well pitch this: I think this module set source handling for docs and the recent isolated docs builds work should be unified as much as possible, using "canonical" names like <nixpkgs/nixos/modules/programs/hello.nix> and <contoso/nixos/modules/programs/hello.nix> at the core. I'd like to be able to ad-hoc extend a specific Nixpkgs module in a dedicated file and have it join the original module in an isolated docs build by assigning that specific module the same canonical path (creating an intentional collision). Additionally, if we have a mapping (attrset?) from these canonical paths to minimal module sets, any docs module dependencies could be declared (sort of like imports) so that evaluation still happens in as isolated chunks as possible while not special casing Nixpkgs as the one module source that gets speedy docs builds.

I don't know how much work implementing this proposal would be.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I understand the use case for that, and in any case it seems well beyond the scope of this PR so I think I'll revert to the "least disruptive" choice (the current state of this PR, but make name non-optional and default to _unknown for raw paths) and let others extend this later.

@ncfavier
Copy link
Member Author

ncfavier commented Dec 1, 2022

I went with my _module.sources idea and isolated the prefix lookup logic into a new function lib.strings.lookupPrefix.
That way it's not NixOS-specific, module sources are responsible for identifying themselves, and we can bake the nixpkgs source in (which will always be used for the _module options if those are rendered).

Also moved the <source/path> rendering down to XSLT; other consumers get a {source, path, url?} attrset which they are free to render as they wish.

I still think it's fine to allow sources with colliding names, e.g. when Nix gets lazy trees we might somehow want to have roots for both "${flake}" and toString flake in certain situations.

I've tested this in a variety of situations and I've got PRs ready for home-manager, nmd and nixos-search.

@fricklerhandwerk
Copy link
Contributor

Oof, that's a large one. I suppose I was added automatically based on CODEOWNERS. Sorry @ncfavier, I won't have time to review this any time soon, maybe never, but you seem to have plenty of reviewers who can help merge this.

@infinisil
Copy link
Member

infinisil commented Dec 1, 2022

This PR does too many things now! Can you split this up into smaller reviewable bits @ncfavier? Also the title of this PR doesn't really match all that it does anymore

@ncfavier
Copy link
Member Author

ncfavier commented Dec 1, 2022

Indeed, forked the path stuff into #203994.

Note that the commits left in this PR are already reviewed (but additional reviews can't hurt!)

</xsl:template>


<xsl:template match="attrs[attr[@name = '_type' and string[@value = 'literalExpression']]]">
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note there's already a template for literalExpression above.

@ncfavier
Copy link
Member Author

ncfavier commented Dec 7, 2022

I think this is good to merge now?

Copy link
Contributor

@pennae pennae left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, looks good (except for a few nitpicks. just ignore them if you want to get this over with.)

nixos/modules/services/databases/openldap.nix Show resolved Hide resolved
nixos/modules/services/games/asf.nix Outdated Show resolved Hide resolved
@@ -294,7 +297,7 @@ rec {
introSpace = if multiline then "\n${indent} " else " ";
outroSpace = if multiline then "\n${indent}" else " ";
in if isInt v then toString v
else if isFloat v then "~${toString v}"
else if isFloat v then toString v
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still very much hate float formatting in nix, and have the feeling that toJSON would be better here (because it can display tiny values like 1.0e-10 / 3 almost correctly)

Copy link
Member Author

@ncfavier ncfavier Dec 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

toJSON does seem better. I think I switched to it at some point and then reverted it because toJSON 1.0 == "1", which might be misleading for options that use types.float and not types.number (builtins.isFloat 1 == false).

I'm not sure which is worse: loss of precision under 1e-6 or type ambiguity?

Maybe we can use toJSON but add .0 at the end if the string matches -?[0-9]+.

Copy link
Contributor

@pennae pennae Dec 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't think type ambiguity is a problem since we show the types adjacent to values (except for complicated cases), where precision loss could badly mangle small values (of which we currently don't seem to have any in nixpkgs, but external modules may trip over that). munging the output of toJSON would be rather complicated since eg 1.0e9 is formatted as 1e+9, which unfortunately doesn't parse at all in nix 😓

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, I went with toJSON and left a comment

With the goal of making `toPretty` suitable for rendering option
values, render derivations as `<derivation foo-1.0>` instead of
`<derivation /nix/store/…-foo-1.0.drv>`.

This is to avoid causing sudden evaluation errors for out-of-tree
projects that have options with `default = pkgs.someUnfreePackage;` and
no `defaultText`.
Render un`_type`d defaults and examples as `literalExpression`s using
`lib.generators.toPretty` so that consumers don't have to reinvent Nix
pretty-printing. `renderOptionValue` is kept internal for now intentionally.

Make `toPretty` print floats as valid Nix values (without a tilde).

Get rid of the now-obsolete `substSpecial` function.

Move towards disallowing evaluation of packages in the manual by
raising a warning on `pkgs.foo.{outPath,drvPath}`; later, this should
throw an error. Instead, module authors should use `literalExpression`
and `mkPackageOption`.
The logic for pretty-printing Nix values isn't needed any more because
`optionAttrSetToDocList` returns already rendered values.
@pennae
Copy link
Contributor

pennae commented Dec 8, 2022

ran the new manual through our diff scripts. the diff is huge (120k lines 😨) so we didn't inspect everything, but what we did check looks a lot better now. (except for the syntax highlighting of multine strings in options.html, that seems to be confused. but was before too, so no harm done)

@pennae pennae merged commit 109f8b4 into NixOS:master Dec 8, 2022
@ncfavier ncfavier deleted the render-option-values branch December 8, 2022 16:53
afilini pushed a commit to h4ckbs/nixos-mailserver that referenced this pull request Jan 30, 2023
Option values are now rendered correctly as Nix thanks to
NixOS/nixpkgs#199363
afilini pushed a commit to h4ckbs/nixos-mailserver that referenced this pull request Jan 30, 2023
Option values are now rendered correctly as Nix thanks to
NixOS/nixpkgs#199363
agentx3 pushed a commit to agentx3/simple-nixos-mailserver that referenced this pull request Sep 1, 2023
Option values are now rendered correctly as Nix thanks to
NixOS/nixpkgs#199363
serpent213 pushed a commit to serpent213/nixos-mailserver that referenced this pull request Nov 13, 2023
Option values are now rendered correctly as Nix thanks to
NixOS/nixpkgs#199363
VictorVSa pushed a commit to VictorVSa/nixos-mailserver that referenced this pull request Jan 14, 2024
add doc for full text search

Store FTS index in directory per domain & user to avoid collisions

Previously all the xapian files and logs would be stored in the same
folder for all users. This couid probably lead to weird situations where
all users get the same search results.

Mention the Freenode IRC chan #nixos-mailserver

Use services.clamav.daemon.settings if it is available

Feature/configurable delimiter

Rework the setup guide

Move indexDir option to the mailserver scope

This option has been initially in the mailserver.fullTextSearch
scope. However, this option modifies the location of all index files
of dovecot and not only those used by the full text search feature. It
is then more relevant to have this option in the mailserver top level
scope.

Moreover, the default option has been changed to null in order to keep
existing index files where they are: changing the index location means
recreating all index files. The fts documentation however recommend to
change this default location when enabling the fts feature.

corrected some pasting

Make vmail_user a system user

This is required since NixOS/nixpkgs#115332

Update nixpkgs-unstable

tests: increase memory limit for indexer process

otherwise fts-xapian with recent versions (1.4.9 at least) prints a
warning and the test fails

Rename intern/extern tests to internal/external

docs: link to an english Wikipedia article instead of a french one

Switch from Freenode to Libera

hydra: remove useless declInput argument

Remove duplicate `default` attribute on mailserver.forwards option

hydra: provide nixpkgs to allow Niv to use pkgs.fetchzip

kresd: no need to explicitly set nameserver

Since NixOS/nixpkgs#124391, enabling kreasd also
sets `networking.resolvconf.useLocalResolver = true`.

Remove nixos-20.03 job

We only support 2 releases.

Make Niv working in restricted evaluation mode

Release nixos-21.05

ci: simplify declarative-jobsets.nix

readme: switch from freenode to libera

Update nixpkgs-unstable

Because of
NixOS/nixpkgs@b7749c7
we need to `set +o pipefail` several asserts.

Switch CI to Nix flakes

We also move tests to Flakes.

This would allow users to submit PRs with a fork of nixpkgs when they
want to test nixpkgs PRs against SNM.

Remove Niv

It is now useless since we are using Nix Flakes

tests: update fts indexer log messages

ci: reenable 20.09 and 21.05 jobs :/

They haven't been moved to flake so we still need to keep the non
flake Hydra configuration.

Update nixpkgs-unstable

Remove non longer supported configurations (<21.05)

docs: generate the list of options

To generate the list of options, we need to generate and commit a rst
file to make all files available for ReadTheDoc.

An Hydra test ensures this generated file is up-to-date. If it is not
up-to-date, the error message explains the user how to generate it:
the user just needs to run `nix-shell --run generate-rst-options`.

Move the logo

Nixify the documentation build

Use the Junk mailbox name defined in the mailboxes attrs

Previously, the static Junk mailbox was used in sieve script to move
spam messages. This patch gets the Junk mailbox defined in the dovecot
mailboxes attribute instead.

Fixes #224

Ensure locally-delivered mails have the X-Original-To header

See #223

docs: remove output paths from generated documentation

Otherwise, the `testRstOptions` test would fail too often!

docs: fix the test which could never fail

Set DKIM policy to relaxed/relaxed

And make this policy configurable.

Fix typos in indexDir example

docs: add .readthedocs.yml conf file to pin Python dependencies

nginx.nix: don't reload nginx

Fixes #227

Reloading nginx manually is actually not needed (see
nginx-config-reload.service) and causes deadlocks.

opendkim: don't recreate keys if private key is present

rspamd: make sure redis is started over TCP socket

Fix fullTextSearch.enable=false

Revert "rspamd: make sure redis is started over TCP socket"

This reverts commit 4f0f0128d8d4115571b3ff0ce2378ddf7de7278e.

Redis does seem to run fine with both unixSocket and TCP enabled. This
broke people's setups.

nginx: generate certificates for custom domains and subdomains

Release nixos-21.11

ci: make release-21.11 a flake job

Fix CI job because of Nix new CLI options

make option documentation compatible with nixos-search

Drop 21.05 branch

Update nixos-unstable and drop 21.11

Regenerate options.rst

rspamd: set default port for redis

Since we are now using services.redis.servers.rspamd, the port defaults
to 0 (i.e. do not bind a TCP socket). We still want rspamd to connect to
redis via TCP, so set a default port that is one above the default redis port.

ci: enable the nix-command feature

docs: add how-to to setup roundcube

tests: compatibility with fts xapian 1.5.4

Fix typo in title

docs/full text search: fix typo; improve ux

docecot -> dovecot

Also, `indexDir` is not expecting to see %d/%n being passed to that
parameter, so remove that to make it easier to cpy the path into
there.

acme: Switch from `postRun` to `reloadServices` to fix hangs. Fixes #232

monit/rspamd: monitor by process name

Release 22.05

Convert minimal test to python test driver

htpasswd -> mkpasswd

docs: explicitly mention a reverse DNS entry is required

Fixes https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/issues/234

ci: pin nixpkgs to 22.05

Because hydra-cli build is currently broken on unstable.

rspamd: allow configuring dmarc reporting

Enabling collects DMARC results in Redis and sends out aggregated
reports (RUA) on a daily basis.

docs: option docs improvements

- add missing description and defaultText fields
- add dmarcReporting option group
- render examples

Removing 22.05 release

Because of some incompabilities with the 22.11 release.

doc: regenerate it

Release 22.11

docs: use MarkDown for option docs

docs: drop options.md from the repository

Generate the file on the readthedocs builder using Nix. Since there is
no root access or user namespaces, we have to use proot (see
https://nixos.wiki/wiki/Nix_Installation_Guide#PRoot).

Update nixpkgs

Option values are now rendered correctly as Nix thanks to
NixOS/nixpkgs#199363

docs: add instructions for rfc6186-compliant setup

opendkim: make public key world-readable

mail-server/dovecot: also learn spam/ham on APPEND

The current configuration doesn't work when moving spam from the INBOX
to Junk on a local maildir and then syncing the result to the IMAP
server with `mbsync(1)`. This is because `mbsync(1)` doesn't support a
mvoe-detection[1] (i.e. an IMAP MOVE which subsequently causes a Sieve
COPY according to RFC6851 which then triggers report{h,sp}am.sieve), but
instead sends `APPEND` (and removes the message in the src mailbox after
that).

Tested on my own mailserver that this fixes spam learning.

This doesn't work the other way round though because `APPEND` doesn't
have an origin. However, learning mails as spam happens more often than
learning spam as ham, so this is IMHO still useful.

[1] https://sourceforge.net/p/isync/mailman/isync-devel/thread/87y2p1tihz.fsf%40ericabrahamsen.net/#msg37030483

dovecot: split passdb and userdb

Fix test names

tests: use `services.dnsmasq.settings`

Gets rid of the warning about `extraConfig` being deprecated.

Allow using existing ACME certificates

Add a certificate scheme for using an existing ACME certificate without
setting up Nginx.

Also use names instead of magic numbers for certificate schemes.

Remove the NixOS 22.11 support

Because the option `nodes.domain1.services.dnsmasq.settings' does not
exist.

docs: add submissions DNS record for autodiscovery

Add the submissions autodiscovery SRV DNS record for implicit TLS in
SMTP (submission) connections according to
[RFC 8314](https://www.rfc-editor.org/rfc/rfc8314#section-5.1).

Improve the certificateScheme number deprecation warning message

Preserve the compatibility with nixos-22.11

readme: remove the announcement public key

Current maintainer no longer has it.

Release 23.05

dovecot: add dovecot_pigeonhole to system packages

`sieve-test` can be used to test sieve scripts.

It's annoying to nix-shell it in, because it reads the dovecot global
config and might stumble over incompatible .so files (as has happened
to me).

Simply providing it in $PATH is easier.

Fix and improve the setup guide

Add support for LDAP users

Allow configuring lookups for users and their mail addresses from an
LDAP directory. The LDAP username will be used as an accountname as
opposed to the email address used as the `loginName` for declarative
accounts. Mailbox for LDAP users will be stored below
`/var/vmail/ldap/<account>`.

Configuring domains is out of scope, since domains require further
configuration within the NixOS mailserver construct to set up all
related services accordingly.

Aliases can already be configured using `mailserver.forwards` but could
be supported using LDAP at a later point.

scripts/mail-check: allow passing the smtp username

Will be prefered over the from address when specified.

Create LDAP test

Sets up a declaratively configured OpenLDAP instance with users alice
and bob. They each own one email address,

First we test that postfix can communicate with LDAP and do the expected
lookups using the defined maps.

Then we use doveadm to make sure it can look up the two accounts.

Next we check the binding between account and mail address, by logging
in as alice and trying to send from bob@example.com, which alice is not
allowed to do. We expect postfix to reject the sender address here.

Finally we check mail delivery between alice and bob. Alice tries to
send a mail from alice@example.com to bob@example.com and bob then
checks whether it arrived in their mailbox.

Make the ldap test working

- The smtp/imap user name is now user@domain.tld
- Make the test_lookup function much more robust: it was now getting
  the correct file from the store.

ldap: do not write password to the Nix store

ldap: improve the documentation

ldap: set assertions to forbid ldap and loginAccounts simultaneously

dovecot: fix a typo on userAttrs

ldap: add an entry in the doc

Use umask for race-free permission setting

Without using umask there's a small time window where paths are world
readable. That is a bad idea to do for secret files (e.g. the dovecot
code path).

docs: fix link

Add support for regex (PCRE) aliases.

Add tests for regex (PCRE) aliases

dovecot: add support store mailbox names on disk using UTF-8

postfix: SMTP Smuggling Protection

Enable Postfix SMTP Smuggling protection, introduced in Postfix 3.8.4,
which is, currently, only available within the nixpkgs' master branch.

- NixOS/nixpkgs#276104
- NixOS/nixpkgs#276264

For information about SMTP Smuggling:

- https://www.postfix.org/smtp-smuggling.html
- https://www.postfix.org/postconf.5.html#smtpd_forbid_bare_newline

postfix: exclude $mynetwork from smtpd_forbid_bare_newline
agentx3 pushed a commit to agentx3/simple-nixos-mailserver that referenced this pull request Feb 26, 2024
Option values are now rendered correctly as Nix thanks to
NixOS/nixpkgs#199363
RyanGibb pushed a commit to RyanGibb/nixos-mailserver that referenced this pull request Mar 21, 2024
Option values are now rendered correctly as Nix thanks to
NixOS/nixpkgs#199363

Former-commit-id: 6d0d9fb966cc565a3df74d3b686f924c7615118c
bolives-hax pushed a commit to bolives-hax/nixos-mailserver that referenced this pull request May 21, 2024
Option values are now rendered correctly as Nix thanks to
NixOS/nixpkgs#199363
RyanGibb pushed a commit to RyanGibb/nixos-mailserver that referenced this pull request Jun 12, 2024
Option values are now rendered correctly as Nix thanks to
NixOS/nixpkgs#199363
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Examples in NixOS options manual do not escape attribute names
6 participants