T1
This commit is contained in:
@@ -1,101 +1,62 @@
|
||||
# P2NS Website
|
||||
|
||||
Modern, professional public-facing website for P2NS (Peer-to-Peer Decentralized DNS System).
|
||||
Public site for **P2NS** (Peer-to-Peer Name System) — decentralized, secure, and censorship-resistant naming infrastructure.
|
||||
|
||||
## Features
|
||||
**Live brand direction:** dark-first (Midnight `#0A0E1A`), indigo-dominant (`#6366F1`), flat technical UI aligned with the P2NS brand package in the main [p2ns](https://git.ssh.surf/snxraven/p2ns) repo.
|
||||
|
||||
- **Modern Design**: Built with Next.js 16, TypeScript, and Tailwind CSS 4
|
||||
- **Responsive**: Mobile-first design that works on all devices
|
||||
- **Dark Mode**: Automatic dark mode support
|
||||
- **Interactive Diagrams**: Animated visualizations of P2P concepts
|
||||
- **Comprehensive Documentation**: Complete guides and API references
|
||||
- **SEO Optimized**: Proper metadata, structured data, and semantic HTML
|
||||
- **Accessible**: WCAG AA compliant with proper ARIA labels
|
||||
## Stack
|
||||
|
||||
- **Next.js 16** (App Router)
|
||||
- **TypeScript 5**
|
||||
- **Tailwind CSS 4** (brand tokens in `app/globals.css`)
|
||||
- **Framer Motion** for light motion
|
||||
- **Lucide React** icons
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Node.js 20 or higher
|
||||
- npm
|
||||
|
||||
### Installation
|
||||
|
||||
```bash
|
||||
# Install dependencies (run as your user, not root — Docker-created node_modules may need removal first)
|
||||
npm install
|
||||
|
||||
# Run development server
|
||||
npm run dev
|
||||
|
||||
# Build and run production server (port 8588)
|
||||
npm run prod
|
||||
|
||||
# Or build once, then start
|
||||
npm run dev # http://localhost:3000
|
||||
npm run build
|
||||
npm start
|
||||
npm start # production on port 8588
|
||||
npm run prod # build + start
|
||||
```
|
||||
|
||||
The production server listens on [http://localhost:8588](http://localhost:8588). Development (`npm run dev`) uses port 3000 by default.
|
||||
|
||||
## Project Structure
|
||||
## Project structure
|
||||
|
||||
```
|
||||
p2ns-website/
|
||||
├── app/ # Next.js App Router pages
|
||||
│ ├── about/ # About P2NS page
|
||||
│ ├── learn/ # P2P education pages
|
||||
│ ├── features/ # Features page
|
||||
│ ├── docs/ # Documentation pages
|
||||
│ └── community/ # Community page
|
||||
├── components/ # React components
|
||||
│ ├── layout/ # Layout components (Navigation, Footer)
|
||||
│ ├── sections/ # Page sections (Hero, Features, etc.)
|
||||
│ ├── diagrams/ # Interactive diagrams
|
||||
│ └── ui/ # Reusable UI components
|
||||
├── public/ # Static assets
|
||||
└── styles/ # Global styles
|
||||
app/ # Routes (home, docs, features, legal, …)
|
||||
components/
|
||||
layout/ # Navigation, Footer
|
||||
sections/ # Homepage sections
|
||||
diagrams/ # Educational diagrams
|
||||
ui/ # BrandLogo, PageHeader, CodeBlock, …
|
||||
legal/
|
||||
lib/legal/ # Legal document metadata
|
||||
public/branding/ # Logos, favicons, hero banner
|
||||
```
|
||||
|
||||
## Design system
|
||||
|
||||
Brand colors and utilities live in `app/globals.css` (`@theme` + helpers):
|
||||
|
||||
| Token | Hex | Use |
|
||||
|-------|-----|-----|
|
||||
| `midnight` | `#0A0E1A` | Primary background |
|
||||
| `deep` | `#0F1419` | Section alternate |
|
||||
| `surface` | `#1A1F2E` | Cards |
|
||||
| `steel` | `#2D3446` | Borders |
|
||||
| `fog` / `mist` | muted text | Secondary / body |
|
||||
| `indigo` | `#6366F1` | CTAs, accents |
|
||||
|
||||
Helpers: `.bg-grid-fade`, `.surface-card`, `.btn-primary`, `.btn-secondary`, `.link-accent`.
|
||||
|
||||
## Deployment
|
||||
|
||||
### Self-Hosted
|
||||
- **Docker:** `Dockerfile` + `docker-compose.yml`
|
||||
- **Node:** `npm run build && npm start` (port 8588)
|
||||
|
||||
The website is designed to be self-hostable. You can deploy it using:
|
||||
## Related
|
||||
|
||||
- **Docker**: See `Dockerfile` and `docker-compose.yml`
|
||||
- **Node.js**: Run `npm run build && npm start`
|
||||
- **Static Export**: Configure Next.js for static export if needed
|
||||
|
||||
### Environment Variables
|
||||
|
||||
No environment variables are required for basic operation. All configuration is handled through Next.js.
|
||||
|
||||
## Technologies Used
|
||||
|
||||
- **Next.js 16**: React framework with App Router
|
||||
- **TypeScript 5**: Type-safe development
|
||||
- **Tailwind CSS 4**: Utility-first CSS framework
|
||||
- **Framer Motion 12**: Animation library
|
||||
- **Lucide React**: Icon library
|
||||
|
||||
## Dependencies and security
|
||||
|
||||
Keep dependencies current:
|
||||
|
||||
```bash
|
||||
npm audit # should report 0 vulnerabilities after overrides in package.json
|
||||
npm outdated # review available upgrades
|
||||
npm install # apply package-lock.json
|
||||
```
|
||||
|
||||
If `npm install` fails with permission errors, `node_modules` may have been created by Docker as root. Remove it and reinstall as your user:
|
||||
|
||||
```bash
|
||||
rm -rf node_modules package-lock.json # or: sudo rm -rf node_modules
|
||||
npm install
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome! Please follow the same contribution guidelines as the main P2NS repository.
|
||||
- Core product: [p2ns](https://git.ssh.surf/snxraven/p2ns)
|
||||
- Brand guidelines: `p2ns/branding/`
|
||||
|
||||
+71
-71
@@ -26,39 +26,39 @@ export const metadata: Metadata = {
|
||||
|
||||
export default function AboutPage() {
|
||||
return (
|
||||
<div className="min-h-screen">
|
||||
<div className="min-h-screen bg-midnight">
|
||||
{/* Hero Section */}
|
||||
<section className="py-20 bg-gradient-to-b from-blue-50 to-white dark:from-gray-900 dark:to-gray-800">
|
||||
<section className="py-20 bg-grid-fade border-b border-steel/40">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div>
|
||||
<h1 className="text-4xl sm:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
<p className="text-sm font-medium tracking-wide uppercase text-indigo-light mb-3">
|
||||
About
|
||||
</p>
|
||||
<h1 className="text-4xl sm:text-5xl font-bold text-white mb-6 tracking-tight">
|
||||
What is P2NS?
|
||||
</h1>
|
||||
<p className="text-xl text-gray-600 dark:text-gray-300 leading-relaxed">
|
||||
P2NS (Peer-to-Peer Name System) is a robust, firewall-resistant
|
||||
peer-to-peer DNS resolution system designed to operate
|
||||
independently of centralized DNS infrastructure. Utilizing UDP
|
||||
hole-punching via the Holesail library, P2NS enables seamless
|
||||
connectivity across challenging network environments.
|
||||
<p className="text-xl text-mist leading-relaxed max-w-3xl">
|
||||
P2NS (Peer-to-Peer Name System) is firewall-resistant peer-to-peer DNS
|
||||
that operates independently of centralized infrastructure. UDP
|
||||
hole-punching via Holesail connects peers across NAT, CGNAT, and
|
||||
restricted networks.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Problem Statement */}
|
||||
<section className="py-20 bg-white dark:bg-gray-900">
|
||||
<section className="py-20 bg-midnight">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
<h2 className="text-3xl font-bold text-white mb-6">
|
||||
The Problem with Centralized DNS
|
||||
</h2>
|
||||
<div className="prose prose-lg dark:prose-invert max-w-none">
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<div className="prose prose-lg max-w-none">
|
||||
<p className="text-mist mb-4">
|
||||
Traditional DNS systems rely on centralized infrastructure
|
||||
controlled by ICANN and major DNS providers.
|
||||
<br /><br />
|
||||
This creates several critical issues:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist">
|
||||
<li>
|
||||
<strong>Single Points of Failure:</strong> Centralized servers
|
||||
can be targeted by DDoS attacks or taken offline, disrupting
|
||||
@@ -86,51 +86,51 @@ export default function AboutPage() {
|
||||
</section>
|
||||
|
||||
{/* Solution */}
|
||||
<section className="py-20 bg-gray-50 dark:bg-gray-800">
|
||||
<section className="py-20 bg-deep">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
<h2 className="text-3xl font-bold text-white mb-6">
|
||||
How P2NS Solves These Problems
|
||||
</h2>
|
||||
<div className="prose prose-lg dark:prose-invert max-w-none">
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
<div className="prose prose-lg max-w-none">
|
||||
<p className="text-mist mb-6">
|
||||
P2NS addresses these fundamental issues through a decentralized,
|
||||
peer-to-peer architecture:
|
||||
</p>
|
||||
<div className="grid md:grid-cols-2 gap-6">
|
||||
<div className="bg-white dark:bg-gray-900 p-6 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">
|
||||
<div className="grid md:grid-cols-2 gap-4">
|
||||
<div className="surface-card p-6">
|
||||
<h3 className="text-lg font-semibold text-white mb-3">
|
||||
Decentralized Resolution
|
||||
</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300">
|
||||
Domains claims are automatically synced with all peers via corestore, and all P2P queries are local to your device. No central authority controls the system.
|
||||
<p className="text-mist text-sm leading-relaxed">
|
||||
Domain claims sync across peers via Corestore. P2P queries resolve
|
||||
on your device — no central authority controls the system.
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-white dark:bg-gray-900 p-6 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">
|
||||
<div className="surface-card p-6">
|
||||
<h3 className="text-lg font-semibold text-white mb-3">
|
||||
Firewall Traversal
|
||||
</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300">
|
||||
UDP hole-punching technology enables connections across
|
||||
firewalls, NAT, CGNAT, and restricted networks like 4G/5G or
|
||||
satellite internet.
|
||||
<p className="text-mist text-sm leading-relaxed">
|
||||
UDP hole-punching connects across firewalls, NAT, CGNAT, and
|
||||
restricted networks like 4G/5G or satellite internet.
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-white dark:bg-gray-900 p-6 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">
|
||||
<div className="surface-card p-6">
|
||||
<h3 className="text-lg font-semibold text-white mb-3">
|
||||
Privacy & Security
|
||||
</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300">
|
||||
Peer connections use Noise XX handshakes and libsodium secretstream (XChaCha20-Poly1305) over UDP via the Holepunch stack. Web connections are safeguarded via TLS and a custom CA.
|
||||
<p className="text-mist text-sm leading-relaxed">
|
||||
Peer links use Noise XX and libsodium secretstream over UDP.
|
||||
Web traffic is TLS with a local CA for seamless browser trust.
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-white dark:bg-gray-900 p-6 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">
|
||||
<div className="surface-card p-6">
|
||||
<h3 className="text-lg font-semibold text-white mb-3">
|
||||
Resilience
|
||||
</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300">
|
||||
The network continues to function even if individual peers go
|
||||
offline. Consensus mechanisms ensure data integrity and
|
||||
prevent tampering.
|
||||
<p className="text-mist text-sm leading-relaxed">
|
||||
The mesh keeps working when individual peers drop. Consensus
|
||||
keeps domain resolution consistent and tamper-resistant.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -139,12 +139,12 @@ export default function AboutPage() {
|
||||
</section>
|
||||
|
||||
{/* Architecture */}
|
||||
<section className="py-20 bg-white dark:bg-gray-900">
|
||||
<section className="py-20 bg-midnight">
|
||||
<div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 text-center">
|
||||
<h2 className="text-3xl font-bold text-white mb-6 text-center">
|
||||
System Architecture
|
||||
</h2>
|
||||
<p className="text-center text-gray-600 dark:text-gray-300 mb-12 max-w-2xl mx-auto">
|
||||
<p className="text-center text-mist mb-12 max-w-2xl mx-auto">
|
||||
P2NS is built on a modular architecture using proven P2P
|
||||
technologies. Built-in plugins include peer.directory, peer.paste,
|
||||
file.drop, and the p2ns.admin interface—extensible via the plugin SDK
|
||||
@@ -155,90 +155,90 @@ export default function AboutPage() {
|
||||
</section>
|
||||
|
||||
{/* Comparison Table */}
|
||||
<section className="py-20 bg-gray-50 dark:bg-gray-800">
|
||||
<section className="py-20 bg-deep">
|
||||
<div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 text-center">
|
||||
<h2 className="text-3xl font-bold text-white mb-6 text-center">
|
||||
P2NS vs Traditional DNS
|
||||
</h2>
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full border-collapse bg-white dark:bg-gray-900 rounded-lg overflow-hidden">
|
||||
<div className="overflow-x-auto rounded-xl border border-steel">
|
||||
<table className="w-full border-collapse bg-surface">
|
||||
<thead>
|
||||
<tr className="bg-gray-100 dark:bg-gray-800">
|
||||
<th className="px-6 py-4 text-left text-sm font-semibold text-gray-900 dark:text-white">
|
||||
<tr className="bg-deep border-b border-steel">
|
||||
<th className="px-6 py-4 text-left text-sm font-semibold text-white">
|
||||
Feature
|
||||
</th>
|
||||
<th className="px-6 py-4 text-left text-sm font-semibold text-gray-900 dark:text-white">
|
||||
<th className="px-6 py-4 text-left text-sm font-semibold text-fog">
|
||||
Traditional DNS
|
||||
</th>
|
||||
<th className="px-6 py-4 text-left text-sm font-semibold text-gray-900 dark:text-white">
|
||||
<th className="px-6 py-4 text-left text-sm font-semibold text-indigo-light">
|
||||
P2NS
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y divide-gray-200 dark:divide-gray-700">
|
||||
<tbody className="divide-y divide-steel">
|
||||
<tr>
|
||||
<td className="px-6 py-4 text-sm font-medium text-gray-900 dark:text-white">
|
||||
<td className="px-6 py-4 text-sm font-medium text-white">
|
||||
Infrastructure
|
||||
</td>
|
||||
<td className="px-6 py-4 text-sm text-gray-600 dark:text-gray-300">
|
||||
<td className="px-6 py-4 text-sm text-mist">
|
||||
Centralized servers
|
||||
</td>
|
||||
<td className="px-6 py-4 text-sm text-gray-600 dark:text-gray-300">
|
||||
<td className="px-6 py-4 text-sm text-mist">
|
||||
Decentralized P2P network
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-6 py-4 text-sm font-medium text-gray-900 dark:text-white">
|
||||
<td className="px-6 py-4 text-sm font-medium text-white">
|
||||
Firewall Traversal
|
||||
</td>
|
||||
<td className="px-6 py-4 text-sm text-gray-600 dark:text-gray-300">
|
||||
<td className="px-6 py-4 text-sm text-mist">
|
||||
Limited
|
||||
</td>
|
||||
<td className="px-6 py-4 text-sm text-gray-600 dark:text-gray-300">
|
||||
<td className="px-6 py-4 text-sm text-mist">
|
||||
UDP hole-punching
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-6 py-4 text-sm font-medium text-gray-900 dark:text-white">
|
||||
<td className="px-6 py-4 text-sm font-medium text-white">
|
||||
Censorship Resistance
|
||||
</td>
|
||||
<td className="px-6 py-4 text-sm text-gray-600 dark:text-gray-300">
|
||||
<td className="px-6 py-4 text-sm text-mist">
|
||||
Vulnerable
|
||||
</td>
|
||||
<td className="px-6 py-4 text-sm text-gray-600 dark:text-gray-300">
|
||||
<td className="px-6 py-4 text-sm text-mist">
|
||||
Highly resistant
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-6 py-4 text-sm font-medium text-gray-900 dark:text-white">
|
||||
<td className="px-6 py-4 text-sm font-medium text-white">
|
||||
Privacy
|
||||
</td>
|
||||
<td className="px-6 py-4 text-sm text-gray-600 dark:text-gray-300">
|
||||
<td className="px-6 py-4 text-sm text-mist">
|
||||
Queries can be logged
|
||||
</td>
|
||||
<td className="px-6 py-4 text-sm text-gray-600 dark:text-gray-300">
|
||||
<td className="px-6 py-4 text-sm text-mist">
|
||||
Distributed queries
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-6 py-4 text-sm font-medium text-gray-900 dark:text-white">
|
||||
<td className="px-6 py-4 text-sm font-medium text-white">
|
||||
Resilience
|
||||
</td>
|
||||
<td className="px-6 py-4 text-sm text-gray-600 dark:text-gray-300">
|
||||
<td className="px-6 py-4 text-sm text-mist">
|
||||
Single points of failure
|
||||
</td>
|
||||
<td className="px-6 py-4 text-sm text-gray-600 dark:text-gray-300">
|
||||
<td className="px-6 py-4 text-sm text-mist">
|
||||
No single point of failure
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-6 py-4 text-sm font-medium text-gray-900 dark:text-white">
|
||||
<td className="px-6 py-4 text-sm font-medium text-white">
|
||||
Control
|
||||
</td>
|
||||
<td className="px-6 py-4 text-sm text-gray-600 dark:text-gray-300">
|
||||
<td className="px-6 py-4 text-sm text-mist">
|
||||
Third-party controlled
|
||||
</td>
|
||||
<td className="px-6 py-4 text-sm text-gray-600 dark:text-gray-300">
|
||||
<td className="px-6 py-4 text-sm text-mist">
|
||||
User-controlled
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
+89
-74
@@ -1,23 +1,17 @@
|
||||
import type { Metadata } from 'next';
|
||||
import { Github, ExternalLink, Code, Heart, MessageCircle } from 'lucide-react';
|
||||
import PageHeader from '@/components/ui/PageHeader';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Community - P2NS',
|
||||
title: 'Community',
|
||||
description: 'Contribute to P2NS, get support, and join the Discord community.',
|
||||
keywords: ['P2NS community', 'contribute', 'open source', 'Discord', 'support', 'contributing'],
|
||||
authors: [{ name: 'Raven Scott' }],
|
||||
openGraph: {
|
||||
title: 'Community - P2NS',
|
||||
title: 'Community · P2NS',
|
||||
description: 'Contribute to P2NS, get support, and join the Discord community.',
|
||||
url: 'https://p2ns.space/community',
|
||||
siteName: 'P2NS',
|
||||
type: 'website',
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: 'Community - P2NS',
|
||||
description: 'Contribute to P2NS, get support, and join the Discord community.',
|
||||
},
|
||||
alternates: {
|
||||
canonical: 'https://p2ns.space/community',
|
||||
},
|
||||
@@ -25,101 +19,123 @@ export const metadata: Metadata = {
|
||||
|
||||
export default function CommunityPage() {
|
||||
return (
|
||||
<div className="min-h-screen">
|
||||
<section className="py-20 bg-gradient-to-b from-blue-50 to-white dark:from-gray-900 dark:to-gray-800">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<h1 className="text-4xl sm:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
Community
|
||||
</h1>
|
||||
<p className="text-xl text-gray-600 dark:text-gray-300">
|
||||
Join the P2NS community and help build the future of decentralized DNS
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
<div className="min-h-screen bg-midnight">
|
||||
<PageHeader
|
||||
eyebrow="Connect"
|
||||
title="Community"
|
||||
description="Build with others. Report bugs, ship plugins, and hang out where Holepunch folks gather."
|
||||
/>
|
||||
|
||||
<section className="py-20 bg-white dark:bg-gray-900">
|
||||
<section className="py-16 sm:py-20">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="space-y-12">
|
||||
<div>
|
||||
<div className="flex items-center space-x-3 mb-4">
|
||||
<Github className="h-8 w-8 text-gray-900 dark:text-white" />
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white">Repository</h2>
|
||||
<div className="grid gap-6">
|
||||
<div className="surface-card p-6 sm:p-8">
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<div className="p-2.5 rounded-lg bg-indigo-deep/80 border border-indigo-dark/40">
|
||||
<Github className="h-5 w-5 text-indigo-light" />
|
||||
</div>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
P2NS is open source and available on Git. Check out the code, report issues, and contribute.
|
||||
<h2 className="text-xl font-semibold text-white">Repository</h2>
|
||||
</div>
|
||||
<p className="text-mist mb-5 leading-relaxed">
|
||||
P2NS is open source. Browse the code, open issues, and send pull requests.
|
||||
</p>
|
||||
<a
|
||||
href="https://git.ssh.surf/snxraven/p2ns"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center space-x-2 px-6 py-3 bg-gray-900 dark:bg-gray-100 text-white dark:text-gray-900 rounded-lg hover:bg-gray-800 dark:hover:bg-gray-200 transition-colors"
|
||||
className="btn-secondary"
|
||||
>
|
||||
<Github className="h-5 w-5" />
|
||||
<span>View Repository</span>
|
||||
<ExternalLink className="h-4 w-4" />
|
||||
<Github className="h-4 w-4" />
|
||||
View Repository
|
||||
<ExternalLink className="h-3.5 w-3.5" />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="flex items-center space-x-3 mb-4">
|
||||
<MessageCircle className="h-8 w-8 text-gray-900 dark:text-white" />
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white">Holesail Discord</h2>
|
||||
<div className="surface-card p-6 sm:p-8">
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<div className="p-2.5 rounded-lg bg-indigo-deep/80 border border-indigo-dark/40">
|
||||
<MessageCircle className="h-5 w-5 text-indigo-light" />
|
||||
</div>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
Join the Holesail Discord server to connect with the community, get help, share ideas, and stay updated on the latest developments.
|
||||
<h2 className="text-xl font-semibold text-white">Holesail Discord</h2>
|
||||
</div>
|
||||
<p className="text-mist mb-5 leading-relaxed">
|
||||
Connect with the community for help, ideas, and updates on Holepunch tooling.
|
||||
</p>
|
||||
<a
|
||||
href="https://discord.gg/3gFegYtNbN"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center space-x-2 px-6 py-3 bg-indigo-600 dark:bg-indigo-500 text-white rounded-lg hover:bg-indigo-700 dark:hover:bg-indigo-600 transition-colors"
|
||||
className="btn-primary"
|
||||
>
|
||||
<MessageCircle className="h-5 w-5" />
|
||||
<span>Join Discord Server</span>
|
||||
<ExternalLink className="h-4 w-4" />
|
||||
<MessageCircle className="h-4 w-4" />
|
||||
Join Discord
|
||||
<ExternalLink className="h-3.5 w-3.5" />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="flex items-center space-x-3 mb-4">
|
||||
<Code className="h-8 w-8 text-gray-900 dark:text-white" />
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white">Contributing</h2>
|
||||
<div className="surface-card p-6 sm:p-8">
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<div className="p-2.5 rounded-lg bg-indigo-deep/80 border border-indigo-dark/40">
|
||||
<Code className="h-5 w-5 text-indigo-light" />
|
||||
</div>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
Contributions are welcome! Here's how you can help:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-6">
|
||||
<li>Report bugs and issues</li>
|
||||
<li>Suggest new features</li>
|
||||
<li>Submit pull requests</li>
|
||||
<li>Improve documentation</li>
|
||||
<li>Test on different platforms</li>
|
||||
<h2 className="text-xl font-semibold text-white">Contributing</h2>
|
||||
</div>
|
||||
<p className="text-mist mb-4 leading-relaxed">Ways to help:</p>
|
||||
<ul className="space-y-2 text-mist mb-6">
|
||||
{[
|
||||
'Report bugs and issues',
|
||||
'Suggest features',
|
||||
'Submit pull requests',
|
||||
'Improve documentation',
|
||||
'Test on different platforms',
|
||||
].map((item) => (
|
||||
<li key={item} className="flex gap-2">
|
||||
<span className="text-indigo mt-1.5 h-1.5 w-1.5 rounded-full bg-indigo shrink-0" />
|
||||
{item}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<div className="bg-gray-50 dark:bg-gray-800 p-6 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-3">Contribution Guidelines</h3>
|
||||
<ol className="list-decimal pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||
<li>Must be a member of Discord-Linux <a href="https://join.discord-linux.com" className="text-blue-600 dark:text-blue-400 hover:underline">Join Now</a></li>
|
||||
<li>Run /register-git command to register an account.</li>
|
||||
<div className="rounded-xl border border-steel bg-deep p-5">
|
||||
<h3 className="text-sm font-semibold text-white mb-3 uppercase tracking-wide">
|
||||
Guidelines
|
||||
</h3>
|
||||
<ol className="list-decimal pl-5 space-y-2 text-sm text-fog">
|
||||
<li>
|
||||
Join Discord-Linux —{' '}
|
||||
<a
|
||||
href="https://join.discord-linux.com"
|
||||
className="text-indigo-light hover:text-indigo-pale"
|
||||
>
|
||||
join.discord-linux.com
|
||||
</a>
|
||||
</li>
|
||||
<li>Run /register-git to register an account</li>
|
||||
<li>Fork the repository</li>
|
||||
<li>Create a branch for your changes</li>
|
||||
<li>Make your changes and test thoroughly</li>
|
||||
<li>Submit a pull request with a clear description</li>
|
||||
<li>Focus on stability and cross-platform compatibility</li>
|
||||
<li>Test thoroughly, then open a PR with a clear description</li>
|
||||
<li>Prioritize stability and cross-platform compatibility</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="flex items-center space-x-3 mb-4">
|
||||
<Heart className="h-8 w-8 text-gray-900 dark:text-white" />
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white">Support</h2>
|
||||
<div className="surface-card p-6 sm:p-8">
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<div className="p-2.5 rounded-lg bg-indigo-deep/80 border border-indigo-dark/40">
|
||||
<Heart className="h-5 w-5 text-indigo-light" />
|
||||
</div>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
Need help? Here are some resources:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||
<li>Check the <a href="/docs/troubleshooting" className="text-blue-600 dark:text-blue-400 hover:underline">Troubleshooting</a> guide</li>
|
||||
<li>Review the <a href="/docs" className="text-blue-600 dark:text-blue-400 hover:underline">Documentation</a></li>
|
||||
<h2 className="text-xl font-semibold text-white">Support</h2>
|
||||
</div>
|
||||
<ul className="space-y-2 text-mist">
|
||||
<li>
|
||||
<a href="/docs/troubleshooting" className="link-accent">
|
||||
Troubleshooting guide
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs" className="link-accent">
|
||||
Full documentation
|
||||
</a>
|
||||
</li>
|
||||
<li>Open an issue on the repository</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -129,4 +145,3 @@ export default function CommunityPage() {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+290
-290
@@ -26,254 +26,254 @@ export const metadata: Metadata = {
|
||||
export default function AdminPanelPage() {
|
||||
return (
|
||||
<div className="min-h-screen">
|
||||
<section className="py-20 bg-gradient-to-b from-blue-50 to-white dark:from-gray-900 dark:to-gray-800">
|
||||
<section className="py-20 bg-grid-fade border-b border-steel/40">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<h1 className="text-4xl sm:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
<h1 className="text-4xl sm:text-5xl font-bold text-white mb-6">
|
||||
Admin Panel
|
||||
</h1>
|
||||
<p className="text-xl text-gray-600 dark:text-gray-300">
|
||||
<p className="text-xl text-mist">
|
||||
Complete guide to the web-based admin interface
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="py-20 bg-white dark:bg-gray-900">
|
||||
<section className="py-20 bg-midnight">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6">Introduction</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h2 className="text-3xl font-bold text-white mb-6">Introduction</h2>
|
||||
<p className="text-mist mb-4">
|
||||
The P2NS Admin Panel is a comprehensive web-based management interface that provides real-time control
|
||||
over all aspects of your P2NS node. It offers an intuitive interface for managing domains, Holesail servers
|
||||
and clients, DNS records, certificates, and system settings.
|
||||
</p>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
The admin panel is accessible at <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">https://p2ns.admin</code> and uses WebSocket connections
|
||||
<p className="text-mist mb-6">
|
||||
The admin panel is accessible at <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">https://p2ns.admin</code> and uses WebSocket connections
|
||||
for real-time updates, ensuring you always have the latest information about your system.
|
||||
</p>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Getting Started</h2>
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4">Accessing the Admin Panel</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">Getting Started</h2>
|
||||
<h3 className="text-2xl font-semibold text-white mb-4">Accessing the Admin Panel</h3>
|
||||
<p className="text-mist mb-4">
|
||||
Once your P2NS node is running, access the admin panel by navigating to:
|
||||
</p>
|
||||
<CodeBlock code="https://p2ns.admin" />
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Certificate Trust</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">Certificate Trust</h3>
|
||||
<p className="text-mist mb-4">
|
||||
The admin panel uses HTTPS with automatically generated certificates. On first access, you'll need to trust
|
||||
the root CA certificate. The system will attempt to install it automatically, but you may need to:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-6">
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-6">
|
||||
<li>Accept the security warning in your browser</li>
|
||||
<li>Manually install the root CA certificate if automatic installation fails</li>
|
||||
<li><strong>Linux + Chrome:</strong> trust both the system CA store and the NSS database (<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">~/.pki/nssdb</code>) — see <a href="/docs/troubleshooting#certificate-authority-issues" className="text-blue-600 dark:text-blue-400 hover:underline">Troubleshooting</a></li>
|
||||
<li><strong>Linux + Chrome:</strong> trust both the system CA store and the NSS database (<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">~/.pki/nssdb</code>) — see <a href="/docs/troubleshooting#certificate-authority-issues" className="text-indigo-light hover:underline">Troubleshooting</a></li>
|
||||
<li>Trust the certificate in your system's certificate store (macOS/Windows; Linux also needs NSS for Chromium)</li>
|
||||
</ul>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Features Overview</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">Features Overview</h2>
|
||||
<p className="text-mist mb-4">
|
||||
The admin panel is organized into several tabs, each providing specific functionality:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-6">
|
||||
<li><strong className="text-gray-900 dark:text-white">Domains</strong> - Manage P2P domain registrations with consensus status</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Host</strong> - Manage Holesail servers and clients, and subscribe to services from other domains</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Local DNS</strong> - Custom DNS records and conflict resolution</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Entries</strong> - View Autopass ledger entries</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Peers</strong> - Monitor connected peers</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Certificates</strong> - Manage TLS certificates</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Interfaces</strong> - View virtual network interfaces</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Backups</strong> - Create, restore, and manage system backups</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Diagnostics</strong> - DNS lookup, ping, traceroute, connection tests, invite RPC diagnostics</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Stats</strong> - Live metrics, Core RPC invite diagnostics, Plugin RPC protocol stats</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Logs</strong> - Tail split log files by channel (core, proxy, DNS, plugins, Holesail)</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Settings</strong> - Configure environment variables and subnets</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Plugins</strong> - Start/stop plugins, view logs, run actions with validated parameters</li>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-6">
|
||||
<li><strong className="text-white">Domains</strong> - Manage P2P domain registrations with consensus status</li>
|
||||
<li><strong className="text-white">Host</strong> - Manage Holesail servers and clients, and subscribe to services from other domains</li>
|
||||
<li><strong className="text-white">Local DNS</strong> - Custom DNS records and conflict resolution</li>
|
||||
<li><strong className="text-white">Entries</strong> - View Autopass ledger entries</li>
|
||||
<li><strong className="text-white">Peers</strong> - Monitor connected peers</li>
|
||||
<li><strong className="text-white">Certificates</strong> - Manage TLS certificates</li>
|
||||
<li><strong className="text-white">Interfaces</strong> - View virtual network interfaces</li>
|
||||
<li><strong className="text-white">Backups</strong> - Create, restore, and manage system backups</li>
|
||||
<li><strong className="text-white">Diagnostics</strong> - DNS lookup, ping, traceroute, connection tests, invite RPC diagnostics</li>
|
||||
<li><strong className="text-white">Stats</strong> - Live metrics, Core RPC invite diagnostics, Plugin RPC protocol stats</li>
|
||||
<li><strong className="text-white">Logs</strong> - Tail split log files by channel (core, proxy, DNS, plugins, Holesail)</li>
|
||||
<li><strong className="text-white">Settings</strong> - Configure environment variables and subnets</li>
|
||||
<li><strong className="text-white">Plugins</strong> - Start/stop plugins, view logs, run actions with validated parameters</li>
|
||||
</ul>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Detailed Feature Descriptions</h2>
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">Detailed Feature Descriptions</h2>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4">Domains</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4">Domains</h3>
|
||||
<p className="text-mist mb-4">
|
||||
The Domains tab provides comprehensive management of P2P domain registrations:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<li><strong className="text-gray-900 dark:text-white">View all domains:</strong> See all registered domains in the network with their associated hashes</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Search functionality:</strong> Quickly find domains using the search bar</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Local indicator:</strong> Domains claimed locally are marked with a 🏠 icon</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Consensus status:</strong> Each domain displays a consensus status badge indicating its state:
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li><strong className="text-white">View all domains:</strong> See all registered domains in the network with their associated hashes</li>
|
||||
<li><strong className="text-white">Search functionality:</strong> Quickly find domains using the search bar</li>
|
||||
<li><strong className="text-white">Local indicator:</strong> Domains claimed locally are marked with a 🏠 icon</li>
|
||||
<li><strong className="text-white">Consensus status:</strong> Each domain displays a consensus status badge indicating its state:
|
||||
<ul className="list-disc pl-6 mt-2 space-y-1">
|
||||
<li><strong className="text-gray-900 dark:text-white">Internal:</strong> Domain is claimed locally</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Resolved:</strong> Consensus has been reached across the network</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Conflicted:</strong> Multiple claimants with equal votes</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Unknown:</strong> Consensus state not yet determined</li>
|
||||
<li><strong className="text-white">Internal:</strong> Domain is claimed locally</li>
|
||||
<li><strong className="text-white">Resolved:</strong> Consensus has been reached across the network</li>
|
||||
<li><strong className="text-white">Conflicted:</strong> Multiple claimants with equal votes</li>
|
||||
<li><strong className="text-white">Unknown:</strong> Consensus state not yet determined</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Vote information:</strong> View vote counts and quorum status for each domain</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Add domains:</strong> Register new domains by providing a domain name and Holesail hash</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Remove domains:</strong> Delete locally claimed domains (only local domains can be removed)</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Pagination:</strong> Navigate through large domain lists efficiently</li>
|
||||
<li><strong className="text-white">Vote information:</strong> View vote counts and quorum status for each domain</li>
|
||||
<li><strong className="text-white">Add domains:</strong> Register new domains by providing a domain name and Holesail hash</li>
|
||||
<li><strong className="text-white">Remove domains:</strong> Delete locally claimed domains (only local domains can be removed)</li>
|
||||
<li><strong className="text-white">Pagination:</strong> Navigate through large domain lists efficiently</li>
|
||||
</ul>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
<p className="text-mist mb-6">
|
||||
All changes are synchronized in real-time via WebSocket, so you'll see updates immediately as they occur. Consensus status is automatically calculated and displayed, helping you understand the network's agreement on domain ownership.
|
||||
</p>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Host</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">Host</h3>
|
||||
<p className="text-mist mb-4">
|
||||
The Host tab manages Holesail servers and clients for network tunneling:
|
||||
</p>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Holesail Servers</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<li><strong className="text-gray-900 dark:text-white">Create servers:</strong> Set up new Holesail servers with custom ports, hosts, and keys</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Configure options:</strong> Set name, port, host (default 0.0.0.0), key, secure/UDP flags, and log level</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Domain assignment:</strong> Optionally assign servers to specific domains</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Restart servers:</strong> Restart running servers without deleting them</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">View logs:</strong> Access real-time logs for each server in a terminal interface</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Delete servers:</strong> Remove servers and clean up resources</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Status monitoring:</strong> See server status (running/stopped) at a glance</li>
|
||||
<h4 className="text-xl font-semibold text-white mb-3">Holesail Servers</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li><strong className="text-white">Create servers:</strong> Set up new Holesail servers with custom ports, hosts, and keys</li>
|
||||
<li><strong className="text-white">Configure options:</strong> Set name, port, host (default 0.0.0.0), key, secure/UDP flags, and log level</li>
|
||||
<li><strong className="text-white">Domain assignment:</strong> Optionally assign servers to specific domains</li>
|
||||
<li><strong className="text-white">Restart servers:</strong> Restart running servers without deleting them</li>
|
||||
<li><strong className="text-white">View logs:</strong> Access real-time logs for each server in a terminal interface</li>
|
||||
<li><strong className="text-white">Delete servers:</strong> Remove servers and clean up resources</li>
|
||||
<li><strong className="text-white">Status monitoring:</strong> See server status (running/stopped) at a glance</li>
|
||||
</ul>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
Server configurations are persisted in <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">holesail_servers.json</code> and survive restarts.
|
||||
<p className="text-mist mb-4">
|
||||
Server configurations are persisted in <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">holesail_servers.json</code> and survive restarts.
|
||||
</p>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Holesail Clients</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<li><strong className="text-gray-900 dark:text-white">Create clients:</strong> Set up Holesail clients to connect to remote servers</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Domain selection:</strong> Choose which domain the client should connect for (only domains you own are shown)</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Service name:</strong> Optionally specify a service name for the client (format: <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">domain_servicename</code>)</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Protocol selection:</strong> Choose TCP or UDP protocol for the client</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Key and port:</strong> Configure connection key and local port</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Restart clients:</strong> Restart clients without deleting configuration</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">View logs:</strong> Monitor client connection logs in real-time</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Delete clients:</strong> Remove client configurations</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Status tracking:</strong> Monitor client connection status</li>
|
||||
<h4 className="text-xl font-semibold text-white mb-3">Holesail Clients</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li><strong className="text-white">Create clients:</strong> Set up Holesail clients to connect to remote servers</li>
|
||||
<li><strong className="text-white">Domain selection:</strong> Choose which domain the client should connect for (only domains you own are shown)</li>
|
||||
<li><strong className="text-white">Service name:</strong> Optionally specify a service name for the client (format: <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">domain_servicename</code>)</li>
|
||||
<li><strong className="text-white">Protocol selection:</strong> Choose TCP or UDP protocol for the client</li>
|
||||
<li><strong className="text-white">Key and port:</strong> Configure connection key and local port</li>
|
||||
<li><strong className="text-white">Restart clients:</strong> Restart clients without deleting configuration</li>
|
||||
<li><strong className="text-white">View logs:</strong> Monitor client connection logs in real-time</li>
|
||||
<li><strong className="text-white">Delete clients:</strong> Remove client configurations</li>
|
||||
<li><strong className="text-white">Status tracking:</strong> Monitor client connection status</li>
|
||||
</ul>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
Client configurations are persisted in <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">holesail_clients.json</code>. When a service name is provided, the client ID follows the format <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">domain_servicename</code> to avoid naming conflicts.
|
||||
<p className="text-mist mb-6">
|
||||
Client configurations are persisted in <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">holesail_clients.json</code>. When a service name is provided, the client ID follows the format <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">domain_servicename</code> to avoid naming conflicts.
|
||||
</p>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Service Subscriptions</h4>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h4 className="text-xl font-semibold text-white mb-3">Service Subscriptions</h4>
|
||||
<p className="text-mist mb-4">
|
||||
The Service Subscription feature allows you to automatically subscribe to services published by domain owners across the network. Access the Service Subscription modal via the "Service Subscription" button in the Host tab.
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<li><strong className="text-gray-900 dark:text-white">Browse domains:</strong> View all domains in the network with their available services</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Search functionality:</strong> Quickly find domains by name</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Individual subscriptions:</strong> Subscribe to specific services from any domain</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Subscribe All:</strong> Enable automatic subscription to all services for a domain, including newly added ones</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Auto-subscription on bootup:</strong> All subscribed services automatically create Holesail clients when the system starts (unless <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">DISABLE_AUTO_SUBSCRIPTION</code> is enabled)</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Dynamic synchronization:</strong> The system automatically:
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li><strong className="text-white">Browse domains:</strong> View all domains in the network with their available services</li>
|
||||
<li><strong className="text-white">Search functionality:</strong> Quickly find domains by name</li>
|
||||
<li><strong className="text-white">Individual subscriptions:</strong> Subscribe to specific services from any domain</li>
|
||||
<li><strong className="text-white">Subscribe All:</strong> Enable automatic subscription to all services for a domain, including newly added ones</li>
|
||||
<li><strong className="text-white">Auto-subscription on bootup:</strong> All subscribed services automatically create Holesail clients when the system starts (unless <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">DISABLE_AUTO_SUBSCRIPTION</code> is enabled)</li>
|
||||
<li><strong className="text-white">Dynamic synchronization:</strong> The system automatically:
|
||||
<ul className="list-disc pl-6 mt-2 space-y-1">
|
||||
<li>Unsubscribes from services when they are removed by the domain owner</li>
|
||||
<li>Subscribes to new services when they are added, if "subscribe all" is enabled for that domain</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Protocol support:</strong> Services support both TCP and UDP protocols</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Service naming:</strong> Subscribed services use the naming format <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">domain_servicename</code> for easy identification</li>
|
||||
<li><strong className="text-white">Protocol support:</strong> Services support both TCP and UDP protocols</li>
|
||||
<li><strong className="text-white">Service naming:</strong> Subscribed services use the naming format <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">domain_servicename</code> for easy identification</li>
|
||||
</ul>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
Subscriptions are stored in <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">cache/subscriptions.json</code> and persist across restarts. The system monitors claim record changes to automatically synchronize subscriptions when domain owners add or remove services.
|
||||
<p className="text-mist mb-6">
|
||||
Subscriptions are stored in <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">cache/subscriptions.json</code> and persist across restarts. The system monitors claim record changes to automatically synchronize subscriptions when domain owners add or remove services.
|
||||
</p>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Local DNS</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">Local DNS</h3>
|
||||
<p className="text-mist mb-4">
|
||||
The Local DNS tab allows you to manage custom DNS records and resolve conflicts between P2P and public DNS:
|
||||
</p>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Custom DNS Records</h4>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h4 className="text-xl font-semibold text-white mb-3">Custom DNS Records</h4>
|
||||
<p className="text-mist mb-4">
|
||||
Create and manage custom DNS records for any domain. Supported record types include:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<li><strong className="text-gray-900 dark:text-white">A</strong> - IPv4 address records</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">AAAA</strong> - IPv6 address records</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">CNAME</strong> - Canonical name records</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">MX</strong> - Mail exchange records</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">TXT</strong> - Text records</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">SRV</strong> - Service records</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">SOA</strong> - Start of authority records</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">CAA</strong> - Certificate authority authorization</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">NS</strong> - Name server records</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">PTR</strong> - Pointer records</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">OTHER</strong> - Other record types</li>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li><strong className="text-white">A</strong> - IPv4 address records</li>
|
||||
<li><strong className="text-white">AAAA</strong> - IPv6 address records</li>
|
||||
<li><strong className="text-white">CNAME</strong> - Canonical name records</li>
|
||||
<li><strong className="text-white">MX</strong> - Mail exchange records</li>
|
||||
<li><strong className="text-white">TXT</strong> - Text records</li>
|
||||
<li><strong className="text-white">SRV</strong> - Service records</li>
|
||||
<li><strong className="text-white">SOA</strong> - Start of authority records</li>
|
||||
<li><strong className="text-white">CAA</strong> - Certificate authority authorization</li>
|
||||
<li><strong className="text-white">NS</strong> - Name server records</li>
|
||||
<li><strong className="text-white">PTR</strong> - Pointer records</li>
|
||||
<li><strong className="text-white">OTHER</strong> - Other record types</li>
|
||||
</ul>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
Each record can be edited or deleted, and all changes are persisted to <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">local_dns.json</code>.
|
||||
<p className="text-mist mb-4">
|
||||
Each record can be edited or deleted, and all changes are persisted to <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">local_dns.json</code>.
|
||||
</p>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">DNS Conflict Selector</h4>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
<h4 className="text-xl font-semibold text-white mb-3">DNS Conflict Selector</h4>
|
||||
<p className="text-mist mb-6">
|
||||
When a domain exists in both the P2P network and public DNS, the DNS Conflict Selector allows you to choose
|
||||
which version to use. You can set preferences for each conflicting domain, and your choices are saved in
|
||||
<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">selector_cache.json</code> for persistence across restarts.
|
||||
<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">selector_cache.json</code> for persistence across restarts.
|
||||
</p>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Entries</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">Entries</h3>
|
||||
<p className="text-mist mb-4">
|
||||
The Entries tab displays all Autopass ledger entries, which represent domain claims and votes in the P2P network:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-6">
|
||||
<li><strong className="text-gray-900 dark:text-white">View all entries:</strong> Browse all claims and votes in the distributed ledger</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Search functionality:</strong> Search entries by key or value</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Pagination:</strong> Navigate through large entry lists</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Real-time updates:</strong> See new entries as they're added to the network</li>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-6">
|
||||
<li><strong className="text-white">View all entries:</strong> Browse all claims and votes in the distributed ledger</li>
|
||||
<li><strong className="text-white">Search functionality:</strong> Search entries by key or value</li>
|
||||
<li><strong className="text-white">Pagination:</strong> Navigate through large entry lists</li>
|
||||
<li><strong className="text-white">Real-time updates:</strong> See new entries as they're added to the network</li>
|
||||
</ul>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
<p className="text-mist mb-6">
|
||||
This view helps you understand the consensus state of the network and see how domain claims are being voted on.
|
||||
</p>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Peers</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">Peers</h3>
|
||||
<p className="text-mist mb-4">
|
||||
The Peers tab shows all currently connected peers in the P2P network:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-6">
|
||||
<li><strong className="text-gray-900 dark:text-white">Peer list:</strong> View all connected peers with their public keys</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Peer count:</strong> See the total number of connected peers</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Search:</strong> Find specific peers by public key</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Pagination:</strong> Navigate through peer lists</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Real-time updates:</strong> See peers connect and disconnect in real-time</li>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-6">
|
||||
<li><strong className="text-white">Peer list:</strong> View all connected peers with their public keys</li>
|
||||
<li><strong className="text-white">Peer count:</strong> See the total number of connected peers</li>
|
||||
<li><strong className="text-white">Search:</strong> Find specific peers by public key</li>
|
||||
<li><strong className="text-white">Pagination:</strong> Navigate through peer lists</li>
|
||||
<li><strong className="text-white">Real-time updates:</strong> See peers connect and disconnect in real-time</li>
|
||||
</ul>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Certificates</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">Certificates</h3>
|
||||
<p className="text-mist mb-4">
|
||||
The Certificates tab manages TLS certificates for secure HTTPS connections:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<li><strong className="text-gray-900 dark:text-white">Generate certificates:</strong> Create new certificates for any domain</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">View certificate details:</strong> Inspect certificate information including SANs and expiration</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Regenerate certificates:</strong> Create new certificates for existing domains</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Delete certificates:</strong> Remove certificates for domains</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Search functionality:</strong> Find certificates by domain name</li>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li><strong className="text-white">Generate certificates:</strong> Create new certificates for any domain</li>
|
||||
<li><strong className="text-white">View certificate details:</strong> Inspect certificate information including SANs and expiration</li>
|
||||
<li><strong className="text-white">Regenerate certificates:</strong> Create new certificates for existing domains</li>
|
||||
<li><strong className="text-white">Delete certificates:</strong> Remove certificates for domains</li>
|
||||
<li><strong className="text-white">Search functionality:</strong> Find certificates by domain name</li>
|
||||
</ul>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">CA Management</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-6">
|
||||
<li><strong className="text-gray-900 dark:text-white">Regenerate Root CA:</strong> Create a new root certificate authority</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Install Root CA:</strong> Install the root CA certificate in your system's trust store</li>
|
||||
<h4 className="text-xl font-semibold text-white mb-3">CA Management</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-6">
|
||||
<li><strong className="text-white">Regenerate Root CA:</strong> Create a new root certificate authority</li>
|
||||
<li><strong className="text-white">Install Root CA:</strong> Install the root CA certificate in your system's trust store</li>
|
||||
</ul>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
<p className="text-mist mb-6">
|
||||
The root CA is used to sign all domain certificates, ensuring secure connections to P2P domains.
|
||||
</p>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Interfaces</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">Interfaces</h3>
|
||||
<p className="text-mist mb-4">
|
||||
The Interfaces tab displays virtual network interface mappings:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<li><strong className="text-gray-900 dark:text-white">Domain-to-IP mappings:</strong> See which domains are assigned to which local IP addresses</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Search functionality:</strong> Find interfaces by domain or IP</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Cleanup:</strong> Remove unused virtual interfaces to free up IP addresses</li>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li><strong className="text-white">Domain-to-IP mappings:</strong> See which domains are assigned to which local IP addresses</li>
|
||||
<li><strong className="text-white">Search functionality:</strong> Find interfaces by domain or IP</li>
|
||||
<li><strong className="text-white">Cleanup:</strong> Remove unused virtual interfaces to free up IP addresses</li>
|
||||
</ul>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
<p className="text-mist mb-6">
|
||||
Virtual interfaces are automatically created when domains are added and are used for local routing.
|
||||
</p>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Backups</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">Backups</h3>
|
||||
<p className="text-mist mb-4">
|
||||
The Backups tab provides comprehensive backup and restore functionality for your P2NS node:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<li><strong className="text-gray-900 dark:text-white">Create backups:</strong> Manually create backups of all critical system files including domains, DNS records, Holesail configurations, certificates, and settings</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">View backup list:</strong> See all available backups with details including:
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li><strong className="text-white">Create backups:</strong> Manually create backups of all critical system files including domains, DNS records, Holesail configurations, certificates, and settings</li>
|
||||
<li><strong className="text-white">View backup list:</strong> See all available backups with details including:
|
||||
<ul className="list-disc pl-6 mt-2 space-y-1">
|
||||
<li>Backup name and timestamp</li>
|
||||
<li>Total size and file count</li>
|
||||
@@ -281,57 +281,57 @@ export default function AdminPanelPage() {
|
||||
<li>List of included files</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Restore from backup:</strong> Restore your system to a previous state by selecting a backup and confirming the restore operation</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Delete backups:</strong> Remove old backups to free up disk space</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Search functionality:</strong> Quickly find backups by name, timestamp, or version</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Pagination:</strong> Navigate through large backup lists efficiently</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Automatic backups:</strong> Configure automatic backup scheduling via the Settings tab (BACKUP_INTERVAL and BACKUP_RETENTION)</li>
|
||||
<li><strong className="text-white">Restore from backup:</strong> Restore your system to a previous state by selecting a backup and confirming the restore operation</li>
|
||||
<li><strong className="text-white">Delete backups:</strong> Remove old backups to free up disk space</li>
|
||||
<li><strong className="text-white">Search functionality:</strong> Quickly find backups by name, timestamp, or version</li>
|
||||
<li><strong className="text-white">Pagination:</strong> Navigate through large backup lists efficiently</li>
|
||||
<li><strong className="text-white">Automatic backups:</strong> Configure automatic backup scheduling via the Settings tab (BACKUP_INTERVAL and BACKUP_RETENTION)</li>
|
||||
</ul>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
Backups are stored in the directory specified by <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">BACKUP_DIR</code> (default: <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">./backups</code>). The system automatically manages backup retention, keeping only the most recent backups based on your configured retention count.
|
||||
<p className="text-mist mb-6">
|
||||
Backups are stored in the directory specified by <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">BACKUP_DIR</code> (default: <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">./backups</code>). The system automatically manages backup retention, keeping only the most recent backups based on your configured retention count.
|
||||
</p>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Logs</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
The Logs tab tails split log files written under <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">LOG_DIR</code> (default <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">./logs</code>):
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">Logs</h3>
|
||||
<p className="text-mist mb-4">
|
||||
The Logs tab tails split log files written under <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">LOG_DIR</code> (default <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">./logs</code>):
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<li><strong className="text-gray-900 dark:text-white">Channels:</strong> core, proxy, httpProxy, dns, plugins, holesail</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Channel filter:</strong> Select which subsystem to tail</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">WebSocket tail:</strong> <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">subscribe-log</code> / <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">file-log</code> / <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">log-snapshot</code></li>
|
||||
<li><strong className="text-gray-900 dark:text-white">REST:</strong> <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/logs</code> and <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/logs/:channel</code></li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Plugin logs:</strong> Per-plugin output also available via plugin-log WebSocket messages</li>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li><strong className="text-white">Channels:</strong> core, proxy, httpProxy, dns, plugins, holesail</li>
|
||||
<li><strong className="text-white">Channel filter:</strong> Select which subsystem to tail</li>
|
||||
<li><strong className="text-white">WebSocket tail:</strong> <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">subscribe-log</code> / <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">file-log</code> / <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">log-snapshot</code></li>
|
||||
<li><strong className="text-white">REST:</strong> <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">GET /api/logs</code> and <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">GET /api/logs/:channel</code></li>
|
||||
<li><strong className="text-white">Plugin logs:</strong> Per-plugin output also available via plugin-log WebSocket messages</li>
|
||||
</ul>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
Use the core channel when debugging invite RPC or consensus sidecar init issues. Check <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/consensus/status</code> for sidecar readiness (<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">bootstrapComplete</code>, <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">domainCount</code>).
|
||||
<p className="text-mist mb-6">
|
||||
Use the core channel when debugging invite RPC or consensus sidecar init issues. Check <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">GET /api/consensus/status</code> for sidecar readiness (<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">bootstrapComplete</code>, <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">domainCount</code>).
|
||||
</p>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Stats</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
The Stats tab loads an initial snapshot via <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/stats</code>, then receives live updates over WebSocket with <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">subscribe-stats</code> and <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">stats-snapshot</code> payloads:
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">Stats</h3>
|
||||
<p className="text-mist mb-4">
|
||||
The Stats tab loads an initial snapshot via <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">GET /api/stats</code>, then receives live updates over WebSocket with <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">subscribe-stats</code> and <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">stats-snapshot</code> payloads:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<li><strong className="text-gray-900 dark:text-white">Core RPC:</strong> Invite flow diagnostics — <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">networkId</code>, genesis vs secondary master, split-network warnings, <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">invite.request</code> / <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">invite.deliver</code></li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Plugin RPC:</strong> Protocol stats for plugin peer communication</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Hypercore stats:</strong> Optional holepunch stats when <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">ENABLE_HYPERCORE_STATS=true</code></li>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li><strong className="text-white">Core RPC:</strong> Invite flow diagnostics — <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">networkId</code>, genesis vs secondary master, split-network warnings, <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">invite.request</code> / <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">invite.deliver</code></li>
|
||||
<li><strong className="text-white">Plugin RPC:</strong> Protocol stats for plugin peer communication</li>
|
||||
<li><strong className="text-white">Hypercore stats:</strong> Optional holepunch stats when <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">ENABLE_HYPERCORE_STATS=true</code></li>
|
||||
</ul>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
Detailed invite diagnostics are also available via <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/diagnostics/invites</code> and the Diagnostics tab.
|
||||
<p className="text-mist mb-4">
|
||||
Detailed invite diagnostics are also available via <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">GET /api/diagnostics/invites</code> and the Diagnostics tab.
|
||||
</p>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<p className="text-mist mb-4">
|
||||
The Stats tab also provides comprehensive statistics and metrics about your P2NS node:
|
||||
</p>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">System Overview</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<li><strong className="text-gray-900 dark:text-white">System uptime:</strong> How long the node has been running</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Node type:</strong> Genesis master, secondary master, master (pending pass), or joiner</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Connected peers:</strong> Current number of connected peers</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Total domains:</strong> Number of registered domains</li>
|
||||
<h4 className="text-xl font-semibold text-white mb-3">System Overview</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li><strong className="text-white">System uptime:</strong> How long the node has been running</li>
|
||||
<li><strong className="text-white">Node type:</strong> Genesis master, secondary master, master (pending pass), or joiner</li>
|
||||
<li><strong className="text-white">Connected peers:</strong> Current number of connected peers</li>
|
||||
<li><strong className="text-white">Total domains:</strong> Number of registered domains</li>
|
||||
</ul>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">DNS Statistics</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h4 className="text-xl font-semibold text-white mb-3">DNS Statistics</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li>Total DNS queries and success rate</li>
|
||||
<li>Average response time</li>
|
||||
<li>P2P resolution rate</li>
|
||||
@@ -339,135 +339,135 @@ export default function AdminPanelPage() {
|
||||
<li>Top queried domains</li>
|
||||
</ul>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Network & Peers</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h4 className="text-xl font-semibold text-white mb-3">Network & Peers</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li>Peer connection events over time</li>
|
||||
<li>Total connections and average duration</li>
|
||||
</ul>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Holesail Statistics</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h4 className="text-xl font-semibold text-white mb-3">Holesail Statistics</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li>Active connections</li>
|
||||
<li>Servers and clients started</li>
|
||||
<li>Average connection duration</li>
|
||||
<li>Protocol usage (TCP/UDP)</li>
|
||||
</ul>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">API & Requests</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h4 className="text-xl font-semibold text-white mb-3">API & Requests</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li>Total API requests and success rate</li>
|
||||
<li>Average response time</li>
|
||||
<li>Failed requests</li>
|
||||
<li>Endpoint usage patterns</li>
|
||||
</ul>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Resource Usage</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h4 className="text-xl font-semibold text-white mb-3">Resource Usage</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li>Active sockets, servers, and connections</li>
|
||||
<li>Memory usage (heap, RSS, external)</li>
|
||||
<li>CPU usage and load average</li>
|
||||
<li>Event loop performance</li>
|
||||
</ul>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Domain Management</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-6">
|
||||
<h4 className="text-xl font-semibold text-white mb-3">Domain Management</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-6">
|
||||
<li>Domains added and removed</li>
|
||||
<li>Net change over time</li>
|
||||
</ul>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
<p className="text-mist mb-6">
|
||||
Charts update live via WebSocket. You can adjust the time range to focus on specific periods.
|
||||
</p>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Plugins</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">Plugins</h3>
|
||||
<p className="text-mist mb-4">
|
||||
The Plugins tab manages built-in and custom plugin sites:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-6">
|
||||
<li><strong className="text-gray-900 dark:text-white">Start/stop:</strong> Enable or disable individual plugins</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Plugin logs:</strong> View per-plugin application logs</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Actions with params:</strong> Run plugin admin actions; parameters are validated before execution via a modal</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Master note:</strong> file.drop is disabled on master nodes (<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">disable_on_master</code>)</li>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-6">
|
||||
<li><strong className="text-white">Start/stop:</strong> Enable or disable individual plugins</li>
|
||||
<li><strong className="text-white">Plugin logs:</strong> View per-plugin application logs</li>
|
||||
<li><strong className="text-white">Actions with params:</strong> Run plugin admin actions; parameters are validated before execution via a modal</li>
|
||||
<li><strong className="text-white">Master note:</strong> file.drop is disabled on master nodes (<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">disable_on_master</code>)</li>
|
||||
</ul>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Network Diagnostics</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">Network Diagnostics</h3>
|
||||
<p className="text-mist mb-4">
|
||||
The Diagnostics tab provides network troubleshooting tools and Core invite RPC diagnostics (aligned with the Stats Core section):
|
||||
</p>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">DNS Lookup</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h4 className="text-xl font-semibold text-white mb-3">DNS Lookup</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li>Perform DNS lookups for any domain</li>
|
||||
<li>Select record type (A, AAAA, MX, TXT, CNAME, etc.)</li>
|
||||
<li>View detailed DNS response information</li>
|
||||
<li>Test both P2P and public DNS resolution</li>
|
||||
</ul>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Ping</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h4 className="text-xl font-semibold text-white mb-3">Ping</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li>Ping any host or IP address</li>
|
||||
<li>Configure ping count (number of packets)</li>
|
||||
<li>View round-trip time statistics</li>
|
||||
<li>Check network connectivity and latency</li>
|
||||
</ul>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Traceroute</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h4 className="text-xl font-semibold text-white mb-3">Traceroute</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li>Trace the network path to a destination</li>
|
||||
<li>View each hop along the route</li>
|
||||
<li>Identify network bottlenecks or routing issues</li>
|
||||
<li>See response times for each hop</li>
|
||||
</ul>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Port Connectivity</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h4 className="text-xl font-semibold text-white mb-3">Port Connectivity</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li>Test connectivity to specific ports on remote hosts</li>
|
||||
<li>Verify service availability</li>
|
||||
<li>Check firewall rules and port accessibility</li>
|
||||
</ul>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Network Interfaces</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h4 className="text-xl font-semibold text-white mb-3">Network Interfaces</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li>View all network interfaces on the system</li>
|
||||
<li>See IP addresses, netmasks, and status</li>
|
||||
<li>Monitor interface statistics</li>
|
||||
</ul>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Invite & network identity</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<li>Run <strong>Invite diagnostics</strong> from the Diagnostics tab (or <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/diagnostics/invites</code>)</li>
|
||||
<h4 className="text-xl font-semibold text-white mb-3">Invite & network identity</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li>Run <strong>Invite diagnostics</strong> from the Diagnostics tab (or <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">GET /api/diagnostics/invites</code>)</li>
|
||||
<li><strong>Network ID</strong> — should match across all peers on the same network</li>
|
||||
<li><strong>Split-network warnings</strong> — peers report a different <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">networkId</code> (often from accidental second genesis or old split-brain)</li>
|
||||
<li><strong>Secondary master pending</strong> — master waiting for invite before <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">dnsPass</code> is ready</li>
|
||||
<li><strong>Split-network warnings</strong> — peers report a different <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">networkId</code> (often from accidental second genesis or old split-brain)</li>
|
||||
<li><strong>Secondary master pending</strong> — master waiting for invite before <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">dnsPass</code> is ready</li>
|
||||
</ul>
|
||||
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
<p className="text-mist mb-6">
|
||||
All diagnostic results are displayed in real-time with detailed output. Results are saved in a history that you can review, making it easy to compare results over time or troubleshoot intermittent issues.
|
||||
</p>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Settings</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">Settings</h3>
|
||||
<p className="text-mist mb-4">
|
||||
The Settings tab provides comprehensive configuration management for your P2NS node. All settings are organized by category for easy navigation:
|
||||
</p>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Settings Categories</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<li><strong className="text-gray-900 dark:text-white">Storage & Files:</strong> Configure file paths for domains, DNS records, Holesail configurations, certificates, and backups</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Network & Ports:</strong> Set DNS, HTTP, HTTPS, and internal ports, plus port check timeouts</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Network Configuration:</strong> Configure virtual interface subnets and IP allocation</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Holesail:</strong> Configure Holesail client timeouts and persistence modes</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Security & Access:</strong> Control feature flags for DNS server, proxy server, virtual interfaces, and writer invites</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Logging & Debugging:</strong> Adjust log verbosity levels</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Performance:</strong> Configure rate limiting, DNS pool size, and metrics collection</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Advanced:</strong> Configure P2P network settings, consensus parameters, and internal domains</li>
|
||||
<h4 className="text-xl font-semibold text-white mb-3">Settings Categories</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li><strong className="text-white">Storage & Files:</strong> Configure file paths for domains, DNS records, Holesail configurations, certificates, and backups</li>
|
||||
<li><strong className="text-white">Network & Ports:</strong> Set DNS, HTTP, HTTPS, and internal ports, plus port check timeouts</li>
|
||||
<li><strong className="text-white">Network Configuration:</strong> Configure virtual interface subnets and IP allocation</li>
|
||||
<li><strong className="text-white">Holesail:</strong> Configure Holesail client timeouts and persistence modes</li>
|
||||
<li><strong className="text-white">Security & Access:</strong> Control feature flags for DNS server, proxy server, virtual interfaces, and writer invites</li>
|
||||
<li><strong className="text-white">Logging & Debugging:</strong> Adjust log verbosity levels</li>
|
||||
<li><strong className="text-white">Performance:</strong> Configure rate limiting, DNS pool size, and metrics collection</li>
|
||||
<li><strong className="text-white">Advanced:</strong> Configure P2P network settings, consensus parameters, and internal domains</li>
|
||||
</ul>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Subnet Configuration</h4>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h4 className="text-xl font-semibold text-white mb-3">Subnet Configuration</h4>
|
||||
<p className="text-mist mb-4">
|
||||
The Settings tab includes a dedicated Subnet Configuration section for managing virtual network interfaces:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<li><strong className="text-gray-900 dark:text-white">View all subnets:</strong> See all configured subnets with their base IP, CIDR notation, start index, and name</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Add subnets:</strong> Create new subnet configurations by specifying:
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li><strong className="text-white">View all subnets:</strong> See all configured subnets with their base IP, CIDR notation, start index, and name</li>
|
||||
<li><strong className="text-white">Add subnets:</strong> Create new subnet configurations by specifying:
|
||||
<ul className="list-disc pl-6 mt-2 space-y-1">
|
||||
<li>Base IP address (network address)</li>
|
||||
<li>CIDR prefix (1-32)</li>
|
||||
@@ -475,21 +475,21 @@ export default function AdminPanelPage() {
|
||||
<li>Optional name for identification</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Edit subnets:</strong> Modify existing subnet configurations</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Delete subnets:</strong> Remove subnet configurations (only if no IPs are in use)</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">IP capacity estimator:</strong> View total available IPs, used IPs, and remaining capacity across all subnets</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Usage statistics:</strong> See how many IPs are available, used, and remaining for each subnet</li>
|
||||
<li><strong className="text-white">Edit subnets:</strong> Modify existing subnet configurations</li>
|
||||
<li><strong className="text-white">Delete subnets:</strong> Remove subnet configurations (only if no IPs are in use)</li>
|
||||
<li><strong className="text-white">IP capacity estimator:</strong> View total available IPs, used IPs, and remaining capacity across all subnets</li>
|
||||
<li><strong className="text-white">Usage statistics:</strong> See how many IPs are available, used, and remaining for each subnet</li>
|
||||
</ul>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<p className="text-mist mb-4">
|
||||
Subnets allow you to manage multiple IP ranges for virtual interfaces, providing flexibility for complex network configurations. The system automatically allocates IPs from available subnets when domains are added.
|
||||
</p>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Live-Reloadable vs Restart-Required Settings</h4>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h4 className="text-xl font-semibold text-white mb-3">Live-Reloadable vs Restart-Required Settings</h4>
|
||||
<p className="text-mist mb-4">
|
||||
Settings are categorized by whether they can be applied immediately or require a restart:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<li><strong className="text-gray-900 dark:text-white">Live-reloadable settings:</strong> These take effect immediately after saving:
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li><strong className="text-white">Live-reloadable settings:</strong> These take effect immediately after saving:
|
||||
<ul className="list-disc pl-6 mt-2 space-y-1">
|
||||
<li>Log level (LOG_LEVEL)</li>
|
||||
<li>Rate limiting (RATE_LIMIT_MAX_REQUESTS, RATE_LIMIT_WINDOW_MS)</li>
|
||||
@@ -500,7 +500,7 @@ export default function AdminPanelPage() {
|
||||
<li>Feature flags (ALLOW_ANY_WRITER_INVITES, FULL_PERSISTENCE)</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Restart-required settings:</strong> These require a node restart to take effect:
|
||||
<li><strong className="text-white">Restart-required settings:</strong> These require a node restart to take effect:
|
||||
<ul className="list-disc pl-6 mt-2 space-y-1">
|
||||
<li>Port configurations (DNS_PORT, HTTPS_PORT, HTTP_PORT, INTERNAL_PORT)</li>
|
||||
<li>File paths (STORAGE_DIR, DOMAINS_FILE, etc.)</li>
|
||||
@@ -511,65 +511,65 @@ export default function AdminPanelPage() {
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<p className="text-mist mb-4">
|
||||
The interface will indicate which settings require a restart. When you save restart-required settings, you'll be notified that a restart is needed for the changes to take effect.
|
||||
</p>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Settings Management Features</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<li><strong className="text-gray-900 dark:text-white">View all settings:</strong> See all current environment variable values organized by category</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Edit values:</strong> Modify settings with appropriate input types (text, number, checkbox, select dropdown)</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Search functionality:</strong> Quickly find specific settings by name or description</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Settings metadata:</strong> Each setting includes a description, default value, and validation rules</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Save changes:</strong> Persist modifications to <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">.env</code> file</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Validation:</strong> Settings are validated before saving to prevent invalid configurations</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Category filtering:</strong> Filter settings by category for easier navigation</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Storage clean:</strong> Reset Corestore and plugin HyperDB storage (same scope as <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--clean</code> on the CLI)</li>
|
||||
<h4 className="text-xl font-semibold text-white mb-3">Settings Management Features</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li><strong className="text-white">View all settings:</strong> See all current environment variable values organized by category</li>
|
||||
<li><strong className="text-white">Edit values:</strong> Modify settings with appropriate input types (text, number, checkbox, select dropdown)</li>
|
||||
<li><strong className="text-white">Search functionality:</strong> Quickly find specific settings by name or description</li>
|
||||
<li><strong className="text-white">Settings metadata:</strong> Each setting includes a description, default value, and validation rules</li>
|
||||
<li><strong className="text-white">Save changes:</strong> Persist modifications to <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">.env</code> file</li>
|
||||
<li><strong className="text-white">Validation:</strong> Settings are validated before saving to prevent invalid configurations</li>
|
||||
<li><strong className="text-white">Category filtering:</strong> Filter settings by category for easier navigation</li>
|
||||
<li><strong className="text-white">Storage clean:</strong> Reset Corestore and plugin HyperDB storage (same scope as <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--clean</code> on the CLI)</li>
|
||||
</ul>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
All settings changes are saved to your <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">.env</code> file. Live-reloadable settings take effect immediately, while restart-required settings will be applied on the next node restart.
|
||||
<p className="text-mist mb-6">
|
||||
All settings changes are saved to your <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">.env</code> file. Live-reloadable settings take effect immediately, while restart-required settings will be applied on the next node restart.
|
||||
</p>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Real-time Updates</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">Real-time Updates</h2>
|
||||
<p className="text-mist mb-4">
|
||||
The admin panel uses WebSocket connections to provide real-time updates across all tabs:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<li><strong className="text-gray-900 dark:text-white">Automatic refresh:</strong> Data updates automatically when changes occur</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Live logs:</strong> Per-channel log tail via WebSocket</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Live stats:</strong> Metrics and Core/Plugin RPC sections update via subscribe-stats</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Peer updates:</strong> See peers connect and disconnect immediately</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Domain changes:</strong> New domain registrations appear instantly</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Status indicators:</strong> Connection status shown in the top-right corner</li>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li><strong className="text-white">Automatic refresh:</strong> Data updates automatically when changes occur</li>
|
||||
<li><strong className="text-white">Live logs:</strong> Per-channel log tail via WebSocket</li>
|
||||
<li><strong className="text-white">Live stats:</strong> Metrics and Core/Plugin RPC sections update via subscribe-stats</li>
|
||||
<li><strong className="text-white">Peer updates:</strong> See peers connect and disconnect immediately</li>
|
||||
<li><strong className="text-white">Domain changes:</strong> New domain registrations appear instantly</li>
|
||||
<li><strong className="text-white">Status indicators:</strong> Connection status shown in the top-right corner</li>
|
||||
</ul>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
<p className="text-mist mb-6">
|
||||
The WebSocket connection automatically reconnects if interrupted, ensuring you always have the latest information.
|
||||
</p>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Tips and Best Practices</h2>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<li><strong className="text-gray-900 dark:text-white">Monitor logs regularly:</strong> Check the Logs tab to catch issues early</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Use Stats for optimization:</strong> Review statistics to identify performance bottlenecks</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Clean up interfaces:</strong> Periodically clean unused virtual interfaces to free resources</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Manage certificates:</strong> Regenerate certificates if you encounter SSL errors</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Use backups for disaster recovery:</strong> Create regular backups using the Backups tab, especially before making major configuration changes. Configure automatic backups via Settings (BACKUP_INTERVAL) and set appropriate retention (BACKUP_RETENTION) to balance disk space and recovery options</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Monitor consensus status:</strong> Check consensus badges in the Domains tab to understand network agreement on domain ownership. Use <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/consensus/status</code> or the <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">domain.consensus</code> plugin overview for sidecar health</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Use diagnostics for troubleshooting:</strong> When experiencing connectivity issues, use the Network Diagnostics tools to test DNS resolution, ping hosts, trace routes, and check port connectivity. This helps isolate network problems quickly</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Manage subnet configurations:</strong> Use the Subnet Configuration section in Settings to efficiently manage IP allocation. Monitor IP capacity to ensure you have enough addresses for new domains. Consider adding multiple subnets for better organization</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Understand live-reloadable settings:</strong> Take advantage of settings that can be changed without restarting (like LOG_LEVEL) for quick adjustments. Remember that restart-required settings need a node restart to take effect</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Use search effectively:</strong> Most tabs have search functionality to quickly find specific items</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Check peer connections:</strong> Monitor the Peers tab to ensure network connectivity</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Review DNS conflicts:</strong> Use the DNS Conflict Selector to manage domains that exist in both P2P and public DNS</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Backup before major changes:</strong> Always create a backup before making significant configuration changes or updates, so you can easily restore if something goes wrong</li>
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">Tips and Best Practices</h2>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li><strong className="text-white">Monitor logs regularly:</strong> Check the Logs tab to catch issues early</li>
|
||||
<li><strong className="text-white">Use Stats for optimization:</strong> Review statistics to identify performance bottlenecks</li>
|
||||
<li><strong className="text-white">Clean up interfaces:</strong> Periodically clean unused virtual interfaces to free resources</li>
|
||||
<li><strong className="text-white">Manage certificates:</strong> Regenerate certificates if you encounter SSL errors</li>
|
||||
<li><strong className="text-white">Use backups for disaster recovery:</strong> Create regular backups using the Backups tab, especially before making major configuration changes. Configure automatic backups via Settings (BACKUP_INTERVAL) and set appropriate retention (BACKUP_RETENTION) to balance disk space and recovery options</li>
|
||||
<li><strong className="text-white">Monitor consensus status:</strong> Check consensus badges in the Domains tab to understand network agreement on domain ownership. Use <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">GET /api/consensus/status</code> or the <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">domain.consensus</code> plugin overview for sidecar health</li>
|
||||
<li><strong className="text-white">Use diagnostics for troubleshooting:</strong> When experiencing connectivity issues, use the Network Diagnostics tools to test DNS resolution, ping hosts, trace routes, and check port connectivity. This helps isolate network problems quickly</li>
|
||||
<li><strong className="text-white">Manage subnet configurations:</strong> Use the Subnet Configuration section in Settings to efficiently manage IP allocation. Monitor IP capacity to ensure you have enough addresses for new domains. Consider adding multiple subnets for better organization</li>
|
||||
<li><strong className="text-white">Understand live-reloadable settings:</strong> Take advantage of settings that can be changed without restarting (like LOG_LEVEL) for quick adjustments. Remember that restart-required settings need a node restart to take effect</li>
|
||||
<li><strong className="text-white">Use search effectively:</strong> Most tabs have search functionality to quickly find specific items</li>
|
||||
<li><strong className="text-white">Check peer connections:</strong> Monitor the Peers tab to ensure network connectivity</li>
|
||||
<li><strong className="text-white">Review DNS conflicts:</strong> Use the DNS Conflict Selector to manage domains that exist in both P2P and public DNS</li>
|
||||
<li><strong className="text-white">Backup before major changes:</strong> Always create a backup before making significant configuration changes or updates, so you can easily restore if something goes wrong</li>
|
||||
</ul>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">API Integration</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">API Integration</h2>
|
||||
<p className="text-mist mb-4">
|
||||
While the admin panel provides a user-friendly interface, all functionality is also available via the REST API
|
||||
for programmatic access. See the <a href="/docs/api" className="text-blue-600 dark:text-blue-400 hover:underline">API Reference</a> documentation
|
||||
for programmatic access. See the <a href="/docs/api" className="text-indigo-light hover:underline">API Reference</a> documentation
|
||||
for complete endpoint documentation.
|
||||
</p>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
<p className="text-mist mb-6">
|
||||
The admin panel itself uses these API endpoints, so you can build custom tools or integrate P2NS management
|
||||
into your own applications.
|
||||
</p>
|
||||
|
||||
+58
-58
@@ -26,26 +26,26 @@ export const metadata: Metadata = {
|
||||
export default function APIPage() {
|
||||
return (
|
||||
<div className="min-h-screen">
|
||||
<section className="py-20 bg-gradient-to-b from-blue-50 to-white dark:from-gray-900 dark:to-gray-800">
|
||||
<section className="py-20 bg-grid-fade border-b border-steel/40">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<h1 className="text-4xl sm:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
<h1 className="text-4xl sm:text-5xl font-bold text-white mb-6">
|
||||
API Reference
|
||||
</h1>
|
||||
<p className="text-xl text-gray-600 dark:text-gray-300">
|
||||
<p className="text-xl text-mist">
|
||||
Complete REST API and WebSocket documentation
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="py-20 bg-white dark:bg-gray-900">
|
||||
<section className="py-20 bg-midnight">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-8">
|
||||
<p className="text-mist mb-8">
|
||||
The P2NS Admin API provides comprehensive endpoints for managing the decentralized DNS system.
|
||||
All endpoints are accessible at <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">https://p2ns.admin</code>.
|
||||
All endpoints are accessible at <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">https://p2ns.admin</code>.
|
||||
</p>
|
||||
|
||||
<div className="bg-blue-50 dark:bg-blue-900 border-l-4 border-blue-500 p-4 rounded mb-8">
|
||||
<p className="text-blue-800 dark:text-blue-200">
|
||||
<div className="bg-indigo/10 border-l-4 border-indigo p-4 rounded mb-8">
|
||||
<p className="text-indigo-pale">
|
||||
<strong>Note:</strong> For complete API documentation including all endpoints, request/response formats,
|
||||
and WebSocket events, please refer to the{' '}
|
||||
<a
|
||||
@@ -60,82 +60,82 @@ export default function APIPage() {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6">Base URL</h2>
|
||||
<h2 className="text-3xl font-bold text-white mb-6">Base URL</h2>
|
||||
<CodeBlock code="https://p2ns.admin" />
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">WebSocket Endpoint</h2>
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">WebSocket Endpoint</h2>
|
||||
<CodeBlock code="wss://p2ns.admin/ws" />
|
||||
<p className="text-gray-600 dark:text-gray-300 mt-4">
|
||||
<p className="text-mist mt-4">
|
||||
The WebSocket connection provides real-time updates including split logs, live stats, database changes, peer updates,
|
||||
and system events.
|
||||
</p>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">WebSocket Messages</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
Common client messages (send as JSON with a <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">type</code> field):
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">WebSocket Messages</h2>
|
||||
<p className="text-mist mb-4">
|
||||
Common client messages (send as JSON with a <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">type</code> field):
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">subscribe-stats</code> / <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">unsubscribe-stats</code> / <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">request-stats-snapshot</code></li>
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">subscribe-log</code> — e.g. <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">{`{ "type": "subscribe-log", "channel": "dns", "lines": 500 }`}</code></li>
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">unsubscribe-log</code></li>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">subscribe-stats</code> / <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">unsubscribe-stats</code> / <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">request-stats-snapshot</code></li>
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">subscribe-log</code> — e.g. <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">{`{ "type": "subscribe-log", "channel": "dns", "lines": 500 }`}</code></li>
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">unsubscribe-log</code></li>
|
||||
</ul>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
Server messages include <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">stats-snapshot</code>, <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">log-snapshot</code>, <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">file-log</code>, and <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">plugin-log</code>.
|
||||
<p className="text-mist mb-4">
|
||||
Server messages include <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">stats-snapshot</code>, <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">log-snapshot</code>, <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">file-log</code>, and <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">plugin-log</code>.
|
||||
Log channels: core, proxy, httpProxy, dns, plugins, holesail.
|
||||
</p>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Key Endpoints</h2>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/consensus/status</code> - Consensus Autobase sidecar health (bootstrap, event counts)</li>
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/consensus/:domain</code> - Consensus state for a domain (vote counts, quorum, resolved hash)</li>
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/consensus/metrics</code> - Aggregate consensus metrics (includes embedded sidecar status)</li>
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">POST /api/consensus/recalculate</code> - Force consensus recalculation and auto-votes</li>
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/resolved-domains</code> - List all resolved domains with ownership and services</li>
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">POST /api/add-domain</code> - Add a new domain</li>
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">POST /api/remove-domain</code> - Remove a domain</li>
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/peers</code> - List connected peers</li>
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/status</code> - Get system status</li>
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/stats</code> - One-shot metrics snapshot (Stats tab initial load; live updates use WebSocket)</li>
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/logs</code> - List split log channels</li>
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/logs/:channel</code> - Tail a log channel</li>
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/diagnostics/invites</code> - Core invite RPC diagnostics</li>
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/local-dns</code> - Get local DNS records</li>
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/holesail-servers</code> - List Holesail servers</li>
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/holesail-clients</code> - List Holesail clients</li>
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">POST /api/holesail-client-create</code> - Create a Holesail client (supports serviceName and protocol)</li>
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">Key Endpoints</h2>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist">
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">GET /api/consensus/status</code> - Consensus Autobase sidecar health (bootstrap, event counts)</li>
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">GET /api/consensus/:domain</code> - Consensus state for a domain (vote counts, quorum, resolved hash)</li>
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">GET /api/consensus/metrics</code> - Aggregate consensus metrics (includes embedded sidecar status)</li>
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">POST /api/consensus/recalculate</code> - Force consensus recalculation and auto-votes</li>
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">GET /api/resolved-domains</code> - List all resolved domains with ownership and services</li>
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">POST /api/add-domain</code> - Add a new domain</li>
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">POST /api/remove-domain</code> - Remove a domain</li>
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">GET /api/peers</code> - List connected peers</li>
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">GET /api/status</code> - Get system status</li>
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">GET /api/stats</code> - One-shot metrics snapshot (Stats tab initial load; live updates use WebSocket)</li>
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">GET /api/logs</code> - List split log channels</li>
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">GET /api/logs/:channel</code> - Tail a log channel</li>
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">GET /api/diagnostics/invites</code> - Core invite RPC diagnostics</li>
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">GET /api/local-dns</code> - Get local DNS records</li>
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">GET /api/holesail-servers</code> - List Holesail servers</li>
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">GET /api/holesail-clients</code> - List Holesail clients</li>
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">POST /api/holesail-client-create</code> - Create a Holesail client (supports serviceName and protocol)</li>
|
||||
</ul>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Service Subscription Endpoints</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">Service Subscription Endpoints</h2>
|
||||
<p className="text-mist mb-4">
|
||||
The following endpoints manage service subscriptions, allowing you to automatically subscribe to services from domain owners across the network:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/domain-services?domain=<domain></code> - Get all services for a specific domain</li>
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/service-subscriptions</code> - List all service subscriptions</li>
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/subscribe-all-domains</code> - List domains with subscribe-all enabled</li>
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">POST /api/service-subscribe</code> - Subscribe to a specific service</li>
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">POST /api/service-unsubscribe</code> - Unsubscribe from a service</li>
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">POST /api/subscribe-all</code> - Enable subscribe-all for a domain</li>
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">POST /api/unsubscribe-all</code> - Disable subscribe-all for a domain</li>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist">
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">GET /api/domain-services?domain=<domain></code> - Get all services for a specific domain</li>
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">GET /api/service-subscriptions</code> - List all service subscriptions</li>
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">GET /api/subscribe-all-domains</code> - List domains with subscribe-all enabled</li>
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">POST /api/service-subscribe</code> - Subscribe to a specific service</li>
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">POST /api/service-unsubscribe</code> - Unsubscribe from a service</li>
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">POST /api/subscribe-all</code> - Enable subscribe-all for a domain</li>
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">POST /api/unsubscribe-all</code> - Disable subscribe-all for a domain</li>
|
||||
</ul>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Authentication</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300">
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">Authentication</h2>
|
||||
<p className="text-mist">
|
||||
The API does not require authentication since it's designed for local use. In production environments,
|
||||
you should restrict access to trusted networks or implement authentication.
|
||||
</p>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Response Format</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
Most endpoints return JSON responses. Success responses typically return <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">200</code>
|
||||
with the requested data or <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">"OK"</code> for successful operations.
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">Response Format</h2>
|
||||
<p className="text-mist mb-4">
|
||||
Most endpoints return JSON responses. Success responses typically return <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">200</code>
|
||||
with the requested data or <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">"OK"</code> for successful operations.
|
||||
Errors return appropriate HTTP status codes with error messages.
|
||||
</p>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">More Information</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300">
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">More Information</h2>
|
||||
<p className="text-mist">
|
||||
For detailed API documentation including all endpoints, parameters, response formats, and WebSocket message types,
|
||||
see the <a href="https://git.ssh.surf/snxraven/p2ns/src/branch/main/docs/RESTAPI.md" target="_blank" rel="noopener noreferrer" className="text-blue-600 dark:text-blue-400 hover:underline">full API documentation</a>.
|
||||
see the <a href="https://git.ssh.surf/snxraven/p2ns/src/branch/main/docs/RESTAPI.md" target="_blank" rel="noopener noreferrer" className="text-indigo-light hover:underline">full API documentation</a>.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -26,120 +26,120 @@ export const metadata: Metadata = {
|
||||
export default function ArchitecturePage() {
|
||||
return (
|
||||
<div className="min-h-screen">
|
||||
<section className="py-20 bg-gradient-to-b from-blue-50 to-white dark:from-gray-900 dark:to-gray-800">
|
||||
<section className="py-20 bg-grid-fade border-b border-steel/40">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<h1 className="text-4xl sm:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
<h1 className="text-4xl sm:text-5xl font-bold text-white mb-6">
|
||||
System Architecture
|
||||
</h1>
|
||||
<p className="text-xl text-gray-600 dark:text-gray-300">
|
||||
<p className="text-xl text-mist">
|
||||
Deep dive into P2NS components and design
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="py-20 bg-white dark:bg-gray-900">
|
||||
<section className="py-20 bg-midnight">
|
||||
<div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<ArchitectureDiagram />
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Core Components</h2>
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">Core Components</h2>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4">Corestore & Autopass (writes)</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4">Corestore & Autopass (writes)</h3>
|
||||
<p className="text-mist mb-4">
|
||||
Corestore provides decentralized, append-only storage for domain claims and votes. Autopass manages
|
||||
secure writer additions through an invitation system, ensuring only authorized peers can write to the ledger.
|
||||
Each claim/vote mutation dual-appends a typed event to the consensus Autobase sidecar.
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||
<li>Stores claims as <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">claim:domain:claimant</code></li>
|
||||
<li>Stores votes as <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">vote:domain:claimant:voter</code></li>
|
||||
<li><strong>Genesis master</strong> (<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--master --genesis</code>) creates Autopass and <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">cache/network.json</code></li>
|
||||
<li><strong>Secondary masters</strong> (<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--master</code> on empty storage) pair via invite into the same ledger</li>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist">
|
||||
<li>Stores claims as <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">claim:domain:claimant</code></li>
|
||||
<li>Stores votes as <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">vote:domain:claimant:voter</code></li>
|
||||
<li><strong>Genesis master</strong> (<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--master --genesis</code>) creates Autopass and <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">cache/network.json</code></li>
|
||||
<li><strong>Secondary masters</strong> (<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--master</code> on empty storage) pair via invite into the same ledger</li>
|
||||
<li>Joiners request invites to become writers via Core RPC (not a legacy invite channel)</li>
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">core.status</code> exposes <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">networkId</code> for split-network detection</li>
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">core.status</code> exposes <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">networkId</code> for split-network detection</li>
|
||||
</ul>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Autobase Consensus Sidecar (reads)</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
Domain resolution reads from a dedicated Autobase apply view (<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">p2ns-consensus</code> Corestore namespace)—not a per-query scan of Autopass entries.
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">Autobase Consensus Sidecar (reads)</h3>
|
||||
<p className="text-mist mb-4">
|
||||
Domain resolution reads from a dedicated Autobase apply view (<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">p2ns-consensus</code> Corestore namespace)—not a per-query scan of Autopass entries.
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||
<li>Sidecar init runs in the background after Autopass pairing (<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">startConsensusForNetwork</code>)</li>
|
||||
<li>Genesis bootstraps by replaying dnsPass claim/vote entries; manifest stores <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">consensusAutobaseKey</code></li>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist">
|
||||
<li>Sidecar init runs in the background after Autopass pairing (<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">startConsensusForNetwork</code>)</li>
|
||||
<li>Genesis bootstraps by replaying dnsPass claim/vote entries; manifest stores <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">consensusAutobaseKey</code></li>
|
||||
<li>Joiners replicate the sidecar over swarm connections; read-only nodes hydrate from local dnsPass when needed</li>
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/consensus/status</code> reports sidecar health and bootstrap progress</li>
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">GET /api/consensus/status</code> reports sidecar health and bootstrap progress</li>
|
||||
</ul>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Core RPC Control Plane</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">Core RPC Control Plane</h3>
|
||||
<p className="text-mist mb-4">
|
||||
Core invite and consensus traffic uses protomux RPC on the p2ns swarm connection:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">invite.request</code>, <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">invite.deliver</code>, <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">invite.ack</code></li>
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">core.status</code> for remote peer diagnostics</li>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist">
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">invite.request</code>, <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">invite.deliver</code>, <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">invite.ack</code></li>
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">core.status</code> for remote peer diagnostics</li>
|
||||
<li>Consensus RPC methods for domain operations across peers</li>
|
||||
</ul>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Plugin System</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
Internal domains are discovered from <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">plugin-sites/{domain}/config.json</code>.
|
||||
Plugin peer communication uses protomux RPC only (<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">sdk.channels.register</code>).
|
||||
Plugin HyperDB data can use shared Corestore namespaces (<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">USE_SHARED_CORESTORE_NAMESPACES</code>).
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">Plugin System</h3>
|
||||
<p className="text-mist mb-4">
|
||||
Internal domains are discovered from <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">plugin-sites/{domain}/config.json</code>.
|
||||
Plugin peer communication uses protomux RPC only (<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">sdk.channels.register</code>).
|
||||
Plugin HyperDB data can use shared Corestore namespaces (<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">USE_SHARED_CORESTORE_NAMESPACES</code>).
|
||||
</p>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Split Logging</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
Subsystem logs are written to separate files under <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">LOG_DIR</code>:
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">Split Logging</h3>
|
||||
<p className="text-mist mb-4">
|
||||
Subsystem logs are written to separate files under <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">LOG_DIR</code>:
|
||||
core, proxy, http-proxy, dns, plugins, and holesail. The admin Logs tab tails these via WebSocket.
|
||||
</p>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Hyperswarm</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
Hyperswarm handles peer discovery on HyperDHT using a 32-byte topic derived from <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">sha256(TOPIC_SEED)</code> (default seed <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">p2ns-dns</code>).
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">Hyperswarm</h3>
|
||||
<p className="text-mist mb-4">
|
||||
Hyperswarm handles peer discovery on HyperDHT using a 32-byte topic derived from <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">sha256(TOPIC_SEED)</code> (default seed <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">p2ns-dns</code>).
|
||||
All peers interested in P2NS join this topic and discover each other without a central directory.
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist">
|
||||
<li>Automatic peer discovery</li>
|
||||
<li>Handles peer churn (peers joining/leaving)</li>
|
||||
<li>No central directory server required</li>
|
||||
<li>Resilient to network partitions</li>
|
||||
</ul>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">DNS Handler</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">DNS Handler</h3>
|
||||
<p className="text-mist mb-4">
|
||||
The DNS handler runs a UDP server on port 53 (configurable) that resolves domains through multiple mechanisms:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist">
|
||||
<li><strong>P2P Resolution:</strong> Reads the Autobase consensus sidecar apply view for domain claims</li>
|
||||
<li><strong>Local DNS:</strong> Checks local_dns.json for custom records</li>
|
||||
<li><strong>Public DNS Fallback:</strong> Forwards to public DNS servers for non-P2P domains</li>
|
||||
<li><strong>Conflict Resolution:</strong> Uses selector_cache.json preferences when domains exist in both P2P and public DNS</li>
|
||||
</ul>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Proxy Server</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">Proxy Server</h3>
|
||||
<p className="text-mist mb-4">
|
||||
The proxy server handles HTTP/HTTPS traffic routing:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist">
|
||||
<li><strong>HTTPS (port 443):</strong> Routes to local IPs via Holesail or public IPs based on DNS preferences</li>
|
||||
<li><strong>HTTP (port 80):</strong> Redirects to HTTPS per domain</li>
|
||||
<li><strong>TLS Termination:</strong> Per-domain TLS servers with SNI support</li>
|
||||
<li><strong>WebSocket Support:</strong> Handles WebSocket upgrades for real-time applications</li>
|
||||
</ul>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Holesail Integration</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">Holesail Integration</h3>
|
||||
<p className="text-mist mb-4">
|
||||
Holesail provides UDP hole-punching for P2P tunneling:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist">
|
||||
<li><strong>Servers:</strong> Persistent servers that can be assigned to domains</li>
|
||||
<li><strong>Clients:</strong> Created lazily when domains are accessed, timeout after inactivity</li>
|
||||
<li><strong>Configuration:</strong> Stored in holesail_servers.json and holesail_clients.json</li>
|
||||
<li><strong>Management:</strong> Full control through admin interface with log viewing</li>
|
||||
</ul>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Data Flow</h2>
|
||||
<ol className="list-decimal pl-6 space-y-3 text-gray-600 dark:text-gray-300">
|
||||
<li>User queries a domain via DNS (e.g., <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">dig @127.0.0.1 example.tld</code>)</li>
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">Data Flow</h2>
|
||||
<ol className="list-decimal pl-6 space-y-3 text-mist">
|
||||
<li>User queries a domain via DNS (e.g., <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">dig @127.0.0.1 example.tld</code>)</li>
|
||||
<li>DNS handler checks local_dns.json, then the consensus sidecar for P2P claims, then public DNS</li>
|
||||
<li>If P2P domain, assigns local IP and creates Holesail client if needed</li>
|
||||
<li>User accesses domain via HTTPS proxy</li>
|
||||
@@ -147,56 +147,56 @@ export default function ArchitecturePage() {
|
||||
<li>Response is returned through the tunnel and back to the user</li>
|
||||
</ol>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Consensus Mechanism</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">Consensus Mechanism</h2>
|
||||
<p className="text-mist mb-4">
|
||||
P2NS uses a quorum-based voting system for domain claims. Autopass KV is the durable write store; resolution reads the Autobase sidecar apply view (see{' '}
|
||||
<a href="https://git.ssh.surf/snxraven/p2ns/src/branch/main/docs/rfcs/0001-autobase-consensus.md" target="_blank" rel="noopener noreferrer" className="text-blue-600 dark:text-blue-400 hover:underline">RFC 0001</a>):
|
||||
<a href="https://git.ssh.surf/snxraven/p2ns/src/branch/main/docs/rfcs/0001-autobase-consensus.md" target="_blank" rel="noopener noreferrer" className="text-indigo-light hover:underline">RFC 0001</a>):
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist">
|
||||
<li>When a domain is claimed, peers vote on the claim</li>
|
||||
<li>Local claims are automatically voted for by the claiming peer</li>
|
||||
<li>Quorum uses peers with initialized <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">dnsPass</code> (from <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">core.status</code>), not raw Hyperswarm connection count</li>
|
||||
<li>Quorum uses peers with initialized <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">dnsPass</code> (from <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">core.status</code>), not raw Hyperswarm connection count</li>
|
||||
<li>Ties are broken by configured policy (timestamp, local writer preference, etc.)</li>
|
||||
<li>This prevents domain hijacking and ensures network integrity</li>
|
||||
</ul>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Network Roles (Multi-Master, One Ledger)</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
Every node on a network shares the same Autopass <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">dnsPass</code>.
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">Network Roles (Multi-Master, One Ledger)</h2>
|
||||
<p className="text-mist mb-6">
|
||||
Every node on a network shares the same Autopass <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">dnsPass</code>.
|
||||
Role flags control bootstrap and operations—not separate ledgers per master.
|
||||
</p>
|
||||
<div className="grid md:grid-cols-3 gap-6">
|
||||
<div className="bg-gray-50 dark:bg-gray-800 p-6 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Genesis Master</h3>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 text-sm">
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--master --genesis</code> once per network</li>
|
||||
<li>Creates Autopass and writes <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">cache/network.json</code></li>
|
||||
<li>Loads <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">domains.json</code> by default</li>
|
||||
<div className="bg-deep p-6 rounded-lg border border-steel">
|
||||
<h3 className="text-xl font-semibold text-white mb-3">Genesis Master</h3>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist text-sm">
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--master --genesis</code> once per network</li>
|
||||
<li>Creates Autopass and writes <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">cache/network.json</code></li>
|
||||
<li>Loads <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">domains.json</code> by default</li>
|
||||
<li>Issues invites; proactive reconnect policy</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="bg-gray-50 dark:bg-gray-800 p-6 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Secondary Master</h3>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 text-sm">
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--master</code> without <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--genesis</code></li>
|
||||
<div className="bg-deep p-6 rounded-lg border border-steel">
|
||||
<h3 className="text-xl font-semibold text-white mb-3">Secondary Master</h3>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist text-sm">
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--master</code> without <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--genesis</code></li>
|
||||
<li>Empty storage pairs via invite (no new ledger)</li>
|
||||
<li>Same invite/reconnect behavior after pairing</li>
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">MASTER_LOAD_DOMAINS=true</code> to import domains.json</li>
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">MASTER_LOAD_DOMAINS=true</code> to import domains.json</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="bg-gray-50 dark:bg-gray-800 p-6 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Joiner</h3>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 text-sm">
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">node p2ns.js</code> — default for participants</li>
|
||||
<div className="bg-deep p-6 rounded-lg border border-steel">
|
||||
<h3 className="text-xl font-semibold text-white mb-3">Joiner</h3>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist text-sm">
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">node p2ns.js</code> — default for participants</li>
|
||||
<li>Requests invite from master or writer peer</li>
|
||||
<li>Becomes a writer after pairing; can vote on claims</li>
|
||||
<li>May issue invites if <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">ALLOW_ANY_WRITER_INVITES=true</code></li>
|
||||
<li>May issue invites if <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">ALLOW_ANY_WRITER_INVITES=true</code></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-gray-600 dark:text-gray-300 mt-6 text-sm">
|
||||
Use a unique <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">TOPIC_SEED</code> per deployment.
|
||||
Admin diagnostics compare <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">networkId</code> across peers to detect split networks.
|
||||
<p className="text-mist mt-6 text-sm">
|
||||
Use a unique <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">TOPIC_SEED</code> per deployment.
|
||||
Admin diagnostics compare <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">networkId</code> across peers to detect split networks.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
+272
-272
@@ -26,515 +26,515 @@ export const metadata: Metadata = {
|
||||
export default function ConfigurationPage() {
|
||||
return (
|
||||
<div className="min-h-screen">
|
||||
<section className="py-20 bg-gradient-to-b from-blue-50 to-white dark:from-gray-900 dark:to-gray-800">
|
||||
<section className="py-20 bg-grid-fade border-b border-steel/40">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<h1 className="text-4xl sm:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
<h1 className="text-4xl sm:text-5xl font-bold text-white mb-6">
|
||||
Configuration
|
||||
</h1>
|
||||
<p className="text-xl text-gray-600 dark:text-gray-300">
|
||||
<p className="text-xl text-mist">
|
||||
Customize P2NS to fit your needs
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="py-20 bg-white dark:bg-gray-900">
|
||||
<section className="py-20 bg-midnight">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6">Environment Variables</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
Configure P2NS via a <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">.env</code> file (copy from <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">default.env</code>):
|
||||
<h2 className="text-3xl font-bold text-white mb-6">Environment Variables</h2>
|
||||
<p className="text-mist mb-6">
|
||||
Configure P2NS via a <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">.env</code> file (copy from <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">default.env</code>):
|
||||
</p>
|
||||
|
||||
<div className="space-y-8">
|
||||
<div>
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">Storage & Files</h3>
|
||||
<table className="w-full border-collapse bg-white dark:bg-gray-900">
|
||||
<h3 className="text-xl font-semibold text-white mb-2">Storage & Files</h3>
|
||||
<table className="w-full border-collapse bg-midnight">
|
||||
<thead>
|
||||
<tr className="bg-gray-100 dark:bg-gray-800">
|
||||
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Variable</th>
|
||||
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Default</th>
|
||||
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Description</th>
|
||||
<tr className="bg-surface">
|
||||
<th className="px-4 py-2 text-left border border-steel text-white font-semibold">Variable</th>
|
||||
<th className="px-4 py-2 text-left border border-steel text-white font-semibold">Default</th>
|
||||
<th className="px-4 py-2 text-left border border-steel text-white font-semibold">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">STORAGE_DIR</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">./my-storage</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Directory for Corestore data storage</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">STORAGE_DIR</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">./my-storage</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Directory for Corestore data storage</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">DOMAINS_FILE</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">cache/domains.json</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Path to domains JSON file</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">DOMAINS_FILE</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">cache/domains.json</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Path to domains JSON file</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">LOCAL_DNS_FILE</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">cache/local_dns.json</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Path to local DNS records file</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">LOCAL_DNS_FILE</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">cache/local_dns.json</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Path to local DNS records file</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">HOLESAIL_SERVERS_FILE</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">cache/holesail_servers.json</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Path to Holesail servers configuration file</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">HOLESAIL_SERVERS_FILE</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">cache/holesail_servers.json</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Path to Holesail servers configuration file</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">HOLESAIL_CLIENTS_FILE</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">cache/holesail_clients.json</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Path to Holesail clients configuration file</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">HOLESAIL_CLIENTS_FILE</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">cache/holesail_clients.json</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Path to Holesail clients configuration file</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">SELECTOR_CACHE_FILE</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">cache/selector_cache.json</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Path to DNS version preferences cache file</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">SELECTOR_CACHE_FILE</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">cache/selector_cache.json</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Path to DNS version preferences cache file</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">SUBSCRIPTIONS_FILE</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">cache/subscriptions.json</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Path to service subscriptions storage file</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">SUBSCRIPTIONS_FILE</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">cache/subscriptions.json</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Path to service subscriptions storage file</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">PEER_HISTORY_FILE</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">cache/peer_history.json</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Path to peer connection history file</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">PEER_HISTORY_FILE</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">cache/peer_history.json</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Path to peer connection history file</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">CERTS_DIR</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">./certs</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Directory for storing certificates</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">CERTS_DIR</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">./certs</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Directory for storing certificates</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">BACKUP_DIR</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">./backups</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Directory for storing backup files</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">BACKUP_DIR</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">./backups</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Directory for storing backup files</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">BACKUP_RETENTION</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">25</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Maximum number of backups to keep. Older backups will be automatically deleted.</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">BACKUP_RETENTION</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">25</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Maximum number of backups to keep. Older backups will be automatically deleted.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">BACKUP_INTERVAL</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">720</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Automatic backup interval in minutes (default: 720 = 12 hours)</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">BACKUP_INTERVAL</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">720</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Automatic backup interval in minutes (default: 720 = 12 hours)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">Network & Ports</h3>
|
||||
<table className="w-full border-collapse bg-white dark:bg-gray-900">
|
||||
<h3 className="text-xl font-semibold text-white mb-2">Network & Ports</h3>
|
||||
<table className="w-full border-collapse bg-midnight">
|
||||
<thead>
|
||||
<tr className="bg-gray-100 dark:bg-gray-800">
|
||||
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Variable</th>
|
||||
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Default</th>
|
||||
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Description</th>
|
||||
<tr className="bg-surface">
|
||||
<th className="px-4 py-2 text-left border border-steel text-white font-semibold">Variable</th>
|
||||
<th className="px-4 py-2 text-left border border-steel text-white font-semibold">Default</th>
|
||||
<th className="px-4 py-2 text-left border border-steel text-white font-semibold">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">DNS_PORT</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">53</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Port for the DNS server (requires sudo)</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">DNS_PORT</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">53</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Port for the DNS server (requires sudo)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">HTTPS_PORT</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">443</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Port for HTTPS proxy server (requires sudo)</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">HTTPS_PORT</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">443</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Port for HTTPS proxy server (requires sudo)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">HTTP_PORT</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">80</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Port for HTTP redirect server (requires sudo)</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">HTTP_PORT</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">80</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Port for HTTP redirect server (requires sudo)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">INTERNAL_PORT</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">8080</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Port used by Holesail clients for tunneling</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">INTERNAL_PORT</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">8080</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Port used by Holesail clients for tunneling</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">PORT_CHECK_TIMEOUT</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">2</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Timeout in seconds for port availability checks</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">PORT_CHECK_TIMEOUT</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">2</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Timeout in seconds for port availability checks</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">PUBLIC_DNS_SERVER</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">1.1.1.1</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Public DNS server(s) for fallback resolution (comma-separated for failover)</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">PUBLIC_DNS_SERVER</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">1.1.1.1</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Public DNS server(s) for fallback resolution (comma-separated for failover)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">Hyperswarm & P2P</h3>
|
||||
<table className="w-full border-collapse bg-white dark:bg-gray-900">
|
||||
<h3 className="text-xl font-semibold text-white mb-2">Hyperswarm & P2P</h3>
|
||||
<table className="w-full border-collapse bg-midnight">
|
||||
<thead>
|
||||
<tr className="bg-gray-100 dark:bg-gray-800">
|
||||
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Variable</th>
|
||||
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Default</th>
|
||||
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Description</th>
|
||||
<tr className="bg-surface">
|
||||
<th className="px-4 py-2 text-left border border-steel text-white font-semibold">Variable</th>
|
||||
<th className="px-4 py-2 text-left border border-steel text-white font-semibold">Default</th>
|
||||
<th className="px-4 py-2 text-left border border-steel text-white font-semibold">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">MAX_PEERS</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">24</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Maximum number of Hyperswarm peer connections</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">MAX_PEERS</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">24</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Maximum number of Hyperswarm peer connections</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">SWARM_CONNECTION_TIMEOUT</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">30000</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Swarm connection timeout in milliseconds</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">SWARM_CONNECTION_TIMEOUT</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">30000</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Swarm connection timeout in milliseconds</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">SWARM_KEEPALIVE_INTERVAL</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">60000</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Interval in ms to rejoin the swarm topic (0 to disable)</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">SWARM_KEEPALIVE_INTERVAL</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">60000</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Interval in ms to rejoin the swarm topic (0 to disable)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">CHANNEL_KEEPALIVE_INTERVAL</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">30000</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Plugin channel heartbeat interval in ms (0 to disable)</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">CHANNEL_KEEPALIVE_INTERVAL</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">30000</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Plugin channel heartbeat interval in ms (0 to disable)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">CHANNEL_KEEPALIVE_TIMEOUT</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">10000</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Time in ms before a stale plugin channel is recreated</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">CHANNEL_KEEPALIVE_TIMEOUT</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">10000</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Time in ms before a stale plugin channel is recreated</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">TOPIC_SEED</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">p2ns-dns</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Seed for generating Hyperswarm discovery topic</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">TOPIC_SEED</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">p2ns-dns</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Seed for generating Hyperswarm discovery topic</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">NETWORK_MANIFEST_FILE</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">cache/network.json</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Network identity manifest (written by genesis master)</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">NETWORK_MANIFEST_FILE</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">cache/network.json</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Network identity manifest (written by genesis master)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">P2NS_GENESIS</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200">(unset)</td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Alternative to <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--genesis</code> — create network Autopass</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">P2NS_GENESIS</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">(unset)</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Alternative to <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--genesis</code> — create network Autopass</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">MASTER_LOAD_DOMAINS</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">false</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Secondary masters: import <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">domains.json</code> (genesis loads by default)</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">MASTER_LOAD_DOMAINS</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">false</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Secondary masters: import <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">domains.json</code> (genesis loads by default)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">MASTER_INVITE_ONLY</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">false</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">If true, only master nodes may issue invites</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">MASTER_INVITE_ONLY</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">false</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">If true, only master nodes may issue invites</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">Network Configuration</h3>
|
||||
<table className="w-full border-collapse bg-white dark:bg-gray-900">
|
||||
<h3 className="text-xl font-semibold text-white mb-2">Network Configuration</h3>
|
||||
<table className="w-full border-collapse bg-midnight">
|
||||
<thead>
|
||||
<tr className="bg-gray-100 dark:bg-gray-800">
|
||||
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Variable</th>
|
||||
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Default</th>
|
||||
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Description</th>
|
||||
<tr className="bg-surface">
|
||||
<th className="px-4 py-2 text-left border border-steel text-white font-semibold">Variable</th>
|
||||
<th className="px-4 py-2 text-left border border-steel text-white font-semibold">Default</th>
|
||||
<th className="px-4 py-2 text-left border border-steel text-white font-semibold">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">SUBNET_BASE</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">192.168.3.</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">IP subnet base for virtual interfaces (legacy, for backward compatibility)</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">SUBNET_BASE</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">192.168.3.</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">IP subnet base for virtual interfaces (legacy, for backward compatibility)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">SUBNET_NAME</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">lo0</code> (macOS), <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">lo</code> (Linux)</td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Network interface name for virtual IPs</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">SUBNET_NAME</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">lo0</code> (macOS), <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">lo</code> (Linux)</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Network interface name for virtual IPs</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">INITIAL_IP_INDEX</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">2</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Starting IP index for virtual interfaces (legacy, for backward compatibility)</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">INITIAL_IP_INDEX</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">2</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Starting IP index for virtual interfaces (legacy, for backward compatibility)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">SUBNETS</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">[]</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">JSON array of subnet configurations. Each subnet has: base (IPv4 address), cidr (1-32), startIndex (1-254), and optional name. Use the Subnet Configuration section in Settings to manage this.</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">SUBNETS</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">[]</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">JSON array of subnet configurations. Each subnet has: base (IPv4 address), cidr (1-32), startIndex (1-254), and optional name. Use the Subnet Configuration section in Settings to manage this.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">Holesail</h3>
|
||||
<table className="w-full border-collapse bg-white dark:bg-gray-900">
|
||||
<h3 className="text-xl font-semibold text-white mb-2">Holesail</h3>
|
||||
<table className="w-full border-collapse bg-midnight">
|
||||
<thead>
|
||||
<tr className="bg-gray-100 dark:bg-gray-800">
|
||||
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Variable</th>
|
||||
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Default</th>
|
||||
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Description</th>
|
||||
<tr className="bg-surface">
|
||||
<th className="px-4 py-2 text-left border border-steel text-white font-semibold">Variable</th>
|
||||
<th className="px-4 py-2 text-left border border-steel text-white font-semibold">Default</th>
|
||||
<th className="px-4 py-2 text-left border border-steel text-white font-semibold">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">HOLESAIL_TIMEOUT</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">5</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Timeout in minutes for non-persistent Holesail clients</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">HOLESAIL_TIMEOUT</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">5</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Timeout in minutes for non-persistent Holesail clients</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">FULL_PERSISTENCE</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">false</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Enable full persistence mode - prevents shutdown/restart of holesail clients/servers (Not recommended for low ram devices)</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">FULL_PERSISTENCE</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">false</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Enable full persistence mode - prevents shutdown/restart of holesail clients/servers (Not recommended for low ram devices)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">Feature Flags</h3>
|
||||
<table className="w-full border-collapse bg-white dark:bg-gray-900">
|
||||
<h3 className="text-xl font-semibold text-white mb-2">Feature Flags</h3>
|
||||
<table className="w-full border-collapse bg-midnight">
|
||||
<thead>
|
||||
<tr className="bg-gray-100 dark:bg-gray-800">
|
||||
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Variable</th>
|
||||
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Default</th>
|
||||
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Description</th>
|
||||
<tr className="bg-surface">
|
||||
<th className="px-4 py-2 text-left border border-steel text-white font-semibold">Variable</th>
|
||||
<th className="px-4 py-2 text-left border border-steel text-white font-semibold">Default</th>
|
||||
<th className="px-4 py-2 text-left border border-steel text-white font-semibold">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">ALLOW_ANY_WRITER_INVITES</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">true</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Allow non-master nodes to issue invites</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">ALLOW_ANY_WRITER_INVITES</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">true</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Allow non-master nodes to issue invites</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">USE_SHARED_CORESTORE_NAMESPACES</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">true</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Use shared main Corestore namespaces for plugin DBs and drives (set false only for debugging)</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">USE_SHARED_CORESTORE_NAMESPACES</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">true</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Use shared main Corestore namespaces for plugin DBs and drives (set false only for debugging)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">ENABLE_HYPERCORE_STATS</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">true</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Collect hypercore/corestore stats for /api/stats (set false to disable)</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">ENABLE_HYPERCORE_STATS</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">true</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Collect hypercore/corestore stats for /api/stats (set false to disable)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">DISABLE_DNS_SERVER</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">false</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Disable the DNS server</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">DISABLE_DNS_SERVER</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">false</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Disable the DNS server</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">DISABLE_PROXY_SERVER</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">false</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Disable HTTPS and HTTP proxy servers</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">DISABLE_PROXY_SERVER</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">false</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Disable HTTPS and HTTP proxy servers</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">DISABLE_VIRTUAL_INTERFACES</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">false</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Disable virtual interface creation</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">DISABLE_VIRTUAL_INTERFACES</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">false</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Disable virtual interface creation</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">DISABLE_AUTO_SUBSCRIPTION</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">false</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Disable automatic starting of Holesail clients for subscribed services on bootup or when new services are detected</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">DISABLE_AUTO_SUBSCRIPTION</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">false</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Disable automatic starting of Holesail clients for subscribed services on bootup or when new services are detected</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">Logging & Debugging</h3>
|
||||
<table className="w-full border-collapse bg-white dark:bg-gray-900">
|
||||
<h3 className="text-xl font-semibold text-white mb-2">Logging & Debugging</h3>
|
||||
<table className="w-full border-collapse bg-midnight">
|
||||
<thead>
|
||||
<tr className="bg-gray-100 dark:bg-gray-800">
|
||||
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Variable</th>
|
||||
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Default</th>
|
||||
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Description</th>
|
||||
<tr className="bg-surface">
|
||||
<th className="px-4 py-2 text-left border border-steel text-white font-semibold">Variable</th>
|
||||
<th className="px-4 py-2 text-left border border-steel text-white font-semibold">Default</th>
|
||||
<th className="px-4 py-2 text-left border border-steel text-white font-semibold">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">LOG_LEVEL</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">1</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Logging verbosity level (0=DEBUG, 1=INFO, 2=WARN, 3=ERROR)</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">LOG_LEVEL</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">1</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Logging verbosity level (0=DEBUG, 1=INFO, 2=WARN, 3=ERROR)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">LOG_DIR</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">./logs</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Directory for split log files (core, proxy, http-proxy, dns, plugins, holesail)</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">LOG_DIR</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">./logs</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Directory for split log files (core, proxy, http-proxy, dns, plugins, holesail)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">LOG_BUFFER_LINES</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">2000</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">In-memory tail lines per channel for admin /api/logs and WebSocket tail</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">LOG_BUFFER_LINES</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">2000</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">In-memory tail lines per channel for admin /api/logs and WebSocket tail</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p className="text-gray-600 dark:text-gray-300 mt-2 text-sm">
|
||||
<p className="text-mist mt-2 text-sm">
|
||||
Protomux RPC is always enabled for core invite/consensus and plugin peer communication.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">Master Node</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-2 text-sm">
|
||||
<strong>Genesis</strong> (<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--master --genesis</code> or <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">P2NS_GENESIS=true</code>) creates the network once.
|
||||
<strong> Secondary masters</strong> use <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--master</code> / <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">P2NS_MASTER=true</code> without genesis and pair via invite.
|
||||
Network identity vars (<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">NETWORK_MANIFEST_FILE</code>, etc.) are listed under P2P Configuration above.
|
||||
<h3 className="text-xl font-semibold text-white mb-2">Master Node</h3>
|
||||
<p className="text-mist mb-2 text-sm">
|
||||
<strong>Genesis</strong> (<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--master --genesis</code> or <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">P2NS_GENESIS=true</code>) creates the network once.
|
||||
<strong> Secondary masters</strong> use <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--master</code> / <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">P2NS_MASTER=true</code> without genesis and pair via invite.
|
||||
Network identity vars (<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">NETWORK_MANIFEST_FILE</code>, etc.) are listed under P2P Configuration above.
|
||||
</p>
|
||||
<table className="w-full border-collapse bg-white dark:bg-gray-900">
|
||||
<table className="w-full border-collapse bg-midnight">
|
||||
<thead>
|
||||
<tr className="bg-gray-100 dark:bg-gray-800">
|
||||
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Variable</th>
|
||||
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Default</th>
|
||||
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Description</th>
|
||||
<tr className="bg-surface">
|
||||
<th className="px-4 py-2 text-left border border-steel text-white font-semibold">Variable</th>
|
||||
<th className="px-4 py-2 text-left border border-steel text-white font-semibold">Default</th>
|
||||
<th className="px-4 py-2 text-left border border-steel text-white font-semibold">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">P2NS_MASTER</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200">unset</td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Operational master (invites, reconnect). Pair with P2NS_GENESIS only for first network bootstrap</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">P2NS_MASTER</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">unset</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Operational master (invites, reconnect). Pair with P2NS_GENESIS only for first network bootstrap</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">P2NS_GENESIS</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200">unset</td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Alternative to <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--genesis</code> — create Autopass + manifest (once per network)</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">P2NS_GENESIS</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">unset</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Alternative to <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--genesis</code> — create Autopass + manifest (once per network)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">MASTER_RECONNECT_INTERVAL</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">5</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Base reconnection interval in seconds for disconnected peers</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">MASTER_RECONNECT_INTERVAL</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">5</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Base reconnection interval in seconds for disconnected peers</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">MASTER_MAX_RECONNECT_ATTEMPTS</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">10</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Maximum reconnection attempts per peer</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">MASTER_MAX_RECONNECT_ATTEMPTS</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">10</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Maximum reconnection attempts per peer</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">MASTER_PROACTIVE_INVITE_DELAY</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">2000</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Delay in ms before sending proactive invite to new peers</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">MASTER_PROACTIVE_INVITE_DELAY</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">2000</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Delay in ms before sending proactive invite to new peers</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">CREATE_INVITE_TIMEOUT_MS</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">20000</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Timeout for Autopass createInvite including member.flushed()</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">CREATE_INVITE_TIMEOUT_MS</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">20000</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Timeout for Autopass createInvite including member.flushed()</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">DNS_PASS_OP_GAP_MS</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">50</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Gap between serialized Autopass operations in ms</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">DNS_PASS_OP_GAP_MS</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">50</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Gap between serialized Autopass operations in ms</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p className="text-gray-600 dark:text-gray-300 mt-2 text-sm">
|
||||
Autopass replication uses its own swarm; <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">MASTER_REPLICATE_DELAY</code> is unused for dnsPass replication.
|
||||
<p className="text-mist mt-2 text-sm">
|
||||
Autopass replication uses its own swarm; <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">MASTER_REPLICATE_DELAY</code> is unused for dnsPass replication.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">Performance</h3>
|
||||
<table className="w-full border-collapse bg-white dark:bg-gray-900">
|
||||
<h3 className="text-xl font-semibold text-white mb-2">Performance</h3>
|
||||
<table className="w-full border-collapse bg-midnight">
|
||||
<thead>
|
||||
<tr className="bg-gray-100 dark:bg-gray-800">
|
||||
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Variable</th>
|
||||
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Default</th>
|
||||
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Description</th>
|
||||
<tr className="bg-surface">
|
||||
<th className="px-4 py-2 text-left border border-steel text-white font-semibold">Variable</th>
|
||||
<th className="px-4 py-2 text-left border border-steel text-white font-semibold">Default</th>
|
||||
<th className="px-4 py-2 text-left border border-steel text-white font-semibold">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">RATE_LIMIT_MAX_REQUESTS</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">100</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Maximum requests per window for rate limiting</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">RATE_LIMIT_MAX_REQUESTS</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">100</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Maximum requests per window for rate limiting</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">RATE_LIMIT_WINDOW_MS</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">60</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Time window in seconds for rate limiting (default: 60 = 1 minute)</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">RATE_LIMIT_WINDOW_MS</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">60</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Time window in seconds for rate limiting (default: 60 = 1 minute)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">DNS_POOL_SIZE</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">5</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Maximum number of DNS resolver connections in pool</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">DNS_POOL_SIZE</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">5</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Maximum number of DNS resolver connections in pool</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">METRICS_RETENTION_MS</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">60</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Metrics data retention period in minutes (default: 60 = 1 hour)</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">METRICS_RETENTION_MS</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">60</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Metrics data retention period in minutes (default: 60 = 1 hour)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">METRICS_SAMPLING_RATE</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">1.0</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Metrics sampling rate (0.0-1.0, default: 1.0 for all samples)</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">METRICS_SAMPLING_RATE</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">1.0</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Metrics sampling rate (0.0-1.0, default: 1.0 for all samples)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">METRICS_AGGREGATION_INTERVAL</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">60</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Metrics aggregation interval in seconds (default: 60 = 1 minute)</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">METRICS_AGGREGATION_INTERVAL</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">60</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Metrics aggregation interval in seconds (default: 60 = 1 minute)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">METRICS_MAX_BUFFER_SIZE</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">1000</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Maximum number of metric samples to buffer</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">METRICS_MAX_BUFFER_SIZE</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">1000</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Maximum number of metric samples to buffer</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">Advanced</h3>
|
||||
<table className="w-full border-collapse bg-white dark:bg-gray-900">
|
||||
<h3 className="text-xl font-semibold text-white mb-2">Advanced</h3>
|
||||
<table className="w-full border-collapse bg-midnight">
|
||||
<thead>
|
||||
<tr className="bg-gray-100 dark:bg-gray-800">
|
||||
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Variable</th>
|
||||
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Default</th>
|
||||
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Description</th>
|
||||
<tr className="bg-surface">
|
||||
<th className="px-4 py-2 text-left border border-steel text-white font-semibold">Variable</th>
|
||||
<th className="px-4 py-2 text-left border border-steel text-white font-semibold">Default</th>
|
||||
<th className="px-4 py-2 text-left border border-steel text-white font-semibold">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">INTERNAL_DOMAINS</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200">auto</td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Internal plugin domains are discovered from plugin-sites/{domain}/config.json. p2ns.admin is always internal. Optional comma-separated override.</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">INTERNAL_DOMAINS</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">auto</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Internal plugin domains are discovered from plugin-sites/{domain}/config.json. p2ns.admin is always internal. Optional comma-separated override.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">CONSENSUS_QUORUM_THRESHOLD</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">0.5</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Percentage of active peers that must vote to meet quorum (0.0-1.0). For example, 0.5 means 50% of peers must vote.</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">CONSENSUS_QUORUM_THRESHOLD</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">0.5</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Percentage of active peers that must vote to meet quorum (0.0-1.0). For example, 0.5 means 50% of peers must vote.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">CONSENSUS_MIN_VOTES</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">2</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Minimum number of votes required regardless of peer count. Ensures quorum even in small networks.</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">CONSENSUS_MIN_VOTES</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">2</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Minimum number of votes required regardless of peer count. Ensures quorum even in small networks.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">CONSENSUS_TIE_BREAKER</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">timestamp</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Strategy for breaking ties between claimants with equal votes. Options: timestamp (prefer oldest claim), claimant_age (prefer local writer among tied claimants, else lexicographic), lexicographic (prefer local writer, else alphabetical).</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">CONSENSUS_TIE_BREAKER</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">timestamp</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Strategy for breaking ties between claimants with equal votes. Options: timestamp (prefer oldest claim), claimant_age (prefer local writer among tied claimants, else lexicographic), lexicographic (prefer local writer, else alphabetical).</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">CONSENSUS_VOTE_VALIDATION</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">true</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Whether to validate that votes reference existing claims. Invalid votes are ignored when enabled.</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">CONSENSUS_VOTE_VALIDATION</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">true</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Whether to validate that votes reference existing claims. Invalid votes are ignored when enabled.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">CONSENSUS_IMMEDIATE_UPDATE</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">true</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Whether to trigger consensus recalculation immediately when claims or votes change. When false, waits for next periodic check.</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">CONSENSUS_IMMEDIATE_UPDATE</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">true</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Whether to trigger consensus recalculation immediately when claims or votes change. When false, waits for next periodic check.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">CONSENSUS_INIT_TIMEOUT_MS</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">30000</code></td>
|
||||
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Timeout for consensus Autobase sidecar ready/update during background init.</td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">CONSENSUS_INIT_TIMEOUT_MS</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist"><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">30000</code></td>
|
||||
<td className="px-4 py-2 border border-steel text-mist">Timeout for consensus Autobase sidecar ready/update during background init.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Example Configuration</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
See <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">default.env</code> in the repository for the full list. Abbreviated example:
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">Example Configuration</h2>
|
||||
<p className="text-mist mb-4">
|
||||
See <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">default.env</code> in the repository for the full list. Abbreviated example:
|
||||
</p>
|
||||
<CodeBlock code={`# Logging
|
||||
LOG_LEVEL=1
|
||||
|
||||
@@ -26,103 +26,103 @@ export const metadata: Metadata = {
|
||||
export default function GettingStartedPage() {
|
||||
return (
|
||||
<div className="min-h-screen">
|
||||
<section className="py-20 bg-gradient-to-b from-blue-50 to-white dark:from-gray-900 dark:to-gray-800">
|
||||
<section className="py-20 bg-grid-fade border-b border-steel/40">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<h1 className="text-4xl sm:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
<h1 className="text-4xl sm:text-5xl font-bold text-white mb-6">
|
||||
Getting Started
|
||||
</h1>
|
||||
<p className="text-xl text-gray-600 dark:text-gray-300">
|
||||
<p className="text-xl text-mist">
|
||||
Get P2NS up and running in minutes
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="py-20 bg-white dark:bg-gray-900">
|
||||
<section className="py-20 bg-midnight">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6">Prerequisites</h2>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||
<h2 className="text-3xl font-bold text-white mb-6">Prerequisites</h2>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist">
|
||||
<li><strong>Node.js:</strong> Version 18 or higher (tested up to 20.x)</li>
|
||||
<li><strong>Holesail CLI:</strong> For generating connection hashes (<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">npm install -g holesail</code>)</li>
|
||||
<li><strong>Holesail CLI:</strong> For generating connection hashes (<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">npm install -g holesail</code>)</li>
|
||||
<li><strong>Platform:</strong> macOS or Linux (sudo required for ports <1024 and interfaces). Windows support planned.</li>
|
||||
<li><strong>Dependencies:</strong> All dependencies are installed via npm</li>
|
||||
</ul>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Installation</h2>
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">Installation</h2>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4">1. Clone the Repository</h3>
|
||||
<h3 className="text-2xl font-semibold text-white mb-4">1. Clone the Repository</h3>
|
||||
<CodeBlock code={`git clone https://git.ssh.surf/snxraven/p2ns.git
|
||||
cd p2ns`} />
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">2. Install Dependencies</h3>
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">2. Install Dependencies</h3>
|
||||
<CodeBlock code="npm install" />
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">3. Configure Environment (Optional)</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">3. Configure Environment (Optional)</h3>
|
||||
<p className="text-mist mb-4">
|
||||
Copy the default environment file and customize as needed:
|
||||
</p>
|
||||
<CodeBlock code={`cp default.env .env
|
||||
# Edit .env with your preferred settings`} />
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Running the System</h2>
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">Running the System</h2>
|
||||
|
||||
<div className="bg-blue-50 dark:bg-blue-900/30 border-l-4 border-blue-500 p-4 rounded mb-8">
|
||||
<p className="text-blue-900 dark:text-blue-100 text-sm">
|
||||
<div className="bg-indigo/10 border-l-4 border-indigo p-4 rounded mb-8">
|
||||
<p className="text-indigo-pale text-sm">
|
||||
<strong>Who needs what:</strong> One operator runs <strong>genesis</strong> to bootstrap the network.
|
||||
Optional <strong>secondary masters</strong> improve invite uptime. Everyone else runs a <strong>joiner</strong> — no <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--master</code> flag required.
|
||||
All roles share one Autopass ledger on the same <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">TOPIC_SEED</code>.
|
||||
Optional <strong>secondary masters</strong> improve invite uptime. Everyone else runs a <strong>joiner</strong> — no <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--master</code> flag required.
|
||||
All roles share one Autopass ledger on the same <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">TOPIC_SEED</code>.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4">Genesis master (once per network)</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
Creates the shared Autopass ledger and <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">cache/network.json</code> manifest (including <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">consensusAutobaseKey</code> after sidecar bootstrap). Loads <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">domains.json</code> on first run:
|
||||
<h3 className="text-2xl font-semibold text-white mb-4">Genesis master (once per network)</h3>
|
||||
<p className="text-mist mb-4">
|
||||
Creates the shared Autopass ledger and <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">cache/network.json</code> manifest (including <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">consensusAutobaseKey</code> after sidecar bootstrap). Loads <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">domains.json</code> on first run:
|
||||
</p>
|
||||
<CodeBlock code="sudo node p2ns.js --master --genesis" />
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4 mt-4">
|
||||
Docker/PM2: <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">P2NS_MASTER=true</code> and{' '}
|
||||
<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">P2NS_GENESIS=true</code>.
|
||||
<p className="text-mist mb-4 mt-4">
|
||||
Docker/PM2: <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">P2NS_MASTER=true</code> and{' '}
|
||||
<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">P2NS_GENESIS=true</code>.
|
||||
</p>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Secondary master</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
Additional masters join the <strong>same</strong> network via invite (empty storage does not create a new ledger). Use the same <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">TOPIC_SEED</code> as genesis:
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">Secondary master</h3>
|
||||
<p className="text-mist mb-4">
|
||||
Additional masters join the <strong>same</strong> network via invite (empty storage does not create a new ledger). Use the same <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">TOPIC_SEED</code> as genesis:
|
||||
</p>
|
||||
<CodeBlock code="sudo node p2ns.js --master" />
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Joiner Node</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
The normal way to participate: connect on the same <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">TOPIC_SEED</code> as the network and receive an invite from a master or writer peer. Storage is reset on each boot unless you use <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--clean</code> explicitly.
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">Joiner Node</h3>
|
||||
<p className="text-mist mb-4">
|
||||
The normal way to participate: connect on the same <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">TOPIC_SEED</code> as the network and receive an invite from a master or writer peer. Storage is reset on each boot unless you use <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--clean</code> explicitly.
|
||||
</p>
|
||||
<CodeBlock code="sudo node p2ns.js" />
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Clean Storage</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">Clean Storage</h3>
|
||||
<p className="text-mist mb-4">
|
||||
Wipe Corestore and plugin database storage for a fresh start. Required after some upgrades and when invite or plugin DB issues persist:
|
||||
</p>
|
||||
<CodeBlock code="sudo node p2ns.js --clean [--master] [--genesis]" />
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4 mt-4">
|
||||
See the <a href="/docs/upgrading" className="text-blue-600 dark:text-blue-400 hover:underline">Upgrading</a> guide for coordinated network upgrades and when to use <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--clean</code>.
|
||||
<p className="text-mist mb-4 mt-4">
|
||||
See the <a href="/docs/upgrading" className="text-indigo-light hover:underline">Upgrading</a> guide for coordinated network upgrades and when to use <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--clean</code>.
|
||||
</p>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Adding Your First Domain</h2>
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">Adding Your First Domain</h2>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4">1. Generate a Holesail Hash</h3>
|
||||
<h3 className="text-2xl font-semibold text-white mb-4">1. Generate a Holesail Hash</h3>
|
||||
<CodeBlock code="holesail --live 80 --public" />
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4 mt-4">
|
||||
This will output a connection hash like: <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">hs://s00084bf87dfa89a3048fb081c0e6207eb5a</code>
|
||||
<p className="text-mist mb-4 mt-4">
|
||||
This will output a connection hash like: <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">hs://s00084bf87dfa89a3048fb081c0e6207eb5a</code>
|
||||
</p>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">2. Add the Domain</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">2. Add the Domain</h3>
|
||||
<p className="text-mist mb-4">
|
||||
You can add domains in several ways:
|
||||
</p>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Via Admin Interface</h4>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
Access <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">https://p2ns.admin</code> and use the Domains tab to add domains interactively.
|
||||
<h4 className="text-xl font-semibold text-white mb-3">Via Admin Interface</h4>
|
||||
<p className="text-mist mb-4">
|
||||
Access <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">https://p2ns.admin</code> and use the Domains tab to add domains interactively.
|
||||
</p>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Via domains.json</h4>
|
||||
<h4 className="text-xl font-semibold text-white mb-3">Via domains.json</h4>
|
||||
<CodeBlock code={`[
|
||||
{
|
||||
"domain": "example.tld",
|
||||
@@ -130,25 +130,25 @@ cd p2ns`} />
|
||||
}
|
||||
]`} language="json" />
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Accessing the Interfaces</h2>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||
<li><strong>Admin Interface:</strong> <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">https://p2ns.admin</code></li>
|
||||
<li><strong>Peer Directory:</strong> <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">https://peer.directory</code></li>
|
||||
<li><strong>Peer Paste:</strong> <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">https://peer.paste</code> — temporary E2EE text snippets</li>
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">Accessing the Interfaces</h2>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist">
|
||||
<li><strong>Admin Interface:</strong> <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">https://p2ns.admin</code></li>
|
||||
<li><strong>Peer Directory:</strong> <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">https://peer.directory</code></li>
|
||||
<li><strong>Peer Paste:</strong> <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">https://peer.paste</code> — temporary E2EE text snippets</li>
|
||||
</ul>
|
||||
<p className="text-gray-600 dark:text-gray-300 mt-4">
|
||||
More built-in plugins: <a href="/docs/plugins" className="text-blue-600 dark:text-blue-400 hover:underline">Built-in Plugins</a>.
|
||||
<p className="text-mist mt-4">
|
||||
More built-in plugins: <a href="/docs/plugins" className="text-indigo-light hover:underline">Built-in Plugins</a>.
|
||||
</p>
|
||||
<p className="text-gray-600 dark:text-gray-300 mt-4">
|
||||
<strong>Note:</strong> Trust the root CA in your browser. P2NS installs it automatically on macOS/Windows; on <strong>Linux</strong> you need both the system store and the NSS database for Chrome — see <a href="/docs/troubleshooting#certificate-authority-issues" className="text-blue-600 dark:text-blue-400 hover:underline">Troubleshooting</a> if HTTPS warnings persist.
|
||||
<p className="text-mist mt-4">
|
||||
<strong>Note:</strong> Trust the root CA in your browser. P2NS installs it automatically on macOS/Windows; on <strong>Linux</strong> you need both the system store and the NSS database for Chrome — see <a href="/docs/troubleshooting#certificate-authority-issues" className="text-indigo-light hover:underline">Troubleshooting</a> if HTTPS warnings persist.
|
||||
</p>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Next Steps</h2>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||
<li>Read the <a href="/docs/configuration" className="text-blue-600 dark:text-blue-400 hover:underline">Configuration</a> guide</li>
|
||||
<li>Review <a href="/docs/upgrading" className="text-blue-600 dark:text-blue-400 hover:underline">Upgrading</a> before updating an existing network</li>
|
||||
<li>Check out the <a href="/docs/api" className="text-blue-600 dark:text-blue-400 hover:underline">API Reference</a></li>
|
||||
<li>Learn about <a href="/learn/p2p" className="text-blue-600 dark:text-blue-400 hover:underline">How P2P Works</a></li>
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">Next Steps</h2>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist">
|
||||
<li>Read the <a href="/docs/configuration" className="text-indigo-light hover:underline">Configuration</a> guide</li>
|
||||
<li>Review <a href="/docs/upgrading" className="text-indigo-light hover:underline">Upgrading</a> before updating an existing network</li>
|
||||
<li>Check out the <a href="/docs/api" className="text-indigo-light hover:underline">API Reference</a></li>
|
||||
<li>Learn about <a href="/learn/p2p" className="text-indigo-light hover:underline">How P2P Works</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
+282
-282
@@ -27,507 +27,507 @@ export const metadata: Metadata = {
|
||||
export default function HowItWorksPage() {
|
||||
return (
|
||||
<div className="min-h-screen">
|
||||
<section className="py-20 bg-gradient-to-b from-blue-50 to-white dark:from-gray-900 dark:to-gray-800">
|
||||
<section className="py-20 bg-grid-fade border-b border-steel/40">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<h1 className="text-4xl sm:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
<h1 className="text-4xl sm:text-5xl font-bold text-white mb-6">
|
||||
How It Works
|
||||
</h1>
|
||||
<p className="text-xl text-gray-600 dark:text-gray-300">
|
||||
<p className="text-xl text-mist">
|
||||
Understanding the complete P2NS workflow from start to finish
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="py-20 bg-white dark:bg-gray-900">
|
||||
<section className="py-20 bg-midnight">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6">Introduction</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h2 className="text-3xl font-bold text-white mb-6">Introduction</h2>
|
||||
<p className="text-mist mb-4">
|
||||
P2NS (Peer-to-Peer Name System) is a decentralized DNS system that allows you to access services and websites
|
||||
without relying on traditional DNS servers or centralized infrastructure. Instead, it uses a peer-to-peer network
|
||||
where nodes work together to resolve domain names and establish direct connections.
|
||||
</p>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<p className="text-mist mb-4">
|
||||
Unlike traditional DNS where a central authority controls domain names, P2NS uses a distributed ledger where
|
||||
anyone can claim a domain and peers vote to reach consensus on which service should be associated with each domain.
|
||||
This makes it resistant to censorship and single points of failure.
|
||||
</p>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
<p className="text-mist mb-6">
|
||||
The system uses UDP hole-punching (via HyperDHT) to connect through firewalls and NAT, making it possible to
|
||||
reach services behind restrictive networks. Two P2P layers work together: <strong className="text-gray-900 dark:text-white">Hyperswarm</strong> on the
|
||||
P2NS topic syncs DNS claims and votes; <strong className="text-gray-900 dark:text-white">Holesail</strong> uses separate hashes on the DHT for each
|
||||
reach services behind restrictive networks. Two P2P layers work together: <strong className="text-white">Hyperswarm</strong> on the
|
||||
P2NS topic syncs DNS claims and votes; <strong className="text-white">Holesail</strong> uses separate hashes on the DHT for each
|
||||
published service tunnel. Let's walk through exactly how this works, step by step.
|
||||
</p>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">The Big Picture</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">The Big Picture</h2>
|
||||
<p className="text-mist mb-4">
|
||||
Here's a high-level view of what happens when you access a P2NS domain:
|
||||
</p>
|
||||
<div className="mb-6">
|
||||
<P2NSFlowDiagram />
|
||||
</div>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
The key components are: <strong className="text-gray-900 dark:text-white">peers</strong> (Hyperswarm + Corestore/Autopass for claim/vote writes and an Autobase consensus sidecar for resolution),
|
||||
<strong className="text-gray-900 dark:text-white"> protomux-rpc</strong> (core invites and plugin traffic),
|
||||
<strong className="text-gray-900 dark:text-white">Holesail</strong> (per-service tunnels),
|
||||
<strong className="text-gray-900 dark:text-white">virtual interfaces</strong> (local IPs per domain), and
|
||||
<strong className="text-gray-900 dark:text-white">HTTPS/HTTP proxies</strong> (TLS and routing). Built-in sites such as{' '}
|
||||
<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">p2ns.admin</code> and plugin domains under{' '}
|
||||
<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">plugin-sites/</code> are resolved without a P2P claim.
|
||||
<p className="text-mist mb-6">
|
||||
The key components are: <strong className="text-white">peers</strong> (Hyperswarm + Corestore/Autopass for claim/vote writes and an Autobase consensus sidecar for resolution),
|
||||
<strong className="text-white"> protomux-rpc</strong> (core invites and plugin traffic),
|
||||
<strong className="text-white">Holesail</strong> (per-service tunnels),
|
||||
<strong className="text-white">virtual interfaces</strong> (local IPs per domain), and
|
||||
<strong className="text-white">HTTPS/HTTP proxies</strong> (TLS and routing). Built-in sites such as{' '}
|
||||
<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">p2ns.admin</code> and plugin domains under{' '}
|
||||
<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">plugin-sites/</code> are resolved without a P2P claim.
|
||||
</p>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Step-by-Step Process</h2>
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">Step-by-Step Process</h2>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4">Part 1: Setting Up a Domain (Service Provider Side)</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4">Part 1: Setting Up a Domain (Service Provider Side)</h3>
|
||||
<p className="text-mist mb-4">
|
||||
Before anyone can access a service through P2NS, the service provider needs to register their domain. Here's how it works:
|
||||
</p>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">1. Generate a Holesail Hash</h4>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h4 className="text-xl font-semibold text-white mb-3">1. Generate a Holesail Hash</h4>
|
||||
<p className="text-mist mb-4">
|
||||
The service provider first needs to create a Holesail connection hash. They run:
|
||||
</p>
|
||||
<CodeBlock code="holesail --live 80 --public" />
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
Use <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--public</code> so the service is announced on HyperDHT for remote peers.
|
||||
This generates a hash like <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">hs://s00084bf87dfa89a3048fb081c0e6207eb5a</code>.
|
||||
<p className="text-mist mb-4">
|
||||
Use <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--public</code> so the service is announced on HyperDHT for remote peers.
|
||||
This generates a hash like <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">hs://s00084bf87dfa89a3048fb081c0e6207eb5a</code>.
|
||||
That hash is independent of the P2NS swarm topic—peers use it only when connecting to your service tunnel.
|
||||
</p>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">2. Create a Domain Claim</h4>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
Next, they register their domain (e.g., <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">example.tld</code>)
|
||||
<h4 className="text-xl font-semibold text-white mb-3">2. Create a Domain Claim</h4>
|
||||
<p className="text-mist mb-4">
|
||||
Next, they register their domain (e.g., <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">example.tld</code>)
|
||||
by creating a claim in the P2P network. This claim says "I own example.tld and it should point to this Holesail hash."
|
||||
Claims live in the shared <strong className="text-gray-900 dark:text-white">Autopass</strong> store (<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">dnsPass</code>) on top of Corestore—an append-only, signed log replicated across writers. Each claim/vote write also appends a typed event to the <strong className="text-gray-900 dark:text-white">consensus Autobase sidecar</strong>, which is the sole read path for domain resolution.
|
||||
Claims live in the shared <strong className="text-white">Autopass</strong> store (<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">dnsPass</code>) on top of Corestore—an append-only, signed log replicated across writers. Each claim/vote write also appends a typed event to the <strong className="text-white">consensus Autobase sidecar</strong>, which is the sole read path for domain resolution.
|
||||
</p>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
You can add domains via the admin UI (<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">https://p2ns.admin</code>),{' '}
|
||||
<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">cache/domains.json</code> (genesis master by default), or the API. On a <strong className="text-gray-900 dark:text-white">new</strong> network, exactly one node runs as{' '}
|
||||
<strong className="text-gray-900 dark:text-white">genesis master</strong> (<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--master --genesis</code>) to create the shared Autopass ledger and{' '}
|
||||
<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">cache/network.json</code>. Everyone else joins with <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">node p2ns.js</code> (joiner) or an optional secondary master (<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--master</code> without <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--genesis</code>) after receiving an invite.
|
||||
<p className="text-mist mb-4">
|
||||
You can add domains via the admin UI (<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">https://p2ns.admin</code>),{' '}
|
||||
<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">cache/domains.json</code> (genesis master by default), or the API. On a <strong className="text-white">new</strong> network, exactly one node runs as{' '}
|
||||
<strong className="text-white">genesis master</strong> (<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--master --genesis</code>) to create the shared Autopass ledger and{' '}
|
||||
<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">cache/network.json</code>. Everyone else joins with <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">node p2ns.js</code> (joiner) or an optional secondary master (<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--master</code> without <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--genesis</code>) after receiving an invite.
|
||||
</p>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
The claim is stored with a key like <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">claim:example.tld:claimant-id</code>
|
||||
where <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">claimant-id</code> is a unique identifier for the person making the claim.
|
||||
<p className="text-mist mb-4">
|
||||
The claim is stored with a key like <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">claim:example.tld:claimant-id</code>
|
||||
where <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">claimant-id</code> is a unique identifier for the person making the claim.
|
||||
</p>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">3. Peer Discovery and Sync</h4>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h4 className="text-xl font-semibold text-white mb-3">3. Peer Discovery and Sync</h4>
|
||||
<p className="text-mist mb-4">
|
||||
Once the claim is created, it's automatically synchronized to all connected peers in the network. Each peer maintains
|
||||
a copy of the distributed ledger, so the claim propagates throughout the network. This happens in real-time as peers
|
||||
connect and exchange data.
|
||||
</p>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
<p className="text-mist mb-6">
|
||||
If multiple people claim the same domain, the network uses a voting and consensus mechanism to decide which claim
|
||||
is legitimate (we'll cover this in detail later).
|
||||
</p>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Part 2: Peer Discovery and Network Formation</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">Part 2: Peer Discovery and Network Formation</h3>
|
||||
<p className="text-mist mb-4">
|
||||
For P2NS to work, nodes need to find and connect to each other. This happens automatically using a technology called Hyperswarm.
|
||||
</p>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">1. Topic-Based Discovery</h4>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h4 className="text-xl font-semibold text-white mb-3">1. Topic-Based Discovery</h4>
|
||||
<p className="text-mist mb-4">
|
||||
All P2NS nodes use the same "topic" to find each other. Think of it like a meeting room number - everyone who wants
|
||||
to participate in P2NS goes to the same room. The topic is a 32-byte buffer from <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">sha256(TOPIC_SEED)</code> (default <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">p2ns-dns</code>),
|
||||
to participate in P2NS goes to the same room. The topic is a 32-byte buffer from <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">sha256(TOPIC_SEED)</code> (default <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">p2ns-dns</code>),
|
||||
which ensures all P2NS nodes discover each other regardless of where they are in the world.
|
||||
</p>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">2. Connection Establishment</h4>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h4 className="text-xl font-semibold text-white mb-3">2. Connection Establishment</h4>
|
||||
<p className="text-mist mb-4">
|
||||
When a node starts up, it joins Hyperswarm on this topic. Under the hood, <strong>HyperDHT</strong> announces and
|
||||
looks up peers, coordinates UDP hole punching, and falls back to encrypted relays when needed. Each connection
|
||||
completes a Noise XX handshake before any application data flows.
|
||||
</p>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<p className="text-mist mb-4">
|
||||
The connection process involves:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li>Noise XX handshake proves each peer holds the advertised key</li>
|
||||
<li>Protomux multiplexes core RPC and plugin protocols on the same connection</li>
|
||||
<li>Autopass replicates <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">dnsPass</code> to authorized writers (separate from the P2NS topic used only for discovery)</li>
|
||||
<li>Autopass replicates <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">dnsPass</code> to authorized writers (separate from the P2NS topic used only for discovery)</li>
|
||||
</ul>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">3. Joining as a Writer (Genesis, Masters, Joiners)</h4>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
Only peers with Autopass writer access can append claims and votes. All nodes on a network share <strong className="text-gray-900 dark:text-white">one</strong> Autopass ledger identified by <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">networkId</code> in <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">cache/network.json</code>:
|
||||
<h4 className="text-xl font-semibold text-white mb-3">3. Joining as a Writer (Genesis, Masters, Joiners)</h4>
|
||||
<p className="text-mist mb-4">
|
||||
Only peers with Autopass writer access can append claims and votes. All nodes on a network share <strong className="text-white">one</strong> Autopass ledger identified by <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">networkId</code> in <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">cache/network.json</code>:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<li><strong className="text-gray-900 dark:text-white">Genesis master</strong> — <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--master --genesis</code> creates the ledger (once per network)</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Secondary masters</strong> — <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--master</code> on empty storage waits for an invite (no implicit second ledger)</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Joiners</strong> — <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">node p2ns.js</code>; no master flag required for everyday use</li>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li><strong className="text-white">Genesis master</strong> — <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--master --genesis</code> creates the ledger (once per network)</li>
|
||||
<li><strong className="text-white">Secondary masters</strong> — <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--master</code> on empty storage waits for an invite (no implicit second ledger)</li>
|
||||
<li><strong className="text-white">Joiners</strong> — <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">node p2ns.js</code>; no master flag required for everyday use</li>
|
||||
</ul>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<p className="text-mist mb-4">
|
||||
Admission uses protomux-rpc on the P2NS swarm connection:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">invite.request</code> — peer asks a master or writer for an invite</li>
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">invite.deliver</code> / <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">invite.ack</code> — invite wire is delivered and acknowledged</li>
|
||||
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">core.status</code> — exposes <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">networkId</code>, invite capability, and split-network warnings</li>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">invite.request</code> — peer asks a master or writer for an invite</li>
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">invite.deliver</code> / <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">invite.ack</code> — invite wire is delivered and acknowledged</li>
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">core.status</code> — exposes <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">networkId</code>, invite capability, and split-network warnings</li>
|
||||
</ul>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
Masters may proactively send invites when new peers connect (<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">MASTER_PROACTIVE_INVITE_DELAY</code>).
|
||||
Quorum counts writers with initialized <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">dnsPass</code>, not raw swarm connections.
|
||||
See <a href="/docs/architecture" className="text-blue-600 dark:text-blue-400 hover:underline">Architecture</a> and <a href="/docs/configuration" className="text-blue-600 dark:text-blue-400 hover:underline">Configuration</a>.
|
||||
<p className="text-mist mb-4">
|
||||
Masters may proactively send invites when new peers connect (<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">MASTER_PROACTIVE_INVITE_DELAY</code>).
|
||||
Quorum counts writers with initialized <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">dnsPass</code>, not raw swarm connections.
|
||||
See <a href="/docs/architecture" className="text-indigo-light hover:underline">Architecture</a> and <a href="/docs/configuration" className="text-indigo-light hover:underline">Configuration</a>.
|
||||
</p>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">4. Data Synchronization</h4>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
Once a peer is a writer, new claims and votes append to <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">dnsPass</code> and replicate
|
||||
<h4 className="text-xl font-semibold text-white mb-3">4. Data Synchronization</h4>
|
||||
<p className="text-mist mb-4">
|
||||
Once a peer is a writer, new claims and votes append to <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">dnsPass</code> and replicate
|
||||
to other writers through Autopass. Corestore manages the underlying Hypercore logs. When a new claim or vote is added, authorized peers receive it automatically.
|
||||
</p>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<p className="text-mist mb-4">
|
||||
This means:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-6">
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-6">
|
||||
<li>Every node has a complete copy of all domain claims and votes</li>
|
||||
<li>New information propagates through the network automatically</li>
|
||||
<li>The network is resilient - if some nodes go offline, others still have the data</li>
|
||||
<li>No central server is needed - the network is truly decentralized</li>
|
||||
</ul>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Part 3: DNS Resolution (When Someone Wants to Access)</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">Part 3: DNS Resolution (When Someone Wants to Access)</h3>
|
||||
<p className="text-mist mb-4">
|
||||
Now let's see what happens when someone wants to access a P2NS domain. This is where the magic happens!
|
||||
</p>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">1. The DNS Query</h4>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
When you type a domain like <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">https://example.tld</code>
|
||||
<h4 className="text-xl font-semibold text-white mb-3">1. The DNS Query</h4>
|
||||
<p className="text-mist mb-4">
|
||||
When you type a domain like <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">https://example.tld</code>
|
||||
in your browser, or when an application makes a DNS query, it goes to the P2NS DNS server (port 53 by default, configurable).
|
||||
This server is configured as your system's DNS resolver, so queries flow through P2NS first.
|
||||
</p>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">2. Internal and Local Records</h4>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h4 className="text-xl font-semibold text-white mb-3">2. Internal and Local Records</h4>
|
||||
<p className="text-mist mb-4">
|
||||
Before P2P lookup, the resolver checks:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<li><strong className="text-gray-900 dark:text-white">Internal domains:</strong> <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">p2ns.admin</code> and any domain with a plugin under <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">plugin-sites/{domain}/config.json</code> (e.g. <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">peer.directory</code>, <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">peer.paste</code>)</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Local DNS:</strong> entries in <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">cache/local_dns.json</code> override both P2P and public DNS</li>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li><strong className="text-white">Internal domains:</strong> <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">p2ns.admin</code> and any domain with a plugin under <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">plugin-sites/{domain}/config.json</code> (e.g. <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">peer.directory</code>, <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">peer.paste</code>)</li>
|
||||
<li><strong className="text-white">Local DNS:</strong> entries in <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">cache/local_dns.json</code> override both P2P and public DNS</li>
|
||||
</ul>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">3. Checking the Cache</h4>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h4 className="text-xl font-semibold text-white mb-3">3. Checking the Cache</h4>
|
||||
<p className="text-mist mb-4">
|
||||
First, P2NS checks its local cache to see if it recently resolved this domain. If the cache entry is still valid
|
||||
(typically cached for 30 seconds), it returns the cached result immediately. This makes repeated queries very fast.
|
||||
</p>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">4. Querying the P2P Network</h4>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
If not in cache, P2NS resolves the domain through the <strong className="text-gray-900 dark:text-white">consensus Autobase sidecar</strong> apply view.
|
||||
<h4 className="text-xl font-semibold text-white mb-3">4. Querying the P2P Network</h4>
|
||||
<p className="text-mist mb-4">
|
||||
If not in cache, P2NS resolves the domain through the <strong className="text-white">consensus Autobase sidecar</strong> apply view.
|
||||
Claim and vote events are replayed in linearized order; the resolver reads that in-memory view rather than scanning the full Autopass ledger on each query.
|
||||
</p>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
Claims originate from Autopass KV keys like <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">claim:example.tld:*</code>;
|
||||
<p className="text-mist mb-4">
|
||||
Claims originate from Autopass KV keys like <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">claim:example.tld:*</code>;
|
||||
the sidecar maintains the current per-domain state used for resolution.
|
||||
</p>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">5. Consensus Mechanism</h4>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h4 className="text-xl font-semibold text-white mb-3">5. Consensus Mechanism</h4>
|
||||
<p className="text-mist mb-4">
|
||||
If multiple people have claimed the same domain, P2NS uses a consensus algorithm to determine which one is correct:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<li><strong className="text-gray-900 dark:text-white">Count votes:</strong> Each claim can have votes from other peers. The system counts how many votes each claimant has received.</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Check quorum:</strong> Configurable via <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">CONSENSUS_QUORUM_THRESHOLD</code> (default 50% of active peers) and <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">CONSENSUS_MIN_VOTES</code> (default 2).</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Resolve ties:</strong> If two claimants have the same number of votes, the system uses a tie-breaker (like preferring the oldest claim).</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Return the hash:</strong> Once consensus is reached, the system returns the Holesail hash associated with the winning claim.</li>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li><strong className="text-white">Count votes:</strong> Each claim can have votes from other peers. The system counts how many votes each claimant has received.</li>
|
||||
<li><strong className="text-white">Check quorum:</strong> Configurable via <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">CONSENSUS_QUORUM_THRESHOLD</code> (default 50% of active peers) and <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">CONSENSUS_MIN_VOTES</code> (default 2).</li>
|
||||
<li><strong className="text-white">Resolve ties:</strong> If two claimants have the same number of votes, the system uses a tie-breaker (like preferring the oldest claim).</li>
|
||||
<li><strong className="text-white">Return the hash:</strong> Once consensus is reached, the system returns the Holesail hash associated with the winning claim.</li>
|
||||
</ul>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<p className="text-mist mb-4">
|
||||
This ensures that everyone in the network agrees on which service should be associated with each domain name.
|
||||
</p>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">6. Fallback to Public DNS</h4>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
If the domain is not internal, not in local DNS, and not resolved via P2P consensus, P2NS forwards to <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">PUBLIC_DNS_SERVER</code> (comma-separated list supported for failover).
|
||||
<h4 className="text-xl font-semibold text-white mb-3">6. Fallback to Public DNS</h4>
|
||||
<p className="text-mist mb-6">
|
||||
If the domain is not internal, not in local DNS, and not resolved via P2P consensus, P2NS forwards to <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">PUBLIC_DNS_SERVER</code> (comma-separated list supported for failover).
|
||||
You can use P2P domains and the public internet through one resolver.
|
||||
</p>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Part 4: Virtual Interface Setup</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">Part 4: Virtual Interface Setup</h3>
|
||||
<p className="text-mist mb-4">
|
||||
Once P2NS has the Holesail hash for a domain, it needs to set up local networking to route traffic to that domain.
|
||||
This is where virtual network interfaces come in.
|
||||
</p>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">1. Assigning a Local IP Address</h4>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
P2NS assigns each domain a unique local IP address from a configured subnet (default: <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">192.168.3.x</code>).
|
||||
For example, the first domain might get <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">192.168.3.2</code>,
|
||||
the second gets <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">192.168.3.3</code>, and so on.
|
||||
<h4 className="text-xl font-semibold text-white mb-3">1. Assigning a Local IP Address</h4>
|
||||
<p className="text-mist mb-4">
|
||||
P2NS assigns each domain a unique local IP address from a configured subnet (default: <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">192.168.3.x</code>).
|
||||
For example, the first domain might get <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">192.168.3.2</code>,
|
||||
the second gets <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">192.168.3.3</code>, and so on.
|
||||
</p>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<p className="text-mist mb-4">
|
||||
You can configure multiple subnets with different IP ranges, and P2NS will automatically allocate IPs from available subnets.
|
||||
This gives you flexibility to organize domains across different network ranges.
|
||||
</p>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">2. Creating the Virtual Interface</h4>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
P2NS creates a virtual network interface (like <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">lo0</code> on macOS or <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">lo</code> on Linux)
|
||||
<h4 className="text-xl font-semibold text-white mb-3">2. Creating the Virtual Interface</h4>
|
||||
<p className="text-mist mb-4">
|
||||
P2NS creates a virtual network interface (like <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">lo0</code> on macOS or <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">lo</code> on Linux)
|
||||
and adds the IP address as an alias. This makes the IP address available on your local machine, even though it's not
|
||||
connected to a physical network.
|
||||
</p>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<p className="text-mist mb-4">
|
||||
The virtual interface acts like a local network adapter, allowing your system to route traffic to that IP address.
|
||||
When your browser or application connects to the domain, it resolves to this local IP, and the traffic gets intercepted
|
||||
by P2NS for processing.
|
||||
</p>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">3. Why Virtual Interfaces?</h4>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
<h4 className="text-xl font-semibold text-white mb-3">3. Why Virtual Interfaces?</h4>
|
||||
<p className="text-mist mb-6">
|
||||
Virtual interfaces are necessary because:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-6">
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-6">
|
||||
<li>They allow P2NS to intercept traffic destined for P2P domains</li>
|
||||
<li>They provide a consistent local endpoint for routing</li>
|
||||
<li>They enable the HTTPS proxy to handle TLS connections properly</li>
|
||||
<li>They allow multiple domains to coexist on the same machine without conflicts</li>
|
||||
</ul>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Part 5: Holesail Connection Establishment</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">Part 5: Holesail Connection Establishment</h3>
|
||||
<p className="text-mist mb-4">
|
||||
Now that we have a local IP address, P2NS needs to establish a connection to the actual service. This is where Holesail
|
||||
comes in - it's the technology that punches through firewalls and NAT to create direct connections.
|
||||
</p>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">1. What Holesail Does</h4>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h4 className="text-xl font-semibold text-white mb-3">1. What Holesail Does</h4>
|
||||
<p className="text-mist mb-4">
|
||||
Holesail uses UDP hole-punching to establish connections through firewalls and NAT (Network Address Translation).
|
||||
Traditional networking often fails when both the client and server are behind firewalls, but Holesail solves this by:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li>Using HyperDHT (the distributed hash table) to exchange endpoints and coordinate simultaneous UDP probes</li>
|
||||
<li>Sending UDP packets from both sides simultaneously to "punch holes" in the firewall</li>
|
||||
<li>Establishing a direct peer-to-peer connection once the hole is punched, with encrypted relay fallback when needed</li>
|
||||
<li>Maintaining tunnels; optional <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">FULL_PERSISTENCE</code> keeps clients/servers alive across restarts (see Configuration)</li>
|
||||
<li>Maintaining tunnels; optional <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">FULL_PERSISTENCE</code> keeps clients/servers alive across restarts (see Configuration)</li>
|
||||
</ul>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
Holesail server and client configs persist under <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">cache/holesail_servers.json</code> and{' '}
|
||||
<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">cache/holesail_clients.json</code>.
|
||||
<p className="text-mist mb-4">
|
||||
Holesail server and client configs persist under <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">cache/holesail_servers.json</code> and{' '}
|
||||
<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">cache/holesail_clients.json</code>.
|
||||
</p>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">2. Using the Hash to Connect</h4>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h4 className="text-xl font-semibold text-white mb-3">2. Using the Hash to Connect</h4>
|
||||
<p className="text-mist mb-4">
|
||||
The Holesail hash we got from the domain claim is a random cryptographic string that acts as a key to look up the service
|
||||
on the DHT. When P2NS needs to connect, it:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li>Uses the hash to query the DHT for the service information</li>
|
||||
<li>Retrieves the metadata stored on the DHT (host, port, protocol configuration)</li>
|
||||
<li>Uses this information along with the hash to establish the connection</li>
|
||||
</ul>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<p className="text-mist mb-4">
|
||||
P2NS creates a Holesail client that uses this hash to look up and connect to the service provider's Holesail server.
|
||||
The connection process happens automatically in the background.
|
||||
</p>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">3. Connection Persistence</h4>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
<h4 className="text-xl font-semibold text-white mb-3">3. Connection Persistence</h4>
|
||||
<p className="text-mist mb-6">
|
||||
Once established, the Holesail connection can be kept alive persistently. This means:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-6">
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-6">
|
||||
<li>Subsequent requests to the same domain reuse the existing connection (faster)</li>
|
||||
<li>The connection automatically reconnects if it drops</li>
|
||||
<li>You can configure timeout behavior for non-persistent connections</li>
|
||||
<li>Multiple domains can share connections when appropriate</li>
|
||||
</ul>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Part 6: HTTPS Proxy and Routing</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">Part 6: HTTPS Proxy and Routing</h3>
|
||||
<p className="text-mist mb-4">
|
||||
Now we have a Holesail tunnel established, but we still need to handle HTTPS properly and route requests correctly.
|
||||
This is where the proxy servers come in.
|
||||
</p>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">1. TLS Certificate Generation</h4>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h4 className="text-xl font-semibold text-white mb-3">1. TLS Certificate Generation</h4>
|
||||
<p className="text-mist mb-4">
|
||||
P2NS automatically generates TLS certificates for each domain using its own Certificate Authority (CA). When you first
|
||||
access a P2NS domain, the system:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li>Generates a certificate for the domain if it doesn't exist</li>
|
||||
<li>Signs it with the P2NS root CA</li>
|
||||
<li>Includes the domain name and local IP in the certificate (Subject Alternative Names)</li>
|
||||
<li>Stores the certificate for reuse</li>
|
||||
</ul>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<p className="text-mist mb-4">
|
||||
You need to trust the P2NS root CA in your browser/system to avoid security warnings. P2NS auto-installs on macOS and Windows;
|
||||
on Linux, Chrome requires both the system CA bundle and the NSS trust database (<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">certutil</code> / <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">~/.pki/nssdb</code>) — see{' '}
|
||||
<a href="/docs/troubleshooting#certificate-authority-issues" className="text-blue-600 dark:text-blue-400 hover:underline">Troubleshooting</a>.
|
||||
on Linux, Chrome requires both the system CA bundle and the NSS trust database (<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">certutil</code> / <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">~/.pki/nssdb</code>) — see{' '}
|
||||
<a href="/docs/troubleshooting#certificate-authority-issues" className="text-indigo-light hover:underline">Troubleshooting</a>.
|
||||
</p>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">2. HTTPS Proxy Server</h4>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h4 className="text-xl font-semibold text-white mb-3">2. HTTPS Proxy Server</h4>
|
||||
<p className="text-mist mb-4">
|
||||
P2NS runs an HTTPS proxy server on port 443. When your browser makes an HTTPS request to a P2NS domain:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li>The request goes to the P2NS HTTPS proxy</li>
|
||||
<li>The proxy uses the domain's TLS certificate to establish a secure connection with your browser</li>
|
||||
<li>The proxy then forwards the request through the Holesail tunnel to the actual service</li>
|
||||
<li>Responses flow back through the tunnel and proxy to your browser</li>
|
||||
</ul>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">3. HTTP to HTTPS Redirect</h4>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h4 className="text-xl font-semibold text-white mb-3">3. HTTP to HTTPS Redirect</h4>
|
||||
<p className="text-mist mb-4">
|
||||
P2NS also runs an HTTP server on port 80 that automatically redirects all HTTP requests to HTTPS. This ensures
|
||||
all connections are encrypted and secure.
|
||||
</p>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">4. WebSocket Support</h4>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
<h4 className="text-xl font-semibold text-white mb-3">4. WebSocket Support</h4>
|
||||
<p className="text-mist mb-6">
|
||||
The proxy also supports WebSocket connections, allowing real-time applications to work through P2NS. WebSocket
|
||||
upgrades are handled transparently, maintaining the connection through the Holesail tunnel.
|
||||
</p>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Part 7: Complete Request Flow</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">Part 7: Complete Request Flow</h3>
|
||||
<p className="text-mist mb-4">
|
||||
Let's put it all together! Here's exactly what happens when you access a P2NS domain:
|
||||
</p>
|
||||
|
||||
<div className="bg-gray-50 dark:bg-gray-800 p-6 rounded-lg mb-6">
|
||||
<ol className="list-decimal pl-6 space-y-3 text-gray-700 dark:text-gray-300">
|
||||
<li><strong className="text-gray-900 dark:text-white">You type</strong> <code className="bg-gray-200 dark:bg-gray-700 px-1.5 py-0.5 rounded">https://example.tld</code> in your browser</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">DNS query:</strong> Your system queries the P2NS DNS server (port 53) for <code className="bg-gray-200 dark:bg-gray-700 px-1.5 py-0.5 rounded">example.tld</code></li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Cache check:</strong> P2NS checks its cache - if found and valid, returns cached result</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">P2P lookup:</strong> If not cached, P2NS reads the consensus sidecar apply view for claims on <code className="bg-gray-200 dark:bg-gray-700 px-1.5 py-0.5 rounded">example.tld</code></li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Consensus:</strong> If multiple claims exist, the sidecar resolver applies quorum and tie-break rules to determine the correct hash</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Hash retrieved:</strong> P2NS gets the Holesail hash (e.g., <code className="bg-gray-200 dark:bg-gray-700 px-1.5 py-0.5 rounded">hs://s00084bf87dfa89a...</code>)</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Virtual interface:</strong> P2NS assigns/uses a local IP (e.g., <code className="bg-gray-200 dark:bg-gray-700 px-1.5 py-0.5 rounded">192.168.3.2</code>) for this domain</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Holesail client:</strong> P2NS creates or reuses a Holesail client connection using the hash</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Tunnel established:</strong> The Holesail connection punches through firewalls and establishes a tunnel</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">TLS proxy:</strong> P2NS sets up an HTTPS proxy using the domain's TLS certificate</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Browser connects:</strong> Your browser connects to the P2NS HTTPS proxy (port 443)</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Request forwarded:</strong> The proxy forwards your request through the Holesail tunnel to the actual service</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Response received:</strong> The service responds, and the response flows back through the tunnel</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">You see the website:</strong> The response reaches your browser, and you see the content!</li>
|
||||
<div className="bg-deep p-6 rounded-lg mb-6">
|
||||
<ol className="list-decimal pl-6 space-y-3 text-mist">
|
||||
<li><strong className="text-white">You type</strong> <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">https://example.tld</code> in your browser</li>
|
||||
<li><strong className="text-white">DNS query:</strong> Your system queries the P2NS DNS server (port 53) for <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">example.tld</code></li>
|
||||
<li><strong className="text-white">Cache check:</strong> P2NS checks its cache - if found and valid, returns cached result</li>
|
||||
<li><strong className="text-white">P2P lookup:</strong> If not cached, P2NS reads the consensus sidecar apply view for claims on <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">example.tld</code></li>
|
||||
<li><strong className="text-white">Consensus:</strong> If multiple claims exist, the sidecar resolver applies quorum and tie-break rules to determine the correct hash</li>
|
||||
<li><strong className="text-white">Hash retrieved:</strong> P2NS gets the Holesail hash (e.g., <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">hs://s00084bf87dfa89a...</code>)</li>
|
||||
<li><strong className="text-white">Virtual interface:</strong> P2NS assigns/uses a local IP (e.g., <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">192.168.3.2</code>) for this domain</li>
|
||||
<li><strong className="text-white">Holesail client:</strong> P2NS creates or reuses a Holesail client connection using the hash</li>
|
||||
<li><strong className="text-white">Tunnel established:</strong> The Holesail connection punches through firewalls and establishes a tunnel</li>
|
||||
<li><strong className="text-white">TLS proxy:</strong> P2NS sets up an HTTPS proxy using the domain's TLS certificate</li>
|
||||
<li><strong className="text-white">Browser connects:</strong> Your browser connects to the P2NS HTTPS proxy (port 443)</li>
|
||||
<li><strong className="text-white">Request forwarded:</strong> The proxy forwards your request through the Holesail tunnel to the actual service</li>
|
||||
<li><strong className="text-white">Response received:</strong> The service responds, and the response flows back through the tunnel</li>
|
||||
<li><strong className="text-white">You see the website:</strong> The response reaches your browser, and you see the content!</li>
|
||||
</ol>
|
||||
</div>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
<p className="text-mist mb-6">
|
||||
All of this happens automatically in milliseconds! The first request might take a bit longer as connections are established,
|
||||
but subsequent requests are much faster as connections are reused.
|
||||
</p>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Consensus and Voting</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">Consensus and Voting</h2>
|
||||
<p className="text-mist mb-4">
|
||||
One of the most important aspects of P2NS is how it handles conflicts when multiple people claim the same domain.
|
||||
Autopass KV remains the durable write store; resolution reads from the replicated <strong className="text-gray-900 dark:text-white">Autobase consensus sidecar</strong> (see{' '}
|
||||
<a href="https://git.ssh.surf/snxraven/p2ns/src/branch/main/docs/rfcs/0001-autobase-consensus.md" target="_blank" rel="noopener noreferrer" className="text-blue-600 dark:text-blue-400 hover:underline">RFC 0001</a> in the repository).
|
||||
Autopass KV remains the durable write store; resolution reads from the replicated <strong className="text-white">Autobase consensus sidecar</strong> (see{' '}
|
||||
<a href="https://git.ssh.surf/snxraven/p2ns/src/branch/main/docs/rfcs/0001-autobase-consensus.md" target="_blank" rel="noopener noreferrer" className="text-indigo-light hover:underline">RFC 0001</a> in the repository).
|
||||
</p>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4">Dual-store architecture</h3>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<li><strong className="text-gray-900 dark:text-white">Writes:</strong> Claims and votes are stored in Autopass; each local mutation dual-appends a typed event to the sidecar</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Reads:</strong> <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">getConsensusState</code> reads the apply view only—no KV-scan fallback</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Bootstrap:</strong> On first run, existing claim/vote entries are replayed into the sidecar; <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">cache/network.json</code> stores <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">consensusAutobaseKey</code> for joiners</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Monitoring:</strong> <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/consensus/status</code> reports sidecar health and bootstrap progress</li>
|
||||
<h3 className="text-2xl font-semibold text-white mb-4">Dual-store architecture</h3>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li><strong className="text-white">Writes:</strong> Claims and votes are stored in Autopass; each local mutation dual-appends a typed event to the sidecar</li>
|
||||
<li><strong className="text-white">Reads:</strong> <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">getConsensusState</code> reads the apply view only—no KV-scan fallback</li>
|
||||
<li><strong className="text-white">Bootstrap:</strong> On first run, existing claim/vote entries are replayed into the sidecar; <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">cache/network.json</code> stores <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">consensusAutobaseKey</code> for joiners</li>
|
||||
<li><strong className="text-white">Monitoring:</strong> <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">GET /api/consensus/status</code> reports sidecar health and bootstrap progress</li>
|
||||
</ul>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4">How Voting Works</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4">How Voting Works</h3>
|
||||
<p className="text-mist mb-4">
|
||||
When a peer sees a domain claim, they can vote for it by creating a vote entry in the ledger. The vote key looks like:
|
||||
<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">vote:example.tld:claimant-id:voter-id</code>
|
||||
<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">vote:example.tld:claimant-id:voter-id</code>
|
||||
</p>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<p className="text-mist mb-4">
|
||||
Peers typically vote for the claim they believe is legitimate. This could be based on:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li>Who they know and trust</li>
|
||||
<li>Which claim was made first (timestamp)</li>
|
||||
<li>Which service they want to use</li>
|
||||
<li>Automatic voting based on local claims</li>
|
||||
</ul>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Quorum Requirements</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">Quorum Requirements</h3>
|
||||
<p className="text-mist mb-4">
|
||||
For a domain to be considered "resolved" (consensus reached), it must meet quorum requirements:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<li><strong className="text-gray-900 dark:text-white">Percentage threshold:</strong> <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">CONSENSUS_QUORUM_THRESHOLD</code> (default 0.5 = 50% of active peers)</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Minimum votes:</strong> <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">CONSENSUS_MIN_VOTES</code> (default 2), regardless of peer count</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Vote validation:</strong> Votes must reference existing claims (invalid votes are ignored)</li>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li><strong className="text-white">Percentage threshold:</strong> <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">CONSENSUS_QUORUM_THRESHOLD</code> (default 0.5 = 50% of active peers)</li>
|
||||
<li><strong className="text-white">Minimum votes:</strong> <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">CONSENSUS_MIN_VOTES</code> (default 2), regardless of peer count</li>
|
||||
<li><strong className="text-white">Vote validation:</strong> Votes must reference existing claims (invalid votes are ignored)</li>
|
||||
</ul>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<p className="text-mist mb-4">
|
||||
This ensures that consensus isn't reached by just one or two nodes, but represents actual network agreement.
|
||||
</p>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Tie-Breaking Strategies</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">Tie-Breaking Strategies</h3>
|
||||
<p className="text-mist mb-4">
|
||||
When multiple claimants have the same number of votes, P2NS uses tie-breaking strategies:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<li><strong className="text-gray-900 dark:text-white">Timestamp:</strong> Prefer the oldest claim (<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">CONSENSUS_TIE_BREAKER=timestamp</code>, default)</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Claimant age:</strong> Prefer the local writer among tied claimants; otherwise lexicographic ordering (<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">CONSENSUS_TIE_BREAKER=claimant_age</code>)</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Lexicographic:</strong> Prefer local writer, then alphabetical ordering of claimant IDs</li>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li><strong className="text-white">Timestamp:</strong> Prefer the oldest claim (<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">CONSENSUS_TIE_BREAKER=timestamp</code>, default)</li>
|
||||
<li><strong className="text-white">Claimant age:</strong> Prefer the local writer among tied claimants; otherwise lexicographic ordering (<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">CONSENSUS_TIE_BREAKER=claimant_age</code>)</li>
|
||||
<li><strong className="text-white">Lexicographic:</strong> Prefer local writer, then alphabetical ordering of claimant IDs</li>
|
||||
</ul>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
<p className="text-mist mb-6">
|
||||
This deterministic approach ensures all nodes reach the same conclusion when resolving ties, maintaining network consistency.
|
||||
</p>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Key Technologies Explained Simply</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">Key Technologies Explained Simply</h2>
|
||||
<p className="text-mist mb-4">
|
||||
P2NS uses several advanced technologies. Here's what each one does in simple terms:
|
||||
</p>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4">Hyperswarm & HyperDHT</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<strong className="text-gray-900 dark:text-white">What it does:</strong> Discovers other P2NS nodes on topic <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">sha256(TOPIC_SEED)</code>, coordinates hole punching, and opens encrypted swarm connections.
|
||||
<h3 className="text-2xl font-semibold text-white mb-4">Hyperswarm & HyperDHT</h3>
|
||||
<p className="text-mist mb-4">
|
||||
<strong className="text-white">What it does:</strong> Discovers other P2NS nodes on topic <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">sha256(TOPIC_SEED)</code>, coordinates hole punching, and opens encrypted swarm connections.
|
||||
</p>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
<strong className="text-gray-900 dark:text-white">Simple analogy:</strong> A distributed meeting room—everyone who joins the same topic can find each other without a central directory server.
|
||||
<p className="text-mist mb-6">
|
||||
<strong className="text-white">Simple analogy:</strong> A distributed meeting room—everyone who joins the same topic can find each other without a central directory server.
|
||||
</p>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4">Protomux / protomux-rpc</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<strong className="text-gray-900 dark:text-white">What it does:</strong> Multiplexes JSON-RPC methods on each peer connection—core invites, consensus helpers, and per-plugin protocols.
|
||||
<h3 className="text-2xl font-semibold text-white mb-4">Protomux / protomux-rpc</h3>
|
||||
<p className="text-mist mb-4">
|
||||
<strong className="text-white">What it does:</strong> Multiplexes JSON-RPC methods on each peer connection—core invites, consensus helpers, and per-plugin protocols.
|
||||
</p>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
<strong className="text-gray-900 dark:text-white">Simple analogy:</strong> Several phone lines over one secure call—core control traffic and plugin apps share the same tunnel without mixing messages.
|
||||
<p className="text-mist mb-6">
|
||||
<strong className="text-white">Simple analogy:</strong> Several phone lines over one secure call—core control traffic and plugin apps share the same tunnel without mixing messages.
|
||||
</p>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4">Corestore, Autopass & Autobase</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<strong className="text-gray-900 dark:text-white">What it does:</strong> Corestore holds Hypercore append-only logs; Autopass (<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">dnsPass</code>) stores claims and votes with invite-gated writers. A dedicated Autobase sidecar (<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">p2ns-consensus</code> namespace) linearizes claim/vote events for deterministic resolution.
|
||||
<h3 className="text-2xl font-semibold text-white mb-4">Corestore, Autopass & Autobase</h3>
|
||||
<p className="text-mist mb-4">
|
||||
<strong className="text-white">What it does:</strong> Corestore holds Hypercore append-only logs; Autopass (<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">dnsPass</code>) stores claims and votes with invite-gated writers. A dedicated Autobase sidecar (<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">p2ns-consensus</code> namespace) linearizes claim/vote events for deterministic resolution.
|
||||
</p>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
<strong className="text-gray-900 dark:text-white">Simple analogy:</strong> Autopass is the signed ledger everyone authorized can append to; the sidecar is the ordered replay that tells every node the same current winner for each domain.
|
||||
<p className="text-mist mb-6">
|
||||
<strong className="text-white">Simple analogy:</strong> Autopass is the signed ledger everyone authorized can append to; the sidecar is the ordered replay that tells every node the same current winner for each domain.
|
||||
</p>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4">Holesail</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<strong className="text-gray-900 dark:text-white">What it does:</strong> Publishes and connects to service tunnels by hash on HyperDHT—separate from the P2NS DNS swarm topic.
|
||||
<h3 className="text-2xl font-semibold text-white mb-4">Holesail</h3>
|
||||
<p className="text-mist mb-4">
|
||||
<strong className="text-white">What it does:</strong> Publishes and connects to service tunnels by hash on HyperDHT—separate from the P2NS DNS swarm topic.
|
||||
</p>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
<strong className="text-gray-900 dark:text-white">Simple analogy:</strong> A dedicated address for your web server or game port; DNS consensus points a domain name at that address.
|
||||
<p className="text-mist mb-6">
|
||||
<strong className="text-white">Simple analogy:</strong> A dedicated address for your web server or game port; DNS consensus points a domain name at that address.
|
||||
</p>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Real-World Example</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">Real-World Example</h2>
|
||||
<p className="text-mist mb-4">
|
||||
Let's walk through a concrete example to see how everything fits together:
|
||||
</p>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4">Scenario: Alice hosts a blog, Bob wants to read it</h3>
|
||||
<h3 className="text-2xl font-semibold text-white mb-4">Scenario: Alice hosts a blog, Bob wants to read it</h3>
|
||||
|
||||
<div className="bg-gray-50 dark:bg-gray-800 p-6 rounded-lg mb-6">
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Step 1: Alice Sets Up Her Blog (Service Provider)</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-700 dark:text-gray-300 mb-4">
|
||||
<div className="bg-deep p-6 rounded-lg mb-6">
|
||||
<h4 className="text-xl font-semibold text-white mb-3">Step 1: Alice Sets Up Her Blog (Service Provider)</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li>Alice runs a blog server on her home computer (port 80)</li>
|
||||
<li>She generates a Holesail hash: <code className="bg-gray-200 dark:bg-gray-700 px-1.5 py-0.5 rounded">hs://s00084bf87dfa89a3048fb081c0e6207eb5a</code></li>
|
||||
<li>She claims the domain <code className="bg-gray-200 dark:bg-gray-700 px-1.5 py-0.5 rounded">alice.blog</code> with this hash</li>
|
||||
<li>She generates a Holesail hash: <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">hs://s00084bf87dfa89a3048fb081c0e6207eb5a</code></li>
|
||||
<li>She claims the domain <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">alice.blog</code> with this hash</li>
|
||||
<li>The claim is stored in the P2P network and synced to all peers</li>
|
||||
</ul>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3 mt-6">Step 2: Bob's Node Joins the Network</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-700 dark:text-gray-300 mb-4">
|
||||
<h4 className="text-xl font-semibold text-white mb-3 mt-6">Step 2: Bob's Node Joins the Network</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li>Bob starts his P2NS node</li>
|
||||
<li>His node connects to Hyperswarm and discovers other peers</li>
|
||||
<li>The distributed ledger syncs, and Bob's node now knows about <code className="bg-gray-200 dark:bg-gray-700 px-1.5 py-0.5 rounded">alice.blog</code></li>
|
||||
<li>The distributed ledger syncs, and Bob's node now knows about <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">alice.blog</code></li>
|
||||
</ul>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3 mt-6">Step 3: Bob Accesses the Blog</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-700 dark:text-gray-300 mb-4">
|
||||
<li>Bob types <code className="bg-gray-200 dark:bg-gray-700 px-1.5 py-0.5 rounded">https://alice.blog</code> in his browser</li>
|
||||
<h4 className="text-xl font-semibold text-white mb-3 mt-6">Step 3: Bob Accesses the Blog</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li>Bob types <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">https://alice.blog</code> in his browser</li>
|
||||
<li>DNS query goes to P2NS DNS server</li>
|
||||
<li>P2NS looks up <code className="bg-gray-200 dark:bg-gray-700 px-1.5 py-0.5 rounded">alice.blog</code> in the ledger</li>
|
||||
<li>P2NS looks up <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">alice.blog</code> in the ledger</li>
|
||||
<li>Finds Alice's claim and gets the Holesail hash</li>
|
||||
<li>Assigns local IP <code className="bg-gray-200 dark:bg-gray-700 px-1.5 py-0.5 rounded">192.168.3.2</code> to <code className="bg-gray-200 dark:bg-gray-700 px-1.5 py-0.5 rounded">alice.blog</code></li>
|
||||
<li>Assigns local IP <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">192.168.3.2</code> to <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">alice.blog</code></li>
|
||||
<li>Creates Holesail client connection using the hash</li>
|
||||
<li>Holesail punches through firewalls and connects to Alice's server</li>
|
||||
<li>HTTPS proxy routes the request through the tunnel</li>
|
||||
@@ -537,25 +537,25 @@ export default function HowItWorksPage() {
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<strong className="text-gray-900 dark:text-white">Timeline:</strong> All of this happens in under a second for the first request.
|
||||
<p className="text-mist mb-4">
|
||||
<strong className="text-white">Timeline:</strong> All of this happens in under a second for the first request.
|
||||
Subsequent requests are even faster because the Holesail connection is reused.
|
||||
</p>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
<strong className="text-gray-900 dark:text-white">The magic:</strong> Even though Alice and Bob are both behind firewalls and NAT,
|
||||
<p className="text-mist mb-6">
|
||||
<strong className="text-white">The magic:</strong> Even though Alice and Bob are both behind firewalls and NAT,
|
||||
they can communicate directly thanks to Holesail's UDP hole-punching. No central server needed, no port forwarding required!
|
||||
</p>
|
||||
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Scenario: Service Subscriptions - Multiple Services, Automatic Management</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 mt-8">Scenario: Service Subscriptions - Multiple Services, Automatic Management</h3>
|
||||
<p className="text-mist mb-4">
|
||||
Service subscriptions allow peers to automatically connect to services hosted by domain owners. This is especially useful when
|
||||
a domain owner hosts multiple services (like a web server, API, and game server) and wants others to easily access them.
|
||||
</p>
|
||||
|
||||
<div className="bg-gray-50 dark:bg-gray-800 p-6 rounded-lg mb-6">
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Step 1: Alice Hosts Multiple Services</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-700 dark:text-gray-300 mb-4">
|
||||
<li>Alice owns the domain <code className="bg-gray-200 dark:bg-gray-700 px-1.5 py-0.5 rounded">alice.services</code></li>
|
||||
<div className="bg-deep p-6 rounded-lg mb-6">
|
||||
<h4 className="text-xl font-semibold text-white mb-3">Step 1: Alice Hosts Multiple Services</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li>Alice owns the domain <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">alice.services</code></li>
|
||||
<li>She hosts three services:
|
||||
<ul className="list-disc pl-6 mt-2 space-y-1">
|
||||
<li><strong>Web Server:</strong> Port 80, TCP protocol, service name "web"</li>
|
||||
@@ -566,46 +566,46 @@ export default function HowItWorksPage() {
|
||||
<li>Alice opens the P2NS admin panel and navigates to the "Host" tab</li>
|
||||
<li>For each service, she creates a Holesail hash and uses the "Create Client" button to add it to her domain</li>
|
||||
<li>When creating each client, she specifies the service name and protocol (TCP or UDP)</li>
|
||||
<li>The system automatically updates the domain's claim record with a <code className="bg-gray-200 dark:bg-gray-700 px-1.5 py-0.5 rounded">clients</code> array containing all three services</li>
|
||||
<li>The system automatically updates the domain's claim record with a <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">clients</code> array containing all three services</li>
|
||||
<li>This claim record is automatically synced to all peers in the network</li>
|
||||
</ul>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4 mt-4">
|
||||
<p className="text-mist mb-4 mt-4">
|
||||
Example claim record structure:
|
||||
</p>
|
||||
<CodeBlock code={'{\n "hash": "original-hash",\n "clients": [\n {\n "name": "web",\n "hash": "hs://s00084bf87dfa89a...",\n "protocol": "tcp"\n },\n {\n "name": "api",\n "hash": "hs://s00091c2e8fa9b0b...",\n "protocol": "tcp"\n },\n {\n "name": "game",\n "hash": "hs://s000a2d3f9b1c2d3...",\n "protocol": "udp"\n }\n ],\n "timestamp": 1234567890\n}'} language="json" />
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3 mt-6">Step 2: Bob Discovers and Subscribes to Services</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-700 dark:text-gray-300 mb-4">
|
||||
<h4 className="text-xl font-semibold text-white mb-3 mt-6">Step 2: Bob Discovers and Subscribes to Services</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li>Bob opens the P2NS admin panel and navigates to the "Service Subscription" modal</li>
|
||||
<li>He searches for <code className="bg-gray-200 dark:bg-gray-700 px-1.5 py-0.5 rounded">alice.services</code> and sees all three available services</li>
|
||||
<li>He searches for <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">alice.services</code> and sees all three available services</li>
|
||||
<li>Bob has two options:
|
||||
<ul className="list-disc pl-6 mt-2 space-y-1">
|
||||
<li><strong>Subscribe to individual services:</strong> He selects just the "web" and "api" services</li>
|
||||
<li><strong>Subscribe to all:</strong> He enables "Subscribe All" for <code className="bg-gray-200 dark:bg-gray-700 px-1.5 py-0.5 rounded">alice.services</code></li>
|
||||
<li><strong>Subscribe to all:</strong> He enables "Subscribe All" for <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">alice.services</code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Bob chooses "Subscribe All" - this means he'll automatically get all current and future services from Alice</li>
|
||||
<li>P2NS automatically creates Holesail clients for all three services:
|
||||
<ul className="list-disc pl-6 mt-2 space-y-1">
|
||||
<li><code className="bg-gray-200 dark:bg-gray-700 px-1.5 py-0.5 rounded">alice.services_web</code> (TCP client)</li>
|
||||
<li><code className="bg-gray-200 dark:bg-gray-700 px-1.5 py-0.5 rounded">alice.services_api</code> (TCP client)</li>
|
||||
<li><code className="bg-gray-200 dark:bg-gray-700 px-1.5 py-0.5 rounded">alice.services_game</code> (UDP client)</li>
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">alice.services_web</code> (TCP client)</li>
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">alice.services_api</code> (TCP client)</li>
|
||||
<li><code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">alice.services_game</code> (UDP client)</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Each client establishes a Holesail connection to the corresponding service</li>
|
||||
<li>Bob's subscription preferences are saved locally in <code className="bg-gray-200 dark:bg-gray-700 px-1.5 py-0.5 rounded">cache/subscriptions.json</code></li>
|
||||
<li>Bob's subscription preferences are saved locally in <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">cache/subscriptions.json</code></li>
|
||||
</ul>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3 mt-6">Step 3: Dynamic Synchronization - Alice Adds a New Service</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-700 dark:text-gray-300 mb-4">
|
||||
<h4 className="text-xl font-semibold text-white mb-3 mt-6">Step 3: Dynamic Synchronization - Alice Adds a New Service</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li>Later, Alice adds a fourth service: "chat" server on port 9000 (TCP)</li>
|
||||
<li>She uses the admin panel's "Create Client" button to add the new service to her domain</li>
|
||||
<li>The system automatically updates her domain's claim record to include the new service</li>
|
||||
<li>The updated claim record is automatically synced to all peers</li>
|
||||
<li>Bob's P2NS node detects the change in the claim record (via AutoPass update events)</li>
|
||||
<li>Since Bob has "Subscribe All" enabled for <code className="bg-gray-200 dark:bg-gray-700 px-1.5 py-0.5 rounded">alice.services</code>, P2NS automatically:
|
||||
<li>Since Bob has "Subscribe All" enabled for <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">alice.services</code>, P2NS automatically:
|
||||
<ul className="list-disc pl-6 mt-2 space-y-1">
|
||||
<li>Creates a new Holesail client: <code className="bg-gray-200 dark:bg-gray-700 px-1.5 py-0.5 rounded">alice.services_chat</code></li>
|
||||
<li>Creates a new Holesail client: <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">alice.services_chat</code></li>
|
||||
<li>Establishes the connection</li>
|
||||
<li>Updates Bob's subscription list</li>
|
||||
</ul>
|
||||
@@ -613,8 +613,8 @@ export default function HowItWorksPage() {
|
||||
<li>Bob can now access the chat service without any manual configuration!</li>
|
||||
</ul>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3 mt-6">Step 4: Dynamic Synchronization - Alice Removes a Service</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-700 dark:text-gray-300 mb-4">
|
||||
<h4 className="text-xl font-semibold text-white mb-3 mt-6">Step 4: Dynamic Synchronization - Alice Removes a Service</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li>Alice decides to shut down her "game" server</li>
|
||||
<li>She uses the admin panel to delete the Holesail client for the "game" service</li>
|
||||
<li>The system automatically removes it from her domain's claim record</li>
|
||||
@@ -622,7 +622,7 @@ export default function HowItWorksPage() {
|
||||
<li>Bob's P2NS node detects the service was removed</li>
|
||||
<li>P2NS automatically:
|
||||
<ul className="list-disc pl-6 mt-2 space-y-1">
|
||||
<li>Stops and deletes the <code className="bg-gray-200 dark:bg-gray-700 px-1.5 py-0.5 rounded">alice.services_game</code> Holesail client</li>
|
||||
<li>Stops and deletes the <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">alice.services_game</code> Holesail client</li>
|
||||
<li>Frees up the UDP port that was being used</li>
|
||||
<li>Removes the service from Bob's subscription list</li>
|
||||
</ul>
|
||||
@@ -630,9 +630,9 @@ export default function HowItWorksPage() {
|
||||
<li>Bob's system is automatically cleaned up - no manual intervention needed!</li>
|
||||
</ul>
|
||||
|
||||
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3 mt-6">Step 5: Auto-Subscription on Bootup</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-700 dark:text-gray-300 mb-4">
|
||||
<li>When Bob restarts his P2NS node, the system loads his saved subscriptions from <code className="bg-gray-200 dark:bg-gray-700 px-1.5 py-0.5 rounded">cache/subscriptions.json</code></li>
|
||||
<h4 className="text-xl font-semibold text-white mb-3 mt-6">Step 5: Auto-Subscription on Bootup</h4>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li>When Bob restarts his P2NS node, the system loads his saved subscriptions from <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">cache/subscriptions.json</code></li>
|
||||
<li>For each subscribed service, P2NS automatically:
|
||||
<ul className="list-disc pl-6 mt-2 space-y-1">
|
||||
<li>Creates the Holesail client</li>
|
||||
@@ -645,30 +645,30 @@ export default function HowItWorksPage() {
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<strong className="text-gray-900 dark:text-white">Key Benefits:</strong>
|
||||
<p className="text-mist mb-4">
|
||||
<strong className="text-white">Key Benefits:</strong>
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<li><strong className="text-gray-900 dark:text-white">Automatic Management:</strong> Services are automatically added/removed as domain owners update their offerings</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Persistent Subscriptions:</strong> Subscriptions survive reboots and are automatically restored</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Protocol Support:</strong> Works with both TCP and UDP services</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">Subscribe All:</strong> Option to automatically get all services from a domain, including future ones</li>
|
||||
<li><strong className="text-gray-900 dark:text-white">No Manual Configuration:</strong> Once subscribed, everything is managed automatically</li>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li><strong className="text-white">Automatic Management:</strong> Services are automatically added/removed as domain owners update their offerings</li>
|
||||
<li><strong className="text-white">Persistent Subscriptions:</strong> Subscriptions survive reboots and are automatically restored</li>
|
||||
<li><strong className="text-white">Protocol Support:</strong> Works with both TCP and UDP services</li>
|
||||
<li><strong className="text-white">Subscribe All:</strong> Option to automatically get all services from a domain, including future ones</li>
|
||||
<li><strong className="text-white">No Manual Configuration:</strong> Once subscribed, everything is managed automatically</li>
|
||||
</ul>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
<strong className="text-gray-900 dark:text-white">The Power:</strong> Service subscriptions make it easy for peers to discover and connect to services across the network.
|
||||
<p className="text-mist mb-6">
|
||||
<strong className="text-white">The Power:</strong> Service subscriptions make it easy for peers to discover and connect to services across the network.
|
||||
Domain owners can offer multiple services, and subscribers can automatically access them all with minimal configuration.
|
||||
The system handles all the complexity of connection management, protocol differences, and dynamic updates.
|
||||
</p>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Related Documentation</h2>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||
<li><a href="/docs/getting-started" className="text-blue-600 dark:text-blue-400 hover:underline">Getting Started</a> — install, genesis/joiner roles, first domain</li>
|
||||
<li><a href="/docs/architecture" className="text-blue-600 dark:text-blue-400 hover:underline">Architecture</a> — modules, Core RPC, plugins, logging</li>
|
||||
<li><a href="/docs/configuration" className="text-blue-600 dark:text-blue-400 hover:underline">Configuration</a> — environment variables and defaults</li>
|
||||
<li><a href="/docs/upgrading" className="text-blue-600 dark:text-blue-400 hover:underline">Upgrading</a> — coordinated upgrades and <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--clean</code></li>
|
||||
<li><a href="/docs/plugins" className="text-blue-600 dark:text-blue-400 hover:underline">Built-in Plugins</a> — peer.directory, peer.paste, and more</li>
|
||||
<li><a href="/learn/p2p" className="text-blue-600 dark:text-blue-400 hover:underline">How P2P Works</a> — NAT, HyperDHT, and the Holepunch stack</li>
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">Related Documentation</h2>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist">
|
||||
<li><a href="/docs/getting-started" className="text-indigo-light hover:underline">Getting Started</a> — install, genesis/joiner roles, first domain</li>
|
||||
<li><a href="/docs/architecture" className="text-indigo-light hover:underline">Architecture</a> — modules, Core RPC, plugins, logging</li>
|
||||
<li><a href="/docs/configuration" className="text-indigo-light hover:underline">Configuration</a> — environment variables and defaults</li>
|
||||
<li><a href="/docs/upgrading" className="text-indigo-light hover:underline">Upgrading</a> — coordinated upgrades and <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--clean</code></li>
|
||||
<li><a href="/docs/plugins" className="text-indigo-light hover:underline">Built-in Plugins</a> — peer.directory, peer.paste, and more</li>
|
||||
<li><a href="/learn/p2p" className="text-indigo-light hover:underline">How P2P Works</a> — NAT, HyperDHT, and the Holepunch stack</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
+40
-42
@@ -1,24 +1,30 @@
|
||||
import type { Metadata } from 'next';
|
||||
import Link from 'next/link';
|
||||
import { Book, Settings, Code, Wrench, Network, FileText, LayoutDashboard, ArrowUpCircle, Puzzle, GitBranch } from 'lucide-react';
|
||||
import {
|
||||
Book,
|
||||
Settings,
|
||||
Wrench,
|
||||
Network,
|
||||
FileText,
|
||||
LayoutDashboard,
|
||||
ArrowUpCircle,
|
||||
Puzzle,
|
||||
GitBranch,
|
||||
} from 'lucide-react';
|
||||
import PageHeader from '@/components/ui/PageHeader';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Documentation - P2NS',
|
||||
description: 'Complete documentation for P2NS including installation, configuration, API reference, and troubleshooting.',
|
||||
keywords: ['P2NS documentation', 'P2NS docs', 'installation guide', 'configuration', 'API reference', 'troubleshooting'],
|
||||
authors: [{ name: 'Raven Scott' }],
|
||||
title: 'Documentation',
|
||||
description:
|
||||
'Complete documentation for P2NS including installation, configuration, API reference, and troubleshooting.',
|
||||
openGraph: {
|
||||
title: 'Documentation - P2NS',
|
||||
description: 'Complete documentation for P2NS including installation, configuration, API reference, and troubleshooting.',
|
||||
title: 'Documentation · P2NS',
|
||||
description:
|
||||
'Complete documentation for P2NS including installation, configuration, API reference, and troubleshooting.',
|
||||
url: 'https://p2ns.space/docs',
|
||||
siteName: 'P2NS',
|
||||
type: 'website',
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: 'Documentation - P2NS',
|
||||
description: 'Complete documentation for P2NS including installation, configuration, API reference, and troubleshooting.',
|
||||
},
|
||||
alternates: {
|
||||
canonical: 'https://p2ns.space/docs',
|
||||
},
|
||||
@@ -27,7 +33,7 @@ export const metadata: Metadata = {
|
||||
const docSections = [
|
||||
{
|
||||
title: 'Getting Started',
|
||||
description: 'Installation guide, prerequisites, and quick start instructions',
|
||||
description: 'Installation, prerequisites, and quick start for genesis, masters, and joiners',
|
||||
icon: Book,
|
||||
href: '/docs/getting-started',
|
||||
},
|
||||
@@ -39,43 +45,43 @@ const docSections = [
|
||||
},
|
||||
{
|
||||
title: 'Configuration',
|
||||
description: 'Environment variables, setup files, and configuration options',
|
||||
description: 'Environment variables, paths, and runtime options',
|
||||
icon: Settings,
|
||||
href: '/docs/configuration',
|
||||
},
|
||||
{
|
||||
title: 'Admin Panel',
|
||||
description: 'Complete guide to the web-based admin interface and its features',
|
||||
description: 'Web UI for domains, peers, logs, stats, and plugins',
|
||||
icon: LayoutDashboard,
|
||||
href: '/docs/admin-panel',
|
||||
},
|
||||
{
|
||||
title: 'API Reference',
|
||||
description: 'Complete REST API documentation and WebSocket events',
|
||||
description: 'REST endpoints and WebSocket events',
|
||||
icon: FileText,
|
||||
href: '/docs/api',
|
||||
},
|
||||
{
|
||||
title: 'Troubleshooting',
|
||||
description: 'Common issues, solutions, and debugging tips',
|
||||
description: 'Common issues, diagnostics, and recovery steps',
|
||||
icon: Wrench,
|
||||
href: '/docs/troubleshooting',
|
||||
},
|
||||
{
|
||||
title: 'Architecture',
|
||||
description: 'Genesis vs joiner roles, Autopass writes, Autobase consensus sidecar, and multi-master design',
|
||||
description: 'Roles, Autopass writes, Autobase consensus, multi-master design',
|
||||
icon: Network,
|
||||
href: '/docs/architecture',
|
||||
},
|
||||
{
|
||||
title: 'How It Works',
|
||||
description: 'End-to-end flows for DNS resolution, tunneling, and consensus',
|
||||
description: 'End-to-end DNS resolution, tunneling, and consensus flows',
|
||||
icon: GitBranch,
|
||||
href: '/docs/how-it-works',
|
||||
},
|
||||
{
|
||||
title: 'Built-in Plugins',
|
||||
description: 'Overview of peer.directory, peer.paste, file.drop, and more',
|
||||
description: 'peer.directory, peer.paste, file.drop, and the plugin SDK',
|
||||
icon: Puzzle,
|
||||
href: '/docs/plugins',
|
||||
},
|
||||
@@ -83,40 +89,33 @@ const docSections = [
|
||||
|
||||
export default function DocsPage() {
|
||||
return (
|
||||
<div className="min-h-screen bg-[#111829]">
|
||||
<section className="py-20 bg-gradient-to-b from-blue-50 to-white dark:from-gray-900 dark:to-gray-800">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<h1 className="text-4xl sm:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
Documentation
|
||||
</h1>
|
||||
<p className="text-xl text-gray-600 dark:text-gray-300">
|
||||
Complete guides and references for using and understanding P2NS
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
<div className="min-h-screen bg-midnight">
|
||||
<PageHeader
|
||||
eyebrow="Docs"
|
||||
title="Documentation"
|
||||
description="Guides and references for installing, operating, and extending P2NS."
|
||||
/>
|
||||
|
||||
<section className="py-20 bg-white dark:bg-gray-900">
|
||||
<section className="py-16 sm:py-20">
|
||||
<div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
{docSections.map((section) => {
|
||||
const Icon = section.icon;
|
||||
return (
|
||||
<Link
|
||||
key={section.href}
|
||||
href={section.href}
|
||||
className="group bg-white dark:bg-gray-800 p-6 rounded-lg border border-gray-200 dark:border-gray-700 hover:border-blue-500 dark:hover:border-blue-500 transition-all hover:shadow-lg"
|
||||
className="group surface-card surface-card-hover p-6"
|
||||
>
|
||||
<div className="flex items-center space-x-3 mb-4">
|
||||
<div className="p-2 bg-blue-100 dark:bg-blue-900 rounded-lg group-hover:bg-blue-200 dark:group-hover:bg-blue-800 transition-colors">
|
||||
<Icon className="h-6 w-6 text-blue-600 dark:text-blue-400" />
|
||||
<div className="flex items-start gap-3 mb-3">
|
||||
<div className="p-2 bg-indigo-deep/80 border border-indigo-dark/40 rounded-lg shrink-0">
|
||||
<Icon className="h-5 w-5 text-indigo-light" aria-hidden />
|
||||
</div>
|
||||
<h2 className="text-xl font-semibold text-gray-900 dark:text-white">
|
||||
<h2 className="text-lg font-semibold text-white group-hover:text-indigo-pale transition-colors pt-1">
|
||||
{section.title}
|
||||
</h2>
|
||||
</div>
|
||||
<p className="text-gray-600 dark:text-gray-400">
|
||||
{section.description}
|
||||
</p>
|
||||
<p className="text-sm text-fog leading-relaxed">{section.description}</p>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
@@ -126,4 +125,3 @@ export default function DocsPage() {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+23
-23
@@ -86,24 +86,24 @@ const plugins = [
|
||||
export default function PluginsPage() {
|
||||
return (
|
||||
<div className="min-h-screen">
|
||||
<section className="py-20 bg-gradient-to-b from-blue-50 to-white dark:from-gray-900 dark:to-gray-800">
|
||||
<section className="py-20 bg-grid-fade border-b border-steel/40">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<h1 className="text-4xl sm:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
<h1 className="text-4xl sm:text-5xl font-bold text-white mb-6">
|
||||
Built-in Plugins
|
||||
</h1>
|
||||
<p className="text-xl text-gray-600 dark:text-gray-300">
|
||||
<p className="text-xl text-mist">
|
||||
Internal domains served by the P2NS plugin system
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="py-20 bg-white dark:bg-gray-900">
|
||||
<section className="py-20 bg-midnight">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-8">
|
||||
Plugin domains are auto-discovered from <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">plugin-sites/{domain}/config.json</code>.
|
||||
<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">p2ns.admin</code> is always treated as internal.
|
||||
<p className="text-mist mb-8">
|
||||
Plugin domains are auto-discovered from <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">plugin-sites/{domain}/config.json</code>.
|
||||
<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">p2ns.admin</code> is always treated as internal.
|
||||
Detailed API and development docs live in the{' '}
|
||||
<a href={`${repoBase}/docs/plugins/README.md`} target="_blank" rel="noopener noreferrer" className="text-blue-600 dark:text-blue-400 hover:underline">
|
||||
<a href={`${repoBase}/docs/plugins/README.md`} target="_blank" rel="noopener noreferrer" className="text-indigo-light hover:underline">
|
||||
main repository
|
||||
</a>.
|
||||
</p>
|
||||
@@ -112,27 +112,27 @@ export default function PluginsPage() {
|
||||
{plugins.map((plugin) => (
|
||||
<div
|
||||
key={plugin.name}
|
||||
className="border border-gray-200 dark:border-gray-700 rounded-lg p-6 bg-white dark:bg-gray-800"
|
||||
className="border border-steel rounded-lg p-6 bg-surface"
|
||||
>
|
||||
<div className="flex flex-wrap items-center gap-2 mb-2">
|
||||
<h2 className="text-xl font-semibold text-gray-900 dark:text-white">{plugin.name}</h2>
|
||||
<h2 className="text-xl font-semibold text-white">{plugin.name}</h2>
|
||||
{plugin.note && (
|
||||
<span className="text-xs font-medium px-2 py-0.5 rounded bg-amber-100 dark:bg-amber-900/40 text-amber-900 dark:text-amber-100">
|
||||
<span className="text-xs font-medium px-2 py-0.5 rounded bg-warning/15 text-warning">
|
||||
{plugin.note}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{plugin.url && (
|
||||
<p className="text-sm text-gray-500 dark:text-gray-400 mb-2">
|
||||
<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">{plugin.url}</code>
|
||||
<p className="text-sm text-fog mb-2">
|
||||
<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">{plugin.url}</code>
|
||||
</p>
|
||||
)}
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">{plugin.description}</p>
|
||||
<p className="text-mist mb-4">{plugin.description}</p>
|
||||
<a
|
||||
href={plugin.docHref}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center gap-1 text-blue-600 dark:text-blue-400 hover:underline text-sm"
|
||||
className="inline-flex items-center gap-1 text-indigo-light hover:underline text-sm"
|
||||
>
|
||||
{plugin.docLabel}
|
||||
<ExternalLink className="h-3.5 w-3.5" />
|
||||
@@ -141,23 +141,23 @@ export default function PluginsPage() {
|
||||
))}
|
||||
</div>
|
||||
|
||||
<h2 className="text-2xl font-bold text-gray-900 dark:text-white mt-12 mb-4">Plugin authors</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
Custom plugins use protomux RPC via <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">sdk.channels.register</code>.
|
||||
<h2 className="text-2xl font-bold text-white mt-12 mb-4">Plugin authors</h2>
|
||||
<p className="text-mist mb-4">
|
||||
Custom plugins use protomux RPC via <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">sdk.channels.register</code>.
|
||||
Legacy message channels are no longer supported.
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist">
|
||||
<li>
|
||||
<a href={`${repoBase}/docs/plugins/PLUGIN_SDK.md`} target="_blank" rel="noopener noreferrer" className="text-blue-600 dark:text-blue-400 hover:underline">Plugin SDK</a>
|
||||
<a href={`${repoBase}/docs/plugins/PLUGIN_SDK.md`} target="_blank" rel="noopener noreferrer" className="text-indigo-light hover:underline">Plugin SDK</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href={`${repoBase}/docs/plugins/PLUGIN_CHANNELS.md`} target="_blank" rel="noopener noreferrer" className="text-blue-600 dark:text-blue-400 hover:underline">Plugin RPC</a>
|
||||
<a href={`${repoBase}/docs/plugins/PLUGIN_CHANNELS.md`} target="_blank" rel="noopener noreferrer" className="text-indigo-light hover:underline">Plugin RPC</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href={`${repoBase}/docs/plugins/HYPERDB.md`} target="_blank" rel="noopener noreferrer" className="text-blue-600 dark:text-blue-400 hover:underline">HyperDB</a>
|
||||
<a href={`${repoBase}/docs/plugins/HYPERDB.md`} target="_blank" rel="noopener noreferrer" className="text-indigo-light hover:underline">HyperDB</a>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/docs/upgrading" className="text-blue-600 dark:text-blue-400 hover:underline">Upgrading</Link> (breaking changes)
|
||||
<Link href="/docs/upgrading" className="text-indigo-light hover:underline">Upgrading</Link> (breaking changes)
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -26,21 +26,21 @@ export const metadata: Metadata = {
|
||||
export default function TroubleshootingPage() {
|
||||
return (
|
||||
<div className="min-h-screen">
|
||||
<section className="py-20 bg-gradient-to-b from-blue-50 to-white dark:from-gray-900 dark:to-gray-800">
|
||||
<section className="py-20 bg-grid-fade border-b border-steel/40">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<h1 className="text-4xl sm:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
<h1 className="text-4xl sm:text-5xl font-bold text-white mb-6">
|
||||
Troubleshooting
|
||||
</h1>
|
||||
<p className="text-xl text-gray-600 dark:text-gray-300">
|
||||
<p className="text-xl text-mist">
|
||||
Common issues and their solutions
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="py-20 bg-white dark:bg-gray-900">
|
||||
<section className="py-20 bg-midnight">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6">Port Conflicts</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h2 className="text-3xl font-bold text-white mb-6">Port Conflicts</h2>
|
||||
<p className="text-mist mb-4">
|
||||
If you encounter port conflicts, check which processes are using the ports:
|
||||
</p>
|
||||
<CodeBlock code={`# Check ports 53, 80, 443
|
||||
@@ -50,12 +50,12 @@ netstat -an | grep LISTEN | grep -E ':(53|80|443)'
|
||||
lsof -i :53
|
||||
lsof -i :80
|
||||
lsof -i :443`} />
|
||||
<p className="text-gray-600 dark:text-gray-300 mt-4">
|
||||
<strong>Solution:</strong> Stop conflicting services or set <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">DISABLE_DNS_SERVER=true</code> or <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">DISABLE_PROXY_SERVER=true</code> in your <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">.env</code> file.
|
||||
<p className="text-mist mt-4">
|
||||
<strong>Solution:</strong> Stop conflicting services or set <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">DISABLE_DNS_SERVER=true</code> or <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">DISABLE_PROXY_SERVER=true</code> in your <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">.env</code> file.
|
||||
</p>
|
||||
|
||||
<h2 id="certificate-authority-issues" className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Certificate Authority Issues</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h2 id="certificate-authority-issues" className="text-3xl font-bold text-white mb-6 mt-12">Certificate Authority Issues</h2>
|
||||
<p className="text-mist mb-4">
|
||||
If the root CA isn't trusted, you may see certificate errors in your browser. Verify installation:
|
||||
</p>
|
||||
<CodeBlock code={`# macOS - Check Keychain
|
||||
@@ -67,8 +67,8 @@ certutil -d sql:$HOME/.pki/nssdb -L | grep "P2NS CA"
|
||||
|
||||
# Windows - Check certificate store
|
||||
certutil -store -user ROOT | findstr P2NS`} />
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4 mt-4">
|
||||
<strong>Linux (Chrome/Chromium):</strong> Install the system CA <em>and</em> the NSS database. Requires <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">libnss3-tools</code> (Debian/Ubuntu) or <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">nss-tools</code> (Fedora) for <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">certutil</code>.
|
||||
<p className="text-mist mb-4 mt-4">
|
||||
<strong>Linux (Chrome/Chromium):</strong> Install the system CA <em>and</em> the NSS database. Requires <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">libnss3-tools</code> (Debian/Ubuntu) or <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">nss-tools</code> (Fedora) for <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">certutil</code>.
|
||||
</p>
|
||||
<CodeBlock code={`# 1. System trust store
|
||||
sudo cp ./certs/ca.cert.pem /usr/local/share/ca-certificates/p2ns-ca.crt
|
||||
@@ -82,12 +82,12 @@ certutil -d sql:$HOME/.pki/nssdb -A -t "C,," -n "P2NS CA" -i ./certs/ca.cert.pem
|
||||
# 3. Optional system NSS (RHEL/Fedora)
|
||||
sudo certutil -d sql:/etc/pki/nssdb -D -n "P2NS CA" 2>/dev/null || true
|
||||
sudo certutil -d sql:/etc/pki/nssdb -A -t "C,," -n "P2NS CA" -i ./certs/ca.cert.pem`} />
|
||||
<p className="text-gray-600 dark:text-gray-300 mt-4">
|
||||
Restart Chrome after installing. Use the admin panel to regenerate/install, or see the repository <a href="https://git.ssh.surf/snxraven/p2ns/src/branch/main/docs/CERTIFICATES.md" target="_blank" rel="noopener noreferrer" className="text-blue-600 dark:text-blue-400 hover:underline">CERTIFICATES.md</a>.
|
||||
<p className="text-mist mt-4">
|
||||
Restart Chrome after installing. Use the admin panel to regenerate/install, or see the repository <a href="https://git.ssh.surf/snxraven/p2ns/src/branch/main/docs/CERTIFICATES.md" target="_blank" rel="noopener noreferrer" className="text-indigo-light hover:underline">CERTIFICATES.md</a>.
|
||||
</p>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Holesail Connection Failures</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">Holesail Connection Failures</h2>
|
||||
<p className="text-mist mb-4">
|
||||
If Holesail connections fail, verify the hash is correct:
|
||||
</p>
|
||||
<CodeBlock code={`# Test hash generation
|
||||
@@ -96,12 +96,12 @@ holesail --live 80
|
||||
# Check Holesail CLI is installed
|
||||
which holesail
|
||||
npm list -g holesail`} />
|
||||
<p className="text-gray-600 dark:text-gray-300 mt-4">
|
||||
<strong>Solution:</strong> Ensure Holesail CLI is installed globally (<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">npm install -g holesail</code>) and the hash is valid.
|
||||
<p className="text-mist mt-4">
|
||||
<strong>Solution:</strong> Ensure Holesail CLI is installed globally (<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">npm install -g holesail</code>) and the hash is valid.
|
||||
</p>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">DNS Resolution Issues</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">DNS Resolution Issues</h2>
|
||||
<p className="text-mist mb-4">
|
||||
If domains aren't resolving, check several things:
|
||||
</p>
|
||||
<CodeBlock code={`# Test DNS resolution
|
||||
@@ -112,18 +112,18 @@ curl -k https://p2ns.admin/api/status
|
||||
|
||||
# Verify peer connections
|
||||
curl -k https://p2ns.admin/api/peers`} />
|
||||
<p className="text-gray-600 dark:text-gray-300 mt-4">
|
||||
<p className="text-mist mt-4">
|
||||
<strong>Common causes:</strong>
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist">
|
||||
<li>No peers connected - check swarm logs</li>
|
||||
<li>Domain not claimed - verify in domains.json or admin interface</li>
|
||||
<li>DNS conflict - check selector_cache.json preferences</li>
|
||||
<li>Local DNS override - check local_dns.json</li>
|
||||
</ul>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Interface Issues</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">Interface Issues</h2>
|
||||
<p className="text-mist mb-4">
|
||||
Virtual interface creation requires sudo privileges:
|
||||
</p>
|
||||
<CodeBlock code={`# macOS - Check interfaces
|
||||
@@ -134,80 +134,80 @@ ip addr show lo
|
||||
|
||||
# Verify IP assignments
|
||||
curl -k https://p2ns.admin/api/interfaces`} />
|
||||
<p className="text-gray-600 dark:text-gray-300 mt-4">
|
||||
<p className="text-mist mt-4">
|
||||
<strong>Solution:</strong> Ensure you're running with sudo and the interface name is correct for your platform.
|
||||
</p>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Admin Interface Not Loading</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">Admin Interface Not Loading</h2>
|
||||
<p className="text-mist mb-4">
|
||||
If the admin interface doesn't load:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||
<li>Verify <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">p2ns.admin</code> resolves to 127.0.0.1</li>
|
||||
<li>Check WebSocket connection at <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">wss://p2ns.admin/ws</code></li>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist">
|
||||
<li>Verify <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">p2ns.admin</code> resolves to 127.0.0.1</li>
|
||||
<li>Check WebSocket connection at <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">wss://p2ns.admin/ws</code></li>
|
||||
<li>Verify certificate is trusted</li>
|
||||
<li>Check browser console for errors</li>
|
||||
</ul>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Upgrade and Version Mismatch</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">Upgrade and Version Mismatch</h2>
|
||||
<p className="text-mist mb-4">
|
||||
After upgrading P2NS, all peers must run the same version. Mixed RPC/legacy nodes break invites and plugin communication.
|
||||
See the <a href="/docs/upgrading" className="text-blue-600 dark:text-blue-400 hover:underline">Upgrading</a> guide.
|
||||
See the <a href="/docs/upgrading" className="text-indigo-light hover:underline">Upgrading</a> guide.
|
||||
</p>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<p className="text-mist mb-4">
|
||||
After a Holepunch stack upgrade, wipe storage on every node:
|
||||
</p>
|
||||
<CodeBlock code="sudo node p2ns.js --clean [--master] [--genesis]" />
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Consensus sidecar not ready</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">Consensus sidecar not ready</h2>
|
||||
<p className="text-mist mb-4">
|
||||
If domains show unresolved consensus or logs mention local hash fallback, the Autobase consensus sidecar may not be bootstrapped yet:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<li>Check <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/consensus/status</code> — confirm <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">open</code>, <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">ready</code>, and <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">bootstrapComplete</code></li>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li>Check <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">GET /api/consensus/status</code> — confirm <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">open</code>, <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">ready</code>, and <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">bootstrapComplete</code></li>
|
||||
<li>Ensure dnsPass is initialized (master paired or joiner invited) before expecting resolved consensus</li>
|
||||
<li>Verify <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">cache/network.json</code> includes <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">consensusAutobaseKey</code> on joiners</li>
|
||||
<li>Tail the <strong>core</strong> log for <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">ConsensusAutobase</code> errors or <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">CONSENSUS_INIT_TIMEOUT_MS</code> timeouts</li>
|
||||
<li>Verify <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">cache/network.json</code> includes <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">consensusAutobaseKey</code> on joiners</li>
|
||||
<li>Tail the <strong>core</strong> log for <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">ConsensusAutobase</code> errors or <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">CONSENSUS_INIT_TIMEOUT_MS</code> timeouts</li>
|
||||
<li>Restart the node; bootstrap/hydration replays claim/vote entries from the local dnsPass copy</li>
|
||||
</ul>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Split network / wrong ledger</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
If peers connect on Hyperswarm but claims never converge, you may have two Autopass universes on the same <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">TOPIC_SEED</code> (historically caused by multiple <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--master</code> nodes on empty storage). Current releases require explicit <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--genesis</code> to create a ledger.
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">Split network / wrong ledger</h2>
|
||||
<p className="text-mist mb-4">
|
||||
If peers connect on Hyperswarm but claims never converge, you may have two Autopass universes on the same <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">TOPIC_SEED</code> (historically caused by multiple <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--master</code> nodes on empty storage). Current releases require explicit <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--genesis</code> to create a ledger.
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li>Open admin <strong>Stats → Core RPC</strong> or run invite diagnostics — check <strong>Network ID</strong> and split-network warnings</li>
|
||||
<li>Ensure only one genesis per network; secondary masters use <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--master</code> without <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--genesis</code></li>
|
||||
<li>Compare <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">cache/network.json</code> <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">networkId</code> across nodes</li>
|
||||
<li>Recovery: stop stray nodes, <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--clean</code> on affected machines, restart one genesis, then re-pair joiners and secondary masters</li>
|
||||
<li>Ensure only one genesis per network; secondary masters use <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--master</code> without <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--genesis</code></li>
|
||||
<li>Compare <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">cache/network.json</code> <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">networkId</code> across nodes</li>
|
||||
<li>Recovery: stop stray nodes, <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--clean</code> on affected machines, restart one genesis, then re-pair joiners and secondary masters</li>
|
||||
</ul>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Sync and Invite Issues</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">Sync and Invite Issues</h2>
|
||||
<p className="text-mist mb-4">
|
||||
If domains aren't syncing or joiners never receive invites:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li>Confirm all peers upgraded together (no mixed versions)</li>
|
||||
<li>Check admin Stats → Core RPC invite diagnostics</li>
|
||||
<li>Use <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/diagnostics/invites</code></li>
|
||||
<li>Use <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">GET /api/diagnostics/invites</code></li>
|
||||
<li>Tail the <strong>core</strong> log channel in the admin Logs tab</li>
|
||||
</ul>
|
||||
<CodeBlock code={`# Reset storage (WARNING: deletes all data)
|
||||
sudo node p2ns.js --clean --master --genesis`} />
|
||||
<p className="text-gray-600 dark:text-gray-300 mt-4">
|
||||
<p className="text-mist mt-4">
|
||||
<strong>Solution:</strong> Ensure peers are connected on Hyperswarm, verify Core RPC invite flow, and use --clean if storage is from an older stack.
|
||||
</p>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Getting Help</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300">
|
||||
<h2 className="text-3xl font-bold text-white mb-6 mt-12">Getting Help</h2>
|
||||
<p className="text-mist">
|
||||
If you're still experiencing issues:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist">
|
||||
<li>Check split logs in the admin Logs tab (select core, dns, or plugins channel)</li>
|
||||
<li>Read <a href="/docs/upgrading" className="text-blue-600 dark:text-blue-400 hover:underline">Upgrading</a> for breaking changes</li>
|
||||
<li>Review the <a href="/docs/architecture" className="text-blue-600 dark:text-blue-400 hover:underline">Architecture</a> documentation</li>
|
||||
<li>Check the <a href="https://git.ssh.surf/snxraven/p2ns" target="_blank" rel="noopener noreferrer" className="text-blue-600 dark:text-blue-400 hover:underline">repository</a> for known issues</li>
|
||||
<li>Enable debug logging by setting <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">LOG_LEVEL=0</code> in your .env</li>
|
||||
<li>Read <a href="/docs/upgrading" className="text-indigo-light hover:underline">Upgrading</a> for breaking changes</li>
|
||||
<li>Review the <a href="/docs/architecture" className="text-indigo-light hover:underline">Architecture</a> documentation</li>
|
||||
<li>Check the <a href="https://git.ssh.surf/snxraven/p2ns" target="_blank" rel="noopener noreferrer" className="text-indigo-light hover:underline">repository</a> for known issues</li>
|
||||
<li>Enable debug logging by setting <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">LOG_LEVEL=0</code> in your .env</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
+68
-68
@@ -29,145 +29,145 @@ const repoBase = 'https://git.ssh.surf/snxraven/p2ns/src/branch/main';
|
||||
export default function UpgradingPage() {
|
||||
return (
|
||||
<div className="min-h-screen">
|
||||
<section className="py-20 bg-gradient-to-b from-blue-50 to-white dark:from-gray-900 dark:to-gray-800">
|
||||
<section className="py-20 bg-grid-fade border-b border-steel/40">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<h1 className="text-4xl sm:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
<h1 className="text-4xl sm:text-5xl font-bold text-white mb-6">
|
||||
Upgrading P2NS
|
||||
</h1>
|
||||
<p className="text-xl text-gray-600 dark:text-gray-300">
|
||||
<p className="text-xl text-mist">
|
||||
Safe upgrade steps for breaking releases and storage migrations
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="py-20 bg-white dark:bg-gray-900">
|
||||
<section className="py-20 bg-midnight">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="bg-amber-50 dark:bg-amber-900/30 border-l-4 border-amber-500 p-4 rounded mb-8">
|
||||
<p className="text-amber-900 dark:text-amber-100">
|
||||
<div className="bg-warning/10 border-l-4 border-warning p-4 rounded mb-8">
|
||||
<p className="text-warning">
|
||||
<strong>Important:</strong> Recent releases include breaking changes to the core invite protocol
|
||||
and plugin peer communication. All peers on a network must upgrade together. Mixed old and new
|
||||
versions will not interoperate for invites or plugin RPC.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6">Coordinated upgrade</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h2 className="text-3xl font-bold text-white mb-6">Coordinated upgrade</h2>
|
||||
<p className="text-mist mb-4">
|
||||
When upgrading across a release that changes the Holepunch stack, core RPC, or plugin protocols:
|
||||
</p>
|
||||
<ol className="list-decimal pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-6">
|
||||
<li>Pull the latest <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">p2ns</code> code on every node (master and joiners).</li>
|
||||
<li>Run <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">npm install</code> on each node.</li>
|
||||
<ol className="list-decimal pl-6 space-y-2 text-mist mb-6">
|
||||
<li>Pull the latest <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">p2ns</code> code on every node (master and joiners).</li>
|
||||
<li>Run <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">npm install</code> on each node.</li>
|
||||
<li>Stop all running nodes.</li>
|
||||
<li>Reset storage on each node (see below) if required for your upgrade path.</li>
|
||||
<li>Start genesis master first (<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--master --genesis</code> for a new network), then secondary masters and joiners.</li>
|
||||
<li>Start genesis master first (<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--master --genesis</code> for a new network), then secondary masters and joiners.</li>
|
||||
</ol>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
Only <strong>one</strong> genesis per network. Additional masters use <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--master</code> without <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--genesis</code> and pair via invite. Existing single-master deployments auto-adopt <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">cache/network.json</code> on first boot with the new version.
|
||||
<p className="text-mist mb-6">
|
||||
Only <strong>one</strong> genesis per network. Additional masters use <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--master</code> without <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--genesis</code> and pair via invite. Existing single-master deployments auto-adopt <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">cache/network.json</code> on first boot with the new version.
|
||||
</p>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
Core control-plane traffic now uses protomux RPC only (<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">invite.request</code>,{' '}
|
||||
<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">invite.deliver</code>,{' '}
|
||||
<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">invite.ack</code>,{' '}
|
||||
<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">core.status</code>, consensus RPC). The legacy{' '}
|
||||
<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">p2ns.core-invite</code> protomux channel is removed.
|
||||
<p className="text-mist mb-6">
|
||||
Core control-plane traffic now uses protomux RPC only (<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">invite.request</code>,{' '}
|
||||
<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">invite.deliver</code>,{' '}
|
||||
<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">invite.ack</code>,{' '}
|
||||
<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">core.status</code>, consensus RPC). The legacy{' '}
|
||||
<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">p2ns.core-invite</code> protomux channel is removed.
|
||||
Plugin peer communication is also RPC-only.
|
||||
</p>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6">Autobase consensus sidecar</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h2 className="text-3xl font-bold text-white mb-6">Autobase consensus sidecar</h2>
|
||||
<p className="text-mist mb-4">
|
||||
Current releases use an Autobase apply-based consensus sidecar as the sole read path for domain resolution (RFC 0001).
|
||||
Autopass KV data is unchanged—upgrading rebuilds the sidecar from bootstrap replay of local claim/vote entries.
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-6">
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-6">
|
||||
<li>No storage wipe required solely for the consensus cutover if dnsPass data is intact</li>
|
||||
<li>After upgrade, verify <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/consensus/status</code> shows <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">bootstrapComplete: true</code></li>
|
||||
<li>Manifest gains <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">consensusAutobaseKey</code> on first genesis sidecar bootstrap</li>
|
||||
<li>After upgrade, verify <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">GET /api/consensus/status</code> shows <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">bootstrapComplete: true</code></li>
|
||||
<li>Manifest gains <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">consensusAutobaseKey</code> on first genesis sidecar bootstrap</li>
|
||||
<li>Rollback: deploy the previous P2NS release; Autopass data is unchanged</li>
|
||||
</ul>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6">When to reset storage</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h2 className="text-3xl font-bold text-white mb-6">When to reset storage</h2>
|
||||
<p className="text-mist mb-4">
|
||||
After a Holepunch stack upgrade (Corestore, Autopass, HyperDB, etc.), existing on-disk P2P storage
|
||||
may be incompatible. Wipe storage with <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--clean</code>:
|
||||
may be incompatible. Wipe storage with <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--clean</code>:
|
||||
</p>
|
||||
<CodeBlock code="sudo node p2ns.js --clean [--master] [--genesis]" />
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4 mt-4">
|
||||
Also use <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--clean</code> when:
|
||||
<p className="text-mist mb-4 mt-4">
|
||||
Also use <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--clean</code> when:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-6">
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-6">
|
||||
<li>Joiners repeatedly fail to accept invites after an upgrade</li>
|
||||
<li>Plugin HyperDB schema mismatches persist after a version bump</li>
|
||||
<li>You need a known-good fresh state for debugging</li>
|
||||
</ul>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--clean</code> clears Corestore data and resets plugin HyperDB storage.
|
||||
<p className="text-mist mb-6">
|
||||
<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--clean</code> clears Corestore data and resets plugin HyperDB storage.
|
||||
The admin panel storage-clean action includes the same plugin storage scope. Back up{' '}
|
||||
<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">STORAGE_DIR</code> and{' '}
|
||||
<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">cache/</code> first if you need to preserve domains or local DNS.
|
||||
<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">STORAGE_DIR</code> and{' '}
|
||||
<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">cache/</code> first if you need to preserve domains or local DNS.
|
||||
</p>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6">Shared Corestore namespaces</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">USE_SHARED_CORESTORE_NAMESPACES</code> defaults to{' '}
|
||||
<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">true</code>.
|
||||
<h2 className="text-3xl font-bold text-white mb-6">Shared Corestore namespaces</h2>
|
||||
<p className="text-mist mb-6">
|
||||
<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">USE_SHARED_CORESTORE_NAMESPACES</code> defaults to{' '}
|
||||
<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">true</code>.
|
||||
Plugin databases and drives use shared namespaces on the main Corestore. Changing this after data
|
||||
exists may require a clean reset. See the{' '}
|
||||
<Link href="/docs/configuration" className="text-blue-600 dark:text-blue-400 hover:underline">Configuration</Link> guide.
|
||||
<Link href="/docs/configuration" className="text-indigo-light hover:underline">Configuration</Link> guide.
|
||||
</p>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6">Invite troubleshooting</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h2 className="text-3xl font-bold text-white mb-6">Invite troubleshooting</h2>
|
||||
<p className="text-mist mb-4">
|
||||
If peers connect but joiners never sync the dnsPass ledger:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-4">
|
||||
<li>Confirm every peer runs the same P2NS generation (no mixed RPC/legacy nodes).</li>
|
||||
<li>Open the admin <strong>Stats</strong> tab and review the <strong>Core RPC</strong> invite diagnostics section.</li>
|
||||
<li>Use <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/diagnostics/invites</code> for detailed invite RPC state.</li>
|
||||
<li>Tail the <strong>core</strong> log channel in the admin <strong>Logs</strong> tab (or <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">core.log</code> under <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">LOG_DIR</code>).</li>
|
||||
<li>Try <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--clean</code> on affected nodes if storage may be from an older stack.</li>
|
||||
<li>Use <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">GET /api/diagnostics/invites</code> for detailed invite RPC state.</li>
|
||||
<li>Tail the <strong>core</strong> log channel in the admin <strong>Logs</strong> tab (or <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">core.log</code> under <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">LOG_DIR</code>).</li>
|
||||
<li>Try <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--clean</code> on affected nodes if storage may be from an older stack.</li>
|
||||
</ul>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
Master nodes send proactive invites after <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">MASTER_PROACTIVE_INVITE_DELAY</code> (default 2000 ms).
|
||||
<p className="text-mist mb-6">
|
||||
Master nodes send proactive invites after <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">MASTER_PROACTIVE_INVITE_DELAY</code> (default 2000 ms).
|
||||
Autopass replication uses its own swarm; the p2ns Hyperswarm topic does not replicate dnsPass directly.
|
||||
</p>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6">Multi-master upgrade notes</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
<h2 className="text-3xl font-bold text-white mb-6">Multi-master upgrade notes</h2>
|
||||
<p className="text-mist mb-4">
|
||||
Releases with multi-master / one-ledger support change bootstrap behavior:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-6">
|
||||
<li>Existing single-master storage without <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">network.json</code> auto-adopts a manifest on first boot — no <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--genesis</code> required for migration</li>
|
||||
<li>Do not run <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--genesis</code> if a manifest already exists (use <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">--clean</code> only when intentionally resetting the network)</li>
|
||||
<li>Admin invite diagnostics show <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">networkId</code> and split-network warnings when peers disagree</li>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist mb-6">
|
||||
<li>Existing single-master storage without <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">network.json</code> auto-adopts a manifest on first boot — no <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--genesis</code> required for migration</li>
|
||||
<li>Do not run <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--genesis</code> if a manifest already exists (use <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">--clean</code> only when intentionally resetting the network)</li>
|
||||
<li>Admin invite diagnostics show <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">networkId</code> and split-network warnings when peers disagree</li>
|
||||
</ul>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6">Plugin authors</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
<h2 className="text-3xl font-bold text-white mb-6">Plugin authors</h2>
|
||||
<p className="text-mist mb-6">
|
||||
If you maintain custom plugins, migrate from legacy message channels to{' '}
|
||||
<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">sdk.channels.register</code> with RPC methods.
|
||||
<code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">sdk.channels.register</code> with RPC methods.
|
||||
See the repository{' '}
|
||||
<a href={`${repoBase}/docs/plugins/PLUGIN_CHANNELS.md`} target="_blank" rel="noopener noreferrer" className="text-blue-600 dark:text-blue-400 hover:underline">Plugin RPC</a>{' '}
|
||||
<a href={`${repoBase}/docs/plugins/PLUGIN_CHANNELS.md`} target="_blank" rel="noopener noreferrer" className="text-indigo-light hover:underline">Plugin RPC</a>{' '}
|
||||
and{' '}
|
||||
<a href={`${repoBase}/docs/plugins/PLUGIN_SDK.md`} target="_blank" rel="noopener noreferrer" className="text-blue-600 dark:text-blue-400 hover:underline">Plugin SDK</a>{' '}
|
||||
<a href={`${repoBase}/docs/plugins/PLUGIN_SDK.md`} target="_blank" rel="noopener noreferrer" className="text-indigo-light hover:underline">Plugin SDK</a>{' '}
|
||||
docs for migration tables and Core RPC methods.
|
||||
</p>
|
||||
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6">Further reading</h2>
|
||||
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||
<li><Link href="/docs/troubleshooting" className="text-blue-600 dark:text-blue-400 hover:underline">Troubleshooting</Link></li>
|
||||
<li><Link href="/docs/admin-panel" className="text-blue-600 dark:text-blue-400 hover:underline">Admin Panel</Link> (Logs, Stats, diagnostics)</li>
|
||||
<li><Link href="/docs/api" className="text-blue-600 dark:text-blue-400 hover:underline">API Reference</Link></li>
|
||||
<h2 className="text-3xl font-bold text-white mb-6">Further reading</h2>
|
||||
<ul className="list-disc pl-6 space-y-2 text-mist">
|
||||
<li><Link href="/docs/troubleshooting" className="text-indigo-light hover:underline">Troubleshooting</Link></li>
|
||||
<li><Link href="/docs/admin-panel" className="text-indigo-light hover:underline">Admin Panel</Link> (Logs, Stats, diagnostics)</li>
|
||||
<li><Link href="/docs/api" className="text-indigo-light hover:underline">API Reference</Link></li>
|
||||
<li>
|
||||
<a href={`${repoBase}/docs/RESTAPI.md`} target="_blank" rel="noopener noreferrer" className="text-blue-600 dark:text-blue-400 hover:underline">REST API (full reference)</a>
|
||||
<a href={`${repoBase}/docs/RESTAPI.md`} target="_blank" rel="noopener noreferrer" className="text-indigo-light hover:underline">REST API (full reference)</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href={`${repoBase}/docs/rfcs/0001-autobase-consensus.md`} target="_blank" rel="noopener noreferrer" className="text-blue-600 dark:text-blue-400 hover:underline">RFC 0001: Autobase consensus sidecar</a>
|
||||
<a href={`${repoBase}/docs/rfcs/0001-autobase-consensus.md`} target="_blank" rel="noopener noreferrer" className="text-indigo-light hover:underline">RFC 0001: Autobase consensus sidecar</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href={`${repoBase}/docs/CONSENSUS.md`} target="_blank" rel="noopener noreferrer" className="text-blue-600 dark:text-blue-400 hover:underline">Consensus mechanism (CONSENSUS.md)</a>
|
||||
<a href={`${repoBase}/docs/CONSENSUS.md`} target="_blank" rel="noopener noreferrer" className="text-indigo-light hover:underline">Consensus mechanism (CONSENSUS.md)</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href={`${repoBase}/docs/plugins/HYPERDB.md`} target="_blank" rel="noopener noreferrer" className="text-blue-600 dark:text-blue-400 hover:underline">HyperDB recovery and version migration</a>
|
||||
<a href={`${repoBase}/docs/plugins/HYPERDB.md`} target="_blank" rel="noopener noreferrer" className="text-indigo-light hover:underline">HyperDB recovery and version migration</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
+21
-21
@@ -268,19 +268,19 @@ export default function FeaturesPage() {
|
||||
return (
|
||||
<div className="min-h-screen">
|
||||
{/* Hero */}
|
||||
<section className="py-20 bg-gradient-to-b from-blue-50 to-white dark:from-gray-900 dark:to-gray-800">
|
||||
<section className="py-20 bg-grid-fade border-b border-steel/40">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
||||
<h1 className="text-4xl sm:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
<h1 className="text-4xl sm:text-5xl font-bold text-white mb-6">
|
||||
Comprehensive Features
|
||||
</h1>
|
||||
<p className="text-xl text-gray-600 dark:text-gray-300">
|
||||
<p className="text-xl text-mist">
|
||||
P2NS provides everything you need to build and manage a decentralized DNS network
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Features List */}
|
||||
<section className="py-20 bg-white dark:bg-gray-900">
|
||||
<section className="py-20 bg-midnight">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="space-y-24">
|
||||
{features.map((feature, index) => {
|
||||
@@ -296,33 +296,33 @@ export default function FeaturesPage() {
|
||||
className="grid md:grid-cols-3 gap-8 items-start"
|
||||
>
|
||||
<div className="md:col-span-1">
|
||||
<div className="inline-flex p-4 rounded-lg bg-gradient-to-r from-blue-500 to-purple-500 mb-4">
|
||||
<Icon className="h-8 w-8 text-white" />
|
||||
<div className="inline-flex p-3.5 rounded-lg bg-indigo-deep/80 border border-indigo-dark/40 mb-4">
|
||||
<Icon className="h-7 w-7 text-indigo-light" />
|
||||
</div>
|
||||
<h2 className="text-2xl font-bold text-gray-900 dark:text-white mb-3">
|
||||
<h2 className="text-2xl font-bold text-white mb-3">
|
||||
{feature.name}
|
||||
</h2>
|
||||
<p className="text-gray-600 dark:text-gray-300">{feature.description}</p>
|
||||
<p className="text-mist">{feature.description}</p>
|
||||
</div>
|
||||
|
||||
<div className="md:col-span-2 space-y-6">
|
||||
<div>
|
||||
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-4">
|
||||
<h3 className="text-lg font-semibold text-white mb-4">
|
||||
Key Benefits
|
||||
</h3>
|
||||
<ul className="grid sm:grid-cols-2 gap-3">
|
||||
{feature.benefits.map((benefit) => (
|
||||
<li key={benefit} className="flex items-center gap-3">
|
||||
<CheckIcon className="h-5 w-5 text-green-500 flex-shrink-0" />
|
||||
<span className="text-gray-600 dark:text-gray-300">{benefit}</span>
|
||||
<CheckIcon className="h-5 w-5 text-success flex-shrink-0" />
|
||||
<span className="text-mist">{benefit}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className="bg-gray-50 dark:bg-gray-800 p-5 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||
<p className="text-sm text-gray-600 dark:text-gray-400">
|
||||
<strong className="text-gray-900 dark:text-white">Example:</strong>{' '}
|
||||
<div className="bg-deep p-5 rounded-lg border border-steel">
|
||||
<p className="text-sm text-fog">
|
||||
<strong className="text-white">Example:</strong>{' '}
|
||||
{feature.example}
|
||||
</p>
|
||||
</div>
|
||||
@@ -335,17 +335,17 @@ export default function FeaturesPage() {
|
||||
</section>
|
||||
|
||||
{/* CTA */}
|
||||
<section className="py-20 bg-gradient-to-r from-blue-600 to-purple-600">
|
||||
<section className="py-20 bg-deep border-t border-steel/40">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
||||
<h2 className="text-3xl font-bold text-white mb-4">Ready to Get Started?</h2>
|
||||
<p className="text-xl text-blue-100 mb-8">
|
||||
<h2 className="text-3xl font-bold text-white mb-4">Ready to get started?</h2>
|
||||
<p className="text-xl text-mist mb-8">
|
||||
Explore the documentation and start building with P2NS today
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center">
|
||||
<a
|
||||
href="/docs"
|
||||
className="px-8 py-3 border-2 border-white rounded-md text-white hover:bg-white hover:text-blue-600 transition-colors font-medium"
|
||||
>
|
||||
<a href="/docs/getting-started" className="btn-primary">
|
||||
Get Started
|
||||
</a>
|
||||
<a href="/docs" className="btn-secondary">
|
||||
View Documentation
|
||||
</a>
|
||||
</div>
|
||||
|
||||
+166
-72
@@ -1,12 +1,41 @@
|
||||
@import "tailwindcss";
|
||||
|
||||
:root {
|
||||
--background: #000000;
|
||||
--foreground: #171717;
|
||||
--font-inter: 'Inter', system-ui, sans-serif;
|
||||
--font-mono: 'JetBrains Mono', 'Fira Code', monospace;
|
||||
/* ─── P2NS Brand Tokens (dark-first, indigo-dominant) ─── */
|
||||
@theme {
|
||||
--color-midnight: #0a0e1a;
|
||||
--color-deep: #0f1419;
|
||||
--color-surface: #1a1f2e;
|
||||
--color-steel: #2d3446;
|
||||
--color-fog: #646e82;
|
||||
--color-mist: #94a3b8;
|
||||
--color-snow: #e2e8f0;
|
||||
|
||||
--color-indigo-deep: #1e2050;
|
||||
--color-indigo-dark: #3b3e96;
|
||||
--color-indigo: #6366f1;
|
||||
--color-indigo-light: #8184f5;
|
||||
--color-indigo-pale: #a5a8f9;
|
||||
|
||||
--color-violet-accent: #a855f7;
|
||||
--color-pink-accent: #ec4899;
|
||||
--color-success: #10b981;
|
||||
--color-warning: #f59e0b;
|
||||
--color-danger: #ef4444;
|
||||
--color-info: #3b82f6;
|
||||
|
||||
--font-sans: var(--font-inter), ui-sans-serif, system-ui, sans-serif;
|
||||
--font-mono: var(--font-mono), ui-monospace, "JetBrains Mono", "Fira Code", monospace;
|
||||
|
||||
--background-image-grid: linear-gradient(to right, rgba(99, 102, 241, 0.06) 1px, transparent 1px),
|
||||
linear-gradient(to bottom, rgba(99, 102, 241, 0.06) 1px, transparent 1px);
|
||||
}
|
||||
|
||||
:root {
|
||||
--background: #0a0e1a;
|
||||
--foreground: #e2e8f0;
|
||||
--font-inter: "Inter", system-ui, sans-serif;
|
||||
--font-mono: "JetBrains Mono", "Fira Code", monospace;
|
||||
|
||||
/* Slim global scrollbar */
|
||||
--scrollbar-size: 6px;
|
||||
--scrollbar-track: transparent;
|
||||
--scrollbar-thumb: rgba(99, 102, 241, 0.28);
|
||||
@@ -15,27 +44,12 @@
|
||||
--scrollbar-corner: transparent;
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: #0a0a0a;
|
||||
--foreground: #ededed;
|
||||
--scrollbar-thumb: rgba(129, 140, 248, 0.32);
|
||||
--scrollbar-thumb-hover: rgba(129, 140, 248, 0.52);
|
||||
--scrollbar-thumb-active: rgba(165, 180, 252, 0.68);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root:not(.light) {
|
||||
--scrollbar-thumb: rgba(129, 140, 248, 0.32);
|
||||
--scrollbar-thumb-hover: rgba(129, 140, 248, 0.52);
|
||||
--scrollbar-thumb-active: rgba(165, 180, 252, 0.68);
|
||||
}
|
||||
}
|
||||
|
||||
/* Global slim scrollbar — Firefox */
|
||||
/* ─── Base ─── */
|
||||
html {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
|
||||
background: var(--background);
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
* {
|
||||
@@ -43,7 +57,6 @@ html {
|
||||
scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
|
||||
}
|
||||
|
||||
/* Global slim scrollbar — Chromium / Safari */
|
||||
*::-webkit-scrollbar {
|
||||
width: var(--scrollbar-size);
|
||||
height: var(--scrollbar-size);
|
||||
@@ -82,31 +95,132 @@ html {
|
||||
body {
|
||||
color: var(--foreground);
|
||||
background: var(--background);
|
||||
font-family: var(--font-inter);
|
||||
transition: background-color 0.2s ease, color 0.2s ease;
|
||||
font-family: var(--font-sans);
|
||||
min-height: 100vh;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
::selection {
|
||||
background: rgba(99, 102, 241, 0.35);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* ─── Utilities ─── */
|
||||
@layer utilities {
|
||||
.text-balance {
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
/* Smooth scrolling */
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
.bg-grid {
|
||||
background-image: var(--background-image-grid);
|
||||
background-size: 48px 48px;
|
||||
}
|
||||
|
||||
/* Focus styles for accessibility */
|
||||
*:focus-visible {
|
||||
outline: 2px solid rgb(59 130 246);
|
||||
.bg-grid-fade {
|
||||
background-image:
|
||||
radial-gradient(ellipse 80% 60% at 50% -10%, rgba(99, 102, 241, 0.14), transparent 55%),
|
||||
var(--background-image-grid);
|
||||
background-size: auto, 48px 48px;
|
||||
}
|
||||
|
||||
.surface-card {
|
||||
background-color: var(--color-surface);
|
||||
border: 1px solid var(--color-steel);
|
||||
border-radius: 0.75rem;
|
||||
}
|
||||
|
||||
.surface-card-hover {
|
||||
transition: border-color 0.15s ease, background-color 0.15s ease;
|
||||
}
|
||||
|
||||
.surface-card-hover:hover {
|
||||
border-color: rgba(99, 102, 241, 0.55);
|
||||
background-color: rgba(26, 31, 46, 0.9);
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.75rem 1.5rem;
|
||||
font-size: 0.9375rem;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
background-color: var(--color-indigo);
|
||||
border: 1px solid transparent;
|
||||
border-radius: 0.5rem;
|
||||
transition: background-color 0.15s ease;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background-color: var(--color-indigo-light);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.75rem 1.5rem;
|
||||
font-size: 0.9375rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-snow);
|
||||
background-color: transparent;
|
||||
border: 1px solid var(--color-steel);
|
||||
border-radius: 0.5rem;
|
||||
transition: border-color 0.15s ease, color 0.15s ease, background-color 0.15s ease;
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
border-color: var(--color-indigo);
|
||||
color: #fff;
|
||||
background-color: rgba(99, 102, 241, 0.08);
|
||||
}
|
||||
|
||||
.link-accent {
|
||||
color: var(--color-indigo-light);
|
||||
transition: color 0.15s ease;
|
||||
}
|
||||
|
||||
.link-accent:hover {
|
||||
color: var(--color-indigo-pale);
|
||||
}
|
||||
|
||||
.focus-ring:focus-visible {
|
||||
outline: 2px solid var(--color-indigo);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
/* Code block styling */
|
||||
pre {
|
||||
.prose-brand :not(pre) > code {
|
||||
background-color: var(--color-surface);
|
||||
color: var(--color-indigo-pale);
|
||||
padding: 0.125rem 0.375rem;
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.875rem;
|
||||
border: 1px solid var(--color-steel);
|
||||
}
|
||||
|
||||
.prose-brand pre {
|
||||
background-color: var(--color-deep);
|
||||
color: var(--color-snow);
|
||||
border: 1px solid var(--color-steel);
|
||||
border-radius: 0.5rem;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.prose-brand pre code {
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
border: none;
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
/* ─── Focus (global a11y) ─── */
|
||||
*:focus-visible {
|
||||
outline: 2px solid var(--color-indigo);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
code {
|
||||
@@ -114,41 +228,20 @@ body {
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
/* Prose adjustments */
|
||||
.prose :not(pre) > code {
|
||||
background-color: rgb(243 244 246);
|
||||
color: rgb(17 24 39);
|
||||
padding: 0.125rem 0.375rem;
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.dark .prose :not(pre) > code {
|
||||
background-color: rgb(55 65 81);
|
||||
color: rgb(229 231 235);
|
||||
}
|
||||
|
||||
.prose pre {
|
||||
background-color: rgb(17 24 39);
|
||||
color: rgb(243 244 246);
|
||||
}
|
||||
|
||||
.prose pre code {
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
color: rgb(243 244 246);
|
||||
}
|
||||
pre {
|
||||
border-radius: 0.5rem;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
/* ─── Legal prose (dark brand) ─── */
|
||||
@layer components {
|
||||
/* Text colors only — scoped to /legal routes via data-legal-page */
|
||||
[data-legal-page] .legal-prose {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.125rem;
|
||||
font-size: 1.0625rem;
|
||||
line-height: 1.75;
|
||||
color: rgb(229 231 235);
|
||||
color: var(--color-mist);
|
||||
}
|
||||
|
||||
[data-legal-page] .legal-prose > h2 {
|
||||
@@ -157,7 +250,7 @@ body {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.025em;
|
||||
color: rgb(255 255 255);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
[data-legal-page] .legal-prose > h2:first-child {
|
||||
@@ -173,7 +266,7 @@ body {
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
color: rgb(255 255 255);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
[data-legal-page] .legal-prose p,
|
||||
@@ -185,19 +278,19 @@ body {
|
||||
|
||||
[data-legal-page] .legal-prose a {
|
||||
font-weight: 500;
|
||||
color: rgb(147 197 253);
|
||||
color: var(--color-indigo-light);
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 3px;
|
||||
transition: color 0.15s ease;
|
||||
}
|
||||
|
||||
[data-legal-page] .legal-prose a:hover {
|
||||
color: rgb(191 219 254);
|
||||
color: var(--color-indigo-pale);
|
||||
}
|
||||
|
||||
[data-legal-page] .legal-prose strong {
|
||||
font-weight: 600;
|
||||
color: rgb(255 255 255);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
[data-legal-page] .legal-prose ul,
|
||||
@@ -216,14 +309,14 @@ body {
|
||||
}
|
||||
|
||||
[data-legal-page] .legal-prose ul > li::before {
|
||||
content: '';
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0.5rem;
|
||||
top: 0.65em;
|
||||
width: 0.375rem;
|
||||
height: 0.375rem;
|
||||
border-radius: 9999px;
|
||||
background-color: rgb(96 165 250);
|
||||
background-color: var(--color-indigo);
|
||||
}
|
||||
|
||||
[data-legal-page] .legal-prose ol {
|
||||
@@ -235,12 +328,12 @@ body {
|
||||
}
|
||||
|
||||
[data-legal-page] .legal-prose ol > li::before {
|
||||
content: counter(legal-ol) '.';
|
||||
content: counter(legal-ol) ".";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
font-weight: 600;
|
||||
font-size: 0.875rem;
|
||||
color: rgb(147 197 253);
|
||||
color: var(--color-indigo-light);
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
@@ -262,8 +355,9 @@ body {
|
||||
margin-bottom: 0;
|
||||
padding: 1rem 1.25rem;
|
||||
border-radius: 0.5rem;
|
||||
background-color: rgb(239 246 255);
|
||||
color: rgb(229 231 235);
|
||||
border: 1px solid var(--color-steel);
|
||||
background-color: var(--color-surface);
|
||||
color: var(--color-mist);
|
||||
font-size: 0.9375rem;
|
||||
}
|
||||
}
|
||||
|
||||
+63
-29
@@ -1,19 +1,41 @@
|
||||
import type { Metadata } from "next";
|
||||
import { Inter } from "next/font/google";
|
||||
import { Inter, JetBrains_Mono } from "next/font/google";
|
||||
import "./globals.css";
|
||||
import Navigation from "@/components/layout/Navigation";
|
||||
import Footer from "@/components/layout/Footer";
|
||||
|
||||
const inter = Inter({
|
||||
subsets: ["latin"],
|
||||
variable: '--font-inter',
|
||||
variable: "--font-inter",
|
||||
display: "swap",
|
||||
});
|
||||
|
||||
const jetbrainsMono = JetBrains_Mono({
|
||||
subsets: ["latin"],
|
||||
variable: "--font-mono",
|
||||
display: "swap",
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
metadataBase: new URL('https://p2ns.space'),
|
||||
title: "P2NS - Peer-to-Peer Decentralized DNS System",
|
||||
description: "A robust, firewall-resistant peer-to-peer DNS resolution system that operates independently of centralized DNS infrastructure.",
|
||||
keywords: ["P2P", "DNS", "decentralized", "peer-to-peer", "NAT traversal", "firewall", "Holesail", "Hyperswarm", "Corestore"],
|
||||
metadataBase: new URL("https://p2ns.space"),
|
||||
title: {
|
||||
default: "P2NS — Peer-to-Peer Name System",
|
||||
template: "%s · P2NS",
|
||||
},
|
||||
description:
|
||||
"Decentralized, secure, and censorship-resistant naming infrastructure for the open web. Firewall-resistant P2P DNS independent of ICANN.",
|
||||
keywords: [
|
||||
"P2P",
|
||||
"DNS",
|
||||
"decentralized",
|
||||
"peer-to-peer",
|
||||
"NAT traversal",
|
||||
"firewall",
|
||||
"Holesail",
|
||||
"Hyperswarm",
|
||||
"Corestore",
|
||||
"P2NS",
|
||||
],
|
||||
authors: [{ name: "HoneyPeer, LLC" }],
|
||||
creator: "HoneyPeer, LLC",
|
||||
publisher: "HoneyPeer, LLC",
|
||||
@@ -27,25 +49,27 @@ export const metadata: Metadata = {
|
||||
},
|
||||
manifest: "/site.webmanifest",
|
||||
openGraph: {
|
||||
title: "P2NS - Peer-to-Peer Decentralized DNS System",
|
||||
description: "A robust, firewall-resistant peer-to-peer DNS resolution system",
|
||||
title: "P2NS — Peer-to-Peer Name System",
|
||||
description:
|
||||
"Decentralized, secure, and censorship-resistant naming infrastructure for the open web.",
|
||||
url: "https://p2ns.space",
|
||||
siteName: "P2NS",
|
||||
type: "website",
|
||||
images: [
|
||||
{
|
||||
url: "/branding/p2ns-primary-horizontal.png",
|
||||
width: 1200,
|
||||
height: 630,
|
||||
url: "/branding/p2ns-hero-banner.png",
|
||||
width: 1600,
|
||||
height: 700,
|
||||
alt: "P2NS — Peer-to-Peer Name System",
|
||||
},
|
||||
],
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
title: "P2NS - Peer-to-Peer Decentralized DNS System",
|
||||
description: "A robust, firewall-resistant peer-to-peer DNS resolution system",
|
||||
images: ["/branding/p2ns-primary-horizontal.png"],
|
||||
title: "P2NS — Peer-to-Peer Name System",
|
||||
description:
|
||||
"Decentralized, secure, and censorship-resistant naming infrastructure for the open web.",
|
||||
images: ["/branding/p2ns-hero-banner.png"],
|
||||
},
|
||||
robots: {
|
||||
index: true,
|
||||
@@ -62,32 +86,42 @@ export default function RootLayout({
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
const jsonLd = {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'SoftwareApplication',
|
||||
name: 'P2NS',
|
||||
applicationCategory: 'NetworkApplication',
|
||||
operatingSystem: 'macOS, Linux',
|
||||
description: 'A robust, firewall-resistant peer-to-peer DNS resolution system',
|
||||
url: 'https://git.ssh.surf/snxraven/p2ns',
|
||||
"@context": "https://schema.org",
|
||||
"@type": "SoftwareApplication",
|
||||
name: "P2NS",
|
||||
applicationCategory: "NetworkApplication",
|
||||
operatingSystem: "macOS, Linux",
|
||||
description:
|
||||
"Decentralized, secure, and censorship-resistant peer-to-peer DNS resolution system",
|
||||
url: "https://p2ns.space",
|
||||
downloadUrl: "https://git.ssh.surf/snxraven/p2ns",
|
||||
author: {
|
||||
'@type': 'Organization',
|
||||
name: 'HoneyPeer, LLC',
|
||||
"@type": "Organization",
|
||||
name: "HoneyPeer, LLC",
|
||||
address: {
|
||||
'@type': 'PostalAddress',
|
||||
addressLocality: 'DeKalb',
|
||||
addressRegion: 'GA',
|
||||
addressCountry: 'US',
|
||||
"@type": "PostalAddress",
|
||||
addressLocality: "DeKalb",
|
||||
addressRegion: "GA",
|
||||
addressCountry: "US",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<html lang="en" className="scroll-smooth bg-black dark:bg-gray-900">
|
||||
<body className={`${inter.variable} antialiased min-h-screen flex flex-col bg-black dark:bg-gray-900`}>
|
||||
<html lang="en" className="scroll-smooth dark">
|
||||
<body
|
||||
className={`${inter.variable} ${jetbrainsMono.variable} antialiased min-h-screen flex flex-col bg-midnight text-snow`}
|
||||
>
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||
/>
|
||||
<a
|
||||
href="#main-content"
|
||||
className="sr-only focus:not-sr-only focus:absolute focus:top-4 focus:left-4 focus:z-[100] focus:px-4 focus:py-2 focus:bg-indigo focus:text-white focus:rounded-md"
|
||||
>
|
||||
Skip to content
|
||||
</a>
|
||||
<Navigation />
|
||||
<main className="flex-1" id="main-content">
|
||||
{children}
|
||||
|
||||
+54
-54
@@ -29,18 +29,18 @@ export default function P2PPage() {
|
||||
return (
|
||||
<div className="min-h-screen">
|
||||
{/* Introduction */}
|
||||
<section className="py-20 bg-gradient-to-b from-blue-50 to-white dark:from-gray-900 dark:to-gray-800">
|
||||
<section className="py-20 bg-grid-fade border-b border-steel/40">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<h1 className="text-4xl sm:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
<h1 className="text-4xl sm:text-5xl font-bold text-white mb-6">
|
||||
Understanding Peer-to-Peer Networking
|
||||
</h1>
|
||||
<p className="text-xl text-gray-600 dark:text-gray-300 leading-relaxed mb-8">
|
||||
<p className="text-xl text-mist leading-relaxed mb-8">
|
||||
Peer-to-peer (P2P) networking is a distributed architecture where participants (peers) share resources
|
||||
and communicate directly without relying on a central server. P2NS leverages P2P technology to create
|
||||
a resilient, decentralized DNS system.
|
||||
</p>
|
||||
<div className="bg-blue-100 dark:bg-blue-900 border-l-4 border-blue-500 p-4 rounded">
|
||||
<p className="text-sm text-blue-800 dark:text-blue-200">
|
||||
<div className="bg-indigo-deep/80 border-l-4 border-indigo p-4 rounded">
|
||||
<p className="text-sm text-indigo-pale">
|
||||
<strong>Key Concept:</strong> In a P2P network, each node can act as both a client and a server,
|
||||
enabling direct communication and resource sharing between peers.
|
||||
</p>
|
||||
@@ -49,12 +49,12 @@ export default function P2PPage() {
|
||||
</section>
|
||||
|
||||
{/* UDP Hole Punching */}
|
||||
<section className="py-20 bg-white dark:bg-gray-900">
|
||||
<section className="py-20 bg-midnight">
|
||||
<div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
<h2 className="text-3xl font-bold text-white mb-4">
|
||||
UDP Hole Punching
|
||||
</h2>
|
||||
<p className="text-lg text-gray-600 dark:text-gray-300 mb-8">
|
||||
<p className="text-lg text-mist mb-8">
|
||||
UDP hole-punching lets two peers behind NAT establish a direct path. In the Holepunch stack
|
||||
(used by Hyperswarm and Holesail), peers coordinate through <strong>HyperDHT</strong>—a distributed
|
||||
hash table—not a single central rendezvous server. When both sides use predictable NAT ports,
|
||||
@@ -63,9 +63,9 @@ export default function P2PPage() {
|
||||
|
||||
<UDPHolePunchingDiagram />
|
||||
|
||||
<div className="mt-8 prose prose-lg dark:prose-invert max-w-none">
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4">How It Works</h3>
|
||||
<ol className="list-decimal pl-6 space-y-3 text-gray-600 dark:text-gray-300">
|
||||
<div className="mt-8 prose prose-lg max-w-none">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4">How It Works</h3>
|
||||
<ol className="list-decimal pl-6 space-y-3 text-mist">
|
||||
<li>
|
||||
<strong>Announce on the DHT:</strong> Each peer registers its public endpoints with HyperDHT
|
||||
under its cryptographic identity.
|
||||
@@ -93,12 +93,12 @@ export default function P2PPage() {
|
||||
</section>
|
||||
|
||||
{/* NAT Traversal */}
|
||||
<section className="py-20 bg-gray-50 dark:bg-gray-800">
|
||||
<section className="py-20 bg-deep">
|
||||
<div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
<h2 className="text-3xl font-bold text-white mb-4">
|
||||
NAT Traversal
|
||||
</h2>
|
||||
<p className="text-lg text-gray-600 dark:text-gray-300 mb-8">
|
||||
<p className="text-lg text-mist mb-8">
|
||||
Network Address Translation (NAT) is used by routers to share a single public IP address among multiple
|
||||
devices. NAT traversal techniques allow P2P connections to work through these devices.
|
||||
</p>
|
||||
@@ -106,24 +106,24 @@ export default function P2PPage() {
|
||||
<NATTraversalDiagram />
|
||||
|
||||
<div className="mt-8 grid md:grid-cols-2 gap-6">
|
||||
<div className="bg-white dark:bg-gray-900 p-6 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Types of NAT</h3>
|
||||
<ul className="space-y-2 text-gray-600 dark:text-gray-300">
|
||||
<div className="bg-midnight p-6 rounded-lg border border-steel">
|
||||
<h3 className="text-xl font-semibold text-white mb-3">Types of NAT</h3>
|
||||
<ul className="space-y-2 text-mist">
|
||||
<li><strong>Open NAT:</strong> Predictable mapping—hole punching usually works.</li>
|
||||
<li><strong>Consistent NAT:</strong> Same external port per internal port—still punchable with coordination.</li>
|
||||
<li><strong>Random / symmetric NAT:</strong> Unpredictable external ports—often needs a relay fallback.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="bg-white dark:bg-gray-900 p-6 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">CGNAT Challenges</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-3">
|
||||
<div className="bg-midnight p-6 rounded-lg border border-steel">
|
||||
<h3 className="text-xl font-semibold text-white mb-3">CGNAT Challenges</h3>
|
||||
<p className="text-mist mb-3">
|
||||
Carrier-Grade NAT (CGNAT) adds an additional layer of NAT, making traversal even more complex.
|
||||
P2NS uses Holesail, which is specifically designed to handle these challenging scenarios.
|
||||
</p>
|
||||
<p className="text-gray-600 dark:text-gray-300">
|
||||
<p className="text-mist">
|
||||
Holesail implements advanced techniques including:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 mt-2 text-gray-600 dark:text-gray-300">
|
||||
<ul className="list-disc pl-6 mt-2 text-mist">
|
||||
<li>Multiple simultaneous connection attempts</li>
|
||||
<li>Protocol-specific optimizations</li>
|
||||
</ul>
|
||||
@@ -133,23 +133,23 @@ export default function P2PPage() {
|
||||
</section>
|
||||
|
||||
{/* Peer Discovery */}
|
||||
<section className="py-20 bg-white dark:bg-gray-900">
|
||||
<section className="py-20 bg-midnight">
|
||||
<div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
<h2 className="text-3xl font-bold text-white mb-4">
|
||||
Peer Discovery with Hyperswarm
|
||||
</h2>
|
||||
<p className="text-lg text-gray-600 dark:text-gray-300 mb-8">
|
||||
<p className="text-lg text-mist mb-8">
|
||||
Hyperswarm is a high-level API on top of <strong>HyperDHT</strong> (Kademlia-style DHT). Peers
|
||||
announce and discover each other by 32-byte topics without a central directory server.
|
||||
</p>
|
||||
|
||||
<PeerDiscoveryDiagram />
|
||||
|
||||
<div className="mt-8 prose prose-lg dark:prose-invert max-w-none">
|
||||
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4">How Hyperswarm Works</h3>
|
||||
<div className="space-y-4 text-gray-600 dark:text-gray-300">
|
||||
<div className="mt-8 prose prose-lg max-w-none">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4">How Hyperswarm Works</h3>
|
||||
<div className="space-y-4 text-mist">
|
||||
<p>
|
||||
<strong>Topic-based discovery:</strong> P2NS hashes <code className="rounded bg-gray-200 px-1.5 py-0.5 font-mono text-sm text-gray-900 dark:bg-gray-700 dark:text-gray-200">TOPIC_SEED</code> (default <code className="rounded bg-gray-200 px-1.5 py-0.5 font-mono text-sm text-gray-900 dark:bg-gray-700 dark:text-gray-200">p2ns-dns</code>) with SHA-256 to form a 32-byte topic. Every node interested in the network joins that topic.
|
||||
<strong>Topic-based discovery:</strong> P2NS hashes <code className="rounded bg-surface px-1.5 py-0.5 font-mono text-sm text-indigo-pale border border-steel">TOPIC_SEED</code> (default <code className="rounded bg-surface px-1.5 py-0.5 font-mono text-sm text-indigo-pale border border-steel">p2ns-dns</code>) with SHA-256 to form a 32-byte topic. Every node interested in the network joins that topic.
|
||||
</p>
|
||||
<p>
|
||||
<strong>DHT lookup:</strong> HyperDHT returns peers that have announced on the topic. DHT results are candidates only—each connection still completes a Noise XX handshake so the remote party must prove key ownership.
|
||||
@@ -167,66 +167,66 @@ export default function P2PPage() {
|
||||
</section>
|
||||
|
||||
{/* Holepunch stack */}
|
||||
<section className="py-20 bg-gray-50 dark:bg-gray-800">
|
||||
<section className="py-20 bg-deep">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
<h2 className="text-3xl font-bold text-white mb-4">
|
||||
The Holepunch Connection Stack
|
||||
</h2>
|
||||
<p className="text-lg text-gray-600 dark:text-gray-300 mb-6">
|
||||
<p className="text-lg text-mist mb-6">
|
||||
P2NS uses the Holepunch stack in layers: raw UDP paths, then encryption, then application protocols.
|
||||
</p>
|
||||
<ol className="list-decimal pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||
<ol className="list-decimal pl-6 space-y-2 text-mist">
|
||||
<li><strong>libudx</strong> — reliable UDP between peers after hole punching</li>
|
||||
<li><strong>Secret Stream (Noise XX)</strong> — mutual authentication and XChaCha20-Poly1305 encryption</li>
|
||||
<li><strong>Protomux / protomux-rpc</strong> — multiplexed channels for core invites, consensus, and plugins</li>
|
||||
<li><strong>Hypercore / Corestore</strong> — append-only, Merkle-verified logs for claim/vote writes</li>
|
||||
<li><strong>Autobase</strong> — consensus sidecar that linearizes claim/vote events for deterministic resolution</li>
|
||||
</ol>
|
||||
<p className="text-sm text-gray-500 dark:text-gray-400 mt-4">
|
||||
<p className="text-sm text-fog mt-4">
|
||||
Domain tunnels use <strong>Holesail</strong> (separate hashes on the DHT) for reaching services behind NAT; the P2NS swarm topic is only for DNS peer sync.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Corestore & Autopass */}
|
||||
<section className="py-20 bg-white dark:bg-gray-900">
|
||||
<section className="py-20 bg-midnight">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
<h2 className="text-3xl font-bold text-white mb-4">
|
||||
Decentralized Storage & Security
|
||||
</h2>
|
||||
<div className="grid md:grid-cols-2 gap-8">
|
||||
<div className="bg-gray-50 dark:bg-gray-800 p-6 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Corestore</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-3">
|
||||
<div className="bg-deep p-6 rounded-lg border border-steel">
|
||||
<h3 className="text-xl font-semibold text-white mb-3">Corestore</h3>
|
||||
<p className="text-mist mb-3">
|
||||
Corestore manages Hypercore append-only logs. Each block is Merkle-linked and signed with Ed25519,
|
||||
so peers verify data by proof—not by trusting who delivered it. P2NS stores domain claims and votes in this replicated log.
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-1 text-gray-600 dark:text-gray-300">
|
||||
<ul className="list-disc pl-6 space-y-1 text-mist">
|
||||
<li>Immutable append-only history</li>
|
||||
<li>Sparse replication of blocks</li>
|
||||
<li>Automatic sync across peers</li>
|
||||
<li>Domain conflicts resolved by peer voting via the Autobase consensus sidecar</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="bg-gray-50 dark:bg-gray-800 p-6 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Autopass</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-3">
|
||||
<div className="bg-deep p-6 rounded-lg border border-steel">
|
||||
<h3 className="text-xl font-semibold text-white mb-3">Autopass</h3>
|
||||
<p className="text-mist mb-3">
|
||||
Autopass manages secure writer additions to the Corestore. It ensures only authorized peers can
|
||||
write to the ledger, preventing spam and attacks.
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-1 text-gray-600 dark:text-gray-300">
|
||||
<ul className="list-disc pl-6 space-y-1 text-mist">
|
||||
<li>Invitation-based access control</li>
|
||||
<li>Genesis master creates the ledger; masters and writers issue invites</li>
|
||||
<li>One <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">networkId</code> and <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">consensusAutobaseKey</code> per network (manifest)</li>
|
||||
<li>One <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">networkId</code> and <code className="bg-surface text-indigo-pale border border-steel px-1.5 py-0.5 rounded">consensusAutobaseKey</code> per network (manifest)</li>
|
||||
<li>Cryptographic verification</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="bg-gray-50 dark:bg-gray-800 p-6 rounded-lg border border-gray-200 dark:border-gray-700 md:col-span-2">
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Autobase (Consensus Sidecar)</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-3">
|
||||
<div className="bg-deep p-6 rounded-lg border border-steel md:col-span-2">
|
||||
<h3 className="text-xl font-semibold text-white mb-3">Autobase (Consensus Sidecar)</h3>
|
||||
<p className="text-mist mb-3">
|
||||
P2NS uses a dedicated Autobase instance to replay claim and vote events in linearized order. Autopass KV remains the durable write store; the sidecar is the sole read path for domain resolution.
|
||||
</p>
|
||||
<ul className="list-disc pl-6 space-y-1 text-gray-600 dark:text-gray-300">
|
||||
<ul className="list-disc pl-6 space-y-1 text-mist">
|
||||
<li>Dual-write: each claim/vote mutation appends a typed event to the sidecar</li>
|
||||
<li>Bootstrap from existing dnsPass entries; joiners replicate via manifest key</li>
|
||||
<li>Deterministic vote ordering and tie-breaking (no per-query KV scan)</li>
|
||||
@@ -237,9 +237,9 @@ export default function P2PPage() {
|
||||
</section>
|
||||
|
||||
{/* Glossary */}
|
||||
<section className="py-20 bg-white dark:bg-gray-900">
|
||||
<section className="py-20 bg-midnight">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-8">
|
||||
<h2 className="text-3xl font-bold text-white mb-8">
|
||||
Glossary
|
||||
</h2>
|
||||
<dl className="space-y-6">
|
||||
@@ -253,11 +253,11 @@ export default function P2PPage() {
|
||||
{ term: 'Consensus', definition: 'In P2NS, agreement on domain ownership through quorum-based voting. Claims and votes are written to Autopass KV; resolution reads the Autobase consensus sidecar apply view in linearized event order.' },
|
||||
{ term: 'Consensus Sidecar', definition: 'The Autobase instance (p2ns-consensus Corestore namespace) that replays claim/vote events and maintains the in-memory view used for domain resolution.' },
|
||||
].map((item) => (
|
||||
<div key={item.term} className="border-l-4 border-blue-500 pl-4">
|
||||
<dt className="text-lg font-semibold text-gray-900 dark:text-white mb-1">
|
||||
<div key={item.term} className="border-l-4 border-indigo pl-4">
|
||||
<dt className="text-lg font-semibold text-white mb-1">
|
||||
{item.term}
|
||||
</dt>
|
||||
<dd className="text-gray-600 dark:text-gray-300">
|
||||
<dd className="text-mist">
|
||||
{item.definition}
|
||||
</dd>
|
||||
</div>
|
||||
|
||||
+10
-10
@@ -27,25 +27,25 @@ export const metadata: Metadata = {
|
||||
|
||||
export default function LegalHubPage() {
|
||||
return (
|
||||
<div className="min-h-screen bg-[#111829]" data-legal-page>
|
||||
<div className="min-h-screen bg-midnight" data-legal-page>
|
||||
<section
|
||||
data-legal-hero
|
||||
className="py-20 bg-gradient-to-b from-blue-50 to-white dark:from-gray-900 dark:to-gray-800 text-white"
|
||||
className="py-20 bg-grid-fade border-b border-steel/40 text-white"
|
||||
>
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<h1 className="text-4xl sm:text-5xl font-bold text-white mb-6">
|
||||
Legal
|
||||
</h1>
|
||||
<p className="text-xl text-gray-200">
|
||||
<p className="text-xl text-mist">
|
||||
Policies and agreements for P2NS and this website, owned and engineered by {LEGAL_ENTITY_FULL}.
|
||||
</p>
|
||||
<p className="mt-4 text-sm text-gray-300">
|
||||
<p className="mt-4 text-sm text-mist">
|
||||
Last updated {LEGAL_LAST_UPDATED}
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section data-legal-content className="py-20 bg-white dark:bg-gray-900 text-white">
|
||||
<section data-legal-content className="py-20 bg-midnight text-white">
|
||||
<div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{legalDocuments.map((doc) => {
|
||||
@@ -54,17 +54,17 @@ export default function LegalHubPage() {
|
||||
<Link
|
||||
key={doc.href}
|
||||
href={doc.href}
|
||||
className="group bg-white dark:bg-gray-800 p-6 rounded-lg border border-gray-200 dark:border-gray-700 hover:border-blue-500 dark:hover:border-blue-500 transition-all hover:shadow-lg text-gray-900"
|
||||
className="group surface-card surface-card-hover p-6"
|
||||
>
|
||||
<div className="flex items-center space-x-3 mb-4">
|
||||
<div className="p-2 bg-blue-100 dark:bg-blue-900 rounded-lg group-hover:bg-blue-200 dark:group-hover:bg-blue-800 transition-colors">
|
||||
<Icon className="h-6 w-6 text-blue-600 dark:text-blue-400" />
|
||||
<div className="p-2 bg-indigo-deep/80 rounded-lg group-hover:bg-indigo-deep transition-colors">
|
||||
<Icon className="h-6 w-6 text-indigo-light" />
|
||||
</div>
|
||||
<h2 className="text-xl font-semibold text-gray-900 dark:text-white">
|
||||
<h2 className="text-xl font-semibold text-white">
|
||||
{doc.title}
|
||||
</h2>
|
||||
</div>
|
||||
<p className="text-gray-600 dark:text-gray-300">{doc.description}</p>
|
||||
<p className="text-mist">{doc.description}</p>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
|
||||
+11
-8
@@ -4,23 +4,25 @@ import FeaturesGrid from '@/components/sections/FeaturesGrid';
|
||||
import HowItWorks from '@/components/sections/HowItWorks';
|
||||
import TechnologyStack from '@/components/sections/TechnologyStack';
|
||||
import QuickStart from '@/components/sections/QuickStart';
|
||||
import CtaBand from '@/components/sections/CtaBand';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'P2NS - Peer-to-Peer Decentralized DNS System',
|
||||
description: 'A robust, firewall-resistant peer-to-peer DNS resolution system that operates independently of centralized DNS infrastructure. Built with Holesail, Hyperswarm, and Corestore.',
|
||||
keywords: ['P2P', 'DNS', 'decentralized', 'peer-to-peer', 'NAT traversal', 'firewall', 'Holesail', 'Hyperswarm', 'Corestore', 'decentralized DNS', 'P2P DNS'],
|
||||
authors: [{ name: 'Raven Scott' }],
|
||||
title: 'P2NS — Peer-to-Peer Name System',
|
||||
description:
|
||||
'Decentralized, secure, and censorship-resistant naming infrastructure for the open web. Firewall-resistant P2P DNS built with Holesail, Hyperswarm, and Corestore.',
|
||||
openGraph: {
|
||||
title: 'P2NS - Peer-to-Peer Decentralized DNS System',
|
||||
description: 'A robust, firewall-resistant peer-to-peer DNS resolution system that operates independently of centralized DNS infrastructure.',
|
||||
title: 'P2NS — Peer-to-Peer Name System',
|
||||
description:
|
||||
'Decentralized, secure, and censorship-resistant naming infrastructure for the open web.',
|
||||
url: 'https://p2ns.space',
|
||||
siteName: 'P2NS',
|
||||
type: 'website',
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: 'P2NS - Peer-to-Peer Decentralized DNS System',
|
||||
description: 'A robust, firewall-resistant peer-to-peer DNS resolution system that operates independently of centralized DNS infrastructure.',
|
||||
title: 'P2NS — Peer-to-Peer Name System',
|
||||
description:
|
||||
'Decentralized, secure, and censorship-resistant naming infrastructure for the open web.',
|
||||
},
|
||||
alternates: {
|
||||
canonical: 'https://p2ns.space',
|
||||
@@ -35,6 +37,7 @@ export default function Home() {
|
||||
<HowItWorks />
|
||||
<TechnologyStack />
|
||||
<QuickStart />
|
||||
<CtaBand />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ const components = [
|
||||
|
||||
export default function ArchitectureDiagram() {
|
||||
return (
|
||||
<div className="relative bg-gray-50 dark:bg-gray-800 rounded-lg p-8 border border-gray-200 dark:border-gray-700">
|
||||
<div className="relative bg-deep rounded-lg p-8 border border-steel">
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
{components.map((component, index) => {
|
||||
const Icon = component.icon;
|
||||
@@ -55,17 +55,17 @@ export default function ArchitectureDiagram() {
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.5, delay: index * 0.1 }}
|
||||
className="bg-white dark:bg-gray-900 p-6 rounded-lg border border-gray-200 dark:border-gray-700 hover:border-blue-500 dark:hover:border-blue-500 transition-colors"
|
||||
className="bg-midnight p-6 rounded-lg border border-steel hover:border-indigo transition-colors"
|
||||
>
|
||||
<div className="flex items-center space-x-3 mb-3">
|
||||
<div className="p-2 bg-blue-100 dark:bg-blue-900 rounded-lg">
|
||||
<Icon className="h-6 w-6 text-blue-600 dark:text-blue-400" />
|
||||
<div className="p-2 bg-indigo-deep/80 rounded-lg">
|
||||
<Icon className="h-6 w-6 text-indigo-light" />
|
||||
</div>
|
||||
<h3 className="text-lg font-semibold text-gray-900 dark:text-white">
|
||||
<h3 className="text-lg font-semibold text-white">
|
||||
{component.name}
|
||||
</h3>
|
||||
</div>
|
||||
<p className="text-sm text-gray-600 dark:text-gray-400">
|
||||
<p className="text-sm text-fog">
|
||||
{component.description}
|
||||
</p>
|
||||
</motion.div>
|
||||
@@ -74,9 +74,9 @@ export default function ArchitectureDiagram() {
|
||||
</div>
|
||||
|
||||
<div className="mt-8 text-center">
|
||||
<div className="inline-flex items-center space-x-2 px-4 py-2 bg-blue-100 dark:bg-blue-900 rounded-lg">
|
||||
<Network className="h-5 w-5 text-blue-600 dark:text-blue-400" />
|
||||
<span className="text-sm font-medium text-gray-900 dark:text-white">
|
||||
<div className="inline-flex items-center space-x-2 px-4 py-2 bg-indigo-deep/80 rounded-lg">
|
||||
<Network className="h-5 w-5 text-indigo-light" />
|
||||
<span className="text-sm font-medium text-white">
|
||||
All components work together to create a resilient P2P DNS system
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -5,20 +5,20 @@ import { Router, Globe, Shield } from 'lucide-react';
|
||||
|
||||
export default function NATTraversalDiagram() {
|
||||
return (
|
||||
<div className="bg-gray-50 dark:bg-gray-800 rounded-lg p-8 border border-gray-200 dark:border-gray-700">
|
||||
<div className="bg-deep rounded-lg p-8 border border-steel">
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
{/* Local Network */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
className="bg-white dark:bg-gray-900 p-6 rounded-lg border border-gray-200 dark:border-gray-700"
|
||||
className="bg-midnight p-6 rounded-lg border border-steel"
|
||||
>
|
||||
<div className="flex items-center space-x-2 mb-4">
|
||||
<Router className="h-6 w-6 text-blue-600 dark:text-blue-400" />
|
||||
<h3 className="font-semibold text-gray-900 dark:text-white">Local Network</h3>
|
||||
<Router className="h-6 w-6 text-indigo-light" />
|
||||
<h3 className="font-semibold text-white">Local Network</h3>
|
||||
</div>
|
||||
<ul className="space-y-2 text-sm text-gray-600 dark:text-gray-400">
|
||||
<ul className="space-y-2 text-sm text-fog">
|
||||
<li>• Device 1: 192.168.1.10</li>
|
||||
<li>• Device 2: 192.168.1.11</li>
|
||||
<li>• Device 3: 192.168.1.12</li>
|
||||
@@ -31,13 +31,13 @@ export default function NATTraversalDiagram() {
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ delay: 0.2 }}
|
||||
className="bg-white dark:bg-gray-900 p-6 rounded-lg border border-gray-200 dark:border-gray-700"
|
||||
className="bg-midnight p-6 rounded-lg border border-steel"
|
||||
>
|
||||
<div className="flex items-center space-x-2 mb-4">
|
||||
<Shield className="h-6 w-6 text-purple-600 dark:text-purple-400" />
|
||||
<h3 className="font-semibold text-gray-900 dark:text-white">NAT Router</h3>
|
||||
<Shield className="h-6 w-6 text-indigo-light" />
|
||||
<h3 className="font-semibold text-white">NAT Router</h3>
|
||||
</div>
|
||||
<div className="text-sm text-gray-600 dark:text-gray-400 space-y-2">
|
||||
<div className="text-sm text-fog space-y-2">
|
||||
<p><strong>Public IP:</strong> 203.0.113.1</p>
|
||||
<p><strong>Function:</strong></p>
|
||||
<ul className="list-disc pl-4 space-y-1">
|
||||
@@ -54,13 +54,13 @@ export default function NATTraversalDiagram() {
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ delay: 0.4 }}
|
||||
className="bg-white dark:bg-gray-900 p-6 rounded-lg border border-gray-200 dark:border-gray-700"
|
||||
className="bg-midnight p-6 rounded-lg border border-steel"
|
||||
>
|
||||
<div className="flex items-center space-x-2 mb-4">
|
||||
<Globe className="h-6 w-6 text-green-600 dark:text-green-400" />
|
||||
<h3 className="font-semibold text-gray-900 dark:text-white">Internet</h3>
|
||||
<Globe className="h-6 w-6 text-success" />
|
||||
<h3 className="font-semibold text-white">Internet</h3>
|
||||
</div>
|
||||
<div className="text-sm text-gray-600 dark:text-gray-400 space-y-2">
|
||||
<div className="text-sm text-fog space-y-2">
|
||||
<p><strong>Challenge:</strong></p>
|
||||
<ul className="list-disc pl-4 space-y-1">
|
||||
<li>Devices behind NAT can't receive direct connections</li>
|
||||
@@ -71,8 +71,8 @@ export default function NATTraversalDiagram() {
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
<div className="mt-6 p-4 bg-blue-50 dark:bg-blue-900 rounded-lg border border-blue-200 dark:border-blue-700">
|
||||
<p className="text-sm text-blue-800 dark:text-blue-200">
|
||||
<div className="mt-6 p-4 bg-indigo/10 rounded-lg border border-steel">
|
||||
<p className="text-sm text-indigo-pale">
|
||||
<strong>P2NS Solution:</strong> Holesail uses advanced UDP hole-punching techniques to establish connections even through multiple layers of NAT and CGNAT.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -56,12 +56,12 @@ const steps = [
|
||||
];
|
||||
|
||||
const colorClasses = {
|
||||
blue: 'bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-400 border-blue-200 dark:border-blue-700',
|
||||
purple: 'bg-purple-100 dark:bg-purple-900 text-purple-600 dark:text-purple-400 border-purple-200 dark:border-purple-700',
|
||||
green: 'bg-green-100 dark:bg-green-900 text-green-600 dark:text-green-400 border-green-200 dark:border-green-700',
|
||||
orange: 'bg-orange-100 dark:bg-orange-900 text-orange-600 dark:text-orange-400 border-orange-200 dark:border-orange-700',
|
||||
red: 'bg-red-100 dark:bg-red-900 text-red-600 dark:text-red-400 border-red-200 dark:border-red-700',
|
||||
indigo: 'bg-indigo-100 dark:bg-indigo-900 text-indigo-600 dark:text-indigo-400 border-indigo-200 dark:border-indigo-700',
|
||||
blue: 'bg-indigo-deep/80 text-indigo-light border-steel',
|
||||
purple: 'bg-indigo-deep/80 text-indigo-light border-steel',
|
||||
green: 'bg-success/15 text-success border-steel',
|
||||
orange: 'bg-warning/15 text-warning border-steel',
|
||||
red: 'bg-danger/15 text-danger border-steel',
|
||||
indigo: 'bg-indigo-deep/80 text-indigo-light border-steel',
|
||||
};
|
||||
|
||||
export default function P2NSFlowDiagram() {
|
||||
@@ -72,7 +72,7 @@ export default function P2NSFlowDiagram() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="bg-gradient-to-br from-gray-50 to-gray-100 dark:from-gray-800 dark:to-gray-900 rounded-xl p-6 md:p-8 border border-gray-200 dark:border-gray-700 shadow-lg">
|
||||
<div className="bg-deep rounded-xl p-6 md:p-8 border border-steel">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
{rows.map((row, rowIndex) => {
|
||||
const isLastRow = rowIndex === rows.length - 1;
|
||||
@@ -95,16 +95,16 @@ export default function P2NSFlowDiagram() {
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.4, delay: globalIndex * 0.08 }}
|
||||
className="flex items-center gap-4 bg-white dark:bg-gray-800 rounded-xl p-4 shadow-md hover:shadow-lg border border-gray-200 dark:border-gray-700 transition-all duration-300 hover:scale-[1.02]"
|
||||
className="flex items-center gap-4 bg-surface rounded-xl p-4 shadow-md border border-steel transition-all duration-300 hover:scale-[1.02]"
|
||||
>
|
||||
<div className={`p-3 rounded-xl border-2 ${colorClasses[step.color as keyof typeof colorClasses]} shadow-sm flex-shrink-0 transition-all duration-300 hover:scale-110`}>
|
||||
<Icon className="h-6 w-6" />
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<h3 className="text-base font-bold text-gray-900 dark:text-white mb-1 leading-tight">
|
||||
<h3 className="text-base font-bold text-white mb-1 leading-tight">
|
||||
{step.title}
|
||||
</h3>
|
||||
<p className="text-sm text-gray-600 dark:text-gray-400 leading-snug">
|
||||
<p className="text-sm text-fog leading-snug">
|
||||
{step.description}
|
||||
</p>
|
||||
</div>
|
||||
@@ -128,16 +128,16 @@ export default function P2NSFlowDiagram() {
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.4, delay: globalIndex * 0.08 }}
|
||||
className="flex items-center gap-4 flex-1 bg-white dark:bg-gray-800 rounded-xl p-4 shadow-md hover:shadow-lg border border-gray-200 dark:border-gray-700 transition-all duration-300 hover:scale-[1.02]"
|
||||
className="flex items-center gap-4 flex-1 bg-surface rounded-xl p-4 shadow-md border border-steel transition-all duration-300 hover:scale-[1.02]"
|
||||
>
|
||||
<div className={`p-3 rounded-xl border-2 ${colorClasses[step.color as keyof typeof colorClasses]} shadow-sm flex-shrink-0 transition-all duration-300 hover:scale-110`}>
|
||||
<Icon className="h-6 w-6" />
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<h3 className="text-base font-bold text-gray-900 dark:text-white mb-1 leading-tight">
|
||||
<h3 className="text-base font-bold text-white mb-1 leading-tight">
|
||||
{step.title}
|
||||
</h3>
|
||||
<p className="text-sm text-gray-600 dark:text-gray-400 leading-snug">
|
||||
<p className="text-sm text-fog leading-snug">
|
||||
{step.description}
|
||||
</p>
|
||||
</div>
|
||||
@@ -151,7 +151,7 @@ export default function P2NSFlowDiagram() {
|
||||
transition={{ duration: 0.4, delay: globalIndex * 0.08 + 0.2 }}
|
||||
className="flex-shrink-0 mx-4"
|
||||
>
|
||||
<ArrowRight className="h-5 w-5 text-gray-500 dark:text-gray-400" strokeWidth={2.5} />
|
||||
<ArrowRight className="h-5 w-5 text-fog" strokeWidth={2.5} />
|
||||
</motion.div>
|
||||
)}
|
||||
</div>
|
||||
@@ -169,7 +169,7 @@ export default function P2NSFlowDiagram() {
|
||||
transition={{ duration: 0.4, delay: (rowIndex * 2 + 1) * 0.08 + 0.2 }}
|
||||
className="my-6 md:my-8"
|
||||
>
|
||||
<ArrowDown className="h-7 w-7 text-gray-500 dark:text-gray-400" strokeWidth={2.5} />
|
||||
<ArrowDown className="h-7 w-7 text-fog" strokeWidth={2.5} />
|
||||
</motion.div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -5,11 +5,11 @@ import { Network, Search, Users } from 'lucide-react';
|
||||
|
||||
export default function PeerDiscoveryDiagram() {
|
||||
return (
|
||||
<div className="bg-gray-50 dark:bg-gray-800 rounded-lg p-8 border border-gray-200 dark:border-gray-700">
|
||||
<div className="bg-deep rounded-lg p-8 border border-steel">
|
||||
<div className="text-center mb-8">
|
||||
<div className="inline-flex items-center space-x-2 px-4 py-2 bg-purple-100 dark:bg-purple-900 rounded-lg mb-4">
|
||||
<Search className="h-5 w-5 text-purple-600 dark:text-purple-400" />
|
||||
<span className="text-sm font-medium text-gray-900 dark:text-white">
|
||||
<div className="inline-flex items-center space-x-2 px-4 py-2 bg-indigo-deep/80 rounded-lg mb-4">
|
||||
<Search className="h-5 w-5 text-indigo-light" />
|
||||
<span className="text-sm font-medium text-white">
|
||||
Topic: sha256(TOPIC_SEED)
|
||||
</span>
|
||||
</div>
|
||||
@@ -28,13 +28,13 @@ export default function PeerDiscoveryDiagram() {
|
||||
whileInView={{ opacity: 1, scale: 1 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.3, delay: index * 0.1 }}
|
||||
className="bg-white dark:bg-gray-900 p-4 rounded-lg border border-gray-200 dark:border-gray-700 text-center"
|
||||
className="bg-midnight p-4 rounded-lg border border-steel text-center"
|
||||
>
|
||||
<Network className="h-8 w-8 text-blue-600 dark:text-blue-400 mx-auto mb-2" />
|
||||
<h4 className="font-semibold text-gray-900 dark:text-white text-sm mb-1">
|
||||
<Network className="h-8 w-8 text-indigo-light mx-auto mb-2" />
|
||||
<h4 className="font-semibold text-white text-sm mb-1">
|
||||
{peer.name}
|
||||
</h4>
|
||||
<span className="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200">
|
||||
<span className="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-success/15 text-success">
|
||||
{peer.status}
|
||||
</span>
|
||||
</motion.div>
|
||||
@@ -42,30 +42,30 @@ export default function PeerDiscoveryDiagram() {
|
||||
</div>
|
||||
|
||||
<div className="mt-8 grid md:grid-cols-3 gap-6">
|
||||
<div className="bg-white dark:bg-gray-900 p-4 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||
<h4 className="font-semibold text-gray-900 dark:text-white mb-2 text-sm">1. Join Topic</h4>
|
||||
<p className="text-xs text-gray-600 dark:text-gray-400">
|
||||
<div className="bg-midnight p-4 rounded-lg border border-steel">
|
||||
<h4 className="font-semibold text-white mb-2 text-sm">1. Join Topic</h4>
|
||||
<p className="text-xs text-fog">
|
||||
Peers announce themselves to the DHT using the P2NS topic
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-white dark:bg-gray-900 p-4 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||
<h4 className="font-semibold text-gray-900 dark:text-white mb-2 text-sm">2. Discover Peers</h4>
|
||||
<p className="text-xs text-gray-600 dark:text-gray-400">
|
||||
<div className="bg-midnight p-4 rounded-lg border border-steel">
|
||||
<h4 className="font-semibold text-white mb-2 text-sm">2. Discover Peers</h4>
|
||||
<p className="text-xs text-fog">
|
||||
Query the DHT to find other peers interested in the same topic
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-white dark:bg-gray-900 p-4 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||
<h4 className="font-semibold text-gray-900 dark:text-white mb-2 text-sm">3. Connect</h4>
|
||||
<p className="text-xs text-gray-600 dark:text-gray-400">
|
||||
<div className="bg-midnight p-4 rounded-lg border border-steel">
|
||||
<h4 className="font-semibold text-white mb-2 text-sm">3. Connect</h4>
|
||||
<p className="text-xs text-fog">
|
||||
Establish direct connections using UDP hole-punching
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-6 p-4 bg-purple-50 dark:bg-purple-900 rounded-lg border border-purple-200 dark:border-purple-700">
|
||||
<div className="mt-6 p-4 bg-indigo/10 rounded-lg border border-steel">
|
||||
<div className="flex items-center space-x-2">
|
||||
<Users className="h-5 w-5 text-purple-600 dark:text-purple-400" />
|
||||
<p className="text-sm text-purple-800 dark:text-purple-200">
|
||||
<Users className="h-5 w-5 text-indigo-light" />
|
||||
<p className="text-sm text-indigo-pale">
|
||||
<strong>Hyperswarm</strong> automatically handles peer churn and reconnection, ensuring the network
|
||||
remains connected even as peers join and leave.
|
||||
</p>
|
||||
|
||||
@@ -5,7 +5,7 @@ import { Network, Server, ArrowRight, ArrowLeft } from 'lucide-react';
|
||||
|
||||
export default function UDPHolePunchingDiagram() {
|
||||
return (
|
||||
<div className="bg-gray-50 dark:bg-gray-800 rounded-lg p-8 border border-gray-200 dark:border-gray-700">
|
||||
<div className="bg-deep rounded-lg p-8 border border-steel">
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 items-center">
|
||||
{/* Peer A */}
|
||||
<motion.div
|
||||
@@ -14,12 +14,12 @@ export default function UDPHolePunchingDiagram() {
|
||||
viewport={{ once: true }}
|
||||
className="text-center"
|
||||
>
|
||||
<div className="bg-blue-100 dark:bg-blue-900 p-6 rounded-lg mb-4">
|
||||
<Network className="h-12 w-12 text-blue-600 dark:text-blue-400 mx-auto mb-2" />
|
||||
<h3 className="font-semibold text-gray-900 dark:text-white">Peer A</h3>
|
||||
<p className="text-sm text-gray-600 dark:text-gray-400">Behind NAT</p>
|
||||
<div className="bg-indigo-deep/80 p-6 rounded-lg mb-4">
|
||||
<Network className="h-12 w-12 text-indigo-light mx-auto mb-2" />
|
||||
<h3 className="font-semibold text-white">Peer A</h3>
|
||||
<p className="text-sm text-fog">Behind NAT</p>
|
||||
</div>
|
||||
<div className="text-sm text-gray-600 dark:text-gray-400">
|
||||
<div className="text-sm text-fog">
|
||||
<p>Private IP: 192.168.1.10</p>
|
||||
<p>Public: 203.0.113.1:5000</p>
|
||||
</div>
|
||||
@@ -33,19 +33,19 @@ export default function UDPHolePunchingDiagram() {
|
||||
transition={{ delay: 0.2 }}
|
||||
className="text-center"
|
||||
>
|
||||
<div className="bg-purple-100 dark:bg-purple-900 p-6 rounded-lg mb-4">
|
||||
<Server className="h-12 w-12 text-purple-600 dark:text-purple-400 mx-auto mb-2" />
|
||||
<h3 className="font-semibold text-gray-900 dark:text-white">HyperDHT</h3>
|
||||
<p className="text-sm text-gray-600 dark:text-gray-400">DHT signaling</p>
|
||||
<div className="bg-indigo-deep/80 p-6 rounded-lg mb-4">
|
||||
<Server className="h-12 w-12 text-indigo-light mx-auto mb-2" />
|
||||
<h3 className="font-semibold text-white">HyperDHT</h3>
|
||||
<p className="text-sm text-fog">DHT signaling</p>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center justify-center space-x-2 text-sm">
|
||||
<ArrowRight className="h-4 w-4 text-green-500" />
|
||||
<span className="text-gray-600 dark:text-gray-400">Exchange info</span>
|
||||
<ArrowRight className="h-4 w-4 text-success" />
|
||||
<span className="text-fog">Exchange info</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-center space-x-2 text-sm">
|
||||
<ArrowLeft className="h-4 w-4 text-green-500" />
|
||||
<span className="text-gray-600 dark:text-gray-400">Coordinate</span>
|
||||
<ArrowLeft className="h-4 w-4 text-success" />
|
||||
<span className="text-fog">Coordinate</span>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
@@ -58,29 +58,29 @@ export default function UDPHolePunchingDiagram() {
|
||||
transition={{ delay: 0.4 }}
|
||||
className="text-center"
|
||||
>
|
||||
<div className="bg-green-100 dark:bg-green-900 p-6 rounded-lg mb-4">
|
||||
<Network className="h-12 w-12 text-green-600 dark:text-green-400 mx-auto mb-2" />
|
||||
<h3 className="font-semibold text-gray-900 dark:text-white">Peer B</h3>
|
||||
<p className="text-sm text-gray-600 dark:text-gray-400">Behind NAT</p>
|
||||
<div className="bg-success/15 p-6 rounded-lg mb-4">
|
||||
<Network className="h-12 w-12 text-success mx-auto mb-2" />
|
||||
<h3 className="font-semibold text-white">Peer B</h3>
|
||||
<p className="text-sm text-fog">Behind NAT</p>
|
||||
</div>
|
||||
<div className="text-sm text-gray-600 dark:text-gray-400">
|
||||
<div className="text-sm text-fog">
|
||||
<p>Private IP: 10.0.0.5</p>
|
||||
<p>Public: 198.51.100.2:6000</p>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
<div className="mt-8 pt-8 border-t border-gray-200 dark:border-gray-700">
|
||||
<div className="mt-8 pt-8 border-t border-steel">
|
||||
<div className="text-center">
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
whileInView={{ opacity: 1 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ delay: 0.6 }}
|
||||
className="inline-flex items-center space-x-2 px-4 py-2 bg-green-100 dark:bg-green-900 rounded-lg"
|
||||
className="inline-flex items-center space-x-2 px-4 py-2 bg-success/15 rounded-lg"
|
||||
>
|
||||
<ArrowRight className="h-5 w-5 text-green-600 dark:text-green-400" />
|
||||
<span className="text-sm font-medium text-gray-900 dark:text-white">
|
||||
<ArrowRight className="h-5 w-5 text-success" />
|
||||
<span className="text-sm font-medium text-white">
|
||||
After hole-punching, peers connect directly
|
||||
</span>
|
||||
</motion.div>
|
||||
|
||||
@@ -1,86 +1,109 @@
|
||||
import Link from 'next/link';
|
||||
import { Github, ExternalLink } from 'lucide-react';
|
||||
import { ArrowUpRight } from 'lucide-react';
|
||||
import { legalDocuments, LEGAL_ENTITY } from '@/lib/legal/documents';
|
||||
import BrandLogo from '@/components/ui/BrandLogo';
|
||||
|
||||
export default function Footer() {
|
||||
const docLinks = [
|
||||
{ href: '/docs/getting-started', label: 'Getting Started' },
|
||||
{ href: '/docs/architecture', label: 'Architecture' },
|
||||
{ href: '/docs/plugins', label: 'Plugins' },
|
||||
{ href: '/docs/api', label: 'API Reference' },
|
||||
{ href: '/docs/troubleshooting', label: 'Troubleshooting' },
|
||||
];
|
||||
|
||||
const productLinks = [
|
||||
{ href: '/features', label: 'Features' },
|
||||
{ href: '/learn/p2p', label: 'Learn P2P' },
|
||||
{ href: '/about', label: 'About' },
|
||||
{ href: '/community', label: 'Community' },
|
||||
];
|
||||
|
||||
const primaryLegal = legalDocuments.filter((d) =>
|
||||
['terms', 'privacy', 'eula'].includes(d.id)
|
||||
);
|
||||
|
||||
export default function Footer() {
|
||||
return (
|
||||
<footer className="border-t border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-900">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-8">
|
||||
<div className="col-span-1 md:col-span-2 lg:col-span-2">
|
||||
<footer className="border-t border-steel/60 bg-deep">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-14">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-12 gap-10">
|
||||
<div className="lg:col-span-4">
|
||||
<BrandLogo href="/" iconSize={28} textClassName="text-lg" className="mb-4" />
|
||||
<p className="text-sm text-gray-600 dark:text-gray-400 mb-4">
|
||||
A robust, firewall-resistant peer-to-peer DNS resolution system that operates independently of centralized DNS infrastructure.
|
||||
<p className="text-sm text-fog leading-relaxed mb-5 max-w-sm">
|
||||
Decentralized, secure, and censorship-resistant naming infrastructure for the open
|
||||
web. Independent of ICANN. Built for networks that fight back.
|
||||
</p>
|
||||
<p className="text-xs font-medium tracking-wide uppercase text-indigo-light mb-3">
|
||||
Decentralized by Design
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-3">
|
||||
<a
|
||||
href="https://git.ssh.surf/snxraven/p2ns"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center space-x-2 text-sm text-gray-600 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
|
||||
className="inline-flex items-center gap-1.5 text-sm text-mist hover:text-white transition-colors"
|
||||
>
|
||||
<Github size={16} />
|
||||
<span>View on Git</span>
|
||||
<ExternalLink size={14} />
|
||||
Source
|
||||
<ArrowUpRight className="h-3.5 w-3.5" />
|
||||
</a>
|
||||
<a
|
||||
href="https://holesail.io"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center gap-1.5 text-sm text-mist hover:text-white transition-colors"
|
||||
>
|
||||
Holesail
|
||||
<ArrowUpRight className="h-3.5 w-3.5" />
|
||||
</a>
|
||||
<a
|
||||
href="https://pears.com"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center gap-1.5 text-sm text-mist hover:text-white transition-colors"
|
||||
>
|
||||
Pears
|
||||
<ArrowUpRight className="h-3.5 w-3.5" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h4 className="text-sm font-semibold mb-4 text-gray-900 dark:text-gray-100">Documentation</h4>
|
||||
<ul className="space-y-2">
|
||||
<li>
|
||||
<Link href="/docs/getting-started" className="text-sm text-gray-600 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors">
|
||||
Getting Started
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/docs/upgrading" className="text-sm text-gray-600 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors">
|
||||
Upgrading
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/docs/plugins" className="text-sm text-gray-600 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors">
|
||||
Plugins
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/learn/p2p" className="text-sm text-gray-600 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors">
|
||||
Learn P2P
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/features" className="text-sm text-gray-600 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors">
|
||||
Features
|
||||
<div className="lg:col-span-2">
|
||||
<h4 className="text-sm font-semibold text-white mb-4">Product</h4>
|
||||
<ul className="space-y-2.5">
|
||||
{productLinks.map((link) => (
|
||||
<li key={link.href}>
|
||||
<Link
|
||||
href={link.href}
|
||||
className="text-sm text-fog hover:text-white transition-colors"
|
||||
>
|
||||
{link.label}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h4 className="text-sm font-semibold mb-4 text-gray-900 dark:text-gray-100">Community</h4>
|
||||
<ul className="space-y-2">
|
||||
<li>
|
||||
<Link href="/community" className="text-sm text-gray-600 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors">
|
||||
Contributing
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/about" className="text-sm text-gray-600 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors">
|
||||
About
|
||||
<div className="lg:col-span-3">
|
||||
<h4 className="text-sm font-semibold text-white mb-4">Documentation</h4>
|
||||
<ul className="space-y-2.5">
|
||||
{docLinks.map((link) => (
|
||||
<li key={link.href}>
|
||||
<Link
|
||||
href={link.href}
|
||||
className="text-sm text-fog hover:text-white transition-colors"
|
||||
>
|
||||
{link.label}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h4 className="text-sm font-semibold mb-4 text-gray-900 dark:text-gray-100">Legal</h4>
|
||||
<ul className="space-y-2">
|
||||
<div className="lg:col-span-3">
|
||||
<h4 className="text-sm font-semibold text-white mb-4">Legal</h4>
|
||||
<ul className="space-y-2.5">
|
||||
<li>
|
||||
<Link href="/legal" className="text-sm text-gray-600 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors">
|
||||
<Link href="/legal" className="text-sm text-fog hover:text-white transition-colors">
|
||||
Legal overview
|
||||
</Link>
|
||||
</li>
|
||||
@@ -88,7 +111,7 @@ export default function Footer() {
|
||||
<li key={doc.href}>
|
||||
<Link
|
||||
href={doc.href}
|
||||
className="text-sm text-gray-600 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
|
||||
className="text-sm text-fog hover:text-white transition-colors"
|
||||
>
|
||||
{doc.title}
|
||||
</Link>
|
||||
@@ -98,23 +121,19 @@ export default function Footer() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-8 pt-8 border-t border-gray-200 dark:border-gray-800">
|
||||
<p className="text-sm text-center text-gray-600 dark:text-gray-400">
|
||||
© {new Date().getFullYear()} {LEGAL_ENTITY}.
|
||||
<span className="hidden sm:inline"> · </span>
|
||||
<span className="block sm:inline mt-2 sm:mt-0">
|
||||
<div className="mt-12 pt-8 border-t border-steel/50 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
|
||||
<p className="text-sm text-fog">
|
||||
© {new Date().getFullYear()} {LEGAL_ENTITY}
|
||||
</p>
|
||||
<p className="text-sm text-fog">
|
||||
{primaryLegal.map((doc, i) => (
|
||||
<span key={doc.href}>
|
||||
{i > 0 && <span className="mx-1.5">·</span>}
|
||||
<Link
|
||||
href={doc.href}
|
||||
className="hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
|
||||
>
|
||||
{i > 0 && <span className="mx-2 text-steel">·</span>}
|
||||
<Link href={doc.href} className="hover:text-white transition-colors">
|
||||
{doc.shortTitle}
|
||||
</Link>
|
||||
</span>
|
||||
))}
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import Link from 'next/link';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { useState } from 'react';
|
||||
import { Menu, X, Ship } from 'lucide-react';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
@@ -22,26 +23,39 @@ const externalNavItems = [
|
||||
{ name: 'Built with Pears', href: 'https://pears.com', icon: PearsIcon },
|
||||
];
|
||||
|
||||
function isActive(pathname: string, href: string) {
|
||||
if (href === '/') return pathname === '/';
|
||||
return pathname === href || pathname.startsWith(`${href}/`);
|
||||
}
|
||||
|
||||
export default function Navigation() {
|
||||
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
||||
const pathname = usePathname();
|
||||
|
||||
return (
|
||||
<nav className="sticky top-0 z-50 w-full border-b border-gray-200 dark:border-gray-800 bg-white/80 dark:bg-gray-900/80 backdrop-blur-sm">
|
||||
<nav className="sticky top-0 z-50 w-full border-b border-steel/50 bg-midnight/85 backdrop-blur-md">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex justify-between items-center h-16">
|
||||
<BrandLogo />
|
||||
|
||||
{/* Desktop Navigation */}
|
||||
<div className="hidden md:flex items-center space-x-8">
|
||||
{navItems.map((item) => (
|
||||
<div className="hidden md:flex items-center gap-1 flex-wrap justify-end">
|
||||
{navItems.map((item) => {
|
||||
const active = isActive(pathname, item.href);
|
||||
return (
|
||||
<Link
|
||||
key={item.href}
|
||||
href={item.href}
|
||||
className="text-sm font-medium text-gray-700 dark:text-gray-300 hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
|
||||
className={`px-2.5 py-2 rounded-md text-sm font-medium transition-colors whitespace-nowrap ${
|
||||
active
|
||||
? 'text-white bg-surface'
|
||||
: 'text-mist hover:text-white hover:bg-surface/60'
|
||||
}`}
|
||||
>
|
||||
{item.name}
|
||||
</Link>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
{externalNavItems.map((item) => {
|
||||
const Icon = item.icon;
|
||||
return (
|
||||
@@ -50,9 +64,9 @@ export default function Navigation() {
|
||||
href={item.href}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-sm font-medium text-gray-700 dark:text-gray-300 hover:text-blue-600 dark:hover:text-blue-400 transition-colors flex items-center space-x-1.5"
|
||||
className="px-2.5 py-2 rounded-md text-sm font-medium text-mist hover:text-white hover:bg-surface/60 transition-colors flex items-center gap-1.5 whitespace-nowrap"
|
||||
>
|
||||
<Icon className="h-4 w-4" />
|
||||
<Icon className="h-4 w-4 shrink-0" />
|
||||
<span>{item.name}</span>
|
||||
</a>
|
||||
);
|
||||
@@ -61,11 +75,13 @@ export default function Navigation() {
|
||||
|
||||
{/* Mobile Menu Button */}
|
||||
<button
|
||||
className="md:hidden p-2 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800"
|
||||
type="button"
|
||||
className="md:hidden p-2 rounded-md text-mist hover:text-white hover:bg-surface transition-colors"
|
||||
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
|
||||
aria-label="Toggle menu"
|
||||
aria-label={mobileMenuOpen ? 'Close menu' : 'Open menu'}
|
||||
aria-expanded={mobileMenuOpen}
|
||||
>
|
||||
{mobileMenuOpen ? <X size={24} /> : <Menu size={24} />}
|
||||
{mobileMenuOpen ? <X size={22} /> : <Menu size={22} />}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -77,19 +93,26 @@ export default function Navigation() {
|
||||
initial={{ opacity: 0, height: 0 }}
|
||||
animate={{ opacity: 1, height: 'auto' }}
|
||||
exit={{ opacity: 0, height: 0 }}
|
||||
className="md:hidden border-t border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-900"
|
||||
className="md:hidden border-t border-steel/50 bg-deep overflow-hidden"
|
||||
>
|
||||
<div className="px-4 pt-2 pb-4 space-y-1">
|
||||
{navItems.map((item) => (
|
||||
{navItems.map((item) => {
|
||||
const active = isActive(pathname, item.href);
|
||||
return (
|
||||
<Link
|
||||
key={item.href}
|
||||
href={item.href}
|
||||
className="block px-3 py-2 rounded-md text-base font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
|
||||
className={`block px-3 py-2.5 rounded-md text-base font-medium transition-colors ${
|
||||
active
|
||||
? 'text-white bg-surface'
|
||||
: 'text-mist hover:text-white hover:bg-surface/60'
|
||||
}`}
|
||||
onClick={() => setMobileMenuOpen(false)}
|
||||
>
|
||||
{item.name}
|
||||
</Link>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
{externalNavItems.map((item) => {
|
||||
const Icon = item.icon;
|
||||
return (
|
||||
@@ -98,7 +121,7 @@ export default function Navigation() {
|
||||
href={item.href}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex items-center space-x-2 px-3 py-2 rounded-md text-base font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
|
||||
className="flex items-center gap-2 px-3 py-2.5 rounded-md text-base font-medium text-mist hover:text-white hover:bg-surface/60 transition-colors"
|
||||
onClick={() => setMobileMenuOpen(false)}
|
||||
>
|
||||
<Icon className="h-4 w-4" />
|
||||
@@ -113,4 +136,3 @@ export default function Navigation() {
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,19 +20,19 @@ export default function LegalDocumentLayout({
|
||||
showNotice = false,
|
||||
}: LegalDocumentLayoutProps) {
|
||||
return (
|
||||
<div className="min-h-screen bg-[#111829]" data-legal-page>
|
||||
<div className="min-h-screen bg-midnight" data-legal-page>
|
||||
<section
|
||||
data-legal-hero
|
||||
className="py-20 bg-gradient-to-b from-blue-50 to-white dark:from-gray-900 dark:to-gray-800 text-white"
|
||||
className="py-20 bg-grid-fade border-b border-steel/40 text-white"
|
||||
>
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<nav
|
||||
aria-label="Breadcrumb"
|
||||
className="flex flex-wrap items-center gap-1.5 text-sm text-gray-300 mb-6"
|
||||
className="flex flex-wrap items-center gap-1.5 text-sm text-fog mb-6"
|
||||
>
|
||||
<Link
|
||||
href="/legal"
|
||||
className="inline-flex items-center gap-1 text-white hover:text-blue-300 transition-colors"
|
||||
className="inline-flex items-center gap-1 text-mist hover:text-white transition-colors"
|
||||
>
|
||||
<Scale className="h-4 w-4 shrink-0 opacity-80" aria-hidden />
|
||||
Legal
|
||||
@@ -44,20 +44,20 @@ export default function LegalDocumentLayout({
|
||||
{title}
|
||||
</h1>
|
||||
{description && (
|
||||
<p className="text-xl text-gray-200">{description}</p>
|
||||
<p className="text-xl text-mist">{description}</p>
|
||||
)}
|
||||
<p className="mt-4 text-sm text-gray-300">
|
||||
<p className="mt-4 text-sm text-fog">
|
||||
Last updated {LEGAL_LAST_UPDATED}
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section data-legal-content className="py-20 bg-white dark:bg-gray-900 text-white">
|
||||
<section data-legal-content className="py-20 bg-midnight text-white">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
{showNotice && (
|
||||
<div
|
||||
role="note"
|
||||
className="mb-8 flex gap-3 rounded-lg border border-amber-200 dark:border-amber-800 bg-amber-50 dark:bg-amber-900/30 px-4 py-3 text-sm leading-relaxed text-white"
|
||||
className="mb-8 flex gap-3 rounded-lg border border-warning/40 bg-warning/10 px-4 py-3 text-sm leading-relaxed text-white"
|
||||
>
|
||||
<span className="mt-0.5 shrink-0" aria-hidden>
|
||||
⚠
|
||||
@@ -78,10 +78,10 @@ export default function LegalDocumentLayout({
|
||||
<li key={link.href}>
|
||||
<Link
|
||||
href={link.href}
|
||||
className="group flex items-center justify-between gap-3 rounded-lg border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 px-4 py-3 text-sm font-medium text-gray-900 dark:text-white transition-all hover:border-blue-500 dark:hover:border-blue-500 hover:shadow-md"
|
||||
className="group flex items-center justify-between gap-3 rounded-lg border border-steel bg-surface px-4 py-3 text-sm font-medium text-white transition-all hover:border-indigo"
|
||||
>
|
||||
<span>{link.label}</span>
|
||||
<ChevronRight className="h-4 w-4 shrink-0 text-gray-300 group-hover:text-blue-300 transition-colors" />
|
||||
<ChevronRight className="h-4 w-4 shrink-0 text-fog group-hover:text-indigo-pale transition-colors" />
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
'use client';
|
||||
|
||||
import Link from 'next/link';
|
||||
import { ArrowRight, MessageCircle } from 'lucide-react';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
export default function CtaBand() {
|
||||
return (
|
||||
<section className="py-20 sm:py-24 bg-midnight">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 12 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
className="relative overflow-hidden rounded-2xl border border-steel bg-surface"
|
||||
>
|
||||
<div className="absolute inset-0 bg-grid opacity-60 pointer-events-none" />
|
||||
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_0%_50%,rgba(99,102,241,0.18),transparent_55%)] pointer-events-none" />
|
||||
|
||||
<div className="relative px-6 py-12 sm:px-12 sm:py-16 lg:flex lg:items-center lg:justify-between gap-8">
|
||||
<div className="max-w-xl mb-8 lg:mb-0">
|
||||
<p className="text-sm font-medium uppercase tracking-wide text-indigo-light mb-3">
|
||||
Ready when you are
|
||||
</p>
|
||||
<h2 className="text-2xl sm:text-3xl font-bold text-white tracking-tight mb-3">
|
||||
Run your own naming mesh
|
||||
</h2>
|
||||
<p className="text-mist leading-relaxed">
|
||||
Open source. Self-hosted. No accounts, no cloud dependency. Join the Holesail
|
||||
community or dive straight into the docs.
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex flex-col sm:flex-row gap-3 shrink-0">
|
||||
<Link href="/docs/getting-started" className="btn-primary">
|
||||
Install P2NS
|
||||
<ArrowRight className="h-4 w-4" />
|
||||
</Link>
|
||||
<a
|
||||
href="https://discord.gg/3gFegYtNbN"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="btn-secondary"
|
||||
>
|
||||
<MessageCircle className="h-4 w-4" />
|
||||
Discord
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -11,107 +11,105 @@ import {
|
||||
Server,
|
||||
Users,
|
||||
RefreshCw,
|
||||
type LucideIcon,
|
||||
} from 'lucide-react';
|
||||
import Link from 'next/link';
|
||||
import SectionHeading from '@/components/ui/SectionHeading';
|
||||
|
||||
const features = [
|
||||
const features: { name: string; description: string; icon: LucideIcon }[] = [
|
||||
{
|
||||
name: 'Decentralized DNS',
|
||||
description: 'Resolve domains to hashes via P2P core, independent of ICANN or central DNS servers.',
|
||||
description:
|
||||
'Resolve domains to Holesail hashes via a P2P ledger — independent of ICANN and central resolvers.',
|
||||
icon: Network,
|
||||
color: 'from-blue-500 to-blue-600',
|
||||
},
|
||||
{
|
||||
name: 'Firewall Traversal',
|
||||
description: 'Uses Holesail for UDP hole-punching to connect across restrictive networks, NAT, and CGNAT.',
|
||||
description:
|
||||
'UDP hole-punching with Holesail connects across NAT, CGNAT, 4G/5G, and satellite networks.',
|
||||
icon: Shield,
|
||||
color: 'from-green-500 to-green-600',
|
||||
},
|
||||
{
|
||||
name: 'Dynamic IP Assignment',
|
||||
description: 'Assigns unique local IPs to domains via virtual network interfaces for seamless routing.',
|
||||
name: 'Local IP Assignment',
|
||||
description:
|
||||
'Virtual interfaces assign per-domain IPs so browsers and tools route like any other site.',
|
||||
icon: Zap,
|
||||
color: 'from-yellow-500 to-yellow-600',
|
||||
},
|
||||
{
|
||||
name: 'Hybrid DNS Resolution',
|
||||
description: 'Falls back to public DNS for non-P2P domains with custom local DNS record support.',
|
||||
name: 'Hybrid Resolution',
|
||||
description:
|
||||
'Public DNS fallback for non-P2P names, plus custom local records when you need them.',
|
||||
icon: Globe,
|
||||
color: 'from-purple-500 to-purple-600',
|
||||
},
|
||||
{
|
||||
name: 'Integrated Proxy',
|
||||
description: 'HTTP/HTTPS proxies with automatic redirection, WebSocket support, and TLS management.',
|
||||
name: 'HTTPS Proxy',
|
||||
description:
|
||||
'HTTP/HTTPS with WebSocket support, auto HTTP→HTTPS redirect, and per-domain TLS.',
|
||||
icon: Server,
|
||||
color: 'from-red-500 to-red-600',
|
||||
},
|
||||
{
|
||||
name: 'Certificate Authority',
|
||||
description: 'Automatic certificate generation and installation with root CA and per-domain certificates.',
|
||||
description:
|
||||
'Root CA and per-domain certs generated and managed automatically for seamless TLS.',
|
||||
icon: Lock,
|
||||
color: 'from-indigo-500 to-indigo-600',
|
||||
},
|
||||
{
|
||||
name: 'Admin Interface',
|
||||
description: 'Comprehensive web-based management panel for domains, servers, DNS, and certificates.',
|
||||
description:
|
||||
'Real-time management at p2ns.admin — domains, peers, logs, stats, and plugins.',
|
||||
icon: Settings,
|
||||
color: 'from-pink-500 to-pink-600',
|
||||
},
|
||||
{
|
||||
name: 'Peer Directory',
|
||||
description: 'Web-based directory for browsing and searching domains across the P2P network.',
|
||||
description:
|
||||
'Browse and search domains across the mesh at peer.directory.',
|
||||
icon: Users,
|
||||
color: 'from-cyan-500 to-cyan-600',
|
||||
},
|
||||
{
|
||||
name: 'Service Subscriptions',
|
||||
description: 'Auto-subscribe to domain services with dynamic synchronization.',
|
||||
description:
|
||||
'Auto-subscribe to services published by other domains and stay in sync as they change.',
|
||||
icon: RefreshCw,
|
||||
color: 'from-orange-500 to-orange-600',
|
||||
},
|
||||
];
|
||||
|
||||
export default function FeaturesGrid() {
|
||||
return (
|
||||
<section className="py-24 bg-white dark:bg-gray-900">
|
||||
<section className="py-20 sm:py-24 bg-midnight">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-16">
|
||||
<h2 className="text-3xl sm:text-4xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
Powerful Features
|
||||
</h2>
|
||||
<p className="text-lg text-gray-600 dark:text-gray-300 max-w-2xl mx-auto">
|
||||
Everything you need to build and manage a decentralized DNS network
|
||||
</p>
|
||||
</div>
|
||||
<SectionHeading
|
||||
eyebrow="Capabilities"
|
||||
title="Infrastructure that works offline of the establishment"
|
||||
description="Everything you need to claim names, traverse hostile networks, and run services on a peer mesh."
|
||||
/>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 sm:gap-5">
|
||||
{features.map((feature, index) => {
|
||||
const Icon = feature.icon;
|
||||
const isLastItem = index === features.length - 1;
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
key={feature.name}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
initial={{ opacity: 0, y: 12 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.5, delay: index * 0.1 }}
|
||||
className={`relative group ${isLastItem ? 'lg:col-start-2 lg:col-span-2' : ''}`}
|
||||
viewport={{ once: true, margin: '-40px' }}
|
||||
transition={{ duration: 0.35, delay: Math.min(index * 0.05, 0.3) }}
|
||||
className="surface-card surface-card-hover p-6"
|
||||
>
|
||||
<div className="bg-white dark:bg-gray-800 rounded-lg p-6 border border-gray-200 dark:border-gray-700 hover:border-blue-500 dark:hover:border-blue-500 transition-all hover:shadow-lg h-full">
|
||||
<div className={`inline-flex p-3 rounded-lg bg-gradient-to-r ${feature.color} mb-4`}>
|
||||
<Icon className="h-6 w-6 text-white" />
|
||||
</div>
|
||||
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">
|
||||
{feature.name}
|
||||
</h3>
|
||||
<p className="text-sm text-gray-600 dark:text-gray-400">
|
||||
{feature.description}
|
||||
</p>
|
||||
<div className="inline-flex p-2.5 rounded-lg bg-indigo-deep/80 border border-indigo-dark/40 mb-4">
|
||||
<Icon className="h-5 w-5 text-indigo-light" aria-hidden />
|
||||
</div>
|
||||
<h3 className="text-base font-semibold text-white mb-2">{feature.name}</h3>
|
||||
<p className="text-sm text-fog leading-relaxed">{feature.description}</p>
|
||||
</motion.div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="mt-10 text-center">
|
||||
<Link href="/features" className="link-accent text-sm font-medium">
|
||||
Explore all features →
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
||||
@@ -2,72 +2,109 @@
|
||||
|
||||
import Link from 'next/link';
|
||||
import Image from 'next/image';
|
||||
import { ArrowRight, Zap } from 'lucide-react';
|
||||
import { ArrowRight, BookOpen, Shield, Network, Zap } from 'lucide-react';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
const highlights = [
|
||||
{ icon: Network, label: 'ICANN-independent DNS' },
|
||||
{ icon: Shield, label: 'NAT & firewall traversal' },
|
||||
{ icon: Zap, label: 'Local resolution, zero round-trips' },
|
||||
];
|
||||
|
||||
export default function Hero() {
|
||||
return (
|
||||
<section className="relative overflow-hidden bg-gradient-to-b from-blue-50 via-white to-white dark:from-gray-900 dark:via-gray-900 dark:to-gray-900 py-20 sm:py-32">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center">
|
||||
<section className="relative overflow-hidden bg-grid-fade border-b border-steel/40">
|
||||
<div className="absolute inset-0 pointer-events-none bg-[radial-gradient(ellipse_at_80%_20%,rgba(99,102,241,0.12),transparent_50%)]" />
|
||||
|
||||
<div className="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20 sm:py-28 lg:py-32">
|
||||
<div className="grid lg:grid-cols-12 gap-12 lg:gap-8 items-center">
|
||||
<div className="lg:col-span-7">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
initial={{ opacity: 0, y: 16 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
transition={{ duration: 0.45 }}
|
||||
>
|
||||
<div className="flex justify-center mb-6">
|
||||
<Image
|
||||
src="/branding/p2ns-favicon-512.png"
|
||||
alt=""
|
||||
width={256}
|
||||
height={256}
|
||||
priority
|
||||
/>
|
||||
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full border border-steel bg-surface/80 text-xs font-medium text-indigo-light mb-6">
|
||||
<span className="h-1.5 w-1.5 rounded-full bg-success" aria-hidden />
|
||||
Peer-to-Peer Name System
|
||||
</div>
|
||||
<h1 className="text-4xl sm:text-5xl md:text-6xl font-bold tracking-tight text-gray-900 dark:text-white mb-6">
|
||||
Decentralized DNS for the
|
||||
<span className="block bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent">
|
||||
Modern Internet
|
||||
</span>
|
||||
|
||||
<h1 className="text-4xl sm:text-5xl lg:text-6xl font-bold tracking-tight text-white leading-[1.08] mb-6">
|
||||
Naming for the open web —{' '}
|
||||
<span className="text-indigo-light">decentralized by design</span>
|
||||
</h1>
|
||||
<p className="mt-6 text-lg sm:text-xl text-gray-600 dark:text-gray-300 max-w-3xl mx-auto">
|
||||
P2NS is a robust, firewall-resistant peer-to-peer DNS resolution system that operates independently of centralized DNS infrastructure.
|
||||
Connect across firewalls, NAT, CGNAT, and restricted networks with ease.
|
||||
|
||||
<p className="text-lg sm:text-xl text-mist leading-relaxed max-w-xl mb-8">
|
||||
P2NS is firewall-resistant peer-to-peer DNS. Resolve and host names across NAT,
|
||||
CGNAT, and restricted networks without centralized infrastructure.
|
||||
</p>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.5, delay: 0.2 }}
|
||||
className="mt-10 flex flex-col sm:flex-row gap-4 justify-center"
|
||||
>
|
||||
<Link
|
||||
href="/docs"
|
||||
className="inline-flex items-center justify-center px-6 py-3 border border-transparent text-base font-medium rounded-md text-white bg-gradient-to-r from-blue-600 to-purple-600 hover:from-blue-700 hover:to-purple-700 transition-all shadow-lg hover:shadow-xl"
|
||||
>
|
||||
<div className="flex flex-col sm:flex-row gap-3 mb-10">
|
||||
<Link href="/docs/getting-started" className="btn-primary">
|
||||
Get Started
|
||||
<ArrowRight className="ml-2 h-5 w-5" />
|
||||
<ArrowRight className="h-4 w-4" />
|
||||
</Link>
|
||||
<Link
|
||||
href="/learn/p2p"
|
||||
className="inline-flex items-center justify-center px-6 py-3 border border-gray-300 dark:border-gray-700 text-base font-medium rounded-md text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"
|
||||
>
|
||||
Learn How P2P Works
|
||||
<Zap className="ml-2 h-5 w-5" />
|
||||
<Link href="/docs" className="btn-secondary">
|
||||
<BookOpen className="h-4 w-4" />
|
||||
View Docs
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<ul className="flex flex-col sm:flex-row sm:flex-wrap gap-4 sm:gap-6">
|
||||
{highlights.map(({ icon: Icon, label }) => (
|
||||
<li key={label} className="inline-flex items-center gap-2 text-sm text-fog">
|
||||
<Icon className="h-4 w-4 text-indigo shrink-0" aria-hidden />
|
||||
{label}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.5, delay: 0.4 }}
|
||||
className="mt-16"
|
||||
className="lg:col-span-5 flex justify-center lg:justify-end"
|
||||
initial={{ opacity: 0, scale: 0.96 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
transition={{ duration: 0.5, delay: 0.12 }}
|
||||
>
|
||||
<div className="relative w-full max-w-md">
|
||||
<div className="surface-card p-8 sm:p-10 flex flex-col items-center text-center">
|
||||
<Image
|
||||
src="/branding/p2ns-icon.png"
|
||||
alt="P2NS network mark"
|
||||
width={128}
|
||||
height={128}
|
||||
priority
|
||||
className="mb-6"
|
||||
/>
|
||||
<p className="text-2xl font-bold text-white tracking-tight mb-1">P2NS</p>
|
||||
<p className="text-sm text-indigo-light font-medium mb-4">
|
||||
Peer-to-Peer Name System
|
||||
</p>
|
||||
<p className="text-sm text-fog leading-relaxed">
|
||||
Domains resolve on your device via Autobase consensus. Tunnels punch through with
|
||||
Holesail. No root servers. No gatekeepers.
|
||||
</p>
|
||||
<div className="mt-6 w-full grid grid-cols-3 gap-2 text-center">
|
||||
{[
|
||||
{ k: 'UDP 53', v: 'DNS' },
|
||||
{ k: 'TLS', v: 'Local CA' },
|
||||
{ k: 'P2P', v: 'Hyperswarm' },
|
||||
].map((stat) => (
|
||||
<div
|
||||
key={stat.k}
|
||||
className="rounded-lg bg-midnight/80 border border-steel/70 px-2 py-3"
|
||||
>
|
||||
<p className="text-xs font-semibold text-white">{stat.k}</p>
|
||||
<p className="text-[11px] text-fog mt-0.5">{stat.v}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,81 +2,86 @@
|
||||
|
||||
import { motion } from 'framer-motion';
|
||||
import { Search, Network, Lock, CheckCircle } from 'lucide-react';
|
||||
import Link from 'next/link';
|
||||
import SectionHeading from '@/components/ui/SectionHeading';
|
||||
|
||||
const steps = [
|
||||
{
|
||||
number: '01',
|
||||
title: 'Discover Peers',
|
||||
description: 'Hyperswarm discovers peers using a fixed topic, enabling automatic peer discovery across the network.',
|
||||
title: 'Discover peers',
|
||||
description:
|
||||
'Hyperswarm finds peers on a fixed topic so nodes meet without central directories.',
|
||||
icon: Search,
|
||||
},
|
||||
{
|
||||
number: '02',
|
||||
title: 'Establish Connection',
|
||||
description: 'UDP hole-punching via Holesail creates connections across firewalls, NAT, and CGNAT.',
|
||||
title: 'Punch through NAT',
|
||||
description:
|
||||
'Holesail establishes direct UDP tunnels across firewalls, NAT, and CGNAT.',
|
||||
icon: Network,
|
||||
},
|
||||
{
|
||||
number: '03',
|
||||
title: 'Resolve Domains',
|
||||
description: 'Domains resolve to Holesail hashes via the Autobase consensus sidecar (Autopass KV for writes).',
|
||||
title: 'Resolve names',
|
||||
description:
|
||||
'Domain claims live in Autopass; Autobase consensus makes every peer resolve the same way.',
|
||||
icon: Lock,
|
||||
},
|
||||
{
|
||||
number: '04',
|
||||
title: 'Route Traffic',
|
||||
description: 'Virtual interfaces assign local IPs, and integrated proxies route traffic through secure tunnels.',
|
||||
title: 'Route traffic',
|
||||
description:
|
||||
'Virtual interfaces assign local IPs; the HTTPS proxy terminates TLS and forwards to tunnels.',
|
||||
icon: CheckCircle,
|
||||
},
|
||||
];
|
||||
|
||||
export default function HowItWorks() {
|
||||
return (
|
||||
<section className="py-24 bg-gray-50 dark:bg-gray-800">
|
||||
<section className="py-20 sm:py-24 bg-deep border-y border-steel/40">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-16">
|
||||
<h2 className="text-3xl sm:text-4xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
How It Works
|
||||
</h2>
|
||||
<p className="text-lg text-gray-600 dark:text-gray-300 max-w-2xl mx-auto">
|
||||
P2NS uses cutting-edge P2P technology to create a resilient, decentralized DNS system
|
||||
</p>
|
||||
</div>
|
||||
<SectionHeading
|
||||
eyebrow="Pipeline"
|
||||
title="How it works"
|
||||
description="From peer discovery to a live site — four steps, no root servers."
|
||||
/>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 sm:gap-5">
|
||||
{steps.map((step, index) => (
|
||||
<motion.div
|
||||
key={step.number}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
initial={{ opacity: 0, y: 12 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.5, delay: index * 0.1 }}
|
||||
viewport={{ once: true, margin: '-40px' }}
|
||||
transition={{ duration: 0.35, delay: index * 0.08 }}
|
||||
className="relative"
|
||||
>
|
||||
<div className="bg-white dark:bg-gray-900 rounded-lg p-6 border border-gray-200 dark:border-gray-700 h-full">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<span className="text-4xl font-bold text-gray-200 dark:text-gray-700">
|
||||
{step.number}
|
||||
</span>
|
||||
<div className="p-3 rounded-lg bg-blue-100 dark:bg-blue-900">
|
||||
<step.icon className="h-6 w-6 text-blue-600 dark:text-blue-400" />
|
||||
<div className="surface-card p-6 h-full">
|
||||
<div className="flex items-center justify-between mb-5">
|
||||
<span className="text-3xl font-bold tabular-nums text-steel">{step.number}</span>
|
||||
<div className="p-2.5 rounded-lg bg-indigo-deep/80 border border-indigo-dark/40">
|
||||
<step.icon className="h-5 w-5 text-indigo-light" aria-hidden />
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">
|
||||
{step.title}
|
||||
</h3>
|
||||
<p className="text-sm text-gray-600 dark:text-gray-400">
|
||||
{step.description}
|
||||
</p>
|
||||
<h3 className="text-lg font-semibold text-white mb-2">{step.title}</h3>
|
||||
<p className="text-sm text-fog leading-relaxed">{step.description}</p>
|
||||
</div>
|
||||
{index < steps.length - 1 && (
|
||||
<div className="hidden lg:block absolute top-1/2 -right-4 w-8 h-0.5 bg-gray-300 dark:bg-gray-600 transform -translate-y-1/2" />
|
||||
<div
|
||||
className="hidden lg:block absolute top-1/2 -right-2.5 w-5 h-px bg-steel"
|
||||
aria-hidden
|
||||
/>
|
||||
)}
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="mt-10 text-center">
|
||||
<Link href="/docs/how-it-works" className="link-accent text-sm font-medium">
|
||||
Deep dive into the flow →
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,25 @@
|
||||
'use client';
|
||||
|
||||
import { motion } from 'framer-motion';
|
||||
import { Terminal, Copy, Check } from 'lucide-react';
|
||||
import { Terminal, Copy, Check, ArrowRight } from 'lucide-react';
|
||||
import { useState } from 'react';
|
||||
import Link from 'next/link';
|
||||
import SectionHeading from '@/components/ui/SectionHeading';
|
||||
|
||||
const commands = [
|
||||
{ label: 'Clone repository', command: 'git clone https://git.ssh.surf/snxraven/p2ns.git' },
|
||||
{ label: 'Install dependencies', command: 'npm install' },
|
||||
{ label: 'Genesis master (once per network)', command: 'sudo node p2ns.js --master --genesis' },
|
||||
{ label: 'Secondary master (optional HA)', command: 'sudo node p2ns.js --master' },
|
||||
{ label: 'Joiner node (most users)', command: 'sudo node p2ns.js' },
|
||||
{
|
||||
label: 'Clone',
|
||||
command: 'git clone https://git.ssh.surf/snxraven/p2ns.git && cd p2ns',
|
||||
},
|
||||
{ label: 'Install', command: 'npm install' },
|
||||
{
|
||||
label: 'Genesis master (once per network)',
|
||||
command: 'sudo node p2ns.js --master --genesis',
|
||||
},
|
||||
{
|
||||
label: 'Joiner (most peers)',
|
||||
command: 'sudo node p2ns.js',
|
||||
},
|
||||
];
|
||||
|
||||
export default function QuickStart() {
|
||||
@@ -22,66 +32,64 @@ export default function QuickStart() {
|
||||
};
|
||||
|
||||
return (
|
||||
<section className="py-24 bg-gradient-to-b from-gray-50 to-white dark:from-gray-800 dark:to-gray-900">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-3xl sm:text-4xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
Quick Start
|
||||
</h2>
|
||||
<p className="text-lg text-gray-600 dark:text-gray-300">
|
||||
Get P2NS running in minutes
|
||||
</p>
|
||||
</div>
|
||||
<section className="py-20 sm:py-24 bg-deep border-t border-steel/40">
|
||||
<div className="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<SectionHeading
|
||||
eyebrow="Install"
|
||||
title="Quick start"
|
||||
description="Spin up a network in minutes. Genesis once, then joiners everywhere else."
|
||||
/>
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-3">
|
||||
{commands.map((item, index) => (
|
||||
<motion.div
|
||||
key={index}
|
||||
initial={{ opacity: 0, x: -20 }}
|
||||
key={item.label}
|
||||
initial={{ opacity: 0, x: -12 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.3, delay: index * 0.1 }}
|
||||
className="bg-gray-900 dark:bg-black rounded-lg p-4 border border-gray-800"
|
||||
transition={{ duration: 0.3, delay: index * 0.06 }}
|
||||
className="rounded-xl border border-steel bg-midnight p-4"
|
||||
>
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<span className="text-sm text-gray-400">{item.label}</span>
|
||||
<span className="text-xs font-medium uppercase tracking-wide text-fog">
|
||||
{item.label}
|
||||
</span>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => copyToClipboard(item.command, index)}
|
||||
className="p-1 text-gray-400 hover:text-white transition-colors"
|
||||
aria-label="Copy command"
|
||||
className="p-1.5 rounded-md text-fog hover:text-white hover:bg-surface transition-colors"
|
||||
aria-label={`Copy: ${item.label}`}
|
||||
>
|
||||
{copiedIndex === index ? (
|
||||
<Check className="h-4 w-4 text-green-500" />
|
||||
<Check className="h-4 w-4 text-success" />
|
||||
) : (
|
||||
<Copy className="h-4 w-4" />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<Terminal className="h-4 w-4 text-green-400" />
|
||||
<code className="text-sm text-gray-300 font-mono">{item.command}</code>
|
||||
<div className="flex items-start gap-2.5 min-w-0">
|
||||
<Terminal className="h-4 w-4 text-indigo-light shrink-0 mt-0.5" aria-hidden />
|
||||
<code className="text-sm text-snow font-mono break-all">{item.command}</code>
|
||||
</div>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.5, delay: 0.4 }}
|
||||
className="mt-8 text-center"
|
||||
className="mt-10 flex flex-col sm:flex-row items-center justify-center gap-4"
|
||||
>
|
||||
<a
|
||||
href="/docs"
|
||||
className="inline-flex items-center text-blue-600 dark:text-blue-400 hover:underline font-medium"
|
||||
>
|
||||
View full documentation
|
||||
<span className="ml-1">→</span>
|
||||
</a>
|
||||
<Link href="/docs/getting-started" className="btn-primary">
|
||||
Full installation guide
|
||||
<ArrowRight className="h-4 w-4" />
|
||||
</Link>
|
||||
<Link href="/docs/upgrading" className="btn-secondary">
|
||||
Upgrading
|
||||
</Link>
|
||||
</motion.div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,48 +1,72 @@
|
||||
'use client';
|
||||
|
||||
import { motion } from 'framer-motion';
|
||||
import { ArrowUpRight } from 'lucide-react';
|
||||
import SectionHeading from '@/components/ui/SectionHeading';
|
||||
|
||||
const technologies = [
|
||||
{ name: 'Corestore', description: 'Decentralized storage', url: 'https://www.npmjs.com/package/corestore' },
|
||||
{ name: 'Hyperswarm', description: 'HyperDHT discovery', url: 'https://www.npmjs.com/package/hyperswarm' },
|
||||
{ name: 'Holesail', description: 'Secure Tunnels', url: 'https://holesail.io' },
|
||||
{ name: 'Autopass', description: 'Claim/vote writes', url: 'https://www.npmjs.com/package/autopass' },
|
||||
{ name: 'Autobase', description: 'Consensus sidecar', url: 'https://www.npmjs.com/package/autobase' },
|
||||
{ name: 'Protomux', description: 'RPC multiplexing (core + plugins)', url: 'https://www.npmjs.com/package/protomux-rpc' },
|
||||
{
|
||||
name: 'Corestore',
|
||||
description: 'Append-only storage',
|
||||
url: 'https://www.npmjs.com/package/corestore',
|
||||
},
|
||||
{
|
||||
name: 'Hyperswarm',
|
||||
description: 'DHT peer discovery',
|
||||
url: 'https://www.npmjs.com/package/hyperswarm',
|
||||
},
|
||||
{
|
||||
name: 'Holesail',
|
||||
description: 'UDP hole-punch tunnels',
|
||||
url: 'https://holesail.io',
|
||||
},
|
||||
{
|
||||
name: 'Autopass',
|
||||
description: 'Claim & vote writes',
|
||||
url: 'https://www.npmjs.com/package/autopass',
|
||||
},
|
||||
{
|
||||
name: 'Autobase',
|
||||
description: 'Consensus sidecar',
|
||||
url: 'https://www.npmjs.com/package/autobase',
|
||||
},
|
||||
{
|
||||
name: 'Protomux',
|
||||
description: 'RPC multiplexing',
|
||||
url: 'https://www.npmjs.com/package/protomux-rpc',
|
||||
},
|
||||
];
|
||||
|
||||
export default function TechnologyStack() {
|
||||
return (
|
||||
<section className="py-24 bg-white dark:bg-gray-900">
|
||||
<section className="py-20 sm:py-24 bg-midnight">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-16">
|
||||
<h2 className="text-3xl sm:text-4xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
Built on Modern Technology
|
||||
</h2>
|
||||
<p className="text-lg text-gray-600 dark:text-gray-300 max-w-2xl mx-auto">
|
||||
P2NS leverages proven P2P technologies to create a robust, scalable system
|
||||
</p>
|
||||
</div>
|
||||
<SectionHeading
|
||||
eyebrow="Stack"
|
||||
title="Built on Holepunch infrastructure"
|
||||
description="P2NS stands on the same primitives that power modern P2P apps — storage, discovery, consensus, and tunnels."
|
||||
/>
|
||||
|
||||
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-6">
|
||||
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-3 sm:gap-4">
|
||||
{technologies.map((tech, index) => (
|
||||
<motion.a
|
||||
key={tech.name}
|
||||
href={tech.url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
initial={{ opacity: 0, scale: 0.9 }}
|
||||
whileInView={{ opacity: 1, scale: 1 }}
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.3, delay: index * 0.1 }}
|
||||
className="text-center p-6 bg-gray-50 dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 hover:border-blue-500 dark:hover:border-blue-500 transition-colors cursor-pointer block"
|
||||
transition={{ duration: 0.3, delay: index * 0.05 }}
|
||||
className="group surface-card surface-card-hover p-5 text-center block"
|
||||
>
|
||||
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-1">
|
||||
<div className="flex items-center justify-center gap-1 mb-1.5">
|
||||
<h3 className="text-sm font-semibold text-white group-hover:text-indigo-pale transition-colors">
|
||||
{tech.name}
|
||||
</h3>
|
||||
<p className="text-sm text-gray-600 dark:text-gray-400">
|
||||
{tech.description}
|
||||
</p>
|
||||
<ArrowUpRight className="h-3 w-3 text-fog opacity-0 group-hover:opacity-100 transition-opacity" />
|
||||
</div>
|
||||
<p className="text-xs text-fog leading-snug">{tech.description}</p>
|
||||
</motion.a>
|
||||
))}
|
||||
</div>
|
||||
@@ -50,4 +74,3 @@ export default function TechnologyStack() {
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ export default function BrandLogo({
|
||||
href = '/',
|
||||
showText = true,
|
||||
iconSize = 32,
|
||||
textClassName = 'text-2xl',
|
||||
textClassName = 'text-xl',
|
||||
className = '',
|
||||
}: BrandLogoProps) {
|
||||
const content = (
|
||||
@@ -27,20 +27,16 @@ export default function BrandLogo({
|
||||
priority
|
||||
/>
|
||||
{showText ? (
|
||||
<span
|
||||
className={`font-bold bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent ${textClassName}`}
|
||||
>
|
||||
P2NS
|
||||
</span>
|
||||
<span className={`font-bold tracking-tight text-white ${textClassName}`}>P2NS</span>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
|
||||
const classes = `inline-flex items-center gap-2 ${className}`.trim();
|
||||
const classes = `inline-flex items-center gap-2.5 focus-ring rounded-sm ${className}`.trim();
|
||||
|
||||
if (href) {
|
||||
return (
|
||||
<Link href={href} className={classes}>
|
||||
<Link href={href} className={classes} aria-label="P2NS home">
|
||||
{content}
|
||||
</Link>
|
||||
);
|
||||
|
||||
@@ -18,24 +18,24 @@ export default function CodeBlock({ code, language = 'bash' }: CodeBlockProps) {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="relative group">
|
||||
<div className="absolute top-2 right-2">
|
||||
<div className="relative group my-4">
|
||||
<div className="absolute top-2.5 right-2.5 z-10">
|
||||
<button
|
||||
type="button"
|
||||
onClick={copyToClipboard}
|
||||
className="p-2 bg-gray-700 hover:bg-gray-600 rounded text-gray-300 hover:text-white transition-colors opacity-0 group-hover:opacity-100"
|
||||
className="p-2 bg-surface hover:bg-steel border border-steel rounded-md text-fog hover:text-white transition-colors opacity-100 sm:opacity-0 sm:group-hover:opacity-100"
|
||||
aria-label="Copy code"
|
||||
>
|
||||
{copied ? (
|
||||
<Check className="h-4 w-4 text-green-400" />
|
||||
<Check className="h-4 w-4 text-success" />
|
||||
) : (
|
||||
<Copy className="h-4 w-4" />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
<pre className="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto">
|
||||
<code className={`language-${language}`}>{code}</code>
|
||||
<pre className="bg-deep text-snow p-4 pr-12 rounded-xl overflow-x-auto border border-steel text-sm leading-relaxed">
|
||||
<code className={`language-${language} font-mono`}>{code}</code>
|
||||
</pre>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
import Link from 'next/link';
|
||||
import { ChevronRight } from 'lucide-react';
|
||||
|
||||
type Crumb = { href?: string; label: string };
|
||||
|
||||
type PageHeaderProps = {
|
||||
title: string;
|
||||
description?: string;
|
||||
eyebrow?: string;
|
||||
breadcrumbs?: Crumb[];
|
||||
align?: 'left' | 'center';
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
export default function PageHeader({
|
||||
title,
|
||||
description,
|
||||
eyebrow,
|
||||
breadcrumbs,
|
||||
align = 'left',
|
||||
children,
|
||||
}: PageHeaderProps) {
|
||||
const alignClass = align === 'center' ? 'text-center mx-auto' : '';
|
||||
|
||||
return (
|
||||
<section className="relative overflow-hidden border-b border-steel/60 bg-grid-fade">
|
||||
<div className={`max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16 sm:py-20 ${alignClass}`}>
|
||||
{breadcrumbs && breadcrumbs.length > 0 && (
|
||||
<nav
|
||||
aria-label="Breadcrumb"
|
||||
className={`flex flex-wrap items-center gap-1.5 text-sm text-fog mb-6 ${ align === 'center' ? 'justify-center' : '' }`}
|
||||
>
|
||||
{breadcrumbs.map((crumb, i) => (
|
||||
<span key={`${crumb.label}-${i}`} className="inline-flex items-center gap-1.5">
|
||||
{i > 0 && <ChevronRight className="h-3.5 w-3.5 shrink-0 opacity-50" aria-hidden />}
|
||||
{crumb.href ? (
|
||||
<Link href={crumb.href} className="text-mist hover:text-white transition-colors">
|
||||
{crumb.label}
|
||||
</Link>
|
||||
) : (
|
||||
<span className="font-medium text-white">{crumb.label}</span>
|
||||
)}
|
||||
</span>
|
||||
))}
|
||||
</nav>
|
||||
)}
|
||||
{eyebrow && (
|
||||
<p className="text-sm font-medium tracking-wide uppercase text-indigo-light mb-3">
|
||||
{eyebrow}
|
||||
</p>
|
||||
)}
|
||||
<h1 className="text-4xl sm:text-5xl font-bold tracking-tight text-white mb-4 max-w-3xl">
|
||||
{title}
|
||||
</h1>
|
||||
{description && (
|
||||
<p className={`text-lg sm:text-xl text-mist leading-relaxed max-w-2xl ${align === 'center' ? 'mx-auto' : ''}`}>
|
||||
{description}
|
||||
</p>
|
||||
)}
|
||||
{children && <div className="mt-8">{children}</div>}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
type SectionHeadingProps = {
|
||||
title: string;
|
||||
description?: string;
|
||||
eyebrow?: string;
|
||||
align?: 'left' | 'center';
|
||||
className?: string;
|
||||
};
|
||||
|
||||
export default function SectionHeading({
|
||||
title,
|
||||
description,
|
||||
eyebrow,
|
||||
align = 'center',
|
||||
className = '',
|
||||
}: SectionHeadingProps) {
|
||||
const alignClass = align === 'center' ? 'text-center mx-auto' : '';
|
||||
|
||||
return (
|
||||
<div className={`mb-12 sm:mb-16 ${alignClass} ${className}`.trim()}>
|
||||
{eyebrow && (
|
||||
<p className="text-sm font-medium tracking-wide uppercase text-indigo-light mb-3">
|
||||
{eyebrow}
|
||||
</p>
|
||||
)}
|
||||
<h2 className="text-3xl sm:text-4xl font-bold tracking-tight text-white mb-4">{title}</h2>
|
||||
{description && (
|
||||
<p
|
||||
className={`text-lg text-mist max-w-2xl leading-relaxed ${ align === 'center' ? 'mx-auto' : '' }`}
|
||||
>
|
||||
{description}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
+3
-1
@@ -1,8 +1,10 @@
|
||||
import type { NextConfig } from "next";
|
||||
import path from "path";
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
turbopack: {
|
||||
root: process.cwd(),
|
||||
// Pin workspace root so parent package-lock.json is ignored
|
||||
root: path.join(__dirname),
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "P2NS - Peer-to-Peer Decentralized DNS",
|
||||
"name": "P2NS — Peer-to-Peer Name System",
|
||||
"short_name": "P2NS",
|
||||
"description": "A robust, firewall-resistant peer-to-peer DNS resolution system",
|
||||
"description": "Decentralized, secure, and censorship-resistant naming infrastructure for the open web",
|
||||
"start_url": "/",
|
||||
"display": "standalone",
|
||||
"background_color": "#0a0e1a",
|
||||
"theme_color": "#0a0e1a",
|
||||
"background_color": "#0A0E1A",
|
||||
"theme_color": "#6366F1",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/favicon.ico",
|
||||
|
||||
+8
-4
@@ -1,5 +1,9 @@
|
||||
import type { Config } from "tailwindcss";
|
||||
|
||||
/**
|
||||
* Tailwind v4 primarily uses @theme in globals.css.
|
||||
* This config remains for content paths and darkMode compatibility.
|
||||
*/
|
||||
const config: Config = {
|
||||
content: [
|
||||
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
@@ -13,13 +17,13 @@ const config: Config = {
|
||||
foreground: "var(--foreground)",
|
||||
},
|
||||
fontFamily: {
|
||||
sans: ['var(--font-inter)', 'system-ui', 'sans-serif'],
|
||||
mono: ['var(--font-mono)', 'monospace'],
|
||||
sans: ["var(--font-inter)", "system-ui", "sans-serif"],
|
||||
mono: ["var(--font-mono)", "monospace"],
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
darkMode: 'class',
|
||||
darkMode: "class",
|
||||
};
|
||||
export default config;
|
||||
|
||||
export default config;
|
||||
|
||||
Reference in New Issue
Block a user