mirror of
https://github.com/frappe/bench.git
synced 2025-01-10 09:02:10 +00:00
Merge pull request #247 from frappe/nginx-domains-wildcard-ssl
[refactor] nginx config now supports wildcard ssl and custom domains
This commit is contained in:
commit
f9e8abc5d3
@ -2,7 +2,7 @@ from jinja2 import Environment, PackageLoader
|
|||||||
|
|
||||||
__version__ = "4.0.0-beta"
|
__version__ = "4.0.0-beta"
|
||||||
|
|
||||||
env = Environment(loader=PackageLoader('bench.config'), trim_blocks=True)
|
env = Environment(loader=PackageLoader('bench.config'))
|
||||||
|
|
||||||
FRAPPE_VERSION = None
|
FRAPPE_VERSION = None
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import os, json, click
|
import os, json, click, random, string
|
||||||
from bench.utils import get_sites, get_bench_name
|
from bench.utils import get_sites, get_bench_name
|
||||||
|
|
||||||
def make_nginx_conf(bench_path, force=False):
|
def make_nginx_conf(bench_path, force=False):
|
||||||
@ -18,7 +18,10 @@ def make_nginx_conf(bench_path, force=False):
|
|||||||
"sites": sites,
|
"sites": sites,
|
||||||
"webserver_port": config.get('webserver_port'),
|
"webserver_port": config.get('webserver_port'),
|
||||||
"socketio_port": config.get('socketio_port'),
|
"socketio_port": config.get('socketio_port'),
|
||||||
"bench_name": get_bench_name(bench_path)
|
"bench_name": get_bench_name(bench_path),
|
||||||
|
|
||||||
|
# for nginx map variable
|
||||||
|
"random_string": "".join(random.choice(string.ascii_lowercase) for i in xrange(7))
|
||||||
})
|
})
|
||||||
|
|
||||||
conf_path = os.path.join(bench_path, "config", "nginx.conf")
|
conf_path = os.path.join(bench_path, "config", "nginx.conf")
|
||||||
@ -31,22 +34,39 @@ def make_nginx_conf(bench_path, force=False):
|
|||||||
|
|
||||||
def prepare_sites(config, bench_path):
|
def prepare_sites(config, bench_path):
|
||||||
sites = {
|
sites = {
|
||||||
|
"that_use_port": [],
|
||||||
"that_use_dns": [],
|
"that_use_dns": [],
|
||||||
"that_use_ssl": [],
|
"that_use_ssl": [],
|
||||||
"that_use_port": []
|
"that_use_wildcard_ssl": []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
domain_map = {}
|
||||||
ports_in_use = {}
|
ports_in_use = {}
|
||||||
|
|
||||||
dns_multitenant = config.get('dns_multitenant')
|
dns_multitenant = config.get('dns_multitenant')
|
||||||
|
|
||||||
for site in get_sites_with_config(bench_path=bench_path):
|
for site in get_sites_with_config(bench_path=bench_path):
|
||||||
if dns_multitenant:
|
if dns_multitenant:
|
||||||
# assumes site's folder name is same as the domain name
|
domain = site.get('domain')
|
||||||
|
|
||||||
if site.get("ssl_certificate") and site.get("ssl_certificate_key"):
|
if domain:
|
||||||
|
# when site's folder name is different than domain name
|
||||||
|
domain_map[domain] = site['name']
|
||||||
|
|
||||||
|
site_name = domain or site['name']
|
||||||
|
|
||||||
|
if site.get('wildcard'):
|
||||||
|
sites["that_use_wildcard_ssl"].append(site_name)
|
||||||
|
|
||||||
|
if not sites.get('wildcard_ssl_certificate'):
|
||||||
|
sites["wildcard_ssl_certificate"] = site['ssl_certificate']
|
||||||
|
sites["wildcard_ssl_certificate_key"] = site['ssl_certificate_key']
|
||||||
|
|
||||||
|
elif site.get("ssl_certificate") and site.get("ssl_certificate_key"):
|
||||||
sites["that_use_ssl"].append(site)
|
sites["that_use_ssl"].append(site)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
sites["that_use_dns"].append(site["name"])
|
sites["that_use_dns"].append(site_name)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if not site.get("port"):
|
if not site.get("port"):
|
||||||
@ -58,10 +78,16 @@ def prepare_sites(config, bench_path):
|
|||||||
ports_in_use[site["port"]] = site["name"]
|
ports_in_use[site["port"]] = site["name"]
|
||||||
sites["that_use_port"].append(site)
|
sites["that_use_port"].append(site)
|
||||||
|
|
||||||
|
sites['domain_map'] = domain_map
|
||||||
|
|
||||||
return sites
|
return sites
|
||||||
|
|
||||||
def get_sites_with_config(bench_path):
|
def get_sites_with_config(bench_path):
|
||||||
|
from bench.config.common_site_config import get_config
|
||||||
|
|
||||||
sites = get_sites(bench_path=bench_path)
|
sites = get_sites(bench_path=bench_path)
|
||||||
|
dns_multitenant = get_config(bench_path).get('dns_multitenant')
|
||||||
|
|
||||||
ret = []
|
ret = []
|
||||||
for site in sites:
|
for site in sites:
|
||||||
site_config = get_site_config(site, bench_path=bench_path)
|
site_config = get_site_config(site, bench_path=bench_path)
|
||||||
@ -71,8 +97,55 @@ def get_sites_with_config(bench_path):
|
|||||||
"ssl_certificate": site_config.get('ssl_certificate'),
|
"ssl_certificate": site_config.get('ssl_certificate'),
|
||||||
"ssl_certificate_key": site_config.get('ssl_certificate_key')
|
"ssl_certificate_key": site_config.get('ssl_certificate_key')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if dns_multitenant and site_config.get('domains'):
|
||||||
|
for domain in site_config.get('domains'):
|
||||||
|
# domain can be a string or a dict with 'domain', 'ssl_certificate', 'ssl_certificate_key'
|
||||||
|
if isinstance(domain, basestring):
|
||||||
|
domain = { 'domain': domain }
|
||||||
|
|
||||||
|
domain['name'] = site
|
||||||
|
ret.append(domain)
|
||||||
|
|
||||||
|
use_wildcard_certificate(bench_path, ret)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
def use_wildcard_certificate(bench_path, ret):
|
||||||
|
'''
|
||||||
|
stored in common_site_config.json as:
|
||||||
|
"wildcard": {
|
||||||
|
"domain": "*.erpnext.com",
|
||||||
|
"ssl_certificate": "/path/to/erpnext.com.cert",
|
||||||
|
"ssl_certificate_key": "/path/to/erpnext.com.key"
|
||||||
|
}
|
||||||
|
'''
|
||||||
|
from bench.config.common_site_config import get_config
|
||||||
|
config = get_config(bench_path=bench_path)
|
||||||
|
wildcard = config.get('wildcard')
|
||||||
|
|
||||||
|
if not wildcard:
|
||||||
|
return
|
||||||
|
|
||||||
|
domain = wildcard['domain']
|
||||||
|
ssl_certificate = wildcard['ssl_certificate']
|
||||||
|
ssl_certificate_key = wildcard['ssl_certificate_key']
|
||||||
|
|
||||||
|
if domain.startswith('*.'):
|
||||||
|
domain = domain[1:]
|
||||||
|
else:
|
||||||
|
domain = '.' + domain
|
||||||
|
|
||||||
|
for site in ret:
|
||||||
|
if site.get('ssl_certificate'):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if (site.get('domain') or site['name']).endswith(domain):
|
||||||
|
# example: ends with .erpnext.com
|
||||||
|
site['ssl_certificate'] = ssl_certificate
|
||||||
|
site['ssl_certificate_key'] = ssl_certificate_key
|
||||||
|
site['wildcard'] = 1
|
||||||
|
|
||||||
def get_site_config(site, bench_path='.'):
|
def get_site_config(site, bench_path='.'):
|
||||||
with open(os.path.join(bench_path, 'sites', site, 'site_config.json')) as f:
|
with open(os.path.join(bench_path, 'sites', site, 'site_config.json')) as f:
|
||||||
return json.load(f)
|
return json.load(f)
|
||||||
|
@ -1,7 +1,16 @@
|
|||||||
{% macro server_block(bench_name, port, server_names, sites_path, ssl_certificate, ssl_certificate_key) %}
|
{%- macro nginx_map(from_variable, to_variable, values, default) %}
|
||||||
|
map {{ from_variable }} {{ to_variable }} {
|
||||||
|
{% for (from, to) in values.items() -%}
|
||||||
|
{{ from }} {{ to }};
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
{%- set site_name = server_names[0] if (server_names|length)==1 else "$host" -%}
|
{%- if default -%}
|
||||||
|
default {{ default }};
|
||||||
|
{% endif %}
|
||||||
|
}
|
||||||
|
{%- endmacro %}
|
||||||
|
|
||||||
|
{%- macro server_block(bench_name, port, server_names, site_name, sites_path, ssl_certificate, ssl_certificate_key) %}
|
||||||
server {
|
server {
|
||||||
listen {{ port }};
|
listen {{ port }};
|
||||||
server_name
|
server_name
|
||||||
@ -94,18 +103,22 @@ server {
|
|||||||
# text/html is always compressed by HttpGzipModule
|
# text/html is always compressed by HttpGzipModule
|
||||||
}
|
}
|
||||||
|
|
||||||
{% if ssl_certificate and ssl_certificate_key %}
|
{% if ssl_certificate and ssl_certificate_key -%}
|
||||||
# http to https redirect for {{ server_names[0] }}
|
# http to https redirect
|
||||||
server {
|
server {
|
||||||
listen 80;
|
listen 80;
|
||||||
server_name {{ server_names[0] }};
|
server_name
|
||||||
|
{% for name in server_names -%}
|
||||||
|
{{ name }}
|
||||||
|
{% endfor -%}
|
||||||
|
;
|
||||||
|
|
||||||
return 301 https://$host$request_uri?$query_string;
|
return 301 https://$host$request_uri?$query_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{# keep the empty line above for a pleasant rendering #}
|
{%- endmacro -%}
|
||||||
{% endmacro %}
|
|
||||||
|
|
||||||
upstream {{ bench_name }}-frappe {
|
upstream {{ bench_name }}-frappe {
|
||||||
server 127.0.0.1:{{ webserver_port or 8000 }} fail_timeout=0;
|
server 127.0.0.1:{{ webserver_port or 8000 }} fail_timeout=0;
|
||||||
@ -115,16 +128,36 @@ upstream {{ bench_name}}-socketio-server {
|
|||||||
server 127.0.0.1:{{ socketio_port or 3000 }} fail_timeout=0;
|
server 127.0.0.1:{{ socketio_port or 3000 }} fail_timeout=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# setup maps
|
||||||
|
{%- set site_name_variable="$host" %}
|
||||||
|
{% if sites.domain_map -%}
|
||||||
|
{# we append these variables with a random string as there could be multiple benches #}
|
||||||
|
{%- set site_name_variable="$site_name_{0}".format(random_string) -%}
|
||||||
|
{{ nginx_map(from_variable="$host", to_variable=site_name_variable, values=sites.domain_map, default="$host") }}
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
|
# server blocks
|
||||||
{% if sites.that_use_dns -%}
|
{% if sites.that_use_dns -%}
|
||||||
|
|
||||||
{{ server_block(bench_name, 80, sites.that_use_dns, sites_path) }}
|
{{ server_block(bench_name, port=80, server_names=sites.that_use_dns, site_name=site_name_variable, sites_path=sites_path) }}
|
||||||
|
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
|
{% if sites.that_use_wildcard_ssl -%}
|
||||||
|
|
||||||
|
{{ server_block(bench_name, port=443, server_names=sites.that_use_wildcard_ssl,
|
||||||
|
site_name=site_name_variable, sites_path=sites_path,
|
||||||
|
ssl_certificate=sites.wildcard_ssl_certificate,
|
||||||
|
ssl_certificate_key=sites.wildcard_ssl_certificate_key) }}
|
||||||
|
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
{%- if sites.that_use_ssl -%}
|
{%- if sites.that_use_ssl -%}
|
||||||
{% for site in sites.that_use_ssl -%}
|
{% for site in sites.that_use_ssl -%}
|
||||||
|
|
||||||
{{ server_block(bench_name, 443, [site.name], sites_path, site.ssl_certificate, site.ssl_certificate_key) }}
|
{{ server_block(bench_name, port=443, server_names=[site.domain or site.name],
|
||||||
|
site_name=site_name_variable, sites_path=sites_path,
|
||||||
|
ssl_certificate=site.ssl_certificate, ssl_certificate_key=site.ssl_certificate_key) }}
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
@ -132,7 +165,7 @@ upstream {{ bench_name}}-socketio-server {
|
|||||||
{% if sites.that_use_port -%}
|
{% if sites.that_use_port -%}
|
||||||
{%- for site in sites.that_use_port -%}
|
{%- for site in sites.that_use_port -%}
|
||||||
|
|
||||||
{{ server_block(bench_name, site.port, [site.name], sites_path) }}
|
{{ server_block(bench_name, port=site.port, server_names=[site.name], site_name=site.name, sites_path=sites_path) }}
|
||||||
|
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
Loading…
Reference in New Issue
Block a user