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
302 lines
10 KiB
JavaScript
Executable File
302 lines
10 KiB
JavaScript
Executable File
#!/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}`,
|
||
);
|