Request: please support NixOS
Opened this issue · 10 comments
Please support NixOS. It is an one time effort, then it becomes an effortless sure-fire success.
Some exploratory work: NordVPN · Issue #101864
I'm attempting building from source. @keliramu I may have questions for you from time to time, but most of the help will need to come from other nix package maintainers.
I managed to write a nix package to compile from source, the nix package can be contributed to this project and built locally using src = ./.
and $ nix-build -E 'with import <nixpkgs> {}; callPackage ./default.nix {}'
default.nix
in the project code or (something like) nordvpn.nix
in your os config:
{ pkgs, lib, gcc, autoPatchelfHook, ... }:
let
patchedPkgs = pkgs.appendOverlays [
(final: prev: {
# Nordvpn uses a patched openvpn in order to perform xor obfuscation
# See https://github.com/NordSecurity/nordvpn-linux/blob/e614303aaaf1a64fde5bb1b4de1a7863b22428c4/ci/openvpn/check_dependencies.sh
openvpn = prev.openvpn.overrideAttrs (old: {
patches = (old.patches or [ ]) ++ [
(prev.fetchpatch {
url =
"https://github.com/Tunnelblick/Tunnelblick/raw/master/third_party/sources/openvpn/openvpn-${old.version}/patches/02-tunnelblick-openvpn_xorpatch-a.diff";
hash = "sha256-b9NiWETc0g2a7FNwrLaNrWx7gfCql7VTbewFu3QluFk=";
})
(prev.fetchpatch {
url =
"https://github.com/Tunnelblick/Tunnelblick/raw/master/third_party/sources/openvpn/openvpn-${old.version}/patches/03-tunnelblick-openvpn_xorpatch-b.diff";
hash = "sha256-X/SshB/8ItLFBx6TPhjBwyA97ra0iM2KgsGqGIy2s9I=";
})
(prev.fetchpatch {
url =
"https://github.com/Tunnelblick/Tunnelblick/raw/master/third_party/sources/openvpn/openvpn-${old.version}/patches/04-tunnelblick-openvpn_xorpatch-c.diff";
hash = "sha256-fw0CxJGIFEydIVRVouTlD1n275eQcbejUdhrU1JAx7g=";
})
(prev.fetchpatch {
url =
"https://github.com/Tunnelblick/Tunnelblick/raw/master/third_party/sources/openvpn/openvpn-${old.version}/patches/05-tunnelblick-openvpn_xorpatch-d.diff";
hash = "sha256-NLRtoRVz+4hQcElyz4elCAv9l1vp4Yb3/VJef+L/FZo=";
})
(prev.fetchpatch {
url =
"https://github.com/Tunnelblick/Tunnelblick/raw/master/third_party/sources/openvpn/openvpn-${old.version}/patches/06-tunnelblick-openvpn_xorpatch-e.diff";
hash = "sha256-mybdjCIT9b6ukbGWYvbr74fKtcncCtTvS5xSVf92T6Y=";
})
];
});
})
];
nordvpn = pkgs.buildGoModule rec {
pname = "nordvpn";
version = "3.19.0";
#src = ./.;
src = pkgs.fetchFromGitHub {
owner = "NordSecurity";
repo = "nordvpn-linux";
rev = "e614303aaaf1a64fde5bb1b4de1a7863b22428c4";
sha256 = "sha256-uIzG9QIVwax0Cop2VuDzy033efEBudFnGNj7osT/x2g";
};
nativeBuildInputs = with pkgs; [ pkg-config gcc ];
buildInputs = with pkgs; [ libxml2 gcc ];
vendorHash = "sha256-h5G5J/Sw0277pDzVXT6b3BX0KUbtyN8ujITfYp5PmgE";
ldflags = [
"-X main.Version=${version}"
"-X main.Environment=dev"
"-X main.Salt=development"
"-X main.Hash=${src.rev}"
];
buildPhase = ''
runHook preBuild
echo "Building nordvpn CLI..."
export LDFLAGS="${builtins.concatStringsSep " " ldflags}"
go build -ldflags "$LDFLAGS" -o bin/nordvpn ./cmd/cli
echo "Building nordvpn user..."
go build -ldflags "$LDFLAGS" -o bin/norduserd ./cmd/norduser
# Fix missing include in a library preventing compilation
chmod +w vendor/github.com/jbowtie/gokogiri/xpath/
sed -i '6i#include <stdlib.h>' vendor/github.com/jbowtie/gokogiri/xpath/expression.go
echo "Building nordvpn daemon..."
go build -ldflags "$LDFLAGS" -o bin/nordvpnd ./cmd/daemon
runHook postBuild
'';
installPhase = ''
runHook preInstall
mkdir -p $out/lib/nordvpn/
mv bin/norduserd $out/lib/nordvpn/
ln -s ${patchedPkgs.openvpn}/bin/openvpn $out/lib/nordvpn/openvpn
ln -s ${pkgs.wireguard-tools}/bin/wg $out/lib/nordvpn/wg
# Nordvpn needs icons for the system tray and notifications
mkdir -p $out/share/icons/hicolor/scalable/apps
cp assets/icon.svg $out/share/icons/hicolor/scalable/apps/nordvpn.svg # Does not follow naming convention
nordvpn_asset_prefix="nordvpn-" # hardcoded image prefix
for file in assets/*; do
cp "$file" "$out/share/icons/hicolor/scalable/apps/''\${nordvpn_asset_prefix}$(basename "$file")"
done
mkdir -p $out/bin
cp bin/* $out/bin
runHook postInstall
'';
meta = with pkgs.lib; {
description = "NordVPN CLI and daemon application for Linux";
homepage = "https://github.com/nordsecurity/nordvpn-linux";
mainProgram = "nordvpn";
license = licenses.gpl3;
platforms = platforms.linux;
};
};
in pkgs.buildFHSEnv {
name = "nordvpnd";
targetPkgs = with pkgs;
pkgs: [
nordvpn
sysctl
iptables
iproute2
procps
cacert
libxml2
libidn2
zlib
wireguard-tools
patchedPkgs.openvpn
e2fsprogs # for chattr
];
extraInstallCommands = ''
mkdir -p $out/bin/
printf "#!${pkgs.bash}/bin/bash\n${nordvpn}/bin/nordvpn \"\$@\"" > $out/bin/nordvpn
chmod +x $out/bin/nordvpn
'';
runScript = ''
${nordvpn}/bin/nordvpnd
'';
}
The daemon can then be activated using this in your os config:
systemd = {
services.nordvpn = {
description = "NordVPN daemon.";
serviceConfig = {
ExecStart = "${pkgs.nordvpn}/bin/nordvpnd";
ExecStartPre = ''
${pkgs.bash}/bin/bash -c '\
mkdir -m 700 -p /var/lib/nordvpn; \
if [ -z "$(ls -A /var/lib/nordvpn)" ]; then \
cp -r ${pkgs.nordvpn}/var/lib/nordvpn/* /var/lib/nordvpn; \
fi'
'';
NonBlocking = true;
KillMode = "process";
Restart = "on-failure";
RestartSec = 5;
RuntimeDirectory = "nordvpn";
RuntimeDirectoryMode = "0750";
Group = "nordvpn";
};
wantedBy = [ "multi-user.target" ];
#after = [ "network-online.target" ];
#wants = [ "network-online.target" ];
};
};
If you are having issues importing the package I found it easiest just appending this to the os config:
nixpkgs.config.packageOverrides = pkgs: {
nordvpn = pkgs.callPackage ./path-to-your-nordvpn.nix { inherit lib; };
};
It's probably not the best solution, but it's easy and works 🤷
That's beautiful. How would you feel about adding it to nixos/nixpkgs (with plenty of support)? It's about 95% of the way there.
That would be great! Unfortunately I am not at all well versed in the PR process to get it into nixpkgs (this is my first package). Feel free to copy the code to make a PR though, just make sure to co-author me 👍
Perhaps @LuisChDev might be interested. I used your package before this ❤️
@Blatzar I tested your solution. The package compiles, but I can not start the service:
building the system configuration...
stopping the following units: nordvpn.service
activating the configuration...
setting up /etc...
reloading user units for getreu...
restarting sysinit-reactivation.target
starting the following units: nordvpn.service
warning: the following units failed: nordvpn.service
● nordvpn.service - NordVPN daemon.
Loaded: loaded (/etc/systemd/system/nordvpn.service; enabled; preset: enabled)
Active: activating (auto-restart) (Result: exit-code) since Sun 2024-11-17 09:00:51 EET; 143ms ago
Process: 420641 ExecStartPre=/nix/store/syl4snn859kpqvn9qh91kr7n9i4dws04-bash-5.2p32/bin/bash -c mkdir -m 700 -p /var/lib/nordvpn; if [ -z "$(ls -A /var/lib/nordvpn)" ]; then cp -r /nix/store/30h9kdmxcamma5b83507mbwyhvcd35aw-nordvpnd/var/lib/nordvpn/* /var/lib/nordvpn; fi (code=exited, status=0/SUCCESS)
Process: 420646 ExecStart=/nix/store/30h9kdmxcamma5b83507mbwyhvcd35aw-nordvpnd/bin/nordvpnd (code=exited, status=1/FAILURE)
Main PID: 420646 (code=exited, status=1/FAILURE)
IP: 0B in, 0B out
CPU: 83ms
warning: error(s) occurred while switching to the new configuration
$ sudo /nix/store/30h9kdmxcamma5b83507mbwyhvcd35aw-nordvpnd/bin/nordvpnd
2024/11/17 09:01:49 [Info] Daemon has started
2024/11/17 09:01:49 cipher: message authentication failed
2024/11/17 09:01:49 cipher: message authentication failed
Any ideas?
@getreu Your issue is likely due to the changed salt. See https://github.com/NordSecurity/nordvpn-linux/blob/main/BUILD.md?plain=1#L65-L68
I do not know what salt the debian package is compiled with, so you need to remove your old /var/lib/nordvpn
and let it regenerate. This also means your need to login and set all your settings again.
@Blatzar thank you for your hint. I tried, but it did not solve my problem. I still can not start the nordvpn service.
I am absolutely positive its the hash, I can replicate your error by changing the hash myself, but if you want to debug go ahead, I've made it easy with a single config file. I built a vm with this config using nixos-rebuild build-vm -I nixos-config=/path/to/this/configuration.nix --no-flake
and it works fine
Stuff to note:
Username and password is "alice"
Make sure you change the VM specs to what your computer can handle
You might need to use nordvpn click <yourloginlink>
if the click to login doesnt work in firefox
You might need to start nordvpnd
as root once to let it generate the data files, not sure why the service doesn't
configuration.nix
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page, on
# https://search.nixos.org/options and in the NixOS manual (`nixos-help`).
{ config, lib, pkgs, ... }:
{
# Use the systemd-boot EFI boot loader.
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
nixpkgs.config.packageOverrides = pkgs: {
nordvpn = pkgs.callPackage ({ pkgs, lib, gcc, autoPatchelfHook, ... }:
let
patchedPkgs = pkgs.appendOverlays [
(final: prev: {
# Nordvpn uses a patched openvpn in order to perform xor obfuscation
# See https://github.com/NordSecurity/nordvpn-linux/blob/e614303aaaf1a64fde5bb1b4de1a7863b22428c4/ci/openvpn/check_dependencies.sh
openvpn = prev.openvpn.overrideAttrs (old: {
patches = (old.patches or [ ]) ++ [
(prev.fetchpatch {
url =
"https://github.com/Tunnelblick/Tunnelblick/raw/master/third_party/sources/openvpn/openvpn-${old.version}/patches/02-tunnelblick-openvpn_xorpatch-a.diff";
hash = "sha256-b9NiWETc0g2a7FNwrLaNrWx7gfCql7VTbewFu3QluFk=";
})
(prev.fetchpatch {
url =
"https://github.com/Tunnelblick/Tunnelblick/raw/master/third_party/sources/openvpn/openvpn-${old.version}/patches/03-tunnelblick-openvpn_xorpatch-b.diff";
hash = "sha256-X/SshB/8ItLFBx6TPhjBwyA97ra0iM2KgsGqGIy2s9I=";
})
(prev.fetchpatch {
url =
"https://github.com/Tunnelblick/Tunnelblick/raw/master/third_party/sources/openvpn/openvpn-${old.version}/patches/04-tunnelblick-openvpn_xorpatch-c.diff";
hash = "sha256-fw0CxJGIFEydIVRVouTlD1n275eQcbejUdhrU1JAx7g=";
})
(prev.fetchpatch {
url =
"https://github.com/Tunnelblick/Tunnelblick/raw/master/third_party/sources/openvpn/openvpn-${old.version}/patches/05-tunnelblick-openvpn_xorpatch-d.diff";
hash = "sha256-NLRtoRVz+4hQcElyz4elCAv9l1vp4Yb3/VJef+L/FZo=";
})
(prev.fetchpatch {
url =
"https://github.com/Tunnelblick/Tunnelblick/raw/master/third_party/sources/openvpn/openvpn-${old.version}/patches/06-tunnelblick-openvpn_xorpatch-e.diff";
hash = "sha256-mybdjCIT9b6ukbGWYvbr74fKtcncCtTvS5xSVf92T6Y=";
})
];
});
})
];
nordvpn = pkgs.buildGoModule rec {
pname = "nordvpn";
version = "3.19.0";
#src = ./.;
src = pkgs.fetchFromGitHub {
owner = "NordSecurity";
repo = "nordvpn-linux";
rev = "e614303aaaf1a64fde5bb1b4de1a7863b22428c4";
sha256 = "sha256-uIzG9QIVwax0Cop2VuDzy033efEBudFnGNj7osT/x2g";
};
nativeBuildInputs = with pkgs; [ pkg-config gcc ];
buildInputs = with pkgs; [ libxml2 gcc ];
vendorHash = "sha256-h5G5J/Sw0277pDzVXT6b3BX0KUbtyN8ujITfYp5PmgE";
ldflags = [
"-X main.Version=${version}"
"-X main.Environment=dev"
"-X main.Salt=development"
"-X main.Hash=${src.rev}"
];
buildPhase = ''
runHook preBuild
echo "Building nordvpn CLI..."
export LDFLAGS="${builtins.concatStringsSep " " ldflags}"
go build -ldflags "$LDFLAGS" -o bin/nordvpn ./cmd/cli
echo "Building nordvpn user..."
go build -ldflags "$LDFLAGS" -o bin/norduserd ./cmd/norduser
# Fix missing include in a library preventing compilation
chmod +w vendor/github.com/jbowtie/gokogiri/xpath/
sed -i '6i#include <stdlib.h>' vendor/github.com/jbowtie/gokogiri/xpath/expression.go
echo "Building nordvpn daemon..."
go build -ldflags "$LDFLAGS" -o bin/nordvpnd ./cmd/daemon
runHook postBuild
'';
installPhase = ''
runHook preInstall
mkdir -p $out/lib/nordvpn/
mv bin/norduserd $out/lib/nordvpn/
ln -s ${patchedPkgs.openvpn}/bin/openvpn $out/lib/nordvpn/openvpn
ln -s ${pkgs.wireguard-tools}/bin/wg $out/lib/nordvpn/wg
# Nordvpn needs icons for the system tray
mkdir -p $out/share/icons/hicolor/scalable/apps
nordvpn_asset_prefix="nordvpn-" # hardcoded image prefix
cp assets/icon.svg $out/share/icons/hicolor/scalable/apps/nordvpn.svg # Does not follow convention
for file in assets/*.svg; do
cp "$file" "$out/share/icons/hicolor/scalable/apps/''${nordvpn_asset_prefix}$(basename "$file")"
done
mkdir -p $out/bin
cp bin/* $out/bin
runHook postInstall
'';
meta = with pkgs.lib; {
description = "NordVPN CLI and daemon application for Linux";
homepage = "https://github.com/nordsecurity/nordvpn-linux";
mainProgram = "nordvpn";
license = licenses.gpl3;
platforms = platforms.linux;
};
};
in pkgs.buildFHSEnv {
name = "nordvpnd";
targetPkgs = with pkgs;
pkgs: [
nordvpn
sysctl
iptables
iproute2
procps
cacert
libxml2
libidn2
zlib
wireguard-tools
patchedPkgs.openvpn
e2fsprogs # for chattr
];
extraInstallCommands = ''
mkdir -p $out/bin/
printf "#!${pkgs.bash}/bin/bash\n${nordvpn}/bin/nordvpn \"\$@\"" > $out/bin/nordvpn
chmod +x $out/bin/nordvpn
'';
runScript = ''
${nordvpn}/bin/nordvpnd
'';
}) { inherit lib; };
};
# networking.hostName = "nixos"; # Define your hostname.
# Pick only one of the below networking options.
# networking.wireless.enable = true; # Enables wireless support via wpa_supplicant.
# networking.networkmanager.enable = true; # Easiest to use and most distros use this by default.
# Set your time zone.
# time.timeZone = "Europe/Amsterdam";
# Configure network proxy if necessary
# networking.proxy.default = "http://user:password@proxy:port/";
# networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";
# Select internationalisation properties.
# i18n.defaultLocale = "en_US.UTF-8";
# console = {
# font = "Lat2-Terminus16";
# keyMap = "us";
# useXkbConfig = true; # use xkb.options in tty.
# };
# Enable the X11 windowing system.
services.xserver.enable = true;
# Enable the Plasma 5 Desktop Environment.
services.displayManager.sddm.enable = true;
services.xserver.desktopManager.plasma5.enable = true;
# Configure keymap in X11
# services.xserver.xkb.layout = "us";
# services.xserver.xkb.options = "eurosign:e,caps:escape";
# Enable CUPS to print documents.
# services.printing.enable = true;
# Enable sound.
# hardware.pulseaudio.enable = true;
# OR
# services.pipewire = {
# enable = true;
# pulse.enable = true;
# };
# Enable touchpad support (enabled default in most desktopManager).
# services.libinput.enable = true;
# Define a user account. Don't forget to set a password with ‘passwd’.
users.groups.nordvpn.gid = 1000;
users.users.alice = {
password = "alice";
isNormalUser = true;
extraGroups = [ "wheel" "nordvpn" ]; # Enable ‘sudo’ for the user.
packages = with pkgs; [ firefox tree ];
};
# Nordvpn doesnt like when you dont have a dns
networking.nameservers = [ "1.1.1.1" "1.0.0.1" ];
services.resolved = {
enable = true;
dnssec = "true";
domains = [ "~." ];
fallbackDns = [ "1.1.1.1" "1.0.0.1" ];
dnsovertls = "true";
};
# Disable the firewall to prevent fuckery with nordvpn rules
# It is possible to use it at the same time but I have spent enough time on this config as is
networking.firewall.enable = false;
# Change this according to your specs
virtualisation.vmVariant = {
# following configuration is added only when building VM with build-vm
virtualisation = {
memorySize = 8000; # Use 8000MiB memory.
cores = 4;
};
};
systemd = {
services.nordvpn = {
description = "NordVPN daemon.";
serviceConfig = {
ExecStart = "${pkgs.nordvpn}/bin/nordvpnd";
ExecStartPre = ''
${pkgs.bash}/bin/bash -c '\
mkdir -m 700 -p /var/lib/nordvpn; \
if [ -z "$(ls -A /var/lib/nordvpn)" ]; then \
cp -r ${pkgs.nordvpn}/var/lib/nordvpn/* /var/lib/nordvpn; \
fi'
'';
NonBlocking = true;
KillMode = "process";
Restart = "on-failure";
RestartSec = 5;
RuntimeDirectory = "nordvpn";
RuntimeDirectoryMode = "0750";
Group = "nordvpn";
};
wantedBy = [ "multi-user.target" ];
#after = [ "network-online.target" ];
#wants = [ "network-online.target" ];
};
services.NetworkManager-wait-online.enable = lib.mkForce false;
};
# List packages installed in system profile. To search, run:
# $ nix search wget
environment.systemPackages = with pkgs; [
vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default.
wget
nordvpn
];
# Some programs need SUID wrappers, can be configured further or are
# started in user sessions.
# programs.mtr.enable = true;
# programs.gnupg.agent = {
# enable = true;
# enableSSHSupport = true;
# };
# List services that you want to enable:
# Enable the OpenSSH daemon.
# services.openssh.enable = true;
# Open ports in the firewall.
# networking.firewall.allowedTCPPorts = [ ... ];
# networking.firewall.allowedUDPPorts = [ ... ];
# Or disable the firewall altogether.
# networking.firewall.enable = false;
# Copy the NixOS configuration file and link it from the resulting system
# (/run/current-system/configuration.nix). This is useful in case you
# accidentally delete configuration.nix.
# system.copySystemConfiguration = true;
# This option defines the first version of NixOS you have installed on this particular machine,
# and is used to maintain compatibility with application data (e.g. databases) created on older NixOS versions.
#
# Most users should NEVER change this value after the initial install, for any reason,
# even if you've upgraded your system to a new NixOS release.
#
# This value does NOT affect the Nixpkgs version your packages and OS are pulled from,
# so changing it will NOT upgrade your system - see https://nixos.org/manual/nixos/stable/#sec-upgrading for how
# to actually do that.
#
# This value being lower than the current NixOS release does NOT mean your system is
# out of date, out of support, or vulnerable.
#
# Do NOT change this value unless you have manually inspected all the changes it would make to your configuration,
# and migrated your data accordingly.
#
# For more information, see `man configuration.nix` or https://nixos.org/manual/nixos/stable/options#opt-system.stateVersion .
system.stateVersion = "24.05"; # Did you read the comment?
}
Working picture
Everything compiles fine, but I still can not start the service:
sudo nordvpnd
2024/11/30 14:04:01 [Info] Daemon has started
2024/11/30 14:04:01 cipher: message authentication failed
2024/11/30 14:04:01 cipher: message authentication failed