Add ONION-URLS.md, export script, and tighten README
- ONION-URLS.md: static registry of all 43 hidden services (port, role, app path) - scripts/export-onion-urls.sh: writes live .onion addresses to onion-urls.txt at runtime - npm run onions:export shortcut added to package.json - onion-urls.txt added to .gitignore (runtime artifact, not source) - README: cohesive rewrite — architecture diagram, operator command table, source-of-truth map, BTCPay notes, full site map, common fixes - BTCPay status route: awaited params destructuring (Next 15 async params) Made-with: Cursor
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -39,3 +39,6 @@ yarn-error.log*
|
|||||||
# typescript
|
# typescript
|
||||||
*.tsbuildinfo
|
*.tsbuildinfo
|
||||||
next-env.d.ts
|
next-env.d.ts
|
||||||
|
|
||||||
|
# runtime-generated onion URL file (populated by scripts/export-onion-urls.sh)
|
||||||
|
onion-urls.txt
|
||||||
|
|||||||
107
ONION-URLS.md
Normal file
107
ONION-URLS.md
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
# CyberLux — Onion URL Reference
|
||||||
|
|
||||||
|
All 43 Tor v3 hidden services. Live `.onion` addresses are generated at runtime by Tor and stored in `/var/lib/tor/<service>/hostname`. This file is a **static registry**; use the commands below to resolve live addresses.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Get Live URLs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Print all live .onion URLs (reads /var/lib/tor/*/hostname)
|
||||||
|
bash scripts/list-onion-urls.sh
|
||||||
|
# or with sudo if not readable as your user:
|
||||||
|
sudo bash scripts/list-onion-urls.sh
|
||||||
|
|
||||||
|
# Save live URLs to onion-urls.txt in the repo root
|
||||||
|
sudo bash scripts/export-onion-urls.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Service Registry
|
||||||
|
|
||||||
|
| # | `torDir` | Port | Role | App Path |
|
||||||
|
|---|----------|------|------|----------|
|
||||||
|
| 1 | `cyberlux` | 8080 | Hub — main storefront | `/` |
|
||||||
|
| 2 | `cyberlux_forum` | 8081 | Void Aggregate — forum | `/forum` |
|
||||||
|
| 3 | `cyberlux_exchange` | 8082 | Classifieds exchange | `/exchange` |
|
||||||
|
| 4 | `cyberlux_wiki` | 8083 | Hidden-wiki layer | `/hidden-wiki` |
|
||||||
|
| 5 | `cyberlux_market` | 8084 | Full catalog / market | `/market` |
|
||||||
|
| 6 | `cyberlux_barter` | 8085 | Ash Pit barter | `/barter` |
|
||||||
|
| 7 | `cyberlux_chatter` | 8086 | Chatter / live feed | `/chatter` |
|
||||||
|
| 8 | `cyberlux_search` | 8087 | Void Crawler search | `/search` |
|
||||||
|
| 9 | `cyberlux_syndicate` | 8088 | Shell network syndicate | `/syndicate` |
|
||||||
|
| 10 | `cyberlux_arb_academy` | 8089 | Arb Academy | `/arb-academy` |
|
||||||
|
| 11 | `cyberlux_reviews` | 8090 | Reviews | `/reviews` |
|
||||||
|
| 12 | `cyberlux_trust` | 8091 | Trust / reputation layer | `/trust` |
|
||||||
|
| 13 | `cyberlux_vault` | 8092 | Vault / secure storage | `/vault` |
|
||||||
|
| 14 | `cyberlux_messages` | 8093 | Private messages | `/messages` |
|
||||||
|
| 15 | `cyberlux_drop_box` | 8094 | Drop Box | `/drop-box` |
|
||||||
|
| 16 | `cyberlux_easter_eggs` | 8095 | Easter Eggs | `/easter-eggs` |
|
||||||
|
| 17 | `cyberlux_links` | 8096 | Curated links | `/links` |
|
||||||
|
| 18 | `cyberlux_red_room` | 8097 | Red Room | `/red-room` |
|
||||||
|
| 19 | `cyberlux_drops` | 8098 | Drops | `/drops` |
|
||||||
|
| 20 | `cyberlux_inner_circle` | 8099 | Inner Circle | `/inner-circle` |
|
||||||
|
| 21 | `cyberlux_comparison` | 8100 | Comparison tool | `/comparison` |
|
||||||
|
| 22 | `cyberlux_testimonials` | 8101 | Testimonials | `/testimonials` |
|
||||||
|
| 23 | `cyberlux_wallets` | 8102 | Wallets | `/wallets` |
|
||||||
|
| 24 | `cyberlux_support` | 8103 | Support desk | `/support` |
|
||||||
|
| 25 | `cyberlux_darknet_atlas` | 8104 | Darknet Atlas taxonomy | `/darknet-atlas` |
|
||||||
|
| 26 | `cyberlux_security_analysis` | 8105 | Security analysis | `/security-analysis` |
|
||||||
|
| 27 | `cyberlux_mixer` | 8106 | Mixer | `/mixer` |
|
||||||
|
| 28 | `cyberlux_secret_layer` | 8107 | Secret Layer | `/secret-layer` |
|
||||||
|
| 29 | `cyberlux_trees` | 8108 | Trees | `/trees` |
|
||||||
|
| 30 | `cyberlux_presswire` | 8109 | Presswire / news | `/presswire` |
|
||||||
|
| 31 | `cyberlux_awards` | 8110 | Awards | `/awards` |
|
||||||
|
| 32 | `cyberlux_raffle` | 8111 | Raffle | `/raffle` |
|
||||||
|
| 33 | `cyberlux_game` | 8112 | Game | `/game` |
|
||||||
|
| 34 | `cyberlux_webring` | 8113 | Webring | `/webring` |
|
||||||
|
| 35 | `cyberlux_conspiracies` | 8114 | Conspiracies | `/conspiracies` |
|
||||||
|
| 36 | `cyberlux_sanctuary` | 8115 | Sanctuary | `/sanctuary` |
|
||||||
|
| 37 | `cyberlux_dashboard` | 8116 | Personal relay dashboard | `/dashboard` |
|
||||||
|
| 38 | `cyberlux_checkout` | 8117 | Checkout flow | `/checkout` |
|
||||||
|
| 39 | `cyberlux_vendors` | 8118 | Vendors | `/vendors` |
|
||||||
|
| 40 | `cyberlux_sign_in` | 8119 | Sign in | `/sign-in` |
|
||||||
|
| 41 | `cyberlux_sign_up` | 8120 | Sign up | `/sign-up` |
|
||||||
|
| 42 | `cyberlux_account` | 8121 | Account / mirror map | `/account` |
|
||||||
|
| 43 | `cyberlux_w` | 8122 | Shadow nodes / syndicate shell | `/w` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Live Address File
|
||||||
|
|
||||||
|
After Tor is running, save all live addresses to a plain-text file:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo bash scripts/export-onion-urls.sh
|
||||||
|
# writes: onion-urls.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
`onion-urls.txt` (if present in this directory) contains the resolved `http://…56chars….onion` addresses for all services and is gitignored — it reflects runtime state, not source.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## How Addresses Stay Stable
|
||||||
|
|
||||||
|
Each service maps to a fixed `HiddenServiceDir` in `/var/lib/tor/`. As long as:
|
||||||
|
|
||||||
|
- the `torDir` name in `scripts/onion-nodes.json` does not change, and
|
||||||
|
- `/var/lib/tor/<service>/` is preserved (or restored from backup),
|
||||||
|
|
||||||
|
the `.onion` address **never rotates**, surviving reboots, rebuilds, and Tor restarts.
|
||||||
|
|
||||||
|
Backup/restore:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo bash scripts/backup-onion-keys.sh # saves to /var/backups/cyberlux-onion-keys/current
|
||||||
|
sudo bash scripts/restore-onion-keys.sh # restores missing dirs from backup
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- All services run from **one** Next.js instance at `127.0.0.1:3000`.
|
||||||
|
- nginx vhosts on `127.0.0.1:8080–8122` proxy to Next with `X-Cyberlux-Node` headers for host-aware routing.
|
||||||
|
- Open addresses in **Tor Browser** or **Onion Browser** (iOS). Standard browsers cannot resolve `.onion`.
|
||||||
|
- Use `http://` — TLS inside the onion circuit is handled end-to-end by Tor.
|
||||||
361
README.md
361
README.md
@@ -2,199 +2,155 @@
|
|||||||
|
|
||||||
> **The clearnet is a showroom. The onion is the door. One engine behind every door.**
|
> **The clearnet is a showroom. The onion is the door. One engine behind every door.**
|
||||||
|
|
||||||
We did not build forty-three repos. We built **one** Next.js stack and **refused** to fracture it—then we **projected** it through Tor until every vertical had its own v3 address, its own myth, its own entry point. Nginx sits in the middle like a bouncer; Tor does the rest. Same codebase. Same deploy. **Different `.onion` front doors** with host-aware rewrites (`proxy.ts` + `X-Cyberlux-Node`).
|
One Next.js stack projected through 43 independent Tor v3 hidden services. Nginx sits in the middle; Tor does the publishing. Same codebase, same deploy — **different `.onion` front doors** with host-aware rewrites (`proxy.ts` + `X-Cyberlux-Node`). No fork army. No split deployments.
|
||||||
|
|
||||||
This is not a route demo. It is **infrastructure with intent**: stable `HiddenServiceDir` names, backup and restore for onion keys, Tor + nginx generated from **one JSON source of truth**. It is built to **boot, survive operator mistakes, and stay legible when everything else is on fire**.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## The thesis
|
## Architecture
|
||||||
|
|
||||||
- **One truth, many masks** — one build, dozens of onions; no fork army.
|
```
|
||||||
- **Identity persists** — keys and dirs are first-class; restarts don’t erase your address book.
|
Tor Browser
|
||||||
- **Loopback only** — Next and nginx don’t audition on the public internet; Tor publishes what you mean to publish.
|
│ http://<56-char>.onion
|
||||||
- **Verify or rot** — `npm run verify` is the line between shipping and LARP.
|
▼
|
||||||
|
[ Tor Network ]
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
nginx 127.0.0.1:8080–8122 (one vhost per .onion, host header → X-Cyberlux-Node)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
Next.js 127.0.0.1:3000 (single instance, proxy.ts routes by header)
|
||||||
|
```
|
||||||
|
|
||||||
|
**43 onion services → one app → zero public ports.**
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Operator controls
|
## Quick Start
|
||||||
|
|
||||||
| Command | What |
|
|
||||||
|--------|------|
|
|
||||||
| `./start.sh` | Full pipeline: generate → build → Tor/nginx → print **every `.onion` URL** → `next start` on `127.0.0.1:3000` |
|
|
||||||
| `npm run onions:list` | Print all `http://….onion` URLs from `/var/lib/tor/*/hostname` (use `sudo` if needed) |
|
|
||||||
| `npm run health:stack` | **Terminal A:** keep `npm run start:onion` running · **Terminal B:** curl Tor/nginx/Next loopbacks |
|
|
||||||
| `npm run onions:status` | URLs + HTTP probe each nginx vhost |
|
|
||||||
| `sudo bash scripts/install-systemd.sh` | Install `cyberlux.service` for boot-time Next |
|
|
||||||
| **`DEPLOY.md`** | Firewall posture, compliance reminder, full systemd notes |
|
|
||||||
|
|
||||||
**Tor on a phone:** **Onion Browser** (iOS) or **Tor Browser for Android** — Safari and Chrome will **never** resolve `.onion`. Paste the full `http://` + 56-char host + `.onion`. Some carriers fight Tor; Wi‑Fi often wins.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## What ships in the box
|
|
||||||
|
|
||||||
- `43` Tor v3 services
|
|
||||||
- stable loopback range `127.0.0.1:8080–8122`
|
|
||||||
- Next bound only to `127.0.0.1:3000`
|
|
||||||
- one `.onion` per major surface
|
|
||||||
- persistent hidden-service identity keyed by `HiddenServiceDir`
|
|
||||||
- self-healing backup / restore of onion key directories
|
|
||||||
|
|
||||||
## What it does (the map)
|
|
||||||
|
|
||||||
CyberLux boots **one** Next.js app and **projects** it through multiple onion entry points.
|
|
||||||
|
|
||||||
- `hub` — main storefront
|
|
||||||
- `forum` — Void Aggregate
|
|
||||||
- `exchange` — classifieds stack
|
|
||||||
- `market` — full catalog vertical
|
|
||||||
- `search` — Void Crawler
|
|
||||||
- `wiki` — hidden-wiki layer
|
|
||||||
- `w` — syndicate shell network
|
|
||||||
- dozens more dedicated onions map to top-level app routes
|
|
||||||
|
|
||||||
The routing layer uses host-aware rewrites so a dedicated onion **feels** like its own property without splitting the app into forty-three deployments.
|
|
||||||
|
|
||||||
## One-command launch
|
|
||||||
|
|
||||||
Install system deps on Debian/Ubuntu:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo apt install tor nginx
|
sudo apt install tor nginx
|
||||||
```
|
|
||||||
|
|
||||||
Then:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
chmod +x start.sh
|
chmod +x start.sh
|
||||||
./start.sh
|
./start.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
What `./start.sh` does:
|
Open the hub in **Tor Browser** (addresses print at the end of start.sh).
|
||||||
|
Local-only (skip Tor/nginx): `CYBERLUX_SKIP_TOR=1 ./start.sh`
|
||||||
|
|
||||||
1. regenerates Tor / nginx / app route maps from `scripts/onion-nodes.json`
|
---
|
||||||
2. runs `git pull --ff-only` if the repo has `.git` (failure is non-fatal)
|
|
||||||
3. runs `npm install`
|
|
||||||
4. repairs `.next` ownership if a root-owned build left it unwritable
|
|
||||||
5. runs a production build
|
|
||||||
6. restores backed-up onion keys if any hidden-service directories are missing
|
|
||||||
7. installs Tor + nginx config only when it actually changed
|
|
||||||
8. waits for all onion hostname files, not just the hub
|
|
||||||
9. refreshes the onion key backup set
|
|
||||||
10. prints every live `.onion` URL
|
|
||||||
11. starts Next on `127.0.0.1:3000`
|
|
||||||
|
|
||||||
Open in Tor Browser:
|
## Operator Commands
|
||||||
|
|
||||||
```text
|
| Command | What it does |
|
||||||
http://<56-char-v3-address>.onion
|
|---------|-------------|
|
||||||
|
| `./start.sh` | Full pipeline: generate → build → Tor/nginx → print URLs → start Next |
|
||||||
|
| `npm run onions:list` | Print all live `.onion` URLs from `/var/lib/tor/*/hostname` |
|
||||||
|
| `sudo npm run onions:export` | Write live URLs to `onion-urls.txt` in repo root |
|
||||||
|
| `npm run onions:status` | URLs + HTTP probe each nginx vhost |
|
||||||
|
| `npm run health:stack` | Curl Tor/nginx/Next loopbacks and report status |
|
||||||
|
| `npm run verify` | Full pre-ship check: config gen, TS, shell syntax, build |
|
||||||
|
| `sudo bash scripts/install-tor-onion.sh` | Install/refresh Tor + nginx config |
|
||||||
|
| `sudo bash scripts/backup-onion-keys.sh` | Back up all hidden-service key dirs |
|
||||||
|
| `sudo bash scripts/restore-onion-keys.sh` | Restore missing key dirs from backup |
|
||||||
|
| `sudo bash scripts/install-systemd.sh` | Install `cyberlux.service` for boot-time start |
|
||||||
|
| `sudo bash scripts/classroom-ufw.sh` | Lock firewall to loopback-only (recommended) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Onion URL Reference
|
||||||
|
|
||||||
|
See [`ONION-URLS.md`](ONION-URLS.md) — full table of all 43 services with ports and app paths.
|
||||||
|
|
||||||
|
To export live `.onion` addresses after Tor is running:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo bash scripts/export-onion-urls.sh
|
||||||
|
# writes onion-urls.txt (gitignored — reflects runtime state)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Persistent onion addresses
|
---
|
||||||
|
|
||||||
Yes — the onion addresses are **meant** to persist.
|
## What Ships in the Box
|
||||||
|
|
||||||
Each service uses a fixed Tor directory:
|
- **43** Tor v3 hidden services
|
||||||
|
- Loopback range `127.0.0.1:8080–8122` (nginx vhosts, never public)
|
||||||
|
- Next.js bound only to `127.0.0.1:3000`
|
||||||
|
- One `.onion` per major surface — hub, forum, market, exchange, wiki, and 38 more
|
||||||
|
- Persistent hidden-service identity keyed by `HiddenServiceDir` name
|
||||||
|
- Self-healing backup / restore for onion keys
|
||||||
|
- BTCPay Server integration (configurable) for on-chain + Lightning deposits
|
||||||
|
- Systemd unit generator for unattended boot
|
||||||
|
|
||||||
```tor
|
---
|
||||||
HiddenServiceDir /var/lib/tor/<service-dir>
|
|
||||||
HiddenServicePort 80 127.0.0.1:<loopback-port>
|
## What `./start.sh` Does (in order)
|
||||||
|
|
||||||
|
1. Regenerates Tor / nginx / app route maps from `scripts/onion-nodes.json`
|
||||||
|
2. Runs `git pull --ff-only` if repo has `.git` (non-fatal on failure)
|
||||||
|
3. Runs `npm install`
|
||||||
|
4. Repairs `.next` ownership if a root-owned build left it unwritable
|
||||||
|
5. Runs a production build
|
||||||
|
6. Restores backed-up onion keys if any hidden-service directories are missing
|
||||||
|
7. Installs Tor + nginx config (only when it changed)
|
||||||
|
8. Waits for **all** onion hostname files, not just the hub
|
||||||
|
9. Refreshes the onion key backup set
|
||||||
|
10. Prints every live `.onion` URL
|
||||||
|
11. Starts Next on `127.0.0.1:3000`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Source of Truth
|
||||||
|
|
||||||
|
Everything — Tor config, nginx vhosts, app route maps — is generated from one file:
|
||||||
|
|
||||||
|
```
|
||||||
|
scripts/onion-nodes.json
|
||||||
```
|
```
|
||||||
|
|
||||||
The `.onion` stays stable as long as:
|
Generated artifacts (do not edit manually):
|
||||||
|
|
||||||
|
| File | Description |
|
||||||
|
|------|-------------|
|
||||||
|
| `tor/cyberlux-nodes.conf` | Tor `HiddenServiceDir` / `HiddenServicePort` blocks |
|
||||||
|
| `nginx/cyberlux-onion-servers.inc` | nginx server blocks (one per onion) |
|
||||||
|
| `lib/onionRoutes.generated.ts` | TypeScript route map used by `proxy.ts` |
|
||||||
|
| `scripts/generated/tor-dirs.txt` | Newline-separated list of service dir names |
|
||||||
|
| `scripts/generated/onion-labels.tsv` | Human-readable labels per service |
|
||||||
|
| `scripts/generated/onion-port-range.txt` | Port min / max for scripts |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Persistent Onion Addresses
|
||||||
|
|
||||||
|
Addresses are stable as long as:
|
||||||
|
|
||||||
- `torDir` names in `scripts/onion-nodes.json` do not change
|
- `torDir` names in `scripts/onion-nodes.json` do not change
|
||||||
- `/var/lib/tor/<service-dir>` is preserved
|
- `/var/lib/tor/<service-dir>/` is preserved
|
||||||
- or the backup set can restore those directories
|
- or the backup set can restore those directories
|
||||||
|
|
||||||
Normal app restarts, rebuilds, and standard Tor restarts do **not** rotate addresses by design.
|
Normal app restarts, rebuilds, and standard Tor restarts **do not rotate addresses**.
|
||||||
|
|
||||||
## Self-healing onion identity
|
Backup location: `/var/backups/cyberlux-onion-keys/current`
|
||||||
|
|
||||||
- `scripts/backup-onion-keys.sh`
|
---
|
||||||
- `scripts/restore-onion-keys.sh`
|
|
||||||
|
|
||||||
Backup location:
|
## BTCPay Server
|
||||||
|
|
||||||
```text
|
The checkout flow supports BTCPay Server for on-chain + Lightning payments. Configure with environment variables (see `.env.example` or `DEPLOY.md`). The stack runs without BTCPay — the API returns `503` if not configured.
|
||||||
/var/backups/cyberlux-onion-keys/current
|
|
||||||
```
|
|
||||||
|
|
||||||
After boot, ready onion service directories are backed up. If a service dir is missing from `/var/lib/tor` next boot, it is restored from backup. That is the gap between **screenshotware** and **survives a tired operator**.
|
---
|
||||||
|
|
||||||
## Tor / nginx topology
|
## Boot at Startup (systemd)
|
||||||
|
|
||||||
Source of truth: `scripts/onion-nodes.json`
|
|
||||||
|
|
||||||
Generated artifacts:
|
|
||||||
|
|
||||||
- `tor/cyberlux-nodes.conf`
|
|
||||||
- `nginx/cyberlux-onion-servers.inc`
|
|
||||||
- `lib/onionRoutes.generated.ts`
|
|
||||||
- `scripts/generated/tor-dirs.txt`
|
|
||||||
- `scripts/generated/onion-labels.tsv`
|
|
||||||
- `scripts/generated/onion-port-range.txt`
|
|
||||||
|
|
||||||
Install path:
|
|
||||||
|
|
||||||
- `/etc/tor/cyberlux-nodes.conf`
|
|
||||||
- `/etc/nginx/cyberlux-server-common.inc`
|
|
||||||
- `/etc/nginx/cyberlux-onion-servers.inc`
|
|
||||||
- `/etc/nginx/sites-available/cyberlux-onion`
|
|
||||||
|
|
||||||
Runtime:
|
|
||||||
|
|
||||||
- Next.js: `127.0.0.1:3000`
|
|
||||||
- nginx onion vhosts: `127.0.0.1:8080–8122`
|
|
||||||
- Tor exposes the public `.onion` endpoints
|
|
||||||
|
|
||||||
## Manual ops
|
|
||||||
|
|
||||||
Install or refresh Tor/nginx config:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo bash scripts/install-tor-onion.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
Back up onion keys:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo bash scripts/backup-onion-keys.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
Restore missing onion keys:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo bash scripts/restore-onion-keys.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
Local-only, skip Tor/nginx:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
CYBERLUX_SKIP_TOR=1 ./start.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
Start app without the helper:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run build
|
|
||||||
npm run start:onion
|
|
||||||
```
|
|
||||||
|
|
||||||
## Boot at startup (systemd)
|
|
||||||
|
|
||||||
Generate the unit with your Unix user and repo path:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo CYBERLUX_USER=$USER bash scripts/install-systemd.sh
|
sudo CYBERLUX_USER=$USER bash scripts/install-systemd.sh
|
||||||
sudo systemctl enable --now tor.service nginx.service cyberlux.service
|
sudo systemctl enable --now tor.service nginx.service cyberlux.service
|
||||||
# use `tor@default.service` instead of `tor.service` if your distro names it that way
|
|
||||||
```
|
```
|
||||||
|
|
||||||
The installer writes `/etc/systemd/system/cyberlux.service` and `/etc/default/cyberlux`. Legacy template notes live in `scripts/cyberlux.service` (prefer the generator).
|
Use `tor@default.service` instead of `tor.service` if your distro names it that way.
|
||||||
|
|
||||||
Tor + nginx must already be configured (`./start.sh` or `sudo bash scripts/install-tor-onion.sh` at least once).
|
Tor + nginx must already be configured (`./start.sh` or `sudo bash scripts/install-tor-onion.sh` first).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Verification
|
## Verification
|
||||||
|
|
||||||
@@ -202,67 +158,76 @@ Tor + nginx must already be configured (`./start.sh` or `sudo bash scripts/insta
|
|||||||
npm run verify
|
npm run verify
|
||||||
```
|
```
|
||||||
|
|
||||||
Checks: onion config generation, TypeScript, shell syntax for boot/install/backup/restore scripts, full Next production build.
|
Checks: config generation, TypeScript compilation, shell syntax for all boot/install/backup/restore scripts, full Next.js production build.
|
||||||
|
|
||||||
## Common failure: `.next` permission hell
|
---
|
||||||
|
|
||||||
If you built with `sudo`, `.next` may be root-owned and Next fails with `EACCES`.
|
## Common Fixes
|
||||||
|
|
||||||
|
**`.next` permission error (built with sudo):**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo bash scripts/fix-next-perms.sh
|
sudo bash scripts/fix-next-perms.sh
|
||||||
./start.sh
|
./start.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
## Security (read twice)
|
**Onion hostnames not showing up:**
|
||||||
|
|
||||||
CyberLux is hardened for a **demo stack**, not sold as magic invisibility.
|
```bash
|
||||||
|
sudo systemctl status tor
|
||||||
|
sudo ls -la /var/lib/tor/
|
||||||
|
# Wait ~30s after Tor starts for v3 descriptor publication
|
||||||
|
```
|
||||||
|
|
||||||
- Next and nginx bind to loopback only
|
**Port 3000 already in use:**
|
||||||
- Tor exposes the onion endpoints
|
|
||||||
- do **not** publish `3000` or `8080–8122` to the public internet
|
|
||||||
- optional host firewall: `sudo bash scripts/classroom-ufw.sh`
|
|
||||||
- bad application logic stays bad behind Tor
|
|
||||||
- operational mistakes beat branding every time
|
|
||||||
|
|
||||||
Tor obscures **reachability** better than raw-IP hosting. It does not forgive bad code, bad habits, or bad judgment.
|
```bash
|
||||||
|
ss -ltnp | grep 3000
|
||||||
## Site map
|
# Stop the conflicting process, then ./start.sh
|
||||||
|
```
|
||||||
Core verticals:
|
|
||||||
|
|
||||||
- `/` hub storefront
|
|
||||||
- `/market` full catalog
|
|
||||||
- `/forum` Void Aggregate
|
|
||||||
- `/exchange` classifieds
|
|
||||||
- `/barter` Ash Pit
|
|
||||||
- `/search` Void Crawler
|
|
||||||
- `/hidden-wiki` wiki layer
|
|
||||||
- `/darknet-atlas` taxonomy / atlas
|
|
||||||
- `/syndicate` shell network
|
|
||||||
- `/dashboard` personal relay
|
|
||||||
- `/account/hidden-services` mirror map
|
|
||||||
|
|
||||||
Additional dedicated onions exist for many top-level routes beyond these.
|
|
||||||
|
|
||||||
## Stack
|
|
||||||
|
|
||||||
- Next.js `16`
|
|
||||||
- React `19`
|
|
||||||
- Tailwind CSS `4`
|
|
||||||
- nginx
|
|
||||||
- Tor hidden services
|
|
||||||
- generated route / host mapping
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Final word
|
## Security
|
||||||
|
|
||||||
If you are running this, you are **past cosplay**. The stack exists to:
|
- Next.js and nginx bind to **loopback only** — they are never public
|
||||||
|
- Tor publishes the `.onion` endpoints
|
||||||
|
- Do **not** expose ports 3000 or 8080–8122 to the internet
|
||||||
|
- Harden with: `sudo bash scripts/classroom-ufw.sh`
|
||||||
|
- Tor obscures reachability — it does not forgive bad code or bad ops
|
||||||
|
|
||||||
- keep **onion identities** across rebuilds when you respect `torDir` names and backups
|
Read `DEPLOY.md` before pointing real users at this stack.
|
||||||
- expose **only** what Tor publishes — not your loopback to the raw internet
|
|
||||||
- fail **loud** in verification instead of silently rotting
|
|
||||||
|
|
||||||
Read **`DEPLOY.md`** before you point real people at it. **You** own jurisdiction, opsec, and what you ship. The network does not owe you anonymity; **you** owe the network discipline.
|
---
|
||||||
|
|
||||||
**This README is the product’s declaration of intent. The code is the rest.**
|
## Site Map
|
||||||
|
|
||||||
|
| Vertical | Path | Onion |
|
||||||
|
|---------|------|-------|
|
||||||
|
| Hub storefront | `/` | `cyberlux` |
|
||||||
|
| Forum (Void Aggregate) | `/forum` | `cyberlux_forum` |
|
||||||
|
| Exchange (classifieds) | `/exchange` | `cyberlux_exchange` |
|
||||||
|
| Market (full catalog) | `/market` | `cyberlux_market` |
|
||||||
|
| Barter (Ash Pit) | `/barter` | `cyberlux_barter` |
|
||||||
|
| Search (Void Crawler) | `/search` | `cyberlux_search` |
|
||||||
|
| Hidden Wiki | `/hidden-wiki` | `cyberlux_wiki` |
|
||||||
|
| Syndicate (shell net) | `/syndicate` | `cyberlux_syndicate` |
|
||||||
|
| Dashboard | `/dashboard` | `cyberlux_dashboard` |
|
||||||
|
| Account / mirror map | `/account` | `cyberlux_account` |
|
||||||
|
| + 33 more | see `ONION-URLS.md` | |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Stack
|
||||||
|
|
||||||
|
- **Next.js 16** · React 19 · Tailwind CSS 4
|
||||||
|
- **nginx** reverse proxy (loopback vhosts)
|
||||||
|
- **Tor** v3 hidden services
|
||||||
|
- **BTCPay Server** (optional, on-chain + Lightning)
|
||||||
|
- Generated route / host mapping from single JSON source
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
> If you are running this, you are past cosplay.
|
||||||
|
> The network does not owe you anonymity — **you** owe the network discipline.
|
||||||
|
> Read `DEPLOY.md`. Own your jurisdiction.
|
||||||
|
|||||||
@@ -3,13 +3,13 @@ import { getBtcPayInvoiceStatus, isBtcPayConfigured } from "@/lib/btcpay";
|
|||||||
|
|
||||||
export async function GET(
|
export async function GET(
|
||||||
_req: Request,
|
_req: Request,
|
||||||
{ params }: { params: { invoiceId: string } },
|
{ params }: { params: Promise<{ invoiceId: string }> },
|
||||||
) {
|
) {
|
||||||
if (!isBtcPayConfigured()) {
|
if (!isBtcPayConfigured()) {
|
||||||
return NextResponse.json({ ok: false, error: "BTCPay not configured" }, { status: 503 });
|
return NextResponse.json({ ok: false, error: "BTCPay not configured" }, { status: 503 });
|
||||||
}
|
}
|
||||||
|
|
||||||
const { invoiceId } = params;
|
const { invoiceId } = await params;
|
||||||
if (!invoiceId || invoiceId.length < 4) {
|
if (!invoiceId || invoiceId.length < 4) {
|
||||||
return NextResponse.json({ ok: false, error: "Invalid invoice ID" }, { status: 400 });
|
return NextResponse.json({ ok: false, error: "Invalid invoice ID" }, { status: 400 });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,8 @@
|
|||||||
"health:stack": "bash scripts/health-check-stack.sh",
|
"health:stack": "bash scripts/health-check-stack.sh",
|
||||||
"onions:status": "node scripts/onion-status.cjs",
|
"onions:status": "node scripts/onion-status.cjs",
|
||||||
"onions:list": "bash scripts/list-onion-urls.sh",
|
"onions:list": "bash scripts/list-onion-urls.sh",
|
||||||
"install:systemd": "bash -c 'echo Run: sudo CYBERLUX_USER=$USER bash scripts/install-systemd.sh'"
|
"install:systemd": "bash -c 'echo Run: sudo CYBERLUX_USER=$USER bash scripts/install-systemd.sh'",
|
||||||
|
"onions:export": "bash scripts/export-onion-urls.sh"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"next": "16.1.7",
|
"next": "16.1.7",
|
||||||
|
|||||||
71
scripts/export-onion-urls.sh
Executable file
71
scripts/export-onion-urls.sh
Executable file
@@ -0,0 +1,71 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Export all live CyberLux .onion URLs to onion-urls.txt in the repo root.
|
||||||
|
# Reads /var/lib/tor/*/hostname — run with sudo if needed.
|
||||||
|
#
|
||||||
|
# bash scripts/export-onion-urls.sh
|
||||||
|
# sudo bash scripts/export-onion-urls.sh
|
||||||
|
#
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
REPO="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
|
TOR_DIRS="${REPO}/scripts/generated/tor-dirs.txt"
|
||||||
|
LABELS="${REPO}/scripts/generated/onion-labels.tsv"
|
||||||
|
OUT="${REPO}/onion-urls.txt"
|
||||||
|
|
||||||
|
if [[ ! -f "${TOR_DIRS}" ]]; then
|
||||||
|
echo "[!] Missing ${TOR_DIRS}. Run: node scripts/generate-onion-config.cjs"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
declare -A ROLE=()
|
||||||
|
if [[ -f "${LABELS}" ]]; then
|
||||||
|
while IFS=$'\t' read -r dir desc || [[ -n "${dir}" ]]; do
|
||||||
|
[[ -z "${dir}" ]] && continue
|
||||||
|
ROLE["${dir}"]="${desc}"
|
||||||
|
done < "${LABELS}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
read_host() {
|
||||||
|
local f="$1"
|
||||||
|
if [[ -r "${f}" ]]; then
|
||||||
|
tr -d '\n' < "${f}"
|
||||||
|
elif command -v sudo >/dev/null 2>&1 && sudo test -r "${f}" 2>/dev/null; then
|
||||||
|
sudo tr -d '\n' < "${f}"
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
echo "# CyberLux — Live .onion URLs"
|
||||||
|
echo "# Generated: $(date -u '+%Y-%m-%d %H:%M:%S UTC')"
|
||||||
|
echo "# Open in: Tor Browser / Onion Browser (iOS) — http:// only"
|
||||||
|
echo "#"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
ready=0
|
||||||
|
missing=0
|
||||||
|
while IFS= read -r d || [[ -n "${d}" ]]; do
|
||||||
|
[[ -z "${d}" ]] && continue
|
||||||
|
f="/var/lib/tor/${d}/hostname"
|
||||||
|
host="$(read_host "${f}")"
|
||||||
|
role="${ROLE[$d]:-}"
|
||||||
|
if [[ -n "${host}" ]]; then
|
||||||
|
printf '%-28s http://%s\n' "${d}" "${host}"
|
||||||
|
[[ -n "${role}" ]] && printf '%-28s %s\n' "" "# ${role}"
|
||||||
|
echo ""
|
||||||
|
((ready++)) || true
|
||||||
|
else
|
||||||
|
printf '%-28s (not available — %s)\n' "${d}" "${f}"
|
||||||
|
echo ""
|
||||||
|
((missing++)) || true
|
||||||
|
fi
|
||||||
|
done < "${TOR_DIRS}"
|
||||||
|
|
||||||
|
echo "# Services resolved: ${ready}"
|
||||||
|
[[ "${missing}" -gt 0 ]] && echo "# Services pending: ${missing} (start Tor and wait ~30s)"
|
||||||
|
} > "${OUT}"
|
||||||
|
|
||||||
|
echo "[*] Wrote ${OUT}"
|
||||||
|
echo "[*] Services resolved: ${ready} / $((ready + missing))"
|
||||||
|
[[ "${missing}" -gt 0 ]] && echo "[!] ${missing} hostname(s) not yet available — run again after Tor fully starts."
|
||||||
Reference in New Issue
Block a user