681 lines
20 KiB
Nix
681 lines
20 KiB
Nix
{
|
|
description = "Materia";
|
|
|
|
inputs = {
|
|
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
|
dream2nix = {
|
|
url = "github:nix-community/dream2nix";
|
|
inputs.nixpkgs.follows = "nixpkgs";
|
|
};
|
|
bonfire.url = "github:L-Nafaryus/bonfire";
|
|
nix-std.url = "github:chessai/nix-std";
|
|
};
|
|
|
|
outputs = {
|
|
self,
|
|
nixpkgs,
|
|
dream2nix,
|
|
bonfire,
|
|
nix-std,
|
|
...
|
|
}: let
|
|
system = "x86_64-linux";
|
|
pkgs = import nixpkgs {inherit system;};
|
|
bonLib = bonfire.lib;
|
|
|
|
dreamBuildPackage = {
|
|
module,
|
|
meta ? {},
|
|
extraModules ? [],
|
|
extraArgs ? {},
|
|
}:
|
|
(
|
|
nixpkgs.lib.evalModules {
|
|
modules = [module] ++ extraModules;
|
|
specialArgs =
|
|
{
|
|
inherit dream2nix;
|
|
packageSets.nixpkgs = pkgs;
|
|
}
|
|
// extraArgs;
|
|
}
|
|
)
|
|
.config
|
|
.public
|
|
// {inherit meta;};
|
|
in {
|
|
packages.x86_64-linux = {
|
|
materia-frontend-vue = dreamBuildPackage {
|
|
module = {
|
|
lib,
|
|
config,
|
|
dream2nix,
|
|
...
|
|
}: {
|
|
name = "materia-frontend-vue";
|
|
version = "0.1.1";
|
|
|
|
imports = [
|
|
dream2nix.modules.dream2nix.WIP-nodejs-builder-v3
|
|
];
|
|
|
|
mkDerivation = {
|
|
src = ./packages/frontend;
|
|
};
|
|
|
|
deps = {nixpkgs, ...}: {
|
|
inherit
|
|
(nixpkgs)
|
|
fetchFromGitHub
|
|
stdenv
|
|
;
|
|
};
|
|
|
|
WIP-nodejs-builder-v3 = {
|
|
packageLockFile = "${config.mkDerivation.src}/package-lock.json";
|
|
};
|
|
};
|
|
meta = with nixpkgs.lib; {
|
|
description = "Materia is a simple and fast cloud storage (vue)";
|
|
homepage = "https://materia.elnafo.ru";
|
|
license = licenses.mit;
|
|
maintainers = with bonLib.maintainers; [L-Nafaryus];
|
|
broken = false;
|
|
};
|
|
};
|
|
|
|
materia-frontend = dreamBuildPackage {
|
|
extraArgs = {
|
|
inherit (self.packages.x86_64-linux) materia-frontend-vue;
|
|
};
|
|
module = {
|
|
config,
|
|
lib,
|
|
dream2nix,
|
|
materia-frontend-vue,
|
|
...
|
|
}: {
|
|
imports = [dream2nix.modules.dream2nix.WIP-python-pdm];
|
|
|
|
pdm.lockfile = ./pdm.lock;
|
|
pdm.pyproject = ./packages/frontend/pyproject.toml;
|
|
|
|
deps = _: {
|
|
python = pkgs.python312;
|
|
};
|
|
|
|
mkDerivation = {
|
|
src = ./packages/frontend;
|
|
buildInputs = [
|
|
pkgs.python312.pkgs.pdm-backend
|
|
];
|
|
configurePhase = ''
|
|
mkdir -p target/materia_frontend
|
|
cp -rv ${materia-frontend-vue}/dist/* ./target/materia_frontend/
|
|
cp -rv templates ./target/materia_frontend/
|
|
touch target/materia_frontend/__init__.py
|
|
'';
|
|
};
|
|
};
|
|
meta = with nixpkgs.lib; {
|
|
description = "Materia is a simple and fast cloud storage (frontend)";
|
|
homepage = "https://materia.elnafo.ru";
|
|
license = licenses.mit;
|
|
maintainers = with bonLib.maintainers; [L-Nafaryus];
|
|
broken = false;
|
|
};
|
|
};
|
|
|
|
materia-server = pkgs.callPackage ({
|
|
withFrontend ? true,
|
|
withDocs ? true,
|
|
...
|
|
}:
|
|
dreamBuildPackage {
|
|
extraArgs = {
|
|
inherit (self.packages.x86_64-linux) materia-frontend materia-docs;
|
|
};
|
|
module = {
|
|
config,
|
|
lib,
|
|
dream2nix,
|
|
materia-frontend,
|
|
materia-docs,
|
|
...
|
|
}: {
|
|
imports = [dream2nix.modules.dream2nix.WIP-python-pdm];
|
|
|
|
pdm.lockfile = ./pdm.lock;
|
|
pdm.pyproject = ./packages/server/pyproject.toml;
|
|
|
|
deps = _: {
|
|
python = pkgs.python312;
|
|
};
|
|
|
|
mkDerivation = {
|
|
src = ./packages/server;
|
|
buildInputs = [
|
|
pkgs.python312.pkgs.pdm-backend
|
|
];
|
|
nativeBuildInputs = [
|
|
pkgs.python312.pkgs.wrapPython
|
|
];
|
|
propagatedBuildInputs =
|
|
lib.optionals withFrontend [
|
|
materia-frontend
|
|
]
|
|
++ lib.optionals withDocs [materia-docs];
|
|
};
|
|
};
|
|
meta = with nixpkgs.lib; {
|
|
description = "Materia is a simple and fast cloud storage";
|
|
homepage = "https://materia.elnafo.ru";
|
|
license = licenses.mit;
|
|
maintainers = with bonLib.maintainers; [L-Nafaryus];
|
|
broken = false;
|
|
mainProgram = "materia";
|
|
};
|
|
}) {};
|
|
|
|
materia-docs = dreamBuildPackage {
|
|
extraArgs = {
|
|
materia-server = self.packages.x86_64-linux.materia-server.override {
|
|
withFrontend = false;
|
|
withDocs = false;
|
|
};
|
|
};
|
|
module = {
|
|
config,
|
|
lib,
|
|
dream2nix,
|
|
materia-server,
|
|
...
|
|
}: {
|
|
imports = [dream2nix.modules.dream2nix.WIP-python-pdm];
|
|
|
|
pdm.lockfile = ./pdm.lock;
|
|
pdm.pyproject = ./packages/docs/pyproject.toml;
|
|
|
|
deps = _: {
|
|
python = pkgs.python312;
|
|
};
|
|
|
|
mkDerivation = {
|
|
src = ./packages/docs;
|
|
buildInputs = [
|
|
pkgs.python312.pkgs.pdm-backend
|
|
];
|
|
nativeBuildInputs = [pkgs.mkdocs materia-server];
|
|
configurePhase = ''
|
|
mkdir -p target/materia_docs
|
|
mkdocs build
|
|
touch target/materia_docs/__init__.py
|
|
'';
|
|
};
|
|
};
|
|
meta = with nixpkgs.lib; {
|
|
description = "Materia is a simple and fast cloud storage (docs)";
|
|
homepage = "https://materia.elnafo.ru";
|
|
license = licenses.mit;
|
|
maintainers = with bonLib.maintainers; [L-Nafaryus];
|
|
broken = false;
|
|
};
|
|
};
|
|
|
|
postgresql-devel = bonfire.packages.x86_64-linux.postgresql;
|
|
|
|
redis-devel = bonfire.packages.x86_64-linux.redis;
|
|
|
|
materia-devel = let
|
|
user = "materia";
|
|
dataDir = "/var/lib/materia";
|
|
entryPoint = pkgs.writeTextDir "entrypoint.sh" ''
|
|
materia start
|
|
'';
|
|
in
|
|
pkgs.dockerTools.buildImage {
|
|
name = "materia";
|
|
tag = "latest";
|
|
|
|
copyToRoot = pkgs.buildEnv {
|
|
name = "image-root";
|
|
pathsToLink = ["/bin" "/etc" "/"];
|
|
paths = with pkgs; [
|
|
bash
|
|
self.packages.x86_64-linux.materia-server
|
|
entryPoint
|
|
];
|
|
};
|
|
runAsRoot = with pkgs; ''
|
|
#!${runtimeShell}
|
|
${dockerTools.shadowSetup}
|
|
groupadd -r ${user}
|
|
useradd -r -g ${user} --home-dir=${dataDir} ${user}
|
|
mkdir -p ${dataDir}
|
|
chown -R ${user}:${user} ${dataDir}
|
|
'';
|
|
|
|
config = {
|
|
Entrypoint = ["bash" "/entrypoint.sh"];
|
|
StopSignal = "SIGINT";
|
|
User = "${user}:${user}";
|
|
WorkingDir = dataDir;
|
|
ExposedPorts = {
|
|
"54601/tcp" = {};
|
|
};
|
|
Env = [
|
|
"MATERIA_APPLICATION__WORKING_DIRECTORY=${dataDir}"
|
|
];
|
|
};
|
|
};
|
|
};
|
|
|
|
devShells.x86_64-linux.default = pkgs.mkShell {
|
|
buildInputs = with pkgs; [postgresql redis pdm nodejs python312];
|
|
# greenlet requires libstdc++
|
|
LD_LIBRARY_PATH = nixpkgs.lib.makeLibraryPath [pkgs.stdenv.cc.cc];
|
|
};
|
|
|
|
nixosModules = rec {
|
|
materia = {
|
|
config,
|
|
lib,
|
|
pkgs,
|
|
...
|
|
}:
|
|
with lib; let
|
|
cfg = config.services.materia;
|
|
in {
|
|
options.services.materia = {
|
|
enable = mkEnableOption "Enables the Materia service";
|
|
|
|
package = mkOption {
|
|
type = types.package;
|
|
default = self.packages.x86_64-linux.materia-server;
|
|
description = "The package to use.";
|
|
};
|
|
|
|
application = mkOption {
|
|
type = types.submodule {
|
|
options = {
|
|
user = mkOption {
|
|
type = types.str;
|
|
};
|
|
group = mkOption {
|
|
type = types.str;
|
|
};
|
|
mode = mkOption {
|
|
type = types.str;
|
|
};
|
|
working_directory = mkOption {
|
|
type = types.path;
|
|
default = "/var/lib/materia";
|
|
};
|
|
};
|
|
};
|
|
default = {
|
|
user = "materia";
|
|
group = "materia";
|
|
mode = "production";
|
|
working_directory = "/var/lib/materia";
|
|
};
|
|
};
|
|
|
|
server = mkOption {
|
|
type = types.submodule {
|
|
options = {
|
|
scheme = mkOption {
|
|
type = types.str;
|
|
};
|
|
address = mkOption {
|
|
type = types.str;
|
|
};
|
|
port = mkOption {
|
|
type = types.port;
|
|
};
|
|
domain = mkOption {
|
|
type = types.str;
|
|
};
|
|
};
|
|
};
|
|
default = {
|
|
scheme = "http";
|
|
address = "127.0.0.1";
|
|
port = 54601;
|
|
domain = "localhost";
|
|
};
|
|
};
|
|
|
|
database = mkOption {
|
|
type = types.submodule {
|
|
options = {
|
|
backend = mkOption {
|
|
type = types.str;
|
|
default = "postgresql";
|
|
};
|
|
scheme = mkOption {
|
|
type = types.str;
|
|
default = "postgresql+asyncpg";
|
|
};
|
|
address = mkOption {
|
|
type = types.str;
|
|
default = "127.0.0.1";
|
|
};
|
|
port = mkOption {
|
|
type = types.port;
|
|
default = 5432;
|
|
};
|
|
name = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = "materia";
|
|
};
|
|
user = mkOption {
|
|
type = types.str;
|
|
default = "materia";
|
|
};
|
|
password = mkOption {
|
|
type = types.nullOr (types.oneOf [types.str types.path]);
|
|
default = null;
|
|
};
|
|
};
|
|
};
|
|
default = {
|
|
backend = "postgresql";
|
|
scheme = "postgresql+asyncpg";
|
|
address = "127.0.0.1";
|
|
port = 5432;
|
|
name = "materia";
|
|
user = "materia";
|
|
password = null;
|
|
};
|
|
};
|
|
|
|
cache = mkOption {
|
|
type = types.submodule {
|
|
options = {
|
|
backend = mkOption {
|
|
type = types.str;
|
|
default = "redis";
|
|
};
|
|
scheme = mkOption {
|
|
type = types.str;
|
|
default = "redis";
|
|
};
|
|
address = mkOption {
|
|
type = types.str;
|
|
default = "127.0.0.1";
|
|
};
|
|
port = mkOption {
|
|
type = types.port;
|
|
default = 6379;
|
|
};
|
|
database = mkOption {
|
|
type = types.nullOr types.int;
|
|
default = 0;
|
|
};
|
|
user = mkOption {
|
|
type = types.str;
|
|
default = "materia";
|
|
};
|
|
password = mkOption {
|
|
type = types.nullOr (types.oneOf [types.str types.path]);
|
|
default = null;
|
|
};
|
|
};
|
|
};
|
|
default = {
|
|
backed = "redis";
|
|
scheme = "redis";
|
|
address = "127.0.0.1";
|
|
port = 6379;
|
|
database = 0;
|
|
user = "materia";
|
|
password = null;
|
|
};
|
|
};
|
|
|
|
security = mkOption {
|
|
type = types.submodule {
|
|
options = {
|
|
secret_key = mkOption {
|
|
type = types.nullOr (types.oneOf [types.str types.path]);
|
|
};
|
|
password_min_length = mkOption {
|
|
type = types.int;
|
|
};
|
|
password_hash_algo = mkOption {
|
|
type = types.nullOr types.str;
|
|
};
|
|
cookie_http_only = mkOption {
|
|
type = types.bool;
|
|
};
|
|
cookie_access_token_name = mkOption {
|
|
type = types.str;
|
|
};
|
|
cookie_refresh_token_name = mkOption {
|
|
type = types.str;
|
|
};
|
|
};
|
|
};
|
|
default = {
|
|
secret_key = null;
|
|
password_min_length = 8;
|
|
password_hash_algo = "bcrypt";
|
|
cookie_http_only = true;
|
|
cookie_access_token_name = "materia_at";
|
|
cookie_refresh_token_name = "materia_rt";
|
|
};
|
|
};
|
|
|
|
oauth2 = mkOption {
|
|
type = types.submodule {
|
|
options = {
|
|
enabled = mkOption {
|
|
type = types.bool;
|
|
};
|
|
jwt_signing_algo = mkOption {
|
|
type = types.str;
|
|
};
|
|
jwt_singing_key = mkOption {
|
|
type = types.nullOr (types.oneOf [types.str types.path]);
|
|
};
|
|
jwt_secret = mkOption {
|
|
type = types.nullOr (types.oneOf [types.str types.path]);
|
|
};
|
|
access_token_lifetime = mkOption {
|
|
type = types.int;
|
|
};
|
|
refresh_token_lifetime = mkOption {
|
|
type = types.int;
|
|
};
|
|
};
|
|
};
|
|
default = {
|
|
enabled = true;
|
|
jwt_signing_algo = "HS256";
|
|
jwt_singing_key = null;
|
|
jwt_secret = "changeme";
|
|
access_token_lifetime = 3600;
|
|
refresh_token_lifetime = 730 * 60;
|
|
};
|
|
};
|
|
|
|
mailer = mkOption {
|
|
type = types.submodule {
|
|
options = {
|
|
enabled = mkOption {
|
|
type = types.bool;
|
|
default = false;
|
|
};
|
|
scheme = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
};
|
|
address = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
};
|
|
port = mkOption {
|
|
type = types.nullOr types.int;
|
|
default = null;
|
|
};
|
|
helo = mkOption {
|
|
type = types.bool;
|
|
default = true;
|
|
};
|
|
cert_file = mkOption {
|
|
type = types.nullOr types.path;
|
|
default = null;
|
|
};
|
|
key_file = mkOption {
|
|
type = types.nullOr types.path;
|
|
default = null;
|
|
};
|
|
sender = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
};
|
|
user = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
};
|
|
password = mkOption {
|
|
type = types.nullOr (types.oneOf [types.str types.path]);
|
|
default = null;
|
|
};
|
|
plain_text = mkOption {
|
|
type = types.bool;
|
|
default = false;
|
|
};
|
|
};
|
|
};
|
|
default = {};
|
|
};
|
|
|
|
cron = mkOption {
|
|
type = types.submodule {
|
|
options = {
|
|
workers_count = mkOption {
|
|
type = types.int;
|
|
};
|
|
};
|
|
};
|
|
default = {
|
|
workers_count = 1;
|
|
};
|
|
};
|
|
|
|
repository = mkOption {
|
|
type = types.submodule {
|
|
options = {
|
|
capacity = mkOption {
|
|
type = types.int;
|
|
};
|
|
};
|
|
};
|
|
default = {capacity = 5368709120;};
|
|
};
|
|
|
|
misc = mkOption {
|
|
type = types.submodule {
|
|
options = {
|
|
enable_client = mkOption {
|
|
type = types.bool;
|
|
};
|
|
enable_docs = mkOption {
|
|
type = types.bool;
|
|
};
|
|
enable_api_docs = mkOption {
|
|
type = types.bool;
|
|
};
|
|
};
|
|
};
|
|
default = {
|
|
enable_client = true;
|
|
enable_docs = true;
|
|
enable_api_docs = false;
|
|
};
|
|
};
|
|
};
|
|
|
|
config = mkIf cfg.enable {
|
|
users.users.materia = {
|
|
description = "Materia service user";
|
|
home = cfg.application.working_directory;
|
|
createHome = true;
|
|
isSystemUser = true;
|
|
group = "materia";
|
|
};
|
|
users.groups.materia = {};
|
|
|
|
systemd.services.materia = {
|
|
description = "Materia service";
|
|
wantedBy = ["multi-user.target"];
|
|
after = ["network.target"];
|
|
|
|
serviceConfig = {
|
|
Restart = "always";
|
|
ExecStart = "${lib.getExe cfg.package} start";
|
|
User = "materia";
|
|
WorkingDirectory = cfg.application.working_directory;
|
|
};
|
|
|
|
preStart = let
|
|
toTOML = nix-std.lib.serde.toTOML;
|
|
configFile = pkgs.writeText "config.toml" ''
|
|
${toTOML {inherit (cfg) application server database cache security oauth2 mailer cron repository misc;}}
|
|
'';
|
|
in ''
|
|
ln -sf ${configFile} ${cfg.application.working_directory}/config.toml
|
|
'';
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
nixosConfigurations.materia = nixpkgs.lib.nixosSystem {
|
|
system = "x86_64-linux";
|
|
modules = [
|
|
self.nixosModules.materia
|
|
({
|
|
pkgs,
|
|
config,
|
|
...
|
|
}: {
|
|
boot.isContainer = true;
|
|
|
|
networking.hostName = "materia";
|
|
networking.useDHCP = false;
|
|
|
|
services.redis.servers.materia = {
|
|
enable = true;
|
|
port = 6379;
|
|
databases = 1;
|
|
};
|
|
|
|
services.postgresql = {
|
|
enable = true;
|
|
enableTCPIP = true;
|
|
authentication = ''
|
|
host materia all 127.0.0.1/32 trust
|
|
'';
|
|
initialScript = pkgs.writeText "init" ''
|
|
CREATE ROLE materia WITH LOGIN PASSWORD 'test';
|
|
CREATE DATABASE materia OWNER materia;
|
|
'';
|
|
ensureDatabases = ["materia"];
|
|
};
|
|
|
|
services.materia = {
|
|
enable = true;
|
|
cache.port = config.services.redis.servers.materia.port;
|
|
database.password = "test";
|
|
};
|
|
|
|
system.stateVersion = "24.05";
|
|
})
|
|
];
|
|
};
|
|
};
|
|
}
|