Compare commits

..

No commits in common. "0c455baebd44b97a338e28167208470ba02558a9" and "23c8076e4d8cd6b0bc73dddfe7b67f463642be27" have entirely different histories.

69 changed files with 9885 additions and 1126 deletions

View File

@ -24,14 +24,4 @@ clean-old-nixos-profiles:
# Garbage Collect # Garbage Collect
.PHONY: gc .PHONY: gc
gc: gc:
nix store gc nix store gc
# Update a flake input by name (ex: 'nixpkgs')
.PHONY: update-input
update-input:
nix flake update $(filter-out $@,$(MAKECMDGOALS))
# Build Custom Install ISO
.PHONY: iso
iso:
nix build .#packages.x86_64-linux.iso

View File

@ -12,13 +12,6 @@
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
"s0.koi-bebop.ts.net:OjbzD86YjyJZpCp9RWaQKANaflcpKhtzBMNP8I2aPUU=" "s0.koi-bebop.ts.net:OjbzD86YjyJZpCp9RWaQKANaflcpKhtzBMNP8I2aPUU="
]; ];
# Allow substituters to be offline
# This isn't exactly ideal since it would be best if I could set up a system
# so that it is an error if a derivation isn't available for any substituters
# and use this flag as intended for deciding if it should build missing
# derivations locally. See https://github.com/NixOS/nix/issues/6901
fallback = true;
}; };
}; };
} }

View File

@ -100,5 +100,7 @@
security.acme.defaults.email = "zuckerberg@neet.dev"; security.acme.defaults.email = "zuckerberg@neet.dev";
# Enable Desktop Environment if this is a PC (machine role is "personal") # Enable Desktop Environment if this is a PC (machine role is "personal")
de.enable = lib.mkDefault (config.thisMachine.hasRole."personal"); de.enable = (
builtins.elem config.networking.hostName config.machines.roles.personal
);
} }

View File

@ -5,90 +5,6 @@
let let
machines = config.machines.hosts; machines = config.machines.hosts;
hostOptionsSubmoduleType = lib.types.submodule {
options = {
hostNames = lib.mkOption {
type = lib.types.listOf lib.types.str;
description = ''
List of hostnames for this machine. The first one is the default so it is the target of deployments.
Used for automatically trusting hosts for ssh connections.
'';
};
arch = lib.mkOption {
type = lib.types.enum [ "x86_64-linux" "aarch64-linux" ];
description = ''
The architecture of this machine.
'';
};
systemRoles = lib.mkOption {
type = lib.types.listOf lib.types.str; # TODO: maybe use an enum?
description = ''
The set of roles this machine holds. Affects secrets available. (TODO add service config as well using this info)
'';
};
hostKey = lib.mkOption {
type = lib.types.str;
description = ''
The system ssh host key of this machine. Used for automatically trusting hosts for ssh connections
and for decrypting secrets with agenix.
'';
};
remoteUnlock = lib.mkOption {
default = null;
type = lib.types.nullOr (lib.types.submodule {
options = {
hostKey = lib.mkOption {
type = lib.types.str;
description = ''
The system ssh host key of this machine used for luks boot unlocking only.
'';
};
clearnetHost = lib.mkOption {
default = null;
type = lib.types.nullOr lib.types.str;
description = ''
The hostname resolvable over clearnet used to luks boot unlock this machine
'';
};
onionHost = lib.mkOption {
default = null;
type = lib.types.nullOr lib.types.str;
description = ''
The hostname resolvable over tor used to luks boot unlock this machine
'';
};
};
});
};
userKeys = lib.mkOption {
default = [ ];
type = lib.types.listOf lib.types.str;
description = ''
The list of user keys. Each key here can be used to log into all other systems as `googlebot`.
TODO: consider auto populating other programs that use ssh keys such as gitea
'';
};
deployKeys = lib.mkOption {
default = [ ];
type = lib.types.listOf lib.types.str;
description = ''
The list of deployment keys. Each key here can be used to log into all other systems as `root`.
'';
};
configurationPath = lib.mkOption {
type = lib.types.path;
description = ''
The path to this machine's configuration directory.
'';
};
};
};
in in
{ {
imports = [ imports = [
@ -97,14 +13,102 @@ in
]; ];
options.machines = { options.machines = {
hosts = lib.mkOption {
type = lib.types.attrsOf hostOptionsSubmoduleType;
};
};
options.thisMachine.config = lib.mkOption { hosts = lib.mkOption {
# For ease of use, a direct copy of the host config from machines.hosts.${hostName} type = lib.types.attrsOf
type = hostOptionsSubmoduleType; (lib.types.submodule {
options = {
hostNames = lib.mkOption {
type = lib.types.listOf lib.types.str;
description = ''
List of hostnames for this machine. The first one is the default so it is the target of deployments.
Used for automatically trusting hosts for ssh connections.
'';
};
arch = lib.mkOption {
type = lib.types.enum [ "x86_64-linux" "aarch64-linux" ];
description = ''
The architecture of this machine.
'';
};
systemRoles = lib.mkOption {
type = lib.types.listOf lib.types.str; # TODO: maybe use an enum?
description = ''
The set of roles this machine holds. Affects secrets available. (TODO add service config as well using this info)
'';
};
hostKey = lib.mkOption {
type = lib.types.str;
description = ''
The system ssh host key of this machine. Used for automatically trusting hosts for ssh connections
and for decrypting secrets with agenix.
'';
};
remoteUnlock = lib.mkOption {
default = null;
type = lib.types.nullOr (lib.types.submodule {
options = {
hostKey = lib.mkOption {
type = lib.types.str;
description = ''
The system ssh host key of this machine used for luks boot unlocking only.
'';
};
clearnetHost = lib.mkOption {
default = null;
type = lib.types.nullOr lib.types.str;
description = ''
The hostname resolvable over clearnet used to luks boot unlock this machine
'';
};
onionHost = lib.mkOption {
default = null;
type = lib.types.nullOr lib.types.str;
description = ''
The hostname resolvable over tor used to luks boot unlock this machine
'';
};
};
});
};
userKeys = lib.mkOption {
default = [ ];
type = lib.types.listOf lib.types.str;
description = ''
The list of user keys. Each key here can be used to log into all other systems as `googlebot`.
TODO: consider auto populating other programs that use ssh keys such as gitea
'';
};
deployKeys = lib.mkOption {
default = [ ];
type = lib.types.listOf lib.types.str;
description = ''
The list of deployment keys. Each key here can be used to log into all other systems as `root`.
'';
};
configurationPath = lib.mkOption {
type = lib.types.path;
description = ''
The path to this machine's configuration directory.
'';
};
};
});
};
}; };
config = { config = {
@ -192,16 +196,5 @@ in
builtins.map (p: { "${dirName p}" = p; }) propFiles; builtins.map (p: { "${dirName p}" = p; }) propFiles;
in in
properties ../../machines; properties ../../machines;
# Don't try to evaluate "thisMachine" when reflecting using moduleless.nix.
# When evaluated by moduleless.nix this will fail due to networking.hostName not
# existing. This is because moduleless.nix is not intended for reflection from the
# perspective of a perticular machine but is instead intended for reflecting on
# the properties of all machines as a whole system.
thisMachine.config = config.machines.hosts.${config.networking.hostName};
# Add ssh keys from KeepassXC
machines.ssh.userKeys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILACiZO7QnB4bcmziVaUkUE0ZPMR0M/yJbbHYsHIZz9g" ];
machines.ssh.deployKeys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID58MvKGs3GDMMcN8Iyi9S59SciSrVM97wKtOvUAl3li" ];
}; };
} }

View File

@ -1,55 +1,19 @@
{ config, lib, ... }: { config, lib, ... }:
# Maps roles to their hosts. # Maps roles to their hosts
# machines.withRole = {
# personal = [
# "machine1" "machine3"
# ];
# cache = [
# "machine2"
# ];
# };
#
# A list of all possible roles
# machines.allRoles = [
# "personal"
# "cache"
# ];
#
# For each role has true or false if the current machine has that role
# thisMachine.hasRole = {
# personal = true;
# cache = false;
# };
{ {
options.machines.withRole = lib.mkOption { options.machines.roles = lib.mkOption {
type = lib.types.attrsOf (lib.types.listOf lib.types.str); type = lib.types.attrsOf (lib.types.listOf lib.types.str);
}; };
options.machines.allRoles = lib.mkOption {
type = lib.types.listOf lib.types.str;
};
options.thisMachine.hasRole = lib.mkOption {
type = lib.types.attrsOf lib.types.bool;
};
config = { config = {
machines.withRole = lib.zipAttrs machines.roles = lib.zipAttrs
(lib.mapAttrsToList (lib.mapAttrsToList
(host: cfg: (host: cfg:
lib.foldl (lib.mergeAttrs) { } lib.foldl (lib.mergeAttrs) { }
(builtins.map (role: { ${role} = host; }) (builtins.map (role: { ${role} = host; })
cfg.systemRoles)) cfg.systemRoles))
config.machines.hosts); config.machines.hosts);
machines.allRoles = lib.attrNames config.machines.withRole;
thisMachine.hasRole = lib.mapAttrs
(role: cfg:
builtins.elem config.networking.hostName config.machines.withRole.${role}
)
config.machines.withRole;
}; };
} }

View File

@ -39,6 +39,6 @@ in
builtins.map builtins.map
(host: machines.hosts.${host}.hostKey) (host: machines.hosts.${host}.hostKey)
hosts) hosts)
machines.withRole; machines.roles;
}; };
} }

View File

@ -1,14 +1,18 @@
{ config, lib, ... }: { config, lib, ... }:
let let
builderRole = "nix-builder";
builderUserName = "nix-builder"; builderUserName = "nix-builder";
builderRole = "nix-builder"; machinesByRole = role: lib.filterAttrs (hostname: cfg: builtins.elem role cfg.systemRoles) config.machines.hosts;
builders = config.machines.withRole.${builderRole}; otherMachinesByRole = role: lib.filterAttrs (hostname: cfg: hostname != config.networking.hostName) (machinesByRole role);
thisMachineIsABuilder = config.thisMachine.hasRole.${builderRole}; thisMachineHasRole = role: builtins.hasAttr config.networking.hostName (machinesByRole role);
builders = machinesByRole builderRole;
thisMachineIsABuilder = thisMachineHasRole builderRole;
# builders don't include themselves as a remote builder # builders don't include themselves as a remote builder
otherBuilders = lib.filter (hostname: hostname != config.networking.hostName) builders; otherBuilders = lib.filterAttrs (hostname: cfg: hostname != config.networking.hostName) builders;
in in
lib.mkMerge [ lib.mkMerge [
# configure builder # configure builder
@ -36,9 +40,9 @@ lib.mkMerge [
nix.distributedBuilds = true; nix.distributedBuilds = true;
nix.buildMachines = builtins.map nix.buildMachines = builtins.map
(builderHostname: { (builderCfg: {
hostName = builderHostname; hostName = builtins.elemAt builderCfg.hostNames 0;
system = config.machines.hosts.${builderHostname}.arch; system = builderCfg.arch;
protocol = "ssh-ng"; protocol = "ssh-ng";
sshUser = builderUserName; sshUser = builderUserName;
sshKey = "/etc/ssh/ssh_host_ed25519_key"; sshKey = "/etc/ssh/ssh_host_ed25519_key";
@ -46,7 +50,7 @@ lib.mkMerge [
speedFactor = 10; speedFactor = 10;
supportedFeatures = [ "nixos-test" "benchmark" "big-parallel" "kvm" ]; supportedFeatures = [ "nixos-test" "benchmark" "big-parallel" "kvm" ];
}) })
otherBuilders; (builtins.attrValues otherBuilders);
# It is very likely that the builder's internet is faster or just as fast # It is very likely that the builder's internet is faster or just as fast
nix.extraOptions = '' nix.extraOptions = ''

View File

@ -92,7 +92,5 @@ in
# Enable wayland support in various chromium based applications # Enable wayland support in various chromium based applications
environment.sessionVariables.NIXOS_OZONE_WL = "1"; environment.sessionVariables.NIXOS_OZONE_WL = "1";
fonts.packages = with pkgs; [ nerd-fonts.symbols-only ];
}; };
} }

View File

@ -1,16 +1,87 @@
# Starting point:
# https://github.com/aldoborrero/mynixpkgs/commit/c501c1e32dba8f4462dcecb57eee4b9e52038e27
{ config, pkgs, lib, ... }: { config, pkgs, lib, ... }:
let let
cfg = config.services.actual; cfg = config.services.actual-server;
stateDir = "/var/lib/${cfg.stateDirName}";
in in
{ {
config = lib.mkIf cfg.enable { options.services.actual-server = {
services.actual.settings = { enable = lib.mkEnableOption "Actual Server";
port = 25448;
hostname = lib.mkOption {
type = lib.types.str;
default = "localhost";
description = "Hostname for the Actual Server.";
}; };
backup.group."actual-budget".paths = [ port = lib.mkOption {
"/var/lib/actual" type = lib.types.int;
]; default = 25448;
description = "Port on which the Actual Server should listen.";
};
stateDirName = lib.mkOption {
type = lib.types.str;
default = "actual-server";
description = "Name of the directory under /var/lib holding the server's data.";
};
upload = {
fileSizeSyncLimitMB = lib.mkOption {
type = lib.types.nullOr lib.types.int;
default = null;
description = "File size limit in MB for synchronized files.";
};
syncEncryptedFileSizeLimitMB = lib.mkOption {
type = lib.types.nullOr lib.types.int;
default = null;
description = "File size limit in MB for synchronized encrypted files.";
};
fileSizeLimitMB = lib.mkOption {
type = lib.types.nullOr lib.types.int;
default = null;
description = "File size limit in MB for file uploads.";
};
};
};
config = lib.mkIf cfg.enable {
systemd.services.actual-server = {
description = "Actual Server";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
ExecStart = "${pkgs.actual-server}/bin/actual-server";
Restart = "always";
StateDirectory = cfg.stateDirName;
WorkingDirectory = stateDir;
DynamicUser = true;
UMask = "0007";
};
environment = {
NODE_ENV = "production";
ACTUAL_PORT = toString cfg.port;
# Actual is actually very bad at configuring it's own paths despite that information being readily available
ACTUAL_USER_FILES = "${stateDir}/user-files";
ACTUAL_SERVER_FILES = "${stateDir}/server-files";
ACTUAL_DATA_DIR = stateDir;
ACTUAL_UPLOAD_FILE_SYNC_SIZE_LIMIT_MB = toString (cfg.upload.fileSizeSyncLimitMB or "");
ACTUAL_UPLOAD_SYNC_ENCRYPTED_FILE_SIZE_LIMIT_MB = toString (cfg.upload.syncEncryptedFileSizeLimitMB or "");
ACTUAL_UPLOAD_FILE_SIZE_LIMIT_MB = toString (cfg.upload.fileSizeLimitMB or "");
};
};
services.nginx.virtualHosts.${cfg.hostname} = {
enableACME = true;
forceSSL = true;
locations."/".proxyPass = "http://localhost:${toString cfg.port}";
};
}; };
} }

