Compare commits
No commits in common. "ebf2035c54e04a19676fe3c4afb5e67d073b352e" and "56cf213e8a63f21846a3852b2fe3957cde46c33d" have entirely different histories.
ebf2035c54
...
56cf213e8a
31 changed files with 464 additions and 308 deletions
145
flake.lock
generated
145
flake.lock
generated
|
@ -35,11 +35,11 @@
|
|||
"nixpkgs": "nixpkgs_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1742042642,
|
||||
"narHash": "sha256-D0gP8srrX0qj+wNYNPdtVJsQuFzIng3q43thnHXQ/es=",
|
||||
"lastModified": 1737621947,
|
||||
"narHash": "sha256-8HFvG7fvIFbgtaYAY2628Tb89fA55nPm2jSiNs0/Cws=",
|
||||
"owner": "cachix",
|
||||
"repo": "cachix",
|
||||
"rev": "a624d3eaf4b1d225f918de8543ed739f2f574203",
|
||||
"rev": "f65a3cd5e339c223471e64c051434616e18cc4f5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -95,11 +95,11 @@
|
|||
"nixpkgs": "nixpkgs_4"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1743783972,
|
||||
"narHash": "sha256-5wPsNCnWmeLpLxavsftA9L7tnYgtlexV7FwLegxtpy4=",
|
||||
"lastModified": 1743521698,
|
||||
"narHash": "sha256-bvl7YmNZjGEZhyH86mGiJdhZGMaRot1TMM6cjwrwH6k=",
|
||||
"owner": "cachix",
|
||||
"repo": "devenv",
|
||||
"rev": "2f53e2f867e0c2ba18b880e66169366e5f8ca554",
|
||||
"rev": "4917f16d045f12d938d0a29fb1cbfb9e24ae6d0d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -211,11 +211,11 @@
|
|||
"nixpkgs-lib": "nixpkgs-lib"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1743550720,
|
||||
"narHash": "sha256-hIshGgKZCgWh6AYJpJmRgFdR3WUbkY04o82X05xqQiY=",
|
||||
"lastModified": 1741352980,
|
||||
"narHash": "sha256-+u2UunDA4Cl5Fci3m7S643HzKmIDAe+fiXrLqYsR2fs=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "c621e8422220273271f52058f618c94e405bb0f5",
|
||||
"rev": "f4330d22f1c5d2ba72d3d22df5597d123fdb60a9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -245,24 +245,6 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-parts_4": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": "nixpkgs-lib_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1743550720,
|
||||
"narHash": "sha256-hIshGgKZCgWh6AYJpJmRgFdR3WUbkY04o82X05xqQiY=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "c621e8422220273271f52058f618c94e405bb0f5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flatpak": {
|
||||
"locked": {
|
||||
"lastModified": 1739444422,
|
||||
|
@ -291,11 +273,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1742649964,
|
||||
"narHash": "sha256-DwOTp7nvfi8mRfuL1escHDXabVXFGT1VlPD1JHrtrco=",
|
||||
"lastModified": 1740849354,
|
||||
"narHash": "sha256-oy33+t09FraucSZ2rZ6qnD1Y1c8azKKmQuCvF2ytUko=",
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"rev": "dcf5072734cb576d2b0c59b2ac44f5050b5eac82",
|
||||
"rev": "4a709a8ce9f8c08fa7ddb86761fe488ff7858a07",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -424,25 +406,6 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"musicomp": {
|
||||
"inputs": {
|
||||
"flake-parts": "flake-parts_4",
|
||||
"nixpkgs": "nixpkgs_6"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1744068246,
|
||||
"narHash": "sha256-ZrLuwXT0uRxa4hyMyCe/IG9lKZEqAM+lUgLKcCiZjbA=",
|
||||
"ref": "refs/heads/main",
|
||||
"rev": "66aa356585132605e8bd9cc630fab7416f3caf3d",
|
||||
"revCount": 2,
|
||||
"type": "git",
|
||||
"url": "https://codeberg.org/helveticanonstandard/musicomp.git"
|
||||
},
|
||||
"original": {
|
||||
"type": "git",
|
||||
"url": "https://codeberg.org/helveticanonstandard/musicomp.git"
|
||||
}
|
||||
},
|
||||
"nix": {
|
||||
"inputs": {
|
||||
"flake-compat": [
|
||||
|
@ -483,11 +446,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1743911143,
|
||||
"narHash": "sha256-4j4JPwr0TXHH4ZyorXN5yIcmqIQr0WYacsuPA4ktONo=",
|
||||
"lastModified": 1743306489,
|
||||
"narHash": "sha256-LROaIjSLo347cwcHRfSpqzEOa2FoLSeJwU4dOrGm55E=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nix-index-database",
|
||||
"rev": "a36f6a7148aec2c77d78e4466215cceb2f5f4bfb",
|
||||
"rev": "b3696bfb6c24aa61428839a99e8b40c53ac3a82d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -499,16 +462,16 @@
|
|||
"nixos-cosmic": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat_3",
|
||||
"nixpkgs": "nixpkgs_7",
|
||||
"nixpkgs": "nixpkgs_6",
|
||||
"nixpkgs-stable": "nixpkgs-stable_2",
|
||||
"rust-overlay": "rust-overlay_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1744137608,
|
||||
"narHash": "sha256-KEuKL7lM2ZqKzvaGIptVDAce29CAR4ZSgWtFD3PnpB0=",
|
||||
"lastModified": 1743531084,
|
||||
"narHash": "sha256-IOfLnebyXv2v8srLwKOx7TSi2NhHrvqL5AtpDEGVhJ4=",
|
||||
"owner": "lilyinstarlight",
|
||||
"repo": "nixos-cosmic",
|
||||
"rev": "d20b15f629985fe6900925bef462f947e4a75b2f",
|
||||
"rev": "c231cbbfdd897b86efc9138a37ac302d5a29fb5d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -535,26 +498,11 @@
|
|||
},
|
||||
"nixpkgs-lib": {
|
||||
"locked": {
|
||||
"lastModified": 1743296961,
|
||||
"narHash": "sha256-b1EdN3cULCqtorQ4QeWgLMrd5ZGOjLSLemfa00heasc=",
|
||||
"lastModified": 1740877520,
|
||||
"narHash": "sha256-oiwv/ZK/2FhGxrCkQkB83i7GnWXPPLzoqFHpDD3uYpk=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"rev": "e4822aea2a6d1cdd36653c134cacfd64c97ff4fa",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-lib_2": {
|
||||
"locked": {
|
||||
"lastModified": 1743296961,
|
||||
"narHash": "sha256-b1EdN3cULCqtorQ4QeWgLMrd5ZGOjLSLemfa00heasc=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"rev": "e4822aea2a6d1cdd36653c134cacfd64c97ff4fa",
|
||||
"rev": "147dee35aab2193b174e4c0868bd80ead5ce755c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -581,11 +529,11 @@
|
|||
},
|
||||
"nixpkgs-stable_2": {
|
||||
"locked": {
|
||||
"lastModified": 1743975612,
|
||||
"narHash": "sha256-o4FjFOUmjSRMK7dn0TFdAT0RRWUWD+WsspPHa+qEQT8=",
|
||||
"lastModified": 1743367904,
|
||||
"narHash": "sha256-sOos1jZGKmT6xxPvxGQyPTApOunXvScV4lNjBCXd/CI=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "a880f49904d68b5e53338d1e8c7bf80f59903928",
|
||||
"rev": "7ffe0edc685f14b8c635e3d6591b0bbb97365e6c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -661,11 +609,11 @@
|
|||
},
|
||||
"nixpkgs_6": {
|
||||
"locked": {
|
||||
"lastModified": 1743964447,
|
||||
"narHash": "sha256-nEo1t3Q0F+0jQ36HJfbJtiRU4OI+/0jX/iITURKe3EE=",
|
||||
"lastModified": 1743315132,
|
||||
"narHash": "sha256-6hl6L/tRnwubHcA4pfUUtk542wn2Om+D4UnDhlDW9BE=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "063dece00c5a77e4a0ea24e5e5a5bd75232806f8",
|
||||
"rev": "52faf482a3889b7619003c0daec593a1912fddc1",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -677,27 +625,11 @@
|
|||
},
|
||||
"nixpkgs_7": {
|
||||
"locked": {
|
||||
"lastModified": 1743964447,
|
||||
"narHash": "sha256-nEo1t3Q0F+0jQ36HJfbJtiRU4OI+/0jX/iITURKe3EE=",
|
||||
"lastModified": 1743076231,
|
||||
"narHash": "sha256-yQugdVfi316qUfqzN8JMaA2vixl+45GxNm4oUfXlbgw=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "063dece00c5a77e4a0ea24e5e5a5bd75232806f8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_8": {
|
||||
"locked": {
|
||||
"lastModified": 1743689281,
|
||||
"narHash": "sha256-y7Hg5lwWhEOgflEHRfzSH96BOt26LaYfrYWzZ+VoVdg=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "2bfc080955153be0be56724be6fa5477b4eefabb",
|
||||
"rev": "6c5963357f3c1c840201eda129a99d455074db04",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -710,15 +642,15 @@
|
|||
"phps": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat_4",
|
||||
"nixpkgs": "nixpkgs_8",
|
||||
"nixpkgs": "nixpkgs_7",
|
||||
"utils": "utils"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1744001863,
|
||||
"narHash": "sha256-0pYw0Idtion++srUKsmGX7mq1weozdVE8gR+inoedUo=",
|
||||
"lastModified": 1743395855,
|
||||
"narHash": "sha256-1OZa0T1PSRTHqQG2eiMDiqJPB8XSseoe7bKUCkG5C0U=",
|
||||
"owner": "fossar",
|
||||
"repo": "nix-phps",
|
||||
"rev": "220ed74315dc7cd64a6181efd3d583a3607ef01f",
|
||||
"rev": "87aa57df1dffc535756256efbd141c735852145f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -763,7 +695,6 @@
|
|||
"flatpak": "flatpak",
|
||||
"hardware": "hardware",
|
||||
"lanzaboote": "lanzaboote",
|
||||
"musicomp": "musicomp",
|
||||
"nix-index-database": "nix-index-database",
|
||||
"nixos-cosmic": "nixos-cosmic",
|
||||
"nixpkgs": [
|
||||
|
@ -802,11 +733,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1744079607,
|
||||
"narHash": "sha256-5cog6Qd6w/bINdLO5mOysAHOHey8PwFXk4IWo+y+Czg=",
|
||||
"lastModified": 1743475035,
|
||||
"narHash": "sha256-uLjVsb4Rxnp1zmFdPCDmdODd4RY6ETOeRj0IkC0ij/4=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "f6b62cc99c25e79a1c17e9fca91dc6b6faebec6c",
|
||||
"rev": "bee11c51c2cda3ac57c9e0149d94b86cc1b00d13",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
url = "github:nix-community/nix-index-database";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
musicomp.url = "git+https://codeberg.org/helveticanonstandard/musicomp.git";
|
||||
};
|
||||
|
||||
nixConfig = {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
services.flatpak.packages = [
|
||||
"io.github.dweymouth.supersonic"
|
||||
"com.spotify.Client"
|
||||
];
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
users.users.futura = {
|
||||
description = "Futura";
|
||||
uid = 1001;
|
||||
isNormalUser = true;
|
||||
password = "futura";
|
||||
};
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
services.flatpak.packages = [
|
||||
"io.github.dweymouth.supersonic"
|
||||
"com.spotify.Client"
|
||||
];
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
services.flatpak.packages = [
|
||||
"io.github.dweymouth.supersonic"
|
||||
];
|
||||
}
|
|
@ -25,7 +25,6 @@
|
|||
xdebug.client_host = localhost
|
||||
'';
|
||||
|
||||
# Wrap all PHP versions with the extensions I need and bundle composer
|
||||
phps = lib.genAttrs supportedPhps (
|
||||
phpName: let
|
||||
phpBase = inputs.phps.packages.${pkgs.system}.${phpName};
|
||||
|
@ -48,6 +47,7 @@
|
|||
paths = [
|
||||
phpWithEnv
|
||||
phpWithEnv.packages.composer
|
||||
pkgs.symfony-cli
|
||||
];
|
||||
};
|
||||
in
|
||||
|
@ -55,32 +55,12 @@
|
|||
);
|
||||
|
||||
prefix = "/var/lib/phps";
|
||||
|
||||
# Tell Symfony's CLI where it can access the different PHP versions
|
||||
symfony-cli = let
|
||||
package = pkgs.symfony-cli;
|
||||
in
|
||||
pkgs.symlinkJoin {
|
||||
inherit (package) pname version meta;
|
||||
|
||||
paths = [package];
|
||||
|
||||
buildInputs = [pkgs.makeWrapper];
|
||||
|
||||
postBuild = ''
|
||||
wrapProgram $out/bin/${package.meta.mainProgram} \
|
||||
--suffix PATH : ${pkgs.lib.makeBinPath (
|
||||
builtins.attrValues phps
|
||||
)}
|
||||
'';
|
||||
};
|
||||
in {
|
||||
nix.settings = {
|
||||
substituters = ["https://fossar.cachix.org/"];
|
||||
trusted-public-keys = ["fossar.cachix.org-1:Zv6FuqIboeHPWQS7ysLCJ7UT7xExb4OE8c4LyGb5AsE="];
|
||||
};
|
||||
|
||||
# Link PHP installations so that PhpStorm knows about them
|
||||
systemd.tmpfiles.settings =
|
||||
builtins.mapAttrs (name: drv: {
|
||||
"${prefix}/${name}"."L+".argument = drv.outPath;
|
||||
|
@ -88,8 +68,6 @@ in {
|
|||
phps;
|
||||
|
||||
environment.systemPackages = [
|
||||
pkgs.jetbrains.phpstorm
|
||||
phps.${selectedPhp}
|
||||
symfony-cli
|
||||
phps.${selectedPhp}.packages.composer
|
||||
];
|
||||
}
|
5
hosts/headful/work/phpstorm.nix
Normal file
5
hosts/headful/work/phpstorm.nix
Normal file
|
@ -0,0 +1,5 @@
|
|||
{pkgs, ...}: {
|
||||
environment.systemPackages = [
|
||||
pkgs.jetbrains.phpstorm
|
||||
];
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
services = {
|
||||
desktopManager = {
|
||||
cosmic.enable = lib.mkForce false;
|
||||
plasma6.enable = true;
|
||||
};
|
||||
displayManager = {
|
||||
cosmic-greeter.enable = lib.mkForce false;
|
||||
sddm = {
|
||||
enable = true;
|
||||
wayland.enable = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
environment.systemPackages = [
|
||||
pkgs.kdePackages.sddm-kcm
|
||||
pkgs.kdePackages.discover
|
||||
pkgs.kdePackages.kate
|
||||
];
|
||||
|
||||
programs = {
|
||||
kdeconnect.enable = true;
|
||||
partition-manager.enable = true;
|
||||
};
|
||||
|
||||
xdg.portal = {
|
||||
xdgOpenUsePortal = true;
|
||||
extraPortals = [pkgs.xdg-desktop-portal-gtk];
|
||||
};
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
services.flatpak.packages = [
|
||||
"io.github.dweymouth.supersonic"
|
||||
"com.spotify.Client"
|
||||
];
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
{pkgs, ...}: {
|
||||
environment.systemPackages = [
|
||||
pkgs.gnumake
|
||||
pkgs.unzip
|
||||
pkgs.pv
|
||||
pkgs.jq
|
||||
pkgs.mariadb
|
||||
pkgs.openssl
|
||||
];
|
||||
}
|
|
@ -12,12 +12,6 @@
|
|||
paths = [
|
||||
config.services.vaultwarden.backupDir
|
||||
config.services.syncthing.dataDir
|
||||
config.services.forgejo.stateDir
|
||||
config.services.postgresqlBackup.location
|
||||
config.services.postgresqlBackup.location
|
||||
# TODO: Add stateDir options for these
|
||||
"/var/lib/headscale"
|
||||
"/var/lib/navidrome"
|
||||
];
|
||||
passwordFile = config.age.secrets."restic-${attrName}".path;
|
||||
pruneOpts = ["--keep-daily 7" "--keep-weekly 5" "--keep-monthly 12"];
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
# TODO: do this via tailscale?
|
||||
# {
|
||||
# config,
|
||||
# lib,
|
||||
# pkgs,
|
||||
# ...
|
||||
# }: let
|
||||
# virtualHostName = "syncserver.helveticanonstandard.net";
|
||||
# in {
|
||||
# age.secrets = lib.mkSecrets {syncserver = {};};
|
||||
#
|
||||
# services.firefox-syncserver = {
|
||||
# enable = true;
|
||||
# secrets = config.age.secrets.syncserver.path;
|
||||
# singleNode = {
|
||||
# enable = true;
|
||||
# hostname = virtualHostName;
|
||||
# url = "https://${virtualHostName}";
|
||||
# };
|
||||
# settings = {
|
||||
# port = 8070;
|
||||
# };
|
||||
# };
|
||||
#
|
||||
# services.nginx.virtualHosts.${config.services.firefox-syncserver.singleNode.hostname} = {
|
||||
# enableACME = true;
|
||||
# forceSSL = true;
|
||||
#
|
||||
# locations."/".proxyPass = let
|
||||
# host = "127.0.0.1";
|
||||
# port = builtins.toString config.services.firefox-syncserver.settings.port;
|
||||
# in "http://${host}:${port}";
|
||||
# };
|
||||
#
|
||||
# services.mysql.package = pkgs.mariadb;
|
||||
# }
|
||||
{}
|
|
@ -1,10 +1,9 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
virtualHostName = "forgejo.helveticanonstandard.net";
|
||||
virtualHostName = "tea.wrz.one";
|
||||
in {
|
||||
age.secrets = lib.mkSecrets {
|
||||
forgejo-mailer = {
|
||||
|
@ -47,30 +46,28 @@ in {
|
|||
USER = "lukas@wrz.one";
|
||||
};
|
||||
};
|
||||
|
||||
secrets.mailer.PASSWD = config.age.secrets.forgejo-mailer.path;
|
||||
};
|
||||
|
||||
systemd.services.forgejo.preStart = lib.getExe pkgs.writeShellApplication {
|
||||
name = "forgejo-init-admin";
|
||||
runtimeInputs = [
|
||||
config.services.forgejo.package
|
||||
];
|
||||
text = let
|
||||
passwordFile = config.age.secrets.forgejo-admin.path;
|
||||
in ''
|
||||
admins=$(admin user list --admin)
|
||||
admins=$((admins - 1))
|
||||
|
||||
if ((admins < 1)); then
|
||||
gitea admin user create \
|
||||
--admin \
|
||||
--email helvetica@helveticanonstandard.net \
|
||||
--username helvetica \
|
||||
--password "$(cat -- ${passwordFile})"
|
||||
fi
|
||||
'';
|
||||
};
|
||||
systemd.services.forgejo.preStart = let
|
||||
forgejo = lib.getExe config.services.forgejo.package;
|
||||
passwordFile = config.age.secrets.forgejo-admin.path;
|
||||
# TODO
|
||||
user = "lukas";
|
||||
email = "lukas@wrz.one";
|
||||
in ''
|
||||
if ! \
|
||||
${forgejo} admin user change-password \
|
||||
--username ${lib.escapeShellArg user} \
|
||||
--password "$(cat -- ${lib.escapeShellArg passwordFile})"
|
||||
then
|
||||
${forgejo} admin user create \
|
||||
--admin \
|
||||
--email ${lib.escapeShellArg email} \
|
||||
--username ${lib.escapeShellArg user} \
|
||||
--password "$(cat -- ${lib.escapeShellArg passwordFile})"
|
||||
fi
|
||||
'';
|
||||
|
||||
services.nginx.virtualHosts.${virtualHostName} = {
|
||||
enableACME = true;
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
# {pkgs, ...}: {
|
||||
# services.mysql.package = pkgs.mariadb;
|
||||
#
|
||||
# services.mysqlBackup = {
|
||||
# enable = true;
|
||||
# startAt = "*-*-* 02:00:00";
|
||||
# location = "/srv/backup/postgresql";
|
||||
# };
|
||||
# }
|
||||
{}
|
|
@ -1,23 +0,0 @@
|
|||
{config, ...}: let
|
||||
virtualHostName = "mealie.helveticanonstandard.net";
|
||||
in {
|
||||
services.mealie = {
|
||||
enable = true;
|
||||
settings = {
|
||||
BASE_URL = "https://${virtualHostName}";
|
||||
ALLOW_SIGNUP = false;
|
||||
};
|
||||
listenAddress = "127.0.0.1";
|
||||
port = 8040;
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts.${virtualHostName} = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
|
||||
locations."/".proxyPass = let
|
||||
host = config.services.mealie.listenAddress;
|
||||
port = builtins.toString config.services.mealie.port;
|
||||
in "http://${host}:${port}";
|
||||
};
|
||||
}
|
|
@ -7,7 +7,6 @@ in {
|
|||
Address = "localhost";
|
||||
Port = 8050;
|
||||
MusicFolder = "/srv/music";
|
||||
EnableSharing = true;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
services.postgresqlBackup = {
|
||||
enable = true;
|
||||
startAt = "*-*-* 02:00:00";
|
||||
location = "/srv/backup/postgresql";
|
||||
backupAll = true;
|
||||
};
|
||||
}
|
|
@ -1,14 +1,9 @@
|
|||
{
|
||||
inputs,
|
||||
self,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
imports = [
|
||||
inputs.musicomp.nixosModules.default
|
||||
];
|
||||
|
||||
services.musicomp.jobs.main = {
|
||||
music = "/srv/music";
|
||||
comp = "/srv/compmusic";
|
||||
|
|
116
modules/musicomp.nix
Normal file
116
modules/musicomp.nix
Normal file
|
@ -0,0 +1,116 @@
|
|||
{
|
||||
self,
|
||||
lib,
|
||||
pkgs,
|
||||
utils,
|
||||
config,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) types;
|
||||
inherit (utils.systemdUtils.unitOptions) unitOption;
|
||||
in {
|
||||
options.services.musicomp.jobs = lib.mkOption {
|
||||
description = ''
|
||||
Compression jobs to run with musicomp.
|
||||
'';
|
||||
default = {};
|
||||
type = types.attrsOf (types.submodule {
|
||||
options = {
|
||||
music = lib.mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
Source directory.
|
||||
'';
|
||||
example = "/srv/music";
|
||||
};
|
||||
|
||||
comp = lib.mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
Destination directory for compressed music.
|
||||
'';
|
||||
example = "/srv/comp";
|
||||
};
|
||||
|
||||
post = lib.mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
description = ''
|
||||
Shell commands that are run after compression has finished.
|
||||
'';
|
||||
};
|
||||
|
||||
workers = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 0;
|
||||
description = ''
|
||||
Number of workers.
|
||||
'';
|
||||
};
|
||||
|
||||
timerConfig = lib.mkOption {
|
||||
type = lib.types.nullOr (lib.types.attrsOf unitOption);
|
||||
default = {
|
||||
OnCalendar = "daily";
|
||||
Persistent = true;
|
||||
};
|
||||
description = ''
|
||||
When to run the job.
|
||||
'';
|
||||
};
|
||||
|
||||
package = lib.mkPackageOption self.packages.${pkgs.system} "musicomp" {};
|
||||
|
||||
inhibitsSleep = lib.mkOption {
|
||||
default = false;
|
||||
type = lib.types.bool;
|
||||
example = true;
|
||||
description = ''
|
||||
Prevents the system from sleeping while running the job.
|
||||
'';
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
config = {
|
||||
systemd.services =
|
||||
lib.mapAttrs'
|
||||
(
|
||||
name: job:
|
||||
lib.nameValuePair "musicomp-jobs-${name}" {
|
||||
wantedBy = ["multi-user.target"];
|
||||
restartIfChanged = false;
|
||||
|
||||
script = ''
|
||||
${lib.optionalString job.inhibitsSleep ''
|
||||
${lib.getExe' pkgs.systemd "systemd-inhibit"} \
|
||||
--mode block \
|
||||
--who musicomp \
|
||||
--what sleep \
|
||||
--why ${lib.escapeShellArg "Scheduled musicomp ${name}"}
|
||||
''}
|
||||
|
||||
${lib.getExe job.package} \
|
||||
${lib.optionalString (job.workers > 0) "--workers ${job.workers}"} \
|
||||
--verbose \
|
||||
-- ${job.music} ${job.comp}
|
||||
'';
|
||||
|
||||
postStart = job.post;
|
||||
|
||||
serviceConfig.Type = "oneshot";
|
||||
}
|
||||
)
|
||||
config.services.musicomp.jobs;
|
||||
|
||||
systemd.timers =
|
||||
lib.mapAttrs'
|
||||
(name: job:
|
||||
lib.nameValuePair "musicomp-jobs-${name}" {
|
||||
wantedBy = ["timers.target"];
|
||||
inherit (job) timerConfig;
|
||||
})
|
||||
(lib.filterAttrs (_: job: job.timerConfig != null) config.services.musicomp.jobs);
|
||||
};
|
||||
}
|
3
packages/musicomp/README.md
Normal file
3
packages/musicomp/README.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# musicomp
|
||||
|
||||
A music compression tool.
|
26
packages/musicomp/package.nix
Normal file
26
packages/musicomp/package.nix
Normal file
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
lib,
|
||||
python3Packages,
|
||||
opusTools,
|
||||
}:
|
||||
python3Packages.buildPythonApplication {
|
||||
pname = "musicomp";
|
||||
version = "0.1.0";
|
||||
|
||||
src = ./.;
|
||||
|
||||
pyproject = true;
|
||||
|
||||
doCheck = false;
|
||||
|
||||
build-system = [python3Packages.hatchling];
|
||||
|
||||
makeWrapperArgs = [
|
||||
"--prefix"
|
||||
"PATH"
|
||||
":"
|
||||
(lib.makeBinPath [opusTools])
|
||||
];
|
||||
|
||||
meta.mainProgram = "musicomp";
|
||||
}
|
17
packages/musicomp/pyproject.toml
Normal file
17
packages/musicomp/pyproject.toml
Normal file
|
@ -0,0 +1,17 @@
|
|||
[project]
|
||||
name = "musicomp"
|
||||
version = "0.1.0"
|
||||
description = "Music compression tool"
|
||||
authors = [{ name = "Lukas Wurzinger", email = "lukas@wrz.one" }]
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
|
||||
[build-system]
|
||||
requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
[project.scripts]
|
||||
musicomp = "musicomp.cli:main"
|
||||
|
||||
[tool.hatch.build.targets.wheel]
|
||||
packages = ["src/musicomp"]
|
3
packages/musicomp/src/musicomp/__main__.py
Normal file
3
packages/musicomp/src/musicomp/__main__.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
from .cli import main
|
||||
|
||||
main()
|
6
packages/musicomp/src/musicomp/clean.py
Normal file
6
packages/musicomp/src/musicomp/clean.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
from os import PathLike
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def clean(dst: str | PathLike[str]) -> None:
|
||||
Path(dst).unlink(missing_ok=True)
|
117
packages/musicomp/src/musicomp/cli.py
Normal file
117
packages/musicomp/src/musicomp/cli.py
Normal file
|
@ -0,0 +1,117 @@
|
|||
import sys
|
||||
from multiprocessing import Pool, cpu_count
|
||||
from argparse import ArgumentParser, ArgumentTypeError, Namespace
|
||||
from pathlib import Path
|
||||
from .todo import Todo
|
||||
|
||||
args = Namespace()
|
||||
|
||||
|
||||
def task(todo: Todo) -> None:
|
||||
todo.run()
|
||||
if args.verbose:
|
||||
print("finished", todo, file=sys.stderr)
|
||||
|
||||
|
||||
def main():
|
||||
def workers_type_func(value: object) -> int:
|
||||
try:
|
||||
value = int(value) # pyright: ignore[reportArgumentType]
|
||||
if value <= 0:
|
||||
raise ArgumentTypeError(f"{value} is not a positive integer")
|
||||
except ValueError:
|
||||
raise ArgumentTypeError(f"{value} is not an integer")
|
||||
|
||||
return value
|
||||
|
||||
parser = ArgumentParser()
|
||||
|
||||
_ = parser.add_argument(
|
||||
"-w",
|
||||
"--workers",
|
||||
default=cpu_count(),
|
||||
type=workers_type_func,
|
||||
help="amount of worker processes",
|
||||
)
|
||||
_ = parser.add_argument(
|
||||
"-i",
|
||||
"--interactive",
|
||||
action="store_true",
|
||||
help="prompt before running",
|
||||
)
|
||||
_ = parser.add_argument(
|
||||
"-k",
|
||||
"--keep",
|
||||
action="store_true",
|
||||
help="whether source files should be kept if both directories are the same",
|
||||
)
|
||||
_ = parser.add_argument(
|
||||
"-r",
|
||||
"--redo",
|
||||
action="store_true",
|
||||
help="whether everything should be re-encoded regardless of whether they have already been transcoded",
|
||||
)
|
||||
_ = parser.add_argument(
|
||||
"-v",
|
||||
"--verbose",
|
||||
action="count",
|
||||
default=0,
|
||||
help="verbose output",
|
||||
)
|
||||
|
||||
_ = parser.add_argument(
|
||||
"music",
|
||||
nargs=1,
|
||||
type=Path,
|
||||
help="the source directory",
|
||||
)
|
||||
_ = parser.add_argument(
|
||||
"comp",
|
||||
nargs=1,
|
||||
type=Path,
|
||||
help="the destination directory for compressed files",
|
||||
)
|
||||
|
||||
global args
|
||||
args = parser.parse_args(sys.argv[1:])
|
||||
|
||||
assert isinstance(args.workers, int) # pyright: ignore[reportAny]
|
||||
assert isinstance(args.interactive, bool) # pyright: ignore[reportAny]
|
||||
assert isinstance(args.keep, bool) # pyright: ignore[reportAny]
|
||||
assert isinstance(args.redo, bool) # pyright: ignore[reportAny]
|
||||
assert isinstance(args.verbose, int) # pyright: ignore[reportAny]
|
||||
assert isinstance(args.music, list) # pyright: ignore[reportAny]
|
||||
assert len(args.music) == 1 # pyright: ignore[reportUnknownMemberType, reportUnknownArgumentType]
|
||||
assert isinstance(args.music[0], Path) # pyright: ignore[reportUnknownMemberType]
|
||||
assert isinstance(args.comp, list) # pyright: ignore[reportAny]
|
||||
assert len(args.comp) == 1 # pyright: ignore[reportUnknownMemberType, reportUnknownArgumentType]
|
||||
assert isinstance(args.comp[0], Path) # pyright: ignore[reportUnknownMemberType]
|
||||
|
||||
src_dir = args.music[0] # pyright: ignore[reportUnknownMemberType]
|
||||
dst_dir = args.comp[0] # pyright: ignore[reportUnknownMemberType]
|
||||
|
||||
plan = list(
|
||||
Todo.plan(
|
||||
src_dir,
|
||||
dst_dir,
|
||||
replace=src_dir.samefile(dst_dir) and not args.keep,
|
||||
redo=args.redo,
|
||||
)
|
||||
)
|
||||
|
||||
if len(plan) == 0:
|
||||
print("Nothing to do", file=sys.stderr)
|
||||
sys.exit(0)
|
||||
|
||||
if args.verbose >= 1 or args.interactive:
|
||||
print("Plan:", file=sys.stderr)
|
||||
for todo in plan:
|
||||
print(todo, file=sys.stderr)
|
||||
|
||||
if args.interactive:
|
||||
result = input("Do you want to continue? [Y/n] ")
|
||||
if result.lower() not in ("", "y", "yes"):
|
||||
sys.exit(1)
|
||||
|
||||
with Pool(args.workers) as pool:
|
||||
_ = pool.map(task, plan)
|
6
packages/musicomp/src/musicomp/replace.py
Normal file
6
packages/musicomp/src/musicomp/replace.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
from os import PathLike
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def replace(src: str | PathLike[str]) -> None:
|
||||
Path(src).unlink(missing_ok=True)
|
68
packages/musicomp/src/musicomp/todo.py
Normal file
68
packages/musicomp/src/musicomp/todo.py
Normal file
|
@ -0,0 +1,68 @@
|
|||
from pathlib import Path
|
||||
from os import PathLike
|
||||
from enum import StrEnum
|
||||
from dataclasses import dataclass
|
||||
from typing import Self, override
|
||||
from collections.abc import Generator
|
||||
from .transcode import transcode as todo_transcode
|
||||
from .clean import clean as todo_clean
|
||||
from .replace import replace as todo_replace
|
||||
|
||||
SRC_SUFFIX = ".flac"
|
||||
DST_SUFFIX = ".opus"
|
||||
|
||||
|
||||
class TodoAct(StrEnum):
|
||||
TRANSCODE = "transcode"
|
||||
CLEAN = "clean"
|
||||
REPLACE = "replace"
|
||||
|
||||
|
||||
@dataclass
|
||||
class Todo:
|
||||
act: TodoAct
|
||||
src: str | PathLike[str]
|
||||
dst: str | PathLike[str]
|
||||
|
||||
@classmethod
|
||||
def plan(
|
||||
cls: type[Self],
|
||||
src_dir: str | PathLike[str],
|
||||
dst_dir: str | PathLike[str],
|
||||
replace: bool = False,
|
||||
redo: bool = False,
|
||||
) -> Generator[Self]:
|
||||
def list_files(dir: str | PathLike[str], suffix: str) -> list[Path]:
|
||||
files: list[Path] = []
|
||||
for f in Path(dir).rglob("*"):
|
||||
if f.is_file() and f.suffix == suffix:
|
||||
files.append(f)
|
||||
return files
|
||||
|
||||
src_files = list_files(src_dir, SRC_SUFFIX)
|
||||
dst_files = list_files(dst_dir, DST_SUFFIX)
|
||||
|
||||
for f in src_files:
|
||||
e = dst_dir / (f.relative_to(src_dir).with_suffix(DST_SUFFIX))
|
||||
if redo or e not in dst_files:
|
||||
yield cls(TodoAct.TRANSCODE, f, e)
|
||||
if replace:
|
||||
yield cls(TodoAct.REPLACE, f, e)
|
||||
|
||||
for f in dst_files:
|
||||
e = src_dir / (f.relative_to(dst_dir).with_suffix(SRC_SUFFIX))
|
||||
if e not in src_files:
|
||||
yield cls(TodoAct.CLEAN, f, e)
|
||||
|
||||
def run(self) -> None:
|
||||
match self.act:
|
||||
case TodoAct.TRANSCODE:
|
||||
todo_transcode(self.src, self.dst)
|
||||
case TodoAct.CLEAN:
|
||||
todo_clean(self.dst)
|
||||
case TodoAct.REPLACE:
|
||||
todo_replace(self.src)
|
||||
|
||||
@override
|
||||
def __str__(self) -> str:
|
||||
return f"{self.act} {self.src} -> {self.dst}"
|
34
packages/musicomp/src/musicomp/transcode.py
Normal file
34
packages/musicomp/src/musicomp/transcode.py
Normal file
|
@ -0,0 +1,34 @@
|
|||
from pathlib import Path
|
||||
from subprocess import run
|
||||
from os import PathLike
|
||||
|
||||
|
||||
class TranscodingError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def transcode(src: str | PathLike[str], dst: str | PathLike[str]) -> None:
|
||||
dst = Path(dst)
|
||||
|
||||
dst.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
if dst.is_file():
|
||||
dst.unlink()
|
||||
|
||||
opusenc: tuple[str, ...] = (
|
||||
"opusenc",
|
||||
"--quiet",
|
||||
"--bitrate",
|
||||
"96.000",
|
||||
"--music",
|
||||
"--vbr",
|
||||
"--comp",
|
||||
"10",
|
||||
"--",
|
||||
str(src),
|
||||
str(dst),
|
||||
)
|
||||
|
||||
cp = run(opusenc)
|
||||
if cp.returncode != 0:
|
||||
raise TranscodingError(f"opusenc exited with code {cp.returncode}")
|
|
@ -14,6 +14,4 @@ in {
|
|||
|
||||
"restic-vessel.age".publicKeys = (builtins.attrValues users) ++ [hosts.vessel];
|
||||
"restic-abacus.age".publicKeys = (builtins.attrValues users) ++ [hosts.abacus];
|
||||
|
||||
"syncserver.age".publicKeys = (builtins.attrValues users) ++ [hosts.abacus];
|
||||
}
|
||||
|
|
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue