1# parsedmarc {#module-services-parsedmarc}
2[parsedmarc](https://domainaware.github.io/parsedmarc/) is a service
3which parses incoming [DMARC](https://dmarc.org/) reports and stores
4or sends them to a downstream service for further analysis. In
5combination with Elasticsearch, Grafana and the included Grafana
6dashboard, it provides a handy overview of DMARC reports over time.
7
8## Basic usage {#module-services-parsedmarc-basic-usage}
9A very minimal setup which reads incoming reports from an external
10email address and saves them to a local Elasticsearch instance looks
11like this:
12
13```nix
14{
15 services.parsedmarc = {
16 enable = true;
17 settings.imap = {
18 host = "imap.example.com";
19 user = "alice@example.com";
20 password = "/path/to/imap_password_file";
21 };
22 provision.geoIp = false; # Not recommended!
23 };
24}
25```
26
27Note that GeoIP provisioning is disabled in the example for
28simplicity, but should be turned on for fully functional reports.
29
30## Local mail {#module-services-parsedmarc-local-mail}
31Instead of watching an external inbox, a local inbox can be
32automatically provisioned. The recipient's name is by default set to
33`dmarc`, but can be configured in
34[services.parsedmarc.provision.localMail.recipientName](options.html#opt-services.parsedmarc.provision.localMail.recipientName). You
35need to add an MX record pointing to the host. More concretely: for
36the example to work, an MX record needs to be set up for
37`monitoring.example.com` and the complete email address that should be
38configured in the domain's dmarc policy is
39`dmarc@monitoring.example.com`.
40
41```nix
42{
43 services.parsedmarc = {
44 enable = true;
45 provision = {
46 localMail = {
47 enable = true;
48 hostname = monitoring.example.com;
49 };
50 geoIp = false; # Not recommended!
51 };
52 };
53}
54```
55
56## Grafana and GeoIP {#module-services-parsedmarc-grafana-geoip}
57The reports can be visualized and summarized with parsedmarc's
58official Grafana dashboard. For all views to work, and for the data to
59be complete, GeoIP databases are also required. The following example
60shows a basic deployment where the provisioned Elasticsearch instance
61is automatically added as a Grafana datasource, and the dashboard is
62added to Grafana as well.
63
64```nix
65{
66 services.parsedmarc = {
67 enable = true;
68 provision = {
69 localMail = {
70 enable = true;
71 hostname = url;
72 };
73 grafana = {
74 datasource = true;
75 dashboard = true;
76 };
77 };
78 };
79
80 # Not required, but recommended for full functionality
81 services.geoipupdate = {
82 settings = {
83 AccountID = 000000;
84 LicenseKey = "/path/to/license_key_file";
85 };
86 };
87
88 services.grafana = {
89 enable = true;
90 addr = "0.0.0.0";
91 domain = url;
92 rootUrl = "https://" + url;
93 protocol = "socket";
94 security = {
95 adminUser = "admin";
96 adminPasswordFile = "/path/to/admin_password_file";
97 secretKeyFile = "/path/to/secret_key_file";
98 };
99 };
100
101 services.nginx = {
102 enable = true;
103 recommendedTlsSettings = true;
104 recommendedOptimisation = true;
105 recommendedGzipSettings = true;
106 recommendedProxySettings = true;
107 upstreams.grafana.servers."unix:/${config.services.grafana.socket}" = {};
108 virtualHosts.${url} = {
109 root = config.services.grafana.staticRootPath;
110 enableACME = true;
111 forceSSL = true;
112 locations."/".tryFiles = "$uri @grafana";
113 locations."@grafana".proxyPass = "http://grafana";
114 };
115 };
116 users.users.nginx.extraGroups = [ "grafana" ];
117}
118```