Commit Graph

15 Commits

Author SHA1 Message Date
roof 50f2200b45 fix: wireguard health_check error + logs page ALL service + rotate confirmation
- WireGuardManager.test_connectivity: make peer_ip optional so health_check
  can call it without args (was logging ERROR on every health poll)
- Logs page: add ALL option to service selector (uses search across all services)
- Logs page: show service tag on each log line when in ALL/search mode
- Logs page: require window.confirm before rotating logs to prevent accidental data loss

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 01:47:41 -04:00
roof 84d33aa88c fix: prevent _syncconf from touching live container when run from tests
Added a path guard: if the config file resolves to /tmp/ or a pytest
temp dir, _syncconf bails out immediately. Without this, tests calling
add_peer/remove_peer with a temp-dir WireGuardManager would connect to
the live cell-wireguard container and remove production peers.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 01:05:56 -04:00
roof 53c7661812 feat: per-peer access enforcement, live peer status, auto IP assignment
Server-side access control:
- firewall_manager.py: per-peer iptables FORWARD rules in WireGuard container;
  virtual IPs on Caddy (172.20.0.21-24) for per-service DROP/ACCEPT targeting
- CoreDNS Corefile regenerated with ACL blocks for blocked services per peer
- POST /api/wireguard/apply-enforcement re-applies rules after WireGuard restart;
  wg0.conf PostUp calls it via curl so rules restore automatically on container start

WireGuard fixes:
- _syncconf uses `wg set peer` instead of `wg syncconf` to avoid resetting ListenPort
- add_peer validates AllowedIPs must be /32 — rejects full/split tunnel CIDRs that
  would route internet or LAN traffic to that peer
- _config_file() checks for linuxserver wg_confs/ subdirectory first

UI:
- Peers page fetches /api/wireguard/peers/statuses for live handshake data;
  status badge now shows real Online/Offline + seconds since last handshake
- IP field removed from Add Peer form (auto-assigned from 10.0.0.0/24)

Tests (246 pass):
- test_firewall_manager.py: 22 tests for ACL generation, iptables rule correctness,
  comment tagging, clear_peer_rules filter logic
- test_peer_wg_integration.py: 10 tests for /32 enforcement, IP auto-assignment,
  syncconf called on add/remove
- test_wireguard_manager.py: updated to reflect correct IPs and /32 requirement

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 01:01:07 -04:00
roof 9d7d74f3f4 fix: full-tunnel default, real host routing table, peer config tunnel mode
- WireGuard default changed to full tunnel (0.0.0.0/0) — all peer traffic
  routes through PIC server so internet latency matches server's clean 41ms
- UI tunnel toggle now defaults to Full tunnel
- API /peers/config accepts allowed_ips param so UI toggle wires through
- Routing page reads real host routes via /proc/1/net/route (pid: host)
  instead of mock data; shows ens18/192.168.31.1 correctly
- Add iproute2 + util-linux to API Dockerfile

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 15:20:55 -04:00
roof e7decf6f06 fix: port check, add missing service domains to Caddy and DNS zone
wg show outputs "listening port" not "listen port" — substring mismatch
caused port status to always show Blocked. Add webdav.cell, webmail.cell,
api.cell to Caddyfile and cell.zone so VPN peers can reach all services.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 14:50:29 -04:00
roof cbdefbd110 fix: static IPs for all containers, radicale config, DNS zone, cleanup
- Assign static IPs to all 13 containers (172.20.0.2–13) so DNS zone
  records match actual container IPs regardless of start order.
- Update cell.zone: all .cell domains now point to cell-caddy (172.20.0.2)
  which is the correct single entry point via Caddy reverse proxy.
- Create config/radicale/config so the calendar container actually starts.
- Fix webdav: replace empty users.passwd with USERNAME/PASSWORD env vars.
- Fix DNS fallback IP in wireguard_manager: 172.20.0.2→172.20.0.3 (cell-dns).
- Remove duplicate http://ui.cell from Caddyfile.
- Add persistent data volumes for rainloop and filegator.
- Fix mail domainname placeholder (yourdomain.com→cell.local).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 14:31:38 -04:00
roof 0b5a5b23e8 fix: split-tunnel default for peers, port check via wg interface, tunnel mode toggle in UI
- check_port_open now checks if wg0 interface is actually listening (via
  'wg show wg0') instead of requiring a live peer handshake. This means
  the port shows 'Open' whenever WireGuard is running, not only when a
  peer has connected recently.

