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 }}