Skip to content

Commit db89d49

Browse files
committed
Require explicit redirects and drop www_redirect
Discontinues the `reverse_www` filter, overcoming its challenges in handling subdomains.
1 parent 41c782a commit db89d49

File tree

13 files changed

+58
-51
lines changed

13 files changed

+58
-51
lines changed

Vagrantfile

+9-3
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,20 @@ Vagrant.configure('2') do |config|
4949
# Required for NFS to work
5050
config.vm.network :private_network, ip: ip, hostsupdater: 'skip'
5151

52-
hostname, *aliases = wordpress_sites.flat_map { |(_name, site)| site['site_hosts'] }
52+
wordpress_sites.flat_map { |(_name, site)| site['site_hosts'] }.each do |host|
53+
if !host.is_a?(Hash) or !host.has_key?('canonical')
54+
fail_with_message File.read(File.join(ANSIBLE_PATH, 'roles/common/templates/site_hosts.j2')).sub!('{{ env }}', 'development').gsub!(/com$/, 'dev')
55+
end
56+
end
57+
58+
hostname, *aliases = wordpress_sites.flat_map { |(_name, site)| site['site_hosts'].map { |host| host['canonical'] } }
5359
config.vm.hostname = hostname
54-
www_aliases = ["www.#{hostname}"] + aliases.map { |host| "www.#{host}" }
60+
redirects = wordpress_sites.flat_map { |(_name, site)| site['site_hosts'].select { |host| host.has_key?('redirects') }.flat_map { |host| host['redirects'] } }
5561

5662
if Vagrant.has_plugin? 'vagrant-hostmanager'
5763
config.hostmanager.enabled = true
5864
config.hostmanager.manage_host = true
59-
config.hostmanager.aliases = aliases + www_aliases
65+
config.hostmanager.aliases = aliases + redirects
6066
else
6167
fail_with_message "vagrant-hostmanager missing, please install the plugin with this command:\nvagrant plugin install vagrant-hostmanager"
6268
end

group_vars/all/main.yml

+3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ wordpress_env_defaults:
1717
wp_siteurl: "${WP_HOME}/wp"
1818

1919
site_env: "{{ wordpress_env_defaults | combine(item.value.env | default({}), vault_wordpress_sites[item.key].env) }}"
20+
site_hosts_canonical: "{{ item.value.site_hosts | map(attribute='canonical') | list }}"
21+
site_hosts_redirects: "{{ item.value.site_hosts | selectattr('redirects', 'defined') | sum(attribute='redirects', start=[]) | list }}"
22+
site_hosts: "{{ site_hosts_canonical | union(site_hosts_redirects) }}"
2023

2124
# Values of raw_vars will be wrapped in `{% raw %}` to avoid templating problems if values include `{%` and `{{`.
2225
# Will recurse dicts/lists. `*` is wildcard for one or more dict keys, list indices, or strings. Example:

group_vars/development/wordpress_sites.yml

+3-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
wordpress_sites:
66
example.com:
77
site_hosts:
8-
- example.dev
8+
- canonical: example.dev
9+
redirects:
10+
- www.example.dev
911
local_path: ../site # path targeting local Bedrock site directory (relative to Ansible root)
1012
admin_email: admin@example.dev
1113
multisite:

group_vars/production/wordpress_sites.yml

+3-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
wordpress_sites:
66
example.com:
77
site_hosts:
8-
- example.com
8+
- canonical: example.com
9+
redirects:
10+
- www.example.com
911
local_path: ../site # path targeting local Bedrock site directory (relative to Ansible root)
1012
repo: git@github.com:example/example.com.git # replace with your Git repo URL
1113
repo_subtree_path: site # relative path to your Bedrock/WP directory in your repo

group_vars/staging/wordpress_sites.yml

+3-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
wordpress_sites:
66
example.com:
77
site_hosts:
8-
- staging.example.com
8+
- canonical: staging.example.com
9+
# redirects:
10+
# - otherdomain.com
911
local_path: ../site # path targeting local Bedrock site directory (relative to Ansible root)
1012
repo: git@github.com:example/example.com.git # replace with your Git repo URL
1113
repo_subtree_path: site # relative path to your Bedrock/WP directory in your repo

lib/trellis/plugins/filter/filters.py

-32
Original file line numberDiff line numberDiff line change
@@ -7,37 +7,6 @@
77
from ansible import errors
88
from ansible.compat.six import string_types
99

