diff --git a/ansible/.ansible-lint b/ansible/.ansible-lint
index 0c31185..4534b90 100644
--- a/ansible/.ansible-lint
+++ b/ansible/.ansible-lint
@@ -1,2 +1,3 @@
+---
 skip_list:
-  - '403' # Package installs should not use latest.
+  - "403" # Package installs should not use latest.
diff --git a/ansible/deploy.yml b/ansible/deploy.yml
new file mode 100644
index 0000000..8e522c3
--- /dev/null
+++ b/ansible/deploy.yml
@@ -0,0 +1,19 @@
+---
+- name: Configure base
+  hosts: all
+  become: true
+  roles:
+    - role: dnf
+      when: ansible_facts['os_family'] == "RedHat"
+    - auditd
+    - fail2ban
+    - journald
+    - sshd
+    - role: timesyncd
+      when: ansible_facts['os_family'] == "Ubuntu"
+
+- name: Resolver
+  hosts: resolver
+  become: true
+  roles:
+    - knot_resolver
diff --git a/ansible/group_vars/all/all.yml b/ansible/group_vars/all/all.yml
new file mode 100644
index 0000000..bf06815
--- /dev/null
+++ b/ansible/group_vars/all/all.yml
@@ -0,0 +1,2 @@
+---
+resolver_ip: 10.20.0.42
diff --git a/ansible/group_vars/resolver/all.yml b/ansible/group_vars/resolver/all.yml
new file mode 100644
index 0000000..7b8e1fa
--- /dev/null
+++ b/ansible/group_vars/resolver/all.yml
@@ -0,0 +1,4 @@
+---
+kresd_allow:
+  - 10.0.0.0/8
+  - 172.16.0.0/12
diff --git a/ansible/hosts.yml b/ansible/hosts.yml
new file mode 100644
index 0000000..db621ac
--- /dev/null
+++ b/ansible/hosts.yml
@@ -0,0 +1,8 @@
+all:
+  hosts:
+    resolver-1:
+      ansible_host: 10.20.0.42
+  children:
+    resolver:
+      hosts:
+        resolver-1:
diff --git a/ansible/packer.yml b/ansible/packer.yml
index d5bf1ee..5df8ea6 100644
--- a/ansible/packer.yml
+++ b/ansible/packer.yml
@@ -13,5 +13,5 @@
       when: ansible_facts['os_family'] == "Ubuntu"
   post_tasks:
     - name: Clean cloud-init
-      ansible.builtin.command: "cloud-init clean"
+      ansible.builtin.command: cloud-init clean
       changed_when: false
diff --git a/ansible/roles/auditd/tasks/main.yml b/ansible/roles/auditd/tasks/main.yml
index 0c1cf00..90acfb8 100755
--- a/ansible/roles/auditd/tasks/main.yml
+++ b/ansible/roles/auditd/tasks/main.yml
@@ -19,6 +19,6 @@
 
 - name: Add rules
   ansible.builtin.copy:
-    src: 'custom.rules'
-    dest: '/etc/audit/rules.d/custom.rules'
+    src: custom.rules
+    dest: /etc/audit/rules.d/custom.rules
     mode: "0640"
diff --git a/ansible/roles/dnf/tasks/main.yml b/ansible/roles/dnf/tasks/main.yml
index fffeaa0..699c785 100644
--- a/ansible/roles/dnf/tasks/main.yml
+++ b/ansible/roles/dnf/tasks/main.yml
@@ -6,5 +6,5 @@
 
 - name: Install epel
   ansible.builtin.dnf:
-    name: "epel-release"
-    state: "latest"
+    name: epel-release
+    state: latest
diff --git a/ansible/roles/fail2ban/tasks/main.yml b/ansible/roles/fail2ban/tasks/main.yml
index 07c6109..b763312 100755
--- a/ansible/roles/fail2ban/tasks/main.yml
+++ b/ansible/roles/fail2ban/tasks/main.yml
@@ -1,20 +1,20 @@
 ---
 - name: Install fail2ban
   ansible.builtin.apt:
-    name: "fail2ban"
+    name: fail2ban
     state: latest
   when: ansible_facts['os_family'] == "Debian"
 
 - name: Install fail2ban
   ansible.builtin.dnf:
-    name: "fail2ban"
+    name: fail2ban
     state: latest
   when: ansible_facts['os_family'] == "RedHat"
 
 - name: Copy sshd.conf
   ansible.builtin.template:
-    src: 'sshd.conf.j2'
-    dest: '/etc/fail2ban/jail.d/sshd.conf'
+    src: sshd.conf.j2
+    dest: /etc/fail2ban/jail.d/sshd.conf
     mode: "0640"
   notify:
     - Restart fail2ban
diff --git a/ansible/roles/journald/tasks/main.yml b/ansible/roles/journald/tasks/main.yml
index 45400e5..880d904 100755
--- a/ansible/roles/journald/tasks/main.yml
+++ b/ansible/roles/journald/tasks/main.yml
@@ -1,14 +1,14 @@
 ---
 - name: Create /etc/systemd/journald.conf.d
   ansible.builtin.file:
-    path: '/etc/systemd/journald.conf.d'
-    state: 'directory'
+    path: /etc/systemd/journald.conf.d
+    state: directory
     mode: "0750"
 
 - name: Copy retention-time.conf
   ansible.builtin.copy:
-    src: 'retention-time.conf'
-    dest: '/etc/systemd/journald.conf.d'
+    src: retention-time.conf
+    dest: /etc/systemd/journald.conf.d
     mode: "0640"
   notify:
     - Restart journald
