provide redirects from www subdomains of zones to their parent domain
* Split the nginx templates again so we have just the part needed to make a domain do a redirect separate from the rest. * Add server blocks to the nginx config for these domains. * List these domains in the SSL certificate install admin panel. * Generate default 'www' records just for domains we provide default redirects for. Fixes #321.
This commit is contained in:
parent
1d09e2406b
commit
95173bb327
6 changed files with 121 additions and 91 deletions
79
conf/nginx-alldomains.conf
Normal file
79
conf/nginx-alldomains.conf
Normal file
|
@ -0,0 +1,79 @@
|
|||
# Expose this directory as static files.
|
||||
root $ROOT;
|
||||
index index.html index.htm;
|
||||
|
||||
location = /robots.txt {
|
||||
log_not_found off;
|
||||
access_log off;
|
||||
}
|
||||
|
||||
location = /favicon.ico {
|
||||
log_not_found off;
|
||||
access_log off;
|
||||
}
|
||||
|
||||
location = /mailinabox.mobileconfig {
|
||||
alias /var/lib/mailinabox/mobileconfig.xml;
|
||||
}
|
||||
location = /.well-known/autoconfig/mail/config-v1.1.xml {
|
||||
alias /var/lib/mailinabox/mozilla-autoconfig.xml;
|
||||
}
|
||||
|
||||
# Roundcube Webmail configuration.
|
||||
rewrite ^/mail$ /mail/ redirect;
|
||||
rewrite ^/mail/$ /mail/index.php;
|
||||
location /mail/ {
|
||||
index index.php;
|
||||
alias /usr/local/lib/roundcubemail/;
|
||||
}
|
||||
location ~ /mail/config/.* {
|
||||
# A ~-style location is needed to give this precedence over the next block.
|
||||
return 403;
|
||||
}
|
||||
location ~ /mail/.*\.php {
|
||||
# note: ~ has precendence over a regular location block
|
||||
include fastcgi_params;
|
||||
fastcgi_split_path_info ^/mail(/.*)()$;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME /usr/local/lib/roundcubemail/$fastcgi_script_name;
|
||||
fastcgi_pass php-fpm;
|
||||
|
||||
# Outgoing mail also goes through this endpoint, so increase the maximum
|
||||
# file upload limit to match the corresponding Postfix limit.
|
||||
client_max_body_size 128M;
|
||||
}
|
||||
|
||||
# Z-Push (Microsoft Exchange ActiveSync)
|
||||
location /Microsoft-Server-ActiveSync {
|
||||
include /etc/nginx/fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME /usr/local/lib/z-push/index.php;
|
||||
fastcgi_param PHP_VALUE "include_path=.:/usr/share/php:/usr/share/pear:/usr/share/awl/inc";
|
||||
fastcgi_read_timeout 630;
|
||||
fastcgi_pass php-fpm;
|
||||
|
||||
# Outgoing mail also goes through this endpoint, so increase the maximum
|
||||
# file upload limit to match the corresponding Postfix limit.
|
||||
client_max_body_size 128M;
|
||||
}
|
||||
location /autodiscover/autodiscover.xml {
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME /usr/local/lib/z-push/autodiscover/autodiscover.php;
|
||||
fastcgi_param PHP_VALUE "include_path=.:/usr/share/php:/usr/share/pear:/usr/share/awl/inc";
|
||||
fastcgi_pass php-fpm;
|
||||
}
|
||||
|
||||
|
||||
# ADDITIONAL DIRECTIVES HERE
|
||||
|
||||
# Disable viewing dotfiles (.htaccess, .svn, .git, etc.)
|
||||
# This block is placed at the end. Nginx's precedence rules means this block
|
||||
# takes precedence over all non-regex matches and only regex matches that
|
||||
# come after it (i.e. none of those, since this is the last one.) That means
|
||||
# we're blocking dotfiles in the static hosted sites but not the FastCGI-
|
||||
# handled locations for ownCloud (which serves user-uploaded files that might
|
||||
# have this pattern, see #414) or some of the other services.
|
||||
location ~ /\.(ht|svn|git|hg|bzr) {
|
||||
log_not_found off;
|
||||
access_log off;
|
||||
deny all;
|
||||
}
|
|
@ -58,3 +58,4 @@
|
|||
rewrite ^/.well-known/carddav /cloud/remote.php/carddav/ redirect;
|
||||
rewrite ^/.well-known/caldav /cloud/remote.php/caldav/ redirect;
|
||||
|
||||
# ADDITIONAL DIRECTIVES HERE
|
||||
|
|
|
@ -33,84 +33,5 @@ server {
|
|||
ssl_certificate_key $SSL_KEY;
|
||||
include /etc/nginx/nginx-ssl.conf;
|
||||
|
||||
# Expose this directory as static files.
|
||||
root $ROOT;
|
||||
index index.html index.htm;
|
||||
|
||||
location = /robots.txt {
|
||||
log_not_found off;
|
||||
access_log off;
|
||||
}
|
||||
|
||||
location = /favicon.ico {
|
||||
log_not_found off;
|
||||
access_log off;
|
||||
}
|
||||
|
||||
location = /mailinabox.mobileconfig {
|
||||
alias /var/lib/mailinabox/mobileconfig.xml;
|
||||
}
|
||||
location = /.well-known/autoconfig/mail/config-v1.1.xml {
|
||||
alias /var/lib/mailinabox/mozilla-autoconfig.xml;
|
||||
}
|
||||
|
||||
# Roundcube Webmail configuration.
|
||||
rewrite ^/mail$ /mail/ redirect;
|
||||
rewrite ^/mail/$ /mail/index.php;
|
||||
location /mail/ {
|
||||
index index.php;
|
||||
alias /usr/local/lib/roundcubemail/;
|
||||
}
|
||||
location ~ /mail/config/.* {
|
||||
# A ~-style location is needed to give this precedence over the next block.
|
||||
return 403;
|
||||
}
|
||||
location ~ /mail/.*\.php {
|
||||
# note: ~ has precendence over a regular location block
|
||||
include fastcgi_params;
|
||||
fastcgi_split_path_info ^/mail(/.*)()$;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME /usr/local/lib/roundcubemail/$fastcgi_script_name;
|
||||
fastcgi_pass php-fpm;
|
||||
|
||||
# Outgoing mail also goes through this endpoint, so increase the maximum
|
||||
# file upload limit to match the corresponding Postfix limit.
|
||||
client_max_body_size 128M;
|
||||
}
|
||||
|
||||
# Z-Push (Microsoft Exchange ActiveSync)
|
||||
location /Microsoft-Server-ActiveSync {
|
||||
include /etc/nginx/fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME /usr/local/lib/z-push/index.php;
|
||||
fastcgi_param PHP_VALUE "include_path=.:/usr/share/php:/usr/share/pear:/usr/share/awl/inc";
|
||||
fastcgi_read_timeout 630;
|
||||
fastcgi_pass php-fpm;
|
||||
|
||||
# Outgoing mail also goes through this endpoint, so increase the maximum
|
||||
# file upload limit to match the corresponding Postfix limit.
|
||||
client_max_body_size 128M;
|
||||
}
|
||||
location /autodiscover/autodiscover.xml {
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME /usr/local/lib/z-push/autodiscover/autodiscover.php;
|
||||
fastcgi_param PHP_VALUE "include_path=.:/usr/share/php:/usr/share/pear:/usr/share/awl/inc";
|
||||
fastcgi_pass php-fpm;
|
||||
}
|
||||
|
||||
|
||||
# ADDITIONAL DIRECTIVES HERE
|
||||
|
||||
# Disable viewing dotfiles (.htaccess, .svn, .git, etc.)
|
||||
# This block is placed at the end. Nginx's precedence rules means this block
|
||||
# takes precedence over all non-regex matches and only regex matches that
|
||||
# come after it (i.e. none of those, since this is the last one.) That means
|
||||
# we're blocking dotfiles in the static hosted sites but not the FastCGI-
|
||||
# handled locations for ownCloud (which serves user-uploaded files that might
|
||||
# have this pattern, see #414) or some of the other services.
|
||||
location ~ /\.(ht|svn|git|hg|bzr) {
|
||||
log_not_found off;
|
||||
access_log off;
|
||||
deny all;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -57,13 +57,15 @@ def do_dns_update(env, force=False):
|
|||
|
||||
# Custom records to add to zones.
|
||||
additional_records = list(get_custom_dns_config(env))
|
||||
from web_update import get_default_www_redirects
|
||||
www_redirect_domains = get_default_www_redirects(env)
|
||||
|
||||
# Write zone files.
|
||||
os.makedirs('/etc/nsd/zones', exist_ok=True)
|
||||
updated_domains = []
|
||||
for i, (domain, zonefile) in enumerate(zonefiles):
|
||||
# Build the records to put in the zone.
|
||||
records = build_zone(domain, domains, additional_records, env)
|
||||
records = build_zone(domain, domains, additional_records, www_redirect_domains, env)
|
||||
|
||||
# See if the zone has changed, and if so update the serial number
|
||||
# and write the zone file.
|
||||
|
@ -126,7 +128,7 @@ def do_dns_update(env, force=False):
|
|||
|
||||
########################################################################
|
||||
|
||||
def build_zone(domain, all_domains, additional_records, env, is_zone=True):
|
||||
def build_zone(domain, all_domains, additional_records, www_redirect_domains, env, is_zone=True):
|
||||
records = []
|
||||
|
||||
# For top-level zones, define the authoritative name servers.
|
||||
|
@ -177,7 +179,7 @@ def build_zone(domain, all_domains, additional_records, env, is_zone=True):
|
|||
subdomains = [d for d in all_domains if d.endswith("." + domain)]
|
||||
for subdomain in subdomains:
|
||||
subdomain_qname = subdomain[0:-len("." + domain)]
|
||||
subzone = build_zone(subdomain, [], additional_records, env, is_zone=False)
|
||||
subzone = build_zone(subdomain, [], additional_records, www_redirect_domains, env, is_zone=False)
|
||||
for child_qname, child_rtype, child_value, child_explanation in subzone:
|
||||
if child_qname == None:
|
||||
child_qname = subdomain_qname
|
||||
|
@ -215,10 +217,13 @@ def build_zone(domain, all_domains, additional_records, env, is_zone=True):
|
|||
has_rec_base = records
|
||||
defaults = [
|
||||
(None, "A", env["PUBLIC_IP"], "Required. May have a different value. Sets the IP address that %s resolves to for web hosting and other services besides mail. The A record must be present but its value does not affect mail delivery." % domain),
|
||||
("www", "A", env["PUBLIC_IP"], "Optional. Sets the IP address that www.%s resolves to, e.g. for web hosting." % domain),
|
||||
(None, "AAAA", env.get('PUBLIC_IPV6'), "Optional. Sets the IPv6 address that %s resolves to, e.g. for web hosting. (It is not necessary for receiving mail on this domain.)" % domain),
|
||||
("www", "AAAA", env.get('PUBLIC_IPV6'), "Optional. Sets the IPv6 address that www.%s resolves to, e.g. for web hosting." % domain),
|
||||
]
|
||||
if "www." + domain in www_redirect_domains:
|
||||
defaults += [
|
||||
("www", "A", env["PUBLIC_IP"], "Optional. Sets the IP address that www.%s resolves to so that the box can provide a redirect to the parent domain." % domain),
|
||||
("www", "AAAA", env.get('PUBLIC_IPV6'), "Optional. Sets the IPv6 address that www.%s resolves to so that the box can provide a redirect to the parent domain." % domain),
|
||||
]
|
||||
for qname, rtype, value, explanation in defaults:
|
||||
if value is None or value.strip() == "": continue # skip IPV6 if not set
|
||||
if not is_zone and qname == "www": continue # don't create any default 'www' subdomains on what are themselves subdomains
|
||||
|
@ -847,8 +852,10 @@ def build_recommended_dns(env):
|
|||
domains = get_dns_domains(env)
|
||||
zonefiles = get_dns_zones(env)
|
||||
additional_records = list(get_custom_dns_config(env))
|
||||
from web_update import get_default_www_redirects
|
||||
www_redirect_domains = get_default_www_redirects(env)
|
||||
for domain, zonefile in zonefiles:
|
||||
records = build_zone(domain, domains, additional_records, env)
|
||||
records = build_zone(domain, domains, additional_records, www_redirect_domains, env)
|
||||
|
||||
# remove records that we don't dislay
|
||||
records = [r for r in records if r[3] is not False]
|
||||
|
|
|
@ -12,7 +12,7 @@ import dns.reversename, dns.resolver
|
|||
import dateutil.parser, dateutil.tz
|
||||
|
||||
from dns_update import get_dns_zones, build_tlsa_record, get_custom_dns_config, get_secondary_dns
|
||||
from web_update import get_web_domains, get_domain_ssl_files
|
||||
from web_update import get_web_domains, get_default_www_redirects, get_domain_ssl_files
|
||||
from mailconfig import get_mail_domains, get_mail_aliases
|
||||
|
||||
from utils import shell, sort_domains, load_env_vars_from_file
|
||||
|
@ -227,7 +227,7 @@ def run_domain_checks(rounded_time, env, output, pool):
|
|||
dns_domains = set(dns_zonefiles)
|
||||
|
||||
# Get the list of domains we serve HTTPS for.
|
||||
web_domains = set(get_web_domains(env))
|
||||
web_domains = set(get_web_domains(env) + get_default_www_redirects(env))
|
||||
|
||||
domains_to_check = mail_domains | dns_domains | web_domains
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
import os, os.path, shutil, re, tempfile, rtyaml
|
||||
|
||||
from mailconfig import get_mail_domains
|
||||
from dns_update import get_custom_dns_config, do_dns_update
|
||||
from dns_update import get_custom_dns_config, do_dns_update, get_dns_zones
|
||||
from utils import shell, safe_domain_name, sort_domains
|
||||
|
||||
def get_web_domains(env):
|
||||
|
@ -36,21 +36,35 @@ def get_domains_with_a_records(env):
|
|||
domains.add(domain)
|
||||
return domains
|
||||
|
||||
def get_default_www_redirects(env):
|
||||
# Returns a list of www subdomains that we want to provide default redirects
|
||||
# for, i.e. any www's that aren't domains the user has actually configured
|
||||
# to serve for real. Which would be unusual.
|
||||
web_domains = set(get_web_domains(env))
|
||||
www_domains = set('www.' + zone for zone, zonefile in get_dns_zones(env))
|
||||
return sort_domains(www_domains - web_domains - get_domains_with_a_records(env), env)
|
||||
|
||||
def do_web_update(env):
|
||||
# Build an nginx configuration file.
|
||||
nginx_conf = open(os.path.join(os.path.dirname(__file__), "../conf/nginx-top.conf")).read()
|
||||
|
||||
# Load the templates.
|
||||
template1 = open(os.path.join(os.path.dirname(__file__), "../conf/nginx.conf")).read()
|
||||
template0 = open(os.path.join(os.path.dirname(__file__), "../conf/nginx.conf")).read()
|
||||
template1 = open(os.path.join(os.path.dirname(__file__), "../conf/nginx-alldomains.conf")).read()
|
||||
template2 = open(os.path.join(os.path.dirname(__file__), "../conf/nginx-primaryonly.conf")).read()
|
||||
template3 = "\trewrite / https://$REDIRECT_DOMAIN permanent;\n"
|
||||
|
||||
# Add the PRIMARY_HOST configuration first so it becomes nginx's default server.
|
||||
nginx_conf += make_domain_config(env['PRIMARY_HOSTNAME'], [template1, template2], env)
|
||||
nginx_conf += make_domain_config(env['PRIMARY_HOSTNAME'], [template0, template1, template2], env)
|
||||
|
||||
# Add configuration all other web domains.
|
||||
for domain in get_web_domains(env):
|
||||
if domain == env['PRIMARY_HOSTNAME']: continue # handled above
|
||||
nginx_conf += make_domain_config(domain, [template1], env)
|
||||
nginx_conf += make_domain_config(domain, [template0, template1], env)
|
||||
|
||||
# Add default www redirects.
|
||||
for domain in get_default_www_redirects(env):
|
||||
nginx_conf += make_domain_config(domain, [template0, template3], env)
|
||||
|
||||
# Did the file change? If not, don't bother writing & restarting nginx.
|
||||
nginx_conf_fn = "/etc/nginx/conf.d/local.conf"
|
||||
|
@ -300,4 +314,12 @@ def get_web_domains_info(env):
|
|||
"static_enabled": not has_root_proxy_or_redirect(domain),
|
||||
}
|
||||
for domain in get_web_domains(env)
|
||||
] + \
|
||||
[
|
||||
{
|
||||
"domain": domain,
|
||||
"ssl_certificate": check_cert(domain),
|
||||
"static_enabled": False,
|
||||
}
|
||||
for domain in get_default_www_redirects(env)
|
||||
]
|
||||
|
|
Loading…
Reference in a new issue