Refactor wireguard to use a different config dir instead of /etc/wireguard

This commit is contained in:
2026-09-13 13:37:48 +01:00
parent 06cf72b2c9
commit 42224c94d3
10 changed files with 192 additions and 34 deletions
@@ -5,6 +5,7 @@ import type {
} from "@/db/types/db";
import { AppData } from "@/src/data/app-data";
import grabDirNames from "@/src/utils/grab-dir-names";
import deriveWireguardInterfaceName from "@/src/utils/derive-wireguard-interface-name";
import { execSync } from "node:child_process";
import path from "node:path";
import grabHostNetworkInterface from "./grab-host-network-interface";
@@ -15,7 +16,8 @@ import checkPrivateIPAvailability from "./check-private-ip-availability";
const {
WGUI_LIB_IP_TABLES_DIR,
WIREGUARD_HOST_CONFIG_DIR,
WGUI_LIB_HOSTS_CONFIGS_DIR,
WGUI_WG_QUICK_SYSTEMD_SCRIPT,
WIREGUARD_PRIVATE_KEY_FILE_NAME,
WIREGUARD_PUBLIC_KEY_FILE_NAME,
} = grabDirNames();
@@ -31,6 +33,12 @@ export default async function setupWireguardHost({
}: Params): Promise<APIResponseObject> {
const host_id = host?.id || AppData["WireguardHostID"];
const INTERFACE_NAME = deriveWireguardInterfaceName({ host_id });
const HOST_CONFIG_PATH = path.join(
WGUI_LIB_HOSTS_CONFIGS_DIR,
`${INTERFACE_NAME}.conf`,
);
const variables_res = await BunSQLite.select<
BUN_SQLITE_WGUI_VARIABLES,
TableType
@@ -83,7 +91,8 @@ export default async function setupWireguardHost({
let pre_sh = ``;
pre_sh += `set -e\n`;
pre_sh += `cd ${WIREGUARD_HOST_CONFIG_DIR}\n`;
pre_sh += `mkdir -p ${WGUI_LIB_HOSTS_CONFIGS_DIR}\n`;
pre_sh += `cd ${WGUI_LIB_HOSTS_CONFIGS_DIR}\n`;
pre_sh += `if [ ! -f ${WIREGUARD_PRIVATE_KEY_FILE_NAME} ]; then\n`;
pre_sh += ` wg genkey | tee ${WIREGUARD_PRIVATE_KEY_FILE_NAME} | wg pubkey > ${WIREGUARD_PUBLIC_KEY_FILE_NAME}\n`;
pre_sh += `fi\n`;
@@ -103,12 +112,12 @@ export default async function setupWireguardHost({
const HOST_PUBLIC_KEY = host?.id
? host.public_key
: execSync(
`cat ${path.join(WIREGUARD_HOST_CONFIG_DIR, WIREGUARD_PUBLIC_KEY_FILE_NAME)}`,
`cat ${path.join(WGUI_LIB_HOSTS_CONFIGS_DIR, WIREGUARD_PUBLIC_KEY_FILE_NAME)}`,
);
const HOST_PRIVATE_KEY = host?.private_key
? host.private_key
: execSync(
`cat ${path.join(WIREGUARD_HOST_CONFIG_DIR, WIREGUARD_PRIVATE_KEY_FILE_NAME)}`,
`cat ${path.join(WGUI_LIB_HOSTS_CONFIGS_DIR, WIREGUARD_PRIVATE_KEY_FILE_NAME)}`,
);
let sh = ``;
@@ -124,17 +133,17 @@ export default async function setupWireguardHost({
`${host_id}-down.sh`,
);
sh += `cd ${WIREGUARD_HOST_CONFIG_DIR}\n`;
sh += `cd ${WGUI_LIB_HOSTS_CONFIGS_DIR}\n`;
sh += `cat > ${POST_UP_PATH} << EOF\n`;
sh += `#!/bin/bash\n\n`;
sh += `# Allow WireGuard traffic to/from the server itself\n`;
sh += `iptables -I INPUT 1 -i wg${host_id} -j ACCEPT\n`;
sh += `iptables -I OUTPUT 1 -o wg${host_id} -j ACCEPT\n`;
sh += `iptables -I INPUT 1 -i ${INTERFACE_NAME} -j ACCEPT\n`;
sh += `iptables -I OUTPUT 1 -o ${INTERFACE_NAME} -j ACCEPT\n`;
sh += `\n`;
sh += `# Allow WireGuard traffic to be forwarded (insert above Docker rules)\n`;
sh += `iptables -I FORWARD 1 -i wg${host_id} -j ACCEPT\n`;
sh += `iptables -I FORWARD 1 -o wg${host_id} -j ACCEPT\n`;
sh += `iptables -I FORWARD 1 -i ${INTERFACE_NAME} -j ACCEPT\n`;
sh += `iptables -I FORWARD 1 -o ${INTERFACE_NAME} -j ACCEPT\n`;
sh += `\n`;
sh += `iptables -t nat -A POSTROUTING -o ${TARGET_INTERFACE} -j MASQUERADE\n`;
sh += `EOF\n`;
@@ -144,19 +153,19 @@ export default async function setupWireguardHost({
sh += `cat > ${POST_DOWN_PATH} << EOF\n`;
sh += `#!/bin/bash\n\n`;
sh += `# Remove WireGuard INPUT/OUTPUT rules\n`;
sh += `iptables -D INPUT -i wg${host_id} -j ACCEPT\n`;
sh += `iptables -D OUTPUT -o wg${host_id} -j ACCEPT\n`;
sh += `iptables -D INPUT -i ${INTERFACE_NAME} -j ACCEPT\n`;
sh += `iptables -D OUTPUT -o ${INTERFACE_NAME} -j ACCEPT\n`;
sh += `\n`;
sh += `# Remove FORWARD rules\n`;
sh += `iptables -D FORWARD -i wg${host_id} -j ACCEPT\n`;
sh += `iptables -D FORWARD -o wg${host_id} -j ACCEPT\n`;
sh += `iptables -D FORWARD -i ${INTERFACE_NAME} -j ACCEPT\n`;
sh += `iptables -D FORWARD -o ${INTERFACE_NAME} -j ACCEPT\n`;
sh += `\n`;
sh += `iptables -t nat -D POSTROUTING -o ${TARGET_INTERFACE} -j MASQUERADE\n`;
sh += `EOF\n`;
sh += `\n`;
sh += `cat > wg${host_id}.conf << EOF\n`;
sh += `cat > ${INTERFACE_NAME}.conf << EOF\n`;
sh += `[Interface]\n`;
sh += `Address = ${HOST_WG_IP}/24\n`;
sh += `ListenPort = 51820\n`;
@@ -183,10 +192,28 @@ export default async function setupWireguardHost({
const exec = execSync(sh, { encoding: "utf-8" });
return {
success: true,
msg: exec,
};
const IS_ROOT =
typeof process.getuid === "function" && process.getuid() === 0;
const SUDO_PREFIX = IS_ROOT ? "" : "sudo -n ";
const MANAGE_WG_QUICK_CMD = `${SUDO_PREFIX}${WGUI_WG_QUICK_SYSTEMD_SCRIPT} ${INTERFACE_NAME} ${HOST_CONFIG_PATH}`;
let exec_systemd = ``;
try {
exec_systemd = execSync(MANAGE_WG_QUICK_CMD, {
encoding: "utf-8",
});
return {
success: true,
msg: [exec.trim(), exec_systemd.trim()].join("\n\n"),
};
} catch (error: any) {
return {
success: false,
msg: `Host config written to ${HOST_CONFIG_PATH}, but could not manage the tunnel via systemd (wg-quick@${INTERFACE_NAME}.service): ${error.message}`,
};
}
} catch (error: any) {
return {
success: false,