Use upstream pykms and Actual Budget. Move Actual to s0. Add automated backups for Actual.
All checks were successful
Check Flake / check-flake (push) Successful in 1m37s
All checks were successful
Check Flake / check-flake (push) Successful in 1m37s
This commit is contained in:
parent
23c8076e4d
commit
1f9fbd87ac
@ -1,87 +1,16 @@
|
|||||||
# Starting point:
|
|
||||||
# https://github.com/aldoborrero/mynixpkgs/commit/c501c1e32dba8f4462dcecb57eee4b9e52038e27
|
|
||||||
|
|
||||||
{ config, pkgs, lib, ... }:
|
{ config, pkgs, lib, ... }:
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.services.actual-server;
|
cfg = config.services.actual;
|
||||||
stateDir = "/var/lib/${cfg.stateDirName}";
|
|
||||||
in
|
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 {
|
config = lib.mkIf cfg.enable {
|
||||||
systemd.services.actual-server = {
|
services.actual.settings = {
|
||||||
description = "Actual Server";
|
port = 25448;
|
||||||
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} = {
|
backup.group."actual-budget".paths = [
|
||||||
enableACME = true;
|
"/var/lib/actual"
|
||||||
forceSSL = true;
|
];
|
||||||
locations."/".proxyPass = "http://localhost:${toString cfg.port}";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -149,7 +149,4 @@
|
|||||||
# 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";
|
|
||||||
}
|
}
|
||||||
|
@ -222,6 +222,7 @@
|
|||||||
(mkVirtualHost "vacuum.s0.neet.dev" "http://192.168.1.125") # valetudo
|
(mkVirtualHost "vacuum.s0.neet.dev" "http://192.168.1.125") # valetudo
|
||||||
(mkVirtualHost "sandman.s0.neet.dev" "http://192.168.9.14:3000") # es
|
(mkVirtualHost "sandman.s0.neet.dev" "http://192.168.9.14:3000") # es
|
||||||
(mkVirtualHost "todo.s0.neet.dev" "http://localhost:${toString config.services.vikunja.port}")
|
(mkVirtualHost "todo.s0.neet.dev" "http://localhost:${toString config.services.vikunja.port}")
|
||||||
|
(mkVirtualHost "budget.s0.neet.dev" "http://localhost:${toString config.services.actual.settings.port}") # actual budget
|
||||||
];
|
];
|
||||||
|
|
||||||
tailscaleAuth = {
|
tailscaleAuth = {
|
||||||
@ -270,7 +271,6 @@
|
|||||||
openMinimalFirewall = true;
|
openMinimalFirewall = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
# TODO: setup backup
|
|
||||||
services.vikunja = {
|
services.vikunja = {
|
||||||
enable = true;
|
enable = true;
|
||||||
port = 61473;
|
port = 61473;
|
||||||
@ -284,5 +284,7 @@
|
|||||||
"/var/lib/vikunja"
|
"/var/lib/vikunja"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
services.actual.enable = true;
|
||||||
|
|
||||||
boot.binfmt.emulatedSystems = [ "aarch64-linux" "armv7l-linux" ];
|
boot.binfmt.emulatedSystems = [ "aarch64-linux" "armv7l-linux" ];
|
||||||
}
|
}
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
{ lib
|
|
||||||
, buildNpmPackage
|
|
||||||
, fetchFromGitHub
|
|
||||||
, python3
|
|
||||||
, nodejs
|
|
||||||
, runtimeShell
|
|
||||||
}:
|
|
||||||
buildNpmPackage rec {
|
|
||||||
pname = "actual-server";
|
|
||||||
version = "24.10.1";
|
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
|
||||||
owner = "actualbudget";
|
|
||||||
repo = pname;
|
|
||||||
rev = "refs/tags/v${version}";
|
|
||||||
hash = "sha256-VJAD+lNamwuYmiPJLXkum6piGi5zLOHBp8cUeZagb4s=";
|
|
||||||
};
|
|
||||||
|
|
||||||
npmDepsHash = "sha256-Z2e4+JMhI/keLerT0F4WYdLnXHRQCqL7NjNyA9SFEF8=";
|
|
||||||
|
|
||||||
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
|
|
||||||
'';
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
diff --git a/src/load-config.js b/src/load-config.js
|
|
||||||
index d99ce42..42d1351 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)));
|
|
||||||
@@ -108,6 +109,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 cba7db0..9983471 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,7 +19,7 @@ export default function run(direction = 'up') {
|
|
||||||
stateStore: `${path.join(config.dataDir, '.migrate')}${
|
|
||||||
config.mode === 'test' ? '-test' : ''
|
|
||||||
}`,
|
|
||||||
- migrationsDirectory: `${path.join(config.projectRoot, 'migrations')}`,
|
|
||||||
+ migrationsDirectory
|
|
||||||
},
|
|
||||||
(err, set) => {
|
|
||||||
if (err) {
|
|
8954
overlays/actualbudget/package-lock.json
generated
8954
overlays/actualbudget/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -4,10 +4,4 @@ final: prev:
|
|||||||
let
|
let
|
||||||
system = prev.system;
|
system = prev.system;
|
||||||
in
|
in
|
||||||
{
|
{ }
|
||||||
actual-server = prev.callPackage ./actualbudget { };
|
|
||||||
|
|
||||||
# Copied entire package from nixpkgs to downgrade to python 3.11 since 3.12 is broken.
|
|
||||||
# See: https://github.com/Py-KMS-Organization/py-kms/issues/117
|
|
||||||
pykms = prev.callPackage ./pykms.nix { };
|
|
||||||
}
|
|
||||||
|
@ -1,103 +0,0 @@
|
|||||||
{ lib
|
|
||||||
, fetchFromGitHub
|
|
||||||
, python311
|
|
||||||
, writeText
|
|
||||||
, writeShellScript
|
|
||||||
, sqlite
|
|
||||||
, nixosTests
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
pypkgs = python311.pkgs;
|
|
||||||
|
|
||||||
dbSql = writeText "create_pykms_db.sql" ''
|
|
||||||
CREATE TABLE clients(
|
|
||||||
clientMachineId TEXT,
|
|
||||||
machineName TEXT,
|
|
||||||
applicationId TEXT,
|
|
||||||
skuId TEXT,
|
|
||||||
licenseStatus TEXT,
|
|
||||||
lastRequestTime INTEGER,
|
|
||||||
kmsEpid TEXT,
|
|
||||||
requestCount INTEGER
|
|
||||||
);
|
|
||||||
'';
|
|
||||||
|
|
||||||
dbScript = writeShellScript "create_pykms_db.sh" ''
|
|
||||||
set -eEuo pipefail
|
|
||||||
|
|
||||||
db=''${1:-/var/lib/pykms/clients.db}
|
|
||||||
|
|
||||||
if [ ! -e $db ] ; then
|
|
||||||
${lib.getBin sqlite}/bin/sqlite3 $db < ${dbSql}
|
|
||||||
fi
|
|
||||||
'';
|
|
||||||
|
|
||||||
in
|
|
||||||
pypkgs.buildPythonApplication rec {
|
|
||||||
pname = "pykms";
|
|
||||||
version = "unstable-2024-05-28";
|
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
|
||||||
owner = "Py-KMS-Organization";
|
|
||||||
repo = "py-kms";
|
|
||||||
rev = "646f4766f4195dbea0695700a7ddaac70a3294f9";
|
|
||||||
hash = "sha256-YCqPo7WkCfXyuTjL4IYapdcUN/Vj465Jz6XhQessyz0=";
|
|
||||||
};
|
|
||||||
|
|
||||||
sourceRoot = "${src.name}/py-kms";
|
|
||||||
|
|
||||||
propagatedBuildInputs = with pypkgs; [
|
|
||||||
systemd
|
|
||||||
pytz
|
|
||||||
tzlocal
|
|
||||||
dnspython
|
|
||||||
];
|
|
||||||
|
|
||||||
postPatch = ''
|
|
||||||
siteDir=$out/${python311.sitePackages}
|
|
||||||
|
|
||||||
substituteInPlace pykms_DB2Dict.py \
|
|
||||||
--replace "'KmsDataBase.xml'" "'$siteDir/KmsDataBase.xml'"
|
|
||||||
'';
|
|
||||||
|
|
||||||
format = "other";
|
|
||||||
|
|
||||||
# there are no tests
|
|
||||||
doCheck = false;
|
|
||||||
|
|
||||||
installPhase = ''
|
|
||||||
runHook preInstall
|
|
||||||
|
|
||||||
mkdir -p $siteDir
|
|
||||||
|
|
||||||
PYTHONPATH="$PYTHONPATH:$siteDir"
|
|
||||||
|
|
||||||
mv * $siteDir
|
|
||||||
for b in Client Server ; do
|
|
||||||
makeWrapper ${python311.interpreter} $out/bin/''${b,,} \
|
|
||||||
--argv0 pykms-''${b,,} \
|
|
||||||
--add-flags $siteDir/pykms_$b.py \
|
|
||||||
--set PYTHONPATH $PYTHONPATH
|
|
||||||
done
|
|
||||||
|
|
||||||
install -Dm755 ${dbScript} $out/libexec/create_pykms_db.sh
|
|
||||||
|
|
||||||
install -Dm644 ../README.md -t $out/share/doc/pykms
|
|
||||||
|
|
||||||
${python311.interpreter} -m compileall $siteDir
|
|
||||||
|
|
||||||
runHook postInstall
|
|
||||||
'';
|
|
||||||
|
|
||||||
passthru.tests = { inherit (nixosTests) pykms; };
|
|
||||||
|
|
||||||
meta = with lib; {
|
|
||||||
description = "Windows KMS (Key Management Service) server written in Python";
|
|
||||||
homepage = "https://github.com/Py-KMS-Organization/py-kms";
|
|
||||||
license = licenses.unlicense;
|
|
||||||
maintainers = with maintainers; [
|
|
||||||
peterhoeg
|
|
||||||
zopieux
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user