From 8d2469ddb684ab31674d4b06f27b9ba7bf045094 Mon Sep 17 00:00:00 2001 From: Rokojori Date: Thu, 16 Jul 2026 18:14:03 +0200 Subject: [PATCH] Update TTL for Testing --- source/server/routes/auth.ts | 2 +- workspace/add-subdomain.html | 440 +++++++++++++++++++++++++++++++++++ 2 files changed, 441 insertions(+), 1 deletion(-) create mode 100644 workspace/add-subdomain.html diff --git a/source/server/routes/auth.ts b/source/server/routes/auth.ts index 5663621..d427d6c 100644 --- a/source/server/routes/auth.ts +++ b/source/server/routes/auth.ts @@ -9,7 +9,7 @@ import { isSuperAdmin } from '../roles'; const router = Router(); -const ACCESS_TOKEN_TTL = '1h'; +const ACCESS_TOKEN_TTL = '10s'; const COOKIE_DOMAIN = process.env.COOKIE_DOMAIN ?? '.rokojori.com'; const RESET_BASE_URL = process.env.RESET_BASE_URL ?? 'https://account.rokojori.com'; const ACCOUNT_BASE_URL = process.env.RESET_BASE_URL ?? 'https://account.rokojori.com'; diff --git a/workspace/add-subdomain.html b/workspace/add-subdomain.html new file mode 100644 index 0000000..2c25033 --- /dev/null +++ b/workspace/add-subdomain.html @@ -0,0 +1,440 @@ + + + + + + Add a Subdomain — rokojori + + + + + +
+ +
+

Guide

+

Add a Subdomain

+

+ Step-by-step checklist for deploying a new Node.js service as a + subdomain.rokojori.com on Server A. + Fill in the variables below — all commands update automatically. +

+
+ + +
+

Variables

+

Fill these in once and every command in the guide updates.

+
+ + + +
+
+ + +
+

0 — Ensure compatibility

+ +
+

When do you need CORS?

+

+ If any other rokojori site loads resources from this service (fonts, CSS, JSON, + images) via a browser request — @import, fetch, + <img src> etc. — the browser enforces the + same-origin policy and blocks the + response unless the server sends an Access-Control-Allow-Origin + header. Services that only serve their own pages and API calls to their own + frontend do not need CORS. +

+
+ +
+

Do not use *

+

+ Access-Control-Allow-Origin: * allows any website on the internet + to load your resources. For public CDN assets that is acceptable, but for + rokojori services restrict it to known origins. +

+

+ Because the header cannot carry a wildcard pattern like + *.rokojori.com, the server must check the incoming + Origin header against an allowlist and echo back the matched + origin. Unrecognised origins receive no header and the browser blocks them. +

+
+ +
+

Pattern — allowlist middleware

+

Add this to source/server/index.ts before the routes that need it:

+
const CORS_ALLOWED: Array<string | RegExp> = [
+  /^https?:\/\/([\w-]+\.)?rokojori\.com$/,  // all *.rokojori.com subdomains
+  // 'https://someother.site',               // add extra origins here
+];
+
+function allowCors(
+  req: express.Request,
+  res: express.Response,
+  next: express.NextFunction
+): void
+{
+  const origin = req.headers.origin;
+  if ( origin && CORS_ALLOWED.some( rule =>
+    typeof rule === 'string' ? rule === origin : rule.test( origin )
+  ) )
+  {
+    res.set( 'Access-Control-Allow-Origin', origin );
+  }
+  next();
+}
+
+// Apply before the routes that serve cross-origin resources:
+app.use( '/your-public-route', allowCors );
+
+ +
+

What the regex matches

+

+ /^https?:\/\/([\w-]+\.)?rokojori\.com$/ accepts: + https://rokojori.com, + https://roject.rokojori.com, + https://styles.rokojori.com, and so on. + HTTP is included so local dev with a mapped host still works. + Extend CORS_ALLOWED with additional strings or regexes for + any external sites that need access. +

+
+
+ + +
+

1 — Create the repository

+ +
+

New repo on Gitea

+

+ Log in to community.rokojori.com, + click New Repository, name it (e.g. subdomain), + set it to private, and copy the clone URL. + Do not initialise with a README — the local project is already set up. +

+
+
+ + +
+

2 — .gitignore, commit, push

+ +
+

.gitignore

+

Create this at the project root before the first commit:

+
node_modules/
+dist/
+build/
+.env
+storage/
+
+ +
+

Initial commit and push

+
git init
+git add .
+git commit -m "init"
+git remote add origin https://community.rokojori.com/Rokojori/subdomain.git
+git push -u origin main
+
+
+ + +
+

3 — DNS record on IONOS

+ +
+

Add A record

+

