Compare commits
13 Commits
cfa01fb550
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 5cf7109eaf | |||
| 4baafb7094 | |||
| 0166547091 | |||
| 1a2a4bd2bd | |||
| 94eb132962 | |||
| 8e01e1621b | |||
| b4e74fc5b2 | |||
| bbac95cac0 | |||
| e5bacc53be | |||
| 5f52a78efa | |||
| dc210d4985 | |||
| 2237c3eea3 | |||
| 771a0df831 |
51
configs/nixos/guests/adguard.nix
Normal file
51
configs/nixos/guests/adguard.nix
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
registry,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
cfg = config.guests.adguard;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.guests.adguard.adminPasswordHash = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "Bcrypt verifier for the AdGuard Home administrator password.";
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
assertions = [
|
||||||
|
{
|
||||||
|
assertion = cfg.address != null;
|
||||||
|
message = "guests.adguard.address must identify the AdGuard Home guest.";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
registry.homepage.${config.networking.hostName}.adguard = {
|
||||||
|
tab = "System";
|
||||||
|
section = "Network";
|
||||||
|
name = "AdGuard Home";
|
||||||
|
description = "Internal DNS";
|
||||||
|
icon = "adguard-home.svg";
|
||||||
|
href = "http://${cfg.address}";
|
||||||
|
};
|
||||||
|
|
||||||
|
guests.adguard = {
|
||||||
|
interior = {
|
||||||
|
modules.services.adguardhome = {
|
||||||
|
enable = true;
|
||||||
|
inherit (cfg) adminPasswordHash;
|
||||||
|
reverseProxyAddress = registry.address.${config.networking.hostName}."reverse-proxy";
|
||||||
|
};
|
||||||
|
|
||||||
|
services.resolved.settings.Resolve.DNSStubListener = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
limits = {
|
||||||
|
memory = lib.mkDefault "256M";
|
||||||
|
cpu = lib.mkDefault "100%";
|
||||||
|
tasksMax = lib.mkDefault 128;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -94,6 +94,14 @@ in
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
registry.homepage.${config.networking.hostName}.romm = {
|
||||||
|
tab = "Apps";
|
||||||
|
section = "Media";
|
||||||
|
name = "RomM";
|
||||||
|
description = "Games";
|
||||||
|
icon = "romm.png";
|
||||||
|
};
|
||||||
|
|
||||||
guests.romm = {
|
guests.romm = {
|
||||||
interior = {
|
interior = {
|
||||||
modules.services.romm.enable = true;
|
modules.services.romm.enable = true;
|
||||||
|
|||||||
@@ -40,7 +40,6 @@
|
|||||||
modules.desktop.enable = true;
|
modules.desktop.enable = true;
|
||||||
modules.desktop.apps.firefox.uiScale = "1.25";
|
modules.desktop.apps.firefox.uiScale = "1.25";
|
||||||
modules.desktop.apps.obsidian.enable = true;
|
modules.desktop.apps.obsidian.enable = true;
|
||||||
modules.desktop.apps.steam.enable = true;
|
|
||||||
|
|
||||||
registry.waybar.neogaia.battery = {
|
registry.waybar.neogaia.battery = {
|
||||||
order = 70;
|
order = 70;
|
||||||
|
|||||||
@@ -29,6 +29,14 @@
|
|||||||
|
|
||||||
registry.address.pikachu.self = "10.23.10.102";
|
registry.address.pikachu.self = "10.23.10.102";
|
||||||
|
|
||||||
|
guests.adguard = {
|
||||||
|
enable = true;
|
||||||
|
vlan = 20;
|
||||||
|
mac = "bc:24:11:91:60:bf";
|
||||||
|
address = "10.23.20.33";
|
||||||
|
adminPasswordHash = "$2b$12$wariglnrCvJOnh4b8KnB9eDX4RdQRaaTZtyXMUOilaYSn7xTR0g1e";
|
||||||
|
};
|
||||||
|
|
||||||
guests.valheim = {
|
guests.valheim = {
|
||||||
enable = true;
|
enable = true;
|
||||||
vlan = 20;
|
vlan = 20;
|
||||||
@@ -104,6 +112,7 @@
|
|||||||
domain = "games.alexion.dev";
|
domain = "games.alexion.dev";
|
||||||
protocol = "https";
|
protocol = "https";
|
||||||
port = 80;
|
port = 80;
|
||||||
|
clientMaxBodySize = "0";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -44,9 +44,10 @@
|
|||||||
modules.desktop.enable = true;
|
modules.desktop.enable = true;
|
||||||
modules.desktop.apps.obsidian.enable = true;
|
modules.desktop.apps.obsidian.enable = true;
|
||||||
modules.desktop.apps.r2modman.enable = true;
|
modules.desktop.apps.r2modman.enable = true;
|
||||||
|
modules.desktop.emulation.enable = true;
|
||||||
modules.desktop.apps.signal.enable = true;
|
modules.desktop.apps.signal.enable = true;
|
||||||
modules.desktop.apps.steam.enable = true;
|
modules.desktop.apps.steam.enable = true;
|
||||||
modules.desktop.apps.vencord.enable = true;
|
modules.desktop.apps.discord.enable = true;
|
||||||
|
|
||||||
home-manager.users.${config.user.name}.wayland.windowManager.hyprland.settings.monitor = [
|
home-manager.users.${config.user.name}.wayland.windowManager.hyprland.settings.monitor = [
|
||||||
{
|
{
|
||||||
|
|||||||
23
configs/nixos/modules/desktop/apps/discord.nix
Normal file
23
configs/nixos/modules/desktop/apps/discord.nix
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
util,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
# Official Discord provides chat, voice, and screen sharing.
|
||||||
|
let
|
||||||
|
user = config.user.name;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.modules.desktop.apps.discord.enable = lib.mkEnableOption "official Discord";
|
||||||
|
|
||||||
|
config = lib.mkIf config.modules.desktop.apps.discord.enable {
|
||||||
|
home-manager.users.${user}.home.packages = [ pkgs.discord ];
|
||||||
|
|
||||||
|
registry.window-icon.${config.networking.hostName}.discord = {
|
||||||
|
class = "[Dd]iscord";
|
||||||
|
icon = util.glyph "f1ff";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
programs.steam = {
|
programs.steam = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
remotePlay.openFirewall = true;
|
||||||
package = pkgs.steam.override {
|
package = pkgs.steam.override {
|
||||||
extraEnv.STEAM_FORCE_DESKTOPUI_SCALING = "1.5";
|
extraEnv.STEAM_FORCE_DESKTOPUI_SCALING = "1.5";
|
||||||
};
|
};
|
||||||
@@ -21,9 +22,10 @@
|
|||||||
|
|
||||||
hardware.steam-hardware.enable = true;
|
hardware.steam-hardware.enable = true;
|
||||||
|
|
||||||
environment.systemPackages = [
|
programs.gamescope = {
|
||||||
pkgs.gamescope
|
enable = true;
|
||||||
];
|
capSysNice = true;
|
||||||
|
};
|
||||||
|
|
||||||
registry.window-icon.${config.networking.hostName}.steam = {
|
registry.window-icon.${config.networking.hostName}.steam = {
|
||||||
class = "[Ss]team";
|
class = "[Ss]team";
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
pkgs,
|
|
||||||
util,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
# Vesktop, a Discord client with Vencord built in.
|
|
||||||
let
|
|
||||||
user = config.user.name;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.modules.desktop.apps.vencord.enable =
|
|
||||||
lib.mkEnableOption "Vesktop, a Discord client with Vencord built in";
|
|
||||||
|
|
||||||
config = lib.mkIf config.modules.desktop.apps.vencord.enable {
|
|
||||||
home-manager.users.${user}.home.packages = [ pkgs.vesktop ];
|
|
||||||
|
|
||||||
registry.window-icon.${config.networking.hostName}.vesktop = {
|
|
||||||
class = "[Vv]esktop";
|
|
||||||
icon = util.glyph "f1ff";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
36
configs/nixos/modules/desktop/emulation.nix
Normal file
36
configs/nixos/modules/desktop/emulation.nix
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
# Shared directories for emulators.
|
||||||
|
let
|
||||||
|
user = config.user.name;
|
||||||
|
directory = "/home/${user}/emulation";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.modules.desktop.emulation.enable = lib.mkEnableOption "shared emulation directories";
|
||||||
|
|
||||||
|
config = lib.mkIf config.modules.desktop.emulation.enable {
|
||||||
|
modules.desktop.emulation.retroarch = {
|
||||||
|
enable = lib.mkDefault true;
|
||||||
|
browserDirectory = "${directory}/roms";
|
||||||
|
};
|
||||||
|
|
||||||
|
home-manager.users.${user} = hm: {
|
||||||
|
home.file = {
|
||||||
|
".config/retroarch/saves".source = hm.config.lib.file.mkOutOfStoreSymlink "${directory}/saves";
|
||||||
|
".config/retroarch/states".source = hm.config.lib.file.mkOutOfStoreSymlink "${directory}/states";
|
||||||
|
".config/retroarch/system".source = hm.config.lib.file.mkOutOfStoreSymlink "${directory}/bios";
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.user.tmpfiles.rules = map (path: "d ${path} 0700 - - -") [
|
||||||
|
directory
|
||||||
|
"${directory}/bios"
|
||||||
|
"${directory}/roms"
|
||||||
|
"${directory}/saves"
|
||||||
|
"${directory}/states"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
62
configs/nixos/modules/desktop/emulation/retroarch.nix
Normal file
62
configs/nixos/modules/desktop/emulation/retroarch.nix
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
util,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
# RetroArch with the selected PlayStation and Sega Saturn cores.
|
||||||
|
let
|
||||||
|
cfg = config.modules.desktop.emulation.retroarch;
|
||||||
|
user = config.user.name;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.modules.desktop.emulation.retroarch = {
|
||||||
|
enable = lib.mkEnableOption "RetroArch with PlayStation and Sega Saturn cores";
|
||||||
|
|
||||||
|
browserDirectory = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "";
|
||||||
|
description = "Directory where RetroArch starts its content browser.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
home-manager.users.${user} = {
|
||||||
|
home.packages = [
|
||||||
|
(pkgs.wrapRetroArch {
|
||||||
|
cores = with pkgs.libretro; [
|
||||||
|
beetle-psx-hw
|
||||||
|
beetle-saturn
|
||||||
|
];
|
||||||
|
settings = {
|
||||||
|
savefiles_in_content_dir = "false";
|
||||||
|
savestates_in_content_dir = "false";
|
||||||
|
system_directory = "/home/${user}/.config/retroarch/system";
|
||||||
|
video_fullscreen = "true";
|
||||||
|
sort_savefiles_enable = "true";
|
||||||
|
sort_savestates_enable = "true";
|
||||||
|
cloud_sync_enable = "true";
|
||||||
|
cloud_sync_driver = "webdav";
|
||||||
|
webdav_url = "https://games.alexion.dev/api/sync/retroarch/";
|
||||||
|
cloud_sync_sync_saves = "true";
|
||||||
|
cloud_sync_sync_configs = "true";
|
||||||
|
cloud_sync_sync_thumbs = "false";
|
||||||
|
cloud_sync_sync_system = "false";
|
||||||
|
cloud_sync_sync_mode = "0";
|
||||||
|
cloud_sync_destructive = "false";
|
||||||
|
}
|
||||||
|
// lib.optionalAttrs (cfg.browserDirectory != "") {
|
||||||
|
rgui_browser_directory = cfg.browserDirectory;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
registry.window-icon.${config.networking.hostName}.retroarch = {
|
||||||
|
class = "com.libretro.RetroArch";
|
||||||
|
icon = util.glyph "f11b";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
277
configs/nixos/modules/services/adguardhome.nix
Normal file
277
configs/nixos/modules/services/adguardhome.nix
Normal file
@@ -0,0 +1,277 @@
|
|||||||
|
{ config, lib, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.modules.services.adguardhome;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.modules.services.adguardhome = {
|
||||||
|
enable = lib.mkEnableOption "AdGuard Home";
|
||||||
|
|
||||||
|
adminPasswordHash = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "Bcrypt verifier for the AdGuard Home administrator password.";
|
||||||
|
};
|
||||||
|
|
||||||
|
reverseProxyAddress = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "IP address of the guest that handles internal HTTP requests.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
services.adguardhome = {
|
||||||
|
enable = true;
|
||||||
|
mutableSettings = false;
|
||||||
|
openFirewall = true;
|
||||||
|
settings = {
|
||||||
|
http = {
|
||||||
|
pprof = {
|
||||||
|
port = 6060;
|
||||||
|
enabled = false;
|
||||||
|
};
|
||||||
|
address = "0.0.0.0:80";
|
||||||
|
session_ttl = "720h";
|
||||||
|
};
|
||||||
|
users = [
|
||||||
|
{
|
||||||
|
name = config.user.name;
|
||||||
|
password = cfg.adminPasswordHash;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
auth_attempts = 5;
|
||||||
|
block_auth_min = 15;
|
||||||
|
http_proxy = "";
|
||||||
|
language = "";
|
||||||
|
theme = "auto";
|
||||||
|
|
||||||
|
dns = {
|
||||||
|
bind_hosts = [ "0.0.0.0" ];
|
||||||
|
port = 53;
|
||||||
|
anonymize_client_ip = false;
|
||||||
|
ratelimit = 20;
|
||||||
|
ratelimit_subnet_len_ipv4 = 24;
|
||||||
|
ratelimit_subnet_len_ipv6 = 56;
|
||||||
|
ratelimit_whitelist = [ ];
|
||||||
|
refuse_any = true;
|
||||||
|
upstream_dns = [
|
||||||
|
"https://dns.cloudflare.com/dns-query"
|
||||||
|
"tls://1.1.1.1"
|
||||||
|
"https://dns.google/dns-query"
|
||||||
|
"tls://8.8.8.8"
|
||||||
|
"https://dns10.quad9.net/dns-query"
|
||||||
|
"tls://9.9.9.9"
|
||||||
|
];
|
||||||
|
upstream_dns_file = "";
|
||||||
|
bootstrap_dns = [
|
||||||
|
"9.9.9.10"
|
||||||
|
"149.112.112.10"
|
||||||
|
"2620:fe::10"
|
||||||
|
"2620:fe::fe:10"
|
||||||
|
];
|
||||||
|
fallback_dns = [ ];
|
||||||
|
upstream_mode = "parallel";
|
||||||
|
fastest_timeout = "1s";
|
||||||
|
allowed_clients = [ ];
|
||||||
|
disallowed_clients = [ ];
|
||||||
|
blocked_hosts = [
|
||||||
|
"version.bind"
|
||||||
|
"id.server"
|
||||||
|
"hostname.bind"
|
||||||
|
];
|
||||||
|
trusted_proxies = [
|
||||||
|
"127.0.0.0/8"
|
||||||
|
"::1/128"
|
||||||
|
];
|
||||||
|
cache_enabled = true;
|
||||||
|
cache_size = 4194304;
|
||||||
|
cache_ttl_min = 0;
|
||||||
|
cache_ttl_max = 0;
|
||||||
|
cache_optimistic = false;
|
||||||
|
cache_optimistic_answer_ttl = "30s";
|
||||||
|
cache_optimistic_max_age = "12h";
|
||||||
|
bogus_nxdomain = [ ];
|
||||||
|
aaaa_disabled = false;
|
||||||
|
enable_dnssec = false;
|
||||||
|
edns_client_subnet = {
|
||||||
|
custom_ip = "";
|
||||||
|
enabled = false;
|
||||||
|
use_custom = false;
|
||||||
|
};
|
||||||
|
max_goroutines = 300;
|
||||||
|
handle_ddr = true;
|
||||||
|
ipset = [ ];
|
||||||
|
ipset_file = "";
|
||||||
|
bootstrap_prefer_ipv6 = false;
|
||||||
|
upstream_timeout = "10s";
|
||||||
|
private_networks = [ ];
|
||||||
|
use_private_ptr_resolvers = true;
|
||||||
|
local_ptr_upstreams = [ ];
|
||||||
|
use_dns64 = false;
|
||||||
|
dns64_prefixes = [ ];
|
||||||
|
serve_http3 = false;
|
||||||
|
use_http3_upstreams = false;
|
||||||
|
serve_plain_dns = true;
|
||||||
|
hostsfile_enabled = true;
|
||||||
|
pending_requests.enabled = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
tls = {
|
||||||
|
enabled = false;
|
||||||
|
server_name = "";
|
||||||
|
force_https = false;
|
||||||
|
port_https = 443;
|
||||||
|
port_dns_over_tls = 853;
|
||||||
|
port_dns_over_quic = 853;
|
||||||
|
port_dnscrypt = 0;
|
||||||
|
dnscrypt_config_file = "";
|
||||||
|
allow_unencrypted_doh = false;
|
||||||
|
certificate_chain = "";
|
||||||
|
private_key = "";
|
||||||
|
certificate_path = "";
|
||||||
|
private_key_path = "";
|
||||||
|
strict_sni_check = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
querylog = {
|
||||||
|
dir_path = "";
|
||||||
|
ignored = [ ];
|
||||||
|
interval = "2160h";
|
||||||
|
size_memory = 1000;
|
||||||
|
enabled = true;
|
||||||
|
ignored_enabled = false;
|
||||||
|
file_enabled = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
statistics = {
|
||||||
|
dir_path = "";
|
||||||
|
ignored = [ ];
|
||||||
|
interval = "24h";
|
||||||
|
enabled = true;
|
||||||
|
ignored_enabled = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
filters = [
|
||||||
|
{
|
||||||
|
enabled = true;
|
||||||
|
url = "https://adguardteam.github.io/HostlistsRegistry/assets/filter_1.txt";
|
||||||
|
name = "AdGuard DNS filter";
|
||||||
|
id = 1;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
enabled = false;
|
||||||
|
url = "https://adguardteam.github.io/HostlistsRegistry/assets/filter_2.txt";
|
||||||
|
name = "AdAway Default Blocklist";
|
||||||
|
id = 2;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
whitelist_filters = [ ];
|
||||||
|
user_rules = [ ];
|
||||||
|
|
||||||
|
dhcp = {
|
||||||
|
enabled = false;
|
||||||
|
interface_name = "";
|
||||||
|
local_domain_name = "lan";
|
||||||
|
dhcpv4 = {
|
||||||
|
gateway_ip = "";
|
||||||
|
subnet_mask = "";
|
||||||
|
range_start = "";
|
||||||
|
range_end = "";
|
||||||
|
lease_duration = 86400;
|
||||||
|
icmp_timeout_msec = 1000;
|
||||||
|
options = [ ];
|
||||||
|
};
|
||||||
|
dhcpv6 = {
|
||||||
|
range_start = "";
|
||||||
|
lease_duration = 86400;
|
||||||
|
ra_slaac_only = false;
|
||||||
|
ra_allow_slaac = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
filtering = {
|
||||||
|
blocking_ipv4 = "";
|
||||||
|
blocking_ipv6 = "";
|
||||||
|
blocked_services = {
|
||||||
|
schedule.time_zone = "Local";
|
||||||
|
ids = [ ];
|
||||||
|
};
|
||||||
|
protection_disabled_until = null;
|
||||||
|
safe_search = {
|
||||||
|
enabled = false;
|
||||||
|
bing = true;
|
||||||
|
duckduckgo = true;
|
||||||
|
ecosia = true;
|
||||||
|
google = true;
|
||||||
|
pixabay = true;
|
||||||
|
yandex = true;
|
||||||
|
youtube = true;
|
||||||
|
};
|
||||||
|
blocking_mode = "default";
|
||||||
|
parental_block_host = "family-block.dns.adguard.com";
|
||||||
|
safebrowsing_block_host = "standard-block.dns.adguard.com";
|
||||||
|
rewrites = [
|
||||||
|
{
|
||||||
|
domain = "*.home";
|
||||||
|
answer = "10.23.20.32";
|
||||||
|
enabled = true;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
domain = "*.alexion.dev";
|
||||||
|
answer = cfg.reverseProxyAddress;
|
||||||
|
enabled = true;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
domain = "home";
|
||||||
|
answer = cfg.reverseProxyAddress;
|
||||||
|
enabled = true;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
safe_fs_patterns = [ "/opt/AdGuardHome/userfilters/*" ];
|
||||||
|
safebrowsing_cache_size = 1048576;
|
||||||
|
safesearch_cache_size = 1048576;
|
||||||
|
parental_cache_size = 1048576;
|
||||||
|
cache_time = 30;
|
||||||
|
filters_update_interval = 24;
|
||||||
|
blocked_response_ttl = 10;
|
||||||
|
filtering_enabled = true;
|
||||||
|
rewrites_enabled = true;
|
||||||
|
parental_enabled = false;
|
||||||
|
safebrowsing_enabled = false;
|
||||||
|
protection_enabled = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
clients = {
|
||||||
|
runtime_sources = {
|
||||||
|
whois = true;
|
||||||
|
arp = true;
|
||||||
|
rdns = true;
|
||||||
|
dhcp = true;
|
||||||
|
hosts = true;
|
||||||
|
};
|
||||||
|
persistent = [ ];
|
||||||
|
};
|
||||||
|
|
||||||
|
log = {
|
||||||
|
enabled = true;
|
||||||
|
file = "";
|
||||||
|
max_backups = 0;
|
||||||
|
max_size = 100;
|
||||||
|
max_age = 3;
|
||||||
|
compress = false;
|
||||||
|
local_time = false;
|
||||||
|
verbose = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
os = {
|
||||||
|
group = "";
|
||||||
|
user = "";
|
||||||
|
rlimit_nofile = 0;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.firewall = {
|
||||||
|
allowedTCPPorts = [ 53 ];
|
||||||
|
allowedUDPPorts = [ 53 ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -71,7 +71,10 @@ let
|
|||||||
extraConfig = lib.optionalString (route.clientMaxBodySize != null) ''
|
extraConfig = lib.optionalString (route.clientMaxBodySize != null) ''
|
||||||
client_max_body_size ${route.clientMaxBodySize};
|
client_max_body_size ${route.clientMaxBodySize};
|
||||||
'';
|
'';
|
||||||
locations."/".proxyPass = mkBackend address port;
|
locations."/" = {
|
||||||
|
proxyPass = mkBackend address port;
|
||||||
|
proxyWebsockets = true;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
config,
|
config,
|
||||||
lib,
|
lib,
|
||||||
|
pkgs,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
@@ -31,13 +32,33 @@ in
|
|||||||
|
|
||||||
services.romm = {
|
services.romm = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
package = pkgs.alexion.romm;
|
||||||
group = "storage";
|
group = "storage";
|
||||||
database.createLocally = true;
|
database.createLocally = true;
|
||||||
redis.createLocally = true;
|
redis.createLocally = true;
|
||||||
watcher.enable = true;
|
watcher.enable = true;
|
||||||
|
extraEnvironment = {
|
||||||
|
HASHEOUS_API_ENABLED = "true";
|
||||||
|
PLAYMATCH_API_ENABLED = "true";
|
||||||
|
ROM_CONVERTO_ENABLED = "false";
|
||||||
|
};
|
||||||
inherit (cfg) environmentFile;
|
inherit (cfg) environmentFile;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
systemd.services.romm-worker.serviceConfig.ExecStart =
|
||||||
|
lib.mkForce "${lib.getExe' config.services.romm.package "romm-worker"} scans";
|
||||||
|
|
||||||
|
systemd.tmpfiles.settings."10-romm"."${config.services.romm.dataDir}/config/config.yml"."L+".argument =
|
||||||
|
toString (
|
||||||
|
(pkgs.formats.yaml { }).generate "romm-config.yml" {
|
||||||
|
emulatorjs.auto_save_sync = false;
|
||||||
|
filesystem.structure = {
|
||||||
|
default = "roms/{platform}/{game}";
|
||||||
|
firmware = "bios/{platform}";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
users.users = {
|
users.users = {
|
||||||
romm.uid = config.registry."stable-uid".${config.networking.hostName}.romm;
|
romm.uid = config.registry."stable-uid".${config.networking.hostName}.romm;
|
||||||
redis-romm.uid = config.registry."stable-uid".${config.networking.hostName}."redis-romm";
|
redis-romm.uid = config.registry."stable-uid".${config.networking.hostName}."redis-romm";
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ or begin
|
|||||||
return $status
|
return $status
|
||||||
end
|
end
|
||||||
|
|
||||||
|
set remote_nar
|
||||||
|
|
||||||
if test (count $missing_paths) -gt 0
|
if test (count $missing_paths) -gt 0
|
||||||
set nar_file (mktemp --suffix=.nar)
|
set nar_file (mktemp --suffix=.nar)
|
||||||
or return $status
|
or return $status
|
||||||
@@ -70,26 +72,23 @@ if test (count $missing_paths) -gt 0
|
|||||||
return $scp_status
|
return $scp_status
|
||||||
end
|
end
|
||||||
|
|
||||||
echo "deploy-to: importing closure on $host" >&2
|
echo "deploy-to: importing the closure, recording $system_path, and activating it on $host" >&2
|
||||||
ssh -t $host "sudo sh -c 'nix-store --import < $remote_nar' && rm -f $remote_nar"
|
|
||||||
or begin
|
|
||||||
echo "deploy-to: closure import failed for $host" >&2
|
|
||||||
return $status
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
echo "deploy-to: $host already has the full closure for $system_path" >&2
|
echo "deploy-to: $host already has the full closure for $system_path" >&2
|
||||||
|
echo "deploy-to: recording $system_path and activating it on $host" >&2
|
||||||
end
|
end
|
||||||
|
|
||||||
echo "deploy-to: recording $system_path as the system profile on $host" >&2
|
set remote_script (
|
||||||
ssh -t $host sudo nix-env --profile /nix/var/nix/profiles/system --set $system_path
|
string join '; ' \
|
||||||
or begin
|
'system_path=$1' \
|
||||||
echo "deploy-to: system profile update failed for $host" >&2
|
'remote_nar=$2' \
|
||||||
return $status
|
'if test -n "$remote_nar"; then nix-store --import < "$remote_nar"; rm -f "$remote_nar"; fi' \
|
||||||
end
|
'nix-env --profile /nix/var/nix/profiles/system --set "$system_path"' \
|
||||||
|
'"$system_path/bin/switch-to-configuration" switch'
|
||||||
|
)
|
||||||
|
|
||||||
echo "deploy-to: activating $system_path on $host" >&2
|
ssh -t $host sudo sh -e -c (string escape -- $remote_script) sh (string escape -- $system_path $remote_nar)
|
||||||
ssh -t $host sudo "$system_path/bin/switch-to-configuration" switch
|
|
||||||
or begin
|
or begin
|
||||||
echo "deploy-to: activation failed for $host" >&2
|
echo "deploy-to: deployment failed for $host" >&2
|
||||||
return $status
|
return $status
|
||||||
end
|
end
|
||||||
|
|||||||
2
docs/.obsidian/app.json
vendored
2
docs/.obsidian/app.json
vendored
@@ -5,7 +5,7 @@
|
|||||||
"livePreview": false,
|
"livePreview": false,
|
||||||
"readableLineLength": false,
|
"readableLineLength": false,
|
||||||
"strictLineBreaks": true,
|
"strictLineBreaks": true,
|
||||||
"propertiesInDocument": "visible",
|
"propertiesInDocument": "hidden",
|
||||||
"showLineNumber": true,
|
"showLineNumber": true,
|
||||||
"autoPairMarkdown": false,
|
"autoPairMarkdown": false,
|
||||||
"useTab": false,
|
"useTab": false,
|
||||||
|
|||||||
48
docs/.obsidian/workspace.json
vendored
48
docs/.obsidian/workspace.json
vendored
@@ -4,21 +4,21 @@
|
|||||||
"type": "split",
|
"type": "split",
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"id": "81c4860f495113bf",
|
"id": "880908ac22302761",
|
||||||
"type": "tabs",
|
"type": "tabs",
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"id": "daab69fc3faab88f",
|
"id": "10ea163afc7dbc62",
|
||||||
"type": "leaf",
|
"type": "leaf",
|
||||||
"state": {
|
"state": {
|
||||||
"type": "markdown",
|
"type": "markdown",
|
||||||
"state": {
|
"state": {
|
||||||
"file": "00 INBOX/credits.md",
|
"file": "TODO.md",
|
||||||
"mode": "source",
|
"mode": "source",
|
||||||
"source": true
|
"source": true
|
||||||
},
|
},
|
||||||
"icon": "lucide-file",
|
"icon": "lucide-file",
|
||||||
"title": "credits"
|
"title": "TODO"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -91,7 +91,7 @@
|
|||||||
"state": {
|
"state": {
|
||||||
"type": "localgraph",
|
"type": "localgraph",
|
||||||
"state": {
|
"state": {
|
||||||
"file": "00 INBOX/credits.md",
|
"file": "TODO.md",
|
||||||
"options": {
|
"options": {
|
||||||
"collapse-filter": true,
|
"collapse-filter": true,
|
||||||
"search": "",
|
"search": "",
|
||||||
@@ -217,34 +217,34 @@
|
|||||||
"table-editor-obsidian:Advanced Tables Toolbar": false
|
"table-editor-obsidian:Advanced Tables Toolbar": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"active": "daab69fc3faab88f",
|
"active": "10ea163afc7dbc62",
|
||||||
"lastOpenFiles": [
|
"lastOpenFiles": [
|
||||||
"00 INBOX/ai/tldr-design.md",
|
"00 INBOX/ai/adguard-pikachu-migration-design-tree.md",
|
||||||
"00 INBOX/ai/caps-escape-design.md",
|
"00 INBOX/ai/caps-escape-design.md",
|
||||||
|
"03 wrk/tasks/0016-romm-manual-rom-migration.md",
|
||||||
|
"03 wrk/tasks/0015-romm-5-4-package.md",
|
||||||
|
"00 INBOX/ai/retroarch-zeus-design-tree.md",
|
||||||
|
"TODO.md",
|
||||||
|
"00 INBOX/ai/romm-5-4-deployment-changes-design-tree.md",
|
||||||
|
"00 INBOX/ai/romm-migration-design-tree.md",
|
||||||
|
"00 INBOX/ai/romm-5-4-package-design-tree.md",
|
||||||
|
"00 INBOX/ai/steamvr-quest-3-design-tree.md",
|
||||||
"AGENTS.md",
|
"AGENTS.md",
|
||||||
|
"03 wrk/homelab.md",
|
||||||
|
"00 INBOX/ai/nixos-agents-style-scope-design-tree.md",
|
||||||
|
"03 wrk/tasks/0014-romm-guest.md",
|
||||||
"00 INBOX/ai/tldr-design-tree.md",
|
"00 INBOX/ai/tldr-design-tree.md",
|
||||||
|
"00 INBOX/ai/tldr-design.md",
|
||||||
|
"00 INBOX/ai/valheim-items.md",
|
||||||
|
"03 wrk/tasks/0013-oidc-provider.md",
|
||||||
|
"03 wrk/tasks/0002-nixos-refactor.md",
|
||||||
|
"03 wrk/tasks/0011-gitea-axi-rust-migration.md",
|
||||||
|
"00 INBOX/credits.md",
|
||||||
"00 INBOX/ai/grill-skill-design.md",
|
"00 INBOX/ai/grill-skill-design.md",
|
||||||
"03 wrk/tasks/0012-gitea-axi-pr-merge-guardrail.md",
|
"03 wrk/tasks/0012-gitea-axi-pr-merge-guardrail.md",
|
||||||
"03 wrk/tasks/0011-gitea-axi-rust-migration.md",
|
|
||||||
"00 INBOX/ai/gitea-axi-pr-merge-guardrail.md",
|
"00 INBOX/ai/gitea-axi-pr-merge-guardrail.md",
|
||||||
"00 INBOX/ai/gitea-axi-rust-migration.md",
|
"00 INBOX/ai/gitea-axi-rust-migration.md",
|
||||||
"00 INBOX/valheim progression.md",
|
"00 INBOX/valheim progression.md",
|
||||||
"03 wrk/tasks/0010-fix-main-monitor-detection.md",
|
|
||||||
"00 INBOX/credits.md",
|
|
||||||
"03 wrk/tasks/0009-bazel-project-scaffolding.md",
|
|
||||||
"03 wrk/tasks/0005-rust-cli-scaffolding.md",
|
|
||||||
"03 wrk/tasks/0008-vim-obsidian-markdown-renderer.md",
|
|
||||||
"03 wrk/tasks/0002-nixos-refactor.md",
|
|
||||||
"TODO.md",
|
|
||||||
"technical-writing.md",
|
|
||||||
"dictionary.md",
|
|
||||||
"03 wrk/tasks/0007-obsidian-source-notes.md",
|
|
||||||
"03 wrk/tasks/0004-dictionary-cli.md",
|
|
||||||
"03 wrk/tasks/0006-wallpaper-randomizer.md",
|
|
||||||
"03 wrk/tasks/0003-whisper-dictation.md",
|
|
||||||
"03 wrk/monorepo.md",
|
|
||||||
"03 wrk/tasks/0001-todo-cli.md",
|
|
||||||
"03 wrk/productivity.md",
|
|
||||||
"03 wrk/tasks",
|
"03 wrk/tasks",
|
||||||
"00 INBOX/let order name resolution.md~",
|
"00 INBOX/let order name resolution.md~",
|
||||||
"00 INBOX/nix name resolution.md~",
|
"00 INBOX/nix name resolution.md~",
|
||||||
|
|||||||
110
docs/00 INBOX/ai/adguard-pikachu-migration-design-tree.md
Normal file
110
docs/00 INBOX/ai/adguard-pikachu-migration-design-tree.md
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
# AdGuard migration to Pikachu: design tree
|
||||||
|
|
||||||
|
## Research facts
|
||||||
|
|
||||||
|
- The pinned Nixpkgs revision provides `adguardhome` version `0.107.79`.
|
||||||
|
- NixOS provides the `services.adguardhome` module.
|
||||||
|
- The module runs AdGuard Home as a hardened dynamic systemd user.
|
||||||
|
- It stores state in `/var/lib/AdGuardHome`.
|
||||||
|
- It grants `CAP_NET_BIND_SERVICE` for DNS port 53.
|
||||||
|
- It grants `CAP_NET_RAW` when AdGuard Home DHCP is enabled.
|
||||||
|
- The module supports an arbitrary YAML configuration through `settings`.
|
||||||
|
- The module supports fully declarative operation with `mutableSettings = false`.
|
||||||
|
- In fully declarative operation, the module replaces `/var/lib/AdGuardHome/AdGuardHome.yaml` on each service start.
|
||||||
|
- Fully declarative operation requires `dns.bootstrap_dns` as a list.
|
||||||
|
- Declarative settings pass an AdGuard configuration check during the build.
|
||||||
|
- `mutableSettings = true` merges declared settings into UI changes at service start.
|
||||||
|
- `mutableSettings = false` replaces the state configuration on every service start.
|
||||||
|
- `openFirewall` opens only the web interface port.
|
||||||
|
- The migration must explicitly open DNS ports 53/TCP and 53/UDP when clients need them.
|
||||||
|
- Pikachu has address `10.23.10.102` on its untagged network.
|
||||||
|
- Pikachu carries VLAN 20 and creates bridge `br-vlan20`.
|
||||||
|
- The guest framework runs each guest in its own systemd-nspawn container.
|
||||||
|
- Each guest attaches to a host VLAN bridge and receives an address through DHCP.
|
||||||
|
- Pikachu currently configures only VLAN 20 for guests.
|
||||||
|
- The repository has no AdGuard configuration, Proxmox inventory, or DHCP-provider configuration.
|
||||||
|
- The current DHCP provider remains unestablished.
|
||||||
|
- The current Proxmox AdGuard container uses MAC `bc:24:11:91:60:bf`.
|
||||||
|
- The current Proxmox AdGuard container uses address `10.23.20.33` on VLAN 20.
|
||||||
|
- This environment has no Proxmox SSH target or local Proxmox control utility.
|
||||||
|
- The current AdGuard configuration listens on all guest addresses at DNS port 53.
|
||||||
|
- The current AdGuard configuration has no allowed-client or disallowed-client restrictions.
|
||||||
|
- The current AdGuard configuration uses Cloudflare, Google, and Quad9 encrypted upstreams in parallel.
|
||||||
|
- The current AdGuard configuration disables DNSSEC.
|
||||||
|
- The current AdGuard configuration defines three local rewrites.
|
||||||
|
- The repository configures no host backup system or monitoring system.
|
||||||
|
- Hosts update through explicit `nixos-rebuild switch --flake` commands.
|
||||||
|
- The working tree has unrelated operator changes.
|
||||||
|
|
||||||
|
## Service tradeoffs
|
||||||
|
|
||||||
|
| Service | NixOS support | Domain filtering | Administration UI | DHCP | Encrypted DNS | Main tradeoff |
|
||||||
|
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
|
||||||
|
| AdGuard Home | `services.adguardhome`; checked YAML and mutable or immutable state | Native block lists, rules, and per-client policy | Native | Native | Upstream and client-facing encrypted DNS | Direct migration with the closest state and feature match. UI state conflicts with fully declarative operation unless configuration is immutable. |
|
||||||
|
| Blocky | `services.blocky`; checked declarative YAML | Native lists, allow lists, rewrites, and per-client groups | No UI; REST API and metrics only | No | Encrypted upstreams and client-facing DoH, DoT, and DoQ | Strong Git-managed configuration and low operational surface. It lacks an interactive administration interface and DHCP. |
|
||||||
|
| Pi-hole | `services.pihole-ftl` plus `services.pihole-web`; declarative TOML, lists, and dashboard | Native gravity lists, allow lists, regex rules, and groups | Native | Native | Use a companion for encrypted upstream DNS | Familiar filtering product with a dashboard. The migration changes product data and uses more coupled services. |
|
||||||
|
| Technitium DNS Server | `services.technitium-dns-server`; service and firewall options only | Native block lists and DNS applications | Native | Native | Upstream and client-facing encrypted DNS | Broadest DNS feature set, including authoritative DNS. NixOS does not expose its runtime configuration declaratively. |
|
||||||
|
| Unbound | `services.unbound`; structured server and free-form settings | Local zones or response-policy zones require custom policy management | No | No | DNS-over-TLS support | Mature validating recursive resolver. Filtering and user operations require separate design. |
|
||||||
|
| dnscrypt-proxy | `services.dnscrypt-proxy`; declarative TOML | Local block and allow rules, without a list-management UI | No | No | Encrypted upstream DNS, including DNSCrypt and DoH | Strong upstream privacy and resolver selection. It is not a full network filtering appliance. |
|
||||||
|
| Knot Resolver | `services.kresd`; structured listener settings and extra Lua | Custom policy modules | No | No | Client-facing DoH and TLS listeners | Flexible high-performance recursive resolver. Filtering requires resolver expertise and custom policy. |
|
||||||
|
| SmartDNS | `services.smartdns`; free-form settings | Domain and address rules | No NixOS-integrated UI | No | Encrypted upstream and client-facing DNS | Optimizes upstream selection and latency. It offers less complete filtering management than dedicated blockers. |
|
||||||
|
|
||||||
|
`Native` means that the product provides the feature without a companion service.
|
||||||
|
|
||||||
|
## Decision tree
|
||||||
|
|
||||||
|
- **D1 — DNS service product** [settled]
|
||||||
|
- Retain AdGuard Home on Pikachu.
|
||||||
|
- Constraint: Preserve AdGuard Home as the DNS service product.
|
||||||
|
- **D2A — AdGuard Home role** [settled]
|
||||||
|
- Provides DNS filtering and resolution only.
|
||||||
|
- Constraint: The existing DHCP provider continues to assign addresses and DHCP options.
|
||||||
|
- **D3A — Execution placement** [settled]
|
||||||
|
- Runs in a dedicated guest on Pikachu's existing VLAN 20.
|
||||||
|
- Constraint: Isolate AdGuard Home from the Pikachu host.
|
||||||
|
- **D4A — Guest network identity** [settled]
|
||||||
|
- Reuses MAC `bc:24:11:91:60:bf` and address `10.23.20.33` on VLAN 20.
|
||||||
|
- Constraint: Stop the Proxmox container before the guest starts.
|
||||||
|
- **D5A — Network exposure** [settled]
|
||||||
|
- Listens on all guest addresses at port 53.
|
||||||
|
- Accepts requests from every reachable internal device.
|
||||||
|
- **D6A — Resolver policy** [settled]
|
||||||
|
- Preserves the existing upstream resolvers and parallel resolver mode.
|
||||||
|
- Preserves disabled DNSSEC and the three local rewrites.
|
||||||
|
- **D7A — Configuration authority** [settled]
|
||||||
|
- Uses fully declarative Nix configuration.
|
||||||
|
- Constraint: Set `services.adguardhome.mutableSettings = false`.
|
||||||
|
- Constraint: Declare `dns.bootstrap_dns` as a list.
|
||||||
|
- Constraint: Web UI changes do not persist.
|
||||||
|
- Constraint: Match existing service behavior except for the administrator password.
|
||||||
|
- **D8A — Migration data** [settled]
|
||||||
|
- Migrate functional DNS configuration only.
|
||||||
|
- Constraint: Do not migrate query history or statistics.
|
||||||
|
- **D9A — Operations** [settled]
|
||||||
|
- Declares a newly generated bcrypt verifier in Nix.
|
||||||
|
- Constraint: Keep the plaintext password outside the repository and Nix store.
|
||||||
|
- Constraint: The verifier is readable from the Nix store.
|
||||||
|
- **D10A — Cutover and rollback** [settled]
|
||||||
|
- Uses a planned atomic cutover with rollback.
|
||||||
|
- Stop the Proxmox container before starting the guest.
|
||||||
|
- Validate the guest before restoring the Proxmox container during rollback.
|
||||||
|
- **D11A — Runtime-state backup** [settled]
|
||||||
|
- Do not back up rebuildable AdGuard Home runtime state.
|
||||||
|
- **D12A — Monitoring** [settled]
|
||||||
|
- Do not add DNS availability monitoring.
|
||||||
|
- **D13A — Upgrade ownership** [settled]
|
||||||
|
- The normal flake update and explicit NixOS rebuild workflow owns upgrades.
|
||||||
|
- Replace AdGuard Home. [not selected]
|
||||||
|
- **D2B — Replacement product** [not applicable]
|
||||||
|
- Choose Blocky, Pi-hole, Technitium, or a composed resolver.
|
||||||
|
|
||||||
|
## Frontier
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
## Sources
|
||||||
|
|
||||||
|
- Pinned Nixpkgs module: `nixos/modules/services/networking/adguardhome.nix`.
|
||||||
|
- Pinned Nixpkgs modules: `blocky.nix`, `pihole-ftl.nix`, `pihole-web.nix`, `technitium-dns-server.nix`, `unbound.nix`, `dnscrypt-proxy.nix`, `knot-resolver.nix`, and `smartdns.nix`.
|
||||||
|
- AdGuard Home README, release `v0.107.79`.
|
||||||
|
- Technitium DNS Server README, current upstream.
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
# Caps Escape Design
|
|
||||||
|
|
||||||
## Facts
|
|
||||||
|
|
||||||
- Commit `250b0b71f` removed `services.xserver.xkb.options` from the shared host module.
|
|
||||||
- The removed option was `caps:escape_shifted_capslock`.
|
|
||||||
- That XKB option maps Caps Lock to Escape.
|
|
||||||
- Shift+Caps Lock still enables Caps Lock.
|
|
||||||
- The shared host module configures Neogaia, Zeus, and Pikachu.
|
|
||||||
- Zeus has QMK firmware that provides equivalent keyboard behavior.
|
|
||||||
- Neogaia and Zeus enable `modules.host.cachyos` and `modules.desktop`.
|
|
||||||
- Pikachu enables neither module.
|
|
||||||
- `configs/nixos/hosts/neogaia/default.nix` directly sets Neogaia-specific hardware, networking, desktop application, and Waybar settings.
|
|
||||||
- The current configuration has no Caps Lock or Escape remapping.
|
|
||||||
- This session runs on Zeus, not Neogaia.
|
|
||||||
|
|
||||||
## Design Tree
|
|
||||||
|
|
||||||
- Restore Caps Lock behavior
|
|
||||||
- Scope the configuration
|
|
||||||
- Configure Neogaia only. ✓
|
|
||||||
- Select the mapping behavior.
|
|
||||||
- Restore `caps:escape_shifted_capslock`. ✓
|
|
||||||
- Set `services.xserver.xkb.options` in `configs/nixos/hosts/neogaia/default.nix`. ✓
|
|
||||||
- Define validation for Neogaia.
|
|
||||||
- Run static checks and manually verify both keys after deployment. ✓
|
|
||||||
- Stop after source and static validation. ✓
|
|
||||||
|
|
||||||
## Settled Decisions
|
|
||||||
|
|
||||||
1. Configure the mapping on Neogaia only.
|
|
||||||
2. Restore `caps:escape_shifted_capslock`.
|
|
||||||
3. Set `services.xserver.xkb.options` directly in Neogaia's host configuration.
|
|
||||||
4. Run static checks and manually verify both keys on Neogaia after deployment.
|
|
||||||
5. Stop after source and static validation.
|
|
||||||
|
|
||||||
## Frontier
|
|
||||||
|
|
||||||
None.
|
|
||||||
98
docs/00 INBOX/ai/retroarch-zeus-design-tree.md
Normal file
98
docs/00 INBOX/ai/retroarch-zeus-design-tree.md
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
---
|
||||||
|
date-created: 2026-10-21 08:47
|
||||||
|
date-modified: 2026-10-21 09:26
|
||||||
|
---
|
||||||
|
# RetroArch on Zeus design tree
|
||||||
|
|
||||||
|
## Facts
|
||||||
|
|
||||||
|
- Zeus is an `x86_64-linux` desktop with AMD graphics, 32-bit graphics support, Bluetooth, Hyprland, and Home Manager.
|
||||||
|
- Nixpkgs provides `pkgs.retroarch.withCores` for an explicit set of Libretro cores.
|
||||||
|
- Nixpkgs provides `pkgs.retroarch-free` and `pkgs.retroarch-full` for broad core sets.
|
||||||
|
- The packaged RetroArch version is 1.22.2 and includes Cloud Sync on Linux.
|
||||||
|
- Linux Cloud Sync uses a WebDAV endpoint.
|
||||||
|
- RomM requires RetroArch 1.22 or newer for this integration.
|
||||||
|
- RomM documents configuration synchronization as part of its Cloud Sync setup.
|
||||||
|
- Cloud Sync supports saves, configuration, thumbnails, and system files as separate categories.
|
||||||
|
- RomM matches a save or state to a ROM by its file name without the extension.
|
||||||
|
- Local ROM files must use the same names as their RomM library records.
|
||||||
|
- RomM 5.4 provides a WebDAV endpoint for RetroArch Cloud Sync.
|
||||||
|
- The endpoint is `https://games.alexion.dev/api/sync/retroarch/`.
|
||||||
|
- RomM stores its ROMs and BIOS files on Pikachu.
|
||||||
|
|
||||||
|
## Constraints
|
||||||
|
|
||||||
|
- Install RetroArch on Zeus.
|
||||||
|
- Start with PlayStation and Sega Saturn cores.
|
||||||
|
- Evaluate RetroArch Cloud Sync.
|
||||||
|
- Keep package selection declarative.
|
||||||
|
- Keep credentials out of the Nix store and version control.
|
||||||
|
|
||||||
|
## Decision tree
|
||||||
|
|
||||||
|
- D1 — Initial core selection [settled]
|
||||||
|
- Use `beetle-psx-hw` for PlayStation.
|
||||||
|
- Use `beetle-saturn` for Sega Saturn.
|
||||||
|
- D4 — Core package viability [settled]
|
||||||
|
- Both core packages support `x86_64-linux`.
|
||||||
|
- Neither package is marked broken or unfree.
|
||||||
|
- D5 — Package composition [settled]
|
||||||
|
- Build a RetroArch wrapper with `beetle-psx-hw` and `beetle-saturn` only.
|
||||||
|
- D2 — Cloud Sync data scope [settled]
|
||||||
|
- Sync saves, states, and configuration.
|
||||||
|
- Do not sync thumbnails or system files.
|
||||||
|
- D6 — Sync endpoint [settled]
|
||||||
|
- Use RomM's RetroArch WebDAV endpoint.
|
||||||
|
- D7 — Sync identity [settled]
|
||||||
|
- Use the existing RomM account.
|
||||||
|
- D15 — Credential injection [settled]
|
||||||
|
- Store the RomM password in RetroArch's writable user configuration.
|
||||||
|
- D8 — Synchronization mode [settled]
|
||||||
|
- Synchronize automatically at startup and after play sessions.
|
||||||
|
- D16 — Launch order [settled]
|
||||||
|
- Do not add a game-launching frontend.
|
||||||
|
- Start RetroArch before loading local ROM content.
|
||||||
|
- D9 — Conflict and destructive-sync policy [settled]
|
||||||
|
- Use non-destructive synchronization.
|
||||||
|
- RetroArch backs up a local file when RomM reports its deletion.
|
||||||
|
- D3 — ROM and firmware access [settled]
|
||||||
|
- Keep ROMs and BIOS files locally on Zeus.
|
||||||
|
- D10 — Mount or replication method [settled]
|
||||||
|
- Do not configure a remote mount or replication method.
|
||||||
|
- D11 — RetroArch directory settings [settled]
|
||||||
|
- Use `~/.local/share/retroarch/`.
|
||||||
|
- Use `roms/`, `system/`, `saves/`, and `states/` subdirectories.
|
||||||
|
- Keep saves and states outside the content directory.
|
||||||
|
- Sort saves and states into per-core folders.
|
||||||
|
- D12 — User-configuration policy [settled]
|
||||||
|
- Nix declares the package, cores, and directory defaults.
|
||||||
|
- RetroArch manages and synchronizes its writable configuration.
|
||||||
|
- D13 — User-facing integration [settled]
|
||||||
|
- Do not add a user-facing integration beyond RetroArch's desktop entry.
|
||||||
|
- D14 — Validation [settled]
|
||||||
|
- Verify the NixOS evaluation and a manual Cloud Sync round trip.
|
||||||
|
|
||||||
|
## Frontier
|
||||||
|
|
||||||
|
No decisions remain open.
|
||||||
|
|
||||||
|
## Decision log
|
||||||
|
|
||||||
|
- D13: Do not add a user-facing integration beyond RetroArch's desktop entry.
|
||||||
|
- D16: Do not add a game-launching frontend. Start RetroArch before loading local ROM content.
|
||||||
|
- D14: Verify the NixOS evaluation and a manual Cloud Sync round trip.
|
||||||
|
- D12: Nix declares the package, cores, and directory defaults. RetroArch manages and synchronizes its writable configuration.
|
||||||
|
- D11: Use `~/.local/share/retroarch/` with `roms/`, `system/`, `saves/`, and `states/` subdirectories.
|
||||||
|
- D9: Use non-destructive synchronization.
|
||||||
|
- D8: Synchronize automatically at startup and after play sessions.
|
||||||
|
- D15: Store the RomM password in RetroArch's writable user configuration.
|
||||||
|
- D5: Build a RetroArch wrapper with `beetle-psx-hw` and `beetle-saturn` only.
|
||||||
|
- D3: Keep ROMs and BIOS files locally on Zeus.
|
||||||
|
- D10: Do not configure a remote mount or replication method.
|
||||||
|
- D7: Use the existing RomM account.
|
||||||
|
- D7 note: RomM accepts API client tokens as Bearer authentication. RetroArch Cloud Sync only supports WebDAV Basic authentication.
|
||||||
|
- D6: Use RomM's RetroArch WebDAV endpoint.
|
||||||
|
- D2: Sync saves, states, and configuration. Do not sync thumbnails or system files.
|
||||||
|
- D11: Keep saves and states outside the content directory. Sort them into per-core folders.
|
||||||
|
- D1: Use `beetle-psx-hw` for PlayStation and `beetle-saturn` for Sega Saturn.
|
||||||
|
- D4: Both selected core packages support Zeus and have no broken or unfree package status.
|
||||||
107
docs/00 INBOX/ai/romm-5-4-deployment-changes-design-tree.md
Normal file
107
docs/00 INBOX/ai/romm-5-4-deployment-changes-design-tree.md
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
---
|
||||||
|
date-created: 2026-10-20 19:15
|
||||||
|
date-modified: 2026-10-20 19:20
|
||||||
|
---
|
||||||
|
# RomM 5.4 deployment changes
|
||||||
|
|
||||||
|
## Known facts
|
||||||
|
|
||||||
|
- The deployed Nixpkgs package is RomM 5.2.0.
|
||||||
|
- RomM 5.4.0 requires Python 3.14 or later.
|
||||||
|
- The pinned Nixpkgs contains Python 3.14.
|
||||||
|
- The pinned Python package set lacks some RomM 5.4.0 dependency versions.
|
||||||
|
- For example, it provides RQ 2.10 while RomM requires RQ 2.12 or later.
|
||||||
|
- In this design, upstream means the Nixpkgs repository.
|
||||||
|
- Nixpkgs upstream still packages RomM 5.2.0.
|
||||||
|
- Two open Nixpkgs pull requests update RomM to 5.4.0.
|
||||||
|
- Pull request 574089 adds a required compatibility patch for Nixpkgs Redis 8.0.1.
|
||||||
|
- Pull request 574089 has not run the NixOS module test.
|
||||||
|
- The existing `romm` derivation already uses Python 3.14 from the pin.
|
||||||
|
- The package can override the current derivation without copying it.
|
||||||
|
- The override evaluates successfully with the RomM 5.4.0 source and frontend hashes.
|
||||||
|
- RomM reads `config.yml` from `/var/lib/romm/config/config.yml`.
|
||||||
|
- Systemd tmpfiles `L+` replaces that path with a generated Nix-store symlink.
|
||||||
|
- NixOS modules use `L+` symlinks for declaratively managed files in persistent application directories.
|
||||||
|
- The existing Nixpkgs RomM NixOS test starts the application with PostgreSQL, Redis, nginx, and the filesystem watcher in a local VM.
|
||||||
|
- The test does not deploy to Pikachu.
|
||||||
|
- The automated update changes only the version, source hash, and frontend dependency hash.
|
||||||
|
- The manual update also removes a Redis maintenance-notification import and argument.
|
||||||
|
- RomM does not require the `rom-converto` executable while `ROM_CONVERTO_ENABLED` is false.
|
||||||
|
- As checked on 2026-10-20, both pull requests remain open.
|
||||||
|
- Neither pull request has a review or a discussion comment.
|
||||||
|
- Both pull requests request review from the RomM package maintainers.
|
||||||
|
- Both pull requests pass evaluation and lint checks.
|
||||||
|
- Their package-test checks have a neutral result.
|
||||||
|
- The Darwin package-test jobs remain queued.
|
||||||
|
- RomM 5.3.0 added a required `filesystem.structure` declaration.
|
||||||
|
- RomM will not start without that declaration.
|
||||||
|
- The existing mounts match Structure A.
|
||||||
|
- Structure A maps ROMs to `roms/{platform}/{game}`.
|
||||||
|
- Structure A maps firmware to `bios/{platform}`.
|
||||||
|
- RomM 5.4.0 enables `emulatorjs.auto_save_sync` by default.
|
||||||
|
- RomM 5.4.0 adds optional in-place library conversion through `rom-converto`.
|
||||||
|
- Library conversion requires `ROM_CONVERTO_ENABLED=true`.
|
||||||
|
- Conversion deletes original files after conversion.
|
||||||
|
- The task requires declarative `config.yml` management.
|
||||||
|
- The task requires disabled browser save synchronization.
|
||||||
|
- The task requires disabled library conversion.
|
||||||
|
- The task retains the IGDB, ScreenScraper, and SteamGridDB configuration.
|
||||||
|
- The task reuses the Nixpkgs `services.romm` module.
|
||||||
|
|
||||||
|
## Sources
|
||||||
|
|
||||||
|
- [RomM 5.3.0 release](https://github.com/rommapp/romm/releases/tag/5.3.0)
|
||||||
|
- [RomM 5.4.0 release](https://github.com/rommapp/romm/releases/tag/5.4.0)
|
||||||
|
- [RomM 5.4.0 configuration example](https://github.com/rommapp/romm/blob/5.4.0/examples/config.example.yml)
|
||||||
|
- [RomM 5.4.0 Python requirement](https://github.com/rommapp/romm/blob/5.4.0/pyproject.toml)
|
||||||
|
- [[0015-romm-5-4-package]]
|
||||||
|
|
||||||
|
## Decision tree
|
||||||
|
|
||||||
|
- RomM 5.4 deployment
|
||||||
|
- Package runtime
|
||||||
|
- Settled: Build the local package with Python 3.14.
|
||||||
|
- Package source
|
||||||
|
- Settled: Maintain a local package.
|
||||||
|
- Constraint: Do not rely on either unreviewed Nixpkgs pull request.
|
||||||
|
- Package exposure
|
||||||
|
- Settled: Expose the package as `pkgs.alexion.romm`.
|
||||||
|
- Library layout
|
||||||
|
- Settled: Manage `config.yml` declaratively with Nix.
|
||||||
|
- Configuration materialization
|
||||||
|
- Settled: Replace the configuration file with a Nix-store symlink on activation.
|
||||||
|
- Settled: Declare Structure A.
|
||||||
|
- Settled: Set `filesystem.structure.default` to `roms/{platform}/{game}`.
|
||||||
|
- Settled: Set `filesystem.structure.firmware` to `bios/{platform}`.
|
||||||
|
- File safety
|
||||||
|
- Settled: Keep library conversion disabled.
|
||||||
|
- Settled: Do not enable `ROM_CONVERTO_ENABLED`.
|
||||||
|
- Browser emulation
|
||||||
|
- Settled: Set `emulatorjs.auto_save_sync` to `false`.
|
||||||
|
- Existing integration
|
||||||
|
- Settled: Reuse `services.romm`.
|
||||||
|
- Settled: Keep IGDB, ScreenScraper, and SteamGridDB configuration unchanged.
|
||||||
|
- Validation
|
||||||
|
- Settled: Build the local package and the Pikachu configuration.
|
||||||
|
- Settled: Do not run a local NixOS VM test.
|
||||||
|
- Settled: The operator validates the deployment on Pikachu.
|
||||||
|
|
||||||
|
## Settled decisions
|
||||||
|
|
||||||
|
- Build a local RomM 5.4.0 package.
|
||||||
|
- Do not rely on either unreviewed Nixpkgs pull request.
|
||||||
|
- Expose the package as `pkgs.alexion.romm`.
|
||||||
|
- Reuse `services.romm`.
|
||||||
|
- Generate `config.yml` with Nix.
|
||||||
|
- Replace `config.yml` with a Nix-store symlink on activation.
|
||||||
|
- Declare Structure A with `roms/{platform}/{game}` and `bios/{platform}`.
|
||||||
|
- Keep `ROM_CONVERTO_ENABLED` disabled.
|
||||||
|
- Set `emulatorjs.auto_save_sync` to `false`.
|
||||||
|
- Keep IGDB, ScreenScraper, and SteamGridDB configuration unchanged.
|
||||||
|
- Build the local package and Pikachu configuration.
|
||||||
|
- Do not run a local NixOS VM test.
|
||||||
|
- Let the operator validate the deployment on Pikachu.
|
||||||
|
|
||||||
|
## Frontier
|
||||||
|
|
||||||
|
No in-scope decisions remain.
|
||||||
109
docs/00 INBOX/ai/steamvr-quest-3-design-tree.md
Normal file
109
docs/00 INBOX/ai/steamvr-quest-3-design-tree.md
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
---
|
||||||
|
date-created: 2026-10-20 17:45
|
||||||
|
date-modified: 2026-10-20 17:52
|
||||||
|
---
|
||||||
|
# SteamVR to Meta Quest 3 design tree
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
Stream PCVR from Zeus to a Meta Quest 3.
|
||||||
|
|
||||||
|
The design must produce a repeatable and diagnosable SteamVR session.
|
||||||
|
|
||||||
|
## Observed facts
|
||||||
|
|
||||||
|
- Zeus runs NixOS with a CachyOS kernel.
|
||||||
|
- Zeus uses an AMD Radeon RX 9070-series GPU with the `amdgpu` driver.
|
||||||
|
- Zeus runs Hyprland on Wayland.
|
||||||
|
- Zeus has Steam and Gamescope configured.
|
||||||
|
- SteamVR 2.17.10 is installed.
|
||||||
|
- SteamVR includes Valve's Linux `vrlink` driver.
|
||||||
|
- A previous `vrlink` session detected the Quest 3 and its Touch controllers.
|
||||||
|
- That session selected 90 Hz from the Quest's 72, 80, 90, and 120 Hz modes.
|
||||||
|
- SteamVR setup lacks `cap_sys_nice` on `vrcompositor-launcher`.
|
||||||
|
- NixOS can declare host packages, permissions, services, and diagnostics.
|
||||||
|
- Steam owns the Quest pairing and SteamVR user settings.
|
||||||
|
- Zeus connects by Ethernet at `10.23.50.221`.
|
||||||
|
- The local Wi-Fi scan finds the `Tracion` 5 GHz network at 5220 MHz.
|
||||||
|
- The scan reports a 1170 Mbit/s link rate.
|
||||||
|
- The operator has no external tracked devices.
|
||||||
|
|
||||||
|
## Decision tree
|
||||||
|
|
||||||
|
- **D1: Host platform commitment** — Settled: Linux-native on the current NixOS installation.
|
||||||
|
- Linux-native on the current NixOS installation.
|
||||||
|
- **D2: Transport** — Blocked by D1
|
||||||
|
- Wireless LAN. — Settled: primary transport.
|
||||||
|
- **D3: Streaming stack** — Settled: SteamVR with its built-in VRLink driver.
|
||||||
|
- SteamVR with its built-in VRLink driver.
|
||||||
|
- **D3a: SteamVR acceptance criteria** — Settled: reliable session test.
|
||||||
|
- Run a SteamVR game for 30 minutes at 90 Hz.
|
||||||
|
- Verify visuals, audio, and Touch controllers.
|
||||||
|
- Verify one reconnect.
|
||||||
|
- ALVR only after SteamVR fails the agreed acceptance criteria.
|
||||||
|
- **D4: Wi-Fi topology** — Settled: keep the current access point.
|
||||||
|
- Keep the current access point.
|
||||||
|
- Add a dedicated access point.
|
||||||
|
- Use a direct Wi-Fi link.
|
||||||
|
- **D5: Session performance target** — Settled: selectable refresh-rate profiles.
|
||||||
|
- Selectable refresh-rate profiles.
|
||||||
|
- **D5a: Default refresh rate** — Settled: 90 Hz.
|
||||||
|
- **D5b: Included refresh rates** — Settled: 72, 80, 90, and 120 Hz.
|
||||||
|
- **D6: Network isolation** — Settled: existing trusted LAN.
|
||||||
|
- Existing trusted LAN.
|
||||||
|
- Dedicated VR VLAN or SSID.
|
||||||
|
- **D7: Controller and tracking scope** — Settled: Quest Touch controllers only.
|
||||||
|
- Quest Touch controllers only.
|
||||||
|
- Also support external tracked devices.
|
||||||
|
- **D8: Launch workflow** — Settled: automatic service and headset connection.
|
||||||
|
- Start SteamVR when Steam Link connects from the Quest.
|
||||||
|
- **D9: Diagnostics and recovery** — Settled: capture health checks and logs.
|
||||||
|
- Capture SteamVR logs and health checks.
|
||||||
|
- Recover failed sessions manually.
|
||||||
|
- USB tether.
|
||||||
|
- **D10: USB streaming stack** — Blocked by D2
|
||||||
|
- ALVR over USB.
|
||||||
|
- Meta Quest Link through a Windows installation.
|
||||||
|
- **D11: USB role** — Blocked by D2
|
||||||
|
- Primary transport.
|
||||||
|
- Fallback transport.
|
||||||
|
- Both wireless LAN and USB tether.
|
||||||
|
- **D12: Primary transport** — Blocked by D2
|
||||||
|
- **D13: Fallback behavior** — Blocked by D12
|
||||||
|
- **D14: System integration** — Settled: hybrid configuration.
|
||||||
|
- NixOS manages system integration.
|
||||||
|
- Steam manages Quest pairing and user settings.
|
||||||
|
- Dual-boot or replace NixOS with Windows.
|
||||||
|
- **D15: Windows streaming stack** — Blocked by D1
|
||||||
|
- Steam Link.
|
||||||
|
- Virtual Desktop.
|
||||||
|
- Meta Quest Link or Air Link.
|
||||||
|
- ALVR.
|
||||||
|
- **D16: Windows installation scope** — Blocked by D1
|
||||||
|
- Dedicated VR installation.
|
||||||
|
- General-use Windows installation.
|
||||||
|
- **D2: Transport** — Blocked by D1
|
||||||
|
- Keep NixOS and add a separate Windows VR host.
|
||||||
|
- **D17: Host placement** — Blocked by D1
|
||||||
|
- **D15: Windows streaming stack** — Blocked by D17
|
||||||
|
- **D2: Transport** — Blocked by D17
|
||||||
|
|
||||||
|
## Frontier
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
## Settled decisions
|
||||||
|
|
||||||
|
- **D1: Host platform commitment** — Linux-native on the current NixOS installation.
|
||||||
|
- **D2: Transport** — Wireless LAN as the primary transport.
|
||||||
|
- **D4: Wi-Fi topology** — Keep the current access point.
|
||||||
|
- **D5: Session performance target** — Selectable profiles at 72, 80, 90, and 120 Hz.
|
||||||
|
- **D5a: Default refresh rate** — 90 Hz.
|
||||||
|
- **D5b: Included refresh rates** — 72, 80, 90, and 120 Hz.
|
||||||
|
- **D6: Network isolation** — Existing trusted LAN.
|
||||||
|
- **D7: Controller and tracking scope** — Quest Touch controllers only.
|
||||||
|
- **D3: Streaming stack** — SteamVR with its built-in VRLink driver.
|
||||||
|
- **D3a: SteamVR acceptance criteria** — 30-minute session at 90 Hz, with visuals, audio, Touch controllers, and one reconnect.
|
||||||
|
- **D8: Launch workflow** — Start SteamVR when Steam Link connects from the Quest.
|
||||||
|
- **D9: Diagnostics and recovery** — Capture health checks and logs. Recover failed sessions manually.
|
||||||
|
- **D14: System integration** — NixOS manages system integration. Steam manages Quest pairing and user settings.
|
||||||
0
docs/03 wrk/homelab.md
Normal file
0
docs/03 wrk/homelab.md
Normal file
@@ -3,8 +3,8 @@ aliases:
|
|||||||
- "0015"
|
- "0015"
|
||||||
- RomM 5.4 Package
|
- RomM 5.4 Package
|
||||||
date-created: 2026-10-19 19:40
|
date-created: 2026-10-19 19:40
|
||||||
date-modified: 2026-10-19 19:40
|
date-modified: 2026-10-21 00:01
|
||||||
status: open
|
status: closed
|
||||||
area: "[[homelab]]"
|
area: "[[homelab]]"
|
||||||
blocked-by:
|
blocked-by:
|
||||||
- "[[0014-romm-guest]]"
|
- "[[0014-romm-guest]]"
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
---
|
||||||
|
date-created: 2026-10-19 02:39
|
||||||
|
date-modified: 2026-10-20 17:45
|
||||||
|
---
|
||||||
# Brain Agent Instructions
|
# Brain Agent Instructions
|
||||||
|
|
||||||
This repository is an Obsidian vault for an execution-focused second brain.
|
This repository is an Obsidian vault for an execution-focused second brain.
|
||||||
@@ -32,6 +36,3 @@ Include negative decisions only when they prevent a likely, harmful, or repeated
|
|||||||
|
|
||||||
Remove template instruction text when writing a note from a template.
|
Remove template instruction text when writing a note from a template.
|
||||||
|
|
||||||
## Gotchas
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -51,11 +51,8 @@
|
|||||||
|
|
||||||
- lidarr (requires raichu)
|
- lidarr (requires raichu)
|
||||||
- immich
|
- immich
|
||||||
- romm
|
|
||||||
- gitea
|
- gitea
|
||||||
- nginxproxymanager (gradual migration to nginx guest)
|
- nginxproxymanager (gradual migration to nginx guest)
|
||||||
- adguard
|
|
||||||
- manage DNS rewrites for local service names such as `home`
|
|
||||||
|
|
||||||
## Raichu Proxmox -> Nixos
|
## Raichu Proxmox -> Nixos
|
||||||
|
|
||||||
@@ -110,8 +107,3 @@
|
|||||||
- Investigate Rust Bazel target structure.
|
- Investigate Rust Bazel target structure.
|
||||||
Prefer clear per-file dependency edges, but `rust_library` maps each target to a crate.
|
Prefer clear per-file dependency edges, but `rust_library` maps each target to a crate.
|
||||||
Decide whether wrapper rules or another pattern can improve graph clarity without forcing artificial crate boundaries.
|
Decide whether wrapper rules or another pattern can improve graph clarity without forcing artificial crate boundaries.
|
||||||
|
|
||||||
## Nix Refactor
|
|
||||||
|
|
||||||
Review Nix files in entrypoint order:
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,5 +4,7 @@
|
|||||||
inherit root;
|
inherit root;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
romm = pkgs.callPackage ./romm.nix { };
|
||||||
|
|
||||||
waybar = pkgs.callPackage ./waybar.nix { };
|
waybar = pkgs.callPackage ./waybar.nix { };
|
||||||
}
|
}
|
||||||
|
|||||||
124
src/flake/packages/romm.nix
Normal file
124
src/flake/packages/romm.nix
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
{
|
||||||
|
buildNpmPackage,
|
||||||
|
fetchFromGitHub,
|
||||||
|
lib,
|
||||||
|
python3,
|
||||||
|
romm,
|
||||||
|
}:
|
||||||
|
romm.overrideAttrs (
|
||||||
|
finalAttrs: previousAttrs:
|
||||||
|
let
|
||||||
|
frontend = buildNpmPackage {
|
||||||
|
pname = "romm-frontend";
|
||||||
|
inherit (finalAttrs) version;
|
||||||
|
src = "${finalAttrs.src}/frontend";
|
||||||
|
|
||||||
|
npmDepsHash = "sha256-f5IcpOVv7JYFzUPkZIq5nbT3dS1f/KCSllh8Vkgl1P0=";
|
||||||
|
npmFlags = [ "--ignore-scripts" ];
|
||||||
|
makeCacheWritable = true;
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
cp -r dist $out
|
||||||
|
chmod u+w $out/assets
|
||||||
|
cp -r assets/. $out/assets/
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
# RomM 5.4 requires packages absent from the Nixpkgs 5.2 environment.
|
||||||
|
pythonEnv = python3.withPackages (
|
||||||
|
ps: with ps; [
|
||||||
|
aiohttp
|
||||||
|
alembic
|
||||||
|
anyio
|
||||||
|
apprise
|
||||||
|
asyncssh
|
||||||
|
authlib
|
||||||
|
bcrypt
|
||||||
|
colorama
|
||||||
|
croniter
|
||||||
|
cryptography
|
||||||
|
defusedxml
|
||||||
|
email-validator
|
||||||
|
fastapi
|
||||||
|
gunicorn
|
||||||
|
httpx
|
||||||
|
httpx2
|
||||||
|
itsdangerous
|
||||||
|
jinja2
|
||||||
|
joserfc
|
||||||
|
mariadb
|
||||||
|
mutagen
|
||||||
|
mysql-connector-python
|
||||||
|
opentelemetry-distro
|
||||||
|
opentelemetry-exporter-otlp
|
||||||
|
opentelemetry-instrumentation-aiohttp-client
|
||||||
|
opentelemetry-instrumentation-fastapi
|
||||||
|
opentelemetry-instrumentation-httpx
|
||||||
|
opentelemetry-instrumentation-redis
|
||||||
|
opentelemetry-instrumentation-sqlalchemy
|
||||||
|
passlib
|
||||||
|
pillow
|
||||||
|
psycopg
|
||||||
|
pydantic
|
||||||
|
pydash
|
||||||
|
python-dotenv
|
||||||
|
python-magic
|
||||||
|
python-multipart
|
||||||
|
python-socketio
|
||||||
|
pyyaml
|
||||||
|
redis
|
||||||
|
rq
|
||||||
|
rq-scheduler
|
||||||
|
sentry-sdk
|
||||||
|
sqlalchemy
|
||||||
|
starlette
|
||||||
|
streaming-form-data
|
||||||
|
strsimpy
|
||||||
|
ua-parser
|
||||||
|
unidecode
|
||||||
|
uvicorn
|
||||||
|
uvicorn-worker
|
||||||
|
watchfiles
|
||||||
|
yarl
|
||||||
|
zipfile-inflate64
|
||||||
|
zstandard
|
||||||
|
]
|
||||||
|
);
|
||||||
|
in
|
||||||
|
{
|
||||||
|
version = "5.4.0";
|
||||||
|
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "rommapp";
|
||||||
|
repo = "romm";
|
||||||
|
tag = finalAttrs.version;
|
||||||
|
hash = "sha256-oIYEdIAJgXkcqjZtWlWKD/NFiQ3gbo7gxwLhqZOCWpM=";
|
||||||
|
};
|
||||||
|
|
||||||
|
postPatch = previousAttrs.postPatch + ''
|
||||||
|
# Redis 8.0.1 removed this argument.
|
||||||
|
# RomM disables the related maintenance notifications.
|
||||||
|
substituteInPlace backend/handler/redis_handler.py \
|
||||||
|
--replace-fail 'from redis.maint_notifications import MaintNotificationsConfig' "" \
|
||||||
|
--replace-fail ' "maint_notifications_config": MaintNotificationsConfig(enabled=False),' ""
|
||||||
|
'';
|
||||||
|
|
||||||
|
installPhase =
|
||||||
|
lib.replaceStrings
|
||||||
|
[
|
||||||
|
"${previousAttrs.passthru.frontend}"
|
||||||
|
"${previousAttrs.passthru.pythonEnv}"
|
||||||
|
]
|
||||||
|
[
|
||||||
|
"${frontend}"
|
||||||
|
"${pythonEnv}"
|
||||||
|
]
|
||||||
|
previousAttrs.installPhase;
|
||||||
|
|
||||||
|
passthru = previousAttrs.passthru // {
|
||||||
|
inherit frontend pythonEnv;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user