feat: WireGuard endpoint override + fix Docker network label issue
Unit Tests / test (push) Successful in 11m14s
Unit Tests / test (push) Successful in 11m14s
Endpoint override: - Add PUT /api/wireguard/endpoint to set endpoint_override in identity config; GET returns detected, override, and effective endpoints - _effective_endpoint() helper applies override in peer config generation (wireguard.py and peer_dashboard.py); detected IP still shown in UI - Add Endpoint Override input in WireGuard page — solves the common case where auto-detected IP is a gateway/VPS but peers connect via LAN IP Docker cell-network fix: - Declare cell-network external in docker-compose.yml; Docker Compose v5 enforces label ownership and rejects networks created by older versions - Makefile start/update pre-create cell-network idempotently - reinstall/uninstall(full) explicitly delete and recreate the network - Fix uninstall loop path: data/api/services/ (not data/services/) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -20,6 +20,10 @@ function WireGuard() {
|
||||
const [qrCodeDataUrl, setQrCodeDataUrl] = useState('');
|
||||
const [peerStatuses, setPeerStatuses] = useState({});
|
||||
const [tunnelMode, setTunnelMode] = useState('full'); // 'split' or 'full'
|
||||
const [endpointOverride, setEndpointOverride] = useState('');
|
||||
const [endpointOverrideDraft, setEndpointOverrideDraft] = useState('');
|
||||
const [isSavingEndpoint, setIsSavingEndpoint] = useState(false);
|
||||
const [endpointSaved, setEndpointSaved] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
fetchWireGuardData();
|
||||
@@ -51,6 +55,22 @@ function WireGuard() {
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
const saveEndpointOverride = async () => {
|
||||
setIsSavingEndpoint(true);
|
||||
try {
|
||||
await wireguardAPI.setEndpointOverride(endpointOverrideDraft);
|
||||
setEndpointOverride(endpointOverrideDraft);
|
||||
setEndpointSaved(true);
|
||||
setTimeout(() => setEndpointSaved(false), 3000);
|
||||
const sc = await fetch('/api/wireguard/server-config', { credentials: 'include' }).then(r => r.json());
|
||||
setServerConfig(prev => ({ ...prev, ...sc }));
|
||||
} catch (e) {
|
||||
console.error('Failed to save endpoint override:', e);
|
||||
} finally {
|
||||
setIsSavingEndpoint(false);
|
||||
}
|
||||
};
|
||||
|
||||
const refreshExternalIp = async () => {
|
||||
setIsRefreshingIp(true);
|
||||
try {
|
||||
@@ -81,6 +101,9 @@ function WireGuard() {
|
||||
setStatus(statusResponse.data);
|
||||
if (serverConfigResponse) {
|
||||
setServerConfig({ ...serverConfigResponse, port_open: 'checking' });
|
||||
const override = serverConfigResponse.endpoint_override || '';
|
||||
setEndpointOverride(override);
|
||||
setEndpointOverrideDraft(override);
|
||||
// Check port asynchronously so page loads fast
|
||||
fetch('/api/wireguard/check-port', { credentials: 'include' })
|
||||
.then(r => r.json())
|
||||
@@ -446,10 +469,38 @@ PersistentKeepalive = ${peer.persistent_keepalive || 25}`;
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{serverConfig && !serverConfig.external_ip && (
|
||||
<div className="mt-4 border-t pt-4">
|
||||
<p className="text-sm font-medium text-gray-700 mb-1">Endpoint Override</p>
|
||||
<p className="text-xs text-gray-500 mb-2">
|
||||
Force a specific endpoint (IP or hostname) for peer configs. Leave blank to use auto-detected IP above.
|
||||
Useful when peers connect via LAN or a different IP than what's detected.
|
||||
</p>
|
||||
<div className="flex gap-2">
|
||||
<input
|
||||
type="text"
|
||||
value={endpointOverrideDraft}
|
||||
onChange={e => setEndpointOverrideDraft(e.target.value)}
|
||||
placeholder="e.g. 192.168.1.100 or myvpn.example.com"
|
||||
className="flex-1 input text-sm font-mono"
|
||||
/>
|
||||
<button
|
||||
onClick={saveEndpointOverride}
|
||||
disabled={isSavingEndpoint || endpointOverrideDraft === endpointOverride}
|
||||
className="btn btn-primary text-sm"
|
||||
>
|
||||
{endpointSaved ? 'Saved' : isSavingEndpoint ? 'Saving…' : 'Save'}
|
||||
</button>
|
||||
</div>
|
||||
{serverConfig?.effective_endpoint && (
|
||||
<p className="text-xs text-gray-500 mt-1">
|
||||
Effective endpoint used in peer configs: <span className="font-mono font-medium">{serverConfig.effective_endpoint}</span>
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
{serverConfig && !serverConfig.external_ip && !endpointOverride && (
|
||||
<div className="mt-3 flex items-center text-yellow-700 bg-yellow-50 rounded p-2 text-sm">
|
||||
<AlertCircle className="h-4 w-4 mr-2 flex-shrink-0" />
|
||||
External IP could not be detected. Check internet connectivity, then click Refresh IP.
|
||||
External IP could not be detected. Set an endpoint override above or check internet connectivity.
|
||||
</div>
|
||||
)}
|
||||
{serverConfig && serverConfig.port_open === false && (
|
||||
|
||||
@@ -137,6 +137,8 @@ export const wireguardAPI = {
|
||||
updatePeerIP: (data) => api.put('/api/wireguard/peers/ip', data),
|
||||
getPeerConfig: (data) => api.post('/api/wireguard/peers/config', data),
|
||||
getPeerStatuses: () => api.get('/api/wireguard/peers/statuses'),
|
||||
getEndpoint: () => api.get('/api/wireguard/endpoint'),
|
||||
setEndpointOverride: (endpoint_override) => api.put('/api/wireguard/endpoint', { endpoint_override }),
|
||||
};
|
||||
|
||||
// Peer Registry API
|
||||
|
||||
Reference in New Issue
Block a user