diff --git a/dkim/defaults/main.yml b/dkim/defaults/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..518de5e91aad96b86fdbc281f30175b58e4b5843
--- /dev/null
+++ b/dkim/defaults/main.yml
@@ -0,0 +1,20 @@
+---
+
+dkim_canonicalization: "simple"
+dkim_mode: "sv"
+dkim_subdomains: "no"
+dkim_temp_dir: "/var/run/opendkim"
+dkim_base_dir: "/var/run/opendkim"
+
+dkim_must_be_signed: "From"
+dkim_on_bad_signature: "accept"  # TODO: evaluate after test phase
+
+dkim_query_cache: "yes"
+dkim_remove_old_signatures: "no"  # TODO: evaluate for RWTH Servers
+dkim_report_address: "{{ dovecot_admin_mail }}"
+dkim_send_reports: "no"  # TODO: evaluate after test phase
+dkim_software_headers: "yes" 
+
+dkim_signature_ttl: 0
+
+dkim_oversign_headers: "From"
diff --git a/dkim/tasks/main.yml b/dkim/tasks/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..4a5f6c2b970ed866486725408dcb6746a8995b48
--- /dev/null
+++ b/dkim/tasks/main.yml
@@ -0,0 +1,22 @@
+---
+
+- name: ensure opendkim is installed
+  apt:
+    name:
+      - opendkim
+      - opendkim-tools
+    state: present
+  
+
+- name: ensure opendkim config is present
+  template:
+    src: opendkim.conf.j2
+    dest: /etc/opendkim.conf
+    mode: "0640"
+
+- name: ensure domain files are present
+  template:
+    src: "{{item}}.j2"
+    dest: "/etc/opendkim/{{item}}"
+    with_items: 
+    
diff --git a/dkim/templates/dns_records.j2 b/dkim/templates/dns_records.j2
new file mode 100644
index 0000000000000000000000000000000000000000..8d1c8b69c3fce7bea45c73efd06983e3c419a92f
--- /dev/null
+++ b/dkim/templates/dns_records.j2
@@ -0,0 +1 @@
+ 
diff --git a/dkim/templates/key_table.j2 b/dkim/templates/key_table.j2
new file mode 100644
index 0000000000000000000000000000000000000000..3c8b4ad8bccb97583dbc2a6a32e600032d912c2d
--- /dev/null
+++ b/dkim/templates/key_table.j2
@@ -0,0 +1,4 @@
+{% for domain in dkim_domains %}
+{% set selector = domain.selector|default(ansible_nodename) %}
+{{ selector }}._domainkey.{{ domain.name }}  {{ domain.name }}:{{ selector }}:/etc/dkimkeys/{{ selector }}.private
+{% endfor %}
diff --git a/dkim/templates/opendkim.conf.j2 b/dkim/templates/opendkim.conf.j2
new file mode 100644
index 0000000000000000000000000000000000000000..aed3eda3ffe312d20ed1dc85399c3b82f7151677
--- /dev/null
+++ b/dkim/templates/opendkim.conf.j2
@@ -0,0 +1,77 @@
+# Log to syslog
+Syslog			yes
+Background      no
+# Required to use local socket with MTAs that access the socket as a non-
+# privileged user (e.g. Postfix)
+UMask			007
+
+# Sign for example.com with key in /etc/dkimkeys/dkim.key using
+# selector '2007' (e.g. 2007._domainkey.example.com)
+
+KeyTable file:/etc/opendkim/key_table
+SigningTable file:/etc/opendkim/signing_table
+ExternalIgnoreList file:/etc/opendkim/trusted_hosts
+InternalHosts file:/etc/opendkim/trusted_hosts
+
+
+# Commonly-used options; the commented-out versions show the defaults.
+
+Canonicalization	{{ dkim_canonicalization }}
+Mode			{{ dkim_mode }}
+SubDomains		{{ dkim_subdomains }}
+
+Socket			local:/var/run/opendkim/opendkim.sock
+PidFile               /var/run/opendkim/opendkim.pid
+
+TemporaryDirectory {{ dkim_temp_dir}}
+BaseDirectory {{ dkim_base_dir }}
+
+MustBeSigned {{ dkim_must_be_signed }}
+
+On-BadSignature {{ dkim_on_bad_signature }}
+
+QueryCache {{ dkim_query_cache }}
+RemoveOldSignatures {{ dkim_remove_old_signatures }}
+ReportAddress {{ dkim_report_address }}
+SendReports {{ dkim_send_reports }}
+SoftwareHeader {{ dkim_software_headers }}
+
+SignatureTTL {{ dkim_signature_ttl }}
+
+
+# Always oversign From (sign using actual From and a null From to prevent
+# malicious signatures header fields (From and/or others) between the signer
+# and the verifier.  From is oversigned by default in the Debian pacakge
+# because it is often the identity key used by reputation systems and thus
+# somewhat security sensitive.
+OversignHeaders		{{ dkim_oversign_headers }}
+
+##  ResolverConfiguration filename
+##      default (none)
+##
+##  Specifies a configuration file to be passed to the Unbound library that
+##  performs DNS queries applying the DNSSEC protocol.  See the Unbound
+##  documentation at http://unbound.net for the expected content of this file.
+##  The results of using this and the TrustAnchorFile setting at the same
+##  time are undefined.
+##  In Debian, /etc/unbound/unbound.conf is shipped as part of the Suggested
+##  unbound package
+
+# ResolverConfiguration     /etc/unbound/unbound.conf
+
+##  TrustAnchorFile filename
+##      default (none)
+##
+## Specifies a file from which trust anchor data should be read when doing
+## DNS queries and applying the DNSSEC protocol.  See the Unbound documentation
+## at http://unbound.net for the expected format of this file.
+
+TrustAnchorFile       /usr/share/dns/root.key
+
+##  Userid userid
+###      default (none)
+###
+###  Change to user "userid" before starting normal operation?  May include
+###  a group ID as well, separated from the userid by a colon.
+#
+UserID                opendkim
diff --git a/dkim/templates/opendkim.service b/dkim/templates/opendkim.service
new file mode 100644
index 0000000000000000000000000000000000000000..179b26fb7adc3f6e46fc9e480bf7372dc947b811
--- /dev/null
+++ b/dkim/templates/opendkim.service
@@ -0,0 +1,15 @@
+[Unit]
+Description=OpenDKIM DomainKeys Identified Mail (DKIM) Milter
+Documentation=man:opendkim(8) man:opendkim.conf(5) man:opendkim-genkey(8) man:opendkim-genzone(8) man:opendkim-testadsp(8) man:opendkim-testkey http://www.opendkim.org/docs.html
+After=network.target nss-lookup.target 
+
+[Service]
+Type=forking
+PIDFile=/var/run/opendkim/opendkim.pid
+UMask=0007
+ExecStart=/usr/sbin/opendkim -x /etc/opendkim.conf
+Restart=on-failure
+ExecReload=/bin/kill -USR1 $MAINPID
+
+[Install]
+WantedBy=multi-user.target
diff --git a/dkim/templates/signing_table.j2 b/dkim/templates/signing_table.j2
new file mode 100644
index 0000000000000000000000000000000000000000..0a579eb08842d7defb70086a20ed5026a449a69f
--- /dev/null
+++ b/dkim/templates/signing_table.j2
@@ -0,0 +1,4 @@
+{% for domain in dkim_domains %}
+{% set selector = domain.selector|default(ansible_nodename) %}
+{{ domain.name }} {{ selector }}._domainkey.{{ domain.name }}
+{% endfor %}
diff --git a/dkim/templates/trusted_hosts.j2 b/dkim/templates/trusted_hosts.j2
new file mode 100644
index 0000000000000000000000000000000000000000..caaba14503bc0e9b453347efa1cb7faf2b38ce94
--- /dev/null
+++ b/dkim/templates/trusted_hosts.j2
@@ -0,0 +1,12 @@
+127.0.0.1
+::1
+localhost
+{{ ansible_all_ipv4_addresses | join("\n") }}
+{{ ansible_all_ipv6_addresses | join("\n") }}
+{{ ansible_fqdn }}
+{% for domain in dkim_domains %}
+{{ domain.name }}
+{% endfor %}
+{% for host in groups["all"] %}
+{{ hostvars[host]["ansible_fqdn"] }}
+{% endfor %}