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