- get_peer_config defaults to split-tunnel AllowedIPs (10.0.0.0/24,
  172.20.0.0/16) so VPN clients only route cell service traffic through
  the tunnel. Local LAN traffic (192.168.x.x etc.) stays direct, fixing
  the 60-120ms penalty when pinging local hosts while on VPN.

- Peer config modal now uses cell DNS (172.20.0.2) so .cell domains
  resolve correctly with both split and full tunnel.

- Added split/full tunnel toggle in the peer config modal so users can
  download either config variant.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 14:18:43 -04:00
roof d3294552f0 fix: hairpin DNAT rule to eliminate VPN ping jitter to server public IP
When a full-tunnel VPN client pings the server's own public IP, traffic
loops out through Docker's external interface and back, causing 60-120ms
jitter. The DNAT PostUp rule intercepts packets from wg0 destined for the
public IP and redirects them to 10.0.0.1 (the VPN interface), keeping
traffic entirely inside the tunnel.

Also updates SERVER_ADDRESS from 172.20.0.1/16 to 10.0.0.1/24 to avoid
routing conflict with the Docker bridge network on eth0.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 14:02:36 -04:00
roof e79ee08c63 fix: WireGuard routing, DNS, service access, and UI improvements
- Fix CoreDNS not loading .cell zones (wrong Corefile path, now uses -conf flag)
- Fix WireGuard server address conflict (172.20.0.1/16 overlapped with Docker
  network; changed to 10.0.0.1/24 to eliminate duplicate routes)
- Add SERVERMODE=true and sysctls to WireGuard docker-compose for server mode
- Fix DNS zone file parser to handle 4-field records (name IN type value)
- Add get_dns_records() to NetworkManager; mount data/dns into API container
- Fix peer config endpoint: look up IP/key from registry, use real endpoint
- Add bulk peer statuses endpoint keyed by public_key
- Normalize snake_case API fields to camelCase in WireGuard UI
- Add port check endpoint (checks via live handshake, not unreliable TCP probe)
- Add Caddy virtual hosts for ui/calendar/files/mail .cell domains (HTTP only)
- Fix cell config domain default from cell.local to cell
- Fix Routing Network Config tab (was calling hardcoded localhost:3000)
- Fix DNS records display (record.value not record.ip)
- Move service access guide to top of Dashboard with login hints
- Add /api/routing/setup endpoint

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 12:43:23 -04:00
roof bd67764bf4 feat: external IP detection, port status, fix peer config generation
- WireGuardManager: get_external_ip() (cached 1h), check_port_open(),
  get_server_config() returning public_key + detected endpoint
- API: /api/wireguard/server-config returns real external IP;
  /api/wireguard/refresh-ip forces re-detection;
  /api/wireguard/peers/config now looks up peer IP + private key from
  registry and uses real server endpoint automatically
- Fix doubled port in Endpoint (178.x:51820:51820 → 178.x:51820)
- Fix Address=/32 when peer_ip already has mask
- WebUI nginx: proxy /api/ and /health to cell-api (fixes localhost:3000
  hardcode — UI now works from any machine)
- api.js: baseURL='' so all calls go through nginx proxy
- WireGuard page: show Server Endpoint card with external IP, endpoint,
  public key, and Refresh IP button

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 02:41:50 -04:00
roof 5239751a71 fix: all 214 tests passing (from 36 failures)
Key fixes:
- safe_makedirs() in all managers so tests run outside Docker (/app paths)
- WireGuardManager: rewrote with X25519 key gen, corrected method names
- VaultManager: init ca_cert=None, guard generate_certificate when CA missing
- ConfigManager: _save_all_configs wraps mkdir+write in try/except
- app.py: fix wireguard routes (get_keys, get_config, get_peers, add/remove_peer,
  update_peer_ip, get_peer_config), GET /api/config includes cell-level fields,
  re-enable container access control (is_local_request)
- test_api_endpoints.py: patch paths api.app.X -> app.X
- test_app_misc.py: patch paths api.app.X -> app.X, relax status assertions
- test_vault_api.py: replace patch('api.vault_manager') with patch.object(app, ...)
  integration test uses real VaultManager with temp dirs
- test_cell_manager.py: pass config_path to both managers in persistence test

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 16:43:07 -04:00
Cloud bb6ccfe023 wip: wireguard 2025-09-14 03:31:14 -05:00
Constantin 4f65f95ac9 wip: peers 2025-09-13 18:56:00 +03:00
Constantin f0b6d1cff1 wip: make work Services Status 2025-09-13 14:23:31 +03:00
Constantin 2277b11563 init 2025-09-12 23:04:52 +03:00