Harden onion boot flow and deepen site surfaces
Add persistent onion key backup and restore, improve startup resilience, and flesh out the major site verticals with richer navigation, search coverage, and operator documentation. Made-with: Cursor
This commit is contained in:
301
scripts/generate-onion-config.cjs
Executable file
301
scripts/generate-onion-config.cjs
Executable file
@@ -0,0 +1,301 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Reads scripts/onion-nodes.json and writes:
|
||||
* lib/onionRoutes.generated.ts
|
||||
* tor/cyberlux-nodes.conf
|
||||
* nginx/cyberlux-onion-servers.inc
|
||||
* scripts/generated/tor-dirs.txt
|
||||
* scripts/generated/onion-labels.tsv
|
||||
* scripts/generated/onion-port-range.txt
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const REPO = path.join(__dirname, "..");
|
||||
const jsonPath = path.join(__dirname, "onion-nodes.json");
|
||||
const data = JSON.parse(fs.readFileSync(jsonPath, "utf8"));
|
||||
const nodes = data.nodes;
|
||||
|
||||
function dedicatedNginx(port, entry) {
|
||||
const h = JSON.stringify(entry);
|
||||
return `
|
||||
# ${entry} @ ${port}
|
||||
server {
|
||||
listen 127.0.0.1:${port};
|
||||
server_name _;
|
||||
|
||||
include /etc/nginx/cyberlux-server-common.inc;
|
||||
proxy_hide_header X-Powered-By;
|
||||
|
||||
client_max_body_size 25m;
|
||||
|
||||
location /checkout {
|
||||
proxy_pass http://127.0.0.1:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-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 http;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
}
|
||||
location /api/ {
|
||||
proxy_pass http://127.0.0.1:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-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 http;
|
||||
}
|
||||
location /forum {
|
||||
proxy_pass http://127.0.0.1:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-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 http;
|
||||
}
|
||||
location /exchange {
|
||||
proxy_pass http://127.0.0.1:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-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 http;
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-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 http;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header X-Cyberlux-Node ${h};
|
||||
proxy_read_timeout 86400;
|
||||
}
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
function wikiNginx(port) {
|
||||
return `
|
||||
# wiki @ ${port}
|
||||
server {
|
||||
listen 127.0.0.1:${port};
|
||||
server_name _;
|
||||
|
||||
include /etc/nginx/cyberlux-server-common.inc;
|
||||
proxy_hide_header X-Powered-By;
|
||||
|
||||
client_max_body_size 25m;
|
||||
|
||||
location /checkout {
|
||||
proxy_pass http://127.0.0.1:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-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 http;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
}
|
||||
location /api/ {
|
||||
proxy_pass http://127.0.0.1:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-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 http;
|
||||
}
|
||||
location /forum {
|
||||
proxy_pass http://127.0.0.1:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-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 http;
|
||||
}
|
||||
location /exchange {
|
||||
proxy_pass http://127.0.0.1:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-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 http;
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-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 http;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header X-Cyberlux-Node "wiki";
|
||||
proxy_read_timeout 86400;
|
||||
}
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
function wNginx(port) {
|
||||
return `
|
||||
# shadow nodes (/w/[slug]) @ ${port}
|
||||
server {
|
||||
listen 127.0.0.1:${port};
|
||||
server_name _;
|
||||
|
||||
include /etc/nginx/cyberlux-server-common.inc;
|
||||
proxy_hide_header X-Powered-By;
|
||||
|
||||
client_max_body_size 25m;
|
||||
|
||||
location /checkout {
|
||||
proxy_pass http://127.0.0.1:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-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 http;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
}
|
||||
location /api/ {
|
||||
proxy_pass http://127.0.0.1:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-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 http;
|
||||
}
|
||||
location /forum {
|
||||
proxy_pass http://127.0.0.1:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-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 http;
|
||||
}
|
||||
location /exchange {
|
||||
proxy_pass http://127.0.0.1:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-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 http;
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-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 http;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header X-Cyberlux-Node "w";
|
||||
proxy_read_timeout 86400;
|
||||
}
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
function torBlock(dir, port) {
|
||||
return `
|
||||
HiddenServiceDir /var/lib/tor/${dir}
|
||||
HiddenServicePort 80 127.0.0.1:${port}
|
||||
HiddenServiceEnableIntroDoSDefense 1
|
||||
HiddenServiceEnableIntroDoSRatePerSec 25
|
||||
HiddenServiceEnableIntroDoSBurstPerSec 200`;
|
||||
}
|
||||
|
||||
const ports = nodes.map((n) => n.port);
|
||||
const minP = Math.min(...ports);
|
||||
const maxP = Math.max(...ports);
|
||||
|
||||
const dedicated = {};
|
||||
for (const n of nodes) {
|
||||
if (n.kind === "dedicated") dedicated[n.entry] = n.path;
|
||||
}
|
||||
|
||||
const uniqueEntries = ["hub", "wiki", "w", ...Object.keys(dedicated).sort()];
|
||||
|
||||
const drLines = Object.keys(dedicated)
|
||||
.sort()
|
||||
.map((k) => ` ${JSON.stringify(k)}: ${JSON.stringify(dedicated[k])},`)
|
||||
.join("\n");
|
||||
|
||||
const ts = `// AUTO-GENERATED by scripts/generate-onion-config.cjs — do not edit
|
||||
|
||||
export const CYBERLUX_ENTRY_VALUES = [
|
||||
${uniqueEntries.map((e) => ` ${JSON.stringify(e)},`).join("\n")}
|
||||
] as const;
|
||||
|
||||
export type CyberluxEntry = (typeof CYBERLUX_ENTRY_VALUES)[number];
|
||||
|
||||
export const DEDICATED_ROOT = {
|
||||
${drLines}
|
||||
} as const;
|
||||
`;
|
||||
|
||||
// fix typo "generon" -> "generate"
|
||||
let nginxInc = "# CyberLux — generated onion vhosts (included from nginx.example.conf)\n";
|
||||
let torConf =
|
||||
"# CyberLux — generated v3 onion services (include from torrc)\n#\n# Tor ≥ 0.4.7: DoS lines follow each HiddenServiceDir/Port pair.\n";
|
||||
|
||||
for (const n of nodes) {
|
||||
torConf += torBlock(n.torDir, n.port);
|
||||
if (n.kind === "hub") continue;
|
||||
if (n.kind === "dedicated") nginxInc += dedicatedNginx(n.port, n.entry);
|
||||
else if (n.kind === "wiki") nginxInc += wikiNginx(n.port);
|
||||
else if (n.kind === "w") nginxInc += wNginx(n.port);
|
||||
}
|
||||
|
||||
const genDir = path.join(REPO, "scripts", "generated");
|
||||
fs.mkdirSync(genDir, { recursive: true });
|
||||
|
||||
const torDirs = nodes.map((n) => n.torDir);
|
||||
fs.writeFileSync(path.join(genDir, "tor-dirs.txt"), torDirs.join("\n") + "\n");
|
||||
|
||||
const labels = [];
|
||||
for (const n of nodes) {
|
||||
let desc = "";
|
||||
if (n.kind === "hub") desc = "Hub — full storefront";
|
||||
else if (n.kind === "wiki") desc = "Wiki — / → /hidden-wiki";
|
||||
else if (n.kind === "w") desc = "Shadow nodes — / → /syndicate, /x → /w/x";
|
||||
else desc = `${n.entry} — / → ${n.path}`;
|
||||
labels.push(`${n.torDir}\t${desc}`);
|
||||
}
|
||||
fs.writeFileSync(path.join(genDir, "onion-labels.tsv"), labels.join("\n") + "\n");
|
||||
fs.writeFileSync(path.join(genDir, "onion-port-range.txt"), `${minP} ${maxP}\n`);
|
||||
|
||||
fs.writeFileSync(path.join(REPO, "lib", "onionRoutes.generated.ts"), ts);
|
||||
fs.writeFileSync(path.join(REPO, "tor", "cyberlux-nodes.conf"), torConf.trim() + "\n");
|
||||
fs.writeFileSync(path.join(REPO, "nginx", "cyberlux-onion-servers.inc"), nginxInc.trim() + "\n");
|
||||
|
||||
console.log(
|
||||
`[generate-onion-config] ${nodes.length} onions, nginx loopback ${minP}–${maxP}, TS entries: ${uniqueEntries.length}`,
|
||||
);
|
||||
Reference in New Issue
Block a user