Home

mint @main - refs - log -
-
https://git.jolheiser.com/mint.git
Budget
tree log patch
nix Signed-off-by: jolheiser <git@jolheiser.com>
Signature
-----BEGIN SSH SIGNATURE----- U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgBTEvCQk6VqUAdN2RuH6bj1dNkY oOpbPWj+jw4ua1B1cAAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5 AAAAQHVSjU5xIQhta7i+qsmoD/PDFtGOxHguXw2gRpPbW/mpsfyGY9/5jIoKdbfd48l/Ka 2JBoCMhtUs9UV4w8KcDgI= -----END SSH SIGNATURE-----
jolheiser <git@jolheiser.com>
1 month ago
9 changed files, 248 additions(+), 12 deletions(-)
flake.lockflake.nixmint/settings.pynix/default.nixnix/module.nixnix/pkg.nixnix/vm.envnix/vm.nixpyproject.toml
M flake.lock -> flake.lock
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
diff --git a/flake.lock b/flake.lock
index 77321069de8933a2c744a5c58b47eb21088b7eab..1faf3b7e87fde6d9ff02fddb0feba8c3f634460a 100644
--- a/flake.lock
+++ b/flake.lock
@@ -2,11 +2,11 @@ {
   "nodes": {
     "nixpkgs": {
       "locked": {
-        "lastModified": 1757746433,
-        "narHash": "sha256-fEvTiU4s9lWgW7mYEU/1QUPirgkn+odUBTaindgiziY=",
+        "lastModified": 1758446476,
+        "narHash": "sha256-5rdAi7CTvM/kSs6fHe1bREIva5W3TbImsto+dxG4mBo=",
         "owner": "nixos",
         "repo": "nixpkgs",
-        "rev": "6d7ec06d6868ac6d94c371458fc2391ded9ff13d",
+        "rev": "a1f79a1770d05af18111fbbe2a3ab2c42c0f6cd0",
         "type": "github"
       },
       "original": {
M flake.nix -> flake.nix
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
diff --git a/flake.nix b/flake.nix
index 6cef4dfe06a2a10af296eb83f17114f6b7239e12..e51eb08156e5f0aecd982b3d7487a867f267d159 100644
--- a/flake.nix
+++ b/flake.nix
@@ -14,6 +14,7 @@       ];
       forAllSystems = f: nixpkgs.lib.genAttrs systems f;
     in
     {
+      packages = forAllSystems (system: import ./nix { pkgs = import nixpkgs { inherit system; }; });
       devShells = forAllSystems (
         system:
         let
@@ -34,6 +35,44 @@                 python-lsp-ruff
                 pylsp-rope
               ])
             ];
+          };
+        }
+      );
+      nixosModules.default = import ./nix/module.nix;
+      nixosConfigurations.vm = nixpkgs.lib.nixosSystem {
+        system = "x86_64-linux";
+        modules = [
+          ./nix/vm.nix
+          {
+            virtualisation.vmVariant.virtualisation = {
+              cores = 2;
+              memorySize = 2048;
+              graphics = false;
+              forwardPorts = [
+                {
+                  from = "host";
+                  host.port = 6468;
+                  guest.port = 6468;
+                }
+              ];
+            };
+            system.stateVersion = "23.11";
+          }
+        ];
+      };
+      apps = forAllSystems (
+        system:
+        let
+          pkgs = import nixpkgs { inherit system; };
+        in
+        {
+          vm = {
+            type = "app";
+            program = "${pkgs.writeShellScript "vm" ''
+              nixos-rebuild build-vm --flake .#vm
+              ./result/bin/run-nixos-vm
+              rm nixos.qcow2
+            ''}";
           };
         }
       );
M mint/settings.py -> mint/settings.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
diff --git a/mint/settings.py b/mint/settings.py
index 69fdc4ef6cb498d9d5cced5a9a333b5d95419e8f..a0f786dec3cd4b6c421952c79eba0afa50ca1df4 100644
--- a/mint/settings.py
+++ b/mint/settings.py
@@ -11,7 +11,7 @@ SECRET_KEY = env.str("SECRET_KEY")
 
 DEBUG = env.bool("DEBUG", False)
 
-ALLOWED_HOSTS = ["localhost", "dev.jolheiser.com"]
+ALLOWED_HOSTS = ["*"]
 
 INSTALLED_APPS = [
     "django.contrib.admin",
@@ -45,7 +45,7 @@         "OPTIONS": {
             "context_processors": [
                 "django.template.context_processors.request",
                 "django.contrib.auth.context_processors.auth",
-                "django.contrib.messages.context_processors.messages"
+                "django.contrib.messages.context_processors.messages",
             ],
         },
     },
