diff --git a/docs/widgets/services/synologyvpn.md b/docs/widgets/services/synologyvpn.md
new file mode 100644
index 00000000..5d943200
--- /dev/null
+++ b/docs/widgets/services/synologyvpn.md
@@ -0,0 +1,14 @@
+---
+title: Synology VPN client status
+description: Synology VPN client status Widget Configuration
+---
+
+Note: the widget is not compatible with 2FA.
+
+```yaml
+widget:
+ type: synologyvpn
+ url: http://downloadstation.host.or.ip:port
+ username: username
+ password: password
+```
diff --git a/mkdocs.yml b/mkdocs.yml
index 572d36b4..d8e0d705 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -123,6 +123,7 @@ nav:
- widgets/services/sonarr.md
- widgets/services/speedtest-tracker.md
- widgets/services/syncthing-relay-server.md
+ - widgets/services/synologyvpn.md
- widgets/services/tailscale.md
- widgets/services/tdarr.md
- widgets/services/traefik.md
diff --git a/src/widgets/components.js b/src/widgets/components.js
index bb9b00fe..1e6a7649 100644
--- a/src/widgets/components.js
+++ b/src/widgets/components.js
@@ -96,6 +96,7 @@ const components = {
sonarr: dynamic(() => import("./sonarr/component")),
speedtest: dynamic(() => import("./speedtest/component")),
strelaysrv: dynamic(() => import("./strelaysrv/component")),
+ synologyvpn: dynamic(() => import("./synologyvpn/component")),
tailscale: dynamic(() => import("./tailscale/component")),
tautulli: dynamic(() => import("./tautulli/component")),
tdarr: dynamic(() => import("./tdarr/component")),
diff --git a/src/widgets/synologyvpn/component.jsx b/src/widgets/synologyvpn/component.jsx
new file mode 100644
index 00000000..5acac267
--- /dev/null
+++ b/src/widgets/synologyvpn/component.jsx
@@ -0,0 +1,24 @@
+import { useTranslation } from "next-i18next";
+
+import Container from "components/services/widget/container";
+import Block from "components/services/widget/block";
+import useWidgetAPI from "utils/proxy/use-widget-api";
+
+export default function Component({ service }) {
+ const { t } = useTranslation();
+ const { widget } = service;
+ const { data: gatewayData, error: gatewayError } = useWidgetAPI(widget, "gatewayList");
+
+ if (gatewayError) {
+ return ;
+ }
+
+ const configs = gatewayData?.data?.configs || [];
+ const isVPNConnected = configs.some(config => config.class === "vpn-client");
+
+ return (
+
+
+
+ );
+}
diff --git a/src/widgets/synologyvpn/widget.js b/src/widgets/synologyvpn/widget.js
new file mode 100644
index 00000000..057670f2
--- /dev/null
+++ b/src/widgets/synologyvpn/widget.js
@@ -0,0 +1,17 @@
+import synologyProxyHandler from "../../utils/proxy/handlers/synology";
+
+const widget = {
+ // Variables to be filled at runtime
+ api: "{url}/webapi/{cgiPath}?api={apiName}&version={maxVersion}&method={apiMethod}",
+ proxyHandler: synologyProxyHandler,
+
+ mappings: {
+ gatewayList: {
+ apiName: "SYNO.Core.Network.Router.Gateway.List",
+ apiMethod: "get&iptype=ipv4&type=wan",
+ endpoint: "gatewayList",
+ },
+ },
+};
+
+export default widget;
diff --git a/src/widgets/widgets.js b/src/widgets/widgets.js
index fe474406..9c4fa16f 100644
--- a/src/widgets/widgets.js
+++ b/src/widgets/widgets.js
@@ -88,6 +88,7 @@ import scrutiny from "./scrutiny/widget";
import sonarr from "./sonarr/widget";
import speedtest from "./speedtest/widget";
import strelaysrv from "./strelaysrv/widget";
+import synologyvpn from "./synologyvpn/widget";
import tailscale from "./tailscale/widget";
import tautulli from "./tautulli/widget";
import tdarr from "./tdarr/widget";
@@ -198,6 +199,7 @@ const widgets = {
sonarr,
speedtest,
strelaysrv,
+ synologyvpn,
tailscale,
tautulli,
tdarr,