This is a automagiduckically updated README.md
Caution
Do not blindly run this flake.
That's my job. 🧑🦯
Here lives home machines configurations,
crafted as a tiny Nix flake
Glued together by a Nix-flavoured command line utility,
easiy expanded and used to deploy, doc, and duck around 🦆✨
Nix Declarative configuration style, custom modules evaluated dynamically for each host.
Home Manager - No duckng way. I just auto symlink ./home to /home
Zigbee and smart home tightly integrated with Nix. For not just a declarative house but also deployable apartments.
- 66 qwacktastic scripts in /bin
- Smart Home Nix style
- Natural Language support with complete voice pipeline
- Infra as everyday accessibility
- Yubikey encrypted deployment system
- Self Documenting
List would get long, very quickly
perhaps a more suitable question would be:
"What makes this configuration common?"
Define yourself at `config.this.user.me`.
{
discord = "https://discordapp.com/users/675530282849533952";
dotfilesDir = "/home/pungkula/dotfiles";
email = "isthisrandomenough@protonmail.com";
extraGroups = [ "networkmanager" "wheel" "dialout" "docker" "dockeruser" "users" "pungkula" "adbusers" "audio" "2000" ];
hashedPassword = "$y$j9T$m8hPD36i1VMaO5rurbZ4j0$KpzQyat.F6NoWFKpisEj77TvpN2wBGB8ezd26QoKDj6";
matrix = "";
mobileDevices = {
iphone = {
pubkey = "UFB0T1Y/uLZi3UBtEaVhCi+QYldYGcOZiF9KKurC5Hw=";
wgip = "10.0.0.7"
};
tablet = {
pubkey = "ETRh93SQaY+Tz/F2rLAZcW7RFd83eofNcBtfyHCBWE4=";
wgip = "10.0.0.8"
};
};
name = "pungkula";
repo = "git@github.com:QuackHack-McBlindy/dotfiles.git"
};
Define each hosts data at `config.this.host`.
{
hostname = "desktop";
interface = [ "enp119s0" ];
ip = "192.168.1.111";
keys = {
privateKeys = {
};
publicKeys = {
adb = "QAAAACEJNfsfRV4PQ9Ah87MbTVbMkbXC6CAMDOR+0K6mIpv/4TSzYMkc2qit3Kryc55IVOjwR3fJRjj/uL549gZ7nEemWtcd3AsYQBp0iIEor8nu1L/V6jfsTY6Xe/pl06xoroy6OwZRWuDbZ4wD2xQRRQjfPd+JtYnMAWneM6r1V15uR67w4ITvjk3ckyfgNeLZMUwahMRjC3wSjaU9sAdKNmg8yPd8uHZ+mK6mstxJFAGEpnnm1lE7Z2r0DF6h6MKY1++dwhU+WM5BRDNiBg+D4i6fDW4+Z1I9ENuFnjT17zAxZXch04SNlG3O94BANYP7jmKp60OvtDL6msfphntuIUzMCkndF9De0Kv4lJdQxe1d+wf+AFpmtd/xtrk45YdMV+eWCJf2OkidaHmSj4ffkAobpun0VrkZN2Z1JymmdsvUbyMjAsby3Zun0xr3EocUS8Jy5TcsK/dcpD6CB5dqzlHhsHSAWt2TDwPzZYXgV1xc+q+PqM09OVN1xActJu75UMkg5b84U15hwQvYdwB8UaopMWWk6p064c7gxYSfH7fSxwkW2Jy1CElgJa55Pp4SZG9b/3B+VcNL1WSf6v/lvJqPbrRvBqvS0+e9wcFMNZtQKTX3n5X0wW1/czZPCQX+hmM8Uu1qrtaz4rKViIEGf4YR0/9eUGYQVfuAxAh8ZmsroJlnAAEAAQA= pungkula@desktop";
age = "age16utg7mmk73cn3glrwthtm0p7mf6g3vrd48h3ucpn6wnf28pgxvcsh4rjjp";
borg = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMVYczAOBSeS7WfSvzYDOS4Q9Ss+yxCf2G5MVfAALOx/";
builder = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINQ7c/AeIpmJS6cWQkHOe4ZEq3DXVRnjtTWuWfx6L46n";
cache = "cache:/pbj1Agw2OoSSDZcClS69RHa1aNcwwTOX3GIEGKYwPc=";
host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILdwPkRQxlbrbRGwEO5zMJ4m+7QqUQPZg1iqbd5HRP34";
iPhone = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMcmr+z7k/yCbrFg+JDgo8JCuWqNVYn10ajRbNTp8fq";
ssh = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPwZL27kGTQDIlSe03abT9F24nSAizORyjo5cI3BD92s";
wireguard = "Oq0ZaYAnOo5sLpV//OEFwLgjVCxPyeQqf8cZBASluWk="
};
};
modules = {
hardware = [ "cpu/intel" "gpu/amd" "audio" ];
networking = [ "default" "pool" ];
programs = [ "default" "thunar" "firefox" "vesktop" ];
services = [ "ssh" "default" "adb" "backup" "cache" "keyd" "jelly" "duck-tv" ];
system = [ "nix" "pkgs" "gnome" "crossEnv" "gtk" ];
virtualisation = [ "docker" "vm" ]
};
system = "x86_64-linux";
wgip = "10.0.0.2"
};
Define any optional theme configuration at `config.this.theme`.
{
cursorTheme = {
name = "Bibata-Modern-Classic";
package = "/nix/store/1np4cfqil5jh04zmscj3i6h2zvh9yqvv-bibata-cursors-2.0.7";
size = 32
};
enable = false;
fonts = {
monospace = "Fira Code";
packages = [ "/nix/store/k4s2ckig2pyi2lzzaxmh8wcwbq7n7pz3-fira-code-6.2" ];
system = "Fira Sans"
};
gtkSettings = {
gtk-application-prefer-dark-theme = "1";
gtk-cursor-theme-name = "Bibata-Modern-Classic";
gtk-icon-theme-name = "elementary-xfce-icon-theme"
};
iconTheme = {
name = "Papirus-Dark";
package = "/nix/store/5ncf05fvvy7zmb2azprzq1qhymwh733h-papirus-icon-theme-20250201"
};
name = "gtk3.css";
styles = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/css/gtk3.css"
};
For smart home integration, define your devices at `config.house`.
Zigbee devices at `config.house.zigbee.devices`.
```nix { 0x000b57fffe0e2a04 = { batteryType = null; endpoint = 1; friendly_name = "Vägg"; icon = "mdi:lightbulb"; room = "hallway"; supports_color = false; type = "light"; }; 0x000b57fffe0f0807 = { batteryType = null; endpoint = 1; friendly_name = "IKEA 5 Dimmer"; icon = "mdi:remote"; room = "other"; supports_color = false; type = "remote"; }; 0x00158d00053ec9b1 = { batteryType = null; endpoint = 1; friendly_name = "Door Sensor Hall"; icon = "mdi:door"; room = "hallway"; supports_color = false; type = "sensor"; }; 0x00178801001ecdaa = { batteryType = null; endpoint = 11; friendly_name = "Bloom"; icon = "mdi:lightbulb"; room = "bedroom"; supports_color = true; type = "light"; }; 0x00178801021311c4 = { batteryType = "AAA"; endpoint = 1; friendly_name = "Motion Sensor Hall"; icon = "mdi:motion-sensor"; room = "hallway"; supports_color = false; type = "motion"; }; 0x0017880102de8570 = { batteryType = null; endpoint = 11; friendly_name = "Rustning"; icon = "mdi:spotlight"; room = "livingroom"; supports_color = true; type = "light"; }; 0x0017880102f0848a = { batteryType = null; endpoint = 11; friendly_name = "Spotlight kök 1"; icon = "mdi:spotlight"; room = "kitchen"; supports_color = false; type = "light"; }; 0x0017880102f08526 = { batteryType = null; endpoint = 11; friendly_name = "Spotlight Kök 2"; icon = "mdi:spotlight"; room = "kitchen"; supports_color = false; type = "light"; }; 0x0017880103406f41 = { batteryType = null; endpoint = 11; friendly_name = "WC 2"; icon = "mdi:ceiling-light"; room = "wc"; supports_color = false; type = "light"; }; 0x001788010361b842 = { batteryType = null; endpoint = 11; friendly_name = "WC 1"; icon = "mdi:ceiling-light"; room = "wc"; supports_color = false; type = "light"; }; 0x00178801037e754e = { batteryType = null; endpoint = 1; friendly_name = "Takkrona 1"; icon = "mdi:ceiling-light"; room = "livingroom"; supports_color = true; type = "light"; }; 0x0017880103a0d280 = { batteryType = null; endpoint = 11; friendly_name = "Uppe"; icon = "mdi:light-strip"; room = "kitchen"; supports_color = true; type = "light"; }; 0x0017880103c73f85 = { batteryType = null; endpoint = 1; friendly_name = "Takkrona 2"; icon = "mdi:ceiling-light"; room = "livingroom"; supports_color = true; type = "light"; }; 0x0017880103c7467d = { batteryType = null; endpoint = 11; friendly_name = "Taket Sovrum 2"; icon = "mdi:ceiling-light"; room = "bedroom"; supports_color = true; type = "light"; }; 0x0017880103c753b8 = { batteryType = null; endpoint = 1; friendly_name = "Takkrona 4"; icon = "mdi:ceiling-light"; room = "livingroom"; supports_color = true; type = "light"; }; 0x0017880103ca6e95 = { batteryType = "CR2450"; endpoint = 1; friendly_name = "Dimmer Switch Kök"; icon = "mdi:toggle-switch"; room = "kitchen"; supports_color = false; type = "dimmer"; }; 0x0017880103e0add1 = { batteryType = null; endpoint = 11; friendly_name = "Golvet"; icon = "mdi:light-strip"; room = "kitchen"; supports_color = true; type = "light"; }; 0x0017880103eafdd6 = { batteryType = null; endpoint = 11; friendly_name = "Tak Hall"; icon = "mdi:ceiling-light"; room = "hallway"; supports_color = false; type = "light"; }; 0x0017880103f44b5f = { batteryType = null; endpoint = 11; friendly_name = "Dörr"; icon = "mdi:light-strip"; room = "bedroom"; supports_color = true; type = "light"; }; 0x0017880103f94041 = { batteryType = null; endpoint = 1; friendly_name = "Takkrona 3"; icon = "mdi:ceiling-light"; room = "livingroom"; supports_color = true; type = "light"; }; 0x0017880104051a86 = { batteryType = null; endpoint = 11; friendly_name = "Sänggavel"; icon = "mdi:light-strip"; room = "bedroom"; supports_color = true; type = "light"; }; 0x0017880104540411 = { batteryType = null; endpoint = 11; friendly_name = "PC"; icon = "mdi:spotlight"; room = "livingroom"; supports_color = true; type = "light"; }; 0x0017880104f77d61 = { batteryType = "CR2450"; endpoint = 1; friendly_name = "Dimmer Switch Sovrum"; icon = "mdi:toggle-switch"; room = "bedroom"; supports_color = false; type = "dimmer"; }; 0x0017880104f78065 = { batteryType = "CR2450"; endpoint = 1; friendly_name = "Dimmer Switch Vardagsrum"; icon = "mdi:toggle-switch"; room = "livingroom"; supports_color = false; type = "dimmer"; }; 0x0017880106156cb0 = { batteryType = null; endpoint = 11; friendly_name = "Taket Sovrum 1"; icon = "mdi:ceiling-light"; room = "bedroom"; supports_color = true; type = "light"; }; 0x0017880109ac14f3 = { batteryType = null; endpoint = 11; friendly_name = "Sänglampa"; icon = "mdi:lightbulb"; room = "bedroom"; supports_color = true; type = "light"; }; 0x0c4314fffe179b05 = { batteryType = null; endpoint = 1; friendly_name = "Fläkt"; icon = "mdi:power-socket-eu"; room = "kitchen"; supports_color = false; type = "outlet"; }; 0x540f57fffe85c9c3 = { batteryType = null; endpoint = 1; friendly_name = "Water Sensor"; icon = "mdi:water"; room = "livingroom"; supports_color = false; type = "sensor"; }; 0x54ef4410003e58e2 = { batteryType = null; endpoint = 1; friendly_name = "Roller Shade"; icon = "mdi:blinds"; room = "livingroom"; supports_color = false; type = "blind"; }; 0x70ac08fffe6497be = { batteryType = "CR2032"; endpoint = 1; friendly_name = "On/Off Switch 1"; icon = "mdi:remote"; room = "other"; supports_color = false; type = "remote"; }; 0x70ac08fffe65211e = { batteryType = "CR2032"; endpoint = 1; friendly_name = "On/Off Switch 2"; icon = "mdi:remote"; room = "other"; supports_color = false; type = "remote"; }; 0x70ac08fffe9fa3d1 = { batteryType = "CR2032"; endpoint = 1; friendly_name = "Motion Sensor Kök"; icon = "mdi:motion-sensor"; room = "kitchen"; supports_color = false; type = "motion"; }; 0xa4c1380afa9f7f3e = { batteryType = null; endpoint = 1; friendly_name = "Smoke Alarm Kitchen"; icon = "mdi:smoke-detector"; room = "kitchen"; supports_color = false; type = "sensor"; }; 0xa4c1382553627626 = { batteryType = null; endpoint = 1; friendly_name = "Power Plug"; icon = "mdi:power-socket-eu"; room = "other"; supports_color = false; type = "outlet"; }; 0xa4c13873044cb7ea = { batteryType = null; endpoint = 11; friendly_name = "Kök Bänk Slinga"; icon = "mdi:light-strip"; room = "kitchen"; supports_color = false; type = "light"; }; 0xa4c138b9aab1cf3f = { batteryType = null; endpoint = 1; friendly_name = "Power Plug 2"; icon = "mdi:power-socket-eu"; room = "other"; supports_color = false; type = "outlet"; }; 0xf4b3b1fffeaccb27 = { batteryType = "CR2032"; endpoint = 1; friendly_name = "Motion Sensor Sovrum"; icon = "mdi:motion-sensor"; room = "bedroom"; supports_color = false; type = "motion"; }; } ```Zigbee scenes at `config.house.zigbee.scenes`.
```nix { Chill Scene = { Bloom = { brightness = 200; color = { hex = "#FFB6C1"; }; state = "ON"; }; Golvet = { brightness = 200; color = { hex = "#40E0D0"; }; state = "ON"; }; PC = { brightness = 200; color = { hex = "#8A2BE2"; }; state = "ON"; }; Spotlight Kök 1 = { brightness = 200; color = { hex = "#FFD700"; }; state = "OFF"; }; Spotlight Kök 2 = { brightness = 200; color = { hex = "#FF8C00"; }; state = "OFF"; }; Sänggavel = { brightness = 200; color = { hex = "#7FFFD4"; }; state = "ON"; }; Taket Sovrum 1 = { brightness = 200; color = { hex = "#00CED1"; }; state = "ON"; }; Taket Sovrum 2 = { brightness = 200; color = { hex = "#9932CC"; }; state = "ON"; }; Takkrona 1 = { brightness = 200; color = { hex = "#7FFFD4"; }; state = "ON"; }; Takkrona 2 = { brightness = 200; color = { hex = "#7FFFD4"; }; state = "ON"; }; Takkrona 3 = { brightness = 200; color = { hex = "#7FFFD4"; }; state = "ON"; }; Takkrona 4 = { brightness = 200; color = { hex = "#7FFFD4"; }; state = "ON"; }; Uppe = { brightness = 200; color = { hex = "#FF69B4"; }; state = "ON"; }; }; Duck Scene = { PC = { brightness = 200; color = { hex = "#00FF00"; }; state = "ON"; }; }; Green D = { Bloom = { brightness = 200; color = { hex = "#00FF00"; }; state = "ON"; }; Golvet = { brightness = 200; color = { hex = "#00FF00"; }; state = "ON"; }; PC = { brightness = 200; color = { hex = "#00FF00"; }; state = "ON"; }; Spotlight Kök 1 = { brightness = 200; color = { hex = "#00FF00"; }; state = "OFF"; }; Spotlight Kök 2 = { brightness = 200; color = { hex = "#00FF00"; }; state = "OFF"; }; Sänggavel = { brightness = 200; color = { hex = "#00FF00"; }; state = "ON"; }; Taket Sovrum 1 = { brightness = 200; color = { hex = "#00FF00"; }; state = "ON"; }; Taket Sovrum 2 = { brightness = 200; color = { hex = "#00FF00"; }; state = "ON"; }; Takkrona 1 = { brightness = 200; color = { hex = "#7FFFD4"; }; state = "ON"; }; Takkrona 2 = { brightness = 200; color = { hex = "#7FFFD4"; }; state = "ON"; }; Takkrona 3 = { brightness = 200; color = { hex = "#7FFFD4"; }; state = "ON"; }; Takkrona 4 = { brightness = 200; color = { hex = "#7FFFD4"; }; state = "ON"; }; Uppe = { brightness = 200; color = { hex = "#00FF00"; }; state = "ON"; }; }; dark = { Bloom = { state = "OFF"; transition = 10; }; Dörr = { state = "OFF"; transition = 10; }; Golvet = { state = "OFF"; transition = 10; }; Kök Bänk Slinga = { state = "OFF"; transition = 10; }; PC = { state = "OFF"; transition = 10; }; Rustning = { state = "OFF"; transition = 10; }; Spotlight Kök 2 = { state = "OFF"; transition = 10; }; Spotlight kök 1 = { state = "OFF"; transition = 10; }; Sänggavel = { state = "OFF"; transition = 10; }; Sänglampa = { state = "OFF"; transition = 10; }; Tak Hall = { state = "OFF"; transition = 10; }; Taket Sovrum 1 = { state = "OFF"; transition = 10; }; Taket Sovrum 2 = { state = "OFF"; transition = 10; }; Takkrona 1 = { state = "OFF"; transition = 10; }; Takkrona 2 = { state = "OFF"; transition = 10; }; Takkrona 3 = { state = "OFF"; transition = 10; }; Takkrona 4 = { state = "OFF"; transition = 10; }; Uppe = { state = "OFF"; transition = 10; }; Vägg = { state = "OFF"; transition = 10; }; WC 1 = { state = "OFF"; transition = 10; }; WC 2 = { state = "OFF"; transition = 10; }; }; dark-fast = { Bloom = { state = "OFF"; }; Dörr = { state = "OFF"; }; Golvet = { state = "OFF"; }; Kök Bänk Slinga = { state = "OFF"; }; PC = { state = "OFF"; }; Rustning = { state = "OFF"; }; Spotlight Kök 2 = { state = "OFF"; }; Spotlight kök 1 = { state = "OFF"; }; Sänggavel = { state = "OFF"; }; Sänglampa = { state = "OFF"; }; Tak Hall = { state = "OFF"; }; Taket Sovrum 1 = { state = "OFF"; }; Taket Sovrum 2 = { state = "OFF"; }; Takkrona 1 = { state = "OFF"; }; Takkrona 2 = { state = "OFF"; }; Takkrona 3 = { state = "OFF"; }; Takkrona 4 = { state = "OFF"; }; Uppe = { state = "OFF"; }; Vägg = { state = "OFF"; }; WC 1 = { state = "OFF"; }; WC 2 = { state = "OFF"; }; }; max = { Bloom = { brightness = 255; color = { hex = "#FFFFFF"; }; state = "ON"; }; Dörr = { brightness = 255; color = { hex = "#FFFFFF"; }; state = "ON"; }; Golvet = { brightness = 255; color = { hex = "#FFFFFF"; }; state = "ON"; }; Kök Bänk Slinga = { brightness = 255; color = { hex = "#FFFFFF"; }; state = "ON"; }; PC = { brightness = 255; color = { hex = "#FFFFFF"; }; state = "ON"; }; Rustning = { brightness = 255; color = { hex = "#FFFFFF"; }; state = "ON"; }; Spotlight Kök 2 = { brightness = 255; color = { hex = "#FFFFFF"; }; state = "ON"; }; Spotlight kök 1 = { brightness = 255; color = { hex = "#FFFFFF"; }; state = "ON"; }; Sänggavel = { brightness = 255; color = { hex = "#FFFFFF"; }; state = "ON"; }; Sänglampa = { brightness = 255; color = { hex = "#FFFFFF"; }; state = "ON"; }; Tak Hall = { brightness = 255; color = { hex = "#FFFFFF"; }; state = "ON"; }; Taket Sovrum 1 = { brightness = 255; color = { hex = "#FFFFFF"; }; state = "ON"; }; Taket Sovrum 2 = { brightness = 255; color = { hex = "#FFFFFF"; }; state = "ON"; }; Takkrona 1 = { brightness = 255; color = { hex = "#FFFFFF"; }; state = "ON"; }; Takkrona 2 = { brightness = 255; color = { hex = "#FFFFFF"; }; state = "ON"; }; Takkrona 3 = { brightness = 255; color = { hex = "#FFFFFF"; }; state = "ON"; }; Takkrona 4 = { brightness = 255; color = { hex = "#FFFFFF"; }; state = "ON"; }; Uppe = { brightness = 255; color = { hex = "#FFFFFF"; }; state = "ON"; }; Vägg = { brightness = 255; color = { hex = "#FFFFFF"; }; state = "ON"; }; WC 1 = { brightness = 255; color = { hex = "#FFFFFF"; }; state = "ON"; }; WC 2 = { brightness = 255; color = { hex = "#FFFFFF"; }; state = "ON"; }; }; } ```Android TV devices at `config.house.tv`.
```nix { arris = { apps = { telenor = "se.telenor.stream/.MainActivity "; tv4 = "se.tv4.tv4playtab/se.tv4.tv4play.ui.mobile.main.BottomNavigationActivity"; }; channels = { 1 = { cmd = ""; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/1.png"; id = 1; name = "SVT1"; scrape_url = "https://tv-tabla.se/tabla/svt1/"; stream_url = ""; }; 10 = { cmd = ""; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/10.png"; id = 10; name = "Kanal 10"; scrape_url = "https://tv-tabla.se/tabla/tv10/"; stream_url = ""; }; 11 = { cmd = ""; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/11.png"; id = 11; name = "Kanal 11"; scrape_url = "https://tv-tabla.se/tabla/tv11/"; stream_url = ""; }; 12 = { cmd = ""; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/12.png"; id = 12; name = "Kanal 12"; scrape_url = "https://tv-tabla.se/tabla/tv12/"; stream_url = ""; }; 13 = { cmd = "nav_down && nav_down && nav_right && nav_right && nav_center"; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/13.png"; id = 13; name = "TV4 Hockey"; scrape_url = "https://tv-tabla.se/tabla/tv4_hockey/"; stream_url = ""; }; 14 = { cmd = "nav_down && nav_down && nav_right && nav_right && nav_center"; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/14.png"; id = 14; name = "TV4 Sport Live 1"; scrape_url = "https://tv-tabla.se/tabla/tv4_sport_live_1/"; stream_url = ""; }; 15 = { cmd = "nav_down && nav_down && nav_right && nav_right && nav_center"; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/15.png"; id = 15; name = "TV4 Sport Live 2"; scrape_url = "https://tv-tabla.se/tabla/tv4_sport_live_2/"; stream_url = ""; }; 16 = { cmd = "nav_down && nav_down && nav_right && nav_right && nav_center"; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/16.png"; id = 16; name = "TV4 Sport Live 3"; scrape_url = "https://tv-tabla.se/tabla/tv4_sport_live_3/"; stream_url = ""; }; 17 = { cmd = "nav_down && nav_down && nav_right && nav_right && nav_center"; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/17.png"; id = 17; name = "TV 4 Sport Live 4"; scrape_url = "https://tv-tabla.se/tabla/tv4_sport_live_4/"; stream_url = ""; }; 2 = { cmd = ""; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/2.png"; id = 2; name = "SVT2"; scrape_url = "https://tv-tabla.se/tabla/svt2/"; stream_url = ""; }; 3 = { cmd = ""; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/3.png"; id = 3; name = "Kanal 3"; scrape_url = "https://tv-tabla.se/tabla/tv3/"; stream_url = ""; }; 4 = { cmd = ""; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/4.png"; id = 4; name = "TV4"; scrape_url = "https://tv-tabla.se/tabla/tv4/"; stream_url = ""; }; 5 = { cmd = ""; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/5.png"; id = 5; name = "TV5"; scrape_url = "https://tv-tabla.se/tabla/kanal_5/"; stream_url = ""; }; 6 = { cmd = ""; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/6.png"; id = 6; name = "Kanal 6"; scrape_url = "https://tv-tabla.se/tabla/tv6/"; stream_url = ""; }; 7 = { cmd = ""; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/7.png"; id = 7; name = "Sjuan"; scrape_url = "https://tv-tabla.se/tabla/sjuan/"; stream_url = ""; }; 8 = { cmd = ""; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/8.png"; id = 8; name = "TV8"; scrape_url = "https://tv-tabla.se/tabla/tv8/"; stream_url = ""; }; 9 = { cmd = ""; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/9.png"; id = 9; name = "Kanal 9"; scrape_url = "https://tv-tabla.se/tabla/kanal_9/"; stream_url = ""; }; }; enable = true; ip = "192.168.1.152"; room = "bedroom"; }; shield = { apps = { telenor = "se.telenor.stream/.MainActivity"; tv4 = "se.tv4.tv4playtab/se.tv4.tv4play.ui.mobile.main.BottomNavigationActivity"; }; channels = { 1 = { cmd = "open_telenor && wait 5 && start_channel_1"; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/1.png"; id = 1; name = "SVT1"; scrape_url = "https://tv-tabla.se/tabla/svt1/"; stream_url = ""; }; 10 = { cmd = ""; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/10.png"; id = 10; name = "Kanal 10"; scrape_url = "https://tv-tabla.se/tabla/tv10/"; stream_url = ""; }; 11 = { cmd = ""; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/11.png"; id = 11; name = "Kanal 11"; scrape_url = "https://tv-tabla.se/tabla/tv11/"; stream_url = ""; }; 12 = { cmd = ""; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/12.png"; id = 12; name = "Kanal 12"; scrape_url = "https://tv-tabla.se/tabla/tv12/"; stream_url = ""; }; 13 = { cmd = "open_tv4 && nav_select && nav_left && nav_down && nav_doown && nav_down && nav_select && wait 3 && nav_down && nav_down && nav_down && nav_down && nav_down && nav_select"; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/13.png"; id = 13; name = "TV4 Hockey"; scrape_url = "https://tv-tabla.se/tabla/tv4_hockey/"; stream_url = ""; }; 14 = { cmd = "open_tv4 && nav_left && nav_down && nav_down && nav_down && nav_select && wait 3 && nav_down && nav_down && nav_down && nav_down && nav_down && nav_right && nav_right && nav_select"; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/14.png"; id = 14; name = "TV4 Sport Live 1"; scrape_url = "https://tv-tabla.se/tabla/tv4_sport_live_1/"; stream_url = ""; }; 15 = { cmd = "open_tv4 && nav_select && nav_left && nav_down && nav_down && nav_down && nav_select && wait 3 && nav_down && nav_down && nav_down && nav_down && nav_down && nav_down && nav_select"; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/15.png"; id = 15; name = "TV4 Sport Live 2"; scrape_url = "https://tv-tabla.se/tabla/tv4_sport_live_2/"; stream_url = ""; }; 16 = { cmd = "open_tv4 && nav_down && nav_right && nav_right && nav_center"; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/16.png"; id = 16; name = "TV4 Sport Live 3"; scrape_url = "https://tv-tabla.se/tabla/tv4_sport_live_3/"; stream_url = ""; }; 17 = { cmd = "open_tv4 && nav_left && nav_down && nav_down && nav_down && nav_select && wait 3 && nav_down && nav_down && nav_down && nav_down && nav_down && nav_down && nav_right && nav_right && nav_select"; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/17.png"; id = 17; name = "TV4 Sport Live 4"; scrape_url = "https://tv-tabla.se/tabla/tv4_sport_live_4/"; stream_url = ""; }; 2 = { cmd = "open_telenor && wait 5 && start_channel_2"; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/2.png"; id = 2; name = "SVT2"; scrape_url = "https://tv-tabla.se/tabla/svt2/"; stream_url = ""; }; 3 = { cmd = "open_telenor && wait 5 && start_channel_3"; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/3.png"; id = 3; name = "Kanal 3"; scrape_url = "https://tv-tabla.se/tabla/tv3/"; stream_url = ""; }; 4 = { cmd = "open_telenor && wait 5 && start_channel_4"; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/4.png"; id = 4; name = "TV4"; scrape_url = "https://tv-tabla.se/tabla/tv4/"; stream_url = ""; }; 5 = { cmd = "open_telenor && wait 5 && start_channel_5"; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/5.png"; id = 5; name = "Kanal 5"; scrape_url = "https://tv-tabla.se/tabla/kanal_5/"; stream_url = ""; }; 6 = { cmd = "open_telenor && wait 5 && start_channel_6"; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/6.png"; id = 6; name = "Kanal 6"; scrape_url = "https://tv-tabla.se/tabla/tv6/"; stream_url = ""; }; 7 = { cmd = "open_telenor && wait 5 && start_channel_7"; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/7.png"; id = 7; name = "Sjuan"; scrape_url = "https://tv-tabla.se/tabla/sjuan/"; stream_url = ""; }; 8 = { cmd = ""; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/8.png"; id = 8; name = "TV8"; scrape_url = "https://tv-tabla.se/tabla/tv8/"; stream_url = ""; }; 9 = { cmd = ""; icon = "/nix/store/n9khvzrxxzhn2mk65ivckxq1pxhashvn-source/modules/themes/icons/tv/9.png"; id = 9; name = "Kanal 9"; scrape_url = "https://tv-tabla.se/tabla/kanal_9/"; stream_url = ""; }; }; enable = true; ip = "192.168.1.223"; room = "livingroom"; }; } ```And you'll get a dashboard for your devices generated and found at http://localhost:13337