@@ -85,20 +85,24 @@ SESSION_COOKIE_NAME = "mint_sessionid"
 SESSION_COOKIE_SECURE = not DEBUG
 
 discovery_url = env.str("OIDC_CONFIG_URL")
-resp = requests.get(discovery_url).json()
+resp: dict = {}
+if discovery_url:
+    resp = requests.get(discovery_url).json()
 
 OIDC_RP_CLIENT_ID = env.str("OIDC_CLIENT_ID")
 OIDC_RP_CLIENT_SECRET = env.str("OIDC_CLIENT_SECRET")
 OIDC_RP_SIGN_ALGO = "RS256"
-OIDC_OP_AUTHORIZATION_ENDPOINT = resp["authorization_endpoint"]
-OIDC_OP_USER_ENDPOINT = resp["userinfo_endpoint"]
-OIDC_OP_TOKEN_ENDPOINT = resp["token_endpoint"]
-OIDC_OP_JWKS_ENDPOINT = resp["jwks_uri"]
+OIDC_OP_AUTHORIZATION_ENDPOINT = resp.get("authorization_endpoint", "")
+OIDC_OP_USER_ENDPOINT = resp.get("userinfo_endpoint", "")
+OIDC_OP_TOKEN_ENDPOINT = resp.get("token_endpoint", "")
+OIDC_OP_JWKS_ENDPOINT = resp.get("jwks_uri", "")
 OIDC_RP_SCOPES = "openid email profile groups"
 
 if DEBUG:
     INTERNAL_IPS = ["127.0.0.1"]
-    TEMPLATES[0]["OPTIONS"]["context_processors"].append("django.template.context_processors.debug")
+    TEMPLATES[0]["OPTIONS"]["context_processors"].append(
+        "django.template.context_processors.debug"
+    )
     try:
         import debug_toolbar
 
