whereNotNull('wg_ip')->pluck('wg_ip')->all(); $prefix = Str::beforeLast(config('provisioning.wireguard.subnet', '10.66.0.0/24'), '.'); for ($octet = 2; $octet <= 254; $octet++) { $ip = "{$prefix}.{$octet}"; if (! in_array($ip, $used, true)) { return $ip; } } throw new RuntimeException('WireGuard management subnet exhausted.'); } public function addPeer(string $publicKey, string $ip): void { Process::run(['wg', 'set', 'wg0', 'peer', $publicKey, 'allowed-ips', $ip.'/32'])->throw(); Process::run('wg-quick save wg0')->throw(); // persist, else the peer is lost on restart } public function removePeer(string $publicKey): void { Process::run(['wg', 'set', 'wg0', 'peer', $publicKey, 'remove'])->throw(); Process::run('wg-quick save wg0')->throw(); // persist, else the peer is lost on restart } public function endpoint(): string { return (string) config('provisioning.wireguard.endpoint'); } public function publicKey(): string { return (string) config('provisioning.wireguard.hub_public_key'); } }