+ Log in to IONOS → Domains & SSL → rokojori.com + → DNS. Add a new record: +

+
Type:  A
+Name:  subdomain
+Value: <Server A IP>
+TTL:   300
+

+ Wait a few minutes for propagation before running certbot. + Verify with ping subdomain.rokojori.com from any machine. +

+
+
+ + +
+

4 — Clone on the server

+ +
+

SSH and clone

+
ssh root@<Server A IP>
+
+cd /opt
+git clone https://community.rokojori.com/Rokojori/subdomain.git subdomain
+cd subdomain
+
+
+ + +
+

5 — Install, build, configure

+ +
+

Install dependencies

+
npm install
+
+ +
+

Copy pages (if the project has source/pages/)

+
node scripts/copy-pages.js
+
+ +
+

Create .env

+

+ Copy the contents from your local .env and paste them on the server. + Update any values that differ in production (port, secrets, URLs). +

+
nano .env
+
+ +
+

Create storage directories (if needed)

+
# example for styles.rokojori.com
+mkdir -p storage/fonts
+
+ +
+

Quick smoke test

+

+ Run the server once manually to confirm it starts. Kill it with + Ctrl+C before moving to the systemd step — leave it + running and the port will conflict. +

+
npm run dev
+# → service running on http://localhost:PORT
+# Ctrl+C to stop
+
+
+ + +
+

6 — nginx config (HTTP only)

+ +
+

Create the site config

+
nano /etc/nginx/sites-available/subdomain.rokojori.com
+
server {
+    listen 80;
+    server_name subdomain.rokojori.com;
+
+    location / {
+        proxy_pass         http://localhost:PORT;
+        proxy_http_version 1.1;
+        proxy_set_header   Upgrade           $http_upgrade;
+        proxy_set_header   Connection        'upgrade';
+        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;
+        proxy_cache_bypass $http_upgrade;
+    }
+}
+
+ +
+

Enable and reload

+
ln -s /etc/nginx/sites-available/subdomain.rokojori.com \
+         /etc/nginx/sites-enabled/subdomain.rokojori.com
+
+nginx -t
+systemctl reload nginx
+
+
+ + +
+

7 — Let's Encrypt certificate

+ +
+

Run certbot

+

+ The --nginx plugin handles the ACME HTTP-01 challenge + through nginx directly — the app does not need to be running. + When prompted whether to redirect HTTP to HTTPS, choose + Redirect (option 2). +

+
certbot --nginx -d subdomain.rokojori.com
+

+ Certbot modifies the nginx config in-place, adding TLS directives and + an HTTP→HTTPS redirect block. It also installs a systemd timer for + automatic renewal — no extra setup needed. +

+
+
+ + +
+

8 — Verify nginx HTTPS config

+ +
+

Check and reload

+

+ Certbot updates the config automatically, but always verify before reloading: +

+
nginx -t
+systemctl reload nginx
+
+ +
+

Confirm TLS is live

+
curl -I https://subdomain.rokojori.com
+

+ Expect HTTP/2 200 (or 502 if the app is not yet running — that is fine at this stage). +

+
+
+ + +
+

9 — systemd service

+ +
+

Create the unit file

+
nano /etc/systemd/system/service-name.service
+
[Unit]
+Description=service-name
+After=network.target
+
+[Service]
+Type=simple
+WorkingDirectory=/opt/subdomain
+ExecStart=/usr/bin/npx ts-node --project tsconfig.ts-node.json source/server/index.ts
+Restart=on-failure
+RestartSec=5
+StandardOutput=journal
+StandardError=journal
+
+[Install]
+WantedBy=multi-user.target
+

+ The .env file is loaded by import 'dotenv/config' + inside the app, so no EnvironmentFile= is needed. +

+
+ +
+

Enable and start

+
systemctl daemon-reload
+systemctl enable service-name
+systemctl start service-name
+systemctl status service-name
+
+ +
+

Check logs

+
journalctl -u service-name -f
+
+
+ + +
+

Quick reference

+ +
+

Deploy an update

+
cd /opt/subdomain
+git pull
+npm install
+node scripts/copy-pages.js   # if applicable
+systemctl restart service-name
+
+ +
+

Common commands

+
systemctl restart service-name        # restart app
+systemctl status  service-name        # current state
+journalctl -u service-name -n 100    # last 100 log lines
+nginx -t                              # validate nginx config
+systemctl reload nginx                # apply nginx changes
+
+ +
+

Certificate renewal

+

+ Certbot installs a systemd timer (certbot.timer) that + renews certificates automatically before expiry. Check its status with: +

+
systemctl status certbot.timer
+
+
+ +
+ rokojori-auth — add-subdomain guide +
+ +
+ + + + + + + +