Mercurial > code > home > repos > infra
diff wireguard/wireguard.py @ 326:5b88b38f2471
huge reorg, reog toplevel functions in preparation of a ui with nice task lists
author | drewp@bigasterisk.com |
---|---|
date | Mon, 20 Jan 2025 21:55:08 -0800 |
parents | wireguard.py@65e28d2e0cd8 |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wireguard/wireguard.py Mon Jan 20 21:55:08 2025 -0800 @@ -0,0 +1,85 @@ +import subprocess + +from pyinfra.context import host +from pyinfra.facts.files import FindInFile +from pyinfra.operations import files, systemd + +import wireguard.wireguard_pubkey as wireguard_pubkey + +# other options: +# https://www.reddit.com/r/WireGuard/comments/fkr240/shortest_path_between_peers/ +# https://github.com/k4yt3x/wireguard-mesh-configurator +# https://github.com/mawalu/wireguard-private-networking +# + + +def peer_block(hostname, allowed_ips, endpoint=None, keepalive=None): + # allowed_ips should be determined mostly from host.data.wireguard_address + + public_key = wireguard_pubkey.pubkey[hostname] + out = f'''\ + +[Peer] +# {hostname} +PublicKey = {public_key} +AllowedIPs = {allowed_ips} +''' + if endpoint is not None: + out += f'Endpoint = {endpoint}\n' + if keepalive is not None: + out += f'PersistentKeepalive = {keepalive}\n' + return out + + +def get_priv_key(wireguard_interface) -> str: + priv_key_lines = host.get_fact(FindInFile, path=f'/etc/wireguard/{wireguard_interface}.conf', pattern=r'PrivateKey.*') + if not priv_key_lines: + priv_key = subprocess.check_output(['wg', 'genkey']).strip().decode('ascii') + else: + priv_key = priv_key_lines[0].split(' = ')[1] + return priv_key + + +def compute_pub_key(priv_key: str) -> str: + pub_key = subprocess.check_output(['wg', 'pubkey'], input=priv_key.encode('ascii')).strip().decode('ascii') + # todo: if this was new, it should be added to a file of pubkeys that + # peer_block can refer to. meanwhile, edit the template. + return pub_key + + +def wireguard(): + for wireguard_interface in ['wg0', 'bogasterisk']: + if wireguard_interface == 'bogasterisk' and host.name != 'prime': + continue + + # note- this is specific to the wg0 setup. Other conf files don't use it. + wireguard_ip = host.host_data.get('wireguard_address') + if wireguard_interface == 'wg0' and wireguard_ip is None: + continue + + # new pi may fail with 'Unable to access interface: Protocol not supported'. reboot fixes. + + priv_key = get_priv_key(wireguard_interface) + + # unused since I still hand-maintain wireguard_pubkey.py :( + # pub_key = compute_pub_key(priv_key) + + files.template( + src=f'wireguard/templates/{wireguard_interface}.conf.j2', + dest=f'/etc/wireguard/{wireguard_interface}.conf', + mode='600', + wireguard_ip=wireguard_ip, + priv_key=priv_key, + peer_block=peer_block, + ) + svc = f'wg-quick@{wireguard_interface}.service' + + files.template(src='wireguard/templates/wg.service.j2', + dest=f'/etc/systemd/system/{svc}', + wireguard_interface=wireguard_interface) + systemd.service(service=svc, daemon_reload=True, restarted=True, enabled=True) + + +operations = [ + wireguard, +]