View File

@ -10,6 +10,7 @@
./matrix.nix ./matrix.nix
./zerobin.nix ./zerobin.nix
./gitea.nix ./gitea.nix
./radio.nix
./samba.nix ./samba.nix
./owncast.nix ./owncast.nix
./mailserver.nix ./mailserver.nix

View File

@ -9,7 +9,10 @@
# TODO: skipping running inside of nixos container for now because of issues getting docker/podman running # TODO: skipping running inside of nixos container for now because of issues getting docker/podman running
let let
thisMachineIsARunner = config.thisMachine.hasRole."gitea-actions-runner"; runnerRole = "gitea-actions-runner";
runners = config.machines.roles.${runnerRole};
thisMachineIsARunner = builtins.elem config.networking.hostName runners;
containerName = "gitea-runner"; containerName = "gitea-runner";
in in
{ {

View File

@ -28,6 +28,7 @@ in
indexDir = "/var/lib/mailindex"; indexDir = "/var/lib/mailindex";
enableManageSieve = true; enableManageSieve = true;
fullTextSearch.enable = true; fullTextSearch.enable = true;
fullTextSearch.indexAttachments = true;
fullTextSearch.memoryLimit = 500; fullTextSearch.memoryLimit = 500;
inherit domains; inherit domains;
loginAccounts = { loginAccounts = {

View File

@ -3,44 +3,28 @@
let let
cfg = config.services.nextcloud; cfg = config.services.nextcloud;
nextcloudHostname = "runyan.org";
collaboraOnlineHostname = "collabora.runyan.org";
whiteboardHostname = "whiteboard.runyan.org";
whiteboardPort = 3002; # Seems impossible to change
# Hardcoded public ip of ponyo... I wish I didn't need this...
public_ip_address = "147.135.114.130";
in in
{ {
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
services.nextcloud = { services.nextcloud = {
https = true; https = true;
package = pkgs.nextcloud31; package = pkgs.nextcloud30;
hostName = nextcloudHostname; hostName = "neet.cloud";
config.dbtype = "sqlite"; config.dbtype = "sqlite";
config.adminuser = "jeremy"; config.adminuser = "jeremy";
config.adminpassFile = "/run/agenix/nextcloud-pw"; config.adminpassFile = "/run/agenix/nextcloud-pw";
# Apps
autoUpdateApps.enable = true; autoUpdateApps.enable = true;
extraAppsEnable = true;
extraApps = with config.services.nextcloud.package.packages.apps; { extraApps = with config.services.nextcloud.package.packages.apps; {
# Want # Want
inherit end_to_end_encryption mail spreed; inherit end_to_end_encryption mail spreed;
# For file and document editing (collabora online and excalidraw)
inherit richdocuments whiteboard;
# Might use # Might use
inherit calendar qownnotesapi; inherit bookmarks calendar cookbook deck memories onlyoffice qownnotesapi;
# Try out # Try out
# inherit bookmarks cookbook deck memories maps music news notes phonetrack polls forms; # inherit maps music news notes phonetrack polls forms;
}; };
extraAppsEnable = true;
# Allows installing Apps from the UI (might remove later)
appstoreEnable = true;
}; };
age.secrets.nextcloud-pw = { age.secrets.nextcloud-pw = {
file = ../../secrets/nextcloud-pw.age; file = ../../secrets/nextcloud-pw.age;
@ -56,100 +40,5 @@ in
enableACME = true; enableACME = true;
forceSSL = true; forceSSL = true;
}; };
# collabora-online
# https://diogotc.com/blog/collabora-nextcloud-nixos/
services.collabora-online = {
enable = true;
port = 15972;
settings = {
# Rely on reverse proxy for SSL
ssl = {
enable = false;
termination = true;
};
# Listen on loopback interface only
net = {
listen = "loopback";
post_allow.host = [ "localhost" ];
};
# Restrict loading documents from WOPI Host
storage.wopi = {
"@allow" = true;
host = [ config.services.nextcloud.hostName ];
};
server_name = collaboraOnlineHostname;
};
};
services.nginx.virtualHosts.${config.services.collabora-online.settings.server_name} = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://localhost:${toString config.services.collabora-online.port}";
proxyWebsockets = true;
};
};
systemd.services.nextcloud-config-collabora =
let
wopi_url = "http://localhost:${toString config.services.collabora-online.port}";
public_wopi_url = "https://${collaboraOnlineHostname}";
wopi_allowlist = lib.concatStringsSep "," [
"127.0.0.1"
"::1"
public_ip_address
];
in
{
wantedBy = [ "multi-user.target" ];
after = [ "nextcloud-setup.service" "coolwsd.service" ];
requires = [ "coolwsd.service" ];
path = [
config.services.nextcloud.occ
];
script = ''
nextcloud-occ -- config:app:set richdocuments wopi_url --value ${lib.escapeShellArg wopi_url}
nextcloud-occ -- config:app:set richdocuments public_wopi_url --value ${lib.escapeShellArg public_wopi_url}
nextcloud-occ -- config:app:set richdocuments wopi_allowlist --value ${lib.escapeShellArg wopi_allowlist}
nextcloud-occ -- richdocuments:setup
'';
serviceConfig = {
Type = "oneshot";
};
};
# Whiteboard
services.nextcloud-whiteboard-server = {
enable = true;
settings.NEXTCLOUD_URL = "https://${nextcloudHostname}";
secrets = [ "/run/agenix/whiteboard-server-jwt-secret" ];
};
systemd.services.nextcloud-config-whiteboard = {
wantedBy = [ "multi-user.target" ];
after = [ "nextcloud-setup.service" ];
requires = [ "coolwsd.service" ];
path = [
config.services.nextcloud.occ
];
script = ''
nextcloud-occ -- config:app:set whiteboard collabBackendUrl --value="https://${whiteboardHostname}"
nextcloud-occ -- config:app:set whiteboard jwt_secret_key --value="$JWT_SECRET_KEY"
'';
serviceConfig = {
Type = "oneshot";
EnvironmentFile = [ "/run/agenix/whiteboard-server-jwt-secret" ];
};
};
age.secrets.whiteboard-server-jwt-secret.file = ../../secrets/whiteboard-server-jwt-secret.age;
services.nginx.virtualHosts.${whiteboardHostname} = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://localhost:${toString whiteboardPort}";
proxyWebsockets = true;
};
};
}; };
} }

75
common/server/radio.nix Normal file
View File

@ -0,0 +1,75 @@
{ config, pkgs, lib, ... }:
let
cfg = config.services.radio;
radioPackage = config.inputs.radio.packages.${config.currentSystem}.radio;
in
{
options.services.radio = {
enable = lib.mkEnableOption "enable radio";
user = lib.mkOption {
type = lib.types.str;
default = "radio";
description = ''
The user radio should run as
'';
};
group = lib.mkOption {
type = lib.types.str;
default = "radio";
description = ''
The group radio should run as
'';
};
dataDir = lib.mkOption {
type = lib.types.str;
default = "/var/lib/radio";
description = ''
Path to the radio data directory
'';
};
host = lib.mkOption {
type = lib.types.str;
description = ''
Domain radio is hosted on
'';
};
nginx = lib.mkEnableOption "enable nginx";
};
config = lib.mkIf cfg.enable {
services.icecast = {
enable = true;
hostname = cfg.host;
mount = "stream.mp3";
fallback = "fallback.mp3";
};
services.nginx.virtualHosts.${cfg.host} = lib.mkIf cfg.nginx {
enableACME = true;
forceSSL = true;
locations."/".root = config.inputs.radio-web;
};
users.users.${cfg.user} = {
isSystemUser = true;
group = cfg.group;
home = cfg.dataDir;
createHome = true;
};
users.groups.${cfg.group} = { };
systemd.services.radio = {
enable = true;
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig.ExecStart = "${radioPackage}/bin/radio ${config.services.icecast.listen.address}:${toString config.services.icecast.listen.port} ${config.services.icecast.mount} 5500";
serviceConfig.User = cfg.user;
serviceConfig.Group = cfg.group;
serviceConfig.WorkingDirectory = cfg.dataDir;
preStart = ''
mkdir -p ${cfg.dataDir}
chown ${cfg.user} ${cfg.dataDir}
'';
};
};
}

View File

@ -21,6 +21,8 @@
shellInit = '' shellInit = ''
# disable annoying fish shell greeting # disable annoying fish shell greeting
set fish_greeting set fish_greeting
alias sudo="doas"
''; '';
}; };

View File

@ -31,6 +31,8 @@
# TODO: Old ssh keys I will remove some day... # TODO: Old ssh keys I will remove some day...
machines.ssh.userKeys = [ machines.ssh.userKeys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMVR/R3ZOsv7TZbICGBCHdjh1NDT8SnswUyINeJOC7QG"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE0dcqL/FhHmv+a1iz3f9LJ48xubO7MZHy35rW9SZOYM"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHSkKiRUUmnErOKGx81nyge/9KqjkPh8BfDk0D3oP586" # nat "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHSkKiRUUmnErOKGx81nyge/9KqjkPh8BfDk0D3oP586" # nat
]; ];
} }

163
flake.lock generated
View File

@ -14,11 +14,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1750173260, "lastModified": 1723293904,
"narHash": "sha256-9P1FziAwl5+3edkfFcr5HeGtQUtrSdk/MksX39GieoA=", "narHash": "sha256-b+uqzj+Wa6xgMS9aNbX4I+sXeb5biPDi39VgvSFqFvU=",
"owner": "ryantm", "owner": "ryantm",
"repo": "agenix", "repo": "agenix",
"rev": "531beac616433bac6f9e2a19feb8e99a22a66baf", "rev": "f6291c5935fdc4e0bef208cfc0dcab7e3f7a1c41",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -74,11 +74,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1744478979, "lastModified": 1700795494,
"narHash": "sha256-dyN+teG9G82G+m+PX/aSAagkC+vUv0SgUw3XkPhQodQ=", "narHash": "sha256-gzGLZSiOhf155FW7262kdHo2YDeugp3VuIFb4/GGng0=",
"owner": "lnl7", "owner": "lnl7",
"repo": "nix-darwin", "repo": "nix-darwin",
"rev": "43975d782b418ebf4969e9ccba82466728c2851b", "rev": "4b9b83d5a92e8c1fbfd8eb27eda375908c11ec4d",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -101,11 +101,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1749105467, "lastModified": 1727447169,
"narHash": "sha256-hXh76y/wDl15almBcqvjryB50B0BaiXJKk20f314RoE=", "narHash": "sha256-3KyjMPUKHkiWhwR91J1YchF6zb6gvckCAY1jOE+ne0U=",
"owner": "serokell", "owner": "serokell",
"repo": "deploy-rs", "repo": "deploy-rs",
"rev": "6bc76b872374845ba9d645a2f012b764fecd765f", "rev": "aa07eb05537d4cd025e2310397a6adcedfe72c76",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -117,11 +117,11 @@
"flake-compat": { "flake-compat": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1747046372, "lastModified": 1696426674,
"narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=", "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
"owner": "edolstra", "owner": "edolstra",
"repo": "flake-compat", "repo": "flake-compat",
"rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885", "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -137,11 +137,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1731533236, "lastModified": 1726560853,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", "narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=",
"owner": "numtide", "owner": "numtide",
"repo": "flake-utils", "repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", "rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -150,54 +150,6 @@
"type": "github" "type": "github"
} }
}, },
"git-hooks": {
"inputs": {
"flake-compat": [
"simple-nixos-mailserver",
"flake-compat"
],
"gitignore": "gitignore",
"nixpkgs": [
"simple-nixos-mailserver",
"nixpkgs"
]
},
"locked": {
"lastModified": 1750779888,
"narHash": "sha256-wibppH3g/E2lxU43ZQHC5yA/7kIKLGxVEnsnVK1BtRg=",
"owner": "cachix",
"repo": "git-hooks.nix",
"rev": "16ec914f6fb6f599ce988427d9d94efddf25fe6d",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "git-hooks.nix",
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"simple-nixos-mailserver",
"git-hooks",
"nixpkgs"
]
},
"locked": {
"lastModified": 1709087332,
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"home-manager": { "home-manager": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@ -205,16 +157,15 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1752208517, "lastModified": 1740845322,
"narHash": "sha256-aRY1cYOdVdXdNjcL/Twpa27CknO7pVHxooPsBizDraE=", "narHash": "sha256-AXEgFj3C0YJhu9k1OhbRhiA6FnDr81dQZ65U3DhaWpw=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "c6a01e54af81b381695db796a43360bf6db5702f", "rev": "fcac3d6d88302a5e64f6cb8014ac785e08874c8d",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "nix-community", "owner": "nix-community",
"ref": "release-25.05",
"repo": "home-manager", "repo": "home-manager",
"type": "github" "type": "github"
} }
@ -226,11 +177,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1752346111, "lastModified": 1728263287,
"narHash": "sha256-SVxCIYnbED0rNYSpm3QQoOhqxYRp1GuE9FkyM5Y2afs=", "narHash": "sha256-GJDtsxz2/zw6g/Nrp4XVWBS5IaZ7ZUkuvxPOBEDe7pg=",
"owner": "Mic92", "owner": "Mic92",
"repo": "nix-index-database", "repo": "nix-index-database",
"rev": "deff7a9a0aa98a08d8c7839fe2658199ce9828f8", "rev": "5fce10c871bab6d7d5ac9e5e7efbb3a2783f5259",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -241,11 +192,11 @@
}, },
"nixos-hardware": { "nixos-hardware": {
"locked": { "locked": {
"lastModified": 1752048960, "lastModified": 1728056216,
"narHash": "sha256-gATnkOe37eeVwKKYCsL+OnS2gU4MmLuZFzzWCtaKLI8=", "narHash": "sha256-IrO06gFUDTrTlIP3Sz+mRB6WUoO2YsgMtOD3zi0VEt0=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixos-hardware", "repo": "nixos-hardware",
"rev": "7ced9122cff2163c6a0212b8d1ec8c33a1660806", "rev": "b7ca02c7565fbf6d27ff20dd6dbd49c5b82eef28",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -257,42 +208,59 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1752431364, "lastModified": 1740374225,
"narHash": "sha256-ciGIXIMq2daX5o4Tn6pnZTd1pf5FICHbqUlHu658G9c=", "narHash": "sha256-Dnmzy5YWUVj3BNaZo5jRpZslXexbNKEk3ADGGcz9RpY=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "fb0f0dbfd95f0e19fdeab8e0f18bf0b5cf057b68", "rev": "3349acd765bdffe454f7c8bbc450855577c1a6cf",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "NixOS", "owner": "NixOS",
"ref": "release-25.05", "ref": "master",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }
}, },
"nixpkgs-linkwarden": { "radio": {
"flake": false, "inputs": {
"flake-utils": [
"flake-utils"
],
"nixpkgs": [
"nixpkgs"
]
},
"locked": { "locked": {
"narHash": "sha256-wW3F+iRM/ATWkyq8+Romal8oFmsM/p98V96d5G0tasA=", "lastModified": 1631585589,
"type": "file", "narHash": "sha256-q4o/4/2pEuJyaKZwNQC5KHnzG1obClzFB7zWk9XSDfY=",
"url": "https://github.com/NixOS/nixpkgs/pull/347353.diff" "ref": "main",
"rev": "5bf607fed977d41a269942a7d1e92f3e6d4f2473",
"revCount": 38,
"type": "git",
"url": "https://git.neet.dev/zuckerberg/radio.git"
}, },
"original": { "original": {
"type": "file", "ref": "main",
"url": "https://github.com/NixOS/nixpkgs/pull/347353.diff" "rev": "5bf607fed977d41a269942a7d1e92f3e6d4f2473",
"type": "git",
"url": "https://git.neet.dev/zuckerberg/radio.git"
} }
}, },
"nixpkgs-memos": { "radio-web": {
"flake": false, "flake": false,
"locked": { "locked": {
"narHash": "sha256-UidUaQY+9vo90rNCVInX1E+JbJ1xKFVSTMNRYKQEKpQ=", "lastModified": 1652121792,
"type": "file", "narHash": "sha256-j1Y9MAjUVNgyFSeGzPoqibAnEysJDjZSXukVfQ7+bsQ=",
"url": "https://github.com/NixOS/nixpkgs/pull/426687.diff" "ref": "refs/heads/master",
"rev": "72e7a9e80b780c84ed8d4a6374bfbb242701f900",
"revCount": 5,
"type": "git",
"url": "https://git.neet.dev/zuckerberg/radio-web.git"
}, },
"original": { "original": {
"type": "file", "type": "git",
"url": "https://github.com/NixOS/nixpkgs/pull/426687.diff" "url": "https://git.neet.dev/zuckerberg/radio-web.git"
} }
}, },
"root": { "root": {
@ -306,8 +274,8 @@
"nix-index-database": "nix-index-database", "nix-index-database": "nix-index-database",
"nixos-hardware": "nixos-hardware", "nixos-hardware": "nixos-hardware",
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs",
"nixpkgs-linkwarden": "nixpkgs-linkwarden", "radio": "radio",
"nixpkgs-memos": "nixpkgs-memos", "radio-web": "radio-web",
"simple-nixos-mailserver": "simple-nixos-mailserver", "simple-nixos-mailserver": "simple-nixos-mailserver",
"systems": "systems" "systems": "systems"
} }
@ -318,25 +286,24 @@
"flake-compat": [ "flake-compat": [
"flake-compat" "flake-compat"
], ],
"git-hooks": "git-hooks",
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
], ],
"nixpkgs-25_05": [ "nixpkgs-24_05": [
"nixpkgs" "nixpkgs"
] ]
}, },
"locked": { "locked": {
"lastModified": 1747965231, "lastModified": 1722877200,
"narHash": "sha256-BW3ktviEhfCN/z3+kEyzpDKAI8qFTwO7+S0NVA0C90o=", "narHash": "sha256-qgKDNJXs+od+1UbRy62uk7dYal3h98I4WojfIqMoGcg=",
"owner": "simple-nixos-mailserver", "owner": "simple-nixos-mailserver",
"repo": "nixos-mailserver", "repo": "nixos-mailserver",
"rev": "53007af63fade28853408370c4c600a63dd97f41", "rev": "af7d3bf5daeba3fc28089b015c0dd43f06b176f2",
"type": "gitlab" "type": "gitlab"
}, },
"original": { "original": {
"owner": "simple-nixos-mailserver", "owner": "simple-nixos-mailserver",
"ref": "nixos-25.05", "ref": "master",
"repo": "nixos-mailserver", "repo": "nixos-mailserver",
"type": "gitlab" "type": "gitlab"
} }

