diff --git a/playbooks/roles/ptgbot/handlers/main.yaml b/playbooks/roles/ptgbot/handlers/main.yaml
new file mode 100644
index 0000000000..442cb5e5d3
--- /dev/null
+++ b/playbooks/roles/ptgbot/handlers/main.yaml
@@ -0,0 +1,4 @@
+- name: ptgbot Reload apache2
+ service:
+ name: apache2
+ state: reloaded
diff --git a/playbooks/roles/ptgbot/tasks/main.yaml b/playbooks/roles/ptgbot/tasks/main.yaml
index 26a909aa0b..f17be21188 100644
--- a/playbooks/roles/ptgbot/tasks/main.yaml
+++ b/playbooks/roles/ptgbot/tasks/main.yaml
@@ -50,3 +50,31 @@
- name: Run docker prune to cleanup unneeded images
shell:
cmd: docker image prune -f
+
+- name: Install apache2
+ apt:
+ name:
+ - apache2
+ - apache2-utils
+ state: present
+
+- name: Apache modules
+ apache2_module:
+ state: present
+ name: "{{ item }}"
+ loop:
+ - rewrite
+ - proxy
+ - proxy_http
+ - ssl
+ - headers
+ - proxy_wstunnel
+
+- name: Copy apache config
+ template:
+ src: ptgbot.vhost.config.j2
+ dest: '/etc/apache2/sites-enabled/010-ptgbot.conf'
+ owner: root
+ group: root
+ mode: 0644
+ notify: ptgbot Reload apache2
diff --git a/playbooks/roles/ptgbot/templates/ptgbot.vhost.config.j2 b/playbooks/roles/ptgbot/templates/ptgbot.vhost.config.j2
new file mode 100644
index 0000000000..7c11afae03
--- /dev/null
+++ b/playbooks/roles/ptgbot/templates/ptgbot.vhost.config.j2
@@ -0,0 +1,43 @@
+
+ ServerName {{ inventory_hostname }}
+ ServerAdmin infra-root@openstack.org
+
+ ErrorLog ${APACHE_LOG_DIR}/ptgbot-error.log
+
+ LogLevel warn
+
+ CustomLog ${APACHE_LOG_DIR}/ptgbot-access.log combined
+
+ Redirect / https://ptgbot.opendev.org/
+
+
+
+
+ ServerName ptgbot.opendev.org
+ ServerAdmin webmaster@openstack.org
+
+ RewriteCond %{HTTP_HOST} !^ptgbot\.opendev\.org [nocase]
+ RewriteRule ^/(.*) https://ptgbot.opendev.org/$1 [last,redirect=permanent]
+
+ AllowEncodedSlashes On
+
+ ErrorLog ${APACHE_LOG_DIR}/ptgbot-ssl-error.log
+
+ LogLevel warn
+
+ CustomLog ${APACHE_LOG_DIR}/ptgbot-ssl-access.log combined
+
+ SSLEngine on
+ SSLProtocol All -SSLv2 -SSLv3
+ # Note: this list should ensure ciphers that provide forward secrecy
+ SSLCipherSuite ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:!AES256:!aNULL:!eNULL:!MD5:!DSS:!PSK:!SRP
+ SSLHonorCipherOrder on
+
+ SSLCertificateFile /etc/letsencrypt-certs/ptgbot.opendev.org/ptgbot.opendev.org.cer
+ SSLCertificateKeyFile /etc/letsencrypt-certs/ptgbot.opendev.org/ptgbot.opendev.org.key
+ SSLCertificateChainFile /etc/letsencrypt-certs/ptgbot.opendev.org/ca.cer
+
+ ProxyPass / http://localhost:8000/ retry=0
+ ProxyPassReverse / http://localhost:8000/
+
+
diff --git a/playbooks/service-eavesdrop.yaml b/playbooks/service-eavesdrop.yaml
index 11b31dddd4..c49c00c980 100644
--- a/playbooks/service-eavesdrop.yaml
+++ b/playbooks/service-eavesdrop.yaml
@@ -7,8 +7,8 @@
- sync-project-config
- accessbot
- gerritbot
- - ptgbot
- statusbot
- limnoria
- matrix-eavesdrop
- matrix-gerritbot
+ - ptgbot
diff --git a/testinfra/test_eavesdrop.py b/testinfra/test_eavesdrop.py
index a1ce9ebdae..0439e9eee9 100644
--- a/testinfra/test_eavesdrop.py
+++ b/testinfra/test_eavesdrop.py
@@ -45,3 +45,9 @@ def test_statusbot_running(host):
cmd = host.run("docker ps -a")
assert 'statusbot-docker_statusbot_1' in cmd.stdout
assert 'Up ' in cmd.stdout
+
+def test_ptgbot(host):
+ cmd = host.run('curl --insecure '
+ '--resolve ptgbot.opendev.org:443:127.0.0.1 '
+ 'https://ptgbot.opendev.org/')
+ assert 'Project Teams Gathering' in cmd.stdout