summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.envrc18
-rw-r--r--.gitignore1
-rw-r--r--flake.lock133
-rw-r--r--flake.nix79
-rw-r--r--module/default.nix140
-rw-r--r--treefmt.nix81
-rwxr-xr-xupdate.sh15
7 files changed, 467 insertions, 0 deletions
diff --git a/.envrc b/.envrc
new file mode 100644
index 0000000..cb4ff0a
--- /dev/null
+++ b/.envrc
@@ -0,0 +1,18 @@
+#!/usr/bin/env sh
+
+# rocie - An enterprise grocery management system
+#
+# Copyright (C) 2024 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+# Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+# This file is part of Rocie.
+#
+# You should have received a copy of the License along with this program.
+# If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
+
+use flake
+
+root="$(git rev-parse --show-toplevel)"
+
+PATH_add ./scripts
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..92b2793
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+.direnv
diff --git a/flake.lock b/flake.lock
new file mode 100644
index 0000000..0e1c398
--- /dev/null
+++ b/flake.lock
@@ -0,0 +1,133 @@
+{
+ "nodes": {
+ "crane": {
+ "locked": {
+ "lastModified": 1773857772,
+ "narHash": "sha256-5xsK26KRHf0WytBtsBnQYC/lTWDhQuT57HJ7SzuqZcM=",
+ "owner": "ipetkov",
+ "repo": "crane",
+ "rev": "b556d7bbae5ff86e378451511873dfd07e4504cd",
+ "type": "github"
+ },
+ "original": {
+ "owner": "ipetkov",
+ "repo": "crane",
+ "type": "github"
+ }
+ },
+ "nixpkgs": {
+ "locked": {
+ "lastModified": 1773907119,
+ "narHash": "sha256-xwDXh9uEMUbTQ3bcQEFRVLNVpYPKuzb9TcnDVbe45uQ=",
+ "owner": "NixOS",
+ "repo": "nixpkgs",
+ "rev": "3c0730b8b60607525c36af3e58226f2038077ae9",
+ "type": "github"
+ },
+ "original": {
+ "owner": "NixOS",
+ "ref": "nixos-unstable-small",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "rocie-mobile": {
+ "inputs": {
+ "crane": "crane",
+ "nixpkgs": [
+ "nixpkgs"
+ ],
+ "rust-overlay": "rust-overlay",
+ "treefmt-nix": [
+ "treefmt-nix"
+ ]
+ },
+ "locked": {
+ "dirtyRev": "f6a3fb9c4d8dd86f78c9f75a23c1ac35bf35d4eb-dirty",
+ "dirtyShortRev": "f6a3fb9-dirty",
+ "lastModified": 1773902714,
+ "narHash": "sha256-90eMtdHW/J6Oigfha/a2vjMepGlna5va9gqP6SQYx04=",
+ "type": "git",
+ "url": "file:../rocie-mobile"
+ },
+ "original": {
+ "type": "git",
+ "url": "file:../rocie-mobile"
+ }
+ },
+ "rocie-server": {
+ "inputs": {
+ "nixpkgs": [
+ "nixpkgs"
+ ],
+ "treefmt-nix": [
+ "treefmt-nix"
+ ]
+ },
+ "locked": {
+ "lastModified": 1773896435,
+ "narHash": "sha256-WK8Nv8F9pfXHnNL1Tj3J/MvEEa28NZHKgK1r6xm2Wwc=",
+ "ref": "refs/heads/prime",
+ "rev": "15dfb099b13ad68b4f286fa9def77f083f79e1b2",
+ "revCount": 49,
+ "type": "git",
+ "url": "file:../rocie-server"
+ },
+ "original": {
+ "type": "git",
+ "url": "file:../rocie-server"
+ }
+ },
+ "root": {
+ "inputs": {
+ "nixpkgs": "nixpkgs",
+ "rocie-mobile": "rocie-mobile",
+ "rocie-server": "rocie-server",
+ "treefmt-nix": "treefmt-nix"
+ }
+ },
+ "rust-overlay": {
+ "inputs": {
+ "nixpkgs": [
+ "rocie-mobile",
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1773889863,
+ "narHash": "sha256-tSsmZOHBgq4qfu5MNCAEsKZL1cI4avNLw2oUTXWeb74=",
+ "owner": "oxalica",
+ "repo": "rust-overlay",
+ "rev": "dbfd51be2692cb7022e301d14c139accb4ee63f0",
+ "type": "github"
+ },
+ "original": {
+ "owner": "oxalica",
+ "repo": "rust-overlay",
+ "type": "github"
+ }
+ },
+ "treefmt-nix": {
+ "inputs": {
+ "nixpkgs": [
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1773297127,
+ "narHash": "sha256-6E/yhXP7Oy/NbXtf1ktzmU8SdVqJQ09HC/48ebEGBpk=",
+ "owner": "numtide",
+ "repo": "treefmt-nix",
+ "rev": "71b125cd05fbfd78cab3e070b73544abe24c5016",
+ "type": "github"
+ },
+ "original": {
+ "owner": "numtide",
+ "repo": "treefmt-nix",
+ "type": "github"
+ }
+ }
+ },
+ "root": "root",
+ "version": 7
+}
diff --git a/flake.nix b/flake.nix
new file mode 100644
index 0000000..b793868
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,79 @@
+# rocie - An enterprise grocery management system
+#
+# Copyright (C) 2024 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+# Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+# This file is part of Rocie.
+#
+# You should have received a copy of the License along with this program.
+# If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
+{
+ description = "rocie";
+
+ inputs = {
+ nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable-small";
+
+ rocie-mobile = {
+ url = "git+file:../rocie-mobile";
+ inputs = {
+ nixpkgs.follows = "nixpkgs";
+ treefmt-nix.follows = "treefmt-nix";
+ };
+ };
+ rocie-server = {
+ url = "git+file:../rocie-server";
+ inputs = {
+ nixpkgs.follows = "nixpkgs";
+ treefmt-nix.follows = "treefmt-nix";
+ };
+ };
+
+ treefmt-nix = {
+ url = "github:numtide/treefmt-nix";
+ inputs = {
+ nixpkgs.follows = "nixpkgs";
+ };
+ };
+ };
+
+ outputs = {
+ self,
+ nixpkgs,
+ treefmt-nix,
+ rocie-mobile,
+ rocie-server,
+ }: let
+ system = "x86_64-linux";
+ pkgs = nixpkgs.legacyPackages."${system}";
+ inherit (pkgs) lib;
+
+ treefmtEval = import ./treefmt.nix {inherit treefmt-nix pkgs;};
+
+ module = import ./module {
+ rocie-mobile =
+ rocie-mobile.outputs.packages."${system}".rocie;
+ rocie-server =
+ rocie-server.outputs.packages."${system}".rocie;
+ };
+ in {
+ checks."${system}" = {
+ formatting = treefmtEval.config.build.check self;
+ };
+
+ nixosModules = {
+ default = module;
+ };
+
+ formatter."${system}" = treefmtEval.config.build.wrapper;
+
+ devShells."${system}".default = pkgs.mkShell {
+ packages = [
+ # Releng
+ pkgs.git-bug
+ pkgs.reuse
+ pkgs.cocogitto
+ ];
+ };
+ };
+}
diff --git a/module/default.nix b/module/default.nix
new file mode 100644
index 0000000..608559b
--- /dev/null
+++ b/module/default.nix
@@ -0,0 +1,140 @@
+{
+ rocie-mobile,
+ rocie-server,
+}: {
+ lib,
+ config,
+ ...
+}: let
+ cfg = config.rocie;
+in {
+ options.rocie = {
+ enable = lib.mkEnableOption "rocie";
+ domain = lib.mkOption {
+ description = "Under which domain (vhost) to deploy rocie?";
+ type = lib.types.str;
+ };
+
+ port = lib.mkOption {
+ description = "Which port to use";
+ type = lib.types.int.port;
+ default = 8543;
+ };
+ address = lib.mkOption {
+ description = "Which address to use";
+ type = lib.types.str;
+ default = "127.0.0.1";
+ };
+
+ dbPath = lib.mkOption {
+ description = "Where to store the database";
+ type = lib.types.str;
+ default = "$STATE_DIRECTORY/storage.db";
+ };
+
+ secretKeyFile = lib.mkOption {
+ description = "Which file to use as signing key for user log-ins";
+ type = lib.types.nullOr lib.types.str;
+ };
+
+ webFrontEnd = lib.mkOption {
+ description = "Which package to use for the web front end";
+ type = lib.types.package;
+ default = rocie-mobile;
+ };
+ server = lib.mkOption {
+ description = "Which package to use for the server";
+ type = lib.types.package;
+ default = rocie-server;
+ };
+ };
+
+ config = lib.mkIf cfg.enable {
+ systemd.packages = [cfg.server];
+ systemd.services.rocie = {
+ wantedBy = ["default.target"];
+ serviceConfig =
+ {
+ StateDirectory = "rocie";
+
+ # Hardening
+ LockPersonality = true;
+ MemoryDenyWriteExecute = true;
+ NoNewPrivileges = true;
+ PrivateDevices = true;
+ PrivateIPC = true;
+ PrivateTmp = true;
+ ProcSubset = "pid";
+ ProtectClock = true;
+ ProtectControlGroups = true;
+ ProtectHome = true;
+ ProtectHostname = true;
+ ProtectKernelLogs = true;
+ ProtectKernelModules = true;
+ ProtectKernelTunables = true;
+ ProtectProc = "invisible";
+ ProtectSystem = "full";
+ RemoveIPC = true;
+ RestrictAddressFamilies = [
+ "AF_INET"
+ "AF_INET6"
+ ];
+ RestrictNamespaces = true;
+ RestrictRealtime = true;
+ RestrictSUIDSGID = true;
+ SystemCallArchitectures = "native";
+ SystemCallFilter = [
+ "~@mount"
+ "~@swap"
+ "~@resources"
+ "~@reboot"
+ "~@raw-io"
+ "~@obsolete"
+ "~@module"
+ "~@debug"
+ "~@cpu-emulation"
+ "~@clock"
+ "~@privileged"
+ ];
+ UMask = "0027";
+
+ ExecStart = [
+ ""
+ "${lib.getExe cfg.server} \
+ serve \
+ --port ${cfg.port} \
+ ${lib.strings.optionalString (cfg.secretKeyFile != null) "--secret-key-file ${cfg.secretKeyFile}"} \
+ --host ${cfg.address} \
+ --db-path ${cfg.dbPath}"
+ ];
+ }
+ // (
+ if (cfg.port < 1024)
+ then {
+ AmbientCapabilities = ["CAP_NET_BIND_SERVICE"];
+ CapabilityBoundingSet = ["CAP_NET_BIND_SERVICE"];
+ }
+ else {
+ # A private user cannot have process capabilities on the host's user
+ # namespace and thus CAP_NET_BIND_SERVICE has no effect.
+ PrivateUsers = true;
+ CapabilityBoundingSet = false;
+ }
+ );
+ };
+
+ services.nginx.virtualHosts."${cfg.domain}" = {
+ locations."/api" = {
+ proxyPass = "http://127.0.0.1:${cfg.port}";
+
+ recommendedProxySettings = true;
+ proxyWebsockets = true;
+ };
+
+ root = "${cfg.webFrontEnd}";
+
+ enableACME = true;
+ forceSSL = true;
+ };
+ };
+}
diff --git a/treefmt.nix b/treefmt.nix
new file mode 100644
index 0000000..8f78ebb
--- /dev/null
+++ b/treefmt.nix
@@ -0,0 +1,81 @@
+# rocie - An enterprise grocery management system
+#
+# Copyright (C) 2024 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+# Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+# This file is part of Rocie.
+#
+# You should have received a copy of the License along with this program.
+# If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
+
+{
+ treefmt-nix,
+ pkgs,
+}:
+treefmt-nix.lib.evalModule pkgs (
+ {pkgs, ...}: {
+ # Used to find the project root
+ projectRootFile = "flake.nix";
+
+ programs = {
+ alejandra.enable = true;
+ rustfmt.enable = true;
+ clang-format.enable = true;
+ mdformat.enable = true;
+ shfmt = {
+ enable = true;
+ indent_size = 4;
+ };
+ shellcheck.enable = true;
+ prettier = {
+ enable = true;
+ settings = {
+ arrowParens = "always";
+ bracketSameLine = false;
+ bracketSpacing = true;
+ editorconfig = true;
+ embeddedLanguageFormatting = "auto";
+ endOfLine = "lf";
+ # experimentalTernaries = false;
+ htmlWhitespaceSensitivity = "css";
+ insertPragma = false;
+ jsxSingleQuote = true;
+ printWidth = 80;
+ proseWrap = "always";
+ quoteProps = "consistent";
+ requirePragma = false;
+ semi = true;
+ singleAttributePerLine = true;
+ singleQuote = false;
+ trailingComma = "all";
+ useTabs = false;
+ vueIndentScriptAndStyle = false;
+
+ tabWidth = 2;
+ };
+ };
+ stylua.enable = true;
+ ruff = {
+ enable = true;
+ format = true;
+ };
+ taplo.enable = true;
+ };
+
+ settings = {
+ global.excludes = [
+ "CHANGELOG.md"
+ "NEWS.md"
+ ];
+ formatter = {
+ clang-format = {
+ options = ["--style" "GNU"];
+ };
+ shfmt = {
+ includes = ["*.bash"];
+ };
+ };
+ };
+ }
+)
diff --git a/update.sh b/update.sh
new file mode 100755
index 0000000..f3598dd
--- /dev/null
+++ b/update.sh
@@ -0,0 +1,15 @@
+#!/usr/bin/env sh
+
+# rocie - An enterprise grocery management system
+#
+# Copyright (C) 2024 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+# Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+# This file is part of Rocie.
+#
+# You should have received a copy of the License along with this program.
+# If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
+
+nix flake update
+# vim: ft=sh