View File

@ -1,15 +1,7 @@
{ {
inputs = { inputs = {
# nixpkgs # nixpkgs
nixpkgs.url = "github:NixOS/nixpkgs/release-25.05"; nixpkgs.url = "github:NixOS/nixpkgs/master";
nixpkgs-linkwarden = {
url = "https://github.com/NixOS/nixpkgs/pull/347353.diff";
flake = false;
};
nixpkgs-memos = {
url = "https://github.com/NixOS/nixpkgs/pull/426687.diff";
flake = false;
};
# Common Utils Among flake inputs # Common Utils Among flake inputs
systems.url = "github:nix-systems/default"; systems.url = "github:nix-systems/default";
@ -27,16 +19,16 @@
# Home Manager # Home Manager
home-manager = { home-manager = {
url = "github:nix-community/home-manager/release-25.05"; url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
# Mail Server # Mail Server
simple-nixos-mailserver = { simple-nixos-mailserver = {
url = "gitlab:simple-nixos-mailserver/nixos-mailserver/nixos-25.05"; url = "gitlab:simple-nixos-mailserver/nixos-mailserver/master";
inputs = { inputs = {
nixpkgs.follows = "nixpkgs"; nixpkgs.follows = "nixpkgs";
nixpkgs-25_05.follows = "nixpkgs"; nixpkgs-24_05.follows = "nixpkgs";
flake-compat.follows = "flake-compat"; flake-compat.follows = "flake-compat";
}; };
}; };
@ -51,6 +43,19 @@
}; };
}; };
# Radio
radio = {
url = "git+https://git.neet.dev/zuckerberg/radio.git?ref=main&rev=5bf607fed977d41a269942a7d1e92f3e6d4f2473";
inputs = {
nixpkgs.follows = "nixpkgs";
flake-utils.follows = "flake-utils";
};
};
radio-web = {
url = "git+https://git.neet.dev/zuckerberg/radio-web.git";
flake = false;
};
# Dailybot # Dailybot
dailybuild_modules = { dailybuild_modules = {
url = "git+https://git.neet.dev/zuckerberg/dailybot.git"; url = "git+https://git.neet.dev/zuckerberg/dailybot.git";
@ -79,11 +84,13 @@
outputs = { self, nixpkgs, ... }@inputs: outputs = { self, nixpkgs, ... }@inputs:
let let
machineHosts = (import ./common/machine-info/moduleless.nix machines = (import ./common/machine-info/moduleless.nix
{ {
inherit nixpkgs; inherit nixpkgs;
assertionsModule = "${nixpkgs}/nixos/modules/misc/assertions.nix"; assertionsModule = "${nixpkgs}/nixos/modules/misc/assertions.nix";
}).machines.hosts; }).machines;
machineHosts = machines.hosts;
machineRoles = machines.roles;
in in
{ {
nixosConfigurations = nixosConfigurations =
@ -108,7 +115,10 @@
home-manager.useGlobalPkgs = true; home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true; home-manager.useUserPackages = true;
home-manager.users.googlebot = import ./home/googlebot.nix; home-manager.users.googlebot = import ./home/googlebot.nix {
inherit hostname;
inherit machineRoles;
};
}; };
# because nixos specialArgs doesn't work for containers... need to pass in inputs a different way # because nixos specialArgs doesn't work for containers... need to pass in inputs a different way
@ -126,14 +136,8 @@
name = "nixpkgs-patched"; name = "nixpkgs-patched";
src = nixpkgs; src = nixpkgs;
patches = [ patches = [
# ./patches/gamepadui.patch ./patches/gamepadui.patch
./patches/dont-break-nix-serve.patch ./patches/dont-break-nix-serve.patch
# music-assistant needs a specific custom version of librespot
# I tried to use an overlay but my attempts to override the rust package did not work out
# despite me following guides and examples specific to rust packages.
./patches/librespot-pin.patch
inputs.nixpkgs-linkwarden
inputs.nixpkgs-memos
]; ];
}; };
patchedNixpkgs = nixpkgs.lib.fix (self: (import "${patchedNixpkgsSrc}/flake.nix").outputs { self = nixpkgs; }); patchedNixpkgs = nixpkgs.lib.fix (self: (import "${patchedNixpkgsSrc}/flake.nix").outputs { self = nixpkgs; });

View File

@ -1,8 +1,9 @@
{ config, lib, pkgs, osConfig, ... }: { hostname, machineRoles }:
{ config, lib, pkgs, ... }:
let let
# Check if the current machine has the role "personal" # Check if the current machine has the role "personal"
thisMachineIsPersonal = osConfig.thisMachine.hasRole."personal"; thisMachineIsPersonal = builtins.elem hostname machineRoles.personal;
in in
{ {
home.username = "googlebot"; home.username = "googlebot";
@ -11,47 +12,6 @@ in
home.stateVersion = "24.11"; home.stateVersion = "24.11";
programs.home-manager.enable = true; programs.home-manager.enable = true;
services.ssh-agent.enable = true;
# System Monitoring
programs.btop.enable = true;
programs.bottom.enable = true;
# Modern "ls" replacement
programs.pls.enable = true;
programs.pls.enableFishIntegration = true;
programs.eza.enable = true;
# Graphical terminal
programs.ghostty.enable = thisMachineIsPersonal;
programs.ghostty.settings = {
theme = "Snazzy";
font-size = 10;
};
# Advanced terminal file explorer
programs.broot.enable = true;
# Shell promt theming
programs.fish.enable = true;
programs.starship.enable = true;
programs.starship.enableFishIntegration = true;
programs.starship.enableInteractive = true;
# programs.oh-my-posh.enable = true;
# programs.oh-my-posh.enableFishIntegration = true;
# Advanced search
programs.ripgrep.enable = true;
# tldr: Simplified, example based and community-driven man pages.
programs.tealdeer.enable = true;
home.shellAliases = {
sudo = "doas";
ls2 = "eza";
explorer = "broot";
};
programs.zed-editor = { programs.zed-editor = {
enable = thisMachineIsPersonal; enable = thisMachineIsPersonal;
extensions = [ extensions = [

View File

@ -7,20 +7,12 @@
../../common/ssh.nix ../../common/ssh.nix
]; ];
boot.initrd.availableKernelModules = [ boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "e1000" "e1000e" "virtio_pci" "r8169" ];
"ata_piix"
"uhci_hcd"
"e1000"
"e1000e"
"virtio_pci"
"r8169"
"sdhci"
"sdhci_pci"
"mmc_core"
"mmc_block"
];
boot.kernelParams = [ boot.kernelParams = [
"panic=30"
"boot.panic_on_fail" # reboot the machine upon fatal boot issues
"console=ttyS0,115200" # enable serial console "console=ttyS0,115200" # enable serial console
"console=tty1"
]; ];
boot.kernel.sysctl."vm.overcommit_memory" = "1"; boot.kernel.sysctl."vm.overcommit_memory" = "1";

View File

@ -6,8 +6,7 @@
nixos-hardware.nixosModules.framework-13-7040-amd nixos-hardware.nixosModules.framework-13-7040-amd
]; ];
# boot.kernelPackages = pkgs.linuxPackages_6_14; boot.kernelPackages = pkgs.linuxPackages_latest;
boot.kernelPackages = pkgs.linuxPackages_6_13;
hardware.framework.amd-7040.preventWakeOnAC = true; hardware.framework.amd-7040.preventWakeOnAC = true;
services.fwupd.enable = true; services.fwupd.enable = true;

View File

@ -15,6 +15,10 @@
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKPnLt84bKhUgFxjQf10+Htro9Lo1Pabqm8mGalBUniv" "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKPnLt84bKhUgFxjQf10+Htro9Lo1Pabqm8mGalBUniv"
]; ];
deployKeys = [
# TODO
];
remoteUnlock = { remoteUnlock = {
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN0N80r0Sl2WlJaUqfxZPkOtYyGumFazkIqq7eq3Gd2o"; hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN0N80r0Sl2WlJaUqfxZPkOtYyGumFazkIqq7eq3Gd2o";
onionHost = "ll6yjnkh4psmfwmtkmqoutl4gq4elqzbmjxv4s6gpgoavyi3kwhjvnqd.onion"; onionHost = "ll6yjnkh4psmfwmtkmqoutl4gq4elqzbmjxv4s6gpgoavyi3kwhjvnqd.onion";

View File

@ -56,6 +56,44 @@
config.services.drastikbot.dataDir config.services.drastikbot.dataDir
]; ];
# music radio
vpn-container.enable = true;
vpn-container.config = {
services.radio = {
enable = true;
host = "radio.runyan.org";
};
};
pia.wireguard.badPortForwardPorts = [ ];
services.nginx.virtualHosts = {
"radio.runyan.org" = {
enableACME = true;
forceSSL = true;
locations = {
"/stream.mp3" = {
proxyPass = "http://vpn.containers:8001/stream.mp3";
extraConfig = ''
add_header Access-Control-Allow-Origin *;
'';
};
"/".root = config.inputs.radio-web;
};
};
"radio.neet.space" = {
enableACME = true;
forceSSL = true;
locations = {
"/stream.mp3" = {
proxyPass = "http://vpn.containers:8001/stream.mp3";
extraConfig = ''
add_header Access-Control-Allow-Origin *;
'';
};
"/".root = config.inputs.radio-web;
};
};
};
# matrix home server # matrix home server
services.matrix = { services.matrix = {
enable = true; enable = true;
@ -78,7 +116,7 @@
services.postgresql.package = pkgs.postgresql_15; services.postgresql.package = pkgs.postgresql_15;
# iodine DNS-based vpn # iodine DNS-based vpn
# services.iodine.server.enable = true; services.iodine.server.enable = true;
# proxied web services # proxied web services
services.nginx.enable = true; services.nginx.enable = true;
@ -95,12 +133,12 @@
root = "/var/www/tmp"; root = "/var/www/tmp";
}; };
# redirect neet.cloud to nextcloud instance on runyan.org # redirect runyan.org to github
services.nginx.virtualHosts."neet.cloud" = { services.nginx.virtualHosts."runyan.org" = {
enableACME = true; enableACME = true;
forceSSL = true; forceSSL = true;
extraConfig = '' extraConfig = ''
return 302 https://runyan.org$request_uri; rewrite ^/(.*)$ https://github.com/GoogleBot42 redirect;
''; '';
}; };
@ -111,4 +149,7 @@
# librechat # librechat
services.librechat.enable = true; services.librechat.enable = true;
services.librechat.host = "chat.neet.dev"; services.librechat.host = "chat.neet.dev";
services.actual-server.enable = true;
services.actual-server.hostname = "actual.runyan.org";
} }

