diff --git a/nixos/doc/manual/release-notes/rl-2505.section.md b/nixos/doc/manual/release-notes/rl-2505.section.md index 1caa762d4ebf1d..e18d3a2eaf8332 100644 --- a/nixos/doc/manual/release-notes/rl-2505.section.md +++ b/nixos/doc/manual/release-notes/rl-2505.section.md @@ -29,6 +29,8 @@ +- [AmneziaVPN](https://amnezia.org/en), an open-source VPN client, with a key feature that enables you to deploy your own VPN server on your server. Available as [programs.amnezia-vpn](#opt-programs.amnezia-vpn.enable). + - [Bazecor](https://github.com/Dygmalab/Bazecor), the graphical configurator for Dygma Products. - [Bonsai](https://git.sr.ht/~stacyharper/bonsai), a general-purpose event mapper/state machine primarily used to create complex key shortcuts, and as part of the [SXMO](https://sxmo.org/) desktop environment. Available as [services.bonsaid](#opt-services.bonsaid.enable). diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 9fe8e3be6477d3..467a25decb72df 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -149,6 +149,7 @@ ./programs/_1password.nix ./programs/adb.nix ./programs/alvr.nix + ./programs/amnezia-vpn.nix ./programs/appgate-sdp.nix ./programs/appimage.nix ./programs/arp-scan.nix diff --git a/nixos/modules/programs/amnezia-vpn.nix b/nixos/modules/programs/amnezia-vpn.nix new file mode 100644 index 00000000000000..412ac76c7ea247 --- /dev/null +++ b/nixos/modules/programs/amnezia-vpn.nix @@ -0,0 +1,38 @@ +{ + config, + lib, + pkgs, + ... +}: +let + cfg = config.programs.amnezia-vpn; +in +{ + options.programs.amnezia-vpn = { + enable = lib.mkEnableOption "The AmneziaVPN client"; + }; + + config = lib.mkIf cfg.enable { + environment.systemPackages = [ pkgs.amnezia-vpn ]; + + services.dbus.packages = [ pkgs.amnezia-vpn ]; + services.resolved.enable = true; + + systemd = { + services.amnezia-vpn = { + description = "AmneziaVPN Service"; + after = [ "network.target" ]; + startLimitIntervalSec = 0; + serviceConfig = { + Type = "simple"; + Restart = "always"; + RestartSec = 1; + ExecStart = "${pkgs.amnezia-vpn}/bin/AmneziaVPN-service"; + }; + wantedBy = [ "multi-user.target" ]; + }; + }; + }; + + meta.maintainers = with lib.maintainers; [ sund3RRR ]; +} diff --git a/pkgs/by-name/am/amnezia-vpn/package.nix b/pkgs/by-name/am/amnezia-vpn/package.nix new file mode 100644 index 00000000000000..b6f6b313bd8b00 --- /dev/null +++ b/pkgs/by-name/am/amnezia-vpn/package.nix @@ -0,0 +1,155 @@ +{ + lib, + stdenv, + fetchFromGitHub, + cmake, + pkg-config, + kdePackages, + qt6, + libsecret, + xdg-utils, + amneziawg-go, + openvpn, + shadowsocks-rust, + cloak-pt, + wireguard-tools, + busybox, + sudo, + libssh, + zlib, + tun2socks, + xray, +}: +let + amnezia-tun2socks = tun2socks.overrideAttrs ( + finalAttrs: prevAttrs: { + pname = "amnezia-tun2socks"; + version = "2.5.4"; + + src = fetchFromGitHub { + owner = "amnezia-vpn"; + repo = "amnezia-tun2socks"; + tag = "v${finalAttrs.version}"; + hash = "sha256-lHo7WtcqccBSHly6neuksh1gC7RCKxbFNX9KSKNNeK8="; + }; + + vendorHash = "sha256-VvOaTJ6dBFlbGZGxnHy2sCtds1tyhu6VsPewYpsDBiM="; + + ldflags = [ + "-w" + "-s" + "-X github.com/amnezia-vpn/amnezia-tun2socks/v2/internal/version.Version=v${finalAttrs.version}" + "-X github.com/amnezia-vpn/amnezia-tun2socks/v2/internal/version.GitCommit=v${finalAttrs.version}" + ]; + } + ); + + amnezia-xray = xray.overrideAttrs ( + finalAttrs: prevAttrs: { + pname = "amnezia-xray"; + version = "1.8.13"; + + src = fetchFromGitHub { + owner = "amnezia-vpn"; + repo = "amnezia-xray-core"; + tag = "v${finalAttrs.version}"; + hash = "sha256-7XYdogoUEv3kTPTOQwRCohsPtfSDf+aRdI28IkTjvPk="; + }; + + vendorHash = "sha256-zArdGj5yeRxU0X4jNgT5YBI9SJUyrANDaqNPAPH3d5M="; + } + ); +in +stdenv.mkDerivation (finalAttrs: { + pname = "amnezia-vpn"; + version = "4.8.2.3"; + + src = fetchFromGitHub { + owner = "amnezia-vpn"; + repo = "amnezia-client"; + tag = finalAttrs.version; + hash = "sha256-bCWPyRW2xnnopcwfPHgQrdP85Ct0CDufJRQ1PvCAiDE="; + fetchSubmodules = true; + }; + + patches = [ ./router.patch ]; + + postPatch = + '' + substituteInPlace client/platforms/linux/daemon/wireguardutilslinux.cpp \ + --replace-fail 'm_tunnel.start(appPath.filePath("../../client/bin/wireguard-go"), wgArgs);' 'm_tunnel.start("${amneziawg-go}/bin/amneziawg-go", wgArgs);' + substituteInPlace client/utilities.cpp \ + --replace-fail 'return Utils::executable("../../client/bin/openvpn", true);' 'return Utils::executable("${openvpn}/bin/openvpn", false);' \ + --replace-fail 'return Utils::executable("../../client/bin/tun2socks", true);' 'return Utils::executable("${amnezia-tun2socks}/bin/amnezia-tun2socks", false);' \ + --replace-fail 'return Utils::usrExecutable("wg-quick");' 'return Utils::executable("${wireguard-tools}/bin/wg-quick", false);' \ + --replace-fail 'QProcess::execute(QString("pkill %1").arg(name));' 'return QProcess::execute(QString("pkill -f %1").arg(name)) == 0;' + substituteInPlace client/protocols/xrayprotocol.cpp \ + --replace-fail 'return Utils::executable(QString("xray"), true);' 'return Utils::executable(QString("${amnezia-xray}/bin/xray"), false);' + substituteInPlace client/protocols/openvpnovercloakprotocol.cpp \ + --replace-fail 'return Utils::executable(QString("/ck-client"), true);' 'return Utils::executable(QString("${cloak-pt}/bin/ck-client"), false);' + substituteInPlace client/protocols/shadowsocksvpnprotocol.cpp \ + --replace-fail 'return Utils::executable(QString("/ss-local"), true);' 'return Utils::executable(QString("${shadowsocks-rust}/bin/sslocal"), false);' + substituteInPlace client/configurators/openvpn_configurator.cpp \ + --replace-fail ".arg(qApp->applicationDirPath());" ".arg(\"$out/local/bin\");" + substituteInPlace client/ui/qautostart.cpp \ + --replace-fail "/usr/share/pixmaps/AmneziaVPN.png" "$out/share/pixmaps/AmneziaVPN.png" + substituteInPlace deploy/installer/config/AmneziaVPN.desktop.in \ + --replace-fail "#!/usr/bin/env xdg-open" "#!${xdg-utils}/bin/xdg-open" \ + --replace-fail "/usr/share/pixmaps/AmneziaVPN.png" "$out/share/pixmaps/AmneziaVPN.png" + substituteInPlace deploy/data/linux/AmneziaVPN.service \ + --replace-fail "ExecStart=/opt/AmneziaVPN/service/AmneziaVPN-service.sh" "ExecStart=$out/bin/AmneziaVPN-service" \ + --replace-fail "Environment=LD_LIBRARY_PATH=/opt/AmneziaVPN/client/lib" "" + '' + + (lib.optionalString (stdenv.hostPlatform.isAarch64 && stdenv.hostPlatform.isLinux) '' + substituteInPlace client/cmake/3rdparty.cmake \ + --replace-fail 'set(LIBSSH_LIB_PATH "''${LIBSSH_ROOT_DIR}/linux/x86_64/libssh.a")' 'set(LIBSSH_LIB_PATH "${libssh}/lib/libssh.so")' \ + --replace-fail 'set(ZLIB_LIB_PATH "''${LIBSSH_ROOT_DIR}/linux/x86_64/libz.a")' 'set(ZLIB_LIB_PATH "${zlib}/lib/libz.so")' \ + --replace-fail 'set(OPENSSL_LIB_SSL_PATH "''${OPENSSL_ROOT_DIR}/linux/x86_64/libssl.a")' 'set(OPENSSL_LIB_SSL_PATH "''${OPENSSL_ROOT_DIR}/linux/arm64/libssl.a")' \ + --replace-fail 'set(OPENSSL_LIB_CRYPTO_PATH "''${OPENSSL_ROOT_DIR}/linux/x86_64/libcrypto.a")' 'set(OPENSSL_LIB_CRYPTO_PATH "''${OPENSSL_ROOT_DIR}/linux/arm64/libcrypto.a")' + ''); + + strictDeps = true; + + nativeBuildInputs = [ + cmake + pkg-config + qt6.wrapQtAppsHook + ]; + + buildInputs = [ + libsecret + qt6.qtbase + qt6.qttools + kdePackages.qtremoteobjects + kdePackages.qtsvg + kdePackages.qt5compat + ]; + + qtWrapperArgs = [ + ''--prefix PATH : ${ + lib.makeBinPath [ + busybox + sudo + ] + }'' + ]; + + postInstall = '' + mkdir -p $out/bin $out/local/bin $out/share/applications $out/share/pixmaps $out/lib/systemd/system + cp client/AmneziaVPN service/server/AmneziaVPN-service $out/bin/ + cp ../deploy/data/linux/client/bin/update-resolv-conf.sh $out/local/bin/ + cp ../AppDir/AmneziaVPN.desktop $out/share/applications/ + cp ../deploy/data/linux/AmneziaVPN.png $out/share/pixmaps/ + cp ../deploy/data/linux/AmneziaVPN.service $out/lib/systemd/system/ + ''; + + meta = with lib; { + description = "Amnezia VPN Client"; + downloadPage = "https://amnezia.org/en/downloads"; + homepage = "https://amnezia.org/en"; + license = licenses.gpl3; + mainProgram = "AmneziaVPN"; + maintainers = with maintainers; [ sund3RRR ]; + platforms = platforms.unix; + }; +}) diff --git a/pkgs/by-name/am/amnezia-vpn/router.patch b/pkgs/by-name/am/amnezia-vpn/router.patch new file mode 100644 index 00000000000000..3f78af405af202 --- /dev/null +++ b/pkgs/by-name/am/amnezia-vpn/router.patch @@ -0,0 +1,54 @@ +--- a/service/server/router_linux.cpp 2025-01-01 11:36:27.615658613 +0300 ++++ b/service/server/router_linux.cpp 2025-01-01 18:07:57.300178080 +0300 +@@ -19,9 +19,27 @@ + #include + #include + #include ++#include ++#include + + #include + ++bool isServiceActive(const QString &serviceName) { ++ QProcess process; ++ process.start("systemctl", { "list-units", "--type=service", "--state=running", "--no-legend" }); ++ process.waitForFinished(); ++ ++ QString output = process.readAllStandardOutput(); ++ QStringList services = output.split('\n', Qt::SkipEmptyParts); ++ ++ for (const QString &service : services) { ++ if (service.contains(serviceName)) { ++ return true; ++ } ++ } ++ return false; ++} ++ + RouterLinux &RouterLinux::Instance() + { + static RouterLinux s; +@@ -158,15 +176,14 @@ + p.setProcessChannelMode(QProcess::MergedChannels); + + //check what the dns manager use +- if (QFileInfo::exists("/usr/bin/nscd") +- || QFileInfo::exists("/usr/sbin/nscd") +- || QFileInfo::exists("/usr/lib/systemd/system/nscd.service")) +- { +- p.start("systemctl restart nscd"); +- } +- else +- { +- p.start("systemctl restart systemd-resolved"); ++ if (isServiceActive("nscd.service")) { ++ qDebug() << "Restarting nscd.service"; ++ p.start("systemctl", { "restart", "nscd" }); ++ } else if (isServiceActive("systemd-resolved.service")) { ++ qDebug() << "Restarting systemd-resolved.service"; ++ p.start("systemctl", { "restart", "systemd-resolved" }); ++ } else { ++ qDebug() << "No suitable DNS manager found."; + } + + p.waitForFinished();