diff --git a/roles/flyspray/handlers/main.yml b/roles/flyspray/handlers/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..f9ee6636586fd8066c42050e97a27c9130809a35
--- /dev/null
+++ b/roles/flyspray/handlers/main.yml
@@ -0,0 +1,4 @@
+---
+
+- name: daemon reload
+  command: systemctl daemon-reload
diff --git a/roles/flyspray/tasks/main.yml b/roles/flyspray/tasks/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..66319e667e78d456532f99ddc84573f245fb9b41
--- /dev/null
+++ b/roles/flyspray/tasks/main.yml
@@ -0,0 +1,42 @@
+---
+
+- name: install git
+  pacman: name=git state=present
+
+- name: make flyspray user
+  user: name=flyspray shell=/bin/false home="{{ flyspray_dir }}" createhome=no
+
+- name: fix home permissions
+  file: state=directory owner=flyspray group=flyspray path="{{ flyspray_dir }}"
+
+- name: set up nginx
+  template: src=nginx.d.conf.j2 dest=/etc/nginx/nginx.d/flyspray.conf owner=root group=root mode=644
+  notify:
+    - reload nginx
+
+- name: make nginx log dir
+  file: path=/var/log/nginx/{{ flyspray_domain }} state=directory owner=http group=log mode=755
+
+- name: clone flyspray repo
+  git: repo=git://git.archlinux.org/vhosts/bugs.archlinux.org.git dest="{{ flyspray_dir }}"
+  become: true
+  become_user: flyspray
+  register: release
+
+- name: fix home permissions
+  file: state=directory owner=flyspray group=flyspray path="{{ flyspray_dir }}"
+
+- name: configure flyspray
+  template: src=flyspray.conf.php.j2 dest=/srv/http/flyspray/flyspray.conf.php owner=flyspray group=flyspray mode=0660
+  register: config
+  no_log: true
+
+- name: create flyspray db
+  mysql_db: name="{{ flyspray_db }}" login_host="{{ flyspray_db_host }}" login_password="{{ mariadb_users.root }}"
+  register: db_created
+
+- name: create flyspray db user
+  mysql_user: name={{ flyspray_db_user }} password={{ flyspray_db_password }}
+              login_host="{{ flyspray_db_host }}" login_password="{{ mariadb_users.root }}"
+              priv="{{ flyspray_db }}.*:ALL"
+  no_log: true
diff --git a/roles/flyspray/templates/flyspray.conf.php.j2 b/roles/flyspray/templates/flyspray.conf.php.j2
new file mode 100644
index 0000000000000000000000000000000000000000..d9a4c274baad657f71753cc0afb2c00af68687e8
--- /dev/null
+++ b/roles/flyspray/templates/flyspray.conf.php.j2
@@ -0,0 +1,31 @@
+; <?php die( 'Do not access this page directly.' ); ?>
+
+[general]
+cookiesalt="{{ flyspray_cookie_salt }}"
+output_buffering="on"
+address_rewriting="1"
+reminder_daemon="0"
+passwdcrypt="md5"
+doku_url="https://wiki.archlinux.org/"
+syntax_plugin="none"
+update_check="0"
+
+[database]
+dbtype="mysqli"
+dbhost="{{ flyspray_db_host }}"
+dbname="{{ flyspray_db }}"
+dbuser="{{ flyspray_db_user }}"
+dbpass="{{ flyspray_db_password }}"
+dbprefix="flyspray_"
+
+[attachments]
+zip="application/zip"
+tgz="application/x-gzip"
+gz="application/x-gzip"
+bz2="application/x-bzip2"
+png="image/png"
+gif="image/gif"
+jpg="image/jpeg"
+jpeg="image/jpeg"
+html="text/html"
+xml="application/xml"
diff --git a/roles/flyspray/templates/nginx.d.conf.j2 b/roles/flyspray/templates/nginx.d.conf.j2
new file mode 100644
index 0000000000000000000000000000000000000000..2aa12a4e1209cf52f16e229f8117f637c8a633d0
--- /dev/null
+++ b/roles/flyspray/templates/nginx.d.conf.j2
@@ -0,0 +1,48 @@
+upstream flyspray {
+    server unix:///run/php-fpm/flyspray.sock;
+}
+
+server {
+    listen       80;
+    listen       [::]:80;
+    server_name  {{ flyspray_domain }};
+
+    access_log   /var/log/nginx/{{ flyspray_domain }}/access.log;
+    error_log    /var/log/nginx/{{ flyspray_domain }}/error.log;
+
+    include snippets/letsencrypt.conf;
+
+    location / {
+        rewrite ^(.*) https://$server_name$1 permanent;
+    }
+}
+
+server {
+    listen       443 ssl http2;
+    listen       [::]:443 ssl http2;
+    server_name  {{ flyspray_domain }};
+
+    access_log   /var/log/nginx/{{ flyspray_domain }}/access.log;
+    error_log    /var/log/nginx/{{ flyspray_domain }}/error.log;
+
+    ssl_certificate      /etc/letsencrypt/live/{{ flyspray_domain }}/fullchain.pem;
+    ssl_certificate_key  /etc/letsencrypt/live/{{ flyspray_domain }}/privkey.pem;
+    ssl_trusted_certificate /etc/letsencrypt/live/{{ flyspray_domain }}/chain.pem;
+
+    location /setup {
+        deny all;
+    }
+
+    location /attachments {
+        location ~ \.php$ {return 403;}
+    }
+
+    location /cache {
+        location ~ \.php$ {return 403;}
+    }
+
+    location / {
+        include fastcgi_params;
+        fastcgi_pass flyspray;
+    }
+}