Compare commits

..

2 commits

Author SHA1 Message Date
33ee2f5760
meow
Some checks failed
ci/woodpecker/push/build-cache Pipeline failed
ci/woodpecker/cron/dependency-pr Pipeline was successful
2025-10-16 12:18:36 +02:00
350885960e
flake update 2025-10-14 14:24:58 +02:00
9 changed files with 10911 additions and 44 deletions

View file

@ -54,9 +54,6 @@ in
gimp3 gimp3
anytype anytype
monero-gui monero-gui
orca-slicer
unstable.kicad
dune3d
pencil2d pencil2d
python311Packages.brother-ql python311Packages.brother-ql
ptouch-print ptouch-print

View file

@ -50,6 +50,7 @@ in
unitConfig.Requisite = "graphical-session.target"; unitConfig.Requisite = "graphical-session.target";
serviceConfig.Restart = "on-failure"; serviceConfig.Restart = "on-failure";
wantedBy = [ "swww-daemon.service" ]; wantedBy = [ "swww-daemon.service" ];
path = with pkgs;[ coreutils findutils cfg.package gnused];
script = '' script = ''
set -eox set -eox
export DEFAULT_INTERVAL=300 # In seconds export DEFAULT_INTERVAL=300 # In seconds
@ -62,22 +63,20 @@ in
export SWWW_TRANSITION_DURATION="1" export SWWW_TRANSITION_DURATION="1"
# export SWWW_TRANSITION_STEP="90" # export SWWW_TRANSITION_STEP="90"
images=( ) # array of randomized images
while true; do while true; do
find "''$DIR" -type f \ for d in ''$(swww query | sed -nE 's/^: ([^:]+).*/\1/p'); do # see swww-query(1)
| while read -r img; do if [[ ''${#images[@]} == 0 ]]; then
echo "''$(</dev/urandom tr -dc a-zA-Z0-9 | head -c 8):''$img" images=( $(find $DIR -regextype posix-extended -type f -regex '.*\.(jpg|jpeg|gif|png|bmp|dds|exr|ico|tga|tiff|webp)$' | shuf) ) # fill queue if arr empty (rust image crate supported formats)
done \ fi
| sort -n | cut -d':' -f2- \
| while read -r img; do swww img --resize "''$RESIZE_TYPE" --outputs "''$d" "''${images[0]}" # show first image of arr
for d in ''$(${cfg.package}/bin/swww query | grep -Po "^[^:]+"); do # see ${cfg.package}/bin/swww-query(1)
# Get next random image for this display, or re-shuffle images images=("''${images[@]:1}") # pop first image of arr
# and pick again if no more unused images are remaining
[ -z "''$img" ] && if read -r img; then true; else break 2; fi
${cfg.package}/bin/swww img --resize "''$RESIZE_TYPE" --outputs "''$d" "''$img"
unset -v img # Each image should only be used once per loop
done
sleep "''${DEFAULT_INTERVAL}"
done done
sleep "''${DEFAULT_INTERVAL}" || true # pkill sleep for next wallpaper xd
done done
''; '';
# restartTriggers = [wpaperdConf]; # restartTriggers = [wpaperdConf];

View file

@ -23,8 +23,8 @@
./presets/gui.nix ./presets/gui.nix
./presets/server.nix ./presets/server.nix
./presets/home-manager.nix ./presets/home-manager.nix
./services/authentik.nix ./services/authentik
./services/caddy.nix ./services/caddy
./services/monitoring.nix ./services/monitoring.nix
./services/wireguard.nix ./services/wireguard.nix
./system/impermanence.nix ./system/impermanence.nix

View file

@ -10,7 +10,7 @@ let
in in
{ {
options.xyno.presets.development.enable = options.xyno.presets.development.enable =
mkEnableOption "enables xynos configs for a development machine"; mkEnableOption "enables xynos configs for a development/workstation machine";
config = mkIf cfg.enable { config = mkIf cfg.enable {
home-manager.users.${config.xyno.system.user.name} = mkIf config.xyno.presets.home-manager.enable ( home-manager.users.${config.xyno.system.user.name} = mkIf config.xyno.presets.home-manager.enable (
{ ... }: { ... }:
@ -25,6 +25,10 @@ in
virtualisation.podman.enable = true; virtualisation.podman.enable = true;
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
orca-slicer
unstable.kicad
freecad
dune3d
jetbrains.rider jetbrains.rider
# android-studio # android-studio
nixpkgs-manual nixpkgs-manual

View file

@ -45,7 +45,7 @@ let
terranixConfig = inputs.terranix.lib.terranixConfiguration { terranixConfig = inputs.terranix.lib.terranixConfiguration {
system = pkgs.system; system = pkgs.system;
modules = [ modules = [
./authentik/provider.nix ./provider.nix
{ {
inherit (cfg) inherit (cfg)
oauthApps oauthApps
@ -192,7 +192,7 @@ in
}; };
sops.secrets."authentik/env" = { sops.secrets."authentik/env" = {
sopsFile = ../../instances/${config.networking.hostName}/secrets/authentik.yaml; sopsFile = ../../../instances/${config.networking.hostName}/secrets/authentik.yaml;
}; };
services.caddy.extraConfig = '' services.caddy.extraConfig = ''

View file

@ -0,0 +1,5 @@
{ json, lib, ...}: with lib;
types.submodule {
freeformType = json.type;
}

File diff suppressed because one or more lines are too long

View file

@ -30,9 +30,14 @@ let
genVHostsFromWildcard = mapAttrs' ( genVHostsFromWildcard = mapAttrs' (
n: v: nameValuePair "*.${n}" (genOneWildcard n v) n: v: nameValuePair "*.${n}" (genOneWildcard n v)
) cfg.wildcardHosts; ) cfg.wildcardHosts;
schema = import ./json-schema.nix { inherit pkgs lib; schema = builtins.fromJSON (builtins.readFile ./caddy_schema.json); };
in in
{ {
options.xyno.services.caddy.enable = mkEnableOption "enables caddy with the desec plugin"; options.xyno.services.caddy.enable = mkEnableOption "enables caddy with the desec plugin";
options.xyno.services.caddy.config = mkOption {
default = {};
type = schema.type;
};
options.xyno.services.caddy.wildcardHosts = mkOption { options.xyno.services.caddy.wildcardHosts = mkOption {
example = { example = {
"hailsatan.eu" = { "hailsatan.eu" = {
@ -77,29 +82,31 @@ in
services.caddy = { services.caddy = {
enable = true; enable = true;
package = pkgs.caddy-desec; package = pkgs.caddy-desec;
virtualHosts = genVHostsFromWildcard; adapter = "json";
email = mkDefault "ssl@xyno.systems"; configFile = json.generate "caddy-config.json" cfg.config;
acmeCA = mkDefault "https://acme-v02.api.letsencrypt.org/directory"; # virtualHosts = genVHostsFromWildcard;
globalConfig = '' # email = mkDefault "ssl@xyno.systems";
metrics { # acmeCA = mkDefault "https://acme-v02.api.letsencrypt.org/directory";
per_host # globalConfig = ''
} # metrics {
''; # per_host
extraConfig = '' # }
(blockBots) { # '';
@botForbidden header_regexp User-Agent "(?i)AdsBot-Google|Amazonbot|anthropic-ai|Applebot|Applebot-Extended|AwarioRssBot|AwarioSmartBot|Bytespider|CCBot|ChatGPT|ChatGPT-User|Claude-Web|ClaudeBot|cohere-ai|DataForSeoBot|Diffbot|FacebookBot|Google-Extended|GPTBot|ImagesiftBot|magpie-crawler|omgili|Omgilibot|peer39_crawler|PerplexityBot|YouBot" # extraConfig = ''
# (blockBots) {
# @botForbidden header_regexp User-Agent "(?i)AdsBot-Google|Amazonbot|anthropic-ai|Applebot|Applebot-Extended|AwarioRssBot|AwarioSmartBot|Bytespider|CCBot|ChatGPT|ChatGPT-User|Claude-Web|ClaudeBot|cohere-ai|DataForSeoBot|Diffbot|FacebookBot|Google-Extended|GPTBot|ImagesiftBot|magpie-crawler|omgili|Omgilibot|peer39_crawler|PerplexityBot|YouBot"
handle @botForbidden { # handle @botForbidden {
redir https://hil-speed.hetzner.com/10GB.bin # redir https://hil-speed.hetzner.com/10GB.bin
} # }
handle /robots.txt { # handle /robots.txt {
respond <<TXT # respond <<TXT
User-Agent: * # User-Agent: *
Disallow: / # Disallow: /
TXT 200 # TXT 200
} # }
} # }
''; # '';
}; };
xyno.services.monitoring.exporters.caddy = 2019; xyno.services.monitoring.exporters.caddy = 2019;

View file

@ -0,0 +1,144 @@
{
pkgs,
lib,
schema,
...
}:
with lib;
let
json = pkgs.formats.json { };
submoduleOptions =
{
spec,
depth,
extraRequires ? [ ],
...
}:
let
isRequired = n: any (x: x == n) (extraRequires ++ (optionals (spec ? required) spec.required));
in
if spec ? "$ref" then
submoduleOptions (getRef x."$ref")
else
mapAttrs (
n: v:
buildOption {
inherit depth;
spec = v;
required = isRequired n;
}
) (if spec ? properties then spec.properties else { });
getRef =
x:
let
path = splitString "/" (traceVal x);
result = attrByPath (tail path) (throw "ref ${x} not found") schema;
in
result;
deref = x: if x ? "$ref" then getRef x."$ref" else x;
buildOptionType =
{
spec,
depth ? 0,
...
}:
let
strType = if spec ? enum then types.enum spec.enum else types.str;
objType = types.submodule {
freeformType = json.type;
options = submoduleOptions { inherit spec depth; };
};
arrType = types.listOf (
if spec ? items then
buildOptionType {
inherit depth;
spec = spec.items;
}
else
types.anything
);
allOfType =
let
resolve = x: if x ? "if" then x."then" else x; # just ignore conditionals for now
resolved = map (x: deref (resolve x)) spec.allOf;
# mergedDesc = concatStringsSep "\n" (
# map (x: if x ? markdownDescription then x.markdownDescription else "") resolved
# );
combined = foldl (x: c: recursiveUpdate c x) { } resolved;
# options = map (
# x:
# submoduleOptions {
# spec = x;
# extraRequires = if spec ? required then spec.required else [ ];
# }
# ) (traceValSeqN 4 resolved);
in
buildOptionType {
depth = depth + 1;
spec = combined;
};
type =
if depth > 3 then
types.deferredModule
else if spec ? "$ref" then
buildOptionType {
depth = depth + 1;
spec = getRef spec."$ref";
}
else if spec ? allOf then
allOfType
else if !spec ? type then
json.type
else if isList spec.type then
types.oneOf (map (x: buildOptionType x) spec.type)
else if spec.type == "string" then
strType
else if spec.type == "boolean" then
types.bool
else if spec.type == "number" then
types.number
else if spec.type == "array" then
arrType
else if spec.type == "object" then
objType
else
(throw "unknown json schema type: ${spec.type}");
in
type;
buildOption =
{
spec,
depth,
required ? false,
...
}:
let
type = buildOptionType { inherit spec depth; };
in
mkOption {
type = if required then type else types.nullOr type;
description = if spec ? markdownDescription then spec.markdownDescription else "no description qwq";
default =
if required then
if spec.type == "object" then
{ }
else if spec.type == "array" then
[ ]
else
null
else
null;
};
in
{
generate = json.generate;
type = buildOptionType {
depth = 0;
spec = schema;
};
}