Skip to content

Commit

Permalink
nixos/actual: init module and tests
Browse files Browse the repository at this point in the history
Co-authored-by: PatrickDaG <[email protected]>
  • Loading branch information
oddlama and PatrickDaG committed Dec 15, 2024
1 parent b77b09e commit 0a11562
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 0 deletions.
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";
};
};
};

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

0 comments on commit 0a11562

Please sign in to comment.