diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5ef6a52 --- /dev/null +++ b/.gitignore @@ -0,0 +1,41 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/README.md b/README.md index 28a683d..40ec067 100644 --- a/README.md +++ b/README.md @@ -1,67 +1,272 @@ -This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). +# CYBERLUX -## Getting Started +> Neon storefront. Forty-three onion doors. One build. One app. No dead air. -First, run the development server: +CyberLux is a layered Next.js fiction stack built for dark-web literacy, classroom demos, mirror discipline drills, and absurdly overbuilt cyberpunk presentation. It runs one app behind Tor + nginx, then fans that app out into dedicated v3 hidden services for the hub, forum, exchange, market, crawler, syndicate, wiki layer, and every other top-level surface in `scripts/onion-nodes.json`. + +This repo is built to feel like a real underground property while still being a controlled demo environment: + +- `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 + +CyberLux boots a single Next.js app and projects it through multiple onion entry points. + +- `hub` is the main storefront +- `forum` is Void Aggregate +- `exchange` is the classifieds stack +- `market` is the full catalog vertical +- `search` is Void Crawler +- `wiki` is the hidden-wiki layer +- `w` is the syndicate shell network +- dozens of additional dedicated onions map directly to top-level app routes + +The routing layer uses host-aware rewrites so a dedicated onion feels like its own property without forking the app into 43 separate deployments. + +## One-Command Launch + +Install system deps first on Debian/Ubuntu: ```bash -npm run dev -# or -yarn dev -# or -pnpm dev -# or -bun dev +sudo apt install tor nginx ``` -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. - -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. - -This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. - -## CyberLux on Tor (classroom / demo) - -The UI uses fictional `.onion` names in places; **live addresses come from your Tor daemon** after you install the hidden services. - -**One-command launch:** install `tor` and `nginx` (`apt install tor nginx` on Debian/Ubuntu), then: +Then run: ```bash -chmod +x start.sh # once -git pull && ./start.sh +chmod +x start.sh +./start.sh ``` -The first step regenerates configs from `scripts/onion-nodes.json` (43 Tor v3 services → loopback `8080–8122`, one `.onion` per top-level area). Then it runs `git pull` if `.git` exists (failure is non-fatal), `npm install` / `npm run build`. If `.next/` is **not writable** (common after a `sudo npm run build`), the script runs **`sudo chown`** on `.next` for you. It then installs Tor + nginx via `sudo` (skip with `CYBERLUX_SKIP_TOR=1` for local-only), prints **every** `.onion` URL, and starts Next on `127.0.0.1:3000`. Use **Tor Browser** with `http://YOUR56CHAR.onion`. +What `./start.sh` does: -To add or reorder onions, edit `scripts/onion-nodes.json` and run `node scripts/generate-onion-config.cjs` (also runs automatically on `npm run build` and via `./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` -Manual steps (equivalent): `sudo bash scripts/install-tor-onion.sh`, then `npm run build && npm run start:onion`. +Use Tor Browser and open the printed URLs as: -**Start at boot (systemd):** copy `scripts/cyberlux.service`, set `User`, `Group`, and `WorkingDirectory` to your clone, `sudo install -m 0644 scripts/cyberlux.service /etc/systemd/system/`, then `sudo systemctl daemon-reload && sudo systemctl enable --now cyberlux.service`. Tor and nginx should already be enabled; this only keeps Next running after reboot. +```text +http://<56-char-v3-address>.onion +``` -**Build fails with `EACCES` on `unlink` / `build-diagnostics.json`:** Next.js writes metadata under `.next/diagnostics/build-diagnostics.json` (build stage, options — not an app bug). If those files were created as **root** (e.g. `sudo npm run build`), your user cannot overwrite them. **`npm run build` now stops in `prebuild`** with a clear error instead of a cryptic unlink message. Fix once: +## Persistent Onion Addresses + +Yes: the onion addresses are meant to persist. + +Each service uses a fixed Tor directory: + +```tor +HiddenServiceDir /var/lib/tor/ +HiddenServicePort 80 127.0.0.1: +``` + +That means the `.onion` address remains stable as long as: + +- the `torDir` names in `scripts/onion-nodes.json` do not change +- `/var/lib/tor/` is preserved +- or the backup set can restore those directories + +Addresses do **not** rotate on normal app restarts, rebuilds, or standard Tor restarts. + +## Self-Healing Onion Identity + +CyberLux now includes automatic onion key persistence tooling: + +- `scripts/backup-onion-keys.sh` +- `scripts/restore-onion-keys.sh` + +Backup location: + +```text +/var/backups/cyberlux-onion-keys/current +``` + +Behavior: + +- after boot, ready onion service directories are backed up +- on next boot, if a service dir is missing from `/var/lib/tor`, it is restored from backup +- Tor identity is preserved across ordinary host mistakes, partial deletions, or service-dir drift recovery + +This is the difference between “looks cool in a screenshot” and “survives operator error.” + +## Tor / nginx Topology + +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 immediately: + +```bash +sudo bash scripts/backup-onion-keys.sh +``` + +Restore missing onion keys: + +```bash +sudo bash scripts/restore-onion-keys.sh +``` + +Run local-only, skipping 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 + +`scripts/cyberlux.service` is included as a systemd template for the Next process. + +Before installing it, set: + +- `User=` +- `Group=` +- `WorkingDirectory=` + +Then install: + +```bash +sudo install -m 0644 scripts/cyberlux.service /etc/systemd/system/cyberlux.service +sudo systemctl daemon-reload +sudo systemctl enable --now cyberlux.service +``` + +Notes: + +- Tor and nginx should already be installed and enabled +- the service unit keeps the Next process alive +- Tor/nginx config is still managed by the repo scripts + +## Verification + +Run the full local verification suite: + +```bash +npm run verify +``` + +That checks: + +- onion config generation +- TypeScript +- shell syntax for boot / install / backup / restore scripts +- full Next production build + +## Common Failure: `.next` Permission Hell + +If you previously ran a build with `sudo`, `.next` may be root-owned and Next will fail with `EACCES` during unlink / diagnostics writes. + +Fix once: ```bash sudo bash scripts/fix-next-perms.sh ``` -(or `sudo chown -R "$USER" .next` / `sudo rm -rf .next`), then `npm run build` or `./start.sh` again. +Then rerun: -**Verify locally:** after fixing permissions, run `npm run verify` — regenerates onion configs, runs `tsc --noEmit`, checks shell scripts, and runs a production build. +```bash +./start.sh +``` -**Security notes (for instructors):** No stack is “perfectly” secure. This setup keeps the app off the public internet: nginx and Next listen on loopback; Tor exposes onion endpoints only. Optional: `sudo bash scripts/classroom-ufw.sh` — do not publish `3000` or nginx loopback ports (`8080–8122`) to the public internet. Tor improves reachability privacy for the **service** vs raw IP hosting; it does not make unsafe application code safe or absolve lawful/ethical/use-policy obligations—use only for legitimate teaching and demos. +## Security Notes -## Learn More +CyberLux is hardened for a demo stack, not sold as magic invisibility. -To learn more about Next.js, take a look at the following resources: +- Next and nginx bind to loopback only +- Tor exposes the onion endpoints +- do **not** publish `3000` or `8080–8122` to the public internet +- optional host firewall script: `sudo bash scripts/classroom-ufw.sh` +- the app can still be insecure if the app code is insecure +- operational mistakes still matter more than branding -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. +Tor hides service reachability better than raw-IP hosting. It does not redeem bad application logic, bad operator habits, or bad judgment. -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! +## Site Map -## Deploy on Vercel +Core verticals: -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. +- `/` 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 -Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. +There are additional dedicated onions for many top-level routes beyond those. + +## Stack + +- Next.js `16` +- React `19` +- Tailwind CSS `4` +- nginx +- Tor hidden services +- generated route / host mapping + +## Final Word + +CyberLux is supposed to boot like a machine that knows what it is: + +- same onion doors +- same identities +- no shallow mirrors +- no fake “self healing” copy without actual restore logic +- no dead routes pretending to be part of the network + +If it starts, it should start hard. diff --git a/app/account/hidden-services/page.tsx b/app/account/hidden-services/page.tsx new file mode 100644 index 0000000..ddc3bcb --- /dev/null +++ b/app/account/hidden-services/page.tsx @@ -0,0 +1,159 @@ +"use client"; + +import { FormEvent, useEffect, useState } from "react"; +import Link from "next/link"; +import { useAccount } from "@/contexts/AccountContext"; +import { exportPortableAccountJson, importPortableAccountJson } from "@/lib/cyberluxAccount"; + +export default function HiddenServicesAccountPage() { + const { user, hydrated, refreshProfile } = useAccount(); + const [importText, setImportText] = useState(""); + const [importMsg, setImportMsg] = useState<{ kind: "ok" | "err"; text: string } | null>(null); + const [copyMsg, setCopyMsg] = useState(null); + + useEffect(() => { + setImportMsg(null); + }, [importText]); + + const onCopyBundle = async () => { + setCopyMsg(null); + const json = exportPortableAccountJson(); + if (!json) return; + try { + await navigator.clipboard.writeText(json); + setCopyMsg("Copied. Paste on another onion host → Import below."); + } catch { + setCopyMsg("Could not use clipboard — select and copy manually."); + } + }; + + const onImport = (e: FormEvent) => { + e.preventDefault(); + setImportMsg(null); + const res = importPortableAccountJson(importText.trim()); + if (!res.ok) { + setImportMsg({ kind: "err", text: res.error }); + return; + } + refreshProfile(); + setImportText(""); + setImportMsg({ kind: "ok", text: "Identity loaded on this hostname. You can use dashboard, forum, exchange, and barter here." }); + }; + + if (!hydrated) { + return ( +
+ Loading… +
+ ); + } + + return ( +
+
+

hidden services

+

Account on every entry node

+

+ Each hidden-service hostname gets an isolated browser vault. Keys you mint on the forum onion do not + automatically exist on the exchange or wiki host — mirror your identity deliberately or enroll separately. +

+ +
    +
  1. + Create a handle on this host:{" "} + + Sign up + {" "} + (or{" "} + + Sign in + + ). +
  2. +
  3. + Repeat on other mirrors with the{" "} + same handle and passphrase,{" "} + or export a bundle here (signed in) and import it on the other host. +
  4. +
  5. + Use{" "} + + Dashboard + + ,{" "} + + Forum + + ,{" "} + + Exchange + + , and{" "} + + Barter + {" "} + once this hostname knows your session. +
  6. +
+ + {user ? ( +
+

Portable bundle

+

+ Signed in as @{user.username}. The bundle contains a + passphrase fingerprint — do not share it. +

+ + {copyMsg ?

{copyMsg}

: null} +
+ ) : ( +

+ + Sign in + {" "} + to copy an export bundle for another host. +

+ )} + +
+

Import bundle

+

Paste JSON from "Copy identity bundle" on the host where you exported it.

+
+