View File

@ -22,7 +22,8 @@
# networking.useDHCP = lib.mkForce true; # networking.useDHCP = lib.mkForce true;
networking.usePredictableInterfaceNames = false; # TODO
# networking.usePredictableInterfaceNames = true;
powerManagement.cpuFreqGovernor = "ondemand"; powerManagement.cpuFreqGovernor = "ondemand";

View File

@ -10,6 +10,8 @@
# Enable serial output # Enable serial output
boot.kernelParams = [ boot.kernelParams = [
"panic=30"
"boot.panic_on_fail" # reboot the machine upon fatal boot issues
"console=ttyS0,115200n8" # enable serial console "console=ttyS0,115200n8" # enable serial console
]; ];
boot.loader.grub.extraConfig = " boot.loader.grub.extraConfig = "
@ -21,8 +23,6 @@
# firmware # firmware
firmware.x86_64.enable = true; firmware.x86_64.enable = true;
nixpkgs.config.allowUnfree = true; nixpkgs.config.allowUnfree = true;
hardware.enableRedistributableFirmware = true;
hardware.enableAllFirmware = true;
# boot # boot
bios = { bios = {
@ -31,18 +31,20 @@
}; };
# disks # disks
remoteLuksUnlock.enable = true;
boot.initrd.luks.devices."enc-pv".device = "/dev/disk/by-uuid/9b090551-f78e-45ca-8570-196ed6a4af0c";
fileSystems."/" = fileSystems."/" =
{ {
device = "/dev/disk/by-uuid/6aa7f79e-bef8-4b0f-b22c-9d1b3e8ac94b"; device = "/dev/disk/by-uuid/421c82b9-d67c-4811-8824-8bb57cb10fce";
fsType = "ext4"; fsType = "btrfs";
}; };
fileSystems."/boot" = fileSystems."/boot" =
{ {
device = "/dev/disk/by-uuid/14dfc562-0333-4ddd-b10c-4eeefe1cd05f"; device = "/dev/disk/by-uuid/d97f324f-3a2e-4b84-ae2a-4b3d1209c689";
fsType = "ext3"; fsType = "ext3";
}; };
swapDevices = swapDevices =
[{ device = "/dev/disk/by-uuid/adf37c64-3b54-480c-a9a7-099d61c6eac7"; }]; [{ device = "/dev/disk/by-uuid/45bf58dd-67eb-45e4-9a98-246e23fa7abd"; }];
nixpkgs.hostPlatform = "x86_64-linux"; nixpkgs.hostPlatform = "x86_64-linux";
} }

View File

@ -1,17 +0,0 @@
{
hostNames = [
"router"
"192.168.6.159"
"192.168.3.1"
];
arch = "x86_64-linux";
systemRoles = [
"server"
"wireless"
"router"
];
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKDCMhEvWJxFBNyvpyuljv5Uun8AdXCxBK9HvPBRe5x6";
}

View File

@ -0,0 +1,21 @@
{
hostNames = [
"router"
"192.168.1.228"
];
arch = "x86_64-linux";
systemRoles = [
"server"
"wireless"
"router"
];
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFr2IHmWFlaLaLp5dGoSmFEYKA/eg2SwGXAogaOmLsHL";
remoteUnlock = {
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJOw5dTPmtKqiPBH6VKyz5MYBubn8leAh5Eaw7s/O85c";
onionHost = "jxx2exuihlls2t6ncs7rvrjh2dssubjmjtclwr2ysvxtr4t7jv55xmqd.onion";
};
}

View File

@ -31,10 +31,8 @@ in
networking.bridges = { networking.bridges = {
br0 = { br0 = {
interfaces = [ interfaces = [
"eth2" "enp2s0"
# "wlp4s0" "wlp4s0"
# "wlan1"
"wlan0"
"wlan1" "wlan1"
]; ];
}; };
@ -66,173 +64,142 @@ in
services.dnsmasq = { services.dnsmasq = {
enable = true; enable = true;
settings = { extraConfig = ''
# sensible behaviours # sensible behaviours
domain-needed = true; domain-needed
bogus-priv = true; bogus-priv
no-resolv = true; no-resolv
# upstream name servers # upstream name servers
server = [ server=1.1.1.1
"1.1.1.1" server=8.8.8.8
"8.8.8.8"
];
# local domains # local domains
expand-hosts = true; expand-hosts
domain = "home"; domain=home
local = "/home/"; local=/home/
# Interfaces to use DNS on # Interfaces to use DNS on
interface = "br0"; interface=br0
# subnet IP blocks to use DHCP on # subnet IP blocks to use DHCP on
dhcp-range = "${cfg.privateSubnet}.10,${cfg.privateSubnet}.254,24h"; dhcp-range=${cfg.privateSubnet}.10,${cfg.privateSubnet}.254,24h
}; '';
}; };
services.hostapd = { services.hostapd = {
enable = true; enable = true;
radios = { radios = {
# Simple 2.4GHz AP # 2.4GHz
wlan0 = { wlp4s0 = {
band = "2g";
noScan = true;
channel = 6;
countryCode = "US"; countryCode = "US";
networks.wlan0 = { wifi4 = {
ssid = "CXNK00BF9176-1"; capabilities = [ "LDPC" "GF" "SHORT-GI-20" "SHORT-GI-40" "TX-STBC" "RX-STBC1" "MAX-AMSDU-7935" "HT40+" ];
authentication.saePasswords = [{ passwordFile = "/run/agenix/hostapd-pw-CXNK00BF9176"; }]; };
wifi5 = {
operatingChannelWidth = "20or40";
capabilities = [ "MAX-A-MPDU-LEN-EXP0" ];
};
wifi6 = {
enable = true;
singleUserBeamformer = true;
singleUserBeamformee = true;
multiUserBeamformer = true;
operatingChannelWidth = "20or40";
};
networks = {
wlp4s0 = {
ssid = "CXNK00BF9176";
authentication.saePasswordsFile = "/run/agenix/hostapd-pw-CXNK00BF9176";
};
# wlp4s0-1 = {
# ssid = "- Experimental 5G Tower by AT&T";
# authentication.saePasswordsFile = "/run/agenix/hostapd-pw-experimental-tower";
# };
# wlp4s0-2 = {
# ssid = "FBI Surveillance Van 2";
# authentication.saePasswordsFile = "/run/agenix/hostapd-pw-experimental-tower";
# };
};
settings = {
he_oper_centr_freq_seg0_idx = 8;
vht_oper_centr_freq_seg0_idx = 8;
}; };
}; };
# WiFi 5 (5GHz) with two advertised networks # 5GHz
wlan1 = { wlan1 = {
band = "5g"; band = "5g";
channel = 0; noScan = true;
channel = 128;
countryCode = "US"; countryCode = "US";
networks.wlan1 = { wifi4 = {
ssid = "CXNK00BF9176-1"; capabilities = [ "LDPC" "GF" "SHORT-GI-20" "SHORT-GI-40" "TX-STBC" "RX-STBC1" "MAX-AMSDU-7935" "HT40-" ];
authentication.saePasswords = [{ passwordFile = "/run/agenix/hostapd-pw-CXNK00BF9176"; }]; };
wifi5 = {
operatingChannelWidth = "160";
capabilities = [ "RXLDPC" "SHORT-GI-80" "SHORT-GI-160" "TX-STBC-2BY1" "SU-BEAMFORMER" "SU-BEAMFORMEE" "MU-BEAMFORMER" "MU-BEAMFORMEE" "RX-ANTENNA-PATTERN" "TX-ANTENNA-PATTERN" "RX-STBC-1" "SOUNDING-DIMENSION-3" "BF-ANTENNA-3" "VHT160" "MAX-MPDU-11454" "MAX-A-MPDU-LEN-EXP7" ];
};
wifi6 = {
enable = true;
singleUserBeamformer = true;
singleUserBeamformee = true;
multiUserBeamformer = true;
operatingChannelWidth = "160";
};
networks = {
wlan1 = {
ssid = "CXNK00BF9176";
authentication.saePasswordsFile = "/run/agenix/hostapd-pw-CXNK00BF9176";
};
# wlan1-1 = {
# ssid = "- Experimental 5G Tower by AT&T";
# authentication.saePasswordsFile = "/run/agenix/hostapd-pw-experimental-tower";
# };
# wlan1-2 = {
# ssid = "FBI Surveillance Van 5";
# authentication.saePasswordsFile = "/run/agenix/hostapd-pw-experimental-tower";
# };
};
settings = {
vht_oper_centr_freq_seg0_idx = 114;
he_oper_centr_freq_seg0_idx = 114;
}; };
}; };
}; };
}; };
age.secrets.hostapd-pw-experimental-tower.file = ../../secrets/hostapd-pw-experimental-tower.age;
age.secrets.hostapd-pw-CXNK00BF9176.file = ../../secrets/hostapd-pw-CXNK00BF9176.age; age.secrets.hostapd-pw-CXNK00BF9176.file = ../../secrets/hostapd-pw-CXNK00BF9176.age;
# wlan0 5Ghz 00:0a:52:08:38:32 hardware.firmware = [
# wlp4s0 2.4Ghz 00:0a:52:08:38:33 pkgs.mt7916-firmware
];
# services.hostapd = { nixpkgs.overlays = [
# enable = true; (self: super: {
# radios = { mt7916-firmware = pkgs.stdenvNoCC.mkDerivation {
# # 2.4GHz pname = "mt7916-firmware";
# wlp4s0 = { version = "custom-feb-02-23";
# band = "2g"; src = ./firmware/mediatek; # from here https://github.com/openwrt/mt76/issues/720#issuecomment-1413537674
# noScan = true; dontBuild = true;
# channel = 6; installPhase = ''
# countryCode = "US"; for i in \
# wifi4 = { mt7916_eeprom.bin \
# capabilities = [ "LDPC" "GF" "SHORT-GI-20" "SHORT-GI-40" "TX-STBC" "RX-STBC1" "MAX-AMSDU-7935" "HT40+" ]; mt7916_rom_patch.bin \
# }; mt7916_wa.bin \
# wifi5 = { mt7916_wm.bin;
# operatingChannelWidth = "20or40"; do
# capabilities = [ "MAX-A-MPDU-LEN-EXP0" ]; install -D -pm644 $i $out/lib/firmware/mediatek/$i
# }; done
# wifi6 = { '';
# enable = true; meta = with lib; {
# singleUserBeamformer = true; license = licenses.unfreeRedistributableFirmware;
# singleUserBeamformee = true; };
# multiUserBeamformer = true; };
# operatingChannelWidth = "20or40"; })
# }; ];
# networks = {
# wlp4s0 = {
# ssid = "CXNK00BF9176";
# authentication.saePasswordsFile = "/run/agenix/hostapd-pw-CXNK00BF9176";
# };
# # wlp4s0-1 = {
# # ssid = "- Experimental 5G Tower by AT&T";
# # authentication.saePasswordsFile = "/run/agenix/hostapd-pw-experimental-tower";
# # };
# # wlp4s0-2 = {
# # ssid = "FBI Surveillance Van 2";
# # authentication.saePasswordsFile = "/run/agenix/hostapd-pw-experimental-tower";
# # };
# };
# settings = {
# he_oper_centr_freq_seg0_idx = 8;
# vht_oper_centr_freq_seg0_idx = 8;
# };
# };
# # 5GHz
# wlan1 = {
# band = "5g";
# noScan = true;
# channel = 128;
# countryCode = "US";
# wifi4 = {
# capabilities = [ "LDPC" "GF" "SHORT-GI-20" "SHORT-GI-40" "TX-STBC" "RX-STBC1" "MAX-AMSDU-7935" "HT40-" ];
# };
# wifi5 = {
# operatingChannelWidth = "160";
# capabilities = [ "RXLDPC" "SHORT-GI-80" "SHORT-GI-160" "TX-STBC-2BY1" "SU-BEAMFORMER" "SU-BEAMFORMEE" "MU-BEAMFORMER" "MU-BEAMFORMEE" "RX-ANTENNA-PATTERN" "TX-ANTENNA-PATTERN" "RX-STBC-1" "SOUNDING-DIMENSION-3" "BF-ANTENNA-3" "VHT160" "MAX-MPDU-11454" "MAX-A-MPDU-LEN-EXP7" ];
# };
# wifi6 = {
# enable = true;
# singleUserBeamformer = true;
# singleUserBeamformee = true;
# multiUserBeamformer = true;
# operatingChannelWidth = "160";
# };
# networks = {
# wlan1 = {
# ssid = "CXNK00BF9176";
# authentication.saePasswordsFile = "/run/agenix/hostapd-pw-CXNK00BF9176";
# };
# # wlan1-1 = {
# # ssid = "- Experimental 5G Tower by AT&T";
# # authentication.saePasswordsFile = "/run/agenix/hostapd-pw-experimental-tower";
# # };
# # wlan1-2 = {
# # ssid = "FBI Surveillance Van 5";
# # authentication.saePasswordsFile = "/run/agenix/hostapd-pw-experimental-tower";
# # };
# };
# settings = {
# vht_oper_centr_freq_seg0_idx = 114;
# he_oper_centr_freq_seg0_idx = 114;
# };
# };
# };
# };
# age.secrets.hostapd-pw-experimental-tower.file = ../../secrets/hostapd-pw-experimental-tower.age;
# age.secrets.hostapd-pw-CXNK00BF9176.file = ../../secrets/hostapd-pw-CXNK00BF9176.age;
# hardware.firmware = [
# pkgs.mt7916-firmware
# ];
# nixpkgs.overlays = [
# (self: super: {
# mt7916-firmware = pkgs.stdenvNoCC.mkDerivation {
# pname = "mt7916-firmware";
# version = "custom-feb-02-23";
# src = ./firmware/mediatek; # from here https://github.com/openwrt/mt76/issues/720#issuecomment-1413537674
# dontBuild = true;
# installPhase = ''
# for i in \
# mt7916_eeprom.bin \
# mt7916_rom_patch.bin \
# mt7916_wa.bin \
# mt7916_wm.bin;
# do
# install -D -pm644 $i $out/lib/firmware/mediatek/$i
# done
# '';
# meta = with lib; {
# license = licenses.unfreeRedistributableFirmware;
# };
# };
# })
# ];
}; };
} }

