Skip to content

Commit e9107b0

Browse files
committed
Feature: Home page rewrite, AsciinemaPlayer terminalFontSize prop + max-width
1 parent fae69b4 commit e9107b0

4 files changed

Lines changed: 296 additions & 10 deletions

File tree

www/src/pages/docs/home/pages/index/index.en.mdx

Lines changed: 146 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,73 @@
1+
import Mermaid from '@shared/components/visualization/Mermaid';
12
import AsciinemaPlayer from '@shared/components/visualization/AsciinemaPlayer';
23
import { InlineNotification } from '@carbon/react';
34

45
# Phantom-WG
56

6-
***Phantom-WG Modern*** is a WireGuard®-based VPN management platform. All components run within a Docker container architecture, and the core component Phantom Daemon communicates over Unix Domain Socket (UDS).
7+
***Phantom-WG*** is a modular tool that lets you set up and manage a WireGuard VPN infrastructure on your own server. Beyond basic VPN management, it offers censorship-resistant connections, multi-layered encryption, and advanced privacy scenarios.
8+
9+
***Phantom-WG Modern*** is the container-native implementation of this vision. All components run within Docker and are isolated from the host system:
10+
11+
- **Userspace WireGuard** — Container-scoped TUN device via Go FFI bridge. No kernel module required, does not touch the host's network namespace.
12+
- **nftables netlink FFI** — Rust backend communicates directly with the kernel. No subprocess calls, firewall rules are managed programmatically.
13+
- **SQLite State Persistence** — All state is stored in SQLite databases. A daemon restart after a crash is sufficient — kernel state is rebuilt from the DB.
14+
- **Dual-Stack IPv6** — Even without IPv6 on the host, an IPv6 subnet is assigned within the container and traffic is carried through the tunnel.
15+
- **Container Isolation**`NET_ADMIN` + `NET_RAW` is sufficient. WireGuard interfaces live within the container namespace. Configurations that weaken host security such as `SYS_ADMIN`, `privileged`, or `host` network mode are not used.
16+
17+
---
18+
19+
## Topology
20+
21+
Three containers, managed via Docker Compose. Management traffic passes through TLS + JWT authentication, WireGuard traffic reaches the daemon directly.
22+
23+
<Mermaid chart={`flowchart
24+
A[Internet] -->|"HTTPS :443"| B[nginx]
25+
B --> C[auth-service]
26+
C <-->|"UDS"| D[daemon]
27+
A -->|"WireGuard :51820/udp"| D
28+
`} />
29+
30+
| Component | Role |
31+
|------------------|-----------------------------------------------------------------------------------------------------|
32+
| **nginx** | TLS termination, React SPA (static compiled files), reverse proxy configuration |
33+
| **auth-service** | Comprehensive authentication system, API proxy to daemon over UDS |
34+
| **daemon** | Userspace WireGuard (Go FFI), nftables firewall (Rust FFI), client and tunnel management, databases |
35+
36+
---
37+
38+
## Key Features
39+
40+
### Bridge Architecture
41+
42+
The daemon performs system-level operations through two native bridges. Python manages the business logic, bridges communicate directly with the kernel.
43+
44+
<Mermaid chart={`graph
45+
D["Daemon (Python)"] -->|"ctypes FFI"| WG["wireguard-go-bridge (Go)"]
46+
D -->|"ctypes FFI"| FW["firewall-bridge (Rust)"]
47+
WG --> TUN["TUN device"]
48+
FW --> NFT["nftables kernel"]
49+
`} />
50+
51+
| Bridge | Language | Responsibility |
52+
|-------------------------|----------|--------------------------------------------------------|
53+
| **wireguard-go-bridge** | Go | Userspace WireGuard, TUN device, IPC state persistence |
54+
| **firewall-bridge** | Rust | nftables rule groups, policy routing, preset system |
55+
56+
### Multihop Exit Routing
57+
58+
You can define your exit tunnel to route traffic through an external WireGuard VPN server. IPv4 and IPv6 tunnels are supported simultaneously.
59+
60+
<Mermaid chart={`flowchart LR
61+
C[Client] -->|"WireGuard"| M["wg_main"] -->|"forward + masquerade"| E["wg_exit"] --> X[Exit Server]
62+
`} />
63+
64+
### IPv6 Dual-Stack
65+
66+
IPv6 support across all layers — firewall rules, policy routing, masquerade, and multihop presets operate with `family: 10` (AF_INET6). IPv6 tunnel traffic can be carried from within the container even without an IPv6 address on the host.
67+
68+
### Crash Recovery
69+
70+
When the service starts, kernel state (nftables rules, routing policies) is rebuilt from SQLite state databases. No data loss after an unexpected shutdown.
771

