diff --git a/playbooks/groups/pkgs.yml b/playbooks/groups/pkgs.yml
index bb7c3c21e9..f7594ec254 100644
--- a/playbooks/groups/pkgs.yml
+++ b/playbooks/groups/pkgs.yml
@@ -27,6 +27,7 @@
- git/server
- git/hooks
- clamav
+ - { role: pagure, when: env == "staging" }
- { role: nfs/client, when: env != "staging", mnt_dir: '/srv/cache/lookaside', nfs_src_dir: 'fedora_sourcecache', nfs_mount_opts='rw,hard,bg,intr,noatime,nodev,nosuid,nfsvers=4' }
- role: distgit
tags: distgit
diff --git a/roles/distgit/pagure/files/stunnel.service b/roles/distgit/pagure/files/stunnel.service
new file mode 100644
index 0000000000..8701ba266f
--- /dev/null
+++ b/roles/distgit/pagure/files/stunnel.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=stunnel
+After=network.target
+Documentation=https://infrastructure.fedoraproject.org/infra/docs/fedmsg-websocket.txt
+
+[Service]
+ExecStart=/usr/bin/stunnel /etc/stunnel/stunnel.conf
+Type=forking
+User=root
+Group=root
+Restart=on-failure
+
+[Install]
+WantedBy=multi-user.target
diff --git a/roles/distgit/pagure/handlers/main.yml b/roles/distgit/pagure/handlers/main.yml
new file mode 100644
index 0000000000..62b144e24b
--- /dev/null
+++ b/roles/distgit/pagure/handlers/main.yml
@@ -0,0 +1,3 @@
+---
+- name: restart pagure_milter
+ service: name=pagure_milter state=restarted
diff --git a/roles/distgit/pagure/tasks/main.yml b/roles/distgit/pagure/tasks/main.yml
new file mode 100644
index 0000000000..54dfa50cac
--- /dev/null
+++ b/roles/distgit/pagure/tasks/main.yml
@@ -0,0 +1,170 @@
+---
+# Configuration for the pagure webapp
+
+- name: install needed packages
+ yum: pkg={{ item }} state=present
+ with_items:
+ - pagure
+ - pagure-milters
+ - pagure-ev
+ - pagure-webhook
+ - python-psycopg2
+ - redis
+ - libsemanage-python
+ # - mod_ssl
+ # - stunnel
+ tags:
+ - pagure
+ - packages
+
+- name: create the /srv/tmp folder where to clone repos
+ file: state=directory
+ path=/srv/tmp
+ owner=git group=git mode=0775
+ tags:
+ - gitolite
+ - pagure
+
+# Set-up stunnel for the event source server
+
+ #- name: install stunnel service definition
+ # copy: src=stunnel.service
+ # dest=/usr/lib/systemd/system/stunnel.service
+ # owner=root group=root mode=0755
+ # notify:
+ # - reload systemd
+ # - restart stunnel
+ # tags:
+ # - pagure
+ # - stunnel
+
+ #- name: ensure old stunnel init file is gone
+ # file: dest=/etc/init.d/stunnel/stunnel.init state=absent
+ # tags:
+ # - pagure
+ # - stunnel
+ # - config
+
+ #- name: install stunnel.conf
+ # template: src={{ item.file }}
+ # dest={{ item.dest }}
+ # owner=root group=root mode=0600
+ # with_items:
+ # - { file: stunnel-conf.j2, dest: /etc/stunnel/stunnel.conf }
+ # notify: restart stunnel
+ # tags:
+ # - pagure
+ # - stunnel
+ # - config
+
+
+# Set-up Pagure
+
+- name: Create an user we can run pagure under
+ user: name=pagure group=pagure groups=packager append=yes
+ tags:
+ - pagure
+
+- name: copy sundry pagure configuration
+ template: src={{ item.file }}
+ dest={{ item.location }}/{{ item.file }}
+ owner=git group=postfix mode=0640
+ with_items:
+ - { file: pagure.cfg, location: /etc/pagure }
+ - { file: alembic.ini, location: /etc/pagure }
+ tags:
+ - config
+ - web
+ - pagure
+ notify:
+ - restart apache
+
+- name: create the database scheme
+ command: /usr/bin/python2 /usr/share/pagure/pagure_createdb.py
+ changed_when: "1 != 1"
+ environment:
+ PAGURE_CONFIG: /etc/pagure/pagure.cfg
+ tags:
+ - web
+ - pagure
+
+- name: Install the apache configuration file
+ template: src={{ item }} dest=/etc/httpd/conf.d/{{ item }}
+ owner=root group=root mode=0644
+ with_items:
+ - 0_pagure.conf
+ tags:
+ - files
+ - config
+ - pagure
+ notify:
+ - restart apache
+
+- name: Install the wsgi file
+ template: src={{ item }}
+ dest=/var/www/{{ item }}
+ owner=git group=git mode=0644
+ with_items:
+ - pagure.wsgi
+ tags:
+ - config
+ - web
+ - pagure
+ notify:
+ - restart apache
+
+- name: Add default facl so apache can read git repos
+ acl: default=yes etype=user entity=apache permissions="rx" name=/srv/git state=present
+ register: acl_updates
+ tags:
+ - pagure
+
+- name: Manually fix current default ACLs since Ansible doesnt know recursive acls
+ when: acl_updates.changed
+ command: /usr/bin/setfacl -Rdm user:apache:rx /srv/git
+ tags:
+ - pagure
+
+- name: Manually fix current ACLs since Ansible doesnt know recursive acls
+ when: acl_updates.changed
+ command: /usr/bin/setfacl -Rm user:apache:rx /srv/git
+ tags:
+ - pagure
+
+- name: set sebooleans so pagure can talk to the db
+ seboolean: name=httpd_can_network_connect_db
+ state=true
+ persistent=true
+ tags:
+ - selinux
+ - web
+ - pagure
+
+- name: set sebooleans so apache can send emails
+ seboolean: name=httpd_can_sendmail
+ state=true
+ persistent=true
+ tags:
+ - selinux
+ - web
+ - pagure
+
+
+# Ensure all the services are up and running
+
+- name: Start and enable httpd, postfix, pagure_milter
+ service: name={{ item }} enabled=yes state=started
+ with_items:
+ - httpd
+ - postfix
+ # - stunnel
+ - pagure_milter
+ - redis
+ - pagure_ev
+ - pagure_webhook
+ - fedmsg-relay
+ ignore_errors: true
+ tags:
+ - pagure
+ - service
+ - postfix
diff --git a/roles/distgit/pagure/templates/0_pagure.conf b/roles/distgit/pagure/templates/0_pagure.conf
new file mode 100644
index 0000000000..c3a7ff34ef
--- /dev/null
+++ b/roles/distgit/pagure/templates/0_pagure.conf
@@ -0,0 +1,46 @@
+WSGISocketPrefix run/wsgi
+#WSGIRestrictStdout On
+WSGIRestrictSignal Off
+WSGIPythonOptimize 1
+WSGIPassAuthorization On
+WSGIDaemonProcess pagure user=pagure group=packager maximum-requests=1000 display-name=pagure processes=4 threads=4 inactivity-timeout=300
+
+
+ WSGIScriptAlias /pagure /var/www/pagure.wsgi
+
+# SSLEngine on
+# SSLProtocol all -SSLv2 -SSLv3
+# # Use secure TLSv1.1 and TLSv1.2 ciphers
+# Header always add Strict-Transport-Security "max-age=15768000; includeSubDomains; preload"
+
+# SSLCertificateFile /etc/pki/tls/certs/pagure.io.cert
+# SSLCertificateChainFile /etc/pki/tls/certs/pagure.io.intermediate.cert
+# SSLCertificateKeyFile /etc/pki/tls/certs/pagure.io.key
+
+ Alias /static /usr/lib/python2.7/site-packages/pagure/static/
+
+ SetEnv GIT_PROJECT_ROOT /srv/git/repositories
+
+ AliasMatch ^/(.*/objects/[0-9a-f]{2}/[0-9a-f]{38})$ /srv/git/repositories/$1
+ AliasMatch ^/(.*/objects/pack/pack-[0-9a-f]{40}.(pack|idx))$ /srv/git/repositories/$1
+ ScriptAliasMatch \
+ "(?x)^/(.*/(HEAD | \
+ info/refs | \
+ objects/info/[^/]+ | \
+ git-(upload|receive)-pack))$" \
+ /usr/libexec/git-core/git-http-backend/$1
+
+
+ WSGIProcessGroup pagure
+
+ # Apache 2.4
+ Require all granted
+
+
+ # Apache 2.2
+ Order deny,allow
+ Allow from all
+
+
+
+#
diff --git a/roles/distgit/pagure/templates/alembic.ini b/roles/distgit/pagure/templates/alembic.ini
new file mode 100644
index 0000000000..fd17497200
--- /dev/null
+++ b/roles/distgit/pagure/templates/alembic.ini
@@ -0,0 +1,51 @@
+# A generic, single database configuration.
+
+[alembic]
+# path to migration scripts
+script_location = /usr/share/pagure/alembic
+
+# template used to generate migration files
+# file_template = %%(rev)s_%%(slug)s
+
+# set to 'true' to run the environment during
+# the 'revision' command, regardless of autogenerate
+# revision_environment = false
+
+#sqlalchemy.url = postgresql://<%= pkgdb_app %>:<%= pkgdb_appPassword %>@db-pkgdb/pkgdb
+sqlalchemy.url = postgresql://{{ distgit_pagure_db_user }}:{{ distgit_pagure_db_pass }}@{{ distgit_pagure_db_host }}/{{ distgit_pagure_db_name }}
+
+
+# Logging configuration
+[loggers]
+keys = root,sqlalchemy,alembic
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = WARN
+handlers = console
+qualname =
+
+[logger_sqlalchemy]
+level = WARN
+handlers =
+qualname = sqlalchemy.engine
+
+[logger_alembic]
+level = INFO
+handlers =
+qualname = alembic
+
+[handler_console]
+class = StreamHandler
+args = (sys.stderr,)
+level = NOTSET
+formatter = generic
+
+[formatter_generic]
+format = %(levelname)-5.5s [%(name)s] %(message)s
+datefmt = %H:%M:%S
diff --git a/roles/distgit/pagure/templates/pagure.cfg b/roles/distgit/pagure/templates/pagure.cfg
new file mode 100644
index 0000000000..b8ba5981cb
--- /dev/null
+++ b/roles/distgit/pagure/templates/pagure.cfg
@@ -0,0 +1,188 @@
+from datetime import timedelta
+
+### Set the time after which the admin session expires
+# There are two sessions on pagure, login that holds for 31 days and
+# the session defined here after which an user has to re-login.
+# This session is used when accessing all administrative parts of pagure
+# (ie: changing a project's or a user's settings)
+ADMIN_SESSION_LIFETIME = timedelta(minutes=20)
+
+### Secret key for the Flask application
+SECRET_KEY='{{ distgit_pagure_secret_key }}'
+SALT_EMAIL='{{ distgit_pagure_secret_salt_email }}'
+
+EMAIL_SEND = True
+
+# This is required so that login specifies https
+PREFERRED_URL_SCHEME='https'
+
+### url to the database server:
+#DB_URL=mysql://user:pass@host/db_name
+#DB_URL=postgres://user:pass@host/db_name
+DB_URL = 'postgresql://{{ distgit_pagure_db_user }}:{{ distgit_pagure_db_pass }}@{{ distgit_pagure_db_host }}/{{ distgit_pagure_db_name }}'
+
+### The FAS group in which the admin of pagure are
+ADMIN_GROUP = ['sysadmin-main']
+
+### The email address to which the flask.log will send the errors (tracebacks)
+EMAIL_ERROR = 'pingou@pingoured.fr'
+
+### Default SMTP server to use for sending emails
+SMTP_SERVER = 'bastion'
+
+### Email used to sent emails
+{% if env == 'staging' %}
+FROM_EMAIL = 'pagure@pkgs.stg.fedoraproject.org'
+DOMAIN_EMAIL_NOTIFICATIONS = 'pkgs.stg.fedoraproject.org'
+{% else %}
+FROM_EMAIL = 'pagure@pkgs.fedoraproject.org'
+DOMAIN_EMAIL_NOTIFICATIONS = 'pkgs.fedoraproject.org'
+{% endif %}
+
+### The URL at which the project is available.
+{% if env == 'staging' %}
+APP_URL = 'https://pkgs.stg.fedoraproject.org/pagure'
+{% else %}
+APP_URL = 'https://pkgs.fedoraproject.org/pagure'
+{% endif %}
+
+### Datagrepper info for the user profile
+{% if env == 'staging' %}
+DATAGREPPER_URL = 'https://apps.stg.fedoraproject.org/datagrepper'
+{% else %}
+DATAGREPPER_URL = 'https://apps.fedoraproject.org/datagrepper'
+{% endif %}
+DATAGREPPER_CATEGORY = 'pagure'
+
+### The URL to use to clone git repositories.
+{% if env == 'staging' %}
+GIT_URL_SSH = 'ssh://pkgs.stg.fedoraproject.org/'
+GIT_URL_GIT = 'https://pkgs.stg.fedoraproject.org/'
+{% else %}
+GIT_URL_SSH = 'ssh://pkgs.fedoraproject.org/'
+GIT_URL_GIT = 'https://pkgs.fedoraproject.org/'
+{% endif %}
+
+### The IP addresses allowed for the internal endpoints
+{% if env == 'pagure-staging' %}
+IP_ALLOWED_INTERNAL = ['127.0.0.1', 'localhost', '::1', '140.211.169.203']
+{% else %}
+IP_ALLOWED_INTERNAL = ['127.0.0.1', 'localhost', '::1', '140.211.169.204']
+{% endif %}
+
+# Redis configuration
+{% if env == 'staging' %}
+#EVENTSOURCE_SOURCE = 'https://pkgs.stg.fedoraproject.org:8088'
+{% else %}
+#EVENTSOURCE_SOURCE = 'https://pkgs.stg.fedoraproject.org:8088'
+{% endif %}
+REDIS_HOST = '0.0.0.0'
+REDIS_PORT = 6379
+REDIS_DB = 0
+
+WEBHOOK = True
+
+### Folder containing to the git repos
+GIT_FOLDER = '/srv/git/repositories'
+
+### Folder containing the docs repos
+DOCS_FOLDER = '/srv/git/repositories/docs'
+
+### Folder containing the pull-requests repos
+REQUESTS_FOLDER = '/srv/git/repositories/requests'
+
+### Folder containing the tickets repos
+TICKETS_FOLDER = '/srv/git/repositories/tickets'
+
+### Folder containing the clones of the remotes git repo
+REMOTE_GIT_FOLDER = '/srv/git/remotes'
+
+### Configuration file for gitolite
+#GITOLITE_CONFIG = '/srv/git/.gitolite/conf/gitolite.conf'
+
+### Temp folder to be used to make the clones to work around bug in libgit2:
+## refs: https://github.com/libgit2/libgit2/issues/2965
+## and https://github.com/libgit2/libgit2/issues/2797
+TMP_FOLDER = '/srv/tmp'
+
+# Optional configuration
+
+### Number of items displayed per page
+# Used when listing items
+ITEM_PER_PAGE = 48
+
+### Maximum size of the uploaded content
+# Used to limit the size of file attached to a ticket for example
+MAX_CONTENT_LENGTH = 1024 # 1024 bytes
+
+### Lenght for short commits ids or file hex
+SHORT_LENGTH = 6
+
+# Authentication related configuration option
+
+### Switch the authentication method
+# Specify which authentication method to use, defaults to `fas` can be or
+# `local`
+# Default: ``fas``.
+PAGURE_AUTH = 'fas'
+
+# When this is set to True, the session cookie will only be returned to the
+# server via ssl (https). If you connect to the server via plain http, the
+# cookie will not be sent. This prevents sniffing of the cookie contents.
+# This may be set to False when testing your application but should always
+# be set to True in production.
+# Default: ``True``.
+SESSION_COOKIE_SECURE = True
+
+# The name of the cookie used to store the session id.
+# Default: ``.pagure``.
+SESSION_COOKIE_NAME = 'disgit_pagure'
+
+# Boolean specifying wether to check the user's IP address when retrieving
+# its session. This make things more secure (thus is on by default) but
+# under certain setup it might not work (for example is there are proxies
+# in front of the application).
+CHECK_SESSION_IP = True
+
+# Used by SESSION_COOKIE_PATH
+APPLICATION_ROOT = '/pagure/'
+
+# Set the SSH certs/keys
+{% if env == 'staging' %}
+SSH_KEYS = {
+ 'RSA': {
+ 'fingerprint': '2048 69:50:46:24:c7:94:44:f8:8d:83:05:5c:eb:73:fb:c4 (RSA)',
+ 'pubkey': 'stg.pagure.io,140.211.169.203 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDJNu490Rp305zGCJLvhVIrKjL7Xngew3NxgRYeopHBDvj+EFQUqULXtgrI5nUBMSB94RrsuHynFAXYy2m0snHjWzWjbIxM4ZVD2sX4GiKX6qu7WyxcGmGcL08MF919r+JSPL9oWWSq/CvvBF0M1eeqkIpjMZHpVKgR3uTMD5yW994NBLAQi9i1UdwGYNQc1KqWvlvW1XhFFtiIGscIFGRKsUOMvnJvWdU6T+djmzMy4hcahxnsPCZxCjbQpuH1JjihNNVWYOq7Ztjs1gxpTTV19ATp4Z2F95uyyQ3Y+Em9KeXcKXYxwVzYVho5SSB1ZYBL+xAH1osK23PvGD39UYp9',
+ 'SHA256': 'SHA256:Gddkd5H7oQ1RaK8WgXSKl7JZP+FgLyidmxbLercJ/JY',
+ }
+}
+{% else %}
+SSH_KEYS = {
+ 'RSA': {
+ 'fingerprint': '2048 90:8e:7f:a3:f7:f1:70:cb:56:77:96:17:44:c4:fc:82 (RSA)',
+ 'pubkey': 'pagure.io,140.211.169.204 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC198DWs0SQ3DX0ptu+8Wq6wnZMrXUCufN+wdSCtlyhHUeQ3q5B4Hgto1n2FMj752vToCfNTn9mWO7l2rNTrKeBsELpubl2jECHu4LqxkRVihu5UEzejfjiWNDN2jdXbYFY27GW9zymD7Gq3u+T/Mkp4lIcQKRoJaLobBmcVxrLPEEJMKI4AJY31jgxMTnxi7KcR+U5udQrZ3dzCn2BqUdiN5dMgckr4yNPjhl3emJeVJ/uhAJrEsgjzqxAb60smMO5/1By+yF85Wih4TnFtF4LwYYuxgqiNv72Xy4D/MGxCqkO/nH5eRNfcJ+AJFE7727F7Tnbo4xmAjilvRria/+l',
+ 'SHA256': 'SHA256:x4xld/tPdeOhbyJcTOxd+IbSZ4OpnBzh/IskocyrOM',
+ }
+}
+{% endif %}
+
+
+# Configuration item that are specific for this odd pagure instance
+
+PROJECT_TICKETS = False
+ENABLE_NEW_PROJECTS = False
+ENABLE_DEL_PROJECTS = False
+ENABLE_TICKETS = False
+ENABLE_USER_MNGT = False
+
+DISABLED_PLUGINS = ['IRC', 'Pagure tickets', 'Read the Doc']
+
+ACLS = {
+ 'create_project': 'Create a new project',
+ 'fork_project': 'Fork a project',
+ 'pull_request_close': 'Close a pull-request of this project',
+ 'pull_request_comment': 'Comment on a pull-request of this project',
+ 'pull_request_flag': 'Flag a pull-request of this project',
+ 'pull_request_merge': 'Merge a pull-request of this project',
+}
+
diff --git a/roles/distgit/pagure/templates/pagure.wsgi b/roles/distgit/pagure/templates/pagure.wsgi
new file mode 100644
index 0000000000..b04abac4d8
--- /dev/null
+++ b/roles/distgit/pagure/templates/pagure.wsgi
@@ -0,0 +1,28 @@
+#-*- coding: utf-8 -*-
+
+# The three lines below are required to run on EL6 as EL6 has
+# two possible version of python-sqlalchemy and python-jinja2
+# These lines make sure the application uses the correct version.
+import __main__
+__main__.__requires__ = ['SQLAlchemy >= 0.8', 'jinja2 >= 2.4']
+import pkg_resources
+
+import os
+## Set the environment variable pointing to the configuration file
+os.environ['PAGURE_CONFIG'] = '/etc/pagure/pagure.cfg'
+
+## Set the environment variable if the tmp folder needs to be moved
+## Is necessary to work around bug in libgit2:
+## refs: https://github.com/libgit2/libgit2/issues/2965
+## and https://github.com/libgit2/libgit2/issues/2797
+os.environ['TEMP'] = '/srv/tmp/'
+
+## The following is only needed if you did not install pagure
+## as a python module (for example if you run it from a git clone).
+#import sys
+#sys.path.insert(0, '/path/to/pagure/')
+
+
+## The most import line to make the wsgi working
+from pagure import APP as application
+#application.debug = True
diff --git a/roles/distgit/pagure/templates/stunnel-conf.j2 b/roles/distgit/pagure/templates/stunnel-conf.j2
new file mode 100644
index 0000000000..6dcf68a09d
--- /dev/null
+++ b/roles/distgit/pagure/templates/stunnel-conf.j2
@@ -0,0 +1,8 @@
+cert = /etc/pki/tls/certs/pagure.io.cert
+key = /etc/pki/tls/certs/pagure.io.key
+pid = /var/run/stunnel.pid
+
+[{{ stunnel_service }}]
+
+accept = {{ stunnel_source_port }}
+connect = {{ stunnel_destination_port }}