View File

@ -214,6 +214,15 @@
statusCheck = true; statusCheck = true;
id = "0_836_matrix"; id = "0_836_matrix";
}; };
radio = {
title = "Radio";
description = "Radio service";
icon = "generative";
url = "https://radio.runyan.org";
target = "sametab";
statusCheck = true;
id = "1_836_radio";
};
mumble = { mumble = {
title = "Mumble"; title = "Mumble";
description = "voice.neet.space"; description = "voice.neet.space";
@ -271,6 +280,7 @@
}; };
servicesList = [ servicesList = [
servicesItems.matrix servicesItems.matrix
servicesItems.radio
servicesItems.mumble servicesItems.mumble
servicesItems.irc servicesItems.irc
servicesItems.git servicesItems.git

View File

@ -20,13 +20,13 @@
secretKeyFile = "/run/agenix/binary-cache-private-key"; secretKeyFile = "/run/agenix/binary-cache-private-key";
}; };
age.secrets.binary-cache-private-key.file = ../../../secrets/binary-cache-private-key.age; age.secrets.binary-cache-private-key.file = ../../../secrets/binary-cache-private-key.age;
# users.users.cache-push = { users.users.cache-push = {
# isNormalUser = true; isNormalUser = true;
# openssh.authorizedKeys.keys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINpUZFFL9BpBVqeeU63sFPhR9ewuhEZerTCDIGW1NPSB" ]; openssh.authorizedKeys.keys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINpUZFFL9BpBVqeeU63sFPhR9ewuhEZerTCDIGW1NPSB" ];
# }; };
# nix.settings = { nix.settings = {
# trusted-users = [ "cache-push" ]; trusted-users = [ "cache-push" ];
# }; };
services.iperf3.enable = true; services.iperf3.enable = true;
services.iperf3.openFirewall = true; services.iperf3.openFirewall = true;
@ -75,32 +75,6 @@
services.lidarr.enable = true; services.lidarr.enable = true;
services.lidarr.user = "public_data"; services.lidarr.user = "public_data";
services.lidarr.group = "public_data"; services.lidarr.group = "public_data";
services.recyclarr = {
enable = true;
configuration = {
radarr.radarr_main = {
api_key = {
_secret = "/run/credentials/recyclarr.service/radarr-api-key";
};
base_url = "http://localhost:7878";
quality_definition.type = "movie";
};
sonarr.sonarr_main = {
api_key = {
_secret = "/run/credentials/recyclarr.service/sonarr-api-key";
};
base_url = "http://localhost:8989";
quality_definition.type = "series";
};
};
};
systemd.services.recyclarr.serviceConfig.LoadCredential = [
"radarr-api-key:/run/agenix/radarr-api-key"
"sonarr-api-key:/run/agenix/sonarr-api-key"
];
services.transmission = { services.transmission = {
enable = true; enable = true;
@ -171,8 +145,6 @@
8686 # lidarr 8686 # lidarr
9091 # transmission web 9091 # transmission web
]; ];
age.secrets.radarr-api-key.file = ../../../secrets/radarr-api-key.age;
age.secrets.sonarr-api-key.file = ../../../secrets/sonarr-api-key.age;
# jellyfin # jellyfin
# jellyfin cannot run in the vpn container and use hardware encoding # jellyfin cannot run in the vpn container and use hardware encoding
@ -237,7 +209,7 @@
globalRedirect = "s0.neet.dev"; globalRedirect = "s0.neet.dev";
}; };
} }
(mkVirtualHost "ha.s0.neet.dev" "http://localhost:${toString config.services.home-assistant.config.http.server_port}") (mkVirtualHost "ha.s0.neet.dev" "http://localhost:8123") # home assistant
(mkVirtualHost "esphome.s0.neet.dev" "http://localhost:6052") (mkVirtualHost "esphome.s0.neet.dev" "http://localhost:6052")
(mkVirtualHost "zigbee.s0.neet.dev" "http://localhost:55834") (mkVirtualHost "zigbee.s0.neet.dev" "http://localhost:55834")
{ {
@ -250,11 +222,6 @@
(mkVirtualHost "vacuum.s0.neet.dev" "http://192.168.1.125") # valetudo (mkVirtualHost "vacuum.s0.neet.dev" "http://192.168.1.125") # valetudo
(mkVirtualHost "sandman.s0.neet.dev" "http://192.168.9.14:3000") # es (mkVirtualHost "sandman.s0.neet.dev" "http://192.168.9.14:3000") # es
(mkVirtualHost "todo.s0.neet.dev" "http://localhost:${toString config.services.vikunja.port}") (mkVirtualHost "todo.s0.neet.dev" "http://localhost:${toString config.services.vikunja.port}")
(mkVirtualHost "budget.s0.neet.dev" "http://localhost:${toString config.services.actual.settings.port}") # actual budget
(mkVirtualHost "linkwarden.s0.neet.dev" "http://localhost:${toString config.services.linkwarden.port}")
(mkVirtualHost "memos.s0.neet.dev" "http://localhost:${toString config.services.memos.port}")
(mkVirtualHost "outline.s0.neet.dev" "http://localhost:${toString config.services.outline.port}")
(mkVirtualHost "languagetool.s0.neet.dev" "http://localhost:${toString config.services.languagetool.port}")
]; ];
tailscaleAuth = { tailscaleAuth = {
@ -275,11 +242,6 @@
"zigbee.s0.neet.dev" "zigbee.s0.neet.dev"
"vacuum.s0.neet.dev" "vacuum.s0.neet.dev"
"todo.s0.neet.dev" "todo.s0.neet.dev"
"budget.s0.neet.dev"
"linkwarden.s0.neet.dev"
# "memos.s0.neet.dev" # messes up memos /auth route
# "outline.s0.neet.dev" # messes up outline /auth route
"languagetool.s0.neet.dev"
]; ];
expectedTailnet = "koi-bebop.ts.net"; expectedTailnet = "koi-bebop.ts.net";
}; };
@ -308,6 +270,7 @@
openMinimalFirewall = true; openMinimalFirewall = true;
}; };
# TODO: setup backup
services.vikunja = { services.vikunja = {
enable = true; enable = true;
port = 61473; port = 61473;
@ -321,65 +284,5 @@
"/var/lib/vikunja" "/var/lib/vikunja"
]; ];
services.actual.enable = true;
services.linkwarden = {
enable = true;
enableRegistration = true;
port = 41709;
environment.NEXTAUTH_URL = "https://linkwarden.s0.neet.dev/api/v1/auth";
environment.FLARESOLVERR_URL = "http://localhost:${toString config.services.flaresolverr.port}/v1";
environmentFile = "/run/agenix/linkwarden-environment";
package = pkgs.linkwarden.overrideAttrs (oldAttrs: {
# Add patch that adds support for flaresolverr
patches = oldAttrs.patches or [ ] ++ [
# https://github.com/linkwarden/linkwarden/pull/1251
../../../patches/linkwarden-flaresolverr.patch
];
});
};
age.secrets.linkwarden-environment.file = ../../../secrets/linkwarden-environment.age;
services.meilisearch = {
enable = true;
package = pkgs.meilisearch;
};
services.flaresolverr = {
enable = true;
port = 48072;
};
services.memos = {
enable = true;
address = "127.0.0.1";
port = 57643;
};
services.outline = {
enable = true;
forceHttps = false; # https through nginx
port = 43933;
publicUrl = "https://outline.s0.neet.dev";
storage.storageType = "local";
smtp = {
secure = true;
fromEmail = "robot@runyan.org";
username = "robot@runyan.org";
replyEmail = "robot@runyan.org";
host = "mail.neet.dev";
port = 465;
passwordFile = "/run/agenix/robots-email-pw";
};
};
age.secrets.robots-email-pw = {
file = ../../../secrets/robots-email-pw.age;
owner = config.services.outline.user;
};
services.languagetool = {
enable = true;
port = 60613;
};
boot.binfmt.emulatedSystems = [ "aarch64-linux" "armv7l-linux" ]; boot.binfmt.emulatedSystems = [ "aarch64-linux" "armv7l-linux" ];
} }

View File

@ -136,16 +136,37 @@ lib.mkMerge [
} }
{ {
# hardware encode/decode with amdgpu vaapi # hardware encode/decode with amdgpu vaapi
services.frigate.vaapiDriver = "radeonsi"; systemd.services.frigate = {
environment.LIBVA_DRIVER_NAME = "radeonsi";
serviceConfig = {
SupplementaryGroups = [ "render" "video" ]; # for access to dev/dri/*
AmbientCapabilities = "CAP_PERFMON";
};
};
services.frigate.settings.ffmpeg.hwaccel_args = "preset-vaapi"; services.frigate.settings.ffmpeg.hwaccel_args = "preset-vaapi";
} }
{ {
# Coral TPU for frigate # Coral TPU for frigate
services.udev.packages = [ pkgs.libedgetpu ];
users.groups.apex = { };
systemd.services.frigate.environment.LD_LIBRARY_PATH = "${pkgs.libedgetpu}/lib";
systemd.services.frigate.serviceConfig.SupplementaryGroups = [ "apex" ];
# Coral PCIe driver
boot.extraModulePackages = with config.boot.kernelPackages; [ gasket ];
services.udev.extraRules = ''
SUBSYSTEM=="apex", MODE="0660", GROUP="apex"
'';
services.frigate.settings.detectors.coral = { services.frigate.settings.detectors.coral = {
type = "edgetpu"; type = "edgetpu";
device = "pci"; device = "pci";
}; };
} }
{
# Fix bug in nixos module where cache is not cleared when starting the service because "rm" cannot be found
systemd.services.frigate.serviceConfig.ExecStartPre = lib.mkForce "${pkgs.bash}/bin/sh -c 'rm -f /var/cache/frigate/*.mp4'";
}
{ {
# Don't require authentication for frigate # Don't require authentication for frigate
# This is ok because the reverse proxy already requires tailscale access anyway # This is ok because the reverse proxy already requires tailscale access anyway

View File

@ -58,11 +58,7 @@
}; };
swapDevices = [ ]; swapDevices = [ ];
### networking ###
# systemd.network.enable = true;
networking = { networking = {
# useNetworkd = true;
dhcpcd.enable = false; dhcpcd.enable = false;
vlans = { vlans = {
@ -81,12 +77,24 @@
prefixLength = 22; prefixLength = 22;
}]; }];
defaultGateway = { defaultGateway = "192.168.1.1";
interface = "eth1";
address = "192.168.1.1";
};
nameservers = [ "1.1.1.1" "8.8.8.8" ]; nameservers = [ "1.1.1.1" "8.8.8.8" ];
}; };
# networking = {
# vlans = {
# iot = {
# id = 2;
# interface = "eth1";
# };
# };
# defaultGateway = {
# interface = "eth1";
# address = "192.168.1.1";
# metric = 10; # always use this route as default gateway
# };
# };
powerManagement.cpuFreqGovernor = "powersave"; powerManagement.cpuFreqGovernor = "powersave";
} }

View File

@ -15,15 +15,7 @@
]; ];
}; };
networking.firewall.allowedTCPPorts = [ networking.firewall.allowedTCPPorts = [
# mqtt 1883 # mqtt
1883
# Must be exposed so some local devices (such as HA voice preview) can pair with home assistant
config.services.home-assistant.config.http.server_port
# Music assistant (must be exposed so local devices can fetch the audio stream from it)
8095
8097
]; ];
services.zigbee2mqtt = { services.zigbee2mqtt = {
@ -55,7 +47,6 @@
enable = true; enable = true;
extraComponents = [ extraComponents = [
"default_config" "default_config"
"rest_command"
"esphome" "esphome"
"met" "met"
"radio_browser" "radio_browser"
@ -83,23 +74,13 @@
"homekit_controller" "homekit_controller"
"zha" "zha"
"bluetooth" "bluetooth"
"whisper"
"piper"
"wyoming"
"tts"
"music_assistant"
"openai_conversation"
]; ];
# config = null;
config = { config = {
# Includes dependencies for a basic setup # Includes dependencies for a basic setup
# https://www.home-assistant.io/integrations/default_config/ # https://www.home-assistant.io/integrations/default_config/
default_config = { }; default_config = { };
homeassistant = {
external_url = "https://ha.s0.neet.dev";
internal_url = "http://192.168.1.2:${toString config.services.home-assistant.config.http.server_port}";
};
# Enable reverse proxy support # Enable reverse proxy support
http = { http = {
use_x_forwarded_for = true; use_x_forwarded_for = true;
@ -113,44 +94,6 @@
]; ];
# Allow using automations generated from the UI # Allow using automations generated from the UI
"automation ui" = "!include automations.yaml"; "automation ui" = "!include automations.yaml";
"rest_command" = {
json_post_request = {
url = "{{ url }}";
method = "POST";
content_type = "application/json";
payload = "{{ payload | default('{}') }}";
};
};
}; };
}; };
services.wyoming.faster-whisper.servers."hass" = {
enable = true;
uri = "tcp://0.0.0.0:45785";
model = "distil-small.en";
language = "en";
};
services.wyoming.piper.servers."hass" = {
enable = true;
uri = "tcp://0.0.0.0:45786";
voice = "en_US-joe-medium";
};
services.music-assistant = {
enable = true;
providers = [
"hass"
"hass_players"
"jellyfin"
"radiobrowser"
"spotify"
];
};
networking.hosts = {
# Workaround for broken spotify api integration
# https://github.com/librespot-org/librespot/issues/1527#issuecomment-3167094158
"0.0.0.0" = [ "apresolve.spotify.com" ];
};
} }

View File

@ -1,7 +1,6 @@
{ {
hostNames = [ hostNames = [
"s0" "s0"
"s0.neet.dev"
]; ];
arch = "x86_64-linux"; arch = "x86_64-linux";
@ -14,17 +13,12 @@
"gitea-actions-runner" "gitea-actions-runner"
"frigate" "frigate"
"zigbee" "zigbee"
"media-server"
"linkwarden"
"outline"
]; ];
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAwiXcUFtAvZCayhu4+AIcF+Ktrdgv9ee/mXSIhJbp4q"; hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAwiXcUFtAvZCayhu4+AIcF+Ktrdgv9ee/mXSIhJbp4q";
remoteUnlock = { remoteUnlock = {
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFNiceeFMos5ZXcYem4yFxh8PiZNNnuvhlyLbQLrgIZH"; hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFNiceeFMos5ZXcYem4yFxh8PiZNNnuvhlyLbQLrgIZH";
clearnetHost = "192.168.1.2";
onionHost = "r3zvf7f2ppaeithzswigma46pajt3hqytmkg3rshgknbl3jbni455fqd.onion"; onionHost = "r3zvf7f2ppaeithzswigma46pajt3hqytmkg3rshgknbl3jbni455fqd.onion";
}; };
} }

