Add optional HTTP->HTTPS redirect per proxy target

Each target can now have an HTTP port with a checkbox to enable
automatic redirect to HTTPS. Configurable in WebUI and API.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Stefan Hacker 2026-04-09 22:32:31 +02:00
parent 0206b5b73a
commit 261482232c
2 changed files with 51 additions and 0 deletions

View File

@ -108,6 +108,9 @@ def generate_nginx_config(config):
location_block = _proxy_location_block(target_scheme, upstream_name) location_block = _proxy_location_block(target_scheme, upstream_name)
http_redirect = target.get("http_redirect", False)
http_port = target.get("http_port", 0)
# Domain-based routing # Domain-based routing
if domains: if domains:
for domain_entry in domains: for domain_entry in domains:
@ -130,6 +133,15 @@ def generate_nginx_config(config):
lines.append("}") lines.append("}")
lines.append("") lines.append("")
# HTTP -> HTTPS redirect for this domain
if http_redirect and http_port:
lines.append("server {")
lines.append(f" listen {http_port};")
lines.append(f" server_name {domain};")
lines.append(f" return 301 https://$host:{domain_port}$request_uri;")
lines.append("}")
lines.append("")
# IP/Port-based routing # IP/Port-based routing
if listen_port: if listen_port:
lines.append("server {") lines.append("server {")
@ -147,6 +159,15 @@ def generate_nginx_config(config):
lines.append("}") lines.append("}")
lines.append("") lines.append("")
# HTTP -> HTTPS redirect for this port
if http_redirect and http_port:
lines.append("server {")
lines.append(f" listen {http_port};")
lines.append(f" server_name _;")
lines.append(f" return 301 https://$host:{listen_port}$request_uri;")
lines.append("}")
lines.append("")
conf_content = "\n".join(lines) conf_content = "\n".join(lines)
os.makedirs(NGINX_CONF_DIR, exist_ok=True) os.makedirs(NGINX_CONF_DIR, exist_ok=True)
with open(NGINX_UPSTREAM_CONF, "w") as f: with open(NGINX_UPSTREAM_CONF, "w") as f:
@ -273,6 +294,8 @@ def add_target():
"target_port": int(request.form.get("target_port", 80)), "target_port": int(request.form.get("target_port", 80)),
"target_scheme": request.form.get("target_scheme", "http"), "target_scheme": request.form.get("target_scheme", "http"),
"listen_port": int(request.form.get("listen_port", 0) or 0), "listen_port": int(request.form.get("listen_port", 0) or 0),
"http_redirect": request.form.get("http_redirect") == "on",
"http_port": int(request.form.get("http_port", 0) or 0),
"domains": domains, "domains": domains,
"enabled": True, "enabled": True,
} }
@ -330,6 +353,8 @@ def edit_target(idx):
"target_port": int(request.form.get("target_port", 80)), "target_port": int(request.form.get("target_port", 80)),
"target_scheme": request.form.get("target_scheme", "http"), "target_scheme": request.form.get("target_scheme", "http"),
"listen_port": int(request.form.get("listen_port", 0) or 0), "listen_port": int(request.form.get("listen_port", 0) or 0),
"http_redirect": request.form.get("http_redirect") == "on",
"http_port": int(request.form.get("http_port", 0) or 0),
"domains": domains, "domains": domains,
"enabled": config["targets"][idx].get("enabled", True), "enabled": config["targets"][idx].get("enabled", True),
} }

View File

@ -237,6 +237,16 @@
<label>Listen-Port (fuer IP-Zugriff)</label> <label>Listen-Port (fuer IP-Zugriff)</label>
<input type="number" name="listen_port" placeholder="z.B. 8080" min="0" max="65535"> <input type="number" name="listen_port" placeholder="z.B. 8080" min="0" max="65535">
</div> </div>
<div class="form-group" style="max-width: 200px;">
<label>HTTP-Port (Redirect)</label>
<input type="number" name="http_port" placeholder="z.B. 8080" min="0" max="65535">
</div>
<div class="form-group" style="max-width: 200px; justify-content: center;">
<label>
<input type="checkbox" name="http_redirect" style="width:auto;margin-right:6px;">
HTTP &rarr; HTTPS Redirect
</label>
</div>
</div> </div>
<div class="form-group"> <div class="form-group">
@ -301,6 +311,11 @@
<span>Domain:</span> {{ d.domain }}:{{ d.port }} <span>Domain:</span> {{ d.domain }}:{{ d.port }}
</div> </div>
{% endfor %} {% endfor %}
{% if target.http_redirect and target.http_port %}
<div class="target-detail">
<span>HTTP Redirect:</span> Port {{ target.http_port }} &rarr; HTTPS
</div>
{% endif %}
</div> </div>
<!-- Edit form --> <!-- Edit form -->
@ -332,6 +347,17 @@
<label>Listen-Port</label> <label>Listen-Port</label>
<input type="number" name="listen_port" value="{{ target.listen_port or '' }}"> <input type="number" name="listen_port" value="{{ target.listen_port or '' }}">
</div> </div>
<div class="form-group" style="max-width: 200px;">
<label>HTTP-Port (Redirect)</label>
<input type="number" name="http_port" value="{{ target.http_port or '' }}">
</div>
<div class="form-group" style="max-width: 200px; justify-content: center;">
<label>
<input type="checkbox" name="http_redirect" style="width:auto;margin-right:6px;"
{{ "checked" if target.http_redirect }}>
HTTP &rarr; HTTPS Redirect
</label>
</div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label>Domaenen</label> <label>Domaenen</label>