stuff
This commit is contained in:
parent
b7e93fc970
commit
ebf2035c54
145
flake.lock
145
flake.lock
|
@ -35,11 +35,11 @@
|
|||
"nixpkgs": "nixpkgs_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1737621947,
|
||||
"narHash": "sha256-8HFvG7fvIFbgtaYAY2628Tb89fA55nPm2jSiNs0/Cws=",
|
||||
"lastModified": 1742042642,
|
||||
"narHash": "sha256-D0gP8srrX0qj+wNYNPdtVJsQuFzIng3q43thnHXQ/es=",
|
||||
"owner": "cachix",
|
||||
"repo": "cachix",
|
||||
"rev": "f65a3cd5e339c223471e64c051434616e18cc4f5",
|
||||
"rev": "a624d3eaf4b1d225f918de8543ed739f2f574203",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -95,11 +95,11 @@
|
|||
"nixpkgs": "nixpkgs_4"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1743521698,
|
||||
"narHash": "sha256-bvl7YmNZjGEZhyH86mGiJdhZGMaRot1TMM6cjwrwH6k=",
|
||||
"lastModified": 1743783972,
|
||||
"narHash": "sha256-5wPsNCnWmeLpLxavsftA9L7tnYgtlexV7FwLegxtpy4=",
|
||||
"owner": "cachix",
|
||||
"repo": "devenv",
|
||||
"rev": "4917f16d045f12d938d0a29fb1cbfb9e24ae6d0d",
|
||||
"rev": "2f53e2f867e0c2ba18b880e66169366e5f8ca554",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -211,11 +211,11 @@
|
|||
"nixpkgs-lib": "nixpkgs-lib"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1741352980,
|
||||
"narHash": "sha256-+u2UunDA4Cl5Fci3m7S643HzKmIDAe+fiXrLqYsR2fs=",
|
||||
"lastModified": 1743550720,
|
||||
"narHash": "sha256-hIshGgKZCgWh6AYJpJmRgFdR3WUbkY04o82X05xqQiY=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "f4330d22f1c5d2ba72d3d22df5597d123fdb60a9",
|
||||
"rev": "c621e8422220273271f52058f618c94e405bb0f5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -245,6 +245,24 @@
|
|||
"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,
|
||||
|
@ -273,11 +291,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1740849354,
|
||||
"narHash": "sha256-oy33+t09FraucSZ2rZ6qnD1Y1c8azKKmQuCvF2ytUko=",
|
||||
"lastModified": 1742649964,
|
||||
"narHash": "sha256-DwOTp7nvfi8mRfuL1escHDXabVXFGT1VlPD1JHrtrco=",
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"rev": "4a709a8ce9f8c08fa7ddb86761fe488ff7858a07",
|
||||
"rev": "dcf5072734cb576d2b0c59b2ac44f5050b5eac82",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -406,6 +424,25 @@
|
|||
"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": [
|
||||
|
@ -446,11 +483,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1743306489,
|
||||
"narHash": "sha256-LROaIjSLo347cwcHRfSpqzEOa2FoLSeJwU4dOrGm55E=",
|
||||
"lastModified": 1743911143,
|
||||
"narHash": "sha256-4j4JPwr0TXHH4ZyorXN5yIcmqIQr0WYacsuPA4ktONo=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nix-index-database",
|
||||
"rev": "b3696bfb6c24aa61428839a99e8b40c53ac3a82d",
|
||||
"rev": "a36f6a7148aec2c77d78e4466215cceb2f5f4bfb",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -462,16 +499,16 @@
|
|||
"nixos-cosmic": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat_3",
|
||||
"nixpkgs": "nixpkgs_6",
|
||||
"nixpkgs": "nixpkgs_7",
|
||||
"nixpkgs-stable": "nixpkgs-stable_2",
|
||||
"rust-overlay": "rust-overlay_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1743531084,
|
||||
"narHash": "sha256-IOfLnebyXv2v8srLwKOx7TSi2NhHrvqL5AtpDEGVhJ4=",
|
||||
"lastModified": 1744137608,
|
||||
"narHash": "sha256-KEuKL7lM2ZqKzvaGIptVDAce29CAR4ZSgWtFD3PnpB0=",
|
||||
"owner": "lilyinstarlight",
|
||||
"repo": "nixos-cosmic",
|
||||
"rev": "c231cbbfdd897b86efc9138a37ac302d5a29fb5d",
|
||||
"rev": "d20b15f629985fe6900925bef462f947e4a75b2f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -498,11 +535,26 @@
|
|||
},
|
||||
"nixpkgs-lib": {
|
||||
"locked": {
|
||||
"lastModified": 1740877520,
|
||||
"narHash": "sha256-oiwv/ZK/2FhGxrCkQkB83i7GnWXPPLzoqFHpDD3uYpk=",
|
||||
"lastModified": 1743296961,
|
||||
"narHash": "sha256-b1EdN3cULCqtorQ4QeWgLMrd5ZGOjLSLemfa00heasc=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"rev": "147dee35aab2193b174e4c0868bd80ead5ce755c",
|
||||
"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",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -529,11 +581,11 @@
|
|||
},
|
||||
"nixpkgs-stable_2": {
|
||||
"locked": {
|
||||
"lastModified": 1743367904,
|
||||
"narHash": "sha256-sOos1jZGKmT6xxPvxGQyPTApOunXvScV4lNjBCXd/CI=",
|
||||
"lastModified": 1743975612,
|
||||
"narHash": "sha256-o4FjFOUmjSRMK7dn0TFdAT0RRWUWD+WsspPHa+qEQT8=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "7ffe0edc685f14b8c635e3d6591b0bbb97365e6c",
|
||||
"rev": "a880f49904d68b5e53338d1e8c7bf80f59903928",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -609,11 +661,11 @@
|
|||
},
|
||||
"nixpkgs_6": {
|
||||
"locked": {
|
||||
"lastModified": 1743315132,
|
||||
"narHash": "sha256-6hl6L/tRnwubHcA4pfUUtk542wn2Om+D4UnDhlDW9BE=",
|
||||
"lastModified": 1743964447,
|
||||
"narHash": "sha256-nEo1t3Q0F+0jQ36HJfbJtiRU4OI+/0jX/iITURKe3EE=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "52faf482a3889b7619003c0daec593a1912fddc1",
|
||||
"rev": "063dece00c5a77e4a0ea24e5e5a5bd75232806f8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -625,11 +677,27 @@
|
|||
},
|
||||
"nixpkgs_7": {
|
||||
"locked": {
|
||||
"lastModified": 1743076231,
|
||||
"narHash": "sha256-yQugdVfi316qUfqzN8JMaA2vixl+45GxNm4oUfXlbgw=",
|
||||
"lastModified": 1743964447,
|
||||
"narHash": "sha256-nEo1t3Q0F+0jQ36HJfbJtiRU4OI+/0jX/iITURKe3EE=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "6c5963357f3c1c840201eda129a99d455074db04",
|
||||
"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",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -642,15 +710,15 @@
|
|||
"phps": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat_4",
|
||||
"nixpkgs": "nixpkgs_7",
|
||||
"nixpkgs": "nixpkgs_8",
|
||||
"utils": "utils"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1743395855,
|
||||
"narHash": "sha256-1OZa0T1PSRTHqQG2eiMDiqJPB8XSseoe7bKUCkG5C0U=",
|
||||
"lastModified": 1744001863,
|
||||
"narHash": "sha256-0pYw0Idtion++srUKsmGX7mq1weozdVE8gR+inoedUo=",
|
||||
"owner": "fossar",
|
||||
"repo": "nix-phps",
|
||||
"rev": "87aa57df1dffc535756256efbd141c735852145f",
|
||||
"rev": "220ed74315dc7cd64a6181efd3d583a3607ef01f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -695,6 +763,7 @@
|
|||
"flatpak": "flatpak",
|
||||
"hardware": "hardware",
|
||||
"lanzaboote": "lanzaboote",
|
||||
"musicomp": "musicomp",
|
||||
"nix-index-database": "nix-index-database",
|
||||
"nixos-cosmic": "nixos-cosmic",
|
||||
"nixpkgs": [
|
||||
|
@ -733,11 +802,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1743475035,
|
||||
"narHash": "sha256-uLjVsb4Rxnp1zmFdPCDmdODd4RY6ETOeRj0IkC0ij/4=",
|
||||
"lastModified": 1744079607,
|
||||
"narHash": "sha256-5cog6Qd6w/bINdLO5mOysAHOHey8PwFXk4IWo+y+Czg=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "bee11c51c2cda3ac57c9e0149d94b86cc1b00d13",
|
||||
"rev": "f6b62cc99c25e79a1c17e9fca91dc6b6faebec6c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
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 = [
|
||||
"com.spotify.Client"
|
||||
"io.github.dweymouth.supersonic"
|
||||
];
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
services.flatpak.packages = [
|
||||
"com.spotify.Client"
|
||||
"io.github.dweymouth.supersonic"
|
||||
];
|
||||
}
|
8
hosts/headful/glacier/users.nix
Normal file
8
hosts/headful/glacier/users.nix
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
users.users.futura = {
|
||||
description = "Futura";
|
||||
uid = 1001;
|
||||
isNormalUser = true;
|
||||
password = "futura";
|
||||
};
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
services.flatpak.packages = [
|
||||
"com.spotify.Client"
|
||||
"io.github.dweymouth.supersonic"
|
||||
];
|
||||
}
|
|
@ -25,6 +25,7 @@
|
|||
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};
|
||||
|
@ -47,7 +48,6 @@
|
|||
paths = [
|
||||
phpWithEnv
|
||||
phpWithEnv.packages.composer
|
||||
pkgs.symfony-cli
|
||||
];
|
||||
};
|
||||
in
|
||||
|
@ -55,12 +55,32 @@
|
|||
);
|
||||
|
||||
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;
|
||||
|
@ -68,6 +88,8 @@ in {
|
|||
phps;
|
||||
|
||||
environment.systemPackages = [
|
||||
phps.${selectedPhp}.packages.composer
|
||||
pkgs.jetbrains.phpstorm
|
||||
phps.${selectedPhp}
|
||||
symfony-cli
|
||||
];
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
{pkgs, ...}: {
|
||||
environment.systemPackages = [
|
||||
pkgs.jetbrains.phpstorm
|
||||
];
|
||||
}
|
35
hosts/headful/work/plasma.nix
Normal file
35
hosts/headful/work/plasma.nix
Normal file
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
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];
|
||||
};
|
||||
}
|
5
hosts/headful/work/supersonic.nix
Normal file
5
hosts/headful/work/supersonic.nix
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
services.flatpak.packages = [
|
||||
"io.github.dweymouth.supersonic"
|
||||
];
|
||||
}
|
10
hosts/headful/work/tools.nix
Normal file
10
hosts/headful/work/tools.nix
Normal file
|
@ -0,0 +1,10 @@
|
|||
{pkgs, ...}: {
|
||||
environment.systemPackages = [
|
||||
pkgs.gnumake
|
||||
pkgs.unzip
|
||||
pkgs.pv
|
||||
pkgs.jq
|
||||
pkgs.mariadb
|
||||
pkgs.openssl
|
||||
];
|
||||
}
|
|
@ -12,6 +12,12 @@
|
|||
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"];
|
||||
|
|
37
hosts/headless/abacus/firefox-syncserver.nix
Normal file
37
hosts/headless/abacus/firefox-syncserver.nix
Normal file
|
@ -0,0 +1,37 @@
|
|||
# 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,6 +1,7 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
virtualHostName = "forgejo.helveticanonstandard.net";
|
||||
|
@ -50,24 +51,26 @@ in {
|
|||
secrets.mailer.PASSWD = config.age.secrets.forgejo-mailer.path;
|
||||
};
|
||||
|
||||
systemd.services.forgejo.preStart = let
|
||||
forgejo = lib.getExe config.services.forgejo.package;
|
||||
passwordFile = config.age.secrets.forgejo-admin.path;
|
||||
user = "helvetica";
|
||||
email = "helvetica@helveticanonstandard.net";
|
||||
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
|
||||
'';
|
||||
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
|
||||
'';
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts.${virtualHostName} = {
|
||||
enableACME = true;
|
||||
|
|
10
hosts/headless/abacus/mariadb.nix
Normal file
10
hosts/headless/abacus/mariadb.nix
Normal file
|
@ -0,0 +1,10 @@
|
|||
# {pkgs, ...}: {
|
||||
# services.mysql.package = pkgs.mariadb;
|
||||
#
|
||||
# services.mysqlBackup = {
|
||||
# enable = true;
|
||||
# startAt = "*-*-* 02:00:00";
|
||||
# location = "/srv/backup/postgresql";
|
||||
# };
|
||||
# }
|
||||
{}
|
23
hosts/headless/abacus/mealie.nix
Normal file
23
hosts/headless/abacus/mealie.nix
Normal file
|
@ -0,0 +1,23 @@
|
|||
{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}";
|
||||
};
|
||||
}
|
8
hosts/headless/abacus/postgresql.nix
Normal file
8
hosts/headless/abacus/postgresql.nix
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
services.postgresqlBackup = {
|
||||
enable = true;
|
||||
startAt = "*-*-* 02:00:00";
|
||||
location = "/srv/backup/postgresql";
|
||||
backupAll = true;
|
||||
};
|
||||
}
|
|
@ -1,9 +1,14 @@
|
|||
{
|
||||
inputs,
|
||||
self,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
imports = [
|
||||
inputs.musicomp.nixosModules.default
|
||||
];
|
||||
|
||||
services.musicomp.jobs.main = {
|
||||
music = "/srv/music";
|
||||
comp = "/srv/compmusic";
|
||||
|
|
|
@ -1,116 +0,0 @@
|
|||
{
|
||||
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);
|
||||
};
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
# musicomp
|
||||
|
||||
A music compression tool.
|
|
@ -1,26 +0,0 @@
|
|||
{
|
||||
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";
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
[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"]
|
|
@ -1,3 +0,0 @@
|
|||
from .cli import main
|
||||
|
||||
main()
|
|
@ -1,6 +0,0 @@
|
|||
from os import PathLike
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def clean(dst: str | PathLike[str]) -> None:
|
||||
Path(dst).unlink(missing_ok=True)
|
|
@ -1,117 +0,0 @@
|
|||
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)
|
|
@ -1,6 +0,0 @@
|
|||
from os import PathLike
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def replace(src: str | PathLike[str]) -> None:
|
||||
Path(src).unlink(missing_ok=True)
|
|
@ -1,68 +0,0 @@
|
|||
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}"
|
|
@ -1,34 +0,0 @@
|
|||
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,4 +14,6 @@ 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];
|
||||
}
|
||||
|
|
BIN
secrets/syncserver.age
Normal file
BIN
secrets/syncserver.age
Normal file
Binary file not shown.
Loading…
Reference in a new issue