I nix/default.nix
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
diff --git a/nix/default.nix b/nix/default.nix
new file mode 100644
index 0000000000000000000000000000000000000000..b3ed86732c83c49ef83f2fde5ca5fc6b3911ab39
--- /dev/null
+++ b/nix/default.nix
@@ -0,0 +1,10 @@
+{
+  pkgs ? import <nixpkgs> { },
+}:
+let
+  pkg = pkgs.callPackage ./pkg.nix { inherit pkgs; };
+in
+{
+  mint = pkg;
+  default = pkg;
+}
I nix/module.nix
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
diff --git a/nix/module.nix b/nix/module.nix
new file mode 100644
index 0000000000000000000000000000000000000000..f89011a6e7493034d04eb6ced6a5cb3a83c9ddef
--- /dev/null
+++ b/nix/module.nix
@@ -0,0 +1,108 @@
+{
+  pkgs,
+  lib,
+  config,
+  ...
+}:
+let
+  cfg = config.services.mint;
+  pkg = pkgs.callPackage ./pkg.nix { inherit pkgs; };
+in
+{
+  options =
+    let
+      inherit (lib) mkEnableOption mkOption types;
+    in
+    {
+      services.mint = {
+        enable = mkEnableOption "Enable mint";
+
+        package = mkOption {
+          type = types.package;
+          description = "mint package to use";
+          default = pkg;
+        };
+
+        address = mkOption {
+          type = types.str;
+          default = "localhost";
+          description = "Web interface address";
+        };
+
+        port = mkOption {
+          type = types.port;
+          default = 6468;
+          description = "Web interface port";
+        };
+
+        user = mkOption {
+          type = types.str;
+          default = "mint";
+          description = "User account under which mint runs";
+        };
+
+        group = mkOption {
+          type = types.str;
+          default = "mint";
+          description = "Group account under which mint runs";
+        };
+
+        database = mkOption {
+          type = types.str;
+          default = "/var/lib/mint/mint.sqlite3";
+          description = "Location for the SQLite3 database";
+        };
+
+        settings = mkOption {
+          type = types.attrs;
+          default = { };
+          description = "Non-secret environment settings";
+          example = {
+            DEBUG = true;
+          };
+        };
+
+        environmentFile = mkOption {
+          type = types.nullOr types.path;
+          default = null;
+          description = "File to use as systemd environmentfile, usually for secret settings";
+        };
+      };
+    };
+  config = lib.mkIf cfg.enable {
+    users.users."${cfg.user}" = {
+      home = "/var/lib/mint";
+      createHome = true;
+      group = "${cfg.group}";
+      isSystemUser = true;
+      isNormalUser = false;
+      description = "user for mint service";
+    };
+    users.groups."${cfg.group}" = { };
+
+    systemd.services.mint = {
+      enable = true;
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+      environment = {
+        PYTHONPATH = "${cfg.package.python.pkgs.makePythonPath cfg.package.propagatedBuildInputs}:${cfg.package}/lib/mint";
+        GUNICORN_CMD_ARGS = "--bind=${cfg.address}:${toString cfg.port}";
+        MINT_DATABASE = cfg.database;
+      } // (pkgs.lib.mapAttrs (_: toString) cfg.settings);
+      serviceConfig = {
+        User = cfg.user;
+        Group = cfg.group;
+        Restart = "always";
+        RestartSec = "15";
+        WorkingDirectory = "/var/lib/mint";
+        EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile;
+        ExecStart = ''
+          ${cfg.package.python.pkgs.gunicorn}/bin/gunicorn mint.wsgi
+        '';
+      };
+      preStart = ''
+        ${cfg.package}/bin/mint migrate
+      '';
+    };
+  };
+}
I nix/pkg.nix
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
diff --git a/nix/pkg.nix b/nix/pkg.nix
new file mode 100644
index 0000000000000000000000000000000000000000..14d336ea373cfa61e1ae5ea1bc8629f5171672d6
--- /dev/null
+++ b/nix/pkg.nix
@@ -0,0 +1,53 @@
+{
+  pkgs ? import <nixpkgs> { },
+}:
+let
+  name = "mint";
+  python = pkgs.python3Packages.python.override {
+    packageOverrides = self: super: {
+      django = super.django_5;
+    };
+  };
+in
+python.pkgs.buildPythonApplication rec {
+  pname = name;
+  version = "main";
+  pyproject = true;
+  src = pkgs.nix-gitignore.gitignoreSource [ ] (
+    builtins.path {
+      inherit name;
+      path = ../.;
+    }
+  );
+  build-system = [ python.pkgs.pdm-backend ];
+  nativeBuildInputs = [
+    pkgs.makeBinaryWrapper
+  ];
+  dependencies = with python.pkgs; [
+    gunicorn
+
+    setuptools
+    environs
+    requests
+
+    django
+    django-debug-toolbar
+    mozilla-django-oidc
+  ];
+  postInstall = ''
+    mkdir -p $out/lib
+    cp -r . $out/lib/mint
+    chmod +x $out/lib/mint/manage.py
+    makeWrapper $out/lib/mint/manage.py $out/bin/mint \
+      --prefix PYTHONPATH : ${passthru.pythonPath}:$out/${python.sitePackages}
+  '';
+  passthru = {
+    inherit python;
+    pythonPath = "${python.pkgs.makePythonPath dependencies}";
+  };
+  meta = {
+    description = "Budget tracking";
+    homepage = "https://git.jolheiser.com/mint";
+    mainProgram = "mint";
+  };
+}
I nix/vm.env
1
2
3
4
5
6
7
8
diff --git a/nix/vm.env b/nix/vm.env
new file mode 100644
index 0000000000000000000000000000000000000000..b54a247873cfa2359549b2bad2c1d9292d332e54
--- /dev/null
+++ b/nix/vm.env
@@ -0,0 +1,2 @@
+MINT_SECRET_KEY=super-secret-key-do-not-use-me
+MINT_OIDC_CLIENT_SECRET=
I nix/vm.nix
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
diff --git a/nix/vm.nix b/nix/vm.nix
new file mode 100644
index 0000000000000000000000000000000000000000..ca4bbf8b3d6c39ae735ae134ed1561a23007cae9
--- /dev/null
+++ b/nix/vm.nix
@@ -0,0 +1,13 @@
+{
+  imports = [ ./module.nix ];
+  services.getty.autologinUser = "root";
+  services.mint = {
+    enable = true;
+    address = "0.0.0.0";
+    settings = {
+      MINT_OIDC_CONFIG_URL = "";
+      MINT_OIDC_CLIENT_ID = "";
+    };
+    environmentFile = ./vm.env;
+  };
+}
M pyproject.toml -> pyproject.toml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
diff --git a/pyproject.toml b/pyproject.toml
index b2bf441100100928451755d597f909444a652afe..8b1ae04ce9fc9c9cb7472e5df0d6ec0afa75e1a6 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -9,5 +9,12 @@     "django>=5.2.6",
     "django-debug-toolbar>=6.0.0",
     "environs>=14.3.0",
     "mozilla-django-oidc>=4.0.1",
-    "requests>=2.32.5",
+    "requests>=2.32.4",
 ]
+[build-system]
+requires = ["pdm-backend"]
+build-backend = "pdm.backend"
+
+[tool.setuptools]
+packages = ["mint"]
+package-dir = {"mint" = "mint"}