summary refs log tree commit diff
path: root/nixos/modules/services/monitoring/parsedmarc.xml
blob: 7167b52d0357db4e7bb99d9b41697b7c7614f788 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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 recipient’s 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 domain’s 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 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.
    </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>