872
---
973

@@ -17,12 +81,12 @@ curl -sSL get.phantom.tc | bash
1781

1882
<AsciinemaPlayer src="/assets/phantom-wg-install.cast" />
1983

20-
### Setup
84+
### Configuration
2185

2286
```bash
2387
cd phantom-wg
2488

25-
# First-time setup (keys, auth DB, TLS certificate, env files)
89+
# First-time setup
2690
./tools/prod.sh setup
2791

2892
# Endpoint configuration
@@ -40,10 +104,87 @@ sed -i "s/^WIREGUARD_ENDPOINT_V6=.*/WIREGUARD_ENDPOINT_V6=${IPV6}/" .env.daemon
40104
- WireGuard: UDP port `51820`
41105
- Admin password: `cat container-data/secrets/production/.admin_password`
42106

107+
#### Access from VPN
108+
109+
To access the dashboard while connected to the VPN, use the nginx container's Docker network address:
110+
111+
```bash
112+
docker inspect phantom-nginx --format '{{range .NetworkSettings.Networks}}IPv4: {{.IPAddress}} | IPv6: {{.GlobalIPv6Address}}{{end}}'
113+
```
114+
115+
Accessible via `https://<IPv4>` or `https://[<IPv6>]` through the tunnel. You can also remove the `ports: "443:443"` line from `docker-compose.yml` to make the dashboard accessible only through the VPN tunnel.
116+
117+
---
118+
119+
## Management
120+
121+
A convenient tool is available at `./tools/prod.sh` for management.
122+
123+
| Command | Description |
124+
|-------------------------|----------------------------------------------|
125+
| `setup` | Full Setup |
126+
| `up` | Start |
127+
| `down` | Stop |
128+
| `restart [service]` | Restart (All or Specific Service) |
129+
| `build` | Build Images |
130+
| `rebuild` | Build Images from Scratch (no-cache) |
131+
| `update` | Update (git pull + restart) |
132+
| `update --skip-compose` | Update (exclude docker-compose.yml) |
133+
| `logs [service]` | Log Tracking (All or Specific Service) |
134+
| `status` | Docker Compose Status |
135+
| `show-versions` | Component Versions (Daemon, Vendor Packages) |
136+
| `shell [service]` | Shell (default: daemon) |
137+
| `exec <svc> <cmd>` | Execute Command |
138+
| `hard-reset` | Delete All Data |
139+
140+
### Setup
141+
142+
The `setup` command creates all required components during first-time installation:
143+
144+
1. Creates `.env.daemon` and `.env.auth-service` files from `.example` templates.
145+
2. Generates WireGuard server key pair. (Curve25519 — `wg_private_key`, `wg_public_key`)
146+
3. Auth-Service bootstrap cycle:
147+
- Generates Ed25519 signing key pair. (`auth_signing_key`, `auth_verify_key`)
148+
- Creates auth database. (`auth.db` — users, sessions, TOTP, audit log)
149+
- Creates admin account. (32-character random password encrypted with Argon2id hash)
150+
4. Generates self-signed TLS certificate for nginx. (`tls_cert`, `tls_key`)
151+
152+
All of these operations take place within the container — no additional dependencies or tools need to be installed on the host.
153+
154+
<InlineNotification
155+
kind="info"
156+
title="Secret Keys"
157+
subtitle="Secret keys are stored under container-data/secrets/production/. The admin password is written to .admin_password in the same directory — you can safely remove it after logging in."
158+
hideCloseButton
159+
lowContrast
160+
/>
161+
162+
### Updating
163+
164+
```bash
165+
./tools/prod.sh update # git pull + restart
166+
./tools/prod.sh update --skip-compose # Preserve compose file
167+
```
168+
169+
<InlineNotification
170+
kind="info"
171+
title="Compose Protection"
172+
subtitle="If you have made configuration changes to docker-compose.yml and want to receive updates, use --skip-compose."
173+
hideCloseButton
174+
lowContrast
175+
/>
176+
177+
For package dependency changes that require container recompilation (Dockerfile, requirements.txt):
178+
179+
```bash
180+
./tools/prod.sh rebuild
181+
./tools/prod.sh up
182+
```
183+
43184
<InlineNotification
44185
kind="info"
45-
title="Detailed guide"
46-
subtitle="See the SETUP file for all commands, environment variables, and update instructions."
186+
title="Build vs Update"
187+
subtitle="Dockerfiles only provide the system dependencies needed for the stack to run. Code updates are received with the update command — rebuild is only required when these dependencies change."
47188
hideCloseButton
48189
lowContrast
49190
/>

