use Caddy instead of NGINX for vhosts
This commit is contained in:
parent
0d55f01bfc
commit
bd50f4142f
|
@ -14,7 +14,7 @@ Docker containers instead, which are much easier to work with than the VM.
|
|||
|
||||
First, make sure you create the virtualenv:
|
||||
```sh
|
||||
docker run --rm -v "$PWD:$PWD" -w "$PWD" -u $(id -u):$(id -g) python:3.7-buster \
|
||||
docker run --rm -v "$PWD:$PWD" -w "$PWD" python:3.7-buster \
|
||||
sh -c 'python -m venv venv && . venv/bin/activate && pip install -r requirements.txt -r dev-requirements.txt'
|
||||
```
|
||||
Then bring up the containers:
|
||||
|
|
|
@ -1 +1 @@
|
|||
1.0.11
|
||||
1.0.12
|
||||
|
|
|
@ -36,8 +36,6 @@ class CloudService:
|
|||
self.members_domain = 'Members'
|
||||
self.vhost_mgr = VHostManager(
|
||||
vhost_dir=cfg.get('cloud vhosts_config_dir'),
|
||||
ssl_cert_path=cfg.get('cloud vhosts_ssl_cert_path'),
|
||||
ssl_key_path=cfg.get('cloud vhosts_ssl_key_path'),
|
||||
)
|
||||
self.max_vhosts_per_account = cfg.get('cloud vhosts_max_vhosts_per_account')
|
||||
self.vhost_domain = cfg.get('cloud vhosts_members_domain')
|
||||
|
|
|
@ -10,22 +10,15 @@ from zope.interface import implementer
|
|||
from ceo_common.logger_factory import logger_factory
|
||||
from ceo_common.interfaces import IVHostManager
|
||||
|
||||
PROXY_PASS_IP_RE = re.compile(r'^\s+proxy_pass\s+http://(?P<ip_address>[\d.]+);$')
|
||||
VHOST_FILENAME_RE = re.compile(r'^member_(?P<username>[0-9a-z-]+)_(?P<domain>[0-9a-z.-]+)$')
|
||||
REVERSE_PROXY_IP_RE = re.compile(r'^\s+reverse_proxy\s+http://(?P<ip_address>[\d.]+)$')
|
||||
VHOST_FILENAME_RE = re.compile(r'^(?P<username>[0-9a-z-]+)_(?P<domain>[0-9a-z.-]+)$')
|
||||
logger = logger_factory(__name__)
|
||||
|
||||
|
||||
@implementer(IVHostManager)
|
||||
class VHostManager:
|
||||
def __init__(
|
||||
self,
|
||||
vhost_dir: str,
|
||||
ssl_cert_path: str,
|
||||
ssl_key_path: str,
|
||||
):
|
||||
def __init__(self, vhost_dir: str):
|
||||
self.vhost_dir = vhost_dir
|
||||
self.ssl_cert_path = ssl_cert_path
|
||||
self.ssl_key_path = ssl_key_path
|
||||
self.jinja_env = jinja2.Environment(
|
||||
loader=jinja2.PackageLoader('ceod.model'),
|
||||
)
|
||||
|
@ -35,7 +28,7 @@ class VHostManager:
|
|||
"""Generate a filename for the vhost record"""
|
||||
# sanity check...
|
||||
assert '..' not in domain and '/' not in domain
|
||||
return 'member' + '_' + username + '_' + domain
|
||||
return username + '_' + domain
|
||||
|
||||
def _vhost_filepath(self, username: str, domain: str) -> str:
|
||||
"""Generate an absolute path for the vhost record"""
|
||||
|
@ -43,17 +36,16 @@ class VHostManager:
|
|||
|
||||
def _vhost_files(self, username: str) -> List[str]:
|
||||
"""Return a list of all vhost files for this user."""
|
||||
return glob.glob(os.path.join(self.vhost_dir, 'member_' + username + '_*'))
|
||||
return glob.glob(os.path.join(self.vhost_dir, username + '_*'))
|
||||
|
||||
def _reload_web_server(self):
|
||||
logger.debug('Reloading nginx')
|
||||
subprocess.run(['systemctl', 'reload', 'nginx'], check=True)
|
||||
logger.debug('Reloading Caddy')
|
||||
subprocess.run(['systemctl', 'reload', 'caddy'], check=True)
|
||||
|
||||
def create_vhost(self, username: str, domain: str, ip_address: str):
|
||||
template = self.jinja_env.get_template('nginx_cloud_vhost_config.j2')
|
||||
template = self.jinja_env.get_template('caddy_cloud_vhost_config.j2')
|
||||
body = template.render(
|
||||
username=username, domain=domain, ip_address=ip_address,
|
||||
ssl_cert_path=self.ssl_cert_path, ssl_key_path=self.ssl_key_path)
|
||||
username=username, domain=domain, ip_address=ip_address)
|
||||
filepath = self._vhost_filepath(username, domain)
|
||||
logger.info(f'Writing a new vhost ({domain} -> {ip_address}) to {filepath}')
|
||||
with open(filepath, 'w') as fo:
|
||||
|
@ -78,7 +70,7 @@ class VHostManager:
|
|||
domain = match.group('domain')
|
||||
ip_address = None
|
||||
for line in open(filepath):
|
||||
match = PROXY_PASS_IP_RE.match(line)
|
||||
match = REVERSE_PROXY_IP_RE.match(line)
|
||||
if match is None:
|
||||
continue
|
||||
ip_address = match.group('ip_address')
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
# This file is automatically managed by ceod.
|
||||
# DO NOT EDIT THIS FILE MANUALLY UNLESS YOU KNOW WHAT YOU ARE DOING.
|
||||
|
||||
{{ domain }} {
|
||||
reverse_proxy http://{{ ip_address }}
|
||||
log {
|
||||
output file /var/log/caddy/member_{{ username }}.log {
|
||||
roll_size 5MiB
|
||||
roll_keep 2
|
||||
}
|
||||
format filter {
|
||||
wrap json
|
||||
fields {
|
||||
request>headers delete
|
||||
request>tls delete
|
||||
resp_headers delete
|
||||
user_id delete
|
||||
common_log delete
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
# This file is automatically managed by ceod.
|
||||
# DO NOT EDIT THIS FILE MANUALLY.
|
||||
# If you want to modify it, please move it to another directory.
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name {{ domain }};
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
server_name {{ domain }};
|
||||
ssl_certificate {{ ssl_cert_path }};
|
||||
ssl_certificate_key {{ ssl_key_path }};
|
||||
|
||||
location / {
|
||||
proxy_pass http://{{ ip_address }};
|
||||
}
|
||||
|
||||
access_log /var/log/nginx/member-{{ username }}-access.log;
|
||||
error_log /var/log/nginx/member-{{ username }}-error.log;
|
||||
}
|
|
@ -81,10 +81,8 @@ secret_key = REPLACE_ME
|
|||
base_url = http://localhost:8080/client/api
|
||||
|
||||
[cloud vhosts]
|
||||
config_dir = /etc/nginx/ceod-member-vhosts
|
||||
ssl_cert_path = /etc/ssl/private/csclub.cloud.chain
|
||||
ssl_key_path = /etc/ssl/private/csclub.cloud.key
|
||||
config_dir = /etc/caddy/ceod-member-vhosts
|
||||
max_vhosts_per_account = 10
|
||||
members_domain = m.csclub.cloud
|
||||
members_domain = csclub.cloud
|
||||
ip_range_min = 172.19.134.10
|
||||
ip_range_max = 172.19.134.160
|
||||
|
|
|
@ -102,7 +102,7 @@ def test_cloud_vhosts(cfg, client, new_user, ldap_conn):
|
|||
assert data == {'vhosts': [{'domain': domain1, 'ip_address': ip1}]}
|
||||
|
||||
# invalid domain name
|
||||
domain2 = uid + 'm.cloud.' + cfg.get('base_domain')
|
||||
domain2 = uid + 'cloud.' + cfg.get('base_domain')
|
||||
ip2 = ip1
|
||||
status, _ = client.put(
|
||||
f'/api/cloud/vhosts/{domain2}', json={'ip_address': ip2},
|
||||
|
|
|
@ -4,8 +4,8 @@ import os
|
|||
def test_vhost_mgr(cloud_srv):
|
||||
vhost_mgr = cloud_srv.vhost_mgr
|
||||
username = 'test1'
|
||||
domain = username + '.m.csclub.cloud'
|
||||
filename = f'member_{username}_{domain}'
|
||||
domain = username + '.csclub.cloud'
|
||||
filename = f'{username}_{domain}'
|
||||
ip_address = '172.19.134.11'
|
||||
vhost_mgr.create_vhost(username, domain, ip_address)
|
||||
path = os.path.join(vhost_mgr.vhost_dir, filename)
|
||||
|
|
|
@ -76,9 +76,7 @@ base_url = http://localhost:8080/client/api
|
|||
|
||||
[cloud vhosts]
|
||||
config_dir = /run/ceod/member-vhosts
|
||||
ssl_cert_path = /etc/ssl/private/csclub.cloud.chain
|
||||
ssl_key_path = /etc/ssl/private/csclub.cloud.key
|
||||
max_vhosts_per_account = 10
|
||||
members_domain = m.csclub.cloud
|
||||
members_domain = csclub.cloud
|
||||
ip_range_min = 172.19.134.10
|
||||
ip_range_max = 172.19.134.160
|
||||
|
|
|
@ -75,9 +75,7 @@ base_url = http://localhost:8080/client/api
|
|||
|
||||
[cloud vhosts]
|
||||
config_dir = /run/ceod/member-vhosts
|
||||
ssl_cert_path = /etc/ssl/private/csclub.cloud.chain
|
||||
ssl_key_path = /etc/ssl/private/csclub.cloud.key
|
||||
max_vhosts_per_account = 10
|
||||
members_domain = m.csclub.cloud
|
||||
members_domain = csclub.cloud
|
||||
ip_range_min = 172.19.134.10
|
||||
ip_range_max = 172.19.134.160
|
||||
|
|
Loading…
Reference in New Issue