diff options
| -rw-r--r-- | .envrc | 18 | ||||
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | flake.lock | 133 | ||||
| -rw-r--r-- | flake.nix | 79 | ||||
| -rw-r--r-- | module/default.nix | 140 | ||||
| -rw-r--r-- | treefmt.nix | 81 | ||||
| -rwxr-xr-x | update.sh | 15 |
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 |