www/src/pages/docs/home/pages/index/index.mdx

Lines changed: 145 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,73 @@
1+
import Mermaid from '@shared/components/visualization/Mermaid';
12
import AsciinemaPlayer from '@shared/components/visualization/AsciinemaPlayer';
23
import { InlineNotification } from '@carbon/react';
34

45
# Phantom-WG
56

6-
***Phantom-WG Modern***, WireGuard® tabanlı bir VPN yönetim platformudur. Tüm bileşenler Docker container yapısı içerisinde çalışır ve asıl işi yapan Phantom Daemon Unix Domain Socket (UDS) üzerinden haberleşir.
7+
***Phantom-WG***, kendi sunucunuzda WireGuard VPN altyapısı kurmanızı ve yönetmenizi sağlayan modüler bir araçtır. Temel VPN yönetiminin ötesinde; sansüre dayanıklı bağlantılar, çok katmanlı şifreleme ve gelişmiş gizlilik senaryoları sunar.
8+
9+
***Phantom-WG Modern***, bu vizyonun container-native implementasyonudur. Tüm bileşenler Docker yapısı içerisinde çalışır ve host sistemden izole edilir:
10+
11+
- **Userspace WireGuard** — Go FFI bridge ile container-scoped TUN device. Kernel modülü gerektirmez, host'un network namespace'ine dokunmaz.
12+
- **nftables netlink FFI** — Rust backend doğrudan kernel ile konuşur. Subprocess çağrısı yoktur, firewall kuralları programatik olarak yönetilir.
13+
- **SQLite State Persistence** — Tüm state SQLite veritabanlarında tutulur. Crash sonrası daemon restart yeterlidir — kernel state DB'den yeniden oluşturulur.
14+
- **Dual-Stack IPv6** — Host'ta IPv6 olmasa bile container içinde IPv6 subnet atanır, tünel içinde trafik taşınabilir.
15+
- **Container İzolasyonu**`NET_ADMIN` + `NET_RAW` yeterlidir. WireGuard arayüzleri container namespace içerisinde yaşar. `SYS_ADMIN`, `privileged` veya `host` network mode gibi host güvenliğini zayıflatan konfigürasyonlar kullanılmaz.
16+
17+
---
18+
19+
## Topoloji
20+
21+
Üç container, Docker Compose ile yönetilir. Yönetim trafiği TLS + JWT kimlik doğrulamadan geçer, WireGuard trafiği doğrudan daemon'a ulaşır.
22+
23+
<Mermaid chart={`flowchart
24+
A[Internet] -->|"HTTPS :443"| B[nginx]
25+
B --> C[auth-service]
26+
C <-->|"UDS"| D[daemon]
27+
A -->|"WireGuard :51820/udp"| D
28+
`} />
29+
30+
| Bileşen | Görev |
31+
|------------------|------------------------------------------------------------------------------------------------------|
32+
| **nginx** | TLS sonlandırma, React SPA (Statik Derlenmiş Dosyalar), Reverse Proxy Yapılandırması |
33+
| **auth-service** | Kapsamlı Kimlik Doğrulama (Authentication) Sistemi, UDS üzerinden daemon'a API proxy |
34+
| **daemon** | Userspace WireGuard (Go FFI), nftables firewall (Rust FFI), İstemci ve Tünel yönetimi, Veritabanları |
35+
36+
---
37+
38+
## Temel Özellikler
39+
40+
### Bridge Mimarisi
41+
42+
Daemon, sistem düzeyindeki işlemleri iki native bridge aracılığıyla gerçekleştirir. Python iş mantığını yönetir, bridge'ler kernel ile doğrudan iletişim kurar.
43+
44+
<Mermaid chart={`graph
45+
D["Daemon (Python)"] -->|"ctypes FFI"| WG["wireguard-go-bridge (Go)"]
46+
D -->|"ctypes FFI"| FW["firewall-bridge (Rust)"]
47+
WG --> TUN["TUN device"]
48+
FW --> NFT["nftables kernel"]
49+
`} />
50+
51+
| Bridge | Dil | Sorumluluk |
52+
|-------------------------|------|---------------------------------------------------------|
53+
| **wireguard-go-bridge** | Go | Userspace WireGuard, TUN device, IPC state persistence |
54+
| **firewall-bridge** | Rust | nftables kural grupları, policy routing, preset sistemi |
55+
56+
### Multihop Exit Routing
57+
58+
Trafiğinizi harici bir WireGuard VPN sunucusu üzerinden aktarmak için exit tünelinizi tanımlayabilirsiniz. IPv4 ve IPv6 tünelleri eş zamanlı olarak desteklenir.
59+
60+
<Mermaid chart={`flowchart LR
61+
C[Client] -->|"WireGuard"| M["wg_main"] -->|"forward + masquerade"| E["wg_exit"] --> X[Exit Server]
62+
`} />
63+
64+
### IPv6 Dual-Stack
65+
66+
IPv6 desteği tüm katmanlarda — firewall kuralları, policy routing, masquerade ve multihop preset'leri `family: 10` (AF_INET6) ile çalışır. Host'ta IPv6 adresi olmadan da container içinden IPv6 tünel trafiği taşınabilir.
67+
68+
### Crash Recovery
69+
70+
Servis başlatıldığında kernel state (nftables kuralları, routing policy'leri) SQLite durum veritabanlarından yeniden oluşturulur. Beklenmeyen kapanma sonrası veri kaybı yaşanmaz.
771

872
---
973

@@ -22,7 +86,7 @@ curl -sSL get.phantom.tc | bash
2286
```bash
2387
cd phantom-wg
2488

25-
# İlk kurulum (anahtarlar, auth DB, TLS sertifikası, env dosyaları)
89+
# İlk kurulum
2690
./tools/prod.sh setup
2791

2892
# Endpoint yapılandırması
@@ -40,10 +104,87 @@ sed -i "s/^WIREGUARD_ENDPOINT_V6=.*/WIREGUARD_ENDPOINT_V6=${IPV6}/" .env.daemon
40104
- WireGuard: UDP port `51820`
41105
- Admin şifresi: `cat container-data/secrets/production/.admin_password`
42106

107+
#### VPN İçinden Erişim
108+
109+
VPN'e bağlıyken kontrol paneline erişmek için nginx container'ın Docker network adresini kullanabilirsiniz:
110+
111+
```bash
112+
docker inspect phantom-nginx --format '{{range .NetworkSettings.Networks}}IPv4: {{.IPAddress}} | IPv6: {{.GlobalIPv6Address}}{{end}}'
113+
```
114+
115+
Tünel içerisinden `https://<IPv4>` veya `https://[<IPv6>]` adresi ile erişilebilir. Dilerseniz `docker-compose.yml` dosyasından `ports: "443:443"` satırını kaldırarak kontrol panelini yalnızca VPN tüneli üzerinden erişilebilir hale getirebilirsiniz.
116+
117+
---
118+
119+
## Yönetim
120+
121+
Yönetim için `./tools/prod.sh` konumunda kullanışlı bir araç bulunur.
122+
123+
| Komut | Açıklama |
124+
|-------------------------|-------------------------------------------------|
125+
| `setup` | Tam Kurulum |
126+
| `up` | Başlat |
127+
| `down` | Durdur |
128+
| `restart [service]` | Yeniden Başlat (Tümü veya Belirli Servis) |
129+
| `build` | İmaj Derle |
130+
| `rebuild` | Sıfırdan İmaj Derle (no-cache) |
131+
| `update` | Güncelle (git pull + restart) |
132+
| `update --skip-compose` | Güncelle (docker-compose.yml hariç tut) |
133+
| `logs [service]` | Log Takibi (Tümü veya Belirli Servis) |
134+
| `status` | Docker Compose Durumu |
135+
| `show-versions` | Bileşen Versiyonları (Daemon, Vendor Paketleri) |
136+
| `shell [service]` | Shell (varsayılan: daemon) |
137+
| `exec <svc> <cmd>` | Komut Çalıştır |
138+
| `hard-reset` | Tüm Veriyi Sil |
139+
140+
### Kurulum
141+
142+
`setup` komutu ilk kurulumda gerekli tüm bileşenleri oluşturur:
143+
144+
1. `.env.daemon` ve `.env.auth-service` dosyalarını `.example` şablonlarından oluşturur.
145+
2. WireGuard sunucu anahtar çifti üretir. (Curve25519 — `wg_private_key`, `wg_public_key`)
146+
3. Auth-Service için bootstrap döngüsü:
147+
- Ed25519 imzalama anahtar çifti üretir. (`auth_signing_key`, `auth_verify_key`)
148+
- Auth veritabanını oluşturur. (`auth.db` — kullanıcılar, oturumlar, TOTP, audit log)
149+
- Admin hesabı oluşturur. (Argon2id hash ile şifrelenen 32 karakterlik rastgele şifre)
150+
4. Nginx için self-signed TLS sertifikası üretir. (`tls_cert`, `tls_key`)
151+
152+
Tüm bu işlemler container içerisinde gerçekleşir — host tarafında ek bir bağımlılık veya araç kurulumu gerekmez.
153+
154+
<InlineNotification
155+
kind="info"
156+
title="Gizli Anahtarlar"
157+
subtitle="Gizli anahtarlar container-data/secrets/production/ altında saklanır. Admin şifresi aynı dizindeki .admin_password dosyasına yazılır — giriş yaptıktan sonra güvenle kaldırabilirsiniz."
158+
hideCloseButton
159+
lowContrast
160+
/>
161+
162+
### Güncelleme
163+
164+
```bash
165+
./tools/prod.sh update # git pull + restart
166+
./tools/prod.sh update --skip-compose # Compose dosyasını koru
167+
```
168+
169+
<InlineNotification
170+
kind="info"
171+
title="Compose Koruması"
172+
subtitle="docker-compose.yml üzerinde bir yapılandırma değişikliği yaptıysanız ve güncellemeleri almak istiyorsanız --skip-compose kullanın."
173+
hideCloseButton
174+
lowContrast
175+
/>
176+
177+
Tekrardan container derlemesi gerektirecek paket bağımlılıkları değişikliklerinde (Dockerfile, requirements.txt):
178+
179+
```bash
180+
./tools/prod.sh rebuild
181+
./tools/prod.sh up
182+
```
183+
43184
<InlineNotification
44185
kind="info"
45-
title="Detaylı rehber"
46-
subtitle="Tüm komutlar, ortam değişkenleri ve güncelleme adımları için SETUP dosyasına bakın."
186+
title="Build ve Update Farkı"
187+
subtitle="Dockerfile'lar yalnızca yapının çalışması için gereken sistem bağımlılıklarını sağlar. Kod güncellemeleri update komutuyla alınır — rebuild yalnızca bu bağımlılıklar değiştiğinde gereklidir."
47188
hideCloseButton
48189
lowContrast
49190
/>

www/src/shared/components/visualization/AsciinemaPlayer.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ interface AsciinemaPlayerProps {
1414
loop?: boolean;
1515
speed?: number;
1616
idleTimeLimit?: number;
17+
terminalFontSize?: string;
1718
fit?: 'width' | 'height' | 'both' | 'none';
1819
className?: string;
1920
}
@@ -36,6 +37,7 @@ const AsciinemaPlayerCore: React.FC<AsciinemaPlayerProps> = ({
3637
loop = true,
3738
speed = 1,
3839
idleTimeLimit = 2,
40+
terminalFontSize,
3941
fit = 'width',
4042
className = '',
4143
}) => {
@@ -71,6 +73,7 @@ const AsciinemaPlayerCore: React.FC<AsciinemaPlayerProps> = ({
7173
idleTimeLimit,
7274
fit,
7375
theme: theme === 'g100' ? 'solarized-dark' : 'solarized-light',
76+
...(terminalFontSize ? { terminalFontSize } : {}),
7477
});
7578

7679
setLoaded(true);
@@ -83,7 +86,7 @@ const AsciinemaPlayerCore: React.FC<AsciinemaPlayerProps> = ({
8386
playerRef.current = null;
8487
}
8588
};
86-
}, [src, theme, cols, rows, autoPlay, loop, speed, idleTimeLimit, fit]);
89+
}, [src, theme, cols, rows, autoPlay, loop, speed, idleTimeLimit, terminalFontSize, fit]);
8790

8891
return (
8992
<div className={`asciinema-player-wrapper ${className}`}>

www/src/shared/components/visualization/styles/AsciinemaPlayer.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
@use '@carbon/react/scss/spacing' as sp;
22

33
.asciinema-player-wrapper {
4+
max-width: 820px;
45
margin-bottom: sp.$spacing-07;
56
border-radius: 8px;
67
overflow: hidden;

0 commit comments

Comments
 (0)