10-
def reverse_www(hosts, enabled=True, append=True):
11-
''' Add or remove www subdomain '''
12-
13-
if not enabled:
14-
return hosts
15-
16-
# Check if hosts is a list and parse each host
17-
if isinstance(hosts, (list, tuple, types.GeneratorType)):
18-
reversed_hosts = [reverse_www(host) for host in hosts]
19-
20-
if append:
21-
return list(set(hosts + reversed_hosts))
22-
else:
23-
return reversed_hosts
24-
25-
# Add or remove www
26-
elif isinstance(hosts, string_types):
27-
host = hosts
28-
29-
if host.startswith('www.'):
30-
return host[4:]
31-
else:
32-
if len(host.split('.')) > 2:
33-
return host
34-
else:
35-
return 'www.{0}'.format(host)
36-
37-
# Handle invalid input type
38-
else:
39-
raise errors.AnsibleFilterError('The reverse_www filter expects a string or list of strings, got ' + repr(hosts))
40-
4110
def to_env(dict_value):
4211
envs = ["{0}='{1}'".format(key.upper(), value) for key, value in sorted(dict_value.items())]
4312
return "\n".join(envs)
@@ -51,7 +20,6 @@ class FilterModule(object):
5120

5221
def filters(self):
5322
return {
54-
'reverse_www': reverse_www,
5523
'to_env': to_env,
5624
'underscore': underscore,
5725
}

roles/common/tasks/main.yml

+7
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@
1010
when: ansible_version is not defined or false in [{% for item in ansible_requirements %}{{ ansible_version.full | version_compare(item.version, item.operator) }},{% endfor %}]
1111
run_once: true
1212

13+
- name: Validate format of site_hosts
14+
fail:
15+
msg: "{{ lookup('template', 'site_hosts.j2') }}"
16+
with_dict: "{{ wordpress_sites }}"
17+
when: item.value.site_hosts | rejectattr('canonical', 'defined') | list | count
18+
tags: [letsencrypt, wordpress]
19+
1320
- name: Update Apt
1421
apt:
1522
update_cache: yes

roles/common/templates/site_hosts.j2

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
Required format for `site_hosts` (group_vars/{{ env }}/wordpress_sites.yml):
2+
3+
example.com:
4+
site_hosts:
5+
- canonical: example.com
6+
7+
The above is the minimum required. Multiple hosts and redirects are possible:
8+
9+
example.com:
10+
site_hosts:
11+
- canonical: example.com
12+
redirects:
13+
- www.example.com
14+
- site.com
15+
- canonical: example.co.uk
16+
redirects:
17+
- www.example.co.uk

roles/letsencrypt/tasks/certificates.yml

+4-4
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,19 @@
1515
tags: [letsencrypt_keys]
1616

1717
- name: Generate CSRs for single domain keys
18-
shell: openssl req -new -sha256 -key "{{ letsencrypt_keys_dir }}/{{ item.key }}.key" -subj "/CN={{ item.value.site_hosts[0] }}" > {{ acme_tiny_data_directory }}/csrs/{{ item.key }}.csr
18+
shell: openssl req -new -sha256 -key "{{ letsencrypt_keys_dir }}/{{ item.key }}.key" -subj "/CN={{ item.value.site_hosts[0].canonical }}" > {{ acme_tiny_data_directory }}/csrs/{{ item.key }}.csr
1919
args:
2020
creates: "{{ acme_tiny_data_directory }}/csrs/{{ item.key }}.csr"
21-
when: site_uses_letsencrypt and item.value.site_hosts | length == 1 and not item.value.www_redirect | default(true)
21+
when: site_uses_letsencrypt and site_hosts | count == 1
2222
with_dict: "{{ wordpress_sites }}"
2323
tags: [letsencrypt_keys]
2424

2525
- name: Generate CSRs for multiple domain keys
26-
shell: "openssl req -new -sha256 -key '{{ letsencrypt_keys_dir }}/{{ item.key }}.key' -subj '/' -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf '[SAN]\nsubjectAltName=DNS:{{ item.value.site_hosts | reverse_www(enabled=item.value.www_redirect | default(true)) | join(',DNS:') }}')) > {{ acme_tiny_data_directory }}/csrs/{{ item.key }}.csr"
26+
shell: "openssl req -new -sha256 -key '{{ letsencrypt_keys_dir }}/{{ item.key }}.key' -subj '/' -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf '[SAN]\nsubjectAltName=DNS:{{ site_hosts | join(',DNS:') }}')) > {{ acme_tiny_data_directory }}/csrs/{{ item.key }}.csr"
2727
args:
2828
executable: /bin/bash
2929
creates: "{{ acme_tiny_data_directory }}/csrs/{{ item.key }}.csr"
30-
when: site_uses_letsencrypt and item.value.www_redirect | default(true)
30+
when: site_uses_letsencrypt and site_hosts | count > 1
3131
with_dict: "{{ wordpress_sites }}"
3232
tags: [letsencrypt_keys]
3333

