Files
LLeMbas/deploy/nginx-vhost.conf
T
Jaroslav Beneš 9179461bfe Add registration toggle and password change; genericise deploy
Two things the running instance needed.

**Registration toggle.** Admin -> General, backed by a new settings table
group rather than the environment. LEMBAS_ALLOW_SIGNUP now seeds only the
initial value: once an administrator saves the setting, the stored value
wins. The alternative -- environment always winning -- means a toggle in
the UI silently reverts on the next restart, which is worse than not
offering one. Closing registration also removes the "Create one" link
from the sign-in page, so the link never leads somewhere that refuses.

**Password change**, on the user settings page. Changing a password
revokes every other session and immediately re-issues a cookie for the
current one: if the reason for the change is that somebody else knows
the password, leaving their session alive defeats the point, but signing
the user out of the tab they are standing in is merely rude.

**deploy/ is now host-agnostic.** This repository is public, so the unit
and vhost became templates with __PREFIX__ / __SITE_HOST__ / __APP_PORT__
substituted at install time, and every path, hostname and port moved to
environment variables. REPO_URL defaults to the checkout's own origin so
a fork deploys itself. Machine-specific values belong in private notes,
not here -- CLAUDE.md now says so.

83 tests, ruff clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 11:14:33 +02:00

62 lines
2.1 KiB
Plaintext

# nginx vhost template for LLeMbas.
#
# install.sh substitutes __SITE_HOST__ and __APP_PORT__ and writes the result to
# /etc/nginx/conf.d/<host>.conf. Edit this file, not the installed copy.
#
# Assumes a self-signed certificate at /etc/nginx/ssl/<host>.{crt,key}, which
# install.sh generates. To use a real certificate, point ssl_certificate at it;
# nothing else here needs to change.
server {
listen 80;
listen [::]:80;
server_name __SITE_HOST__;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name __SITE_HOST__;
ssl_certificate /etc/nginx/ssl/__SITE_HOST__.crt;
ssl_certificate_key /etc/nginx/ssl/__SITE_HOST__.key;
ssl_protocols TLSv1.2 TLSv1.3;
# File uploads land here once that feature exists; 0 = no limit.
client_max_body_size 0;
location / {
proxy_pass http://127.0.0.1:__APP_PORT__;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Streamed replies are server-sent events. Every one of these matters:
# with buffering on (the default) nginx holds the whole reply and
# delivers it in one lump at the end, which is indistinguishable from
# streaming being broken.
proxy_buffering off;
proxy_request_buffering off;
proxy_cache off;
# SSE is plain HTTP/1.1 chunked, not a websocket upgrade, so the
# connection header must simply be left to keep-alive.
proxy_set_header Connection "";
# A model can think for minutes before the first token. The default
# 60s read timeout would cut long generations off mid-sentence.
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
location /static/ {
proxy_pass http://127.0.0.1:__APP_PORT__;
proxy_set_header Host $host;
expires 1h;
add_header Cache-Control "public";
}
}