diff --git a/docs/maintenance.md b/docs/maintenance.md
index 2b410eb2e33a613d0e99a1221aebdff9e23f2fef..c7fbd82088a4bcb7fd23cadbbb65075b837319c9 100644
--- a/docs/maintenance.md
+++ b/docs/maintenance.md
@@ -27,6 +27,7 @@ The basic configuration looks like this:
     service_name: "<service name>"
     service_domain: "{{ service_domain }}"
     service_alternate_domains: []
+    service_legacy_domains: []
     service_nginx_conf: "{{ service_nginx_conf }}"
   when: maintenance is defined
 ```
diff --git a/roles/archweb/defaults/main.yml b/roles/archweb/defaults/main.yml
index 7530dda6a8e7d484c446a0c18cde69b59ed88fd8..d2ee0c9b471f501aacd84766cfbafec794de0785 100644
--- a/roles/archweb/defaults/main.yml
+++ b/roles/archweb/defaults/main.yml
@@ -1,6 +1,7 @@
 archweb_dir: '/srv/http/archweb'
 archweb_domain: 'archlinux.org'
-archweb_alternate_domains: ['www.archlinux.org', 'master-key.archlinux.org', 'dev.archlinux.org', 'packages.archlinux.org', 'ipxe.archlinux.org', 'planet.archlinux.org']
+archweb_alternate_domains: ['www.archlinux.org', 'master-key.archlinux.org', 'dev.archlinux.org', 'packages.archlinux.org', 'planet.archlinux.org']
+archweb_legacy_domains: ['ipxe.archlinux.org']
 archweb_domains_redirects:
         'www.archlinux.org': '$request_uri'
         'master-key.archlinux.org': '/master-keys/'
diff --git a/roles/archweb/tasks/main.yml b/roles/archweb/tasks/main.yml
index aeb233fc281309b3a69ec09f6ae2013c77544fbe..487dc715a150d92900643c1c61ae4aa35b054789 100644
--- a/roles/archweb/tasks/main.yml
+++ b/roles/archweb/tasks/main.yml
@@ -5,6 +5,7 @@
     service_name: "site"
     service_domain: "{{ archweb_domain }}"
     service_alternate_domains: "{{ archweb_alternate_domains }}"
+    service_legacy_domains: "{{ archweb_legacy_domains }}"
     service_nginx_conf: "{{ archweb_nginx_conf }}"
     service_nginx_template: "maintenance-nginx.d.conf.j2"
   when: maintenance is defined and archweb_site
@@ -29,6 +30,15 @@
     domains: "{{ [archweb_domain] + archweb_alternate_domains }}"
   when: archweb_site | bool and maintenance is not defined
 
+- name: Create legacy ssl cert
+  include_role:
+    name: certificate
+  vars:
+    cert_name: "{{ archweb_domain }}_legacy"
+    domains: "{{ archweb_legacy_domains }}"
+    legacy: true
+  when: archweb_site | bool and maintenance is not defined
+
 - name: Set up nginx
   template: src=nginx.d.conf.j2 dest="{{ archweb_nginx_conf }}" owner=root group=root mode=644
   notify: Reload nginx
diff --git a/roles/archweb/templates/ipxe.archlinux.org.j2 b/roles/archweb/templates/ipxe.archlinux.org.j2
index 721b8e3c393b7f8afbf57891cb52806078bdb68e..2df4e1d6007c854437a4340c8ee5e6e6e6aeaf96 100644
--- a/roles/archweb/templates/ipxe.archlinux.org.j2
+++ b/roles/archweb/templates/ipxe.archlinux.org.j2
@@ -27,9 +27,9 @@ server {
 
     ssl_ciphers AES128-SHA:AES256-SHA:AES128-SHA256:AES256-SHA256;
 
-    ssl_certificate      /etc/letsencrypt/live/{{ archweb_domain }}/fullchain.pem;
-    ssl_certificate_key  /etc/letsencrypt/live/{{ archweb_domain }}/privkey.pem;
-    ssl_trusted_certificate /etc/letsencrypt/live/{{ archweb_domain }}/chain.pem;
+    ssl_certificate      /etc/letsencrypt/live/{{ archweb_domain }}_legacy/fullchain.pem;
+    ssl_certificate_key  /etc/letsencrypt/live/{{ archweb_domain }}_legacy/privkey.pem;
+    ssl_trusted_certificate /etc/letsencrypt/live/{{ archweb_domain }}_legacy/chain.pem;
 
     location /releng/netboot/ {
         access_log   /var/log/nginx/{{ archweb_domain }}/access.log main;
diff --git a/roles/archweb/templates/maintenance-nginx.d.conf.j2 b/roles/archweb/templates/maintenance-nginx.d.conf.j2
index b2fe6fbc27ea1aed137ec5c0134280ceca888fb4..6eddee94891bc5189a37bcfc1578d3fdde6dd19f 100644
--- a/roles/archweb/templates/maintenance-nginx.d.conf.j2
+++ b/roles/archweb/templates/maintenance-nginx.d.conf.j2
@@ -40,6 +40,45 @@ server {
     }
 }
 
+{% endfor %}
+{% for domain in service_legacy_domains | default([]) %}
+server {
+    listen       80;
+    listen       [::]:80;
+    server_name  {{ domain }};
+
+    access_log   {{ maintenance_logs_dir }}/{{ service_domain }}-access.log reduced;
+    access_log   {{ maintenance_logs_dir }}/{{ service_domain }}-access.log.json json_reduced;
+    error_log    {{ maintenance_logs_dir }}/{{ service_domain }}-error.log;
+
+    include snippets/letsencrypt.conf;
+
+    location / {
+        access_log off;
+        return 302 https://$server_name$request_uri;
+    }
+}
+
+server {
+    listen       443 ssl;
+    listen       [::]:443 ssl;
+    http2        on;
+    server_name  {{ domain }};
+
+    access_log   {{ maintenance_logs_dir }}/{{ service_domain }}-access.log reduced;
+    access_log   {{ maintenance_logs_dir }}/{{ service_domain }}-access.log.json json_reduced;
+    error_log    {{ maintenance_logs_dir }}/{{ service_domain }}-error.log;
+
+    ssl_certificate      /etc/letsencrypt/live/{{ service_domain }}_legacy/fullchain.pem;
+    ssl_certificate_key  /etc/letsencrypt/live/{{ service_domain }}_legacy/privkey.pem;
+    ssl_trusted_certificate /etc/letsencrypt/live/{{ service_domain }}_legacy/chain.pem;
+
+    location / {
+        access_log off;
+        return 302 https://{{ service_domain }};
+    }
+}
+
 {% endfor %}
 server {
     listen       80;
diff --git a/roles/maintenance/templates/nginx-maintenance.conf.j2 b/roles/maintenance/templates/nginx-maintenance.conf.j2
index 2a4edc4fc8542a253462ce964621d7df32d3e3c6..2493c1b78c2c3b9d177d36e23d6137ae6b2da86d 100644
--- a/roles/maintenance/templates/nginx-maintenance.conf.j2
+++ b/roles/maintenance/templates/nginx-maintenance.conf.j2
@@ -36,6 +36,45 @@ server {
     }
 }
 
+{% endfor %}
+{% for domain in service_legacy_domains | default([]) %}
+server {
+    listen       80;
+    listen       [::]:80;
+    server_name  {{ domain }};
+
+    access_log   {{ maintenance_logs_dir }}/{{ service_domain }}-access.log reduced;
+    access_log   {{ maintenance_logs_dir }}/{{ service_domain }}-access.log.json json_reduced;
+    error_log    {{ maintenance_logs_dir }}/{{ service_domain }}-error.log;
+
+    include snippets/letsencrypt.conf;
+
+    location / {
+        access_log off;
+        return 302 https://$server_name$request_uri;
+    }
+}
+
+server {
+    listen       443 ssl;
+    listen       [::]:443 ssl;
+    http2        on;
+    server_name  {{ domain }};
+
+    access_log   {{ maintenance_logs_dir }}/{{ service_domain }}-access.log reduced;
+    access_log   {{ maintenance_logs_dir }}/{{ service_domain }}-access.log.json json_reduced;
+    error_log    {{ maintenance_logs_dir }}/{{ service_domain }}-error.log;
+
+    ssl_certificate      /etc/letsencrypt/live/{{ service_domain }}_legacy/fullchain.pem;
+    ssl_certificate_key  /etc/letsencrypt/live/{{ service_domain }}_legacy/privkey.pem;
+    ssl_trusted_certificate /etc/letsencrypt/live/{{ service_domain }}_legacy/chain.pem;
+
+    location / {
+        access_log off;
+        return 302 https://{{ service_domain }};
+    }
+}
+
 {% endfor %}
 server {
     listen       80;