summaryrefslogtreecommitdiff
path: root/playbooks.d/vpn-wireguard/playbook.bash
blob: 734761d6d2ed1d5b1405f10d8e55ac6cb98bff96 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#!/usr/bin/env bash

# shellcheck disable=SC2034

BASHTARD_PLAYBOOK_VARS[$BASHTARD_PLAYBOOK.endpoint]="required"
BASHTARD_PLAYBOOK_VARS[$BASHTARD_PLAYBOOK.ipv4]="required"
BASHTARD_PLAYBOOK_VARS[$BASHTARD_PLAYBOOK.ipv6]="required"

playbook_add() {
	local data
	local interface

	data="$(playbook_path "data")"
	interface="$(config "$BASHTARD_PLAYBOOK.interface" "wg0")"

	pkg install wireguard

	# If there's no data directory yet, make it with a proper gitignore to ensure
	# the private key is not included
	if [[ ! -d "$data" ]]
	then
		mkdir -pv -- "$data" "$data/hooks" "$data/peers"
		cat <<-EOF >> "$data/.gitignore"
			privkey
			EOF
	fi

	# Generate the private key for this machine
	( umask 077 && wg genkey > "$data/privkey" )

	# Generate the peerfile for this machine
	file_template "peer" \
		endpoint="$(config "$BASHTARD_PLAYBOOK.endpoint")" \
		ipv4="$(config "$BASHTARD_PLAYBOOK.ipv4")" \
		ipv6="$(config "$BASHTARD_PLAYBOOK.ipv6")" \
		keepalive="$(config "$BASHTARD_PLAYBOOK.keepalive" "0")" \
		port="$(config "$BASHTARD_PLAYBOOK.port" "51820")" \
		pubkey="$(wg pubkey < "$data/privkey")" \
		> "$data/peers/${BASHTARD_PLATFORM[fqdn]}"

	# Run the sync stage to make sure all the configuration files are written as
	# desired
	playbook_sync

	# Enable the wireguard interface
	info "$BASHTARD_PLAYBOOK" "Enabling wireguard interface $interface"
	systemctl enable --now "wg-quick@$interface.service"
}

playbook_sync() {
	local data
	local wgconf
	local interface
	local hash

	data="$(playbook_path "data")"
	interface="$(config "$BASHTARD_PLAYBOOK.interface" "wg0")"
	wgconf="$(config "fs.etcdir")/wireguard/$interface.conf"
	hash="$(file_hash "$wgconf")"

	# Create the wireguard config directory
	mkdir -pv "$(config "fs.etcdir")/wireguard"

	info "$BASHTARD_PLAYBOOK" "Generating wireguard configuration at $wgconf"

	# Write the Interface section
	file_template "interface" \
		ipv4="$(config "$BASHTARD_PLAYBOOK.ipv4")" \
		ipv6="$(config "$BASHTARD_PLAYBOOK.ipv6")" \
		port="$(config "$BASHTARD_PLAYBOOK.port" "51820")" \
		privkey="$(cat "$data/privkey")" \
		> "$wgconf"

	if [[ -f "$data/hooks/post-up" ]]
	then
		printf "PostUp = %s\n" "$data/hooks/post-up" >> "$wgconf"
	fi

	if [[ -f "$data/hooks/pre-down" ]]
	then
		printf "PreDown = %s\n" "$data/hooks/pre-down" >> "$wgconf"
	fi

	# Include peerfiles for all other machines
	for path in "$data/peers"/*
	do
		local peer="$(basename "$path")"

		# Skip the machine itself, as it needs not peer with itself
		[[ "$peer" == "${BASHTARD_PLATFORM[fqdn]}" ]] && continue

		# Append peerfile, but add a newline in there to make the
		# resulting configuration file a little nicer
		printf "\n" >> "$wgconf"
		cat "$path" >> "$wgconf"
	done

	# Don't continue here if this was just part of the add invocation
	[[ "$BASHTARD_COMMAND" == "add" ]] && return

	# Nothing left to do if the Wireguard configs are the same
	[[ "$hash" == "$(file_hash "$wgconf")" ]] && return

	# Refresh the wireguard interface
	# A simple reload seems to not discover newly added peers
	info "$BASHTARD_PLAYBOOK" "Reloading wireguard interface $interface"
	systemctl restart "wg-quick@$interface.service"
}

playbook_del() {
	local interface

	interface="$(config "$BASHTARD_PLAYBOOK.interface" "wg0")"

	info "$BASHTARD_PLAYBOOK" "Disabling wireguard interface $interface"
	systemctl disable --now "wg-quick@$interface.service"
	rm -fv -- "$(config "fs.etcdir")/wireguard/$interface.conf"
	pkg uninstall wireguard
}