The dashboard currently gives you:
- Advanced zigbee device control
- Remote for your Android TV devices
- Set scenes
- Access to
yo do
through both an text input field aswell as microphone - and more...
I like my flakes tiny & ny modules dynamically loaded,
# dotfiles/flake.nix ⮞ https://github.com/quackhack-mcblindy/dotfiles
{
description = "❄️🦆 ⮞ QuackHack-McBLindy's big dot of flakyfiles with extra quackz.";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
sops-nix.url = "github:Mic92/sops-nix";
sops-nix.inputs.nixpkgs.follows = "nixpkgs";
caddy-duckdns.url = "github:QuackHack-McBlindy/nix-caddy-duckdns";
installer.url = "github:QuackHack-McBlindy/auto-installer-nixos";
};
outputs = inputs @ { self, systems, nixpkgs, ... }:
let
lib = import ./lib {
inherit self inputs;
lib = nixpkgs.lib;
};
in lib.makeFlake {
systems = [ "x86_64-linux" "aarch64-linux" ];
overlays = lib.mapOverlays ./overlays { inherit lib; };
hosts = lib.mapHosts ./hosts;
specialArgs = { pkgs = system: nixpkgs.legacyPackages.${system}; };
packages = lib.mapModules ./packages import;
devShells = lib.mapModules ./devShells (path: import path);
};} # 🦆 duck say ⮞ flakes all set, with no debating — next nix file awaiting, ducks be there waitin'
View Flake Outputs
git+file:///home/pungkula/dotfiles
├───devShells
│ ├───aarch64-linux
│ │ ├───android omitted (use '--all-systems' to show)
│ │ ├───esphome omitted (use '--all-systems' to show)
│ │ ├───go omitted (use '--all-systems' to show)
│ │ ├───java omitted (use '--all-systems' to show)
│ │ ├───node omitted (use '--all-systems' to show)
│ │ ├───python312 omitted (use '--all-systems' to show)
│ │ ├───python38 omitted (use '--all-systems' to show)
│ │ └───rust omitted (use '--all-systems' to show)
│ └───x86_64-linux
│ ├───android: development environment 'nix-shell'
│ ├───esphome: development environment 'nix-shell'
│ ├───go: development environment 'nix-shell'
│ ├───java: development environment 'nix-shell'
│ ├───node: development environment 'nix-shell'
│ ├───python312: development environment 'nix-shell'
│ ├───python38: development environment 'nix-shell'
│ └───rust: development environment 'nix-shell'
├───nixosConfigurations
│ ├───desktop: NixOS configuration
│ ├───homie: NixOS configuration
│ ├───laptop: NixOS configuration
│ └───nasty: NixOS configuration
├───overlays
│ └───noisereduce: Nixpkgs overlay
└───packages
├───aarch64-linux
│ ├───health omitted (use '--all-systems' to show)
│ ├───installer omitted (use '--all-systems' to show)
│ ├───jellyfin omitted (use '--all-systems' to show)
│ ├───say omitted (use '--all-systems' to show)
│ ├───tv omitted (use '--all-systems' to show)
│ └───yo-bitch omitted (use '--all-systems' to show)
└───x86_64-linux
├───health: package 'health'
├───installer: package 'nixos-auto-installer-24.05.20240406.ff0dbd9-x86_64-linux.iso'
├───jellyfin: package 'jellyfin'
├───say: package 'say'
├───tv: package 'tv'
└───yo-bitch: package 'yo-bitch'
Build automated, offline USB NixOS installer
$ sudo bash usb-installer \
--user "pungkula" \
--host "laptop" \
--ssid "IfYouDontHaveEthernet" \
--wifipass "CanBeOmitted" \
--publickey "ssh-ed25519 AAAAC3FoRSsHCoNnEcTiOn..."
# dd result to flash drive (replace sdX)
$ sudo dd if="$(readlink -f ./result/iso/*.iso)" of=/dev/sdX bs=4M status=progress oflag=sync
Plug in flash drive into laptop and boot. Let it work and wait until it powers down.
Remove flash drive, boot it up again and deploy configuration from your main machine:
# 🦆🔓 First deploy? Get your Yubikey: PIN+Touch unlocks host specific AGE key for sops-nix
$ yo deploy laptop
Any builds after first deployment will use local cached binaries for enhanced build time.
The yo
CLI is a framework designed to execute scripts defined in the ./bin
directory.
It provides a unified interface for script execution, centralizes all help commands, and automatically updates the documentation.
Usage: yo <command> [arguments]
The yo CLI supports flexible parameter parsing through two primary mechanisms:
# Named Parameters
$ yo deploy --host laptop --flake /home/pungkula/dotfiles
# Positional Parameters
$ yo deploy laptop /home/pungkula/dotfiles
# Scripts can also be executed with natural language text by typing:
$ yo do "is laptop overheating"
# Natural language voice commands are also supported, say:
"yo bitch reboot the laptop"
# If the server is not running, it can be manually started with:
$ yo transcription
$ yo wake
# Get list of all defined sentences for voice commands:
$ yo do --help
Set default values for your parameters to have them marked [optional]
Command Syntax | Aliases | Description | VoiceReady |
---|---|---|---|
🖥️ System Management | |||
yo deploy --host [--flake] [--user] [--repo] [--port] [--!] | Build and deploy a NixOS configuration to a remote host. Bootstraps, builds locally, activates remotely, and auto-tags the generation. | 📛 | |
yo dev [--devShell] | Start development enviorment | 📛 | |
yo duckTrace [--file] | log | View duckTrace logs quick and quack, unified logging system | 📛 |
yo esp [--device] [--serialPort] [--ota] [--otaPort] [--OTAPwFile] [--wifiSSID] [--wifiPwFile] [--mqttHost] [--mqttUser] [--mqttPwFile] [--transcriptionHostIP] | Declarative firmware deployment tool for ESP32 boards with built-in version control. | 📛 | |
yo reboot [--host] | restart | Force reboot and wait for host | 📛 |
yo rollback --host [--flake] [--user] | Rollback a host to a previous NixOS generation. Fetches Git tags and reverts system+config to a synced, tagged state. | 📛 | |
yo switch [--flake] [--!] | rb | Rebuild and switch Nix OS system configuration | 📛 |
⚙️ Configuration | |||
yo do --input [--fuzzyThreshold] | d | Natural language to Shell script translator with dynamic regex matching and automatic parameter resolutiion | 📛 |
yo espaudio | 📛 | ||
yo mic [--port] [--host] [--seconds] | Trigger microphone recording sent to transcription. | 📛 | |
yo say --text [--model] [--modelDir] [--silence] [--host] [--blocking] [--file] [--caf] | Text to speech with built in language detection and automatic model downloading | 📛 | |
yo tests [--input] | Extensive automated sentence testing for the NLP | 📛 | |
yo train --phrase | Trains the NLP module. Correct misclassified commands and update NLP patterns | 📛 | |
yo transcribe [--port] [--model] [--language] [--beamSize] [--gpu] [--cert] [--key] | Transcription server-side service. Sit and waits for audio that get transcribed and returned. | 📛 | |
yo wake [--threshold] [--cooldown] [--sound] [--remoteSound] [--redisHost] [--redis_pwFIle] | Run Wake word detection for audio recording and transcription | 📛 | |
⚡ Productivity | |||
yo calculator --expression | calc | Calculate math expressions | ✅ |
yo calendar --operation [--calenders] | kal | Calendar assistant | ✅ |
yo clip2phone --copy | Send clipboard to an iPhone, for quick copy paste | 📛 | |
yo fzf | f | Interactive fzf search for file content with quick edit & jump to line | 📛 |
yo google --search [--apiKeyFile] [--searchIDFile] | g | Perform web search on google | ✅ |
yo img2phone --image | Send images to an iPhone | 📛 | |
yo pull [--flake] | pl | Pull the latest changes from your dotfiles repo. Safely resets local state and syncs with origin/main cleanly. | 📛 |
yo push [--flake] [--repo] [--host] [--generation] | ps | Commit, tag, and push dotfiles and system state to GitHub. Tags based on host + generation, auto-updates README, and preserves history. | 📛 |
yo scp --host [--path] [--username] [--downloadPath] | Move files between hosts interactively | 📛 | |
🌍 Localization | |||
yo stores --store_name [--location] [--radius] | store, shop | Finds nearby stores using OpenStreetMap data with fuzzy name matching. Returns results with opening hours. | ✅ |
yo travel [--arrival] [--departure] [--type] [--apikeyPath] | Public transportation helper. Fetches current bus and train schedules. (Sweden) | ✅ | |
yo weather [--location] [--day] [--condition] [--locationPath] | weat | Weather Assistant. Ask anything weather related (3 day forecast) | ✅ |
🌐 Networking | |||
yo block --url [--blocklist] | ad | Block URLs using DNS | 📛 |
yo ip-updater [--token1] [--token2] [--token3] | DDNS updater | 📛 | |
yo notify [--text] [--title] [--icon] [--url] [--group] [--sound] [--volume] [--copy] [--autoCopy] [--level] [--encrypt] [--base_urlFile] [--deviceKeyFile] | Send custom push to iOS devices | 📛 | |
yo notify-me [--address] [--port] [--dataDir] | Notification server for iOS devices | 📛 | |
yo shareWiFi [--ssidFile] [--passwordFile] | creates a QR code of guest WiFi and push image to iPhone | ✅ | |
yo speed | st | Test internet download speed | 📛 |
🎧 Media Management | |||
yo news [--apis] [--clean] [--playedFile] | API caller and playlist manager for latest Swedish news | ✅ | |
yo transcode [--directory] | trans | Transcode media files | 📛 |
yo tv [--typ] [--search] [--device] [--shuffle] [--tvshowsDir] [--moviesDir] [--musicDir] [--musicvideoDir] [--videosDir] [--podcastDir] [--audiobookDir] [--youtubeAPIkeyFile] [--webserver] [--defaultPlaylist] [--favoritesPlaylist] [--max_items] [--mqttUser] [--mqttPWFile] | remote | Android TV Controller. Fuzzy search all media types and creates playlist and serves over webserver for casting. Fully conttrollable. | ✅ |
yo tv-guide [--search] [--channel] [--jsonFilePath] | tvg | TV-guide assistant.. | ✅ |
yo tv-scraper [--epgFilePath] [--jsonFilePath] [--flake] | tvs | Scrapes web for tv-listing data. Builds EPG and generates HTML. | 📛 |
🔐 Security & Encryption | |||
yo sops --input [--operation] [--value] [--output] [--agePub] | e | Encrypts a file with sops-nix | 📛 |
yo yubi --operation --input | yk | Encrypts and decrypts files using a Yubikey and AGE | 📛 |
🛖 Home Automation | |||
yo alarm [--hours] [--minutes] [--sound] | wakeup | Set an alarm for a specified time | ✅ |
yo bed [--part] [--state] | Bed controller | ✅ | |
yo blinds [--state] | Turn blinds up/down | ✅ | |
yo chair [--part] [--state] | Chair controller | ✅ | |
yo darkTime [--location] [--locationPath] [--offset] | Configures darkTime - the window of time where motion is triggering lights based upon sunrise/sunset. | 📛 | |
yo duckDash [--host] [--port] [--cert] [--key] | dash | Mobile-first dashboard, unified frontend for zigbee devices, tv remotes and other smart home gadgets. | 📛 |
yo findPhone | Helper for locating Phone | ✅ | |
yo house [--device] [--state] [--brightness] [--color] [--temperature] [--scene] [--user] [--passwordfile] [--flake] | Control lights and other home automatioon devices | ✅ | |
yo kitchenFan [--state] | Turns kitchen fan on/off | ✅ | |
yo leaving | Run when leaving house to set away state | 📛 | |
yo returned | Run when returned home to set home state | 📛 | |
yo temperatures | Get all temperature values from sensors and return a average value. | ✅ | |
yo tibber [--mode] [--homeIDFile] [--APIKeyFile] [--filePath] [--user] [--pwfile] | el | Fetches home electricity price data | ✅ |
yo timer [--minutes] [--seconds] [--hours] [--sound] | Set a timer | ✅ | |
yo toilet | Flush the toilet | ✅ | |
yo zigduck [--user] [--pwfile] | zigb, hem | Home Automations at its best! Bash & Nix cool as dat. Runs on single process | 📛 |
🧩 Miscellaneous | |||
yo invokeai --prompt [--host] [--port] [--outputDir] [--width] [--height] [--steps] [--cfgScale] [--seed] [--model] | genimg | AI generated images powered by InvokeAI | ✅ |
yo joke [--jokeFile] | Tells a quacktastic joke | ✅ | |
yo post [--postalCodeFile] [--postalCode] | Check for the next postal delivery day. (Sweden) | ✅ | |
yo qr --input [--icon] [--output] | Create fun randomized QR codes from input. | 📛 | |
yo reminder [--about] [--list] | remind | Reminder Assistant | ✅ |
yo shop-list [--operation] [--item] | Shopping list management | ✅ | |
yo suno --prompt [--genre] | mg | AI generated lyrics and music files powered by Suno | ✅ |
yo time | Tells time, day and date | ✅ | |
🧹 Maintenance | |||
yo clean | gc | Run a total garbage collection: Removes old NixOS generations, empty trash, flush tmp files, whipes cache and runs a docker prune | 📛 |
yo health [--host] | hc | Check system health status across your machines | ✅ |
For specific command help:
yo <command> --help
yo <command> -h
Nix Talk? Or just say tiny flake sucks?
That's cool!
I am all ears. 👀
Note
Im not blind.
I just can't see. 🧑🦯