mirror of
https://github.com/narrrl/proton-drive-linux.git
synced 2026-11-03 16:41:26 +01:00
feat(packaging): add a Nix flake and NixOS module
Builds the four binaries with rustPlatform.buildRustPackage from Cargo.lock, installs the desktop entries, icon, user service and translations as the other packages do, and wraps the binaries with exiftool and ffmpeg on PATH. The NixOS module installs the package, pulls proton-drive.service into the graphical session with the fusermount3 wrapper on its PATH, and enables FUSE and GNOME Keyring. A Nix workflow builds the flake when its recipe, the lock files or the code change. Refs #37 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EuyxByBpK3fSWtyPkugeHz
This commit is contained in:
9 files changed
+321
No files matched your search
@@ -0,0 +1,52 @@
|
|||||||
|
name: Nix
|
||||||
|
|
||||||
|
# Builds the flake (docs/INSTALL.md#nixos-flake) whenever its recipe, the lock
|
||||||
|
# files or the code change, so a NixOS user's `nix build` keeps working. Run it
|
||||||
|
# from the Actions tab for any branch to get a build to try.
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- 'flake.nix'
|
||||||
|
- 'flake.lock'
|
||||||
|
- 'packaging/nix/**'
|
||||||
|
- 'Cargo.lock'
|
||||||
|
- 'Cargo.toml'
|
||||||
|
- 'crates/**'
|
||||||
|
- 'po/**'
|
||||||
|
- '.github/workflows/nix.yml'
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- 'flake.nix'
|
||||||
|
- 'flake.lock'
|
||||||
|
- 'packaging/nix/**'
|
||||||
|
- 'Cargo.lock'
|
||||||
|
- '.github/workflows/nix.yml'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: nix-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v7
|
||||||
|
|
||||||
|
- uses: cachix/install-nix-action@v31
|
||||||
|
|
||||||
|
- name: Check the flake
|
||||||
|
run: nix flake check --print-build-logs --no-build
|
||||||
|
|
||||||
|
- name: Build the package
|
||||||
|
run: nix build --print-build-logs .#proton-drive-linux
|
||||||
|
|
||||||
|
- name: Smoke test
|
||||||
|
run: |
|
||||||
|
./result/bin/pdfs --version
|
||||||
|
for bin in pdfs-app pdfs-tray pdfs-prompt; do test -x "result/bin/$bin"; done
|
||||||
|
grep -q "ExecStart=$(readlink -f result)/bin/pdfs" result/lib/systemd/user/proton-drive.service
|
||||||
|
ls result/share/locale/*/LC_MESSAGES/pdfs.mo
|
||||||
@@ -3,3 +3,5 @@
|
|||||||
*.pdb
|
*.pdb
|
||||||
.env
|
.env
|
||||||
/rpmbuild
|
/rpmbuild
|
||||||
|
/result
|
||||||
|
/result-*
|
||||||
@@ -76,6 +76,7 @@ scriptable CLI.
|
|||||||
| Debian, Ubuntu 24.04 or newer | `.deb` from the [latest release](https://github.com/narrrl/proton-drive-linux/releases/latest) |
|
| Debian, Ubuntu 24.04 or newer | `.deb` from the [latest release](https://github.com/narrrl/proton-drive-linux/releases/latest) |
|
||||||
| Fedora 44 or newer | `.rpm` from the [latest release](https://github.com/narrrl/proton-drive-linux/releases/latest) |
|
| Fedora 44 or newer | `.rpm` from the [latest release](https://github.com/narrrl/proton-drive-linux/releases/latest) |
|
||||||
| Arch Linux | [`proton-drive-for-linux`](https://aur.archlinux.org/packages/proton-drive-for-linux) (also `-bin` and `-git`) in the AUR |
|
| Arch Linux | [`proton-drive-for-linux`](https://aur.archlinux.org/packages/proton-drive-for-linux) (also `-bin` and `-git`) in the AUR |
|
||||||
|
| NixOS | The flake in this repository: see [Install → NixOS](docs/INSTALL.md#nixos-flake) |
|
||||||
| Anything else | [Build from source](docs/INSTALL.md#build-from-source) |
|
| Anything else | [Build from source](docs/INSTALL.md#build-from-source) |
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -11,6 +11,12 @@ scratch (user data in `staging/` and `recovery/` is never touched by this).
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- **A Nix flake for NixOS.** `nix build github:narrrl/proton-drive-linux` builds the client, and
|
||||||
|
the flake's NixOS module installs it and runs the mount in every graphical session. See
|
||||||
|
[Install → NixOS](INSTALL.md#nixos-flake).
|
||||||
|
([#37](https://github.com/narrrl/proton-drive-linux/issues/37))
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- **Writing to a file again soon after a partial write could fail with an I/O error.** When the
|
- **Writing to a file again soon after a partial write could fail with an I/O error.** When the
|
||||||
first write changed only part of a file this client had not read, a second write, or saving
|
first write changed only part of a file this client had not read, a second write, or saving
|
||||||
|
|||||||
@@ -82,6 +82,39 @@ paru -S proton-drive-for-linux # or yay, or any other AUR helper
|
|||||||
|
|
||||||
The recipes live in [`packaging/aur/`](../packaging/aur/README.md).
|
The recipes live in [`packaging/aur/`](../packaging/aur/README.md).
|
||||||
|
|
||||||
|
### NixOS (flake)
|
||||||
|
|
||||||
|
The repository is a flake. Add it as an input and enable the module, which installs the package,
|
||||||
|
links the user service into every graphical session and turns on the `fusermount3` wrapper and
|
||||||
|
GNOME Keyring for you:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{
|
||||||
|
inputs.proton-drive-linux.url = "github:narrrl/proton-drive-linux";
|
||||||
|
|
||||||
|
outputs = { nixpkgs, proton-drive-linux, ... }: {
|
||||||
|
nixosConfigurations.<host> = nixpkgs.lib.nixosSystem {
|
||||||
|
modules = [
|
||||||
|
proton-drive-linux.nixosModules.default
|
||||||
|
{ services.proton-drive-linux.enable = true; }
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
To try it without changing your system, run the app straight from the flake:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nix run github:narrrl/proton-drive-linux#proton-drive-linux -- --help # the CLI
|
||||||
|
nix shell github:narrrl/proton-drive-linux -c pdfs-app # the desktop app
|
||||||
|
```
|
||||||
|
|
||||||
|
The mount itself needs the setuid `fusermount3` from NixOS (`programs.fuse.enable`, on by default
|
||||||
|
with the module) and a Secret Service such as GNOME Keyring or KWallet. To leave out ffmpeg and
|
||||||
|
with it video thumbnails, override the package with `withFfmpeg = false`. The recipe lives in
|
||||||
|
[`packaging/nix/`](../packaging/nix/).
|
||||||
|
|
||||||
### Other distributions
|
### Other distributions
|
||||||
|
|
||||||
Unpack the `.tar.gz` into a directory on your `PATH`, then install the service unit as shown in
|
Unpack the `.tar.gz` into a directory on your `PATH`, then install the service unit as shown in
|
||||||
|
|||||||
Generated
+27
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1791456040,
|
||||||
|
"narHash": "sha256-H83yz/do+hjOO0uujHyH8RgtIQP2v7Mw+cLwcZK/xKc=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "e7439b6b14ad3cc35d05608ebca9bce01a25f5f8",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
description = "Unofficial Proton Drive client for Linux: files-on-demand FUSE mount, CLI, GTK4 app and tray";
|
||||||
|
|
||||||
|
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
|
|
||||||
|
outputs =
|
||||||
|
{ self, nixpkgs }:
|
||||||
|
let
|
||||||
|
systems = [
|
||||||
|
"x86_64-linux"
|
||||||
|
"aarch64-linux"
|
||||||
|
];
|
||||||
|
forAllSystems = f: nixpkgs.lib.genAttrs systems (system: f nixpkgs.legacyPackages.${system});
|
||||||
|
in
|
||||||
|
{
|
||||||
|
packages = forAllSystems (pkgs: rec {
|
||||||
|
proton-drive-linux = pkgs.callPackage ./packaging/nix/package.nix { };
|
||||||
|
default = proton-drive-linux;
|
||||||
|
});
|
||||||
|
|
||||||
|
overlays.default = final: _: {
|
||||||
|
proton-drive-linux = final.callPackage ./packaging/nix/package.nix { };
|
||||||
|
};
|
||||||
|
|
||||||
|
nixosModules.default = import ./packaging/nix/module.nix self;
|
||||||
|
|
||||||
|
devShells = forAllSystems (pkgs: {
|
||||||
|
default = pkgs.mkShell {
|
||||||
|
inputsFrom = [ self.packages.${pkgs.stdenv.hostPlatform.system}.proton-drive-linux ];
|
||||||
|
packages = with pkgs; [
|
||||||
|
cargo
|
||||||
|
clippy
|
||||||
|
rustfmt
|
||||||
|
rust-analyzer
|
||||||
|
];
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
formatter = forAllSystems (pkgs: pkgs.nixfmt);
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
# NixOS module: installs the package and runs the mount daemon in every
|
||||||
|
# graphical session, as the other packages' user service does.
|
||||||
|
#
|
||||||
|
# services.proton-drive-linux.enable = true;
|
||||||
|
self:
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.services.proton-drive-linux;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.services.proton-drive-linux = {
|
||||||
|
enable = lib.mkEnableOption "the Proton Drive for Linux mount daemon, app and tray";
|
||||||
|
package = lib.mkOption {
|
||||||
|
type = lib.types.package;
|
||||||
|
default = self.packages.${pkgs.stdenv.hostPlatform.system}.proton-drive-linux;
|
||||||
|
defaultText = lib.literalExpression "proton-drive-linux.packages.\${system}.proton-drive-linux";
|
||||||
|
description = "The package to use.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
environment.systemPackages = [ cfg.package ];
|
||||||
|
# The unit ships in the package; this links it and pulls it into the
|
||||||
|
# graphical session, which is what `systemctl --user enable` would do.
|
||||||
|
systemd.packages = [ cfg.package ];
|
||||||
|
systemd.user.services.proton-drive = {
|
||||||
|
wantedBy = [ "graphical-session.target" ];
|
||||||
|
# The mount runs fusermount3 from PATH, and it has to be the setuid
|
||||||
|
# wrapper; the PATH NixOS gives a unit does not include it.
|
||||||
|
path = [ "/run/wrappers" ];
|
||||||
|
};
|
||||||
|
programs.fuse.enable = lib.mkDefault true;
|
||||||
|
# Session tokens are kept in the Secret Service.
|
||||||
|
services.gnome.gnome-keyring.enable = lib.mkDefault true;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
# Nix package for the workspace, built from the checkout this file lives in.
|
||||||
|
# The flake at the repository root exposes it; `nix build` builds it.
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
rustPlatform,
|
||||||
|
pkg-config,
|
||||||
|
gettext,
|
||||||
|
glib,
|
||||||
|
wrapGAppsHook4,
|
||||||
|
fuse3,
|
||||||
|
gtk4,
|
||||||
|
libadwaita,
|
||||||
|
webkitgtk_6_0,
|
||||||
|
libsecret,
|
||||||
|
dbus,
|
||||||
|
exiftool,
|
||||||
|
ffmpeg-headless,
|
||||||
|
withFfmpeg ? true,
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
cargoToml = lib.importTOML ../../Cargo.toml;
|
||||||
|
in
|
||||||
|
rustPlatform.buildRustPackage {
|
||||||
|
pname = "proton-drive-linux";
|
||||||
|
inherit (cargoToml.workspace.package) version;
|
||||||
|
|
||||||
|
# Only what the build reads, so editing docs or CI does not rebuild.
|
||||||
|
src = lib.fileset.toSource {
|
||||||
|
root = ../..;
|
||||||
|
fileset = lib.fileset.unions [
|
||||||
|
../../Cargo.toml
|
||||||
|
../../Cargo.lock
|
||||||
|
../../crates
|
||||||
|
../../po
|
||||||
|
../../LICENSE
|
||||||
|
../proton-drive.service
|
||||||
|
../io.narl.proton-drive-linux.desktop
|
||||||
|
../io.narl.proton-drive-linux-tray.desktop
|
||||||
|
../io.narl.proton-drive-linux.svg
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
cargoLock.lockFile = ../../Cargo.lock;
|
||||||
|
|
||||||
|
cargoBuildFlags = [
|
||||||
|
"--bin"
|
||||||
|
"pdfs"
|
||||||
|
"--bin"
|
||||||
|
"pdfs-tray"
|
||||||
|
"--bin"
|
||||||
|
"pdfs-app"
|
||||||
|
"--bin"
|
||||||
|
"pdfs-prompt"
|
||||||
|
];
|
||||||
|
|
||||||
|
nativeBuildInputs = [
|
||||||
|
pkg-config
|
||||||
|
gettext # msgfmt, for po/build.sh
|
||||||
|
glib # glib-compile-resources, for the GUI's build.rs
|
||||||
|
wrapGAppsHook4
|
||||||
|
];
|
||||||
|
|
||||||
|
buildInputs = [
|
||||||
|
fuse3
|
||||||
|
gtk4
|
||||||
|
libadwaita
|
||||||
|
webkitgtk_6_0
|
||||||
|
libsecret
|
||||||
|
dbus
|
||||||
|
];
|
||||||
|
|
||||||
|
# The app looks for its catalogs here instead of /usr/share/locale.
|
||||||
|
env.PDFS_LOCALEDIR = "${placeholder "out"}/share/locale";
|
||||||
|
|
||||||
|
# The suite mounts FUSE, talks to D-Bus and the kernel keyring, and checks
|
||||||
|
# permissions a build sandbox does not have; CI runs it on every push.
|
||||||
|
doCheck = false;
|
||||||
|
|
||||||
|
postInstall = ''
|
||||||
|
install -Dm644 packaging/io.narl.proton-drive-linux.desktop \
|
||||||
|
$out/share/applications/io.narl.proton-drive-linux.desktop
|
||||||
|
install -Dm644 packaging/io.narl.proton-drive-linux-tray.desktop \
|
||||||
|
$out/etc/xdg/autostart/io.narl.proton-drive-linux-tray.desktop
|
||||||
|
install -Dm644 packaging/io.narl.proton-drive-linux.svg \
|
||||||
|
$out/share/icons/hicolor/scalable/apps/io.narl.proton-drive-linux.svg
|
||||||
|
substituteInPlace $out/share/applications/io.narl.proton-drive-linux.desktop \
|
||||||
|
--replace-fail "Exec=pdfs-app" "Exec=$out/bin/pdfs-app"
|
||||||
|
substituteInPlace $out/etc/xdg/autostart/io.narl.proton-drive-linux-tray.desktop \
|
||||||
|
--replace-fail "Exec=pdfs-tray" "Exec=$out/bin/pdfs-tray"
|
||||||
|
|
||||||
|
install -Dm644 packaging/proton-drive.service \
|
||||||
|
$out/lib/systemd/user/proton-drive.service
|
||||||
|
substituteInPlace $out/lib/systemd/user/proton-drive.service \
|
||||||
|
--replace-fail "ExecStart=/usr/bin/pdfs" "ExecStart=$out/bin/pdfs"
|
||||||
|
|
||||||
|
patchShebangs po/build.sh
|
||||||
|
po/build.sh $out/share/locale
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Thumbnails shell out to exiftool, and to ffmpeg for video. Suffixed, so a
|
||||||
|
# user's own builds on PATH win. fusermount3 comes from the system: on NixOS
|
||||||
|
# it is the setuid wrapper in /run/wrappers/bin.
|
||||||
|
preFixup = ''
|
||||||
|
gappsWrapperArgs+=(--suffix PATH : ${
|
||||||
|
lib.makeBinPath ([ exiftool ] ++ lib.optional withFfmpeg ffmpeg-headless)
|
||||||
|
})
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = {
|
||||||
|
description = "Unofficial Proton Drive client for Linux: files-on-demand FUSE mount, CLI, GTK4 app and tray";
|
||||||
|
homepage = "https://proton-drive.narl.io";
|
||||||
|
license = lib.licenses.mit;
|
||||||
|
platforms = lib.platforms.linux;
|
||||||
|
mainProgram = "pdfs";
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in new issue
Block a user