Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nixos/actual: init at 24.10.1 #347825

Merged
merged 2 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions nixos/doc/manual/release-notes/rl-2505.section.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@

- [nostr-rs-relay](https://git.sr.ht/~gheartsfield/nostr-rs-relay/), This is a nostr relay, written in Rust. Available as [services.nostr-rs-relay](options.html#opt-services.nostr-rs-relay.enable).

- [Actual Budget](https://actualbudget.org/), a local-first personal finance app. Available as [services.actual](#opt-services.actual.enable).

- [mqtt-exporter](https://github.com/kpetremann/mqtt-exporter/), a Prometheus exporter for exposing messages from MQTT. Available as [services.prometheus.exporters.mqtt](#opt-services.prometheus.exporters.mqtt.enable).

- [Buffyboard](https://gitlab.postmarketos.org/postmarketOS/buffybox/-/tree/master/buffyboard), a framebuffer on-screen keyboard. Available as [services.buffyboard](option.html#opt-services.buffyboard).
Expand Down
1 change: 1 addition & 0 deletions nixos/modules/module-list.nix
Original file line number Diff line number Diff line change
Expand Up @@ -1413,6 +1413,7 @@
./services/video/wivrn.nix
./services/wayland/cage.nix
./services/wayland/hypridle.nix
./services/web-apps/actual.nix
./services/web-apps/akkoma.nix
./services/web-apps/agorakit.nix
./services/web-apps/alps.nix
Expand Down
121 changes: 121 additions & 0 deletions nixos/modules/services/web-apps/actual.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
{
lib,
pkgs,
config,
...
}:
let
inherit (lib)
getExe
mkDefault
mkEnableOption
mkIf
mkOption
mkPackageOption
types
;

cfg = config.services.actual;
configFile = formatType.generate "config.json" cfg.settings;
dataDir = "/var/lib/actual";

formatType = pkgs.formats.json { };
in
{
options.services.actual = {
enable = mkEnableOption "actual, a privacy focused app for managing your finances";
package = mkPackageOption pkgs "actual-server" { };

openFirewall = mkOption {
default = false;
type = types.bool;
description = "Whether to open the firewall for the specified port.";
};

settings = mkOption {
default = { };
description = "Server settings, refer to [the documentation](https://actualbudget.org/docs/config/) for available options.";
type = types.submodule {
freeformType = formatType.type;

options = {
hostname = mkOption {
type = types.str;
description = "The address to listen on";
default = "::";
};

port = mkOption {
type = types.port;
description = "The port to listen on";
default = 3000;
};
};

config = {
serverFiles = mkDefault "${dataDir}/server-files";
userFiles = mkDefault "${dataDir}/user-files";
dataDir = mkDefault dataDir;
};
};
};
};

config = mkIf cfg.enable {
networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.settings.port ];

systemd.services.actual = {
description = "Actual server, a local-first personal finance app";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
environment.ACTUAL_CONFIG_PATH = configFile;
serviceConfig = {
ExecStart = getExe cfg.package;
DynamicUser = true;
User = "actual";
Group = "actual";
StateDirectory = "actual";
WorkingDirectory = dataDir;
LimitNOFILE = "1048576";
PrivateTmp = true;
PrivateDevices = true;
StateDirectoryMode = "0700";
Restart = "always";

# Hardening
CapabilityBoundingSet = "";
LockPersonality = true;
#MemoryDenyWriteExecute = true; # Leads to coredump because V8 does JIT
PrivateUsers = true;
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
ProcSubset = "pid";
ProtectSystem = "strict";
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
"AF_NETLINK"
];
RestrictNamespaces = true;
RestrictRealtime = true;
SystemCallArchitectures = "native";
SystemCallFilter = [
"@system-service"
"@pkey"
];
UMask = "0077";
};
};
oddlama marked this conversation as resolved.
Show resolved Hide resolved
};

meta.maintainers = [
lib.maintainers.oddlama
lib.maintainers.patrickdag
];
}
18 changes: 18 additions & 0 deletions nixos/tests/actual.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import ./make-test-python.nix (
{ lib, ... }:
{
name = "actual";
meta.maintainers = [ lib.maintainers.oddlama ];

nodes.machine =
{ ... }:
{
services.actual.enable = true;
};

testScript = ''
machine.wait_for_open_port(3000)
machine.succeed("curl -fvvv -Ls http://localhost:3000/ | grep 'Actual'")
'';
}
)
1 change: 1 addition & 0 deletions nixos/tests/all-tests.nix
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ in {
aaaaxy = runTest ./aaaaxy.nix;
acme = runTest ./acme.nix;
acme-dns = handleTest ./acme-dns.nix {};
actual = handleTest ./actual.nix {};
adguardhome = runTest ./adguardhome.nix;
aesmd = runTestOn ["x86_64-linux"] ./aesmd.nix;
agate = runTest ./web-servers/agate.nix;
Expand Down
128 changes: 128 additions & 0 deletions pkgs/by-name/ac/actual-server/package.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
{
lib,
stdenv,
stdenvNoCC,
fetchFromGitHub,
makeWrapper,
cacert,
gitMinimal,
nodejs_20,
yarn,
nixosTests,
nix-update-script,
}:
let
version = "24.12.0";
src = fetchFromGitHub {
owner = "actualbudget";
repo = "actual-server";
tag = "v${version}";
hash = "sha256-qCATfpYjDlR2LaalkF0/b5tD4HDE4aNDrLvTC4g0ctY=";
};

yarn_20 = yarn.override { nodejs = nodejs_20; };

# We cannot use fetchYarnDeps because that doesn't support yarn2/berry
# lockfiles (see https://github.com/NixOS/nixpkgs/issues/254369)
offlineCache = stdenvNoCC.mkDerivation {
name = "actual-server-${version}-offline-cache";
inherit src;

nativeBuildInputs = [
cacert # needed for git
gitMinimal # needed to download git dependencies
yarn_20
];

SUPPORTED_ARCHITECTURES = builtins.toJSON {
os = [
"darwin"
"linux"
];
cpu = [
"arm"
"arm64"
"ia32"
"x64"
];
libc = [
"glibc"
"musl"
];
};

buildPhase = ''
runHook preBuild

export HOME=$(mktemp -d)
yarn config set enableTelemetry 0
yarn config set cacheFolder $out
yarn config set --json supportedArchitectures "$SUPPORTED_ARCHITECTURES"
yarn
Comment on lines +60 to +61
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately this will only build the native libraries for the current platform, meaning the content hash will vary (as seen by ofborg).

I already tried to fix it (by building in the package derivation), but couldn't make it work.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The solution would be to use fetchYarnDeps but we can't since it doesn't support v2/berry lockfiles yet. So i guess the best workaround we have is to set the output hash conditionally, at least this is what is done in the grafana build which also does that.

I guess this will make updates a bit more tedious, but we probably have no other choice.


runHook postBuild
'';

installPhase = ''
oddlama marked this conversation as resolved.
Show resolved Hide resolved
runHook preInstall

mkdir -p $out
cp -r ./node_modules $out/node_modules

runHook postInstall
'';
dontFixup = true;

outputHashAlgo = "sha256";
outputHashMode = "recursive";
outputHash =
{
x86_64-linux = "sha256-Rz+iKw4JDWtZOrCjs9sbHVw/bErAEY4TfoG+QfGKY94=";
aarch64-linux = "sha256-JGpRoIQrEI6crczHD62ZQO08GshBbzJC0dONYD69K/I=";
aarch64-darwin = "sha256-v2qzKmtqBdU6igyHat+NyL/XTzWgq/CKlNpai/iFHyQ=";
x86_64-darwin = "sha256-0ksWLlF/a58KY/8NgOQ5aPOLoXzqDqO3lhkmFvT17Bk=";
}
.${stdenv.hostPlatform.system} or (throw "Unsupported system: ${stdenv.hostPlatform.system}");
};
in
stdenv.mkDerivation {
pname = "actual-server";
inherit version src;

nativeBuildInputs = [
makeWrapper
yarn_20
];

installPhase = ''
runHook preInstall

mkdir -p $out/{bin,lib,lib/actual}
cp -r ${offlineCache}/node_modules/ $out/lib/actual
cp -r ./ $out/lib/actual

makeWrapper ${lib.getExe nodejs_20} "$out/bin/actual-server" \
--add-flags "$out/lib/actual/app.js" \
--set NODE_PATH "$out/node_modules"

runHook postInstall
'';

passthru = {
oddlama marked this conversation as resolved.
Show resolved Hide resolved
inherit offlineCache;
tests = nixosTests.actual;
passthru.updateScript = nix-update-script { };
oddlama marked this conversation as resolved.
Show resolved Hide resolved
};

meta = {
changelog = "https://actualbudget.org/docs/releases";
description = "Super fast privacy-focused app for managing your finances";
homepage = "https://actualbudget.org/";
mainProgram = "actual-server";
license = lib.licenses.mit;
maintainers = [
lib.maintainers.oddlama
lib.maintainers.patrickdag
];
};
}
Loading