diff --git a/ansible/roles/knot_resolver/handlers/main.yml b/ansible/roles/knot_resolver/handlers/main.yml
new file mode 100644
index 0000000..e40da42
--- /dev/null
+++ b/ansible/roles/knot_resolver/handlers/main.yml
@@ -0,0 +1,19 @@
+---
+- name: Package cache update
+  become: true
+  ansible.builtin.package:
+    update_cache: true
+
+- name: Restart knot resolver
+  become: true
+  ansible.builtin.service:
+    state: restarted
+    name: kresd@{{ item }}.service
+  with_sequence: count={{ ansible_processor_vcpus }}
+
+- name: Enable knot resolver
+  become: true
+  ansible.builtin.service:
+    enabled: true
+    name: kresd@{{ item }}.service
+  with_sequence: count={{ ansible_processor_vcpus }}
diff --git a/ansible/roles/knot_resolver/tasks/main.yml b/ansible/roles/knot_resolver/tasks/main.yml
new file mode 100644
index 0000000..e798b06
--- /dev/null
+++ b/ansible/roles/knot_resolver/tasks/main.yml
@@ -0,0 +1,21 @@
+---
+- name: Install knot repository
+  ansible.builtin.apt:
+    deb: https://secure.nic.cz/files/knot-resolver/knot-resolver-release.deb
+  notify:
+    - Package cache update
+
+- name: Install knot resolver
+  ansible.builtin.apt:
+    name: knot-resolver
+  notify:
+    - Enable knot resolver
+    - Restart knot resolver
+
+- name: Configure
+  ansible.builtin.template:
+    src: kresd.conf.j2
+    dest: /etc/knot-resolver/kresd.conf
+    mode: "0644"
+  notify:
+    - Restart knot resolver
diff --git a/ansible/roles/knot_resolver/templates/kresd.conf.j2 b/ansible/roles/knot_resolver/templates/kresd.conf.j2
new file mode 100644
index 0000000..8754040
--- /dev/null
+++ b/ansible/roles/knot_resolver/templates/kresd.conf.j2
@@ -0,0 +1,26 @@
+net.listen('{{resolver_ip}}', 53, { kind = 'dns'})
+cache.size = 128 * MB
+modules = {
+	'hints > iterate',  -- Allow loading /etc/hosts or custom root hints
+	'predict',          -- Prefetch expiring/frequent records
+}
+
+modules.load('prefill')
+prefill.config({
+    ['.'] = {
+        url = 'https://www.internic.net/domain/root.zone',
+        interval = 86400, -- seconds
+    }
+})
+
+modules.load('view')
+view:addr('127.0.0.0/8', policy.all(policy.PASS))
+view:addr('::1/128', policy.all(policy.PASS))
+{% for prefix in kresd_allow %}
+view:addr('{{ prefix }}', policy.all(policy.PASS))
+{% endfor %}
+view:addr('0.0.0.0/0', policy.all(policy.DROP))
+view:addr('::/0', policy.all(policy.DROP))
+
+log_target('stdout')
+log_level('debug') 
\ No newline at end of file
diff --git a/ansible/roles/sshd/handlers/main.yml b/ansible/roles/sshd/handlers/main.yml
index 89aa775..435d655 100644
--- a/ansible/roles/sshd/handlers/main.yml
+++ b/ansible/roles/sshd/handlers/main.yml
@@ -1,3 +1,4 @@
+---
 - name: Restart SSH
   ansible.builtin.service:
     name: sshd
diff --git a/ansible/roles/sshd/tasks/main.yml b/ansible/roles/sshd/tasks/main.yml
index 31f34f7..4bb826d 100644
--- a/ansible/roles/sshd/tasks/main.yml
+++ b/ansible/roles/sshd/tasks/main.yml
@@ -2,8 +2,8 @@
 - name: Disable Password Authentication
   ansible.builtin.lineinfile:
     dest: /etc/ssh/sshd_config
-    regexp: '^PasswordAuthentication'
-    line: "PasswordAuthentication no"
+    regexp: ^PasswordAuthentication
+    line: PasswordAuthentication no
     state: present
     backup: true
   notify:
@@ -12,8 +12,8 @@
 - name: Disable Root Login
   ansible.builtin.lineinfile:
     dest: /etc/ssh/sshd_config
-    regexp: '^PermitRootLogin'
-    line: "PermitRootLogin no"
+    regexp: ^PermitRootLogin
+    line: PermitRootLogin no
     state: present
     backup: true
   notify:
@@ -22,8 +22,8 @@
 - name: Restrict host key
   ansible.builtin.lineinfile:
     dest: /etc/ssh/sshd_config
-    regexp: '#HostKey /etc/ssh/ssh_host_ed25519_key'
-    line: "HostKey /etc/ssh/ssh_host_ed25519_key"
+    regexp: "#HostKey /etc/ssh/ssh_host_ed25519_key"
+    line: HostKey /etc/ssh/ssh_host_ed25519_key
     state: present
     backup: true
   notify:
@@ -31,8 +31,8 @@
 
 - name: Configure sshd
   ansible.builtin.copy:
-    src: "crypto.conf"
-    dest: "/etc/ssh/sshd_config.d/"
+    src: crypto.conf
+    dest: /etc/ssh/sshd_config.d/
     owner: root
     group: root
     mode: "0640"
diff --git a/ansible/roles/timesyncd/tasks/main.yml b/ansible/roles/timesyncd/tasks/main.yml
index 51079fe..f747c0c 100755
--- a/ansible/roles/timesyncd/tasks/main.yml
+++ b/ansible/roles/timesyncd/tasks/main.yml
@@ -4,5 +4,5 @@
     name: Europe/Brussels
 
 - name: Enable ntp
-  ansible.builtin.command: 'timedatectl set-ntp true'
+  ansible.builtin.command: timedatectl set-ntp true
   changed_when: false