Add Actual server
All checks were successful
Check Flake / check-flake (push) Successful in 6m3s

This commit is contained in:
Zuckerberg 2024-02-19 19:44:07 -07:00
parent bfc1bb2da9
commit 01af25a57e
7 changed files with 8999 additions and 0 deletions

View File

@ -0,0 +1,87 @@
# Starting point:
# https://github.com/aldoborrero/mynixpkgs/commit/c501c1e32dba8f4462dcecb57eee4b9e52038e27
{ config, pkgs, lib, ... }:
let
cfg = config.services.actual-server;
stateDir = "/var/lib/${cfg.stateDirName}";
in
{
options.services.actual-server = {
enable = lib.mkEnableOption "Actual Server";
hostname = lib.mkOption {
type = lib.types.str;
default = "localhost";
description = "Hostname for the Actual Server.";
};
port = lib.mkOption {
type = lib.types.int;
default = 25448;
description = "Port on which the Actual Server should listen.";
};
stateDirName = lib.mkOption {
type = lib.types.str;
default = "actual-server";
description = "Name of the directory under /var/lib holding the server's data.";
};
upload = {
fileSizeSyncLimitMB = lib.mkOption {
type = lib.types.nullOr lib.types.int;
default = null;
description = "File size limit in MB for synchronized files.";
};
syncEncryptedFileSizeLimitMB = lib.mkOption {
type = lib.types.nullOr lib.types.int;
default = null;
description = "File size limit in MB for synchronized encrypted files.";
};
fileSizeLimitMB = lib.mkOption {
type = lib.types.nullOr lib.types.int;
default = null;
description = "File size limit in MB for file uploads.";
};
};
};
config = lib.mkIf cfg.enable {
systemd.services.actual-server = {
description = "Actual Server";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
ExecStart = "${pkgs.actual-server}/bin/actual-server";
Restart = "always";
StateDirectory = cfg.stateDirName;
WorkingDirectory = stateDir;
DynamicUser = true;
UMask = "0007";
};
environment = {
NODE_ENV = "production";
ACTUAL_PORT = toString cfg.port;
# Actual is actually very bad at configuring it's own paths despite that information being readily available
ACTUAL_USER_FILES = "${stateDir}/user-files";
ACTUAL_SERVER_FILES = "${stateDir}/server-files";
ACTUAL_DATA_DIR = stateDir;
ACTUAL_UPLOAD_FILE_SYNC_SIZE_LIMIT_MB = toString (cfg.upload.fileSizeSyncLimitMB or "");
ACTUAL_UPLOAD_SYNC_ENCRYPTED_FILE_SIZE_LIMIT_MB = toString (cfg.upload.syncEncryptedFileSizeLimitMB or "");
ACTUAL_UPLOAD_FILE_SIZE_LIMIT_MB = toString (cfg.upload.fileSizeLimitMB or "");
};
};
services.nginx.virtualHosts.${cfg.hostname} = {
enableACME = true;
forceSSL = true;
locations."/".proxyPass = "http://localhost:${toString cfg.port}";
};
};
}

View File

@ -21,5 +21,6 @@
./gitea-actions-runner.nix ./gitea-actions-runner.nix
./dashy.nix ./dashy.nix
./librechat.nix ./librechat.nix
./actualbudget.nix
]; ];
} }

View File

@ -155,4 +155,7 @@
# librechat # librechat
services.librechat.enable = true; services.librechat.enable = true;
services.librechat.host = "chat.neet.dev"; services.librechat.host = "chat.neet.dev";
services.actual-server.enable = true;
services.actual-server.hostname = "actual.runyan.org";
} }

View File

@ -0,0 +1,39 @@
{ lib
, buildNpmPackage
, fetchFromGitHub
, python3
, nodejs
, runtimeShell
}:
buildNpmPackage rec {
pname = "actual-server";
version = "24.2.0";
src = fetchFromGitHub {
owner = "actualbudget";
repo = pname;
rev = "refs/tags/v${version}";
hash = "sha256-9Dx6FxWZvGAgJfYYuEgkLr5dhpe5P+bdiSQWhPVeUu8=";
};
npmDepsHash = "sha256-j9i+Z6ZlywwCgs198bt9jOwVxe1Rhh7EQVH3ZJ+YNI4=";
patches = [
./migrations-should-use-pkg-path.patch
];
postPatch = ''
cp ${./package-lock.json} package-lock.json
'';
dontNpmBuild = true;
postInstall = ''
mkdir -p $out/bin
cat <<EOF > $out/bin/actual-server
#!${runtimeShell}
exec ${nodejs}/bin/node $out/lib/node_modules/actual-sync/app.js "\$@"
EOF
chmod +x $out/bin/actual-server
'';
}

View File

@ -0,0 +1,47 @@
diff --git a/src/load-config.js b/src/load-config.js
index d3cc5dd..cfcad8a 100644
--- a/src/load-config.js
+++ b/src/load-config.js
@@ -3,7 +3,8 @@ import path from 'node:path';
import { fileURLToPath } from 'node:url';
import createDebug from 'debug';
-const debug = createDebug('actual:config');
+// const debug = createDebug('actual:config');
+const debug = console.log;
const debugSensitive = createDebug('actual-sensitive:config');
const projectRoot = path.dirname(path.dirname(fileURLToPath(import.meta.url)));
@@ -90,6 +91,7 @@ const finalConfig = {
serverFiles: process.env.ACTUAL_SERVER_FILES || config.serverFiles,
userFiles: process.env.ACTUAL_USER_FILES || config.userFiles,
webRoot: process.env.ACTUAL_WEB_ROOT || config.webRoot,
+ dataDir: process.env.ACTUAL_DATA_DIR || config.dataDir,
https:
process.env.ACTUAL_HTTPS_KEY && process.env.ACTUAL_HTTPS_CERT
? {
diff --git a/src/migrations.js b/src/migrations.js
index 964e1f2..3a341d7 100644
--- a/src/migrations.js
+++ b/src/migrations.js
@@ -1,6 +1,12 @@
import migrate from 'migrate';
import path from 'node:path';
import config from './load-config.js';
+import { fileURLToPath } from 'url';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+const appRoot = path.dirname(__dirname);
+const migrationsDirectory = path.join(appRoot, "migrations");
export default function run(direction = 'up') {
console.log(
@@ -13,6 +19,7 @@ export default function run(direction = 'up') {
stateStore: `${path.join(config.dataDir, '.migrate')}${
config.mode === 'test' ? '-test' : ''
}`,
+ migrationsDirectory,
},
(err, set) => {
if (err) {

8821
overlays/actualbudget/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -2,4 +2,5 @@ final: prev:
{ {
libedgetpu = prev.callPackage ./libedgetpu { }; libedgetpu = prev.callPackage ./libedgetpu { };
actual-server = prev.callPackage ./actualbudget { };
} }