diff --git a/Makefile b/Makefile
index 441c154..e43de39 100644
--- a/Makefile
+++ b/Makefile
@@ -13,7 +13,7 @@ python_tests:
 #	rm -fr \
 #		deps/com.github.aiortc.aiortc/src/online_fxreader/vpn/dist;
 
-PYTHON_PROJECTS := \
+PYTHON_PROJECTS ?= \
 	deps/com.github.aiortc.aiortc/ \
 	deps/com.github.aiortc.aiortc/src/online_fxreader/vpn/ \
 	python
@@ -95,3 +95,15 @@ dotfiles_deploy:
 		dotfiles \
 	| xz --compress -9 --stdout > \
 	releases/tar/dotfiles-$(DOTFILES_VERSION).tar.xz
+
+systemd:
+	/usr/bin/env python3 d1/systemd.py
+	for d in tmp/d1; do \
+		(\
+			cd $$d; \
+			for i in *.service *.timer; do \
+				sudo ln -s -f $$PWD/$$i /etc/systemd/system/$$i; \
+			done; \
+		); \
+	done
+	sudo systemctl daemon-reload
diff --git a/d1/certbot.py b/d1/certbot.py
new file mode 100644
index 0000000..91ab5a0
--- /dev/null
+++ b/d1/certbot.py
@@ -0,0 +1,19 @@
+#!/usr/bin/env python3
+
+import subprocess
+import time
+import logging
+
+logger = logging.getLogger(__name__)
+
+
+logging.basicConfig(level=logging.INFO)
+
+while True:
+    subprocess.check_call([
+        'docker', 'compose', 'exec', 'ssl-app', 'certbot', 'renew',
+    ])
+    subprocess.check_call([
+        'docker', 'compose', 'exec', 'ssl-app', 'nginx', '-s', 'reload',
+    ])
+    break
diff --git a/d1/fxreader.online-certbot.service b/d1/fxreader.online-certbot.service
new file mode 100644
index 0000000..f249bf4
--- /dev/null
+++ b/d1/fxreader.online-certbot.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=fxreader.online-certbot
+
+[Service]
+Type=oneshot
+ExecStart=/usr/bin/python3 d1/certbot.py
+WorkingDirectory={{PROJECT_ROOT}}
+#Restart=always
+
+#[Install]
+#WantedBy=multi-user.target
diff --git a/d1/fxreader.online-certbot.timer b/d1/fxreader.online-certbot.timer
new file mode 100644
index 0000000..fc80867
--- /dev/null
+++ b/d1/fxreader.online-certbot.timer
@@ -0,0 +1,9 @@
+[Unit]
+Description=fxreader.online-certbot-timer
+
+[Timer]
+OnUnitActiveSec=1d
+OnBootSec=1m
+
+[Install]
+WantedBy=timers.target
diff --git a/d1/nginx_config.py b/d1/nginx_config.py
index c7939db..57a5556 100644
--- a/d1/nginx_config.py
+++ b/d1/nginx_config.py
@@ -214,6 +214,23 @@ def ssl(input_json, output_conf):
     servers = []
 
     if 'stream_server' in ssl_nginx:
+        upstream_servers = []
+        server_names = []
+
+        for k, v in ssl_nginx['stream_server'].items():
+            upstream_servers.append(
+                'upstream %s { server %s; }' % (
+                    v['upstream_name'],
+                    v['url'],
+                )
+            )
+            server_names.append(
+                '"%s" %s;' % (
+                    v['server_name'], v['upstream_name'],
+                )
+            )
+            
+
         ssl_port = 444
         stream_server = r'''
 stream {
@@ -221,26 +238,41 @@ stream {
         server 127.0.0.1:444;
     }
 
-    upstream ssh {
-        server {ssh};
-    }
+{upstream_servers}
 
-    map $ssl_preread_protocol $upstream {
-        default ssh;
-        "TLSv1.2" web;
-        "TLSv1.3" web;
+    #upstream ssh {
+    #    server {ssh};
+    #}
+
+    #map $ssl_preread_protocol $upstream {
+    #    default ssh;
+    #    "TLSv1.2" web;
+    #    "TLSv1.3" web;
+    #}
+
+    map $ssl_preread_server_name $upstream {
+        default web;
+{server_names}
     }
 
     # SSH and SSL on the same port
     server {
         listen 443;
 
-        proxy_pass $upstream;
         ssl_preread on;
+        proxy_pass $upstream;
     }
 }
         '''.replace(
-            '{ssh}', str(ssl_nginx['stream_server'])[:256]
+            '{upstream_servers}', ''.join([
+                '    ' + o + '\n'
+                for o in upstream_servers
+            ]),
+        ).replace(
+            '{server_names}', ''.join([
+                '        ' + o + '\n'
+                for o in server_names
+            ]),
         )
     else:
         stream_server = ''
diff --git a/d1/systemd.py b/d1/systemd.py
new file mode 100644
index 0000000..907c53a
--- /dev/null
+++ b/d1/systemd.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python3
+
+import os
+import pathlib
+import io
+import glob
+import subprocess
+import logging
+
+logger = logging.getLogger(__name__)
+
+logging.basicConfig(level=logging.INFO)
+
+cache_path = pathlib.Path.cwd() / 'tmp'
+
+project_root = pathlib.Path.cwd()
+
+logger.info(dict(project_root=project_root, cache_path=cache_path,))
+
+for service in [
+    pathlib.Path(o) for o in sum([
+        glob.glob('d1/*.service'),
+        glob.glob('d1/*.timer')
+    ], [])
+]:
+    os.makedirs(str((cache_path / service).parent), exist_ok=True)
+
+    with io.open(str(service), 'r') as f:
+        with io.open(
+            str(cache_path / service), 'w'
+        ) as f2:
+            f2.write(
+                f.read().replace(
+                    '{{PROJECT_ROOT}}',
+                    str(project_root),
+                )
+            )
+    logger.info(dict(
+        service=str(service),
+        msg='updated',
+    ))
diff --git a/deps/com.github.aiortc.aiortc b/deps/com.github.aiortc.aiortc
index d3cdc32..adef10a 160000
--- a/deps/com.github.aiortc.aiortc
+++ b/deps/com.github.aiortc.aiortc
@@ -1 +1 @@
-Subproject commit d3cdc32f8c474d90e48ecc4729c0088999cb82ad
+Subproject commit adef10a8c41f5c550622879370a40f8a9e545574
diff --git a/docker-compose.yml b/docker-compose.yml
index 3c4f9e0..6f8df28 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -32,16 +32,20 @@ services:
     build:
       context: .
       dockerfile: ./docker/dynu/Dockerfile
+    profiles:
+      - broken
     volumes:
       - ./d1/dynu_update.py:/app/d1/dynu_update.py:ro
       - ./tmp/cache/dynu.auth.json:/app/tmp/cache/dynu.auth.json:ro
     restart: always
-    links:
-      - ngrok
+    # links:
+    #  - ngrok
   ngrok:
     image: wernight/ngrok
     links:
       - app
+    profiles:
+      - broken
     command: ['ngrok', 'http', 'app:80']
     volumes:
       - ./tmp/cache/ngrok.yml:/home/ngrok/.ngrok2/ngrok.yml:ro