diff --git a/software/caddy-frontend/buildout.hash.cfg b/software/caddy-frontend/buildout.hash.cfg
index 0e57508ac047fa029c433f45d3ce764f579fcf19..8123dd7c8b2c214d3b8615abe95243f5ba0111a0 100644
--- a/software/caddy-frontend/buildout.hash.cfg
+++ b/software/caddy-frontend/buildout.hash.cfg
@@ -26,7 +26,7 @@ md5sum = ab1795f92e32655d05c662c965d2b1f5
 
 [template-apache-replicate]
 filename = instance-apache-replicate.cfg.in
-md5sum = 5e750fa9a5fd37932d31f8fb8b5f3694
+md5sum = a0110d0ec69875946a16ac3a4b269eb8
 
 [template-slave-list]
 filename = templates/apache-custom-slave-list.cfg.in
diff --git a/software/caddy-frontend/instance-apache-replicate.cfg.in b/software/caddy-frontend/instance-apache-replicate.cfg.in
index 937bb0cd43b79a93a5764ebcfa3dcdd3e885c37e..abf78054b827a5d4227cc36fb680c22a6a903de4 100644
--- a/software/caddy-frontend/instance-apache-replicate.cfg.in
+++ b/software/caddy-frontend/instance-apache-replicate.cfg.in
@@ -80,7 +80,12 @@ context =
 {%   endif %}
 {%   if slave.get('server-alias') %}
 {%     for slave_alias in slave['server-alias'].split() %}
-{%       if not validators.domain(slave_alias) %}
+{%       if slave_alias.startswith('*.') %}
+{%         set clean_slave_alias = slave_alias[2:] %}
+{%       else %}
+{%         set clean_slave_alias = slave_alias %}
+{%       endif %}
+{%       if not validators.domain(clean_slave_alias) %}
 {%         do slave_error_list.append('server-alias %r not valid' % (slave_alias,)) %}
 {%       else %}
 {%         if slave_alias in used_host_list %}
@@ -122,7 +127,12 @@ context =
 {%     endif %}
 {%   endif %}
 {%   if slave.get('custom_domain') %}
-{%     if not validators.domain(slave['custom_domain']) %}
+{%     if slave['custom_domain'].startswith('*.') %}
+{%       set clean_custom_domain = slave['custom_domain'][2:] %}
+{%     else %}
+{%       set clean_custom_domain = slave['custom_domain'] %}
+{%     endif %}
+{%     if not validators.domain(clean_custom_domain) %}
 {%       do slave_error_list.append('custom_domain %r invalid' % (slave['custom_domain'],)) %}
 {%     endif %}
 {%   endif %}
diff --git a/software/caddy-frontend/test/test.py b/software/caddy-frontend/test/test.py
index d2aff06d802f1f92490afcba2b752313895702b3..298e0fe29ffa1dc0d0bbbf85412a775573727e6e 100644
--- a/software/caddy-frontend/test/test.py
+++ b/software/caddy-frontend/test/test.py
@@ -585,6 +585,10 @@ http://apachecustomhttpsaccepted.example.com:%%(http_port)s {
         'url': cls.backend_url,
         'server-alias': 'alias1.example.com alias2.example.com',
       },
+      'server-alias-wildcard': {
+        'url': cls.backend_url,
+        'server-alias': '*.alias1.example.com',
+      },
       'ssl-proxy-verify_ssl_proxy_ca_crt': {
         'url': cls.backend_https_url,
         'ssl-proxy-verify': True,
@@ -602,6 +606,10 @@ http://apachecustomhttpsaccepted.example.com:%%(http_port)s {
         'url': cls.backend_url,
         'custom_domain': 'customdomain.example.com',
       },
