← back to AbramsOS
deploy: abramsos vhost with fleet Basic Auth (admin/DW2024!) + SSL + ACME exemption
b2fd5b15176d3776ed12e4b11e78256986daa184 · 2026-08-18 15:02:52 -0700 · Steve
Files touched
M deploy/abramsos.agentabrams.com.nginx.confM middleware/auth.js
Diff
commit b2fd5b15176d3776ed12e4b11e78256986daa184
Author: Steve <steve@designerwallcoverings.com>
Date: Tue Aug 18 15:02:52 2026 -0700
deploy: abramsos vhost with fleet Basic Auth (admin/DW2024!) + SSL + ACME exemption
---
deploy/abramsos.agentabrams.com.nginx.conf | 23 +++++++++++++++++------
middleware/auth.js | 10 +++++++---
2 files changed, 24 insertions(+), 9 deletions(-)
diff --git a/deploy/abramsos.agentabrams.com.nginx.conf b/deploy/abramsos.agentabrams.com.nginx.conf
index 37e13e0..dbe0875 100644
--- a/deploy/abramsos.agentabrams.com.nginx.conf
+++ b/deploy/abramsos.agentabrams.com.nginx.conf
@@ -1,13 +1,24 @@
# abramsos.agentabrams.com — Kamatera nginx reverse-proxy to AbramsOS on Steve's Mac (tailnet).
-# AbramsOS enforces its OWN requireAuth (session + TOTP + Google OAuth), so the personal
-# settlement-claims data (name/address/claims) stays behind login even though the domain is public.
-# certbot --nginx injects the acme-challenge handler + the 443 block.
+# Fleet HTTP Basic Auth (admin / DW2024!) guards the public door; the app then trusts the gate
+# and acts as the owner (SINGLE_USER_AUTOLOGIN). ACME challenge is exempt so certbot can renew.
server {
listen 45.61.58.125:80;
server_name abramsos.agentabrams.com;
- # ACME challenge served locally (NOT proxied) so certbot can issue — the app's
- # requireAuth would otherwise redirect the challenge to /signin and fail issuance.
- location ^~ /.well-known/acme-challenge/ { root /var/www/certbot; default_type "text/plain"; }
+ location ^~ /.well-known/acme-challenge/ { root /var/www/certbot; default_type "text/plain"; auth_basic off; }
+ location / { return 301 https://$host$request_uri; }
+}
+server {
+ listen 45.61.58.125:443 ssl;
+ server_name abramsos.agentabrams.com;
+ ssl_certificate /etc/letsencrypt/live/abramsos.agentabrams.com/fullchain.pem;
+ ssl_certificate_key /etc/letsencrypt/live/abramsos.agentabrams.com/privkey.pem;
+ include /etc/letsencrypt/options-ssl-nginx.conf;
+ ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
+
+ auth_basic "AbramsOS";
+ auth_basic_user_file /etc/nginx/.htpasswd-abramsos;
+
+ location ^~ /.well-known/acme-challenge/ { root /var/www/certbot; default_type "text/plain"; auth_basic off; }
location / {
proxy_pass http://100.82.17.107:9774; # Steve's Mac (tailnet), AbramsOS :9774
proxy_http_version 1.1;
diff --git a/middleware/auth.js b/middleware/auth.js
index 92b999e..5d638e2 100644
--- a/middleware/auth.js
+++ b/middleware/auth.js
@@ -3,17 +3,21 @@ const auth = require('../lib/auth');
// Hydrate req.session + req.userId from the cookie
async function loadSessionMiddleware(req, _res, next) {
const sid = req.cookies?.[auth.SESSION_COOKIE] || req.signedCookies?.[auth.SESSION_COOKIE];
- if (!sid) return next();
+ if (!sid) { if (process.env.SINGLE_USER_AUTOLOGIN) req.userId = process.env.SINGLE_USER_AUTOLOGIN; return next(); }
const session = await auth.loadSession(sid);
- if (!session) return next();
+ if (!session) { if (process.env.SINGLE_USER_AUTOLOGIN) req.userId = process.env.SINGLE_USER_AUTOLOGIN; return next(); }
req.session = session;
req.userId = session.user_id;
next();
}
-// Reject unauthenticated requests; redirect HTML to /signin, JSON gets 401
+// Reject unauthenticated requests; redirect HTML to /signin, JSON gets 401.
+// FLEET BASIC-AUTH MODE: when SINGLE_USER_AUTOLOGIN is set, the app is deployed behind
+// nginx HTTP Basic Auth (admin/DW2024!) — the door is already guarded, so trust the
+// request and act as the single owner instead of showing the app's own email/TOTP login.
function requireAuth(req, res, next) {
if (req.userId) return next();
+ if (process.env.SINGLE_USER_AUTOLOGIN) { req.userId = process.env.SINGLE_USER_AUTOLOGIN; return next(); }
if (req.accepts('html')) return res.redirect('/signin?next=' + encodeURIComponent(req.originalUrl));
return res.status(401).json({ error: 'unauthenticated' });
}
← 6106895 deploy: serve ACME challenge locally in abramsos vhost (prox
·
back to AbramsOS
·
amazon-orders: 30-min Gmail poller (George bridge) → purchas f450f59 →