From 67185192fde84a979d2022508f4bd1eab03479e9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 14 Nov 2025 13:25:22 +0000 Subject: [PATCH] Refactor environment variables with shorter names and add comprehensive override support - Rename OVERRIDE_INTERFACE_* to WG_* (shorter, non-conflicting) - Add interface overrides: WG_PORT, WG_DEVICE, WG_MTU, WG_IPV4_CIDR, WG_IPV6_CIDR, WG_ENABLED - Add client config overrides: WG_HOST, WG_CLIENT_PORT, WG_DEFAULT_DNS, WG_DEFAULT_ALLOWED_IPS, WG_DEFAULT_MTU, WG_DEFAULT_PERSISTENT_KEEPALIVE - Add general config overrides: WG_SESSION_TIMEOUT, WG_METRICS_PROMETHEUS, WG_METRICS_JSON - Update all API endpoints to apply and filter overrides - Update documentation with all new environment variables - Exclude AmneziaWG parameters (j*, s*, i*, h*) as requested Co-authored-by: kaaax0815 <32197462+kaaax0815@users.noreply.github.com> --- .../advanced/config/optional-config.md | 42 +++++++- src/server/api/admin/general.get.ts | 3 +- src/server/api/admin/general.post.ts | 15 ++- src/server/api/admin/interface/cidr.post.ts | 11 ++- src/server/api/admin/interface/index.post.ts | 15 ++- src/server/api/admin/userconfig.get.ts | 3 +- src/server/api/admin/userconfig.post.ts | 24 ++++- src/server/utils/WireGuard.ts | 3 +- src/server/utils/config.ts | 96 +++++++++++++++++-- 9 files changed, 189 insertions(+), 23 deletions(-) diff --git a/docs/content/advanced/config/optional-config.md b/docs/content/advanced/config/optional-config.md index 791acbe3..acaa89f5 100644 --- a/docs/content/advanced/config/optional-config.md +++ b/docs/content/advanced/config/optional-config.md @@ -25,11 +25,35 @@ This option can be removed in the future, as more devices support IPv6. These environment variables allow you to override settings that would normally be configured through the Admin Panel. When set, these values take precedence over database settings and cannot be changed through the Web UI. -| Env | Example | Description | -| --------------------------- | ------- | ---------------------------------------------------- | -| `OVERRIDE_INTERFACE_PORT` | `51820` | Override the WireGuard interface listening port | -| `OVERRIDE_INTERFACE_DEVICE` | `eth1` | Override the network device/interface | -| `OVERRIDE_INTERFACE_MTU` | `1420` | Override the MTU (Maximum Transmission Unit) setting | +### Interface Settings + +| Env | Example | Description | +| -------------- | ----------------- | ---------------------------------- | +| `WG_PORT` | `51820` | WireGuard interface listening port | +| `WG_DEVICE` | `eth0` | Network device/interface | +| `WG_MTU` | `1420` | Maximum Transmission Unit | +| `WG_IPV4_CIDR` | `10.8.0.0/24` | IPv4 CIDR range | +| `WG_IPV6_CIDR` | `fdcc::/112` | IPv6 CIDR range | +| `WG_ENABLED` | `true` or `false` | Whether the interface is enabled | + +### Client Connection Settings + +| Env | Example | Description | +| --------------------------------- | ----------------- | ---------------------------------------- | +| `WG_HOST` | `vpn.example.com` | Host clients will connect to | +| `WG_CLIENT_PORT` | `51820` | Port clients will connect to | +| `WG_DEFAULT_DNS` | `1.1.1.1,8.8.8.8` | Default DNS servers for clients | +| `WG_DEFAULT_ALLOWED_IPS` | `0.0.0.0/0,::/0` | Default allowed IPs for clients | +| `WG_DEFAULT_MTU` | `1420` | Default MTU for clients | +| `WG_DEFAULT_PERSISTENT_KEEPALIVE` | `25` | Default persistent keepalive for clients | + +### General Settings + +| Env | Example | Description | +| ----------------------- | ----------------- | -------------------------- | +| `WG_SESSION_TIMEOUT` | `3600` | Session timeout in seconds | +| `WG_METRICS_PROMETHEUS` | `true` or `false` | Enable Prometheus metrics | +| `WG_METRICS_JSON` | `true` or `false` | Enable JSON metrics | /// warning | Override Behavior @@ -43,3 +67,11 @@ When these override environment variables are set: These overrides are useful for containerized environments where configuration should be controlled externally. /// + +/// note | Note on Port Variables + +- `WG_PORT` - The port WireGuard listens on (interface port) +- `WG_CLIENT_PORT` - The port clients connect to (endpoint port, usually same as `WG_PORT`) +- `PORT` - The port the Web UI listens on (HTTP server port) + +/// diff --git a/src/server/api/admin/general.get.ts b/src/server/api/admin/general.get.ts index 075eefce..c99f77f7 100644 --- a/src/server/api/admin/general.get.ts +++ b/src/server/api/admin/general.get.ts @@ -1,4 +1,5 @@ export default definePermissionEventHandler('admin', 'any', async () => { const generalConfig = await Database.general.getConfig(); - return generalConfig; + const generalConfigWithOverrides = applyGeneralOverrides(generalConfig); + return generalConfigWithOverrides; }); diff --git a/src/server/api/admin/general.post.ts b/src/server/api/admin/general.post.ts index 414af6d7..f43f47fc 100644 --- a/src/server/api/admin/general.post.ts +++ b/src/server/api/admin/general.post.ts @@ -8,7 +8,20 @@ export default definePermissionEventHandler( event, validateZod(GeneralUpdateSchema, event) ); - await Database.general.update(data); + + // Remove overridden fields from the update data + const updateData = { ...data }; + if (WG_GENERAL_OVERRIDE_ENV.SESSION_TIMEOUT !== undefined) { + delete updateData.sessionTimeout; + } + if (WG_GENERAL_OVERRIDE_ENV.METRICS_PROMETHEUS !== undefined) { + delete updateData.metricsPrometheus; + } + if (WG_GENERAL_OVERRIDE_ENV.METRICS_JSON !== undefined) { + delete updateData.metricsJson; + } + + await Database.general.update(updateData); return { success: true }; } ); diff --git a/src/server/api/admin/interface/cidr.post.ts b/src/server/api/admin/interface/cidr.post.ts index 95e239cf..2c4f4096 100644 --- a/src/server/api/admin/interface/cidr.post.ts +++ b/src/server/api/admin/interface/cidr.post.ts @@ -9,7 +9,16 @@ export default definePermissionEventHandler( validateZod(InterfaceCidrUpdateSchema, event) ); - await Database.interfaces.updateCidr(data); + // Remove overridden fields from the update data + const updateData = { ...data }; + if (WG_OVERRIDE_ENV.IPV4_CIDR !== undefined) { + delete updateData.ipv4Cidr; + } + if (WG_OVERRIDE_ENV.IPV6_CIDR !== undefined) { + delete updateData.ipv6Cidr; + } + + await Database.interfaces.updateCidr(updateData); await WireGuard.saveConfig(); return { success: true }; } diff --git a/src/server/api/admin/interface/index.post.ts b/src/server/api/admin/interface/index.post.ts index ba5bda29..7a19eed5 100644 --- a/src/server/api/admin/interface/index.post.ts +++ b/src/server/api/admin/interface/index.post.ts @@ -11,15 +11,24 @@ export default definePermissionEventHandler( // Remove overridden fields from the update data const updateData = { ...data }; - if (WG_OVERRIDE_ENV.INTERFACE_PORT !== undefined) { + if (WG_OVERRIDE_ENV.PORT !== undefined) { delete updateData.port; } - if (WG_OVERRIDE_ENV.INTERFACE_DEVICE !== undefined) { + if (WG_OVERRIDE_ENV.DEVICE !== undefined) { delete updateData.device; } - if (WG_OVERRIDE_ENV.INTERFACE_MTU !== undefined) { + if (WG_OVERRIDE_ENV.MTU !== undefined) { delete updateData.mtu; } + if (WG_OVERRIDE_ENV.IPV4_CIDR !== undefined) { + delete updateData.ipv4Cidr; + } + if (WG_OVERRIDE_ENV.IPV6_CIDR !== undefined) { + delete updateData.ipv6Cidr; + } + if (WG_OVERRIDE_ENV.ENABLED !== undefined) { + delete updateData.enabled; + } await Database.interfaces.update(updateData); await WireGuard.saveConfig(); diff --git a/src/server/api/admin/userconfig.get.ts b/src/server/api/admin/userconfig.get.ts index b41a81bd..acac9086 100644 --- a/src/server/api/admin/userconfig.get.ts +++ b/src/server/api/admin/userconfig.get.ts @@ -1,4 +1,5 @@ export default definePermissionEventHandler('admin', 'any', async () => { const userConfig = await Database.userConfigs.get(); - return userConfig; + const userConfigWithOverrides = applyUserConfigOverrides(userConfig); + return userConfigWithOverrides; }); diff --git a/src/server/api/admin/userconfig.post.ts b/src/server/api/admin/userconfig.post.ts index ff150b0c..68d63de4 100644 --- a/src/server/api/admin/userconfig.post.ts +++ b/src/server/api/admin/userconfig.post.ts @@ -8,7 +8,29 @@ export default definePermissionEventHandler( event, validateZod(UserConfigUpdateSchema, event) ); - await Database.userConfigs.update(data); + + // Remove overridden fields from the update data + const updateData = { ...data }; + if (WG_CLIENT_OVERRIDE_ENV.HOST !== undefined) { + delete updateData.host; + } + if (WG_CLIENT_OVERRIDE_ENV.CLIENT_PORT !== undefined) { + delete updateData.port; + } + if (WG_CLIENT_OVERRIDE_ENV.DEFAULT_DNS !== undefined) { + delete updateData.defaultDns; + } + if (WG_CLIENT_OVERRIDE_ENV.DEFAULT_ALLOWED_IPS !== undefined) { + delete updateData.defaultAllowedIps; + } + if (WG_CLIENT_OVERRIDE_ENV.DEFAULT_MTU !== undefined) { + delete updateData.defaultMtu; + } + if (WG_CLIENT_OVERRIDE_ENV.DEFAULT_PERSISTENT_KEEPALIVE !== undefined) { + delete updateData.defaultPersistentKeepalive; + } + + await Database.userConfigs.update(updateData); await WireGuard.saveConfig(); return { success: true }; } diff --git a/src/server/utils/WireGuard.ts b/src/server/utils/WireGuard.ts index 61101249..27dbad50 100644 --- a/src/server/utils/WireGuard.ts +++ b/src/server/utils/WireGuard.ts @@ -154,6 +154,7 @@ class WireGuard { const wgInterface = await Database.interfaces.get(); const wgInterfaceWithOverrides = applyInterfaceOverrides(wgInterface); const userConfig = await Database.userConfigs.get(); + const userConfigWithOverrides = applyUserConfigOverrides(userConfig); const client = await Database.clients.get(clientId); @@ -163,7 +164,7 @@ class WireGuard { return wg.generateClientConfig( wgInterfaceWithOverrides, - userConfig, + userConfigWithOverrides, client, { enableIpv6: !WG_ENV.DISABLE_IPV6, diff --git a/src/server/utils/config.ts b/src/server/utils/config.ts index e6d63079..d72cf997 100644 --- a/src/server/utils/config.ts +++ b/src/server/utils/config.ts @@ -56,15 +56,59 @@ export const WG_INITIAL_ENV = { export const WG_OVERRIDE_ENV = { /** Override the WireGuard interface port */ - INTERFACE_PORT: process.env.OVERRIDE_INTERFACE_PORT - ? Number.parseInt(process.env.OVERRIDE_INTERFACE_PORT, 10) + PORT: process.env.WG_PORT + ? Number.parseInt(process.env.WG_PORT, 10) : undefined, /** Override the network device/interface */ - INTERFACE_DEVICE: process.env.OVERRIDE_INTERFACE_DEVICE, + DEVICE: process.env.WG_DEVICE, /** Override the MTU setting */ - INTERFACE_MTU: process.env.OVERRIDE_INTERFACE_MTU - ? Number.parseInt(process.env.OVERRIDE_INTERFACE_MTU, 10) + MTU: process.env.WG_MTU + ? Number.parseInt(process.env.WG_MTU, 10) : undefined, + /** Override the IPv4 CIDR */ + IPV4_CIDR: process.env.WG_IPV4_CIDR, + /** Override the IPv6 CIDR */ + IPV6_CIDR: process.env.WG_IPV6_CIDR, + /** Override the enabled status */ + ENABLED: process.env.WG_ENABLED === 'true' ? true : + process.env.WG_ENABLED === 'false' ? false : + undefined, +}; + +export const WG_CLIENT_OVERRIDE_ENV = { + /** Override the client connection host */ + HOST: process.env.WG_HOST, + /** Override the client connection port (different from WG_PORT which is the interface port) */ + CLIENT_PORT: process.env.WG_CLIENT_PORT + ? Number.parseInt(process.env.WG_CLIENT_PORT, 10) + : undefined, + /** Override default client DNS servers */ + DEFAULT_DNS: process.env.WG_DEFAULT_DNS?.split(',').map((x) => x.trim()), + /** Override default client allowed IPs */ + DEFAULT_ALLOWED_IPS: process.env.WG_DEFAULT_ALLOWED_IPS?.split(',').map((x) => x.trim()), + /** Override default client MTU */ + DEFAULT_MTU: process.env.WG_DEFAULT_MTU + ? Number.parseInt(process.env.WG_DEFAULT_MTU, 10) + : undefined, + /** Override default client persistent keepalive */ + DEFAULT_PERSISTENT_KEEPALIVE: process.env.WG_DEFAULT_PERSISTENT_KEEPALIVE + ? Number.parseInt(process.env.WG_DEFAULT_PERSISTENT_KEEPALIVE, 10) + : undefined, +}; + +export const WG_GENERAL_OVERRIDE_ENV = { + /** Override session timeout */ + SESSION_TIMEOUT: process.env.WG_SESSION_TIMEOUT + ? Number.parseInt(process.env.WG_SESSION_TIMEOUT, 10) + : undefined, + /** Override metrics Prometheus enabled status */ + METRICS_PROMETHEUS: process.env.WG_METRICS_PROMETHEUS === 'true' ? true : + process.env.WG_METRICS_PROMETHEUS === 'false' ? false : + undefined, + /** Override metrics JSON enabled status */ + METRICS_JSON: process.env.WG_METRICS_JSON === 'true' ? true : + process.env.WG_METRICS_JSON === 'false' ? false : + undefined, }; function assertEnv(env: T) { @@ -81,12 +125,46 @@ function assertEnv(env: T) { * Apply environment variable overrides to an interface object */ export function applyInterfaceOverrides< - T extends { port: number; device: string; mtu: number }, + T extends { port: number; device: string; mtu: number; ipv4Cidr: string; ipv6Cidr: string; enabled: boolean }, >(wgInterface: T): T { return { ...wgInterface, - port: WG_OVERRIDE_ENV.INTERFACE_PORT ?? wgInterface.port, - device: WG_OVERRIDE_ENV.INTERFACE_DEVICE ?? wgInterface.device, - mtu: WG_OVERRIDE_ENV.INTERFACE_MTU ?? wgInterface.mtu, + port: WG_OVERRIDE_ENV.PORT ?? wgInterface.port, + device: WG_OVERRIDE_ENV.DEVICE ?? wgInterface.device, + mtu: WG_OVERRIDE_ENV.MTU ?? wgInterface.mtu, + ipv4Cidr: WG_OVERRIDE_ENV.IPV4_CIDR ?? wgInterface.ipv4Cidr, + ipv6Cidr: WG_OVERRIDE_ENV.IPV6_CIDR ?? wgInterface.ipv6Cidr, + enabled: WG_OVERRIDE_ENV.ENABLED ?? wgInterface.enabled, + }; +} + +/** + * Apply environment variable overrides to a user config object + */ +export function applyUserConfigOverrides< + T extends { host: string; port: number; defaultDns: string[]; defaultAllowedIps: string[]; defaultMtu: number; defaultPersistentKeepalive: number }, +>(userConfig: T): T { + return { + ...userConfig, + host: WG_CLIENT_OVERRIDE_ENV.HOST ?? userConfig.host, + port: WG_CLIENT_OVERRIDE_ENV.CLIENT_PORT ?? userConfig.port, + defaultDns: WG_CLIENT_OVERRIDE_ENV.DEFAULT_DNS ?? userConfig.defaultDns, + defaultAllowedIps: WG_CLIENT_OVERRIDE_ENV.DEFAULT_ALLOWED_IPS ?? userConfig.defaultAllowedIps, + defaultMtu: WG_CLIENT_OVERRIDE_ENV.DEFAULT_MTU ?? userConfig.defaultMtu, + defaultPersistentKeepalive: WG_CLIENT_OVERRIDE_ENV.DEFAULT_PERSISTENT_KEEPALIVE ?? userConfig.defaultPersistentKeepalive, + }; +} + +/** + * Apply environment variable overrides to a general config object + */ +export function applyGeneralOverrides< + T extends { sessionTimeout: number; metricsPrometheus: boolean; metricsJson: boolean }, +>(generalConfig: T): T { + return { + ...generalConfig, + sessionTimeout: WG_GENERAL_OVERRIDE_ENV.SESSION_TIMEOUT ?? generalConfig.sessionTimeout, + metricsPrometheus: WG_GENERAL_OVERRIDE_ENV.METRICS_PROMETHEUS ?? generalConfig.metricsPrometheus, + metricsJson: WG_GENERAL_OVERRIDE_ENV.METRICS_JSON ?? generalConfig.metricsJson, }; }