diff --git a/playbooks/aur.yml b/playbooks/aur.yml
new file mode 100644
index 0000000000000000000000000000000000000000..15f53720a281bff94c3be07591c82a9b6e8adbbe
--- /dev/null
+++ b/playbooks/aur.yml
@@ -0,0 +1,10 @@
+---
+
+- name: setup aur server
+  hosts: 127.0.0.1
+  remote_user: root
+  roles:
+    - { role: mariadb, mariadb_innodb_buffer_pool_size: '64M', tags: ['mariadb'] , configure_zabbix_agent: False}
+    - { role: nginx, tags: ["nginx"] }
+    - { role: php-fpm, php_extensions: ['pdo_mysql'], tags: ["php-fpm"] }
+    - { role: aur, tags: ['aur'] }
diff --git a/roles/aur/defaults/main.yml b/roles/aur/defaults/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..361ab43a854baeffc196b2cb6ef07e6d07f11952
--- /dev/null
+++ b/roles/aur/defaults/main.yml
@@ -0,0 +1,17 @@
+---
+
+aurweb_domain: 'www.aur.archlinux.org'
+aurweb_repository: 'https://git.archlinux.org/aurweb.git'
+aurweb_dir: '/srv/http/aurweb'
+aurweb_conf_dir: '/etc/aurweb'
+aurweb_git_dir: "{{ aurweb_dir }}/aur.git"
+aurweb_git_hook: '/usr/local/bin/aurweb-git-update'
+aurweb_version: 'master'
+
+aurweb_db: 'aur'
+aurweb_db_host: 'localhost'
+aurweb_db_user: 'aur'
+aurweb_db_password: 'aur'
+
+aurweb_user: 'aurweb'
+aurweb_socket: '/run/php-fpm/{{aurweb_user}}.socket'
diff --git a/roles/aur/files/aurweb-aurblup.service b/roles/aur/files/aurweb-aurblup.service
new file mode 100644
index 0000000000000000000000000000000000000000..d3d007c97ba42bb7e33c83c2c0619adf3a02f160
--- /dev/null
+++ b/roles/aur/files/aurweb-aurblup.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Update aurweb blacklist
+Requires=mysqld.service
+After=mysqld.service
+
+[Service]
+Type=Oneshot
+User=aur
+ExecStart=/usr/local/bin/aurweb-aurblup
diff --git a/roles/aur/files/aurweb-aurblup.timer b/roles/aur/files/aurweb-aurblup.timer
new file mode 100644
index 0000000000000000000000000000000000000000..48db8acc2da2362dca74d1fd38469865508fb1ad
--- /dev/null
+++ b/roles/aur/files/aurweb-aurblup.timer
@@ -0,0 +1,9 @@
+[Unit]
+Description=Update aurweb blacklist
+
+[Timer]
+OnStartupSec=2h
+OnUnitActiveSec=2h
+
+[Install]
+WantedBy=timers.target
diff --git a/roles/aur/files/aurweb-mkpkglists.service b/roles/aur/files/aurweb-mkpkglists.service
new file mode 100644
index 0000000000000000000000000000000000000000..b0f6c44df4f28bc1c687759fe23a7be24d97514c
--- /dev/null
+++ b/roles/aur/files/aurweb-mkpkglists.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Regenerate aurweb package and user lists
+Requires=mysqld.service
+After=mysqld.service
+
+[Service]
+Type=Oneshot
+User=aur
+ExecStart=/usr/local/bin/aurweb-mkpkglists
diff --git a/roles/aur/files/aurweb-mkpkglists.timer b/roles/aur/files/aurweb-mkpkglists.timer
new file mode 100644
index 0000000000000000000000000000000000000000..b1ee108c8e338b394271de268fa595b967975686
--- /dev/null
+++ b/roles/aur/files/aurweb-mkpkglists.timer
@@ -0,0 +1,9 @@
+[Unit]
+Description=Regenerate aurweb package and user lists
+
+[Timer]
+OnStartupSec=5m
+OnUnitActiveSec=5m
+
+[Install]
+WantedBy=timers.target
diff --git a/roles/aur/files/aurweb-pkgmaint.service b/roles/aur/files/aurweb-pkgmaint.service
new file mode 100644
index 0000000000000000000000000000000000000000..83ba2a4c49ff476411398709b88034152e37f3b3
--- /dev/null
+++ b/roles/aur/files/aurweb-pkgmaint.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Delete old, empty reserved aurweb pkgbases
+Requires=mysqld.service
+After=mysqld.service
+
+[Service]
+Type=Oneshot
+User=aur
+ExecStart=/usr/local/bin/aurweb-pkgmaint
diff --git a/roles/aur/files/aurweb-pkgmaint.timer b/roles/aur/files/aurweb-pkgmaint.timer
new file mode 100644
index 0000000000000000000000000000000000000000..a29753102335651da7eb87411974c7a43a175a67
--- /dev/null
+++ b/roles/aur/files/aurweb-pkgmaint.timer
@@ -0,0 +1,9 @@
+[Unit]
+Description=Delete old, empty reserved aurweb pkgbases
+
+[Timer]
+OnStartupSec=2h
+OnUnitActiveSec=2h
+
+[Install]
+WantedBy=timers.target
diff --git a/roles/aur/files/aurweb-popupdate.service b/roles/aur/files/aurweb-popupdate.service
new file mode 100644
index 0000000000000000000000000000000000000000..8850eec86508d1612b10fabf7fb0f246e9f16e83
--- /dev/null
+++ b/roles/aur/files/aurweb-popupdate.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Update aurweb per-package popularity counts
+Requires=mysqld.service
+After=mysqld.service
+
+[Service]
+Type=Oneshot
+User=aur
+ExecStart=/usr/local/bin/aurweb-popupdate
diff --git a/roles/aur/files/aurweb-popupdate.timer b/roles/aur/files/aurweb-popupdate.timer
new file mode 100644
index 0000000000000000000000000000000000000000..69805f094ae05e4a0688f36ffb3000009f19265b
--- /dev/null
+++ b/roles/aur/files/aurweb-popupdate.timer
@@ -0,0 +1,9 @@
+[Unit]
+Description=Update aurweb per-package popularity counts
+
+[Timer]
+OnStartupSec=2h
+OnUnitActiveSec=2h
+
+[Install]
+WantedBy=timers.target
diff --git a/roles/aur/files/aurweb-tuvotereminder.service b/roles/aur/files/aurweb-tuvotereminder.service
new file mode 100644
index 0000000000000000000000000000000000000000..b66859f0e6617c6f812ef0e8b756be4696640082
--- /dev/null
+++ b/roles/aur/files/aurweb-tuvotereminder.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Send aurweb TU vote reminder emails
+Requires=mysqld.service
+After=mysqld.service
+
+[Service]
+Type=Oneshot
+User=aur
+ExecStart=/usr/local/bin/aurweb-tuvotereminder
diff --git a/roles/aur/files/aurweb-tuvotereminder.timer b/roles/aur/files/aurweb-tuvotereminder.timer
new file mode 100644
index 0000000000000000000000000000000000000000..c22b99e1ab15befcac5fef320da22bf82f816381
--- /dev/null
+++ b/roles/aur/files/aurweb-tuvotereminder.timer
@@ -0,0 +1,9 @@
+[Unit]
+Description=Send aurweb TU vote reminder emails
+
+[Timer]
+OnStartupSec=12h
+OnUnitActiveSec=12h
+
+[Install]
+WantedBy=timers.target
diff --git a/roles/aur/handlers/main.yml b/roles/aur/handlers/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..1793138fabb5bf7b22686762e151ef2d1c70501b
--- /dev/null
+++ b/roles/aur/handlers/main.yml
@@ -0,0 +1,7 @@
+---
+
+- name: daemon reload
+  command: systemctl daemon-reload
+
+- name: restart php-fpm@aurweb
+  service: name=php-fpm@{{ aurweb_user }} state=restarted
diff --git a/roles/aur/tasks/main.yml b/roles/aur/tasks/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..d0e3de0fb5ae81ff8a65f09e7ac224c4059f9cfa
--- /dev/null
+++ b/roles/aur/tasks/main.yml
@@ -0,0 +1,172 @@
+---
+- name: install required packages
+  pacman: name=git,sudo,python-mysql-connector,python-pygit2,python-srcinfo,python-bleach,python-markdown,make,asciidoc state=present
+
+- name: make aur user
+  user: name="{{ aurweb_user }}" shell=/bin/bash createhome=yes
+
+- name: Create directory
+  file: path={{ aurweb_dir }} state=directory owner={{aurweb_user}} group=http mode=0775
+
+- name: clone aurweb repo
+  git: >
+    repo={{ aurweb_repository }}
+    dest="{{ aurweb_dir }}"
+    version={{ aurweb_version }}
+  become: true
+  become_user: "{{aurweb_user}}"
+  register: release
+
+- name: create aur db
+  mysql_db: name="{{ aurweb_db }}" login_host="{{ aurweb_db_host }}" login_password="{{ mariadb_users.root }}" encoding=utf8
+  register: db_created
+
+- name: create aur db user
+  mysql_user: name={{ aurweb_db_user }} password={{ aurweb_db_password }}
+              login_host="{{ aurweb_db_host }}" login_password="{{ mariadb_users.root }}"
+              priv="{{ aurweb_db }}.*:ALL"
+
+- name: enable innodb_large_prefix
+  mysql_variables:
+    login_host: "{{ aurweb_db_host }}"
+    login_password: "{{ mariadb_users.root }}"
+    variable: innodb_large_prefix
+    value: 1
+
+- name: enable innodb_file_format
+  mysql_variables:
+    login_host: "{{ aurweb_db_host }}"
+    login_password: "{{ mariadb_users.root }}"
+    variable: innodb_file_format
+    value: Barracuda
+
+- name: check if db is imported
+  shell: mysql -u {{ aurweb_db_user }} -p{{ aurweb_db_password }} -e "SELECT ID FROM Users" {{ aurweb_db }}
+  ignore_errors: true
+  register: db_imported
+
+- name: import aur sql db
+  mysql_db:
+    state: import
+    name: "{{ aurweb_db }}"
+    login_host: "{{ aurweb_db_host }}"
+    login_password: "{{ mariadb_users.root }}"
+    target: "{{ aurweb_dir }}/schema/aur-schema.sql"
+  when: db_imported.rc != 0
+
+- name: create aurweb conf dir
+  file: path={{ aurweb_conf_dir }} state=directory
+
+- name: copy aurweb configuration file
+  copy: src={{ aurweb_dir }}/conf/config.defaults dest={{ aurweb_conf_dir }}/config.defaults remote_src=yes
+
+- name: install custom aurweb configuration
+  template: src=config.j2 dest={{ aurweb_conf_dir }}/config
+
+- name: Install python module
+  shell: "python3 setup.py install --install-scripts=/usr/local/bin"
+  args:
+    chdir: "{{ aurweb_dir }}"
+
+- name: Generate HTML documentation
+  make:
+      chdir: "{{ aurweb_dir }}/doc"
+  become: true
+  become_user: "{{aurweb_user}}"
+
+- name: set up nginx
+  template: src=nginx.d.conf.j2 dest=/etc/nginx/nginx.d/aurweb.conf owner=root group=root mode=644
+  notify: reload nginx
+  tags: ['nginx']
+
+- name: make nginx log dir
+  file: path=/var/log/nginx/{{ aurweb_domain }} state=directory owner=root group=root mode=0755
+
+- name: configure php-fpm
+  template:
+    src=php-fpm.conf.j2 dest="/etc/php/php-fpm.d/{{ aurweb_user }}.conf"
+    owner=root group=root mode=0644
+  notify:
+    - restart php-fpm@{{ aurweb_user }}
+
+- name: start and enable systemd socket
+  service: name=php-fpm@{{ aurweb_user }}.socket state=started enabled=true
+
+- name: create git repo dir
+  file: path={{ aurweb_git_dir }} state=directory owner={{aurweb_user}} group=http mode=0775
+
+- name: init git directory
+  command: git init --bare {{ aurweb_git_dir }}
+  args:
+    creates: "{{ aurweb_git_dir }}/HEAD"
+  become: true
+  become_user: "{{aurweb_user}}"
+
+- shell: git config --local --get-all transfer.hideRefs
+  register: git_config
+  args:
+    chdir: "{{ aurweb_git_dir }}"
+  failed_when: git_config.rc == 2 # FIXME: does not work.
+
+- name: configure git tranfser.hideRefs
+  command: git config --local transfer.hideRefs '^refs/'
+  args:
+    chdir: "{{ aurweb_git_dir }}"
+  become: true
+  become_user: "{{aurweb_user}}"
+  when: git_config.stdout.find('^refs/') == -1
+
+
+- name: configure git transfer.hideRefs second
+  command: git config --local --add transfer.hideRefs '!refs/'
+  args:
+    chdir: "{{ aurweb_git_dir }}"
+  become: true
+  become_user: "{{aurweb_user}}"
+  when: git_config.stdout.find('!refs/') == -1
+
+- name: configure git transfer.hideRefs third
+  command: git config --local --add transfer.hideRefs '!HEAD'
+  args:
+    chdir: "{{ aurweb_git_dir }}"
+  become: true
+  become_user: "{{aurweb_user}}"
+  when: git_config.stdout.find('!HEAD') == -1
+
+- name: create symlink for git hook
+  file:
+    src: "{{ aurweb_git_hook }}"
+    dest: "{{ aurweb_git_dir }}/hooks/update"
+    state: link
+
+- name: install AUR maintenance services/timers
+  copy: src={{ item }} dest=/etc/systemd/system/{{ item }} owner=root group=root mode=0644
+  with_items:
+      - aurweb-aurblup.service
+      - aurweb-aurblup.timer
+      - aurweb-mkpkglists.service
+      - aurweb-mkpkglists.timer
+      - aurweb-pkgmaint.service
+      - aurweb-pkgmaint.timer
+      - aurweb-popupdate.service
+      - aurweb-popupdate.timer
+      - aurweb-tuvotereminder.service
+      - aurweb-tuvotereminder.timer
+
+- name: start and enable AUR maintenance timers
+  service: name={{ item }} enabled=yes state=started
+  with_items:
+      - aurweb-aurblup.timer
+      - aurweb-mkpkglists.timer
+      - aurweb-pkgmaint.timer
+      - aurweb-popupdate.timer
+      - aurweb-tuvotereminder.timer
+
+- name: install AUR git gc service/timer
+  template: src={{ item }}.j2 dest=/etc/systemd/system/{{ item }} owner=root group=root mode=0644
+  with_items:
+      - aurweb-git.service
+      - aurweb-git.timer
+
+- name: start and enable AUR git gc timer
+  service: name=aurweb-git.timer enabled=yes state=started
diff --git a/roles/aur/templates/aurweb-git.service.j2 b/roles/aur/templates/aurweb-git.service.j2
new file mode 100644
index 0000000000000000000000000000000000000000..adbf3a803c3b2b6c6adf7d8bf74bd9352c142710
--- /dev/null
+++ b/roles/aur/templates/aurweb-git.service.j2
@@ -0,0 +1,9 @@
+[Unit]
+Description=Git gc AUR
+
+[Service]
+Type=Oneshot
+User=aur
+WorkingDirectory={{ aurweb_git_dir }}
+ExecStart=/usr/bin/git gc
+Nice=5
diff --git a/roles/aur/templates/aurweb-git.timer.j2 b/roles/aur/templates/aurweb-git.timer.j2
new file mode 100644
index 0000000000000000000000000000000000000000..f95766091b55c75c1d8a512a51333bcefb818a5c
--- /dev/null
+++ b/roles/aur/templates/aurweb-git.timer.j2
@@ -0,0 +1,8 @@
+[Unit]
+Description=Git gc & repack AUR
+
+[Timer]
+OnCalendar=daily
+
+[Install]
+WantedBy=timers.target
diff --git a/roles/aur/templates/config.j2 b/roles/aur/templates/config.j2
new file mode 100644
index 0000000000000000000000000000000000000000..d5fd185101182c26e6aa0e1d2df406211f8ed5d9
--- /dev/null
+++ b/roles/aur/templates/config.j2
@@ -0,0 +1,21 @@
+[database]
+name = {{ aurweb_db }}
+user = {{ aurweb_db_user }}
+password = {{ aurweb_db_password }}
+
+[options]
+enable-maintenance = 0
+localedir = {{ aurweb_dir }}/web/locale/
+
+[serve]
+repo-path = {{ aurweb_git_dir }}
+git-shell-cmd = /usr/bin/sh
+
+[aurblup]
+db-path = {{ aurweb_dir }}/aurblup
+server = https://mirrors.kernel.org/archlinux/%s/os/x86_64
+
+[mkpkglists]
+packagesfile = {{ aurweb_dir }}/web/html/packages.gz
+pkgbasefile = {{ aurweb_dir }}/web/html/pkgbase.gz
+userfile = {{ aurweb_dir }}/web/html/users.gz
diff --git a/roles/aur/templates/nginx.d.conf.j2 b/roles/aur/templates/nginx.d.conf.j2
new file mode 100644
index 0000000000000000000000000000000000000000..3d40cc1e9005030750cd17d99e0afa1df2a3c3ac
--- /dev/null
+++ b/roles/aur/templates/nginx.d.conf.j2
@@ -0,0 +1,47 @@
+upstream aurweb {
+    server unix://{{aurweb_socket}};
+}
+
+server {
+    listen       80;
+    listen       [::]:80;
+    server_name  {{ aurweb_domain }};
+
+    access_log   /var/log/nginx/{{ aurweb_domain }}/access.log main;
+    error_log    /var/log/nginx/{{ aurweb_domain }}/error.log;
+
+    include snippets/letsencrypt.conf;
+
+    location / {
+        rewrite ^(.*) https://{{ aurweb_domain }}$1 permanent;
+    }
+}
+
+server {
+    listen       443 ssl http2;
+    listen       [::]:443 ssl http2;
+    server_name  {{ aurweb_domain }};
+
+    access_log   /var/log/nginx/{{ aurweb_domain }}/access.log main;
+    error_log    /var/log/nginx/{{ aurweb_domain }}/error.log;
+
+    ssl_certificate      /etc/letsencrypt/live/{{ aurweb_domain }}/fullchain.pem;
+    ssl_certificate_key  /etc/letsencrypt/live/{{ aurweb_domain }}/privkey.pem;
+    ssl_trusted_certificate /etc/letsencrypt/live/{{ aurweb_domain }}/chain.pem;
+
+    root    {{ aurweb_dir }}/web/html;
+    index   index.php;
+
+    location ~ ^/[^/]+\.php($|/) {
+         fastcgi_pass   aurweb;
+         fastcgi_index  index.php;
+         fastcgi_split_path_info ^(/[^/]+\.php)(/.*)$;
+         fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
+         fastcgi_param  PATH_INFO        $fastcgi_path_info;
+         include        fastcgi_params;
+    }
+  
+    location ~ .* {
+         rewrite ^/(.*)$ /index.php/$1 last;
+    } 
+}
diff --git a/roles/aur/templates/php-fpm.conf.j2 b/roles/aur/templates/php-fpm.conf.j2
new file mode 100644
index 0000000000000000000000000000000000000000..47f75ec628df47eb9ce525bece8bcf97372be6fe
--- /dev/null
+++ b/roles/aur/templates/php-fpm.conf.j2
@@ -0,0 +1,21 @@
+[global]
+error_log = syslog
+daemonize = no
+
+[{{ aurweb_user }}]
+listen = {{ aurweb_socket }}
+listen.owner = {{ aurweb_user }}
+listen.group = http
+listen.mode = 0660
+
+pm = dynamic
+pm.max_children = 80
+pm.start_servers = 20
+pm.min_spare_servers = 10
+pm.max_spare_servers = 20
+pm.max_requests = 2000
+
+php_admin_value[open_basedir] = {{aurweb_dir}}:/etc/aurweb/
+php_admin_value[upload_tmp_dir] = {{ aurweb_dir }}/uploads
+php_admin_value[session.save_path] = {{ aurweb_dir }}/sessions
+env[TMPDIR] = {{ aurweb_dir }}/uploads