roles/letsencrypt/tasks/nginx.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737

3838
- name: Test Acme Challenges
3939
test_challenges:
40-
hosts: "{{ item.value.site_hosts | reverse_www(enabled=item.value.www_redirect | default(true)) }}"
40+
hosts: "{{ site_hosts }}"
4141
register: letsencrypt_test_challenges
4242
ignore_errors: true
4343
when: site_uses_letsencrypt
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
server {
22
listen 80;
3-
server_name {{ item.item.value.site_hosts | reverse_www(enabled=item.item.value.www_redirect | default(true)) | join(' ') }};
3+
server_name{% for item in item.item.value.site_hosts %} {{ item.canonical }}{% for redirect in item.redirects | default([]) %} {{ redirect }}{% endfor %}{% endfor %};
44
include acme-challenge-location.conf;
55
}

roles/wordpress-setup/tasks/self-signed-certificate.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
- name: Generate self-signed certificates
33
shell: >
4-
openssl req -subj "/CN={{ item.value.site_hosts | first }}" -new
4+
openssl req -subj "/CN={{ item.value.site_hosts[0].canonical }}" -new
55
-newkey rsa:2048 -days 3650 -nodes -x509 -sha256
66
-keyout {{ item.key }}.key -out {{ item.key }}.cert
77
args:

roles/wordpress-setup/templates/wordpress-site.conf.j2

+6-6
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ server {
77
listen 80;
88
{% endif %}
99

10-
server_name {% for host in item.value.site_hosts %} {{ host }} {% if item.value.multisite.subdomains | default(false) %} *.{{ host }} {% endif %} {% endfor %};
10+
server_name {% for host in site_hosts_canonical %}{{ host }} {% if item.value.multisite.subdomains | default(false) %}*.{{ host }} {% endif %}{% endfor %};
1111
access_log {{ www_root }}/{{ item.key }}/logs/access.log;
1212
error_log {{ www_root }}/{{ item.key }}/logs/error.log;
1313

@@ -81,7 +81,7 @@ server {
8181
server {
8282
listen 80;
8383

84-
server_name {{ item.value.site_hosts | reverse_www(enabled=item.value.www_redirect | default(true)) | join(' ') }} {% if item.value.multisite.subdomains | default(false) %} *.{{ item.value.site_hosts | join(' *.') }} {% endif %};
84+
server_name {{ site_hosts | join(' ') }}{% if item.value.multisite.subdomains | default(false) %} *.{{ site_hosts_canonical | join(' *.') }}{% endif %};
8585

8686
{% if item.value.ssl.provider | default('manual') == 'letsencrypt' -%}
8787
include acme-challenge-location.conf;
@@ -95,7 +95,7 @@ server {
9595
}
9696
{% endif %}
9797

98-
{% for host in item.value.site_hosts if item.value.www_redirect | default(true) %}
98+
{% for host in item.value.site_hosts if host.redirects | default([]) %}
9999
server {
100100
{% if item.value.ssl is defined and item.value.ssl.enabled | default(false) -%}
101101
listen 443 ssl http2;
@@ -105,16 +105,16 @@ server {
105105
listen 80;
106106
{% endif -%}
107107

108-
server_name {{ host | reverse_www(append=false) }};
108+
server_name {{ host.redirects | join(' ') }};
109109

110110
{% if item.value.ssl is not defined or not item.value.ssl.enabled | default(false) -%}
111111
include acme-challenge-location.conf;
112112

113113
location / {
114-
return 301 $scheme://{{ host }}$request_uri;
114+
return 301 $scheme://{{ host.canonical }}$request_uri;
115115
}
116116
{% else %}
117-
return 301 $scheme://{{ host }}$request_uri;
117+
return 301 $scheme://{{ host.canonical }}$request_uri;
118118
{% endif %}
119119
}
120120
{% endfor %}

0 commit comments

Comments
 (0)