+      'custom_domain_wildcard': {
+        'url': cls.backend_url,
+        'custom_domain': '*.customdomain.example.com',
+      },
       'custom_domain_ssl_crt_ssl_key': {
         'url': cls.backend_url,
         'custom_domain': 'customdomainsslcrtsslkey.example.com',
@@ -757,9 +765,9 @@ http://apachecustomhttpsaccepted.example.com:%%(http_port)s {
     expected_parameter_dict = {
       'monitor-base-url': None,
       'domain': 'example.com',
-      'accepted-slave-amount': '33',
+      'accepted-slave-amount': '35',
       'rejected-slave-amount': '3',
-      'slave-amount': '36',
+      'slave-amount': '38',
       'rejected-slave-dict':
       '{"_apache_custom_http_s-rejected": ["slave not authorized"], '
       '"_caddy_custom_http_s-rejected": ["slave not authorized"], '
@@ -1082,6 +1090,38 @@ http://apachecustomhttpsaccepted.example.com:%%(http_port)s {
       open('wildcard.example.com.crt').read(),
       der2pem(result.peercert))
 
+  def test_server_alias_wildcard(self):
+    parameter_dict = self.slave_connection_parameter_dict_dict[
+      'server-alias-wildcard']
+    self.assertLogAccessUrlWithPop(parameter_dict, 'server-alias-wildcard')
+    self.assertEqual(
+      {
+        'domain': 'serveraliaswildcard.example.com',
+        'replication_number': '1',
+        'url': 'http://serveraliaswildcard.example.com',
+        'site_url': 'http://serveraliaswildcard.example.com',
+        'secure_access': 'https://serveraliaswildcard.example.com',
+        'public-ipv4': LOCAL_IPV4,
+      },
+      parameter_dict
+    )
+
+    result = self.fakeHTTPSResult(
+      parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
+
+    self.assertEqual(
+      open('wildcard.example.com.crt').read(),
+      der2pem(result.peercert))
+
+    self.assertEqualResultJson(result, 'Path', '/test-path')
+
+    result = self.fakeHTTPSResult(
+      'wild.alias1.example.com', parameter_dict['public-ipv4'], 'test-path')
+
+    self.assertEqual(
+      open('wildcard.example.com.crt').read(),
+      der2pem(result.peercert))
+
     self.assertEqualResultJson(result, 'Path', '/test-path')
 
   @skip('Feature postponed')
@@ -1155,6 +1195,32 @@ http://apachecustomhttpsaccepted.example.com:%%(http_port)s {
 
     self.assertEqualResultJson(result, 'Path', '/test-path')
 
+  def test_custom_domain_wildcard(self):
+    parameter_dict = self.slave_connection_parameter_dict_dict[
+      'custom_domain_wildcard']
+    self.assertLogAccessUrlWithPop(parameter_dict, 'custom_domain_wildcard')
+    self.assertEqual(
+      {
+        'domain': '*.customdomain.example.com',
+        'replication_number': '1',
+        'url': 'http://*.customdomain.example.com',
+        'site_url': 'http://*.customdomain.example.com',
+        'secure_access': 'https://*.customdomain.example.com',
+        'public-ipv4': LOCAL_IPV4,
+      },
+      parameter_dict
+    )
+
+    result = self.fakeHTTPSResult(
+      'wild.customdomain.example.com', parameter_dict['public-ipv4'],
+      'test-path')
+
+    self.assertEqual(
+      open('wildcard.example.com.crt').read(),
+      der2pem(result.peercert))
+
+    self.assertEqualResultJson(result, 'Path', '/test-path')
+
   def test_custom_domain_ssl_crt_ssl_key(self):
     parameter_dict = self.slave_connection_parameter_dict_dict[
       'custom_domain_ssl_crt_ssl_key']
diff --git a/software/caddy-frontend/test/test_data/test.TestSlave.test_file_list_log-CADDY.txt b/software/caddy-frontend/test/test_data/test.TestSlave.test_file_list_log-CADDY.txt
index 3446e747c4d6370f17657730f0c3922ea377b882..dcf05a80eb108caaf78bc76b9c6203491ff56838 100644
--- a/software/caddy-frontend/test/test_data/test.TestSlave.test_file_list_log-CADDY.txt
+++ b/software/caddy-frontend/test/test_data/test.TestSlave.test_file_list_log-CADDY.txt
@@ -9,6 +9,8 @@ TestSlave-1/var/log/httpd/_custom_domain_access_log
 TestSlave-1/var/log/httpd/_custom_domain_error_log
 TestSlave-1/var/log/httpd/_custom_domain_ssl_crt_ssl_key_access_log
 TestSlave-1/var/log/httpd/_custom_domain_ssl_crt_ssl_key_error_log
+TestSlave-1/var/log/httpd/_custom_domain_wildcard_access_log
+TestSlave-1/var/log/httpd/_custom_domain_wildcard_error_log
 TestSlave-1/var/log/httpd/_disabled-cookie-list_access_log
 TestSlave-1/var/log/httpd/_disabled-cookie-list_error_log
 TestSlave-1/var/log/httpd/_empty_access_log
@@ -37,6 +39,8 @@ TestSlave-1/var/log/httpd/_prefer-gzip-encoding-to-backend_access_log
 TestSlave-1/var/log/httpd/_prefer-gzip-encoding-to-backend_error_log
 TestSlave-1/var/log/httpd/_re6st-optimal-test_access_log
 TestSlave-1/var/log/httpd/_re6st-optimal-test_error_log
+TestSlave-1/var/log/httpd/_server-alias-wildcard_access_log
+TestSlave-1/var/log/httpd/_server-alias-wildcard_error_log
 TestSlave-1/var/log/httpd/_server-alias_access_log
 TestSlave-1/var/log/httpd/_server-alias_error_log
 TestSlave-1/var/log/httpd/_ssl-proxy-verify-unverified_access_log
diff --git a/software/caddy-frontend/test/test_data/test.TestSlave.test_monitor_promise_list-CADDY.txt b/software/caddy-frontend/test/test_data/test.TestSlave.test_monitor_promise_list-CADDY.txt
index a069f1a1e831cc7e093abaa46e7ffffcffc35c5a..febced599d4be67b4de00da0536260580c92ad83 100644
--- a/software/caddy-frontend/test/test_data/test.TestSlave.test_monitor_promise_list-CADDY.txt
+++ b/software/caddy-frontend/test/test_data/test.TestSlave.test_monitor_promise_list-CADDY.txt
@@ -6,6 +6,8 @@ TestSlave-1/etc/monitor-promise/check-_custom_domain-error-log-last-day
 TestSlave-1/etc/monitor-promise/check-_custom_domain-error-log-last-hour
 TestSlave-1/etc/monitor-promise/check-_custom_domain_ssl_crt_ssl_key-error-log-last-day
 TestSlave-1/etc/monitor-promise/check-_custom_domain_ssl_crt_ssl_key-error-log-last-hour
+TestSlave-1/etc/monitor-promise/check-_custom_domain_wildcard-error-log-last-day
+TestSlave-1/etc/monitor-promise/check-_custom_domain_wildcard-error-log-last-hour
 TestSlave-1/etc/monitor-promise/check-_disabled-cookie-list-error-log-last-day
 TestSlave-1/etc/monitor-promise/check-_disabled-cookie-list-error-log-last-hour
 TestSlave-1/etc/monitor-promise/check-_empty-error-log-last-day
@@ -39,6 +41,8 @@ TestSlave-1/etc/monitor-promise/check-_re6st-optimal-test-error-log-last-hour
 TestSlave-1/etc/monitor-promise/check-_re6st-optimal-test-re6st-optimal-test
 TestSlave-1/etc/monitor-promise/check-_server-alias-error-log-last-day
 TestSlave-1/etc/monitor-promise/check-_server-alias-error-log-last-hour
+TestSlave-1/etc/monitor-promise/check-_server-alias-wildcard-error-log-last-day
+TestSlave-1/etc/monitor-promise/check-_server-alias-wildcard-error-log-last-hour
 TestSlave-1/etc/monitor-promise/check-_ssl-proxy-verify-unverified-error-log-last-day
 TestSlave-1/etc/monitor-promise/check-_ssl-proxy-verify-unverified-error-log-last-hour
 TestSlave-1/etc/monitor-promise/check-_ssl-proxy-verify_ssl_proxy_ca_crt-error-log-last-day