nginx: serve Gitea over HTTPS on gitea.wingard.pro

Adds a Let's Encrypt-backed vhost in front of Gitea's port 3010, which carries
both the web UI and the Docker registry (/v2/). This is what lets containers
push and pull the local image WITHOUT insecure-registries: that daemon option
needs a config change plus a daemon restart on every client that pulls,
including the arch-vm guest, and what it really buys is skipping cert
verification. A real cert on a name clients already resolve needs no client
configuration at all. Body and timeout limits are raised because image layers
are GB-scale.

Also adds gitea.wingard.pro to networking.hosts and to the Pi-hole records: the
host's own resolver goes to Comcast (*.wingard.pro -> WAN) and the router does
not hairpin, so the host cannot reach its own services by name.

ROOT_URL is deliberately still the plain-HTTP address; it flips to the HTTPS
name in a follow-up once the certificate is proven to issue and serve.
This commit is contained in:
Harley
2026-09-27 16:01:57 -04:00
parent 52aca33469
commit 40ae3e0026
+34 -1
View File
@@ -743,12 +743,13 @@ PYEOF
## (correctly) not port-forwarded and Comcast hairpinning is broken. Net effect:
## the host cannot reach its own services by name. Measured 2026-09-23: the joplin
## CLI failed with `connect ECONNREFUSED 71.61.169.167:8444` (that is the WAN IP).
## Same four names as the Pi-hole records in 5.3, from the host side.
## Same five names as the Pi-hole records in 5.3, from the host side.
networking.hosts = {
"10.0.1.49" = [
"jellyfin.wingard.pro"
"speedtest.wingard.pro"
"vault.wingard.pro"
"gitea.wingard.pro"
"joplin.wingard.pro"
];
};
@@ -987,6 +988,7 @@ PYEOF
"10.0.1.49 jellyfin.wingard.pro"
"10.0.1.49 speedtest.wingard.pro"
"10.0.1.49 vault.wingard.pro"
"10.0.1.49 gitea.wingard.pro"
"10.0.1.49 joplin.wingard.pro"
];
};
@@ -1108,6 +1110,37 @@ PYEOF
enable = true;
recommendedProxySettings = true;
virtualHosts = {
## Gitea — the HTTPS front for both the web UI and the Docker registry.
##
## Why TLS rather than `insecure-registries`: that daemon option needs a
## config change (and a daemon restart) on every client that pulls —
## including the arch-vm guest — and what it really buys is "don't verify
## the certificate". With a real certificate on a name the clients already
## resolve, `docker push/pull gitea.wingard.pro/...` needs no client
## configuration at all, and the TLS is genuinely verified.
##
## Gitea serves its registry on the same port as the web UI (3010), so one
## vhost covers both: /v2/ is the registry, everything else is the UI.
## The body and timeout settings below exist because image layers are
## GB-scale — nginx's defaults (1m body, 60s read) reject a real push.
## Do not add proxy_http_version here: proxyWebsockets already emits it,
## and a duplicate directive makes nginx refuse to start.
"gitea.wingard.pro" = {
enableACME = true;
acmeRoot = "/var/lib/acme/acme-challenge";
addSSL = true;
locations."/" = {
proxyPass = "http://127.0.0.1:3010";
proxyWebsockets = true;
extraConfig = ''
client_max_body_size 0;
proxy_request_buffering off;
proxy_read_timeout 900s;
proxy_send_timeout 900s;
'';
};
};
"jellyfin.wingard.pro" = {
## Cert issued + renewed automatically by security.acme
enableACME = true;