View File

@ -0,0 +1,39 @@
{ lib
, buildNpmPackage
, fetchFromGitHub
, python3
, nodejs
, runtimeShell
}:
buildNpmPackage rec {
pname = "actual-server";
version = "24.10.1";
src = fetchFromGitHub {
owner = "actualbudget";
repo = pname;
rev = "refs/tags/v${version}";
hash = "sha256-VJAD+lNamwuYmiPJLXkum6piGi5zLOHBp8cUeZagb4s=";
};
npmDepsHash = "sha256-Z2e4+JMhI/keLerT0F4WYdLnXHRQCqL7NjNyA9SFEF8=";
patches = [
./migrations-should-use-pkg-path.patch
];
postPatch = ''
cp ${./package-lock.json} package-lock.json
'';
dontNpmBuild = true;
postInstall = ''
mkdir -p $out/bin
cat <<EOF > $out/bin/actual-server
#!${runtimeShell}
exec ${nodejs}/bin/node $out/lib/node_modules/actual-sync/app.js "\$@"
EOF
chmod +x $out/bin/actual-server
'';
}

View File

@ -0,0 +1,48 @@
diff --git a/src/load-config.js b/src/load-config.js
index d99ce42..42d1351 100644
--- a/src/load-config.js
+++ b/src/load-config.js
@@ -3,7 +3,8 @@ import path from 'node:path';
import { fileURLToPath } from 'node:url';
import createDebug from 'debug';
-const debug = createDebug('actual:config');
+// const debug = createDebug('actual:config');
+const debug = console.log;
const debugSensitive = createDebug('actual-sensitive:config');
const projectRoot = path.dirname(path.dirname(fileURLToPath(import.meta.url)));
@@ -108,6 +109,7 @@ const finalConfig = {
serverFiles: process.env.ACTUAL_SERVER_FILES || config.serverFiles,
userFiles: process.env.ACTUAL_USER_FILES || config.userFiles,
webRoot: process.env.ACTUAL_WEB_ROOT || config.webRoot,
+ dataDir: process.env.ACTUAL_DATA_DIR || config.dataDir,
https:
process.env.ACTUAL_HTTPS_KEY && process.env.ACTUAL_HTTPS_CERT
? {
diff --git a/src/migrations.js b/src/migrations.js
index cba7db0..9983471 100644
--- a/src/migrations.js
+++ b/src/migrations.js
@@ -1,6 +1,12 @@
import migrate from 'migrate';
import path from 'node:path';
import config from './load-config.js';
+import { fileURLToPath } from 'url';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+const appRoot = path.dirname(__dirname);
+const migrationsDirectory = path.join(appRoot, "migrations");
export default function run(direction = 'up') {
console.log(
@@ -13,7 +19,7 @@ export default function run(direction = 'up') {
stateStore: `${path.join(config.dataDir, '.migrate')}${
config.mode === 'test' ? '-test' : ''
}`,
- migrationsDirectory: `${path.join(config.projectRoot, 'migrations')}`,
+ migrationsDirectory
},
(err, set) => {
if (err) {

8954
overlays/actualbudget/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -4,4 +4,10 @@ final: prev:
let let
system = prev.system; system = prev.system;
in in
{ } {
actual-server = prev.callPackage ./actualbudget { };
# Copied entire package from nixpkgs to downgrade to python 3.11 since 3.12 is broken.
# See: https://github.com/Py-KMS-Organization/py-kms/issues/117
pykms = prev.callPackage ./pykms.nix { };
}

103
overlays/pykms.nix Normal file
View File

@ -0,0 +1,103 @@
{ lib
, fetchFromGitHub
, python311
, writeText
, writeShellScript
, sqlite
, nixosTests
}:
let
pypkgs = python311.pkgs;
dbSql = writeText "create_pykms_db.sql" ''
CREATE TABLE clients(
clientMachineId TEXT,
machineName TEXT,
applicationId TEXT,
skuId TEXT,
licenseStatus TEXT,
lastRequestTime INTEGER,
kmsEpid TEXT,
requestCount INTEGER
);
'';
dbScript = writeShellScript "create_pykms_db.sh" ''
set -eEuo pipefail
db=''${1:-/var/lib/pykms/clients.db}
if [ ! -e $db ] ; then
${lib.getBin sqlite}/bin/sqlite3 $db < ${dbSql}
fi
'';
in
pypkgs.buildPythonApplication rec {
pname = "pykms";
version = "unstable-2024-05-28";
src = fetchFromGitHub {
owner = "Py-KMS-Organization";
repo = "py-kms";
rev = "646f4766f4195dbea0695700a7ddaac70a3294f9";
hash = "sha256-YCqPo7WkCfXyuTjL4IYapdcUN/Vj465Jz6XhQessyz0=";
};
sourceRoot = "${src.name}/py-kms";
propagatedBuildInputs = with pypkgs; [
systemd
pytz
tzlocal
dnspython
];
postPatch = ''
siteDir=$out/${python311.sitePackages}
substituteInPlace pykms_DB2Dict.py \
--replace "'KmsDataBase.xml'" "'$siteDir/KmsDataBase.xml'"
'';
format = "other";
# there are no tests
doCheck = false;
installPhase = ''
runHook preInstall
mkdir -p $siteDir
PYTHONPATH="$PYTHONPATH:$siteDir"
mv * $siteDir
for b in Client Server ; do
makeWrapper ${python311.interpreter} $out/bin/''${b,,} \
--argv0 pykms-''${b,,} \
--add-flags $siteDir/pykms_$b.py \
--set PYTHONPATH $PYTHONPATH
done
install -Dm755 ${dbScript} $out/libexec/create_pykms_db.sh
install -Dm644 ../README.md -t $out/share/doc/pykms
${python311.interpreter} -m compileall $siteDir
runHook postInstall
'';
passthru.tests = { inherit (nixosTests) pykms; };
meta = with lib; {
description = "Windows KMS (Key Management Service) server written in Python";
homepage = "https://github.com/Py-KMS-Organization/py-kms";
license = licenses.unlicense;
maintainers = with maintainers; [
peterhoeg
zopieux
];
};
}

View File

@ -1,28 +0,0 @@
diff --git a/pkgs/applications/audio/librespot/default.nix b/pkgs/applications/audio/librespot/default.nix
index 9694c3d0cf4f..ca9502de7ee1 100644
--- a/pkgs/applications/audio/librespot/default.nix
+++ b/pkgs/applications/audio/librespot/default.nix
@@ -25,14 +25,19 @@ rustPlatform.buildRustPackage rec {
version = "0.6.0";
src = fetchFromGitHub {
- owner = "librespot-org";
+ owner = "googlebot42";
repo = "librespot";
- rev = "v${version}";
- sha256 = "sha256-dGQDRb7fgIkXelZKa+PdodIs9DxbgEMlVGJjK/hU3Mo=";
+ rev = "786cc46199e583f304a84c786acb0a9b37bc3fbd";
+ sha256 = "sha256-xaOrqC8yCjF23Tz31RD3CzqZ3xxrDM6ncW1yoovEaGQ=";
};
useFetchCargoVendor = true;
- cargoHash = "sha256-SqvJSHkyd1IicT6c4pE96dBJNNodULhpyG14HRGVWCk=";
+ cargoHash = "sha256-sUAZgOuBD9CGAy1mRqLRzVnVfxB0DqSCNAc2yzItTCA=";
+
+ cargoBuildFlags = [
+ "--features"
+ "passthrough-decoder"
+ ];
nativeBuildInputs = [
pkg-config

View File

@ -1,144 +0,0 @@
commit 3dac9f081f267e4a528decbd9d50e1f45ea7c2ba
Author: SteveImmanuel <steve@telepix.net>
Date: Fri Jun 27 13:07:38 2025 +0900
Add flaresolverr support into linkwarden
diff --git a/.env.sample b/.env.sample
index bd3abcb0..0ca96d92 100644
--- a/.env.sample
+++ b/.env.sample
@@ -43,6 +43,7 @@ TEXT_CONTENT_LIMIT=
SEARCH_FILTER_LIMIT=
INDEX_TAKE_COUNT=
MEILI_TIMEOUT=
+FLARESOLVERR_URL=
# AI Settings
NEXT_PUBLIC_OLLAMA_ENDPOINT_URL=
diff --git a/apps/worker/lib/archiveHandler.ts b/apps/worker/lib/archiveHandler.ts
index 8ae19e2c..6c8656b2 100644
--- a/apps/worker/lib/archiveHandler.ts
+++ b/apps/worker/lib/archiveHandler.ts
@@ -6,6 +6,7 @@ import {
chromium,
devices,
} from "playwright";
+import axios from 'axios';
import { prisma } from "@linkwarden/prisma";
import sendToWayback from "./preservationScheme/sendToWayback";
import { AiTaggingMethod } from "@linkwarden/prisma/client";
@@ -75,6 +76,22 @@ export default async function archiveHandler(
});
const { browser, context } = await getBrowser();
+
+ const captchaSolve = await solveCaptcha(link.url);
+
+ if (captchaSolve.status === 'error') {
+ console.error('Error solving captcha');
+ } else if (captchaSolve.status === 'fail') {
+ console.warn('Failed solving captcha');
+ } else if (captchaSolve.status === 'skip') {
+ console.info('Skip solving captcha');
+ } else {
+ if (captchaSolve.solution) {
+ console.info('Solving captcha');
+ await context.addCookies(captchaSolve.solution.cookies);
+ }
+ }
+
const page = await context.newPage();
createFolder({ filePath: `archives/preview/${link.collectionId}` });
@@ -105,6 +122,7 @@ export default async function archiveHandler(
aiTag: user.aiTaggingMethod !== AiTaggingMethod.DISABLED,
};
+ let newLinkName = '';
try {
await Promise.race([
(async () => {
@@ -127,6 +145,7 @@ export default async function archiveHandler(
// archive url
await page.goto(link.url, { waitUntil: "domcontentloaded" });
+ newLinkName = await page.title();
const metaDescription = await page.evaluate(() => {
const description = document.querySelector(
@@ -186,10 +205,16 @@ export default async function archiveHandler(
where: { id: link.id },
});
- if (finalLink)
+ if (finalLink) {
+ // Replace the captcha-blocked link name if it has not been updated by user, else keep the same name
+ if (newLinkName === '' || finalLink.name === newLinkName || finalLink.name !== 'Just a moment...') {
+ newLinkName = finalLink.name;
+ }
+
await prisma.link.update({
where: { id: link.id },
data: {
+ name: newLinkName,
lastPreserved: new Date().toISOString(),
readable: !finalLink.readable ? "unavailable" : undefined,
image: !finalLink.image ? "unavailable" : undefined,
@@ -203,6 +228,7 @@ export default async function archiveHandler(
: undefined,
},
});
+ }
else {
await removeFiles(link.id, link.collectionId);
}
@@ -271,6 +297,48 @@ export function getBrowserOptions(): LaunchOptions {
return browserOptions;
}
+async function solveCaptcha(url: string, maxTimeout: number = 60000): Promise<{
+ status: string,
+ solution?: {
+ cookies: {
+ name: string,
+ value: string,
+ domain: string,
+ path: string,
+ secure: boolean,
+ expires?: number,
+ httpOnly?: boolean,
+ sameSite?: "Strict" | "Lax" | "None"
+ }[],
+ }
+}> {
+ if (process.env.FLARESOLVERR_URL) {
+ try {
+ const response = await axios.post(process.env.FLARESOLVERR_URL,
+ {
+ cmd: 'request.get',
+ url,
+ maxTimeout
+ },
+ {
+ headers: { 'Content-Type': 'application/json' }
+ }
+ )
+
+ if (response.status !== 200) {
+ return { status: 'fail' };
+ }
+
+ return { status: response.data.status, solution: response.data.solution };
+ } catch (error) {
+ console.error('Error during captcha solving:', error);
+ return { status: 'error' };
+ }
+ }
+
+ return { status: 'skip' };
+}
+
async function getBrowser(): Promise<{
browser: Browser;
context: BrowserContext;

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,9 +1,10 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 6AT2/g /5WB1i5RrjWIbnBErUWliedwnv8qTIsl8r8zbWNkOmA -> ssh-ed25519 6AT2/g WZ9p/pCsEDpKbgGDLcTtisn25kExQX9iv+tL3wyPwiY
wr8fN2FbNnCRUNgV3aZPQibXHy1MNjMP9SMK7urHL+o vom2z9QRIQSFB0+4/7lSWUEB0eoAG+08nXgiUg/OSX4
-> ssh-ed25519 w3nu8g exWaIxM68nwycLphws0PRnRvvdOuT7h3xOZqndsAHxo -> ssh-ed25519 w3nu8g ECLZwCRJVJqyUMf70EOl2/3ExTruKaxCSQlY5fBZqxk
EIUTjS57F5MKGt6bJjaFxHnbTFzUrpmrTVqNZoQ060Y VemnmGpzx1VprkybW1hPlkfmiDaNcBDoEzX0mDZgmu0
-> ssh-ed25519 evqvfg SAQyzljqtBd65bpZo6yMsIAS1d5ymjKBoODjOQMUdTs -> ssh-ed25519 dMQYog QiPsbFE8MtXnRNBwkUEC+6grqXEbDstEtxYR8uJks2w
/roobEvljSoREVHygqLNKTJHWG6rDdhXmlc4BM/7Em8 O3JWQGppFeZEd6o3W0KVTEIyNVGeLxKfTYTlgsAEVHQ
--- Gp+OLOIN5aqR3G1fSM+Epdw4B6RTXrB99Ty/YUWI0S8 --- RncZzBFEyMAkpZRWrPORA0DPHuCTNswmWG5CMNnfm4A
ÊžÁ<EFBFBD>¶…Àoÿ;¥3ŽeºÉ<>„Ôu âT éÄdŸ«‡ñüÈ<²y{ Jëë¶ñg]nŸþ+QX˜Øéóå´qEÜ™çƒ MþË/QàÓÔ#k­É[8(ß5 ñ/¼ÔËõôŒ8nàÅ¥«¸7hîtä?T˜=%zˆ°[¤ÝØ!(…uÔdÇuò@
×¢Ebƒyަù¦D=Ü!„XþtÞÔ:#¦þþãÞXÈX@ú_M

View File

@ -1,16 +1,11 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 WBT1Hw ZMrG+yubAhxfDf/hh8gSfxZuvM5hsOBQu/V/KfdcNyk -> ssh-ed25519 WBT1Hw TGdD8Nw+GPITDOXGhevSu+880DWET7WYN3nIyJ0xy2o
un2XWeWmt9pYLAk4n54A52T96sgvasNgD65AiYL9YO0 69xepRTnmaFwa4IsGJjDdwZqTSf5fz6EZK0/q3oz/ZA
-> ssh-ed25519 6AT2/g KxgJ1UJ1amcXzpcFmFFi3C3umo70iwmL5GxDaqfk1j8 -> ssh-ed25519 6AT2/g EmqXrXXsRxSS6AsH+7VMgoJTYo9eGj8ebLiLT4IWNxg
VZkDd3vgf1xX9kdzrDhmv2w/Ubq6UUJyw7UAkqmWlOU eKs5/3tQMdg5bGJKNz8PFh9C7HiV+IlOU9dzpYcGIjo
-> ssh-ed25519 r848+g MXTm1V8lHIb4oHg0glttyooeECLn0uVrHaY5NzAE718 -> ssh-ed25519 hPp1nw wsIF676is8FquF6oANNauPrumsMnfVUZpPeVKEtBOzQ
Qv+vEeuFz+sew5GmR17ALXKmpfByjwi2j93dMVAU5WY qZR8LSF+TQ2K3K0An69NHfk53ZqNEWev0IVcb71SR40
-> ssh-ed25519 hPp1nw 7dxkddbQHdVi+7dpxBHXYi8pNgMsRjfj8KLqgJFYqQc -> ssh-ed25519 w3nu8g TKHY/5JuzFMhbW9CQAOI3woX8M9b1H/XXUpIMT0Mylk
984ysvTIvdjJirkUIfNMEUVKkzUTCBDAOgLbKZj5AhU byJV0/BJ3ftG5eYv5BeyIYBi0VoWG31HRiENUxSeYE8
-> ssh-ed25519 w3nu8g fC2KGM9/I2Sl0VHkYZy7YbvmF5CMWRIUahgGaGiZPVM --- fwHXHtE/sMLqCLSD8tR0oCPgNuif9Y/ncHU97hbf/Bw
+IGvvjHj14bV9PS2r0L3pFNV+eDCE63ZmNdHfCG0yCw f"+ÉŒqc<71>H†Ñjï!JSšË¡Ì|yMìðX¼þMl<4D>ýçCy™îUXn»Égk¨ë)¤óOY§uº„¦²¶g%è Håvœ5ô!$Jœ¤Š…¶$<24>#Dö;±¥àÖ }ÏŸcçKšˆ{R/
-> ssh-ed25519 evqvfg fAr1POoqc5y1stRkCJfgCHSW8QXIPEiFZT0STSP931s
wFWWX6tPV0mV5HC3be7a2xr4Pax35rT16S0h7eiF990
--- N5A6/IK5wKwzUT20Hxu/37ovLEkLGGj7Y30p1hu5fNM
r&BãHA%ǺhŒRÕ²~!Ä<>{bÝ[ØU?k(µD
öB7[öùððb/ [¿YçÚÃy[yOCjT-9:†xâ²(;ÝüœXy\¬NhÄíòäLPö¼§y¿mG±—ÑÁfŽý4aT<²Š ‡çaŠè†@

View File

@ -1,9 +1,7 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 hPp1nw p8uus03Jrn9HtEelmufFx2orYkSlyAq90L7bTm3n/GQ -> ssh-ed25519 hPp1nw zOXF7NsZjm+DCYrJ+Ap2mX35JUt37CLJP1RhyOjB/XE
Ki+Pf1RG27H2wmgxXz2u7fqlU2hrxTmBZCn8RMIh8wI ePprJM2cnhYZhP8aJUXOZeGHJm/DHlRYomWN+lFaU6w
-> ssh-ed25519 w3nu8g UQQYC93hQLRIgaA5P3Upax2HzfNddWkjTkAyZF5/hFs -> ssh-ed25519 w3nu8g gjeFAbFWXyPdGauKHXAzuIP9fmaj2Oysq9fHO8q7u38
33fVUBBaJFRhDIuZoM8Rn1fd0JwqjmyXsbu4pioxXw4 KiMR0pgEPtsfZnYAIsH7UHNhnsB6rtsW/hqV03uS2dI
-> ssh-ed25519 evqvfg /J1fpbZORlnYADjqAcF8kV81e+mlxXC4mhMwozG7YXw --- BPzPECz1g6vEv4OlRn6+FnWP9oq3tn6TN2o867icxYA
KYAtHd1MyNiEKoN/RgBCOsn/uCvXIjusXPFWW4urMFY }ìjºùŽ+l&þàx<C3A0>-TïÝb‡ÅèØÄ·<C384>Dg‰ñgc*ˆ0<CB86>÷µcp …}uþ7Íßã%9Ð%ŽÒú©S¥ ‰|šôêöQœÃ*9Ø$ä ŽŠ ÍÖi;)c?ÍÍýGh¤VvªnlÚs¤Ç)r }Ò­hE5K‡bg­-<2D>®
--- KVdBWZjlOA44GAK3GubvPaXlbg1zdpxL7+rJ4hv4Lmo
X/{×[PĽćÎĹ+ł$_Z,t\#e¶ĐĂ ř>„,0ié©Ě°ÖVńB§QÍ8,Řëńú'JŞR×=´ŐLśęÉäęLłÝ@běđp?HĹM¦2—uÁňł€ŕÝp'g:ÄWŔ;YXs©ÍóN ĂO´m»y~Łň

View File

@ -1,9 +1,11 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 hPp1nw 5wFHyqBRdZxUDa180U3RgrL4DWNF3BO60C1ytWdZvXM -> ssh-ed25519 WBT1Hw PbGwwDeulHF6kdh073rq0RvD1hlx6spnKNgKU+QeDAw
anPvoQk7kvz/wBddKYquSZ7b6dslhIrhV8wnMpC725E 7dITwSQ2p1LZuaVEzLxcGOhB97MQT2zGoRrnNUMcOFk
-> ssh-ed25519 w3nu8g McO3H/GkcqQavMokZhXAsRijGq0wiXzmN1GH29n12wg -> ssh-ed25519 hPp1nw Dn+5Fpme+JmRZKkCkqtCuD87p+sDYDA6OZ2aUmBkCRs
ooFxa+vYd49JSwdj9Knc8iDFyxX4elDb3IjOjrC5Cmo Dgg3orXF4RYT/fHtc2tRuIhOQu48zICMqgPyV47vpf4
-> ssh-ed25519 evqvfg pW/T4WXURnk7G+HL+O3STBWkQ+5by7EgwOPTcMNakyw -> ssh-ed25519 w3nu8g dghNLDH1Tm+sm42HXDhrLFtmU4iDF1yCGrO2VSgzZjo
HByJjWNhOg7PSms4Px9NO0FnFcMj1Ig2rOXhCNQri7Y 71scUVrGr4c4dunAFJYKd+uJ6aYJpSWBAk9swbv+IzM
--- LCgnSaNDEKv8du0OxZoLtyF4W02E/6pC/e1h0+XDDGA -> ssh-ed25519 dMQYog Wnl1+rh0Q3YD2s1UD0OYVm39wY/Uw1NRK3K7EFhFMls
õViÁ°“ìbð[¾í<C2BE><C3AD>%þÚ{œtäL8àP[¦2z{g/KG®üÈAëZýåšœÂïàþ0pÃSg²…ó µ¿P³ÊYÊù—$•á wXF6QBonlCalS1vI9cxzWgv1Gi+yAtYn6HrYCfpl5Nw
--- rLOoGk0iX+wuNd1CKv7g2PRd2Ic+8JHCQhrVBaF9zbE
<EFBFBD>òüüˤ/A¦Ì(ØiHC¸@¢Þð‰h`ˆ3ªá´' ¬ÚöáDì>ð¿¤~¸ÿÁö?ÑÃMêÙ@<40>t°(“Ò@ö׿^xÆ}

View File

@ -1,9 +1,9 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 6AT2/g kH4DufpuybglKzupJsGvWKfWsZ5xhRwefdPKkx/AuW4 -> ssh-ed25519 6AT2/g 98/m3t8axoVBE6WzdxBtRhV2uSQKSCXwQjyxfWXPmQk
QrDu/vSbgEIgYSnraG5u37RNp6Mp6ARjqzAduy9iX/Y AxV0FTvqbWfk/gf65d05PcotbEnYr4PgDQnsaYxP/MU
-> ssh-ed25519 w3nu8g mBt4VQNJAMwcseVhc8k/mB5XThbQT48OnstkWaGQ8zQ -> ssh-ed25519 w3nu8g jys7B4COD4iINANeSCD3BqGFoghxTmsbuXoOOIiP+wQ
6w7lMJA8giG9PVux1ncjCPrN7ER0S7uWi8UjhOOeMS8 b7eSN5fe4szfliINOr7ZQ7AoSsIK5akmIQ6uLDabcIE
-> ssh-ed25519 evqvfg uM4SAf1aMCvtRKdPn5BFr1EWlBGVgbgjp6OkuMV7GnU -> ssh-ed25519 dMQYog ToNUqTPYmxpz9OUcC94egELcPfHQHCErfHN6l9kSrRY
Zi5X5TL7phRpwsbUVsFgS0qHvqtLdckz01qDfVypn/s 2KoSVoWp+FH29YfH57ri2KOvhkuqYew1+PXm99e0BaI
--- I92hNxGkHSHR/fQhUI5UAXvzIvMd+YBih9nFP5IZW3w --- Cjk3E/MjgCF45aLlFeyoGiaUEZk/QuKtsvPb6GpzD8Q
áÎ_§ØN/ úú®H<C2AE>ô¡ÒaŽeõâ¼ÈêÅhÊB¤ê»[Ô´ðªqÂ<71>\ý+M:FÜîñgP¦¤¤nh¨¼N/¸2ÞÇl8µ3q> rHtUJG×n m°å>‹“~czÆê匦†``ÜÏqX«š'ÁÎ%ôwÔž~×ÄL·eä'a±]û´LÉÀ‰%ÍYTÊÓc9f¡W¶Ã^¤9ÊõÙÝ2®™æ¶ÆBÌa ƒ™

Binary file not shown.

View File

@ -1,7 +1,7 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 w3nu8g 6127BAGsI/0p6vDXwo4W9ehh/Tzr/XblDYFYYtNfziU -> ssh-ed25519 w3nu8g ER07FH17Wm9op5F4pCftNK76f+nNjtA6zQc/2dLyAHI
k0ZYtv6bTTKTdE81mPqwmuC3KSgimMn+noAm3LrzAkw nxxq/8tS3ENJhAEIhJCiSi7dV+68AmcEMh9zvZoWpdY
-> ssh-ed25519 evqvfg n2/Ds6CbjTEGK0/faiUj+S1VbZ8cLjqAMBZEVM6PIwQ -> ssh-ed25519 dMQYog JelCfh+akP7C/i1kimq3fC5PRQa9gHbmBaOnjKu+PDw
sPaFFL2bU2mUzKf8DLIHqXxGXZcER5gnKq9VpGA+GyU GVTwo7MzkpCereZRh0HVjGYmtdMY1gHowMZtUQl7XQw
--- /KNS4o0n8Ol/i8vRJ1dBJklDR1UhR6kQNcM2rwqGNRw --- p2l83t3bEdBrrp1ctaqqKhwB4l2McgZqZTtc2SXgd8Q
Îd;©<>_ɕԟ ŽVë3_"ûÈ)“Ú(e…âßqÍþ$+ÓA¨æ±ÿç” Y#G ø±ôeÆd\Yå4lXVF§U©<55>þM||)دÔûú•¶Ü8¿>ëž­%ðóJ$à´Õè

View File

@ -1,9 +1,9 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 6AT2/g +D1KEq8bDAErE5NJABbpoONsmolgc2aNDPucgzJZT2A -> ssh-ed25519 6AT2/g Knb25oYknkiXyMqVBR3T0sFSO4hDjWUTq3xIml/b4ig
jJpebutfcnNYT71oiwEATP89ZSnmjXx3skHrrk2MLOY n7xamnrZ+SCWiKqniF3r2JvH4G8q2pJaHzF0riNEDf4
-> ssh-ed25519 w3nu8g MHVAh0Jp4pTahZoHIw5wUsp8STJ3rlH1C6+jrA+sJFI -> ssh-ed25519 w3nu8g 7+2R5RpLjBf4jjj3S8ibMquUWgRMrifziGQubwuLrhA
sqMpGLw3HPumgAE7GYddT/iuewYZH3xy7mE5gyrWloA 3jLCalnbA3Z2jr8Zs+qrpzSoi3Jv6E5OV2binpr3Kk4
-> ssh-ed25519 evqvfg HoJqNfMckAJbHBCleHcSnI1VbOx3l7lQv1yM030G5mc -> ssh-ed25519 dMQYog Nh2e7me0tiG7ZwQK8669VS0LCYFSH+b33I9tr8uI5CY
cscFawOoA4rA3EAc/FtCafLYlVZ4vcDEEmzouOrwVVY 7Gs1N9eZa1CGR9pczzugHbqnghqevX7kQCOeqR4q0eI
--- sjGmx4I61x+AP72rCFeWyNJAEUlQz/az5rQ7jNfjXjU --- OzW+omJsZA/b4DMF4hdQga7JVgiEYluZok3r8JM258I
ËgîV&\÷MŒ²ÜuÊMm;ãY?‡úRDÆ`‰(2Õ·Õ øÒ‘à–é €Æ²)¸ Àò¦Ý£T *³²ÝPކAcèÈ1·@Át¸e÷nf&ù#I7‡a‰Ûâc†ÃÀ<C383>êbDâ~aõ]1w=Á

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,12 +1,11 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 6AT2/g rk3jNJlQwab++isNOPpQJZlb4rL7nIAYfoAhlvY9QTc -> ssh-ed25519 6AT2/g MGKlbzVOk5+czgAOerwl+eIyOifXJm/q4UgQUXVpx1c
J+6/MRepeixmDQzz3bRd/AMJpZls60dUBjrHh+p759Y 43l6s4+5TSMQyO9tAg7v9Y5OdXOjKYz56lbr9Jm2r+o
-> ssh-ed25519 hPp1nw GnjIH+V6mLcXvfNhiBBwqBvY6NO8W+1sPcgvu6fS0nI -> ssh-ed25519 hPp1nw aOxni4sFPPgedUkBOuOyEWfFPJrhdTJnivIaWt5RJxM
qP6jDxd+0h/AZhsBs7om0BDutrPmP/1NUEuZ7LBlxmw KNaxijzSMp7EjYKwWiAP66nPYYZK3/VXL8u+3uJt6bg
-> ssh-ed25519 w3nu8g QwztUaCCtEVeI9AbJn5dKH07Y2fal+Nn9/bsnBkTJgI -> ssh-ed25519 w3nu8g qTAzEzQbFze35AtbvkYREw3wa7ApDN5u7RSZUXrEpms
/Ce0a9bGv6RmQiK8C3wIvMCh5DM+m/EujYFsXgNjieY Dy0uGF458A9RJMvDl2XKOkEABbbRgT+eIgvb6ZOEQqg
-> ssh-ed25519 evqvfg VLoQNzz62Q1KawvTHWeyBfCGTlGYNPQcdTaPq7cLxDo -> ssh-ed25519 dMQYog 5DfYuGeWuN0/CO6WWbFIi7LaKl23FXYVdPROM+TFpCA
eabkTR9iUPYqCj50R7rwYcrMqcs+RHWqRZai2KKzPMQ PDBdDn+YUMKYNKFkCEfXesmkB/XUxZRK3ddQt0kqQ7g
--- fQkT/xI/iptJd/UmihEcUWx77d2wr6bOj5lecPa/P8o --- JOeG87EVD+QBx6n+rMoPTOni0PyoG7xx4a2USNiapYI
,V„ý²lz­ºOP¿'Ìü2ÑÃ4¦o¸ü|ÅK´» ²FYL†Ì&ìâÓáéÊÁ>†©Ä\@emVÈnŒm½®6u—O@wRèãÁåý^_ Zsý{ÅiÁ_\+ô@@Üò߸ù&_š5­$¿Gt2¢rF“y×ÄQ§Iaž 7ôÙÉzàgf­%O(µÙ,VéÂ}ÿn|û'J¸2ø¨óQÑ B
ztFŠ©~

View File

@ -1,9 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 hPp1nw MRItBkM6GC+jht3ly0K04wCptE28UI9FmFAm2+8KHHw
Pbz+oZcWtzSz4eyWyRbi/a89Q3PripNJ+PYM/wiLKq0
-> ssh-ed25519 w3nu8g a5G6FrbGmglm2Ba2T6NPsaVP+/4g//jh9ui/BVzR0EU
f0xNuCbhC0FqqFH6CD9jPAgWmTEZqga/fRjU6VMdfSk
-> ssh-ed25519 evqvfg 1lhGzpY7I0fKimq6sQ/zWUHCFSEaN31rmGCckUepfHY
3OfNrzAajS6azIT90CmVnBzXLXcwMw/BRhOfbcuuz3c
--- vagzuZWeWUcZTBISnL4vNVcpMX2CbJGHwfaAFiIZeHM
en¼!<z'ß‹û,W 8†}òÙö=åà—lõÖŸê^^5iÌ”½àÜd<C39C>æß»ü<C2BB>t.yçw>_%

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -17,7 +17,7 @@ with roles;
"cris-hashed-email-pw.age".publicKeys = email-server; "cris-hashed-email-pw.age".publicKeys = email-server;
"sasl_relay_passwd.age".publicKeys = email-server; "sasl_relay_passwd.age".publicKeys = email-server;
"hashed-robots-email-pw.age".publicKeys = email-server; "hashed-robots-email-pw.age".publicKeys = email-server;
"robots-email-pw.age".publicKeys = gitea ++ outline; "robots-email-pw.age".publicKeys = gitea;
# nix binary cache # nix binary cache
# public key: s0.koi-bebop.ts.net:OjbzD86YjyJZpCp9RWaQKANaflcpKhtzBMNP8I2aPUU= # public key: s0.koi-bebop.ts.net:OjbzD86YjyJZpCp9RWaQKANaflcpKhtzBMNP8I2aPUU=
@ -31,14 +31,12 @@ with roles;
# cloud # cloud
"nextcloud-pw.age".publicKeys = nextcloud; "nextcloud-pw.age".publicKeys = nextcloud;
"whiteboard-server-jwt-secret.age".publicKeys = nextcloud;
"smb-secrets.age".publicKeys = personal ++ media-center; "smb-secrets.age".publicKeys = personal ++ media-center;
"oauth2-proxy-env.age".publicKeys = server; "oauth2-proxy-env.age".publicKeys = server;
# services # services
"searx.age".publicKeys = nobody; "searx.age".publicKeys = nobody;
"wolframalpha.age".publicKeys = dailybot; "wolframalpha.age".publicKeys = dailybot;
"linkwarden-environment.age".publicKeys = linkwarden;
# hostapd # hostapd
"hostapd-pw-experimental-tower.age".publicKeys = nobody; "hostapd-pw-experimental-tower.age".publicKeys = nobody;
@ -62,8 +60,4 @@ with roles;
# zigbee2mqtt secrets # zigbee2mqtt secrets
"zigbee2mqtt.yaml.age".publicKeys = zigbee; "zigbee2mqtt.yaml.age".publicKeys = zigbee;
# Sonarr and Radarr secrets
"radarr-api-key.age".publicKeys = media-server;
"sonarr-api-key.age".publicKeys = media-server;
} }

View File

@ -1,17 +1,19 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 N7drjg lVrCcpRGeAJ+62CF+fTT+iGKmaaiBk2rmtzS3jz4ux4 -> ssh-ed25519 N7drjg x2s9QZ7Ijvg4t2peGng9/zX1ZmnGggsvWHJFHEktCgw
BbMLKa0uCoopsV0BekIcApzyJggQf4uFICuC26inA/c o64an6DJ6Be8Jlhzn9ciQTByRAK5f2ckankCRH3y+Uw
-> ssh-ed25519 jQaHAA k7JCJlbAKDuH+bLhaoiQQssN5gfwPw9w30J3OAA4nWg -> ssh-ed25519 yHDAQw HYHo6anhKDnD74ab04Ql4RB8+WBA6EavYASX7532NCE
fQ6te5iDG54mn5oXdarxMYPeze4ZWbk1yPAsLsTFby4 aTp2V9g18yzUTq1ezqETj6jM2Yb1Bt5+JNkrIDT2Djs
-> ssh-ed25519 w3nu8g r3wLOavRLT++n+NaBRtcQqKXFTFhRYGl8naqUWNR0kE -> ssh-ed25519 jQaHAA xGKcIQOkO/i4E2ZWZ+O4sAp7ADqCRqfRQHhKQu6yWh4
pYkqQIiwzpN/XkDBrfCuFPc3yzyFjRbdCcFmRaY8iIU RJnqK/t0YQrIej8fRDJGjOtQD7VvgJRfCUWR0/UYcSY
-> ssh-ed25519 evqvfg b+BUWYHdu1z38I0BMqpkSf5qaeaCm2C+vf9Hcqgjlg4 -> ssh-ed25519 w3nu8g P9DQy19TvDCi3nfOhFj73bNZEtUs1BrLubt5/BtLoU4
PK0y5MadYrM9ANyTMdHKXRTNi5cwD8/+19mN+vaTNiM Sx41bk41dQYa3eoBayUMRIHqMWaRiwXm8BqErDBSbDw
-> ssh-ed25519 jQaHAA 86i8je5q4vVBfdi/Ws8/n4R/Z25uLw1e6zXDza8SwiI -> ssh-ed25519 dMQYog OWU92PMFo9tGtlkK9zlmMFhh81TGkYlcX1PrxZl35yc
5yuvdl0InHxrjRyi4SJOWEo6pWZt/mX8BsaFer3NwlE owDk8wWXETS+iybhTMDmQH+eBuzZRDJIlVGCwu4LqTI
-> ssh-ed25519 w3nu8g N2QWi7I8V//jfK2ZGsXwBkEt2Zh7/5zpWCKUNV30bFA -> ssh-ed25519 jQaHAA MzA8dSYZ/Ysp4ogKEEu84mal8779RgkT4Gy6rBEw+kM
ZmjY/lwFaVeM88FZSGwG+BYHi+32UPffZPZPbVcw+J8 m75x/b83aP5G1vg7EXlcLizcm16fEAUAD+VNcdTMnnQ
-> ssh-ed25519 evqvfg cZflDyFn9H85TnSbi2HFrdVvlT5uZ+6+l4stOaoyOxE -> ssh-ed25519 w3nu8g AAA3Me3KJgLvtQvyxLvlQ7pCnv7w73ja6Z2+3A82eGs
3HpWWCbWoU1ufbi02xpXnU47Ti6YjrpMVh/mS5jgO0M +yCW7qCdjk0fiQJmH8poMoc7APKyX/PY7zZyAG1O+Yg
--- wF990HQn1zh8JVo2alfC/QhpFimLsLDtj26DREVYr18 -> ssh-ed25519 dMQYog Dd8e6srT+EIl2PH0RP1bQVsDx+HCQjhFndx5TFyhfx8
QhE{+帻R(+­ ÝNYIľŤ<ýęţk¦/ČÖŻ„pA<70>ݶ°Đ_ž'ËĹ«ž‰@3ů;»°÷-0‰Çˇab9W5ÔĂęźbU3)ASóĹ÷Śe÷ůQ/SMJ“_šĹe<16>Ža*‡:ť<>µ j7Met77pWZzK9cMTt29gWB+d9YFVH5T9qs+ulHS3kAo
--- MgOK/g5hOVkGuUNDBSgVeGc9+ndjxLEA7nKSfLJMr4s
~Ÿ‹¬&”™)<29>ŠG®Ÿ¨‡'UÐÞzc¾uFGì(<ò¯ùçV"ƒÕ3þH0x0$•<>w$Yv O3 "Ï×ðV~ÀЏHÁ~XÛ]GœÆqµ®ã÷œ¢y'ãÓ*Dê±ÏúœÕk#\ðAï<41>5ë{«Fe\~

View File

@ -1,9 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 hPp1nw aoj3IvYutQWfkOYOcDu0g7/FX05Y1t5NE2dP/x50gw8
KV2kpClMmBPavyyhtC2coc3Gw9/QJQwXxfM13aKRrvQ
-> ssh-ed25519 w3nu8g ZjQIXYV3oK5ppG9ltfojwZ0Z93wFvXdiVBnFz5ncSSQ
CI3je4tMSb9ws+IyAgBVokFdy7z23n2EwtDrvLTziM8
-> ssh-ed25519 evqvfg bWwaEp5s9nvzzQXbPd3rwmy4Ei9PWZg3Gk2I1nYBcCM
PwLLVWVI0GY4snYRadT92NZFneuA54yzL+Ie4RWDxDk
--- aqM1/sssbDgs4DNsGHqiaVH1LCyhh0vtoHSD3ju67Ew
&ネ゙<EFBE88>タニg~ハ*Y<12>訷E┴<45>゙oE,yセワE{濁チ瑩ャ*レ訶_A=キ6 =怨M'燕ヘァr0<72>

View File

@ -1,9 +1,10 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 6AT2/g G3ahigKIYvEJNDgz97yprVfANFzbR2uKcvBPNAxgwWI -> ssh-ed25519 6AT2/g Kw5/he5m/XAJUNv8XEJQU+e+Ou7hCYluMXXWlHiePXY
iLpm56WMuc1Y10FwZ8HPOyBFNlhm1nWFS05DMXsjDD4 GkhJOzSlcC9S7bs8FuDNMvMaFU3+fQ5z+o+Pb8wllp8
-> ssh-ed25519 w3nu8g lx5NuJq4c4wwww887MFA1qwuLPVvddvG83l4xLzUYgk -> ssh-ed25519 w3nu8g fUORtXN1ygOeV42jveCosGXR/Y6R6OG6DK7LPDBEAk8
JgYBgcPw1jBa5yLSFBYVjf4jdoJJPoV6Q/d4Hkr3Efs yFpoasbY/sl6BQp0LVBQnInA4Kxd8A8meEObU1KD108
-> ssh-ed25519 evqvfg Gw0pMtP3bxgZXeEseJ+2xSb21AFX46JCAeHMroEJg1c -> ssh-ed25519 dMQYog 75qVEe6/1yOV4DDLAOGaufs3ojx1/Sc1fIQOe+Oirz0
qj1BjH+J9HOwYxoL2PEMa74nxfk9nlakl+40qoFunJ4 iDFsr6/30AHKH6hUs/WTpHEM8WQ03QMlGbtQkGrnVCU
--- 5Om+5hhrNjOi0MRmrb8N1t9vVnM3wWosDsJCARknPNk --- islx8t7a6bShXGxvYeDVuUxkmAMtpUfr0Gp7aYrJUkI
©5HÉòÉ;)ôŽ\K“Au¯7ìx¢jûox…e*FÈæ€†)èµ&<26> úÑú} é<> 2Ûí4¤†7Õ
?Õw€À<E282AC>JÁÆØv ¨º9,ËxÅŠò¨‰¦Æ¦ñnäH?>I­

View File

@ -1,9 +1,8 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 hPp1nw FnUaydWe7+2dVUIYrKqx2/0AzRPN3ZylczJBkTqeeXg -> ssh-ed25519 hPp1nw TSDuPaFp/Qcz4r819X4QmU/4J2TGpoX7jCCJCdFDog0
boSEnMZmQyre4mJBQkEPuXuRP90woU1obqMdh+uQKhM SwQUqEp45xMOeTkvBG6uX28kB8YWG66laYqakSgl9w4
-> ssh-ed25519 w3nu8g pIDzDUVLZuZUCn6tGKpCLVS7OmhQiMgtMvuCKfWcgiM -> ssh-ed25519 w3nu8g tLZDNE0iBgOpUB3djpNu3CgimsRc0zcds+AgctzxyQ4
zZxCUe0LslQ0ZqHV6sSMNQ5fhyscDFxVmJk0h2voEfc Oyz6XORsApM4vFxWyaD3bR/ApIUFPY3q4yGvtbosUIY
-> ssh-ed25519 evqvfg eukXn1jUoHwP/cVmYCJ1O0kYQw+Xsad1PswvbcFUMEk --- vuXlQmuOFbJhBTACN5ciH2GlOCbRCMPZdlogG2O+KOk
B0AvuWyfqK8ZFgCAW/iuXB0sKoKmB9d62ZNRTdDG43w Áëÿ!}UIì p0@Xž|°þ#晆0HÙõò#BÇRR<52>Ù
--- 0aziJ5/DCB9kJUqWhIggCqRnsuqu9s/g4Rt4vbwsBJk òùø5¾Iÿ?vX?pÝ<70><>fqÍ[lž¸˜­G7ü; UäÀOUä¶
FVÜçi`í1¥XFIÇI´oÞmf§Á³¤õ“ˆQ=ñè彈臼i?²¿ƒb?Á P6ŒA„-“°ÉY´°[Gö9<C3B6>ó î¥„½ÇÕ