nixos/parsedmarc: Add manual entry and release note

This commit is contained in:
talyz 2021-06-03 18:31:15 +02:00
parent d46e78fd76
commit 6496902fb2
No known key found for this signature in database
GPG Key ID: 2DED2151F4671A2B
5 changed files with 259 additions and 0 deletions

View File

@ -239,6 +239,17 @@
<link xlink:href="options.html#opt-programs.git.enable">programs.git</link>.
</para>
</listitem>
<listitem>
<para>
<link xlink:href="https://domainaware.github.io/parsedmarc/">parsedmarc</link>,
a service which parses incoming
<link xlink:href="https://dmarc.org/">DMARC</link> reports and
stores or sends them to a downstream service for further
analysis. Documented in
<link linkend="module-services-parsedmarc">its manual
entry</link>.
</para>
</listitem>
</itemizedlist>
</section>
<section xml:id="sec-release-21.11-incompatibilities">

View File

@ -73,6 +73,11 @@ subsonic-compatible api. Available as [navidrome](#opt-services.navidrome.enable
- [git](https://git-scm.com), a distributed version control system. Available as [programs.git](options.html#opt-programs.git.enable).
- [parsedmarc](https://domainaware.github.io/parsedmarc/), a service
which parses incoming [DMARC](https://dmarc.org/) reports and stores
or sends them to a downstream service for further analysis.
Documented in [its manual entry](#module-services-parsedmarc).
## Backward Incompatibilities {#sec-release-21.11-incompatibilities}

View File

@ -0,0 +1,113 @@
# parsedmarc {#module-services-parsedmarc}
[parsedmarc](https://domainaware.github.io/parsedmarc/) is a service
which parses incoming [DMARC](https://dmarc.org/) reports and stores
or sends them to a downstream service for further analysis. In
combination with Elasticsearch, Grafana and the included Grafana
dashboard, it provides a handy overview of DMARC reports over time.
## Basic usage {#module-services-parsedmarc-basic-usage}
A very minimal setup which reads incoming reports from an external
email address and saves them to a local Elasticsearch instance looks
like this:
```nix
services.parsedmarc = {
enable = true;
settings.imap = {
host = "imap.example.com";
user = "alice@example.com";
password = "/path/to/imap_password_file";
watch = true;
};
provision.geoIp = false; # Not recommended!
};
```
Note that GeoIP provisioning is disabled in the example for
simplicity, but should be turned on for fully functional reports.
## Local mail
Instead of watching an external inbox, a local inbox can be
automatically provisioned. The recipient's name is by default set to
`dmarc`, but can be configured in
[services.parsedmarc.provision.localMail.recipientName](options.html#opt-services.parsedmarc.provision.localMail.recipientName). You
need to add an MX record pointing to the host. More concretely: for
the example to work, an MX record needs to be set up for
`monitoring.example.com` and the complete email address that should be
configured in the domain's dmarc policy is
`dmarc@monitoring.example.com`.
```nix
services.parsedmarc = {
enable = true;
provision = {
localMail = {
enable = true;
hostname = monitoring.example.com;
};
geoIp = false; # Not recommended!
};
};
```
## Grafana and GeoIP
The reports can be visualized and summarized with parsedmarc's
official Grafana dashboard. For all views to work, and for the data to
be complete, GeoIP databases are also required. The following example
shows a basic deployment where the provisioned Elasticsearch instance
is automatically added as a Grafana datasource, and the dashboard is
added to Grafana as well.
```nix
services.parsedmarc = {
enable = true;
provision = {
localMail = {
enable = true;
hostname = url;
};
grafana = {
datasource = true;
dashboard = true;
};
};
};
# Not required, but recommended for full functionality
services.geoipupdate = {
settings = {
AccountID = 000000;
LicenseKey = "/path/to/license_key_file";
};
};
services.grafana = {
enable = true;
addr = "0.0.0.0";
domain = url;
rootUrl = "https://" + url;
protocol = "socket";
security = {
adminUser = "admin";
adminPasswordFile = "/path/to/admin_password_file";
secretKeyFile = "/path/to/secret_key_file";
};
};
services.nginx = {
enable = true;
recommendedTlsSettings = true;
recommendedOptimisation = true;
recommendedGzipSettings = true;
recommendedProxySettings = true;
upstreams.grafana.servers."unix:/${config.services.grafana.socket}" = {};
virtualHosts.${url} = {
root = config.services.grafana.staticRootPath;
enableACME = true;
forceSSL = true;
locations."/".tryFiles = "$uri @grafana";
locations."@grafana".proxyPass = "http://grafana";
};
};
users.users.nginx.extraGroups = [ "grafana" ];
```

View File

@ -529,4 +529,9 @@ in
description = "DMARC mail recipient";
};
};
# Don't edit the docbook xml directly, edit the md and generate it:
# `pandoc parsedmarc.md -t docbook --top-level-division=chapter --extract-media=media -f markdown+smart > parsedmarc.xml`
meta.doc = ./parsedmarc.xml;
meta.maintainers = [ lib.maintainers.talyz ];
}

View File

@ -0,0 +1,125 @@
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-parsedmarc">
<title>parsedmarc</title>
<para>
<link xlink:href="https://domainaware.github.io/parsedmarc/">parsedmarc</link>
is a service which parses incoming
<link xlink:href="https://dmarc.org/">DMARC</link> reports and
stores or sends them to a downstream service for further analysis.
In combination with Elasticsearch, Grafana and the included Grafana
dashboard, it provides a handy overview of DMARC reports over time.
</para>
<section xml:id="module-services-parsedmarc-basic-usage">
<title>Basic usage</title>
<para>
A very minimal setup which reads incoming reports from an external
email address and saves them to a local Elasticsearch instance
looks like this:
</para>
<programlisting language="bash">
services.parsedmarc = {
enable = true;
settings.imap = {
host = &quot;imap.example.com&quot;;
user = &quot;alice@example.com&quot;;
password = &quot;/path/to/imap_password_file&quot;;
watch = true;
};
provision.geoIp = false; # Not recommended!
};
</programlisting>
<para>
Note that GeoIP provisioning is disabled in the example for
simplicity, but should be turned on for fully functional reports.
</para>
</section>
<section xml:id="local-mail">
<title>Local mail</title>
<para>
Instead of watching an external inbox, a local inbox can be
automatically provisioned. The recipients name is by default set
to <literal>dmarc</literal>, but can be configured in
<link xlink:href="options.html#opt-services.parsedmarc.provision.localMail.recipientName">services.parsedmarc.provision.localMail.recipientName</link>.
You need to add an MX record pointing to the host. More
concretely: for the example to work, an MX record needs to be set
up for <literal>monitoring.example.com</literal> and the complete
email address that should be configured in the domains dmarc
policy is <literal>dmarc@monitoring.example.com</literal>.
</para>
<programlisting language="bash">
services.parsedmarc = {
enable = true;
provision = {
localMail = {
enable = true;
hostname = monitoring.example.com;
};
geoIp = false; # Not recommended!
};
};
</programlisting>
</section>
<section xml:id="grafana-and-geoip">
<title>Grafana and GeoIP</title>
<para>
The reports can be visualized and summarized with parsedmarcs
official Grafana dashboard. For all views to work, and for the
data to be complete, GeoIP databases are also required. The
following example shows a basic deployment where the provisioned
Elasticsearch instance is automatically added as a Grafana
datasource, and the dashboard is added to Grafana as well.
</para>
<programlisting language="bash">
services.parsedmarc = {
enable = true;
provision = {
localMail = {
enable = true;
hostname = url;
};
grafana = {
datasource = true;
dashboard = true;
};
};
};
# Not required, but recommended for full functionality
services.geoipupdate = {
settings = {
AccountID = 000000;
LicenseKey = &quot;/path/to/license_key_file&quot;;
};
};
services.grafana = {
enable = true;
addr = &quot;0.0.0.0&quot;;
domain = url;
rootUrl = &quot;https://&quot; + url;
protocol = &quot;socket&quot;;
security = {
adminUser = &quot;admin&quot;;
adminPasswordFile = &quot;/path/to/admin_password_file&quot;;
secretKeyFile = &quot;/path/to/secret_key_file&quot;;
};
};
services.nginx = {
enable = true;
recommendedTlsSettings = true;
recommendedOptimisation = true;
recommendedGzipSettings = true;
recommendedProxySettings = true;
upstreams.grafana.servers.&quot;unix:/${config.services.grafana.socket}&quot; = {};
virtualHosts.${url} = {
root = config.services.grafana.staticRootPath;
enableACME = true;
forceSSL = true;
locations.&quot;/&quot;.tryFiles = &quot;$uri @grafana&quot;;
locations.&quot;@grafana&quot;.proxyPass = &quot;http://grafana&quot;;
};
};
users.users.nginx.extraGroups = [ &quot;grafana&quot; ];
</programlisting>
</section>
</chapter>