Massive nixfmt reformatting

This commit is contained in:
Natsu Kagami 2025-04-03 13:59:50 +02:00
parent fe4492f004
commit b29ddd5e65
Signed by: nki
GPG key ID: 55A032EB38B49ADB
109 changed files with 4323 additions and 2368 deletions

View file

@ -1,4 +1,3 @@
# WARN: this file will get overwritten by $ cachix use <name> # WARN: this file will get overwritten by $ cachix use <name>
{ pkgs, lib, ... }: { pkgs, lib, ... }:
@ -7,7 +6,8 @@ let
toImport = name: value: folder + ("/" + name); toImport = name: value: folder + ("/" + name);
filterCaches = key: value: value == "regular" && lib.hasSuffix ".nix" key; filterCaches = key: value: value == "regular" && lib.hasSuffix ".nix" key;
imports = lib.mapAttrsToList toImport (lib.filterAttrs filterCaches (builtins.readDir folder)); imports = lib.mapAttrsToList toImport (lib.filterAttrs filterCaches (builtins.readDir folder));
in { in
{
inherit imports; inherit imports;
nix.settings.substituters = ["https://cache.nixos.org/"]; nix.settings.substituters = [ "https://cache.nixos.org/" ];
} }

View file

@ -1,4 +1,3 @@
{ {
nix = { nix = {
settings = { settings = {

View file

@ -1,16 +1,33 @@
let let
# Default shell # Default shell
defaultShell = { lib, pkgs, config, ... }: with lib; { defaultShell =
environment.shells = with pkgs; [ bash fish ]; {
users.users = mkMerge [ lib,
{ nki.shell = pkgs.bash; } pkgs,
# (mkIf (builtins.hasAttr "natsukagami" config.users.users) { natsukagami.shell = pkgs.fish; }) config,
]; ...
}; }:
with lib;
{
environment.shells = with pkgs; [
bash
fish
];
users.users = mkMerge [
{ nki.shell = pkgs.bash; }
# (mkIf (builtins.hasAttr "natsukagami" config.users.users) { natsukagami.shell = pkgs.fish; })
];
};
in in
# Common stuff # Common stuff
{ lib, pkgs, config, ... }: {
with lib; { lib,
pkgs,
config,
...
}:
with lib;
{
imports = [ imports = [
# defaultShell # defaultShell
./modules/services/nix-cache ./modules/services/nix-cache

View file

@ -1,11 +1,14 @@
{ pkgs, config, lib, ... }: {
pkgs,
config,
lib,
...
}:
with lib; with lib;
{ {
homebrew.enable = true; homebrew.enable = true;
homebrew.brewPrefix = homebrew.brewPrefix = if pkgs.stdenv.isAarch64 then "/opt/homebrew/bin" else "/usr/local/bin";
if pkgs.stdenv.isAarch64 then "/opt/homebrew/bin"
else "/usr/local/bin";
homebrew.onActivation.cleanup = "zap"; homebrew.onActivation.cleanup = "zap";
homebrew.onActivation.upgrade = true; homebrew.onActivation.upgrade = true;

View file

@ -1,4 +1,9 @@
{ config, pkgs, lib, ... }: {
config,
pkgs,
lib,
...
}:
{ {
imports = [ imports = [
@ -7,8 +12,10 @@
]; ];
# List packages installed in system profile. To search by name, run: # List packages installed in system profile. To search by name, run:
# $ nix-env -qaP | grep wget # $ nix-env -qaP | grep wget
environment.systemPackages = environment.systemPackages = with pkgs; [
with pkgs; [ podman qemu ]; podman
qemu
];
environment.shells = with pkgs; [ fish ]; environment.shells = with pkgs; [ fish ];

199
flake.nix
View file

@ -61,86 +61,120 @@
secrets.url = "git+ssh://git@github.com/natsukagami/nix-deploy-secrets"; secrets.url = "git+ssh://git@github.com/natsukagami/nix-deploy-secrets";
}; };
outputs = { self, darwin, nixpkgs, nixpkgs-unstable, home-manager, deploy-rs, sops-nix, ... }@inputs: outputs =
{
self,
darwin,
nixpkgs,
nixpkgs-unstable,
home-manager,
deploy-rs,
sops-nix,
...
}@inputs:
let let
overlays = import ./overlay.nix inputs; overlays = import ./overlay.nix inputs;
lib = nixpkgs.lib; lib = nixpkgs.lib;
applyOverlays = { ... }: { applyOverlays =
nixpkgs.overlays = lib.mkAfter overlays; { ... }:
}; {
nixpkgs.overlays = lib.mkAfter overlays;
nixpkgsAsRegistry_ = stable: { lib, ... }: {
imports = [ applyOverlays ];
nix.registry.current-system.flake = self;
nix.registry.nixpkgs-unstable.flake = nixpkgs-unstable;
nixpkgs.config.allowUnfree = true;
nix.nixPath = lib.mkDefault [
"nixpkgs-unstable=${nixpkgs-unstable}"
];
};
osuStable = { pkgs, ... }: {
nix.settings = {
substituters = [ "https://nix-gaming.cachix.org" ];
trusted-public-keys = [ "nix-gaming.cachix.org-1:nbjlureqMbRAxR1gJ/f3hxemL9svXaZF/Ees8vCUUs4=" ];
}; };
environment.systemPackages = [ inputs.nix-gaming.packages.${pkgs.hostPlatform.system}.osu-stable ];
programs.gamemode = {
enable = true;
enableRenice = true;
settings = {
general = {
renice = 10;
};
custom = { nixpkgsAsRegistry_ =
start = "${pkgs.libnotify}/bin/notify-send 'GameMode started'"; stable:
end = "${pkgs.libnotify}/bin/notify-send 'GameMode ended'"; { lib, ... }:
{
imports = [ applyOverlays ];
nix.registry.current-system.flake = self;
nix.registry.nixpkgs-unstable.flake = nixpkgs-unstable;
nixpkgs.config.allowUnfree = true;
nix.nixPath = lib.mkDefault [
"nixpkgs-unstable=${nixpkgs-unstable}"
];
};
osuStable =
{ pkgs, ... }:
{
nix.settings = {
substituters = [ "https://nix-gaming.cachix.org" ];
trusted-public-keys = [ "nix-gaming.cachix.org-1:nbjlureqMbRAxR1gJ/f3hxemL9svXaZF/Ees8vCUUs4=" ];
};
environment.systemPackages = [ inputs.nix-gaming.packages.${pkgs.hostPlatform.system}.osu-stable ];
programs.gamemode = {
enable = true;
enableRenice = true;
settings = {
general = {
renice = 10;
};
custom = {
start = "${pkgs.libnotify}/bin/notify-send 'GameMode started'";
end = "${pkgs.libnotify}/bin/notify-send 'GameMode ended'";
};
}; };
}; };
}; };
};
# Common Nix modules # Common Nix modules
common-nix = stable: { ... }: { common-nix =
imports = [ stable:
(nixpkgsAsRegistry_ stable) { ... }:
./common.nix {
sops-nix.nixosModules.sops imports = [
inputs.lix-module.nixosModules.default (nixpkgsAsRegistry_ stable)
]; ./common.nix
config.nix.settings.extra-deprecated-features = [ "url-literals" ]; # So lix won't complain sops-nix.nixosModules.sops
}; inputs.lix-module.nixosModules.default
common-nixos = stable: { ... }: { ];
imports = [ config.nix.settings.extra-deprecated-features = [ "url-literals" ]; # So lix won't complain
./modules/my-tinc };
./modules/common/linux common-nixos =
(common-nix stable) stable:
inputs.secrets.nixosModules.common { ... }:
inputs.nix-gaming.nixosModules.pipewireLowLatency {
inputs.niri.nixosModules.niri imports = [
]; ./modules/my-tinc
}; ./modules/common/linux
(common-nix stable)
inputs.secrets.nixosModules.common
inputs.nix-gaming.nixosModules.pipewireLowLatency
inputs.niri.nixosModules.niri
];
};
mkPersonalSystem = nixpkgs-module: system: { configuration mkPersonalSystem =
, homeManagerUsers ? { } nixpkgs-module: system:
, extraModules ? [ ] {
, includeCommonModules ? true configuration,
, homeManagerUsers ? { },
}: extraModules ? [ ],
includeCommonModules ? true,
}:
let let
home-manager-module = home-manager-module =
if nixpkgs-module == inputs.nixpkgs then inputs.home-manager if nixpkgs-module == inputs.nixpkgs then
else if nixpkgs-module == inputs.nixpkgs-unstable then inputs.home-manager-unstable inputs.home-manager
else builtins.abort "Unknown nixpkgs module, use `nixpkgs` or `nixpkgs-unstable`"; else if nixpkgs-module == inputs.nixpkgs-unstable then
inputs.home-manager-unstable
else
builtins.abort "Unknown nixpkgs module, use `nixpkgs` or `nixpkgs-unstable`";
in in
nixpkgs-module.lib.nixosSystem { nixpkgs-module.lib.nixosSystem {
inherit system; inherit system;
modules = modules =
(if includeCommonModules then [ (
(common-nixos nixpkgs-module) if includeCommonModules then
] else [ ]) ++ [ [
(common-nixos nixpkgs-module)
]
else
[ ]
)
++ [
configuration configuration
# Home Manager # Home Manager
home-manager-module.nixosModules.home-manager home-manager-module.nixosModules.home-manager
@ -149,7 +183,8 @@
home-manager.useUserPackages = true; home-manager.useUserPackages = true;
home-manager.users = homeManagerUsers; home-manager.users = homeManagerUsers;
} }
] ++ extraModules; ]
++ extraModules;
}; };
in in
@ -186,14 +221,17 @@
homeManagerUsers.nki = import ./home/nki-x1c1.nix; homeManagerUsers.nki = import ./home/nki-x1c1.nix;
extraModules = [ extraModules = [
inputs.lanzaboote.nixosModules.lanzaboote inputs.lanzaboote.nixosModules.lanzaboote
({ ... }: { (
# Sets up secure boot { ... }:
boot.loader.systemd-boot.enable = lib.mkForce false; {
boot.lanzaboote = { # Sets up secure boot
enable = true; boot.loader.systemd-boot.enable = lib.mkForce false;
pkiBundle = "/etc/secureboot"; boot.lanzaboote = {
}; enable = true;
}) pkiBundle = "/etc/secureboot";
};
}
)
]; ];
}; };
# framework configuration # framework configuration
@ -203,14 +241,17 @@
extraModules = [ extraModules = [
inputs.lanzaboote.nixosModules.lanzaboote inputs.lanzaboote.nixosModules.lanzaboote
inputs.nixos-hardware.nixosModules.framework-13-7040-amd inputs.nixos-hardware.nixosModules.framework-13-7040-amd
({ ... }: { (
# Sets up secure boot { ... }:
boot.loader.systemd-boot.enable = lib.mkForce false; {
boot.lanzaboote = { # Sets up secure boot
enable = true; boot.loader.systemd-boot.enable = lib.mkForce false;
pkiBundle = "/etc/secureboot"; boot.lanzaboote = {
}; enable = true;
}) pkiBundle = "/etc/secureboot";
};
}
)
]; ];
}; };
# macbook nixos # macbook nixos

View file

@ -1,24 +1,34 @@
{ pkgs, config, lib, ... }: {
pkgs,
config,
lib,
...
}:
with lib; with lib;
let let
kwallet = { pkgs, lib, ... }: { kwallet =
home.packages = with pkgs; [ kdePackages.kwallet kdePackages.ksshaskpass ]; { pkgs, lib, ... }:
home.sessionVariables = { {
# https://wiki.archlinux.org/title/KDE_Wallet#Using_the_KDE_Wallet_to_store_ssh_key_passphrases home.packages = with pkgs; [
SSH_ASKPASS = lib.getExe pkgs.kdePackages.ksshaskpass; kdePackages.kwallet
SSH_ASKPASS_REQUIRE = "prefer"; kdePackages.ksshaskpass
];
home.sessionVariables = {
# https://wiki.archlinux.org/title/KDE_Wallet#Using_the_KDE_Wallet_to_store_ssh_key_passphrases
SSH_ASKPASS = lib.getExe pkgs.kdePackages.ksshaskpass;
SSH_ASKPASS_REQUIRE = "prefer";
};
# Enable this for sway
wayland.windowManager.sway.config.startup = [
{ command = "${pkgs.kdePackages.kwallet-pam}/libexec/pam_kwallet_init"; }
];
# Automatic dbus activation
xdg.dataFile."dbus-1/services/org.freedesktop.secrets.service".text = ''
[D-BUS Service]
Name=org.freedesktop.secrets
Exec=${pkgs.kdePackages.kwallet}/bin/kwalletd6
'';
}; };
# Enable this for sway
wayland.windowManager.sway.config.startup = [
{ command = "${pkgs.kdePackages.kwallet-pam}/libexec/pam_kwallet_init"; }
];
# Automatic dbus activation
xdg.dataFile."dbus-1/services/org.freedesktop.secrets.service".text = ''
[D-BUS Service]
Name=org.freedesktop.secrets
Exec=${pkgs.kdePackages.kwallet}/bin/kwalletd6
'';
};
in in
{ {
imports = [ imports = [
@ -27,33 +37,34 @@ in
./modules/X11/xfce4-notifyd.nix ./modules/X11/xfce4-notifyd.nix
kwallet kwallet
]; ];
config = (mkIf pkgs.stdenv.isLinux { config = (
home.packages = with pkgs; [ mkIf pkgs.stdenv.isLinux {
psmisc # killall and friends home.packages = with pkgs; [
file # Query file type psmisc # killall and friends
zip file # Query file type
python3 zip
python3
pinentry-gnome3 # until pinentry-qt introduces caching pinentry-gnome3 # until pinentry-qt introduces caching
]; ];
systemd.user.startServices = "sd-switch"; systemd.user.startServices = "sd-switch";
# Audio stuff! # Audio stuff!
# services.easyeffects.enable = true; # services.easyeffects.enable = true;
# Bluetooth controls # Bluetooth controls
# services.mpris-proxy.enable = true; # services.mpris-proxy.enable = true;
# Owncloud # Owncloud
services.owncloud-client.enable = true; services.owncloud-client.enable = true;
services.owncloud-client.package = pkgs.owncloud-client.overrideAttrs (attrs: { services.owncloud-client.package = pkgs.owncloud-client.overrideAttrs (attrs: {
buildInputs = attrs.buildInputs ++ [ pkgs.qt6.qtwayland ]; buildInputs = attrs.buildInputs ++ [ pkgs.qt6.qtwayland ];
}); });
systemd.user.services.owncloud-client.Unit.After = [ "graphical-session.target" ]; systemd.user.services.owncloud-client.Unit.After = [ "graphical-session.target" ];
# UDisks automounter # UDisks automounter
services.udiskie.enable = true; services.udiskie.enable = true;
}); }
);
} }

View file

@ -1,4 +1,9 @@
{ config, pkgs, lib, ... }: {
config,
pkgs,
lib,
...
}:
{ {
imports = [ imports = [
@ -52,7 +57,6 @@
$pdf_previewer = '${lib.getExe' pkgs.xdg-utils "xdg-open"}'; $pdf_previewer = '${lib.getExe' pkgs.xdg-utils "xdg-open"}';
''; '';
home.sessionVariables = { home.sessionVariables = {
# Bat theme # Bat theme
BAT_THEME = "GitHub"; BAT_THEME = "GitHub";

View file

@ -1,4 +1,10 @@
{ config, options, pkgs, lib, ... }: {
config,
options,
pkgs,
lib,
...
}:
with lib; with lib;
let let
@ -157,7 +163,6 @@ in
}; };
}; };
tide = { tide = {
enable = true; enable = true;
leftItems = options.programs.fish.tide.leftItems.default; leftItems = options.programs.fish.tide.leftItems.default;
@ -172,10 +177,7 @@ in
}; };
everywhereAbbrs = { everywhereAbbrs = {
lsports = lsports = if pkgs.stdenv.isDarwin then "lsof -i -P | grep LISTEN" else "ss -tulp";
if pkgs.stdenv.isDarwin
then "lsof -i -P | grep LISTEN"
else "ss -tulp";
}; };
shellInit = '' shellInit = ''
@ -234,11 +236,11 @@ in
bind -M default gl end-of-line bind -M default gl end-of-line
# Everywhere abbrs # Everywhere abbrs
${ ${concatStringsSep "\n" (
concatStringsSep "\n" mapAttrsToList (
(mapAttrsToList (k: v: "abbr --add --position anywhere -- ${k} ${escapeShellArg v}") k: v: "abbr --add --position anywhere -- ${k} ${escapeShellArg v}"
config.programs.fish.everywhereAbbrs) ) config.programs.fish.everywhereAbbrs
} )}
# Replace today with actual today # Replace today with actual today
abbr --add --position anywhere today -f echo-today abbr --add --position anywhere today -f echo-today

View file

@ -1,4 +1,9 @@
{ config, pkgs, lib, ... }: {
config,
pkgs,
lib,
...
}:
with lib; with lib;
let let
@ -42,25 +47,38 @@ in
leftItems = mkOption { leftItems = mkOption {
type = types.listOf types.str; type = types.listOf types.str;
description = "The list of left-items. Note that `newline` and `character` is not included here and will always appear last"; description = "The list of left-items. Note that `newline` and `character` is not included here and will always appear last";
default = [ "os" "context" "pwd" "git" ]; default = [
"os"
"context"
"pwd"
"git"
];
}; };
}; };
config.programs.fish = config.programs.fish =
let let
tideItems = attrsets.mapAttrs' (name: def: { name = "_tide_item_${name}"; value = def; }); tideItems = attrsets.mapAttrs' (
name: def: {
name = "_tide_item_${name}";
value = def;
}
);
in in
mkIf cfg.enable { mkIf cfg.enable {
functions = tideItems ({ functions = tideItems (
nix_shell = '' {
# In a Nix Shell nix_shell = ''
if set -qx DIRENV_FILE && test -f $DIRENV_FILE && rg -q "^use flake" $DIRENV_FILE # In a Nix Shell
set -U tide_nix_shell_color "FFA500" if set -qx DIRENV_FILE && test -f $DIRENV_FILE && rg -q "^use flake" $DIRENV_FILE
set -U tide_nix_shell_bg_color normal set -U tide_nix_shell_color "FFA500"
_tide_print_item nix_shell "" set -U tide_nix_shell_bg_color normal
end _tide_print_item nix_shell ""
''; end
} // cfg.items); '';
}
// cfg.items
);
plugins = [ plugins = [
{ {
name = "tide"; name = "tide";
@ -78,7 +96,9 @@ in
config.xdg.configFile."fish/tide/init.fish" = { config.xdg.configFile."fish/tide/init.fish" = {
text = '' text = ''
# Configure tide items # Configure tide items
set -U tide_left_prompt_items ${concatMapStringsSep " " escapeShellArg cfg.leftItems} newline character set -U tide_left_prompt_items ${
concatMapStringsSep " " escapeShellArg cfg.leftItems
} newline character
set -U tide_right_prompt_items ${concatMapStringsSep " " escapeShellArg cfg.rightItems} time set -U tide_right_prompt_items ${concatMapStringsSep " " escapeShellArg cfg.rightItems} time
''; '';

View file

@ -1,4 +1,9 @@
{ pkgs, config, lib, ... }: {
pkgs,
config,
lib,
...
}:
{ {
imports = [ imports = [
@ -14,19 +19,22 @@
home.homeDirectory = "/home/nki"; home.homeDirectory = "/home/nki";
# More packages # More packages
home.packages = (with pkgs; [ home.packages = (
# Gaming stuff with pkgs;
wineWowPackages.full [
# wine-lol # Gaming stuff
winetricks wineWowPackages.full
lutris # wine-lol
steam winetricks
lutris
steam
# Manage tlmc # Manage tlmc
flacon flacon
ttaenc ttaenc
picard picard
]); ]
);
# Enable X11 configuration # Enable X11 configuration
linux.graphical.type = "wayland"; linux.graphical.type = "wayland";
@ -46,12 +54,24 @@
# 144hz adaptive refresh ON! # 144hz adaptive refresh ON!
nki.programs.kitty.enable = true; nki.programs.kitty.enable = true;
nki.programs.kitty.fontSize = 14; nki.programs.kitty.fontSize = 14;
programs.my-waybar.makeBars = with config.common.monitors; barWith: [ programs.my-waybar.makeBars =
# For primary with config.common.monitors;
(barWith { extraSettings = { output = [ home_4k.meta.connection ]; }; }) barWith: [
# For secondary, hide mpd # For primary
(barWith { showMedia = false; showConnectivity = false; extraSettings = { output = [ home_1440.meta.connection ]; }; }) (barWith {
]; extraSettings = {
output = [ home_4k.meta.connection ];
};
})
# For secondary, hide mpd
(barWith {
showMedia = false;
showConnectivity = false;
extraSettings = {
output = [ home_1440.meta.connection ];
};
})
];
# Yellow light! # Yellow light!
services.wlsunset = { services.wlsunset = {
@ -72,10 +92,28 @@
# ncmpcpp # ncmpcpp
programs.ncmpcpp.enable = true; programs.ncmpcpp.enable = true;
programs.ncmpcpp.bindings = [ programs.ncmpcpp.bindings = [
{ key = "j"; command = "scroll_down"; } {
{ key = "k"; command = "scroll_up"; } key = "j";
{ key = "J"; command = [ "select_item" "scroll_down" ]; } command = "scroll_down";
{ key = "K"; command = [ "select_item" "scroll_up" ]; } }
{
key = "k";
command = "scroll_up";
}
{
key = "J";
command = [
"select_item"
"scroll_down"
];
}
{
key = "K";
command = [
"select_item"
"scroll_up"
];
}
]; ];
programs.ncmpcpp.settings = { programs.ncmpcpp.settings = {
# General # General
@ -133,4 +171,3 @@
# changes in each release. # changes in each release.
home.stateVersion = "21.05"; home.stateVersion = "21.05";
} }

View file

@ -68,7 +68,15 @@ in
in in
{ {
grammar.src = src; grammar.src = src;
grammar.compile.args = [ "-c" "-fpic" "../parser.c" "../scanner.c" "../unicode.h" "-I" ".." ]; grammar.compile.args = [
"-c"
"-fpic"
"../parser.c"
"../scanner.c"
"../unicode.h"
"-I"
".."
];
queries.src = src; queries.src = src;
queries.path = "queries"; queries.path = "queries";
}; };
@ -79,9 +87,24 @@ in
rev = "0e36bed171768908f331ff7dff9d956bae016efb"; rev = "0e36bed171768908f331ff7dff9d956bae016efb";
hash = "sha256-bpiT3FraOZhJaoiFWAoVJX1O+plnIi8aXOW2LwyU23M="; hash = "sha256-bpiT3FraOZhJaoiFWAoVJX1O+plnIi8aXOW2LwyU23M=";
}; };
grammar.compile.args = [ "-c" "-fpic" "../scanner.cc" "../parser.c" "-I" ".." ]; grammar.compile.args = [
grammar.link.args = [ "-shared" "-fpic" "scanner.o" "parser.o" ]; "-c"
grammar.link.flags = [ "-O3" "-lstdc++" ]; "-fpic"
"../scanner.cc"
"../parser.c"
"-I"
".."
];
grammar.link.args = [
"-shared"
"-fpic"
"scanner.o"
"parser.o"
];
grammar.link.flags = [
"-O3"
"-lstdc++"
];
queries.src = pkgs.fetchFromGitHub { queries.src = pkgs.fetchFromGitHub {
owner = "helix-editor"; owner = "helix-editor";
@ -115,8 +138,18 @@ in
go = { go = {
grammar.src = tree-sitter-go; grammar.src = tree-sitter-go;
grammar.compile.args = [ "-c" "-fpic" "../parser.c" "-I" ".." ]; grammar.compile.args = [
grammar.link.args = [ "-shared" "-fpic" "parser.o" ]; "-c"
"-fpic"
"../parser.c"
"-I"
".."
];
grammar.link.args = [
"-shared"
"-fpic"
"parser.o"
];
queries.src = tree-sitter-go; queries.src = tree-sitter-go;
queries.path = "queries"; queries.path = "queries";
}; };
@ -132,11 +165,20 @@ in
in in
{ {
grammar.src = src; grammar.src = src;
grammar.compile.args = [ "-c" "-fpic" "../parser.c" "-I" ".." ]; grammar.compile.args = [
grammar.link.args = [ "-shared" "-fpic" "parser.o" ]; "-c"
"-fpic"
"../parser.c"
"-I"
".."
];
grammar.link.args = [
"-shared"
"-fpic"
"parser.o"
];
queries.src = src; queries.src = src;
queries.path = "queries"; queries.path = "queries";
}; };
}; };
} }

View file

@ -1,4 +1,9 @@
{ config, pkgs, lib, ... }: {
config,
pkgs,
lib,
...
}:
{ {
imports = [ ./common.nix ]; imports = [ ./common.nix ];

View file

@ -1,4 +1,9 @@
{ pkgs, config, lib, ... }: {
pkgs,
config,
lib,
...
}:
let let
discord = pkgs.armcord.override { nss = pkgs.nss_latest; }; discord = pkgs.armcord.override { nss = pkgs.nss_latest; };
@ -30,15 +35,18 @@ in
''; '';
# More packages # More packages
home.packages = (with pkgs; [ home.packages = (
mate.mate-terminal with pkgs;
[
mate.mate-terminal
firefox-wayland firefox-wayland
discord discord
typora typora
]); ]
);
# Graphical set up # Graphical set up
linux.graphical.type = "wayland"; linux.graphical.type = "wayland";
@ -125,4 +133,3 @@ in
# changes in each release. # changes in each release.
home.stateVersion = "21.05"; home.stateVersion = "21.05";
} }

View file

@ -1,4 +1,9 @@
{ pkgs, config, lib, ... }: {
pkgs,
config,
lib,
...
}:
with lib; with lib;
let let

View file

@ -1,4 +1,9 @@
{ pkgs, config, lib, ... }: {
pkgs,
config,
lib,
...
}:
with lib; with lib;
let let
@ -28,7 +33,10 @@ in
}; };
shell = { shell = {
program = "/bin/sh"; program = "/bin/sh";
args = [ "-ic" "${config.programs.fish.package}/bin/fish" ]; args = [
"-ic"
"${config.programs.fish.package}/bin/fish"
];
}; };
colors = { colors = {
# Default colors # Default colors
@ -57,7 +65,11 @@ in
}; };
key_bindings = [ key_bindings = [
{ key = "C"; mods = "Alt|Control"; action = "SpawnNewInstance"; } {
key = "C";
mods = "Alt|Control";
action = "SpawnNewInstance";
}
]; ];
}; };
}; };

View file

@ -1,4 +1,9 @@
{ pkgs, lib, config, ... }: {
pkgs,
lib,
config,
...
}:
with lib; with lib;
let let
cfg = config.linux.graphical; cfg = config.linux.graphical;
@ -17,34 +22,56 @@ let
end end
''; '';
mkPackageWithDesktopOption = opts: mkOption ({ mkPackageWithDesktopOption =
type = types.submodule { opts:
options = { mkOption (
package = mkOption { {
type = types.package; type = types.submodule {
description = "The package for " + description; options = {
package = mkOption {
type = types.package;
description = "The package for " + description;
};
desktopFile = mkOption {
type = types.nullOr types.str;
default = null;
description = "The desktop file name for " + description + ", defaults to [packagename].desktop";
};
};
}; };
desktopFile = mkOption { }
type = types.nullOr types.str; // opts
default = null; );
description = "The desktop file name for " + description + ", defaults to [packagename].desktop";
};
};
};
} // opts);
desktopFileOf = cfg: if cfg.desktopFile == null then "${cfg.package}/share/applications/${cfg.package.pname}.desktop" else cfg.desktopFile; desktopFileOf =
cfg:
if cfg.desktopFile == null then
"${cfg.package}/share/applications/${cfg.package.pname}.desktop"
else
cfg.desktopFile;
in in
{ {
imports = [ ./x11.nix ./wayland.nix ./alacritty.nix ]; imports = [
./x11.nix
./wayland.nix
./alacritty.nix
];
options.linux.graphical = { options.linux.graphical = {
type = mkOption { type = mkOption {
type = types.nullOr (types.enum [ "x11" "wayland" ]); type = types.nullOr (
types.enum [
"x11"
"wayland"
]
);
description = "Enable linux graphical configurations, with either 'x11' or 'wayland'"; description = "Enable linux graphical configurations, with either 'x11' or 'wayland'";
default = null; default = null;
}; };
wallpaper = mkOption { wallpaper = mkOption {
type = types.oneOf [ types.str types.path ]; type = types.oneOf [
types.str
types.path
];
description = "Path to the wallpaper file"; description = "Path to the wallpaper file";
default = ""; default = "";
}; };
@ -59,52 +86,61 @@ in
}; };
defaults = { defaults = {
webBrowser = mkPackageWithDesktopOption { description = "default web browser"; }; webBrowser = mkPackageWithDesktopOption { description = "default web browser"; };
terminal = mkPackageWithDesktopOption { description = "default terminal"; default.package = pkgs.kitty; }; terminal = mkPackageWithDesktopOption {
discord = mkPackageWithDesktopOption { description = "Discord client"; default.package = pkgs.vesktop; }; description = "default terminal";
default.package = pkgs.kitty;
};
discord = mkPackageWithDesktopOption {
description = "Discord client";
default.package = pkgs.vesktop;
};
}; };
}; };
config = mkIf (cfg.type != null) { config = mkIf (cfg.type != null) {
# Packages # Packages
home.packages = (with pkgs; [ home.packages = (
cfg.defaults.webBrowser.package with pkgs;
cfg.defaults.terminal.package [
cfg.defaults.webBrowser.package
cfg.defaults.terminal.package
## GUI stuff ## GUI stuff
evince # PDF reader evince # PDF reader
gparted gparted
vscode vscode
feh # For images? feh # For images?
deluge # Torrent client deluge # Torrent client
pavucontrol # PulseAudio control panel pavucontrol # PulseAudio control panel
sublime-music # For navidrome sublime-music # For navidrome
# cinny-desktop # cinny-desktop
gajim gajim
vivaldi vivaldi
# Audio # Audio
qpwgraph # Pipewire graph qpwgraph # Pipewire graph
audacity audacity
vlc vlc
unstable.zotero unstable.zotero
libreoffice libreoffice
mpv # for anki mpv # for anki
anki-bin anki-bin
# Chat stuff # Chat stuff
tdesktop tdesktop
whatsapp-for-linux whatsapp-for-linux
slack slack
zoom-us zoom-us
## CLI stuff
## CLI stuff dex # .desktop file management, startup
dex # .desktop file management, startup # sct # Display color temperature
# sct # Display color temperature xdg-utils # Open stuff
xdg-utils # Open stuff wifi-indicator
wifi-indicator ]
] ++ cfg.startup); ++ cfg.startup
);
# OBS # OBS
programs.obs-studio = { programs.obs-studio = {
@ -129,7 +165,10 @@ in
xdg.mimeApps.enable = true; xdg.mimeApps.enable = true;
xdg.mimeApps.associations.added = { xdg.mimeApps.associations.added = {
"x-scheme-handler/mailto" = [ "thunderbird.desktop" "org.gnome.Evolution.desktop" ]; "x-scheme-handler/mailto" = [
"thunderbird.desktop"
"org.gnome.Evolution.desktop"
];
"application/pdf" = [ "org.gnome.Evince.desktop" ]; "application/pdf" = [ "org.gnome.Evince.desktop" ];
"text/plain" = [ "kakoune.desktop" ]; "text/plain" = [ "kakoune.desktop" ];
@ -154,7 +193,10 @@ in
}; };
xdg.mimeApps.defaultApplications = { xdg.mimeApps.defaultApplications = {
# Email # Email
"x-scheme-handler/mailto" = [ "thunderbird.desktop" "org.gnome.Evolution.desktop" ]; "x-scheme-handler/mailto" = [
"thunderbird.desktop"
"org.gnome.Evolution.desktop"
];
"x-scheme-handler/webcal" = [ "thunderbird.desktop" ]; "x-scheme-handler/webcal" = [ "thunderbird.desktop" ];
"x-scheme-handler/webcals" = [ "thunderbird.desktop" ]; "x-scheme-handler/webcals" = [ "thunderbird.desktop" ];
@ -246,7 +288,10 @@ in
## Qt ## Qt
qt.enable = true; qt.enable = true;
qt.platformTheme.name = "kde"; qt.platformTheme.name = "kde";
qt.platformTheme.package = with pkgs.kdePackages; [ plasma-integration systemsettings ]; qt.platformTheme.package = with pkgs.kdePackages; [
plasma-integration
systemsettings
];
qt.style.package = [ pkgs.kdePackages.breeze ]; qt.style.package = [ pkgs.kdePackages.breeze ];
qt.style.name = "Breeze"; qt.style.name = "Breeze";
@ -267,7 +312,8 @@ in
}; };
autoStartup = listToAttrs (map f cfg.startup); autoStartup = listToAttrs (map f cfg.startup);
in in
autoStartup // { autoStartup
// {
## Polkit UI ## Polkit UI
"autostart/polkit.desktop".text = '' "autostart/polkit.desktop".text = ''
${builtins.readFile "${pkgs.pantheon.pantheon-agent-polkit}/etc/xdg/autostart/io.elementary.desktop.agent-polkit.desktop"} ${builtins.readFile "${pkgs.pantheon.pantheon-agent-polkit}/etc/xdg/autostart/io.elementary.desktop.agent-polkit.desktop"}
@ -304,5 +350,3 @@ in
}; };
}; };
} }

View file

@ -1,40 +1,60 @@
{ pkgs, config, lib, ... }: {
pkgs,
config,
lib,
...
}:
let let
notificationModule = { config, pkgs, lib, ... }: notificationModule =
{
config,
pkgs,
lib,
...
}:
let let
swaync = pkgs.swaynotificationcenter; swaync = pkgs.swaynotificationcenter;
in in
with lib; mkIf (config.linux.graphical.type == "wayland") { with lib;
mkIf (config.linux.graphical.type == "wayland") {
services.swaync = { services.swaync = {
enable = true; enable = true;
settings.widgets = [ "inhibitors" "title" "dnd" "mpris" "notifications" ]; settings.widgets = [
"inhibitors"
"title"
"dnd"
"mpris"
"notifications"
];
style = ./swaync.css; style = ./swaync.css;
}; };
programs.my-waybar = { programs.my-waybar = {
extraSettings = [{ extraSettings = [
modules-right = mkAfter [ "custom/swaync" ]; {
modules."custom/swaync" = { modules-right = mkAfter [ "custom/swaync" ];
tooltip = false; modules."custom/swaync" = {
format = "{icon} {}"; tooltip = false;
format-icons = { format = "{icon} {}";
notification = "<span foreground='red'><sup></sup></span>"; format-icons = {
none = ""; notification = "<span foreground='red'><sup></sup></span>";
dnd-notification = "<span foreground='red'><sup></sup></span>"; none = "";
dnd-none = ""; dnd-notification = "<span foreground='red'><sup></sup></span>";
inhibited-notification = "<span foreground='red'><sup></sup></span>"; dnd-none = "";
inhibited-none = ""; inhibited-notification = "<span foreground='red'><sup></sup></span>";
dnd-inhibited-notification = "<span foreground='red'><sup></sup></span>"; inhibited-none = "";
dnd-inhibited-none = ""; dnd-inhibited-notification = "<span foreground='red'><sup></sup></span>";
dnd-inhibited-none = "";
};
return-type = "json";
# exec-if = "which swaync-client";
exec = "${swaync}/bin/swaync-client -swb";
on-click = "${swaync}/bin/swaync-client -t -sw";
on-click-right = "${swaync}/bin/swaync-client -d -sw";
escape = true;
}; };
return-type = "json"; }
# exec-if = "which swaync-client"; ];
exec = "${swaync}/bin/swaync-client -swb";
on-click = "${swaync}/bin/swaync-client -t -sw";
on-click-right = "${swaync}/bin/swaync-client -d -sw";
escape = true;
};
}];
extraStyle = mkAfter '' extraStyle = mkAfter ''
#custom-swaync { #custom-swaync {
background: #F0FFFF; background: #F0FFFF;
@ -44,32 +64,43 @@ let
}; };
}; };
plasmaModule = { pkgs, ... }: { plasmaModule =
home.packages = with pkgs.kdePackages; [ { pkgs, ... }:
discover {
kmail home.packages = with pkgs.kdePackages; [
kontact discover
akonadi kmail
kdepim-runtime kontact
kmail-account-wizard akonadi
akonadi-import-wizard kdepim-runtime
]; kmail-account-wizard
xdg.configFile."plasma-workspace/env/wayland.sh".source = pkgs.writeScript "plasma-wayland-env.sh" '' akonadi-import-wizard
export NIXOS_OZONE_WL=1 ];
''; xdg.configFile."plasma-workspace/env/wayland.sh".source =
xdg.dataFile."dbus-1/services/org.freedesktop.Notifications.service".source = "${pkgs.kdePackages.plasma-workspace}/share/dbus-1/services/org.kde.plasma.Notifications.service"; pkgs.writeScript "plasma-wayland-env.sh" ''
}; export NIXOS_OZONE_WL=1
'';
xdg.dataFile."dbus-1/services/org.freedesktop.Notifications.service".source =
"${pkgs.kdePackages.plasma-workspace}/share/dbus-1/services/org.kde.plasma.Notifications.service";
};
rofi-rbw-script = pkgs.writeShellApplication { rofi-rbw-script = pkgs.writeShellApplication {
name = "rofi-rbw-script"; name = "rofi-rbw-script";
runtimeInputs = with pkgs; [ rofi wtype rofi-rbw ]; runtimeInputs = with pkgs; [
rofi
wtype
rofi-rbw
];
text = "rofi-rbw"; text = "rofi-rbw";
meta.mainProgram = "rofi-rbw-script"; meta.mainProgram = "rofi-rbw-script";
}; };
in in
with lib; with lib;
{ {
imports = [ notificationModule plasmaModule ]; imports = [
notificationModule
plasmaModule
];
config = mkIf (config.linux.graphical.type == "wayland") { config = mkIf (config.linux.graphical.type == "wayland") {
# Additional packages # Additional packages
home.packages = with pkgs; [ home.packages = with pkgs; [
@ -92,7 +123,12 @@ with lib;
font = "monospace"; font = "monospace";
terminal = "${lib.getExe config.programs.kitty.package}"; terminal = "${lib.getExe config.programs.kitty.package}";
theme = "Paper"; theme = "Paper";
plugins = with pkgs; [ rofi-bluetooth rofi-calc rofi-rbw rofi-power-menu ]; plugins = with pkgs; [
rofi-bluetooth
rofi-calc
rofi-rbw
rofi-power-menu
];
}; };
home.sessionVariables = { home.sessionVariables = {
@ -129,4 +165,3 @@ with lib;
# }; # };
}; };
} }

View file

@ -1,10 +1,18 @@
{ pkgs, config, lib, ... }: {
pkgs,
config,
lib,
...
}:
let let
cfg = config.linux.graphical; cfg = config.linux.graphical;
in in
with lib; with lib;
{ {
imports = [ ./x11/hidpi.nix ./x11/i3.nix ]; imports = [
./x11/hidpi.nix
./x11/i3.nix
];
options.linux.graphical.hasDE = mkOption { options.linux.graphical.hasDE = mkOption {
type = types.bool; type = types.bool;
description = "When enabled, disable stuff that already comes with a DE"; description = "When enabled, disable stuff that already comes with a DE";
@ -43,4 +51,3 @@ with lib;
}; };
}; };
} }

View file

@ -1,4 +1,9 @@
{ pkgs, config, lib, ... }: {
pkgs,
config,
lib,
...
}:
with lib; with lib;
let let

View file

@ -1,4 +1,9 @@
{ pkgs, config, lib, ... }: {
pkgs,
config,
lib,
...
}:
with lib; with lib;
let let
@ -18,12 +23,14 @@ let
"10: 10" "10: 10"
]; ];
wsAttrs = builtins.listToAttrs ( wsAttrs = builtins.listToAttrs (
map map (i: {
(i: { name = toString (remainder i 10); value = builtins.elemAt workspaces (i - 1); }) name = toString (remainder i 10);
(range 1 11) value = builtins.elemAt workspaces (i - 1);
}) (range 1 11)
); );
remainder = x: y: x - (builtins.div x y) * y; remainder = x: y: x - (builtins.div x y) * y;
range = from: to: range =
from: to:
let let
f = cur: if cur == to then [ ] else [ cur ] ++ f (cur + 1); f = cur: if cur == to then [ ] else [ cur ] ++ f (cur + 1);
in in
@ -40,27 +47,55 @@ in
xsession.windowManager.i3 = { xsession.windowManager.i3 = {
enable = true; enable = true;
config.assigns = { config.assigns = {
"${wsAttrs."1"}" = [{ class = "^firefox$"; }]; "${wsAttrs."1"}" = [ { class = "^firefox$"; } ];
"${wsAttrs."2"}" = [{ class = "^discord$"; }]; "${wsAttrs."2"}" = [ { class = "^discord$"; } ];
}; };
config.bars = [{ config.bars = [
command = "${pkgs.i3-gaps}/bin/i3bar -t"; {
statusCommand = "${pkgs.i3status-rust}/bin/i3status-rs ~/.config/i3status-rust/config-default.toml"; command = "${pkgs.i3-gaps}/bin/i3bar -t";
position = "top"; statusCommand = "${pkgs.i3status-rust}/bin/i3status-rs ~/.config/i3status-rust/config-default.toml";
colors = { position = "top";
background = "#00000080"; colors = {
statusline = "#ffffff"; background = "#00000080";
separator = "#666666"; statusline = "#ffffff";
separator = "#666666";
focusedWorkspace = { background = "#4c7899"; border = "#285577"; text = "#ffffff"; }; focusedWorkspace = {
activeWorkspace = { background = "#333333"; border = "#5f676a"; text = "#ffffff"; }; background = "#4c7899";
inactiveWorkspace = { background = "#333333"; border = "#222222"; text = "#888888"; }; border = "#285577";
urgentWorkspace = { background = "#2f343a"; border = "#900000"; text = "#ffffff"; }; text = "#ffffff";
bindingMode = { background = "#2f343a"; border = "#900000"; text = "#ffffff"; }; };
}; activeWorkspace = {
}]; background = "#333333";
border = "#5f676a";
text = "#ffffff";
};
inactiveWorkspace = {
background = "#333333";
border = "#222222";
text = "#888888";
};
urgentWorkspace = {
background = "#2f343a";
border = "#900000";
text = "#ffffff";
};
bindingMode = {
background = "#2f343a";
border = "#900000";
text = "#ffffff";
};
};
}
];
config.focus.newWindow = "none"; config.focus.newWindow = "none";
config.fonts = { names = [ "FantasqueSansMono Nerd Font Mono" "monospace" ]; size = 11.0; }; config.fonts = {
names = [
"FantasqueSansMono Nerd Font Mono"
"monospace"
];
size = 11.0;
};
config.gaps.outer = 5; config.gaps.outer = 5;
config.gaps.inner = 5; config.gaps.inner = 5;
config.gaps.smartGaps = true; config.gaps.smartGaps = true;
@ -69,53 +104,57 @@ in
config.window.titlebar = false; config.window.titlebar = false;
# Keybindings # Keybindings
config.keybindings = lib.mkOptionDefault ({ config.keybindings = lib.mkOptionDefault (
## vim-style movements {
"${mod}+h" = "focus left"; ## vim-style movements
"${mod}+j" = "focus down"; "${mod}+h" = "focus left";
"${mod}+k" = "focus up"; "${mod}+j" = "focus down";
"${mod}+l" = "focus right"; "${mod}+k" = "focus up";
"${mod}+Shift+h" = "move left"; "${mod}+l" = "focus right";
"${mod}+Shift+j" = "move down"; "${mod}+Shift+h" = "move left";
"${mod}+Shift+k" = "move up"; "${mod}+Shift+j" = "move down";
"${mod}+Shift+l" = "move right"; "${mod}+Shift+k" = "move up";
## Splits "${mod}+Shift+l" = "move right";
"${mod}+v" = "split v"; ## Splits
"${mod}+Shift+v" = "split h"; "${mod}+v" = "split v";
## Run "${mod}+Shift+v" = "split h";
"${mod}+r" = "exec ${pkgs.dmenu}/bin/dmenu_run"; ## Run
"${mod}+d" = "exec i3-dmenu-desktop --dmenu='${pkgs.dmenu}/bin/dmenu -i'"; "${mod}+r" = "exec ${pkgs.dmenu}/bin/dmenu_run";
} // ( "${mod}+d" = "exec i3-dmenu-desktop --dmenu='${pkgs.dmenu}/bin/dmenu -i'";
builtins.listToAttrs (lib.flatten (map }
(key: [ // (builtins.listToAttrs (
{ lib.flatten (
name = "${mod}+${key}"; map (key: [
value = "workspace ${builtins.getAttr key wsAttrs}"; {
} name = "${mod}+${key}";
{ value = "workspace ${builtins.getAttr key wsAttrs}";
name = "${mod}+Shift+${key}"; }
value = "move to workspace ${builtins.getAttr key wsAttrs}"; {
} name = "${mod}+Shift+${key}";
]) value = "move to workspace ${builtins.getAttr key wsAttrs}";
(builtins.attrNames wsAttrs)) }
))); ]) (builtins.attrNames wsAttrs)
)
))
);
# Workspace # Workspace
config.defaultWorkspace = "workspace ${builtins.getAttr "1" wsAttrs}"; config.defaultWorkspace = "workspace ${builtins.getAttr "1" wsAttrs}";
config.startup = [ config.startup =
{ command = "firefox"; } [
{ command = "discord"; } { command = "firefox"; }
{ command = "dex -ae i3"; } { command = "discord"; }
{ command = "ibus-daemon -drxR"; } { command = "dex -ae i3"; }
] ++ { command = "ibus-daemon -drxR"; }
( ]
if (config.linux.graphical.wallpaper != "") ++ (
then [{ command = "${pkgs.feh}/bin/feh --bg-fill ${config.linux.graphical.wallpaper}"; }] if (config.linux.graphical.wallpaper != "") then
else [ ] [ { command = "${pkgs.feh}/bin/feh --bg-fill ${config.linux.graphical.wallpaper}"; } ]
); else
[ ]
);
}; };
# i3status # i3status
programs.i3status-rust.enable = true; programs.i3status-rust.enable = true;
programs.i3status-rust.bars.default = { programs.i3status-rust.bars.default = {
@ -154,5 +193,3 @@ in
}; };
}; };
} }

View file

@ -1,9 +1,14 @@
{ pkgs, config, lib, ... }: {
pkgs,
config,
lib,
...
}:
with lib; with lib;
{ {
xsession.windowManager.i3.config = mkIf (config.linux.graphical.x11.enablei3) { xsession.windowManager.i3.config = mkIf (config.linux.graphical.x11.enablei3) {
startup = [{ command = "${pkgs.flameshot}/bin/flameshot"; }]; startup = [ { command = "${pkgs.flameshot}/bin/flameshot"; } ];
keybindings = mkOptionDefault { "Print" = "exec ${pkgs.flameshot}/bin/flameshot gui"; }; keybindings = mkOptionDefault { "Print" = "exec ${pkgs.flameshot}/bin/flameshot gui"; };
}; };
} }

View file

@ -1,24 +1,42 @@
# A monitor list and common sway set up # A monitor list and common sway set up
{ config, pkgs, lib, ... }: with lib; {
config,
pkgs,
lib,
...
}:
with lib;
let let
monitors = { monitors = {
# Internal # Internal
"framework" = { "framework" = {
name = "BOE 0x0BCA Unknown"; name = "BOE 0x0BCA Unknown";
meta.mode = { width = 2256; height = 1504; refresh = 60.0; }; meta.mode = {
width = 2256;
height = 1504;
refresh = 60.0;
};
scale = 1.25; scale = 1.25;
}; };
"yoga" = { "yoga" = {
name = "AU Optronics 0xD291 Unknown"; name = "AU Optronics 0xD291 Unknown";
meta.connection = "eDP-1"; meta.connection = "eDP-1";
meta.mode = { width = 1920; height = 1080; refresh = 60.026; }; meta.mode = {
width = 1920;
height = 1080;
refresh = 60.026;
};
scale = 1; scale = 1;
}; };
# External # External
## Work @ EPFL ## Work @ EPFL
"work" = { "work" = {
name = "LG Electronics LG ULTRAFINE 301MAXSGHD10"; name = "LG Electronics LG ULTRAFINE 301MAXSGHD10";
meta.mode = { width = 3840; height = 2160; refresh = 60.0; }; meta.mode = {
width = 3840;
height = 2160;
refresh = 60.0;
};
scale = 1.25; scale = 1.25;
}; };
"home_4k" = { "home_4k" = {
@ -27,8 +45,15 @@ let
adaptive_sync = "on"; adaptive_sync = "on";
meta = { meta = {
connection = "DP-2"; connection = "DP-2";
mode = { width = 3840; height = 2160; refresh = 60.0; }; mode = {
fixedPosition = { x = 0; y = 0; }; width = 3840;
height = 2160;
refresh = 60.0;
};
fixedPosition = {
x = 0;
y = 0;
};
niriName = "PNP(AOC) U28G2G6B PPYP2JA000013"; niriName = "PNP(AOC) U28G2G6B PPYP2JA000013";
}; };
}; };
@ -37,15 +62,26 @@ let
adaptive_sync = "on"; adaptive_sync = "on";
meta = { meta = {
connection = "DP-3"; connection = "DP-3";
mode = { width = 2560; height = 1440; refresh = 165.0; }; mode = {
fixedPosition = { x = 2560; y = 0; }; width = 2560;
height = 1440;
refresh = 165.0;
};
fixedPosition = {
x = 2560;
y = 0;
};
niriName = "PNP(AOC) Q27G2G3R3B VXJP6HA000442"; niriName = "PNP(AOC) Q27G2G3R3B VXJP6HA000442";
}; };
}; };
"viewsonic_1080" = { "viewsonic_1080" = {
name = "ViewSonic Corporation XG2402 SERIES V4K182501054"; name = "ViewSonic Corporation XG2402 SERIES V4K182501054";
meta.mode = { width = 1920; height = 1080; refresh = 144.0; }; meta.mode = {
width = 1920;
height = 1080;
refresh = 144.0;
};
adaptive_sync = "on"; adaptive_sync = "on";
}; };
@ -53,13 +89,21 @@ let
eachMonitor = _name: monitor: { eachMonitor = _name: monitor: {
name = monitor.name; name = monitor.name;
value = builtins.removeAttrs monitor [ "scale" "name" "meta" ] // (lib.optionalAttrs (monitor ? scale) { value =
scale = toString monitor.scale; builtins.removeAttrs monitor [
}) // { "scale"
mode = with monitor.meta.mode; "${toString width}x${toString height}@${toString refresh}Hz"; "name"
} // (lib.optionalAttrs (monitor.meta ? fixedPosition) { "meta"
position = with monitor.meta.fixedPosition; "${toString x} ${toString y}"; ]
}); // (lib.optionalAttrs (monitor ? scale) {
scale = toString monitor.scale;
})
// {
mode = with monitor.meta.mode; "${toString width}x${toString height}@${toString refresh}Hz";
}
// (lib.optionalAttrs (monitor.meta ? fixedPosition) {
position = with monitor.meta.fixedPosition; "${toString x} ${toString y}";
});
}; };
in in
{ {
@ -73,4 +117,3 @@ in
mapAttrs' eachMonitor config.common.monitors mapAttrs' eachMonitor config.common.monitors
); );
} }

View file

@ -1,4 +1,9 @@
{ config, pkgs, lib, ... }: {
config,
pkgs,
lib,
...
}:
with lib; with lib;
let let
@ -91,10 +96,13 @@ in
# Add an extra syntax_color config # Add an extra syntax_color config
xdg.configFile."broot/conf.toml".source = mkOverride 1 ( xdg.configFile."broot/conf.toml".source = mkOverride 1 (
tomlFormat.generate "broot-config" (with config.programs.broot; { tomlFormat.generate "broot-config" (
inherit (settings) verbs modal skin; with config.programs.broot;
syntax_theme = "base16-ocean.light"; {
}) inherit (settings) verbs modal skin;
syntax_theme = "base16-ocean.light";
}
)
); );
}; };
} }

View file

@ -1,11 +1,20 @@
{ config, options, pkgs, lib, ... }: {
config,
options,
pkgs,
lib,
...
}:
with lib; with lib;
let let
cfg = config.programs.my-kakoune; cfg = config.programs.my-kakoune;
in in
{ {
imports = [ ./fish-session.nix ./tree-sitter.nix ]; imports = [
./fish-session.nix
./tree-sitter.nix
];
options.programs.my-kakoune = { options.programs.my-kakoune = {
enable = mkEnableOption "My version of the kakoune configuration"; enable = mkEnableOption "My version of the kakoune configuration";
@ -38,7 +47,11 @@ in
let let
kakouneFaces = kakouneFaces =
let let
txt = strings.concatStringsSep "\n" (builtins.attrValues (builtins.mapAttrs (name: face: "face global ${name} \"${face}\"") cfg.extraFaces)); txt = strings.concatStringsSep "\n" (
builtins.attrValues (
builtins.mapAttrs (name: face: "face global ${name} \"${face}\"") cfg.extraFaces
)
);
in in
pkgs.writeText "faces.kak" txt; pkgs.writeText "faces.kak" txt;
in in
@ -51,15 +64,13 @@ in
# Load faces # Load faces
source ${kakouneFaces} source ${kakouneFaces}
''; '';
} // lib.mapAttrs' }
(name: attrs: { // lib.mapAttrs' (name: attrs: {
name = "kak/autoload/${name}"; name = "kak/autoload/${name}";
value = attrs // { value = attrs // {
target = "kak/autoload/${name}"; target = "kak/autoload/${name}";
}; };
}) }) cfg.autoloadFile;
cfg.autoloadFile;
xdg.dataFile."kak".source = "${cfg.package}/share/kak"; xdg.dataFile."kak".source = "${cfg.package}/share/kak";
}; };
} }

View file

@ -1,4 +1,9 @@
{ config, pkgs, lib, ... }: {
config,
pkgs,
lib,
...
}:
with lib; with lib;
let let

View file

@ -1,4 +1,9 @@
{ config, pkgs, lib, ... }: {
config,
pkgs,
lib,
...
}:
with lib; with lib;
let let
cfg = config.programs.my-kakoune.tree-sitter; cfg = config.programs.my-kakoune.tree-sitter;
@ -14,14 +19,44 @@ let
default = "src"; default = "src";
}; };
grammar.compile = { grammar.compile = {
command = mkOption { type = types.str; default = "${pkgs.gcc}/bin/gcc"; }; command = mkOption {
args = mkOption { type = types.listOf types.str; default = [ "-c" "-fpic" "../parser.c" "../scanner.c" "-I" ".." ]; }; type = types.str;
flags = mkOption { type = types.listOf types.str; default = [ "-O3" ]; }; default = "${pkgs.gcc}/bin/gcc";
};
args = mkOption {
type = types.listOf types.str;
default = [
"-c"
"-fpic"
"../parser.c"
"../scanner.c"
"-I"
".."
];
};
flags = mkOption {
type = types.listOf types.str;
default = [ "-O3" ];
};
}; };
grammar.link = { grammar.link = {
command = mkOption { type = types.str; default = "${pkgs.gcc}/bin/gcc"; }; command = mkOption {
args = mkOption { type = types.listOf types.str; default = [ "-shared" "-fpic" "parser.o" "scanner.o" ]; }; type = types.str;
flags = mkOption { type = types.listOf types.str; default = [ "-O3" ]; }; default = "${pkgs.gcc}/bin/gcc";
};
args = mkOption {
type = types.listOf types.str;
default = [
"-shared"
"-fpic"
"parser.o"
"scanner.o"
];
};
flags = mkOption {
type = types.listOf types.str;
default = [ "-O3" ];
};
}; };
queries.src = mkOption { queries.src = mkOption {
type = types.package; type = types.package;
@ -34,12 +69,27 @@ let
}; };
}; };
mkGrammarPackage = mkGrammarPackage =
{ name {
, src name,
, grammarPath ? "src" src,
, grammarCompileArgs ? [ "-O3" "-c" "-fpic" "../parser.c" "../scanner.c" "-I" ".." ] grammarPath ? "src",
, grammarLinkArgs ? [ "-shared" "-fpic" "parser.o" "scanner.o" ] grammarCompileArgs ? [
}: pkgs.stdenv.mkDerivation { "-O3"
"-c"
"-fpic"
"../parser.c"
"../scanner.c"
"-I"
".."
],
grammarLinkArgs ? [
"-shared"
"-fpic"
"parser.o"
"scanner.o"
],
}:
pkgs.stdenv.mkDerivation {
inherit src; inherit src;
name = "kak-tree-sitter-grammar-${name}.so"; name = "kak-tree-sitter-grammar-${name}.so";
version = "latest"; version = "latest";
@ -215,43 +265,54 @@ in
toTs = name: "ts_${strings.concatStringsSep "_" (strings.splitString "." name)}"; toTs = name: "ts_${strings.concatStringsSep "_" (strings.splitString "." name)}";
toScm = name: strings.concatStringsSep "." (strings.splitString "_" name); toScm = name: strings.concatStringsSep "." (strings.splitString "_" name);
definedFaces = attrsets.mapAttrs' (name: value: { inherit value; name = toTs name; }) allGroups; definedFaces = attrsets.mapAttrs' (name: value: {
aliasFaces = attrsets.mapAttrs' (name: value: { name = toTs name; value = "@${toTs value}"; }) aliases; inherit value;
name = toTs name;
}) allGroups;
aliasFaces = attrsets.mapAttrs' (name: value: {
name = toTs name;
value = "@${toTs value}";
}) aliases;
faces = attrsets.recursiveUpdate definedFaces aliasFaces; faces = attrsets.recursiveUpdate definedFaces aliasFaces;
toml = pkgs.formats.toml { }; toml = pkgs.formats.toml { };
toLanguageConf = name: lang: with lang; { toLanguageConf =
grammar = { name: lang: with lang; {
source.local.path = mkGrammarPackage { grammar = {
inherit name; source.local.path = mkGrammarPackage {
src = grammar.src; inherit name;
grammarPath = grammar.path; src = grammar.src;
grammarCompileArgs = grammar.compile.flags ++ grammar.compile.args; grammarPath = grammar.path;
grammarLinkArgs = grammar.link.flags ++ grammar.link.args; grammarCompileArgs = grammar.compile.flags ++ grammar.compile.args;
grammarLinkArgs = grammar.link.flags ++ grammar.link.args;
};
compile = grammar.compile.command;
compile_args = grammar.compile.args;
compile_flags = grammar.compile.flags;
link = grammar.link.command;
link_args = grammar.link.args ++ [
"-o"
"${name}.so"
];
link_flags = grammar.link.flags;
};
queries = rec {
path = if queries.path == null then "runtime/queries/${name}" else queries.path;
source.local.path = "${queries.src}/${path}";
}; };
compile = grammar.compile.command;
compile_args = grammar.compile.args;
compile_flags = grammar.compile.flags;
link = grammar.link.command;
link_args = grammar.link.args ++ [ "-o" "${name}.so" ];
link_flags = grammar.link.flags;
}; };
queries = rec {
path = if queries.path == null then "runtime/queries/${name}" else queries.path;
source.local.path = "${queries.src}/${path}";
};
};
in in
mkIf cfg.enable { mkIf cfg.enable {
assertions = with lib.asserts; ([ ] assertions =
++ attrsets.mapAttrsToList with lib.asserts;
(name: _: { (
assertion = (! (builtins.hasAttr name allGroups)); [ ]
message = "${name} was both defined and aliased"; ++ attrsets.mapAttrsToList (name: _: {
}) assertion = (!(builtins.hasAttr name allGroups));
aliases message = "${name} was both defined and aliased";
); }) aliases
);
home.packages = [ cfg.package ]; home.packages = [ cfg.package ];
xdg.configFile."kak-tree-sitter/config.toml" = { xdg.configFile."kak-tree-sitter/config.toml" = {
@ -271,4 +332,3 @@ in
}; };
} }

View file

@ -1,9 +1,15 @@
{ pkgs, config, lib, ... }: {
pkgs,
config,
lib,
...
}:
let let
cfg = config.nki.programs.kitty; cfg = config.nki.programs.kitty;
cmd = "cmd"; cmd = "cmd";
in in
with lib; { with lib;
{
programs.kitty = mkIf (cfg.enable && pkgs.stdenv.isDarwin) { programs.kitty = mkIf (cfg.enable && pkgs.stdenv.isDarwin) {
# Darwin-specific setup # Darwin-specific setup
@ -24,4 +30,3 @@ with lib; {
}; };
}; };
} }

View file

@ -1,21 +1,41 @@
{ pkgs, config, lib, ... }: {
pkgs,
config,
lib,
...
}:
let let
cfg = config.nki.programs.kitty; cfg = config.nki.programs.kitty;
theme = { lib, options, config, ... }: { theme =
programs.kitty = lib.mkIf config.nki.programs.kitty.enable ( {
if builtins.hasAttr "themeFile" options.programs.kitty then { lib,
themeFile = "ayu_light"; options,
} else { config,
theme = "Ayu Light"; ...
} }:
); {
}; programs.kitty = lib.mkIf config.nki.programs.kitty.enable (
if builtins.hasAttr "themeFile" options.programs.kitty then
{
themeFile = "ayu_light";
}
else
{
theme = "Ayu Light";
}
);
};
in in
with lib; with lib;
{ {
imports = [ theme ./darwin.nix ./linux.nix ./tabs.nix ]; imports = [
theme
./darwin.nix
./linux.nix
./tabs.nix
];
options.nki.programs.kitty = { options.nki.programs.kitty = {
enable = mkEnableOption "Enable kitty"; enable = mkEnableOption "Enable kitty";
@ -73,14 +93,17 @@ with lib;
let let
# Background color and transparency # Background color and transparency
background = background =
if isNull cfg.background then { if isNull cfg.background then
background_opacity = "0.93"; {
dynamic_background_opacity = true; background_opacity = "0.93";
} else { dynamic_background_opacity = true;
background_image = "${cfg.background}"; }
background_image_layout = "scaled"; else
background_tint = "0.85"; {
}; background_image = "${cfg.background}";
background_image_layout = "scaled";
background_tint = "0.85";
};
in in
mkMerge [ mkMerge [
background background
@ -123,4 +146,3 @@ with lib;
''; '';
}; };
} }

View file

@ -1,4 +1,9 @@
{ config, pkgs, lib, ... }: {
config,
pkgs,
lib,
...
}:
let let
cfg = config.nki.programs.kitty; cfg = config.nki.programs.kitty;
in in

View file

@ -1,4 +1,9 @@
{ config, pkgs, lib, ... }: {
config,
pkgs,
lib,
...
}:
let let
cfg = config.nki.programs.kitty; cfg = config.nki.programs.kitty;
@ -7,33 +12,33 @@ in
with lib; with lib;
{ {
programs.kitty = mkIf cfg.enableTabs { programs.kitty = mkIf cfg.enableTabs {
keybindings = { keybindings =
"${cmd}+t" = "new_tab_with_cwd"; {
"${cmd}+shift+t" = "new_tab"; "${cmd}+t" = "new_tab_with_cwd";
"${cmd}+shift+o" = "launch --cwd=current --location=vsplit"; "${cmd}+shift+t" = "new_tab";
"${cmd}+o" = "launch --cwd=current --location=hsplit"; "${cmd}+shift+o" = "launch --cwd=current --location=vsplit";
"${cmd}+r" = "start_resizing_window"; "${cmd}+o" = "launch --cwd=current --location=hsplit";
"${cmd}+shift+r" = "layout_action rotate"; "${cmd}+r" = "start_resizing_window";
## Move the active window in the indicated direction "${cmd}+shift+r" = "layout_action rotate";
"${cmd}+shift+h" = "move_window left"; ## Move the active window in the indicated direction
"${cmd}+shift+k" = "move_window up"; "${cmd}+shift+h" = "move_window left";
"${cmd}+shift+j" = "move_window down"; "${cmd}+shift+k" = "move_window up";
"${cmd}+shift+l" = "move_window right"; "${cmd}+shift+j" = "move_window down";
## Switch focus to the neighboring window in the indicated direction "${cmd}+shift+l" = "move_window right";
"${cmd}+h" = "neighboring_window left"; ## Switch focus to the neighboring window in the indicated direction
"${cmd}+k" = "neighboring_window up"; "${cmd}+h" = "neighboring_window left";
"${cmd}+j" = "neighboring_window down "; "${cmd}+k" = "neighboring_window up";
"${cmd}+l" = "neighboring_window right"; "${cmd}+j" = "neighboring_window down ";
## Detach window to its own tab "${cmd}+l" = "neighboring_window right";
"${cmd}+shift+d" = "detach_window new-tab"; ## Detach window to its own tab
## Change layout to fullscreen (stack) and back "${cmd}+shift+d" = "detach_window new-tab";
"${cmd}+f" = "toggle_layout stack"; ## Change layout to fullscreen (stack) and back
} "${cmd}+f" = "toggle_layout stack";
# Tab bindings }
// builtins.listToAttrs # Tab bindings
(map // builtins.listToAttrs (
(x: attrsets.nameValuePair "${cmd}+${toString x}" "goto_tab ${toString x}") map (x: attrsets.nameValuePair "${cmd}+${toString x}" "goto_tab ${toString x}") (lists.range 1 9)
(lists.range 1 9)); );
settings = { settings = {
# Tab settings # Tab settings
tab_bar_edge = "top"; tab_bar_edge = "top";

View file

@ -1,4 +1,10 @@
{ config, osConfig, lib, pkgs, ... }: {
config,
osConfig,
lib,
pkgs,
...
}:
let let
cfg = config.programs.my-niri; cfg = config.programs.my-niri;
@ -26,16 +32,33 @@ in
lock-command = lib.mkOption { lock-command = lib.mkOption {
type = lib.types.listOf lib.types.str; type = lib.types.listOf lib.types.str;
description = "The command to lock the screen"; description = "The command to lock the screen";
default = [ "${pkgs.swaylock}/bin/swaylock" ] default =
++ (if wallpaper == "" then [ "" ] else [ "-i" "${wallpaper}" "-s" "fill" ]) [ "${pkgs.swaylock}/bin/swaylock" ]
++ [ "-l" "-k" ]; ++ (
if wallpaper == "" then
[ "" ]
else
[
"-i"
"${wallpaper}"
"-s"
"fill"
]
)
++ [
"-l"
"-k"
];
}; };
workspaces = lib.mkOption { workspaces = lib.mkOption {
type = lib.types.attrsOf type = lib.types.attrsOf (
(lib.types.submodule { lib.types.submodule {
options = { options = {
name = lib.mkOption { type = lib.types.str; description = "workspace name"; }; name = lib.mkOption {
type = lib.types.str;
description = "workspace name";
};
fixed = lib.mkOption { fixed = lib.mkOption {
type = lib.types.bool; type = lib.types.bool;
default = true; default = true;
@ -47,7 +70,8 @@ in
description = "Default monitor to spawn workspace in"; description = "Default monitor to spawn workspace in";
}; };
}; };
}); }
);
description = "A mapping of ordering to workspace names, for fixed workspaces"; description = "A mapping of ordering to workspace names, for fixed workspaces";
}; };
}; };
@ -55,17 +79,39 @@ in
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
programs.my-niri.workspaces = { programs.my-niri.workspaces = {
# Default workspaces, always there # Default workspaces, always there
"01" = { name = "🌏 web"; }; "01" = {
"02" = { name = "💬 chat"; }; name = "🌏 web";
"03" = { name = " code"; }; };
"04" = { name = "🎶 music"; }; "02" = {
"05" = { name = "🔧 extra"; }; name = "💬 chat";
"06" = { name = "🧰 6"; }; };
"07" = { name = "🔩 7"; }; "03" = {
"08" = { name = "🛠 8"; }; name = " code";
"09" = { name = "🔨 9"; }; };
"10" = { name = "🎲 misc"; }; "04" = {
"99" = { name = "📧 Email"; }; name = "🎶 music";
};
"05" = {
name = "🔧 extra";
};
"06" = {
name = "🧰 6";
};
"07" = {
name = "🔩 7";
};
"08" = {
name = "🛠 8";
};
"09" = {
name = "🔨 9";
};
"10" = {
name = "🎲 misc";
};
"99" = {
name = "📧 Email";
};
}; };
systemd.user.services.swaync.Install.WantedBy = [ "niri.service" ]; systemd.user.services.swaync.Install.WantedBy = [ "niri.service" ];
systemd.user.services.swaync.Unit.After = [ "niri.service" ]; systemd.user.services.swaync.Unit.After = [ "niri.service" ];
@ -84,7 +130,10 @@ in
Unit = { Unit = {
Description = "XWayland Client for niri"; Description = "XWayland Client for niri";
PartOf = [ "xwayland.target" ]; PartOf = [ "xwayland.target" ];
Before = [ "xwayland.target" "xdg-desktop-autostart.target" ]; Before = [
"xwayland.target"
"xdg-desktop-autostart.target"
];
After = [ "niri.service" ]; After = [ "niri.service" ];
}; };
Install.WantedBy = [ "niri.service" ]; Install.WantedBy = [ "niri.service" ];
@ -97,16 +146,20 @@ in
}; };
programs.niri.settings = { programs.niri.settings = {
environment = { environment =
QT_QPA_PLATFORM = "wayland"; {
QT_WAYLAND_DISABLE_WINDOWDECORATION = "1"; QT_QPA_PLATFORM = "wayland";
QT_IM_MODULE = "fcitx"; QT_WAYLAND_DISABLE_WINDOWDECORATION = "1";
# export NIXOS_OZONE_WL=1 # Until text-input is merged QT_IM_MODULE = "fcitx";
DISPLAY = xwayland-display; # export NIXOS_OZONE_WL=1 # Until text-input is merged
} // lib.optionalAttrs osConfig.services.desktopManager.plasma6.enable { DISPLAY = xwayland-display;
XDG_MENU_PREFIX = "plasma-"; }
// lib.optionalAttrs osConfig.services.desktopManager.plasma6.enable {
XDG_MENU_PREFIX = "plasma-";
};
input.keyboard.xkb = {
layout = "jp";
}; };
input.keyboard.xkb = { layout = "jp"; };
input.touchpad = lib.mkIf cfg.enableLaptop { input.touchpad = lib.mkIf cfg.enableLaptop {
tap = true; tap = true;
dwt = true; dwt = true;
@ -138,9 +191,25 @@ in
spawn-at-startup = [ spawn-at-startup = [
# Wallpaper # Wallpaper
{ command = [ (lib.getExe pkgs.swaybg) "-i" "${wallpaper}" "-m" "fill" ]; } {
command = [
(lib.getExe pkgs.swaybg)
"-i"
"${wallpaper}"
"-m"
"fill"
];
}
# Waybar # Waybar
{ command = [ "systemctl" "--user" "start" "xdg-desktop-portal-gtk.service" "xdg-desktop-portal.service" ]; } {
command = [
"systemctl"
"--user"
"start"
"xdg-desktop-portal-gtk.service"
"xdg-desktop-portal.service"
];
}
]; ];
layout = { layout = {
@ -154,11 +223,24 @@ in
focus-ring = { focus-ring = {
width = 4; width = 4;
active.gradient = { from = "#00447AFF"; to = "#71C4FFAA"; angle = 45; }; active.gradient = {
from = "#00447AFF";
to = "#71C4FFAA";
angle = 45;
};
inactive.color = "#505050"; inactive.color = "#505050";
}; };
border.enable = false; border.enable = false;
struts = let v = 8; in { left = v; right = v; bottom = v; top = v; }; struts =
let
v = 8;
in
{
left = v;
right = v;
bottom = v;
top = v;
};
}; };
prefer-no-csd = true; prefer-no-csd = true;
@ -166,18 +248,31 @@ in
workspaces = workspaces =
let let
fixedWorkspaces = lib.filterAttrs (_: w: w.fixed) cfg.workspaces; fixedWorkspaces = lib.filterAttrs (_: w: w.fixed) cfg.workspaces;
workspaceConfig = lib.mapAttrs workspaceConfig = lib.mapAttrs (
(_: w: { inherit (w) name; } // (lib.optionalAttrs (w.monitor != null) { _: w:
{
inherit (w) name;
}
// (lib.optionalAttrs (w.monitor != null) {
open-on-output = w.monitor; open-on-output = w.monitor;
})) })
fixedWorkspaces; ) fixedWorkspaces;
in in
workspaceConfig; workspaceConfig;
window-rules = [ window-rules = [
# Rounded Corners # Rounded Corners
{ {
geometry-corner-radius = let v = 8.0; in { bottom-left = v; bottom-right = v; top-left = v; top-right = v; }; geometry-corner-radius =
let
v = 8.0;
in
{
bottom-left = v;
bottom-right = v;
top-left = v;
top-right = v;
};
clip-to-geometry = true; clip-to-geometry = true;
} }
# Workspace assignments # Workspace assignments
@ -185,9 +280,18 @@ in
open-on-workspace = cfg.workspaces."01".name; open-on-workspace = cfg.workspaces."01".name;
open-maximized = true; open-maximized = true;
matches = [ matches = [
{ at-startup = true; app-id = "^firefox$"; } {
{ at-startup = true; app-id = "^librewolf$"; } at-startup = true;
{ at-startup = true; app-id = "^zen$"; } app-id = "^firefox$";
}
{
at-startup = true;
app-id = "^librewolf$";
}
{
at-startup = true;
app-id = "^zen$";
}
]; ];
} }
{ {
@ -225,7 +329,7 @@ in
# xwaylandvideobridge # xwaylandvideobridge
{ {
matches = [{ app-id = "^xwaylandvideobridge$"; }]; matches = [ { app-id = "^xwaylandvideobridge$"; } ];
open-floating = true; open-floating = true;
focus-ring.enable = false; focus-ring.enable = false;
opacity = 0.0; opacity = 0.0;
@ -242,15 +346,15 @@ in
# Kitty dimming # Kitty dimming
{ {
matches = [{ app-id = "kitty"; }]; matches = [ { app-id = "kitty"; } ];
excludes = [{ is-focused = true; }]; excludes = [ { is-focused = true; } ];
opacity = 0.95; opacity = 0.95;
} }
]; ];
layer-rules = [ layer-rules = [
{ {
matches = [{ namespace = "^swaync-.*"; }]; matches = [ { namespace = "^swaync-.*"; } ];
block-out-from = "screen-capture"; block-out-from = "screen-capture";
} }
]; ];
@ -268,14 +372,38 @@ in
"Mod+Shift+P".action = spawn "rofi-rbw-script"; "Mod+Shift+P".action = spawn "rofi-rbw-script";
# Audio and Volume # Audio and Volume
"XF86AudioPrev" = { action = spawn playerctl "previous"; allow-when-locked = true; }; "XF86AudioPrev" = {
"XF86AudioPlay" = { action = spawn playerctl "play-pause"; allow-when-locked = true; }; action = spawn playerctl "previous";
"Shift+XF86AudioPlay" = { action = spawn playerctl "stop"; allow-when-locked = true; }; allow-when-locked = true;
"XF86AudioNext" = { action = spawn playerctl "next"; allow-when-locked = true; }; };
"XF86AudioRecord" = { action = spawn amixer "-q" "set" "Capture" "toggle"; allow-when-locked = true; }; "XF86AudioPlay" = {
"XF86AudioMute" = { action = spawn amixer "-q" "set" "Master" "toggle"; allow-when-locked = true; }; action = spawn playerctl "play-pause";
"XF86AudioLowerVolume" = { action = spawn amixer "-q" "set" "Master" "3%-"; allow-when-locked = true; }; allow-when-locked = true;
"XF86AudioRaiseVolume" = { action = spawn amixer "-q" "set" "Master" "3%+"; allow-when-locked = true; }; };
"Shift+XF86AudioPlay" = {
action = spawn playerctl "stop";
allow-when-locked = true;
};
"XF86AudioNext" = {
action = spawn playerctl "next";
allow-when-locked = true;
};
"XF86AudioRecord" = {
action = spawn amixer "-q" "set" "Capture" "toggle";
allow-when-locked = true;
};
"XF86AudioMute" = {
action = spawn amixer "-q" "set" "Master" "toggle";
allow-when-locked = true;
};
"XF86AudioLowerVolume" = {
action = spawn amixer "-q" "set" "Master" "3%-";
allow-when-locked = true;
};
"XF86AudioRaiseVolume" = {
action = spawn amixer "-q" "set" "Master" "3%+";
allow-when-locked = true;
};
# Backlight # Backlight
"XF86MonBrightnessDown".action = spawn brightnessctl "s" "10%-"; "XF86MonBrightnessDown".action = spawn brightnessctl "s" "10%-";
@ -320,10 +448,22 @@ in
"Mod+Ctrl+O".action = move-workspace-up; "Mod+Ctrl+O".action = move-workspace-up;
# Mouse bindings # Mouse bindings
"Mod+WheelScrollDown" = { action = focus-workspace-down; cooldown-ms = 150; }; "Mod+WheelScrollDown" = {
"Mod+WheelScrollUp" = { action = focus-workspace-up; cooldown-ms = 150; }; action = focus-workspace-down;
"Mod+Ctrl+WheelScrollDown" = { action = move-column-to-workspace-down; cooldown-ms = 150; }; cooldown-ms = 150;
"Mod+Ctrl+WheelScrollUp" = { action = move-column-to-workspace-up; cooldown-ms = 150; }; };
"Mod+WheelScrollUp" = {
action = focus-workspace-up;
cooldown-ms = 150;
};
"Mod+Ctrl+WheelScrollDown" = {
action = move-column-to-workspace-down;
cooldown-ms = 150;
};
"Mod+Ctrl+WheelScrollUp" = {
action = move-column-to-workspace-up;
cooldown-ms = 150;
};
"Mod+WheelScrollRight".action = focus-column-right; "Mod+WheelScrollRight".action = focus-column-right;
"Mod+WheelScrollLeft".action = focus-column-left; "Mod+WheelScrollLeft".action = focus-column-left;
@ -338,26 +478,66 @@ in
# #
# For example, with 2 workspaces + 1 empty, indices 3, 4, 5 and so on # For example, with 2 workspaces + 1 empty, indices 3, 4, 5 and so on
# will all refer to the 3rd workspace. # will all refer to the 3rd workspace.
"Mod+1" = lib.mkIf cfg.workspaces."01".fixed { action = focus-workspace (cfg.workspaces."01".name); }; "Mod+1" = lib.mkIf cfg.workspaces."01".fixed {
"Mod+2" = lib.mkIf cfg.workspaces."02".fixed { action = focus-workspace (cfg.workspaces."02".name); }; action = focus-workspace (cfg.workspaces."01".name);
"Mod+3" = lib.mkIf cfg.workspaces."03".fixed { action = focus-workspace (cfg.workspaces."03".name); }; };
"Mod+4" = lib.mkIf cfg.workspaces."04".fixed { action = focus-workspace (cfg.workspaces."04".name); }; "Mod+2" = lib.mkIf cfg.workspaces."02".fixed {
"Mod+5" = lib.mkIf cfg.workspaces."05".fixed { action = focus-workspace (cfg.workspaces."05".name); }; action = focus-workspace (cfg.workspaces."02".name);
"Mod+6" = lib.mkIf cfg.workspaces."06".fixed { action = focus-workspace (cfg.workspaces."06".name); }; };
"Mod+7" = lib.mkIf cfg.workspaces."07".fixed { action = focus-workspace (cfg.workspaces."07".name); }; "Mod+3" = lib.mkIf cfg.workspaces."03".fixed {
"Mod+8" = lib.mkIf cfg.workspaces."08".fixed { action = focus-workspace (cfg.workspaces."08".name); }; action = focus-workspace (cfg.workspaces."03".name);
"Mod+9" = lib.mkIf cfg.workspaces."09".fixed { action = focus-workspace (cfg.workspaces."09".name); }; };
"Mod+0" = lib.mkIf cfg.workspaces."10".fixed { action = focus-workspace (cfg.workspaces."10".name); }; "Mod+4" = lib.mkIf cfg.workspaces."04".fixed {
"Mod+Shift+1" = lib.mkIf cfg.workspaces."01".fixed { action = move-column-to-workspace (cfg.workspaces."01".name); }; action = focus-workspace (cfg.workspaces."04".name);
"Mod+Shift+2" = lib.mkIf cfg.workspaces."02".fixed { action = move-column-to-workspace (cfg.workspaces."02".name); }; };
"Mod+Shift+3" = lib.mkIf cfg.workspaces."03".fixed { action = move-column-to-workspace (cfg.workspaces."03".name); }; "Mod+5" = lib.mkIf cfg.workspaces."05".fixed {
"Mod+Shift+4" = lib.mkIf cfg.workspaces."04".fixed { action = move-column-to-workspace (cfg.workspaces."04".name); }; action = focus-workspace (cfg.workspaces."05".name);
"Mod+Shift+5" = lib.mkIf cfg.workspaces."05".fixed { action = move-column-to-workspace (cfg.workspaces."05".name); }; };
"Mod+Shift+6" = lib.mkIf cfg.workspaces."06".fixed { action = move-column-to-workspace (cfg.workspaces."06".name); }; "Mod+6" = lib.mkIf cfg.workspaces."06".fixed {
"Mod+Shift+7" = lib.mkIf cfg.workspaces."07".fixed { action = move-column-to-workspace (cfg.workspaces."07".name); }; action = focus-workspace (cfg.workspaces."06".name);
"Mod+Shift+8" = lib.mkIf cfg.workspaces."08".fixed { action = move-column-to-workspace (cfg.workspaces."08".name); }; };
"Mod+Shift+9" = lib.mkIf cfg.workspaces."09".fixed { action = move-column-to-workspace (cfg.workspaces."09".name); }; "Mod+7" = lib.mkIf cfg.workspaces."07".fixed {
"Mod+Shift+0" = lib.mkIf cfg.workspaces."10".fixed { action = move-column-to-workspace (cfg.workspaces."10".name); }; action = focus-workspace (cfg.workspaces."07".name);
};
"Mod+8" = lib.mkIf cfg.workspaces."08".fixed {
action = focus-workspace (cfg.workspaces."08".name);
};
"Mod+9" = lib.mkIf cfg.workspaces."09".fixed {
action = focus-workspace (cfg.workspaces."09".name);
};
"Mod+0" = lib.mkIf cfg.workspaces."10".fixed {
action = focus-workspace (cfg.workspaces."10".name);
};
"Mod+Shift+1" = lib.mkIf cfg.workspaces."01".fixed {
action = move-column-to-workspace (cfg.workspaces."01".name);
};
"Mod+Shift+2" = lib.mkIf cfg.workspaces."02".fixed {
action = move-column-to-workspace (cfg.workspaces."02".name);
};
"Mod+Shift+3" = lib.mkIf cfg.workspaces."03".fixed {
action = move-column-to-workspace (cfg.workspaces."03".name);
};
"Mod+Shift+4" = lib.mkIf cfg.workspaces."04".fixed {
action = move-column-to-workspace (cfg.workspaces."04".name);
};
"Mod+Shift+5" = lib.mkIf cfg.workspaces."05".fixed {
action = move-column-to-workspace (cfg.workspaces."05".name);
};
"Mod+Shift+6" = lib.mkIf cfg.workspaces."06".fixed {
action = move-column-to-workspace (cfg.workspaces."06".name);
};
"Mod+Shift+7" = lib.mkIf cfg.workspaces."07".fixed {
action = move-column-to-workspace (cfg.workspaces."07".name);
};
"Mod+Shift+8" = lib.mkIf cfg.workspaces."08".fixed {
action = move-column-to-workspace (cfg.workspaces."08".name);
};
"Mod+Shift+9" = lib.mkIf cfg.workspaces."09".fixed {
action = move-column-to-workspace (cfg.workspaces."09".name);
};
"Mod+Shift+0" = lib.mkIf cfg.workspaces."10".fixed {
action = move-column-to-workspace (cfg.workspaces."10".name);
};
"Mod+asciicircum".action = focus-workspace (cfg.workspaces."99".name); "Mod+asciicircum".action = focus-workspace (cfg.workspaces."99".name);
"Mod+Shift+asciicircum".action = move-column-to-workspace (cfg.workspaces."99".name); "Mod+Shift+asciicircum".action = move-column-to-workspace (cfg.workspaces."99".name);
@ -392,4 +572,3 @@ in
}; };
}; };
} }

View file

@ -1,4 +1,11 @@
{ pkgs, lib, options, config, osConfig, ... }: {
pkgs,
lib,
options,
config,
osConfig,
...
}:
with lib; with lib;
let let
cfg = config.programs.my-sway; cfg = config.programs.my-sway;
@ -22,12 +29,14 @@ let
mail = "📧 Email"; mail = "📧 Email";
}; };
wsAttrs = builtins.listToAttrs ( wsAttrs = builtins.listToAttrs (
map map (i: {
(i: { name = toString (remainder i 10); value = builtins.elemAt workspaces (i - 1); }) name = toString (remainder i 10);
(range 1 11) value = builtins.elemAt workspaces (i - 1);
}) (range 1 11)
); );
remainder = x: y: x - (builtins.div x y) * y; remainder = x: y: x - (builtins.div x y) * y;
range = from: to: range =
from: to:
let let
f = cur: if cur == to then [ ] else [ cur ] ++ f (cur + 1); f = cur: if cur == to then [ ] else [ cur ] ++ f (cur + 1);
in in
@ -64,7 +73,10 @@ in
default = true; default = true;
}; };
wallpaper = mkOption { wallpaper = mkOption {
type = types.oneOf [ types.path types.str ]; type = types.oneOf [
types.path
types.str
];
description = "Path to the wallpaper to be used"; description = "Path to the wallpaper to be used";
default = config.linux.graphical.wallpaper; default = config.linux.graphical.wallpaper;
}; };
@ -83,14 +95,20 @@ in
lockCmd = mkOption { lockCmd = mkOption {
type = types.str; type = types.str;
description = "The screen lock command"; description = "The screen lock command";
default = "${pkgs.swaylock}/bin/swaylock" default =
"${pkgs.swaylock}/bin/swaylock"
+ (if cfg.wallpaper == "" then "" else " -i ${cfg.wallpaper} -s fill") + (if cfg.wallpaper == "" then "" else " -i ${cfg.wallpaper} -s fill")
+ " -l -k"; + " -l -k";
}; };
}; };
config.systemd.user.targets.sway-session = mkIf cfg.enable { config.systemd.user.targets.sway-session = mkIf cfg.enable {
Unit.Before = [ "tray.target" "xwayland.target" "xdg-desktop-portal.service" "xdg-desktop-autostart.target" ]; Unit.Before = [
"tray.target"
"xwayland.target"
"xdg-desktop-portal.service"
"xdg-desktop-autostart.target"
];
Unit.Upholds = [ "waybar.service" ]; Unit.Upholds = [ "waybar.service" ];
Unit.Wants = [ "xdg-desktop-autostart.target" ]; Unit.Wants = [ "xdg-desktop-autostart.target" ];
}; };
@ -107,13 +125,16 @@ in
enable = true; enable = true;
package = cfg.package; package = cfg.package;
systemd.enable = true; systemd.enable = true;
systemd.variables = options.wayland.windowManager.sway.systemd.variables.default ++ [ systemd.variables =
"PATH" # for portals options.wayland.windowManager.sway.systemd.variables.default
"XDG_DATA_DIRS" # For extra icons ++ [
"XDG_DATA_HOME" # For extra icons "PATH" # for portals
] ++ lib.optionals osConfig.services.desktopManager.plasma6.enable [ "XDG_DATA_DIRS" # For extra icons
"XDG_MENU_PREFIX" "XDG_DATA_HOME" # For extra icons
]; ]
++ lib.optionals osConfig.services.desktopManager.plasma6.enable [
"XDG_MENU_PREFIX"
];
# systemd.extraCommands = options.wayland.windowManager.sway.systemd.extraCommands.default # systemd.extraCommands = options.wayland.windowManager.sway.systemd.extraCommands.default
# ++ [ # ++ [
# "systemctl --user restart xdg-desktop-portal.service" # "systemctl --user restart xdg-desktop-portal.service"
@ -137,7 +158,8 @@ in
### Seats ### Seats
# #
# Cursor # Cursor
seat."*".xcursor_theme = "${config.home.pointerCursor.name} ${toString config.home.pointerCursor.size}"; seat."*".xcursor_theme =
"${config.home.pointerCursor.name} ${toString config.home.pointerCursor.size}";
### Programs ### Programs
# #
@ -158,110 +180,120 @@ in
# #
# Main modifier # Main modifier
modifier = mod; modifier = mod;
keybindings = { keybindings =
### Default Bindings {
# ### Default Bindings
## App management #
"${mod}+Return" = "exec ${swayCfg.config.terminal}"; ## App management
"${mod}+Shift+q" = "kill"; "${mod}+Return" = "exec ${swayCfg.config.terminal}";
"${mod}+d" = "exec ${swayCfg.config.menu}"; "${mod}+Shift+q" = "kill";
## Windowing "${mod}+d" = "exec ${swayCfg.config.menu}";
# Focus ## Windowing
"${mod}+${swayCfg.config.left}" = "focus left"; # Focus
"${mod}+${swayCfg.config.down}" = "focus down"; "${mod}+${swayCfg.config.left}" = "focus left";
"${mod}+${swayCfg.config.up}" = "focus up"; "${mod}+${swayCfg.config.down}" = "focus down";
"${mod}+${swayCfg.config.right}" = "focus right"; "${mod}+${swayCfg.config.up}" = "focus up";
"${mod}+Left" = "focus left"; "${mod}+${swayCfg.config.right}" = "focus right";
"${mod}+Down" = "focus down"; "${mod}+Left" = "focus left";
"${mod}+Up" = "focus up"; "${mod}+Down" = "focus down";
"${mod}+Right" = "focus right"; "${mod}+Up" = "focus up";
# Move "${mod}+Right" = "focus right";
"${mod}+Shift+${swayCfg.config.left}" = "move left"; # Move
"${mod}+Shift+${swayCfg.config.down}" = "move down"; "${mod}+Shift+${swayCfg.config.left}" = "move left";
"${mod}+Shift+${swayCfg.config.up}" = "move up"; "${mod}+Shift+${swayCfg.config.down}" = "move down";
"${mod}+Shift+${swayCfg.config.right}" = "move right"; "${mod}+Shift+${swayCfg.config.up}" = "move up";
"${mod}+Shift+Left" = "move left"; "${mod}+Shift+${swayCfg.config.right}" = "move right";
"${mod}+Shift+Down" = "move down"; "${mod}+Shift+Left" = "move left";
"${mod}+Shift+Up" = "move up"; "${mod}+Shift+Down" = "move down";
"${mod}+Shift+Right" = "move right"; "${mod}+Shift+Up" = "move up";
# Toggles "${mod}+Shift+Right" = "move right";
"${mod}+f" = "fullscreen toggle"; # Toggles
"${mod}+a" = "focus parent"; "${mod}+f" = "fullscreen toggle";
# Layouts "${mod}+a" = "focus parent";
"${mod}+s" = "layout stacking"; # Layouts
"${mod}+w" = "layout tabbed"; "${mod}+s" = "layout stacking";
"${mod}+e" = "layout toggle split"; "${mod}+w" = "layout tabbed";
# Floating "${mod}+e" = "layout toggle split";
"${mod}+Shift+space" = "floating toggle"; # Floating
# Scratchpad "${mod}+Shift+space" = "floating toggle";
"${mod}+Shift+minus" = "move scratchpad"; # Scratchpad
# Resize "${mod}+Shift+minus" = "move scratchpad";
"${mod}+r" = "mode resize"; # Resize
"${mod}+minus" = "scratchpad show"; "${mod}+r" = "mode resize";
## Reload and exit "${mod}+minus" = "scratchpad show";
"${mod}+Shift+c" = "reload"; ## Reload and exit
"${mod}+Shift+e" = "${mod}+Shift+c" = "reload";
"exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit'"; "${mod}+Shift+e" =
# Launcher "exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit'";
"${mod}+space" = "exec rofi -show drun"; # Launcher
"${mod}+tab" = "exec ${./rofi-window.py}"; "${mod}+space" = "exec rofi -show drun";
"${mod}+shift+p" = "exec rofi-rbw-script"; "${mod}+tab" = "exec ${./rofi-window.py}";
} // { "${mod}+shift+p" = "exec rofi-rbw-script";
## Splits }
"${mod}+v" = "split v"; // {
"${mod}+Shift+v" = "split h"; ## Splits
## Run "${mod}+v" = "split v";
"${mod}+r" = "exec ${config.wayland.windowManager.sway.config.menu}"; "${mod}+Shift+v" = "split h";
"${mod}+Shift+r" = "mode resize"; ## Run
## Screenshot "${mod}+r" = "exec ${config.wayland.windowManager.sway.config.menu}";
"Print" = "exec ${screenshotScript}/bin/screenshot"; "${mod}+Shift+r" = "mode resize";
"Shift+Print" = "exec ${screenshotEditScript}/bin/screenshot"; ## Screenshot
## Locking "Print" = "exec ${screenshotScript}/bin/screenshot";
"${mod}+semicolon" = "exec ${cfg.lockCmd}"; "Shift+Print" = "exec ${screenshotEditScript}/bin/screenshot";
## Multimedia ## Locking
"XF86AudioPrev" = "exec ${playerctl} previous"; "${mod}+semicolon" = "exec ${cfg.lockCmd}";
"XF86AudioPlay" = "exec ${playerctl} play-pause"; ## Multimedia
"Shift+XF86AudioPlay" = "exec ${playerctl} stop"; "XF86AudioPrev" = "exec ${playerctl} previous";
"XF86AudioNext" = "exec ${playerctl} next"; "XF86AudioPlay" = "exec ${playerctl} play-pause";
"XF86AudioRecord" = "exec ${pkgs.alsa-utils}/bin/amixer -q set Capture toggle"; "Shift+XF86AudioPlay" = "exec ${playerctl} stop";
"XF86AudioMute" = "exec ${pkgs.alsa-utils}/bin/amixer -q set Master toggle"; "XF86AudioNext" = "exec ${playerctl} next";
"XF86AudioLowerVolume" = "exec ${pkgs.alsa-utils}/bin/amixer -q set Master 3%-"; "XF86AudioRecord" = "exec ${pkgs.alsa-utils}/bin/amixer -q set Capture toggle";
"XF86AudioRaiseVolume" = "exec ${pkgs.alsa-utils}/bin/amixer -q set Master 3%+"; "XF86AudioMute" = "exec ${pkgs.alsa-utils}/bin/amixer -q set Master toggle";
## Backlight "XF86AudioLowerVolume" = "exec ${pkgs.alsa-utils}/bin/amixer -q set Master 3%-";
"XF86MonBrightnessDown" = "exec ${pkgs.brightnessctl}/bin/brightnessctl s 10%-"; "XF86AudioRaiseVolume" = "exec ${pkgs.alsa-utils}/bin/amixer -q set Master 3%+";
"XF86MonBrightnessUp" = "exec ${pkgs.brightnessctl}/bin/brightnessctl s 10%+"; ## Backlight
"Shift+XF86MonBrightnessDown" = "exec ${pkgs.brightnessctl}/bin/brightnessctl -d kbd_backlight s 25%-"; "XF86MonBrightnessDown" = "exec ${pkgs.brightnessctl}/bin/brightnessctl s 10%-";
"Shift+XF86MonBrightnessUp" = "exec ${pkgs.brightnessctl}/bin/brightnessctl -d kbd_backlight s 25%+"; "XF86MonBrightnessUp" = "exec ${pkgs.brightnessctl}/bin/brightnessctl s 10%+";
} // "Shift+XF86MonBrightnessDown" =
# Map the workspaces "exec ${pkgs.brightnessctl}/bin/brightnessctl -d kbd_backlight s 25%-";
(builtins.listToAttrs (lib.flatten (map "Shift+XF86MonBrightnessUp" =
(key: [ "exec ${pkgs.brightnessctl}/bin/brightnessctl -d kbd_backlight s 25%+";
}
//
# Map the workspaces
(builtins.listToAttrs (
lib.flatten (
map (key: [
{
name = "${mod}+${key}";
value = "workspace ${builtins.getAttr key wsAttrs}";
}
{
name = "${mod}+Shift+${key}";
value = "move to workspace ${builtins.getAttr key wsAttrs}";
}
]) (builtins.attrNames wsAttrs)
)
))
// {
# Extra workspaces
"${mod}+asciicircum" = "workspace ${extraWorkspaces.mail}";
"${mod}+shift+asciicircum" = "move to workspace ${extraWorkspaces.mail}";
}
//
# Move workspaces between outputs
{ {
name = "${mod}+${key}"; "${mod}+ctrl+h" = "move workspace to output left";
value = "workspace ${builtins.getAttr key wsAttrs}"; "${mod}+ctrl+l" = "move workspace to output right";
} };
{
name = "${mod}+Shift+${key}";
value = "move to workspace ${builtins.getAttr key wsAttrs}";
}
])
(builtins.attrNames wsAttrs))
)) //
{
# Extra workspaces
"${mod}+asciicircum" = "workspace ${extraWorkspaces.mail}";
"${mod}+shift+asciicircum" = "move to workspace ${extraWorkspaces.mail}";
} //
# Move workspaces between outputs
{
"${mod}+ctrl+h" = "move workspace to output left";
"${mod}+ctrl+l" = "move workspace to output right";
};
### Fonts ### Fonts
# #
fonts = { fonts = {
names = [ "monospace" "FontAwesome5Free" ]; names = [
"monospace"
"FontAwesome5Free"
];
size = cfg.fontSize; size = cfg.fontSize;
}; };
@ -298,21 +330,31 @@ in
]; ];
}; };
# Commands # Commands
window.commands = [ window.commands =
{ criteria = { title = ".*"; }; command = "inhibit_idle fullscreen"; } [
] ++ ( {
# Floating assignments criteria = {
let title = ".*";
criterias = [ };
{ app_id = ".*float.*"; } command = "inhibit_idle fullscreen";
{ app_id = "org\\.freedesktop\\.impl\\.portal\\.desktop\\..*"; } }
{ class = ".*float.*"; } ]
{ title = "Extension: .*Bitwarden.*"; } ++ (
]; # Floating assignments
toCommand = criteria: { inherit criteria; command = "floating enable"; }; let
in criterias = [
map toCommand criterias { app_id = ".*float.*"; }
); { app_id = "org\\.freedesktop\\.impl\\.portal\\.desktop\\..*"; }
{ class = ".*float.*"; }
{ title = "Extension: .*Bitwarden.*"; }
];
toCommand = criteria: {
inherit criteria;
command = "floating enable";
};
in
map toCommand criterias
);
# Focus # Focus
focus.followMouse = true; focus.followMouse = true;
focus.mouseWarping = true; focus.mouseWarping = true;
@ -334,36 +376,50 @@ in
# swaynag # swaynag
swaynag.enable = true; swaynag.enable = true;
# Environment Variables # Environment Variables
extraSessionCommands = '' extraSessionCommands =
export QT_QPA_PLATFORM=wayland ''
export QT_WAYLAND_DISABLE_WINDOWDECORATION="1" export QT_QPA_PLATFORM=wayland
export QT_IM_MODULE=fcitx export QT_WAYLAND_DISABLE_WINDOWDECORATION="1"
export GTK_IM_MODULE=fcitx # Til text-input is merged export QT_IM_MODULE=fcitx
# export NIXOS_OZONE_WL=1 # Until text-input is merged export GTK_IM_MODULE=fcitx # Til text-input is merged
# export NIXOS_OZONE_WL=1 # Until text-input is merged
'' + (if config.services.gnome-keyring.enable then '' ''
# gnome-keyring + (
if type gnome-keyring-daemon >/dev/null; then if config.services.gnome-keyring.enable then
eval `gnome-keyring-daemon` ''
export SSH_AUTH_SOCK # gnome-keyring
fi if type gnome-keyring-daemon >/dev/null; then
'' else "") + lib.optionalString osConfig.services.desktopManager.plasma6.enable '' eval `gnome-keyring-daemon`
export XDG_MENU_PREFIX=plasma- export SSH_AUTH_SOCK
''; fi
''
else
""
)
+ lib.optionalString osConfig.services.desktopManager.plasma6.enable ''
export XDG_MENU_PREFIX=plasma-
'';
# Extra # Extra
wrapperFeatures.base = true; wrapperFeatures.base = true;
wrapperFeatures.gtk = true; wrapperFeatures.gtk = true;
extraConfig = extraConfig =
(if cfg.enableLaptop then '' (
# Lock screen on lid close if cfg.enableLaptop then
bindswitch lid:off exec ${cfg.lockCmd} ''
# Lock screen on lid close
bindswitch lid:off exec ${cfg.lockCmd}
# Gesture bindings # Gesture bindings
bindgesture swipe:3:right workspace prev bindgesture swipe:3:right workspace prev
bindgesture swipe:3:left workspace next bindgesture swipe:3:left workspace next
bindgesture swipe:3:up exec ${./rofi-window.py} bindgesture swipe:3:up exec ${./rofi-window.py}
'' else "") + '' ''
else
""
)
+ ''
## swayfx stuff ## swayfx stuff
# Rounded corners # Rounded corners
corner_radius 5 corner_radius 5
@ -378,10 +434,10 @@ in
# Blur # Blur
for_window [app_id=".*kitty.*"] blur enable for_window [app_id=".*kitty.*"] blur enable
blur_xray disable blur_xray disable
'' + '' ''
+ ''
# Enable portal stuff # Enable portal stuff
exec ${pkgs.writeShellScript "start-portals.sh" '' exec ${pkgs.writeShellScript "start-portals.sh" ''''}
''}
''; '';
}; };
@ -393,20 +449,28 @@ in
# { timeout = 15 * 60; command = cfg.lockCmd; } # { timeout = 15 * 60; command = cfg.lockCmd; }
]; ];
events = [ events = [
{ event = "lock"; command = cfg.lockCmd; } {
{ event = "before-sleep"; command = cfg.lockCmd; } event = "lock";
command = cfg.lockCmd;
}
{
event = "before-sleep";
command = cfg.lockCmd;
}
]; ];
}; };
config.home.packages = mkIf cfg.enable (with pkgs; [ config.home.packages = mkIf cfg.enable (
# Needed for QT_QPA_PLATFORM with pkgs;
kdePackages.qtwayland [
# For waybar # Needed for QT_QPA_PLATFORM
font-awesome kdePackages.qtwayland
]); # For waybar
font-awesome
]
);
config.programs.rofi = mkIf cfg.enable { config.programs.rofi = mkIf cfg.enable {
font = lib.mkForce "monospace ${toString cfg.fontSize}"; font = lib.mkForce "monospace ${toString cfg.fontSize}";
}; };
} }

View file

@ -1,4 +1,9 @@
{ pkgs, config, lib, ... }: {
pkgs,
config,
lib,
...
}:
with lib; with lib;
let let
cfg = config.programs.my-sway; cfg = config.programs.my-sway;
@ -6,15 +11,22 @@ let
# Set up an ibus script # Set up an ibus script
ibusNext = ( ibusNext = (
let let
input-methods = [ "xkb:us::eng" "mozc-jp" "Bamboo" ]; input-methods = [
next = m: "xkb:us::eng"
"mozc-jp"
"Bamboo"
];
next =
m:
let let
nextRec = l: nextRec =
if (length l == 1) l:
then head input-methods if (length l == 1) then
else if (m == head l) head input-methods
then (head (tail l)) else if (m == head l) then
else nextRec (tail l); (head (tail l))
else
nextRec (tail l);
in in
nextRec input-methods; nextRec input-methods;
changeTo = m: '' changeTo = m: ''
@ -52,4 +64,3 @@ in
}; };
}; };
} }

View file

@ -1,4 +1,9 @@
{ lib, config, pkgs, ... }: {
lib,
config,
pkgs,
...
}:
let let
cfg = config.programs.my-waybar; cfg = config.programs.my-waybar;
in in
@ -47,382 +52,418 @@ in
}; };
config.programs.waybar = config.programs.waybar =
let let
barWith = { showMedia ? true, showConnectivity ? true, extraSettings ? { }, ... }: lib.mkMerge ([{ barWith =
layer = "top"; {
position = "top"; showMedia ? true,
modules-left = [ showConnectivity ? true,
"sway/workspaces" extraSettings ? { },
"sway/mode" ...
"sway/window" }:
"niri/workspaces" lib.mkMerge (
"niri/window" [
]; {
modules-center = [ layer = "top";
]; position = "top";
modules-right = modules-left = [
lib.optional showMedia (if cfg.enableMpd then "mpd" else "custom/media") "sway/workspaces"
++ [ "sway/mode"
"tray" "sway/window"
"pulseaudio" "niri/workspaces"
] ++ lib.optionals showConnectivity [ "niri/window"
"bluetooth" ];
"network" modules-center = [
] ++ [ ];
"cpu" modules-right =
"memory" lib.optional showMedia (if cfg.enableMpd then "mpd" else "custom/media")
"temperature" ++ [
] ++ lib.optionals cfg.enableLaptopBars [ "battery" "battery#bat2" ] "tray"
++ [ "pulseaudio"
"clock" ]
]; ++ lib.optionals showConnectivity [
"bluetooth"
"network"
]
++ [
"cpu"
"memory"
"temperature"
]
++ lib.optionals cfg.enableLaptopBars [
"battery"
"battery#bat2"
]
++ [
"clock"
];
modules = { modules = {
"sway/workspaces" = { "sway/workspaces" = {
format = "{name}"; format = "{name}";
}; };
"sway/mode" = { "sway/mode" = {
format = "<span style=\"italic\">{}</span>"; format = "<span style=\"italic\">{}</span>";
}; };
"sway/window" = { "sway/window" = {
max-length = 70; max-length = 70;
format = "{title}"; format = "{title}";
"rewrite" = { "rewrite" = {
"(.*) Mozilla Firefox" = "[🌎] $1"; "(.*) Mozilla Firefox" = "[🌎] $1";
"(.*) - Mozilla Thunderbird" = "[📧] $1"; "(.*) - Mozilla Thunderbird" = "[📧] $1";
"(.*) - Kakoune" = "[] $1"; "(.*) - Kakoune" = "[] $1";
"(.*) - fish" = "[>_] $1"; "(.*) - fish" = "[>_] $1";
"(.*) - Discord" = "[🗨] $1"; "(.*) - Discord" = "[🗨] $1";
# ArmCord thing # ArmCord thing
" Discord \\| (.*)" = "[🗨] $1"; " Discord \\| (.*)" = "[🗨] $1";
"\\((\\d+)\\) Discord \\| (.*)" = "[🗨] {$1} $2"; "\\((\\d+)\\) Discord \\| (.*)" = "[🗨] {$1} $2";
}; };
}; };
"niri/window" = { "niri/window" = {
format = "{title}"; format = "{title}";
"rewrite" = { "rewrite" = {
"(.*) Mozilla Firefox" = "[🌎] $1"; "(.*) Mozilla Firefox" = "[🌎] $1";
"(.*) - Mozilla Thunderbird" = "[📧] $1"; "(.*) - Mozilla Thunderbird" = "[📧] $1";
"(.*) - Kakoune" = "[] $1"; "(.*) - Kakoune" = "[] $1";
"(.*) - fish" = "[>_] $1"; "(.*) - fish" = "[>_] $1";
"(.*) - Discord" = "[🗨] $1"; "(.*) - Discord" = "[🗨] $1";
# ArmCord thing # ArmCord thing
" Discord \\| (.*)" = "[🗨] $1"; " Discord \\| (.*)" = "[🗨] $1";
"\\((\\d+)\\) Discord \\| (.*)" = "[🗨] {$1} $2"; "\\((\\d+)\\) Discord \\| (.*)" = "[🗨] {$1} $2";
}; };
}; };
"tray" = { "tray" = {
icon-size = 21; icon-size = 21;
spacing = 10; spacing = 10;
}; };
"clock" = { "clock" = {
# format = "{:📅 %Y-%m-%d | 🕰️ %H:%M [%Z]}"; # format = "{:📅 %Y-%m-%d | 🕰️ %H:%M [%Z]}";
format = "📅 {0:%Y-%m-%d} | 🕰 {0:%H:%M [%Z]}"; format = "📅 {0:%Y-%m-%d} | 🕰 {0:%H:%M [%Z]}";
tooltip-format = "\n<span size='9pt' font_family='Noto Sans Mono CJK JP'>{calendar}</span>"; tooltip-format = "\n<span size='9pt' font_family='Noto Sans Mono CJK JP'>{calendar}</span>";
timezones = [ timezones = [
"Europe/Zurich" "Europe/Zurich"
"America/Toronto" "America/Toronto"
"Asia/Tokyo" "Asia/Tokyo"
"Asia/Ho_Chi_Minh" "Asia/Ho_Chi_Minh"
]; ];
calendar = { calendar = {
mode = "year"; mode = "year";
mode-mon-col = 3; mode-mon-col = 3;
weeks-pos = "right"; weeks-pos = "right";
on-scroll = 1; on-scroll = 1;
on-click-right = "mode"; on-click-right = "mode";
format = { format = {
months = "<span color='#ffead3'><b>{}</b></span>"; months = "<span color='#ffead3'><b>{}</b></span>";
days = "<span color='#ecc6d9'><b>{}</b></span>"; days = "<span color='#ecc6d9'><b>{}</b></span>";
weeks = "<span color='#99ffdd'><b>W{}</b></span>"; weeks = "<span color='#99ffdd'><b>W{}</b></span>";
weekdays = "<span color='#ffcc66'><b> </b></span>"; # See https://github.com/Alexays/Waybar/issues/3132 weekdays = "<span color='#ffcc66'><b> </b></span>"; # See https://github.com/Alexays/Waybar/issues/3132
today = "<span color='#ff6699'><b><u>{}</u></b></span>"; today = "<span color='#ff6699'><b><u>{}</u></b></span>";
};
};
actions = {
on-click-middle = "mode";
on-click-right = "tz_up";
on-scroll-up = "shift_up";
on-scroll-down = "shift_down";
};
};
"cpu" = {
format = "{usage}% ";
};
"memory" = {
format = "{}% ";
};
"temperature" = {
# thermal-zone = 2;
# hwmon-path" = "/sys/class/hwmon/hwmon2/temp1_input";
critical-threshold = 80;
# format-critical = "{temperatureC}°C ";
format = "{temperatureC}°C ";
};
"backlight" = {
# device = "acpi_video1";
format = "{percent}% {icon}";
states = [
0
50
];
format-icons = [
""
""
];
};
"battery" = lib.mkIf cfg.enableLaptopBars {
states = {
good = 95;
warning = 30;
critical = 15;
};
format = "{capacity}% {icon}";
# format-good = ""; # An empty format will hide the module
# format-full = "";
format-icons = [
""
""
""
""
""
];
};
"battery#bat2" = lib.mkIf cfg.enableLaptopBars {
bat = "BAT2";
};
"network" = {
# interface = wlp2s0 # (Optional) To force the use of this interface
format-wifi = "{essid} ({signalStrength}%) ";
format-ethernet = "{ifname} ";
format-disconnected = "Disconnected ";
interval = 7;
on-click = "${cfg.terminal} ${lib.getExe' pkgs.iwd "iwctl"}";
};
"bluetooth" = {
format = " {status}";
format-connected = " {device_alias}";
format-connected-battery = " {device_alias} {device_battery_percentage}%";
# format-device-preference= [ "device1", "device2" ], // preference list deciding the displayed devic;
tooltip-format = "{controller_alias}\t{controller_address}\n\n{num_connections} connected";
tooltip-format-connected = "{controller_alias}\t{controller_address}\n\n{num_connections} connected\n\n{device_enumerate}";
tooltip-format-enumerate-connected = "{device_alias}\t{device_address}";
tooltip-format-enumerate-connected-battery = "{device_alias}\t{device_address}\t{device_battery_percentage}%";
on-click = "${pkgs.blueman}/bin/blueman-manager";
};
"pulseaudio" = {
# scroll-step = 1;
format = "{volume}% {icon}";
format-bluetooth = "{volume}% {icon}";
format-muted = "";
format-icons = {
headphones = "";
handsfree = "";
headset = "";
phone = "";
portable = "";
car = "";
default = [
""
""
];
};
on-click = "${pkgs.pavucontrol}/bin/pavucontrol";
};
"mpd" = {
"format" =
"{stateIcon} {consumeIcon}{randomIcon}{repeatIcon}{singleIcon}{artist} - {album} - {title} ({elapsedTime:%M:%S}/{totalTime:%M:%S}) 🎧";
"format-disconnected" = "Disconnected 🎧";
"format-stopped" = "{consumeIcon}{randomIcon}{repeatIcon}{singleIcon}Stopped 🎧";
"interval" = 2;
"consume-icons" = {
"on" = " "; # Icon shows only when "consume" is on
};
"random-icons" = {
"off" = "<span color=\"#f53c3c\"></span> "; # Icon grayed out when "random" is off;
"on" = " ";
};
"repeat-icons" = {
"on" = " ";
};
"single-icons" = {
"on" = "1 ";
};
"state-icons" = {
"paused" = "";
"playing" = "";
};
"tooltip-format" = "MPD (connected)";
"tooltip-format-disconnected" = "MPD (disconnected)";
"on-click" = "${pkgs.mpc_cli}/bin/mpc toggle";
"on-click-right" = "${pkgs.mpc_cli}/bin/mpc stop";
"on-click-middle" = "${cfg.terminal} --class=kitty_ncmpcpp ${pkgs.ncmpcpp}/bin/ncmpcpp";
};
"custom/media" = {
"format" = "{icon}{}";
"return-type" = "json";
"format-icons" = {
"Playing" = " ";
"Paused" = " ";
};
"max-length" = 80;
"exec" =
"${lib.getExe pkgs.playerctl} -a metadata --format '{\"text\": \"{{artist}} - {{markup_escape(title)}}\", \"tooltip\": \"{{playerName}} : {{markup_escape(title)}}\", \"alt\": \"{{status}}\", \"class\": \"{{status}}\"}' -F";
"on-click" = "${lib.getExe pkgs.playerctl} play-pause";
};
}; };
}; }
actions = { ]
on-click-middle = "mode"; ++ cfg.extraSettings
on-click-right = "tz_up"; ++ [ extraSettings ]
on-scroll-up = "shift_up"; );
on-scroll-down = "shift_down";
};
};
"cpu" = {
format = "{usage}% ";
};
"memory" = {
format = "{}% ";
};
"temperature" = {
# thermal-zone = 2;
# hwmon-path" = "/sys/class/hwmon/hwmon2/temp1_input";
critical-threshold = 80;
# format-critical = "{temperatureC}°C ";
format = "{temperatureC}°C ";
};
"backlight" = {
# device = "acpi_video1";
format = "{percent}% {icon}";
states = [ 0 50 ];
format-icons = [ "" "" ];
};
"battery" = lib.mkIf cfg.enableLaptopBars {
states = {
good = 95;
warning = 30;
critical = 15;
};
format = "{capacity}% {icon}";
# format-good = ""; # An empty format will hide the module
# format-full = "";
format-icons = [ "" "" "" "" "" ];
};
"battery#bat2" = lib.mkIf cfg.enableLaptopBars {
bat = "BAT2";
};
"network" = {
# interface = wlp2s0 # (Optional) To force the use of this interface
format-wifi = "{essid} ({signalStrength}%) ";
format-ethernet = "{ifname} ";
format-disconnected = "Disconnected ";
interval = 7;
on-click = "${cfg.terminal} ${lib.getExe' pkgs.iwd "iwctl"}";
};
"bluetooth" = {
format = " {status}";
format-connected = " {device_alias}";
format-connected-battery = " {device_alias} {device_battery_percentage}%";
# format-device-preference= [ "device1", "device2" ], // preference list deciding the displayed devic;
tooltip-format = "{controller_alias}\t{controller_address}\n\n{num_connections} connected";
tooltip-format-connected = "{controller_alias}\t{controller_address}\n\n{num_connections} connected\n\n{device_enumerate}";
tooltip-format-enumerate-connected = "{device_alias}\t{device_address}";
tooltip-format-enumerate-connected-battery = "{device_alias}\t{device_address}\t{device_battery_percentage}%";
on-click = "${pkgs.blueman}/bin/blueman-manager";
};
"pulseaudio" = {
# scroll-step = 1;
format = "{volume}% {icon}";
format-bluetooth = "{volume}% {icon}";
format-muted = "";
format-icons = {
headphones = "";
handsfree = "";
headset = "";
phone = "";
portable = "";
car = "";
default = [ "" "" ];
};
on-click = "${pkgs.pavucontrol}/bin/pavucontrol";
};
"mpd" = {
"format" = "{stateIcon} {consumeIcon}{randomIcon}{repeatIcon}{singleIcon}{artist} - {album} - {title} ({elapsedTime:%M:%S}/{totalTime:%M:%S}) 🎧";
"format-disconnected" = "Disconnected 🎧";
"format-stopped" = "{consumeIcon}{randomIcon}{repeatIcon}{singleIcon}Stopped 🎧";
"interval" = 2;
"consume-icons" = {
"on" = " "; # Icon shows only when "consume" is on
};
"random-icons" = {
"off" = "<span color=\"#f53c3c\"></span> "; # Icon grayed out when "random" is off;
"on" = " ";
};
"repeat-icons" = {
"on" = " ";
};
"single-icons" = {
"on" = "1 ";
};
"state-icons" = {
"paused" = "";
"playing" = "";
};
"tooltip-format" = "MPD (connected)";
"tooltip-format-disconnected" = "MPD (disconnected)";
"on-click" = "${pkgs.mpc_cli}/bin/mpc toggle";
"on-click-right" = "${pkgs.mpc_cli}/bin/mpc stop";
"on-click-middle" = "${cfg.terminal} --class=kitty_ncmpcpp ${pkgs.ncmpcpp}/bin/ncmpcpp";
};
"custom/media" = {
"format" = "{icon}{}";
"return-type" = "json";
"format-icons" = {
"Playing" = " ";
"Paused" = " ";
};
"max-length" = 80;
"exec" = "${lib.getExe pkgs.playerctl} -a metadata --format '{\"text\": \"{{artist}} - {{markup_escape(title)}}\", \"tooltip\": \"{{playerName}} : {{markup_escape(title)}}\", \"alt\": \"{{status}}\", \"class\": \"{{status}}\"}' -F";
"on-click" = "${lib.getExe pkgs.playerctl} play-pause";
};
};
}] ++
cfg.extraSettings
++ [ extraSettings ]);
in in
lib.mkIf cfg.enable { lib.mkIf cfg.enable {
enable = true; enable = true;
systemd.enable = true; systemd.enable = true;
systemd.target = "sway-session.target"; systemd.target = "sway-session.target";
settings = cfg.makeBars barWith; settings = cfg.makeBars barWith;
style = '' style =
* { ''
border: none; * {
border-radius: 0; border: none;
font-family: monospace, 'Font Awesome 5', 'Symbols Nerd Font Mono', 'SFNS Display', Helvetica, Arial, sans-serif; border-radius: 0;
font-size: ${toString (cfg.fontSize * 1.1)}px; font-family: monospace, 'Font Awesome 5', 'Symbols Nerd Font Mono', 'SFNS Display', Helvetica, Arial, sans-serif;
min-height: 0; font-size: ${toString (cfg.fontSize * 1.1)}px;
} min-height: 0;
}
window#waybar { window#waybar {
background: rgba(43, 48, 59, 0.8); background: rgba(43, 48, 59, 0.8);
border-bottom: 3px solid rgba(100, 114, 125, 0.5); border-bottom: 3px solid rgba(100, 114, 125, 0.5);
color: #ffffff; color: #ffffff;
} }
window#waybar.hidden { window#waybar.hidden {
opacity: 0.0; opacity: 0.0;
} }
/* https://github.com/Alexays/Waybar/wiki/FAQ#the-workspace-buttons-have-a-strange-hover-effect */ /* https://github.com/Alexays/Waybar/wiki/FAQ#the-workspace-buttons-have-a-strange-hover-effect */
#workspaces button { #workspaces button {
padding: 0 5px; padding: 0 5px;
background: transparent; background: transparent;
color: #ffffff; color: #ffffff;
border-bottom: 3px solid transparent; border-bottom: 3px solid transparent;
} }
#workspaces button.focused { #workspaces button.focused {
background: #64727D; background: #64727D;
border-bottom: 3px solid #ffffff; border-bottom: 3px solid #ffffff;
} }
#workspaces button.urgent { #workspaces button.urgent {
background-color: #eb4d4b; background-color: #eb4d4b;
} }
#window, #sway, #sway-window { #window, #sway, #sway-window {
padding-left: 1em; padding-left: 1em;
margin-bottom: 0.4em; margin-bottom: 0.4em;
} }
#mode { #mode {
background: #64727D; background: #64727D;
border-bottom: 3px solid #ffffff; border-bottom: 3px solid #ffffff;
} }
/* #clock, #battery, #cpu, #memory, #temperature, #backlight, #network, #pulseaudio, #bluetooth, #custom-media, #tray, #mode, #idle_inhibitor, #mpd { */ /* #clock, #battery, #cpu, #memory, #temperature, #backlight, #network, #pulseaudio, #bluetooth, #custom-media, #tray, #mode, #idle_inhibitor, #mpd { */
.modules-right > * > * { .modules-right > * > * {
margin: 0.2em 0 0.4em 0; margin: 0.2em 0 0.4em 0;
padding: 0.2em 0.5em; padding: 0.2em 0.5em;
border: 1px solid rgba(0, 0, 0, 0.25); border: 1px solid rgba(0, 0, 0, 0.25);
border-radius: 0.3em; border-radius: 0.3em;
} }
.modules-right > *:not(:last-child) > * { .modules-right > *:not(:last-child) > * {
margin-right: 0.4em; margin-right: 0.4em;
} }
#clock { #clock {
background-color: #64727D; background-color: #64727D;
} }
#battery { #battery {
background-color: #ffffff; background-color: #ffffff;
color: #000000; color: #000000;
} }
#battery.charging { #battery.charging {
color: #ffffff; color: #ffffff;
background-color: #26A65B; background-color: #26A65B;
} }
@keyframes blink { @keyframes blink {
to { to {
background-color: #ffffff; background-color: #ffffff;
color: #000000; color: #000000;
} }
} }
#battery.critical:not(.charging) { #battery.critical:not(.charging) {
background: #f53c3c; background: #f53c3c;
color: #ffffff; color: #ffffff;
animation-name: blink; animation-name: blink;
animation-duration: 0.5s; animation-duration: 0.5s;
animation-timing-function: linear; animation-timing-function: linear;
animation-iteration-count: infinite; animation-iteration-count: infinite;
animation-direction: alternate; animation-direction: alternate;
} }
#cpu { #cpu {
background: #2ecc71; background: #2ecc71;
color: #000000; color: #000000;
} }
#memory { #memory {
background: #9b59b6; background: #9b59b6;
} }
#backlight { #backlight {
background: #90b1b1; background: #90b1b1;
} }
#network { #network {
background: #2980b9; background: #2980b9;
} }
#network.disconnected { #network.disconnected {
background: #f53c3c; background: #f53c3c;
} }
#pulseaudio { #pulseaudio {
background: #f1c40f; background: #f1c40f;
color: #000000; color: #000000;
} }
#pulseaudio.muted { #pulseaudio.muted {
background: #90b1b1; background: #90b1b1;
} }
#bluetooth { #bluetooth {
background: DarkSlateBlue; background: DarkSlateBlue;
color: white; color: white;
} }
#custom-media { #custom-media {
background: #66cc99; background: #66cc99;
color: #2a5c45; color: #2a5c45;
} }
.custom-spotify { .custom-spotify {
background: #66cc99; background: #66cc99;
} }
.custom-vlc { .custom-vlc {
background: #ffa000; background: #ffa000;
} }
#temperature { #temperature {
background: #f0932b; background: #f0932b;
} }
#temperature.critical { #temperature.critical {
background: #eb4d4b; background: #eb4d4b;
} }
#tray { #tray {
background-color: #2980b9; background-color: #2980b9;
} }
#idle_inhibitor { #idle_inhibitor {
background-color: #2d3436; background-color: #2d3436;
} }
#idle_inhibitor.activated { #idle_inhibitor.activated {
background-color: #ecf0f1; background-color: #ecf0f1;
color: #2d3436; color: #2d3436;
} }
#mpd { #mpd {
background-color: teal; background-color: teal;
color: white; color: white;
} }
'' + cfg.extraStyle; ''
+ cfg.extraStyle;
}; };
} }

View file

@ -1,8 +1,16 @@
{ pkgs, lib, config, ... }: {
pkgs,
lib,
config,
...
}:
let let
openconnect-epfl = pkgs.writeShellApplication { openconnect-epfl = pkgs.writeShellApplication {
name = "openconnect-epfl"; name = "openconnect-epfl";
runtimeInputs = with pkgs; [ openconnect rbw ]; runtimeInputs = with pkgs; [
openconnect
rbw
];
text = '' text = ''
METHOD="Microsoft Entra ID" METHOD="Microsoft Entra ID"
RBW_ENTRY="EPFL Microsoft Auth" RBW_ENTRY="EPFL Microsoft Auth"
@ -20,4 +28,3 @@ in
{ {
home.packages = [ openconnect-epfl ]; home.packages = [ openconnect-epfl ];
} }

View file

@ -1,4 +1,9 @@
{ pkgs, config, lib, ... }: {
pkgs,
config,
lib,
...
}:
{ {
imports = [ imports = [
@ -56,9 +61,11 @@
powerprofilesctl set $new_profile powerprofilesctl set $new_profile
''; '';
in in
[{ [
modules."battery"."on-click" = change-mode; {
}]; modules."battery"."on-click" = change-mode;
}
];
# input-remapping # input-remapping
xdg.configFile."autostart/input-remapper-autoload.desktop".source = xdg.configFile."autostart/input-remapper-autoload.desktop".source =
@ -75,7 +82,7 @@
settings = [ settings = [
{ {
profile.name = "undocked"; profile.name = "undocked";
profile.outputs = [{ criteria = "eDP-1"; }]; profile.outputs = [ { criteria = "eDP-1"; } ];
} }
{ {
profile.name = "work-both"; profile.name = "work-both";
@ -85,7 +92,10 @@
position = "0,${toString (builtins.floor ((2160 / work.scale - 1200) + 1200 / 3))}"; position = "0,${toString (builtins.floor ((2160 / work.scale - 1200) + 1200 / 3))}";
status = "enable"; status = "enable";
} }
{ criteria = work.name; position = "1920,0"; } {
criteria = work.name;
position = "1920,0";
}
]; ];
} }
{ {
@ -111,4 +121,3 @@
# changes in each release. # changes in each release.
home.stateVersion = "21.05"; home.stateVersion = "21.05";
} }

View file

@ -1,4 +1,10 @@
{ pkgs, options, config, lib, ... }: {
pkgs,
options,
config,
lib,
...
}:
let let
iio-sway = pkgs.stdenv.mkDerivation { iio-sway = pkgs.stdenv.mkDerivation {
@ -11,7 +17,11 @@ let
hash = "sha256-JGacKajslCOvd/BFfFSf7s1/hgF6rJqJ6H6xNnsuMb4="; hash = "sha256-JGacKajslCOvd/BFfFSf7s1/hgF6rJqJ6H6xNnsuMb4=";
}; };
buildInputs = with pkgs; [ dbus ]; buildInputs = with pkgs; [ dbus ];
nativeBuildInputs = with pkgs; [ meson ninja pkg-config ]; nativeBuildInputs = with pkgs; [
meson
ninja
pkg-config
];
meta.mainProgram = "iio-sway"; meta.mainProgram = "iio-sway";
}; };
in in
@ -31,10 +41,13 @@ in
home.homeDirectory = "/home/nki"; home.homeDirectory = "/home/nki";
# More packages # More packages
home.packages = (with pkgs; [ home.packages = (
# Note-taking with pkgs;
rnote [
]); # Note-taking
rnote
]
);
# Graphical set up # Graphical set up
linux.graphical.type = "wayland"; linux.graphical.type = "wayland";
@ -65,7 +78,9 @@ in
programs.my-niri.enable = true; programs.my-niri.enable = true;
programs.my-niri.enableLaptop = true; programs.my-niri.enableLaptop = true;
# Assign some of the workspaces to big screen # Assign some of the workspaces to big screen
programs.my-niri.workspaces = lib.genAttrs [ "06" "07" "08" "09" "10" ] (_: { monitor = config.common.monitors.work.name; }); programs.my-niri.workspaces = lib.genAttrs [ "06" "07" "08" "09" "10" ] (_: {
monitor = config.common.monitors.work.name;
});
programs.niri.settings = { programs.niri.settings = {
# input.keyboard.xkb.options = "ctrl:swapcaps"; # input.keyboard.xkb.options = "ctrl:swapcaps";
input.mouse = lib.mkForce { input.mouse = lib.mkForce {
@ -110,19 +125,29 @@ in
settings = [ settings = [
{ {
profile.name = "undocked"; profile.name = "undocked";
profile.outputs = [{ criteria = "eDP-1"; }]; profile.outputs = [ { criteria = "eDP-1"; } ];
} }
{ {
profile.name = "work-both"; profile.name = "work-both";
profile.outputs = [ profile.outputs = [
{ criteria = "eDP-1"; position = "0,${toString (builtins.floor ((2160 / work.scale - 1200) + 1200 / 3))}"; status = "enable"; } {
{ criteria = work.name; position = "1920,0"; } criteria = "eDP-1";
position = "0,${toString (builtins.floor ((2160 / work.scale - 1200) + 1200 / 3))}";
status = "enable";
}
{
criteria = work.name;
position = "1920,0";
}
]; ];
} }
{ {
profile.name = "work-one"; profile.name = "work-one";
profile.outputs = [ profile.outputs = [
{ criteria = "eDP-1"; status = "disable"; } {
criteria = "eDP-1";
status = "disable";
}
{ criteria = work.name; } { criteria = work.name; }
]; ];
} }
@ -139,4 +164,3 @@ in
# changes in each release. # changes in each release.
home.stateVersion = "21.05"; home.stateVersion = "21.05";
} }

View file

@ -2,7 +2,9 @@
let let
# osu-pkg = pkgs.unstable.osu-lazer-bin; # osu-pkg = pkgs.unstable.osu-lazer-bin;
osu-pkg = with pkgs; with lib; osu-pkg =
with pkgs;
with lib;
appimageTools.wrapType2 rec { appimageTools.wrapType2 rec {
pname = "osu-lazer-bin"; pname = "osu-lazer-bin";
version = "2025.321.0"; version = "2025.321.0";
@ -13,7 +15,8 @@ let
extraPkgs = pkgs: with pkgs; [ icu ]; extraPkgs = pkgs: with pkgs; [ icu ];
extraInstallCommands = extraInstallCommands =
let contents = appimageTools.extract { inherit pname version src; }; let
contents = appimageTools.extract { inherit pname version src; };
in in
'' ''
mv -v $out/bin/${pname} $out/bin/osu\! mv -v $out/bin/${pname} $out/bin/osu\!
@ -30,4 +33,3 @@ in
xdg.mimeApps.defaultApplications."x-scheme-handler/osu" = "osu!.desktop"; xdg.mimeApps.defaultApplications."x-scheme-handler/osu" = "osu!.desktop";
# home.packages = [ pkgs.osu-lazer ]; # home.packages = [ pkgs.osu-lazer ];
} }

View file

@ -2,25 +2,40 @@
# your system. Help is available in the configuration.nix(5) man page # your system. Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running nixos-help). # and in the NixOS manual (accessible by running nixos-help).
{ config, pkgs, lib, ... }: {
config,
pkgs,
lib,
...
}:
{ {
imports = imports = [
[ # Include the results of the hardware scan.
# Include the results of the hardware scan. ./hardware-configuration.nix
./hardware-configuration.nix # Fonts
# Fonts ../modules/personal/fonts
../modules/personal/fonts # Encrypted DNS
# Encrypted DNS ../modules/services/edns
../modules/services/edns # Override base mesa
# Override base mesa (
({ ... }: { nixpkgs.overlays = lib.mkBefore [ (final: prev: { mesa = prev.mesa.override { enableOpenCL = true; meson = final.unstable.meson; }; }) ]; }) { ... }:
]; {
nixpkgs.overlays = lib.mkBefore [
(final: prev: {
mesa = prev.mesa.override {
enableOpenCL = true;
meson = final.unstable.meson;
};
})
];
}
)
];
# time.timeZone = lib.mkForce "Asia/Ho_Chi_Minh"; # time.timeZone = lib.mkForce "Asia/Ho_Chi_Minh";
services.xserver.desktopManager.plasma5.enable = true; services.xserver.desktopManager.plasma5.enable = true;
# Asahi kernel configuration # Asahi kernel configuration
hardware.asahi = { hardware.asahi = {
peripheralFirmwareDirectory = ./firmware; peripheralFirmwareDirectory = ./firmware;
@ -46,9 +61,9 @@
hash = "sha256-IcKKe1RA8sCaUfWK71ELzF15YaBS3DjoYhNMIWiQ5Jw="; hash = "sha256-IcKKe1RA8sCaUfWK71ELzF15YaBS3DjoYhNMIWiQ5Jw=";
}; };
patches = lib.forEach attrs.patches (p: patches = lib.forEach attrs.patches (
if lib.hasSuffix "opencl.patch" p p: if lib.hasSuffix "opencl.patch" p then ./mesa-asahi-edge/opencl.patch else p
then ./mesa-asahi-edge/opencl.patch else p); );
}); });
}) })
]; ];
@ -145,4 +160,3 @@
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "22.05"; # Did you read the comment? system.stateVersion = "22.05"; # Did you read the comment?
} }

View file

@ -1,33 +1,39 @@
# Do not modify this file! It was generated by nixos-generate-config # Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes # and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead. # to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }: {
config,
lib,
pkgs,
modulesPath,
...
}:
{ {
imports = imports = [
[ (modulesPath + "/installer/scan/not-detected.nix")
(modulesPath + "/installer/scan/not-detected.nix") ];
];
boot.initrd.availableKernelModules = [ "usb_storage" ]; boot.initrd.availableKernelModules = [ "usb_storage" ];
boot.initrd.kernelModules = [ ]; boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ]; boot.kernelModules = [ ];
boot.extraModulePackages = [ ]; boot.extraModulePackages = [ ];
fileSystems."/" = fileSystems."/" = {
{ device = "/dev/disk/by-uuid/ebb6bf2e-2d7f-4fa6-88cb-751fdd174ef9";
device = "/dev/disk/by-uuid/ebb6bf2e-2d7f-4fa6-88cb-751fdd174ef9"; fsType = "ext4";
fsType = "ext4"; };
};
fileSystems."/boot" = fileSystems."/boot" = {
{ device = "/dev/disk/by-uuid/19BC-1BE8";
device = "/dev/disk/by-uuid/19BC-1BE8"; fsType = "vfat";
fsType = "vfat"; };
};
swapDevices = [ swapDevices = [
{ device = "/swap"; size = 16 * 1024; } {
device = "/swap";
size = 16 * 1024;
}
]; ];
# nixpkgs.hostPlatform = lib.mkDefault "aarch64-linux"; # nixpkgs.hostPlatform = lib.mkDefault "aarch64-linux";

View file

@ -1,11 +1,15 @@
{ pkgs, config, lib, ... }: {
pkgs,
config,
lib,
...
}:
with lib; with lib;
let let
cfg = config.cloud.authentik; cfg = config.cloud.authentik;
mkImage = mkImage = { imageName, imageDigest, ... }: "${imageName}@${imageDigest}";
{ imageName, imageDigest, ... }: "${imageName}@${imageDigest}";
# If we can pullImage we can just do # If we can pullImage we can just do
# mkImage = pkgs.dockerTools.pullImage; # mkImage = pkgs.dockerTools.pullImage;
@ -62,7 +66,10 @@ in
image = images.postgresql; image = images.postgresql;
restart = "unless-stopped"; restart = "unless-stopped";
healthcheck = { healthcheck = {
test = [ "CMD-SHELL" "pg_isready -d $\${POSTGRES_DB} -U $\${POSTGRES_USER}" ]; test = [
"CMD-SHELL"
"pg_isready -d $\${POSTGRES_DB} -U $\${POSTGRES_USER}"
];
start_period = "20s"; start_period = "20s";
interval = "30s"; interval = "30s";
retries = 5; retries = 5;
@ -73,14 +80,20 @@ in
POSTGRES_USER = "authentik"; POSTGRES_USER = "authentik";
POSTGRES_DB = "authentik"; POSTGRES_DB = "authentik";
}; };
env_file = [ cfg.envFile "${postgresEnv}" ]; env_file = [
cfg.envFile
"${postgresEnv}"
];
}; };
services.redis.service = { services.redis.service = {
image = images.redis; image = images.redis;
command = "--save 60 1 --loglevel warning"; command = "--save 60 1 --loglevel warning";
restart = "unless-stopped"; restart = "unless-stopped";
healthcheck = { healthcheck = {
test = [ "CMD-SHELL" "redis-cli ping | grep PONG" ]; test = [
"CMD-SHELL"
"redis-cli ping | grep PONG"
];
start_period = "20s"; start_period = "20s";
interval = "30s"; interval = "30s";
retries = 5; retries = 5;
@ -102,7 +115,10 @@ in
AUTHENTIK_POSTGRESQL__USER = "authentik"; AUTHENTIK_POSTGRESQL__USER = "authentik";
AUTHENTIK_POSTGRESQL__NAME = "authentik"; AUTHENTIK_POSTGRESQL__NAME = "authentik";
}; };
env_file = [ cfg.envFile "${authentikEnv}" ]; env_file = [
cfg.envFile
"${authentikEnv}"
];
ports = [ ports = [
"127.0.0.1:${toString cfg.port}:9000" "127.0.0.1:${toString cfg.port}:9000"
]; ];
@ -124,7 +140,10 @@ in
AUTHENTIK_POSTGRESQL__USER = "authentik"; AUTHENTIK_POSTGRESQL__USER = "authentik";
AUTHENTIK_POSTGRESQL__NAME = "authentik"; AUTHENTIK_POSTGRESQL__NAME = "authentik";
}; };
env_file = [ cfg.envFile "${authentikEnv}" ]; env_file = [
cfg.envFile
"${authentikEnv}"
];
user = "root"; user = "root";
}; };
docker-compose.volumes = { docker-compose.volumes = {
@ -134,4 +153,3 @@ in
}; };
}; };
} }

View file

@ -1,4 +1,9 @@
{ pkgs, lib, config, ... }: {
pkgs,
lib,
config,
...
}:
with lib; with lib;
let let

View file

@ -1,4 +1,9 @@
{ pkgs, config, lib, ... }: {
pkgs,
config,
lib,
...
}:
let let
cfg = config.cloud.conduit; cfg = config.cloud.conduit;
@ -33,95 +38,105 @@ with lib;
}; };
instances = mkOption { instances = mkOption {
type = types.attrsOf (types.submodule { type = types.attrsOf (
options = { types.submodule {
host = mkOption { options = {
type = types.str; host = mkOption {
type = types.str;
};
server_name = mkOption {
type = types.str;
default = "";
};
port = mkOption {
type = types.int;
};
noCloudflare = mkOption {
type = types.bool;
default = false;
};
allow_registration = mkOption {
type = types.bool;
default = false;
};
well-known_port = mkOption {
type = types.int;
};
}; };
server_name = mkOption { }
type = types.str; );
default = "";
};
port = mkOption {
type = types.int;
};
noCloudflare = mkOption {
type = types.bool;
default = false;
};
allow_registration = mkOption {
type = types.bool;
default = false;
};
well-known_port = mkOption {
type = types.int;
};
};
});
}; };
}; };
config.systemd.services = mkIf cfg.enable config.systemd.services = mkIf cfg.enable (
(lib.attrsets.mapAttrs' lib.attrsets.mapAttrs' (
(name: instance: lib.attrsets.nameValuePair "matrix-conduit-${name}" name: instance:
( lib.attrsets.nameValuePair "matrix-conduit-${name}" (
let let
srvName = "matrix-conduit-${name}"; srvName = "matrix-conduit-${name}";
format = pkgs.formats.toml { }; format = pkgs.formats.toml { };
server_name = if instance.server_name == "" then instance.host else instance.server_name; server_name = if instance.server_name == "" then instance.host else instance.server_name;
configFile = format.generate "conduit.toml" (lib.attrsets.recursiveUpdate defaultConfig { configFile = format.generate "conduit.toml" (
lib.attrsets.recursiveUpdate defaultConfig {
global.server_name = server_name; global.server_name = server_name;
global.port = instance.port; global.port = instance.port;
global.allow_registration = instance.allow_registration; global.allow_registration = instance.allow_registration;
global.database_path = "/mnt/data/${srvName}/"; global.database_path = "/mnt/data/${srvName}/";
global.well_known_client = "https://${instance.host}"; global.well_known_client = "https://${instance.host}";
global.well_known_server = "${instance.host}:443"; global.well_known_server = "${instance.host}:443";
}); }
in );
{ in
description = "Conduit Matrix Server (for ${server_name})"; {
documentation = [ "https://gitlab.com/famedly/conduit/" ]; description = "Conduit Matrix Server (for ${server_name})";
wantedBy = [ "multi-user.target" ]; documentation = [ "https://gitlab.com/famedly/conduit/" ];
environment = { CONDUIT_CONFIG = configFile; }; wantedBy = [ "multi-user.target" ];
serviceConfig = { environment = {
DynamicUser = true; CONDUIT_CONFIG = configFile;
User = "${srvName}"; };
LockPersonality = true; serviceConfig = {
MemoryDenyWriteExecute = true; DynamicUser = true;
ProtectClock = true; User = "${srvName}";
ProtectControlGroups = true; LockPersonality = true;
ProtectHostname = true; MemoryDenyWriteExecute = true;
ProtectKernelLogs = true; ProtectClock = true;
ProtectKernelModules = true; ProtectControlGroups = true;
ProtectKernelTunables = true; ProtectHostname = true;
PrivateDevices = true; ProtectKernelLogs = true;
PrivateMounts = true; ProtectKernelModules = true;
PrivateUsers = true; ProtectKernelTunables = true;
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ]; PrivateDevices = true;
RestrictNamespaces = true; PrivateMounts = true;
RestrictRealtime = true; PrivateUsers = true;
SystemCallArchitectures = "native"; RestrictAddressFamilies = [
SystemCallFilter = [ "AF_INET"
"@system-service" "AF_INET6"
"~@privileged" ];
]; RestrictNamespaces = true;
# StateDirectory = "/mnt/data/${srvName}"; RestrictRealtime = true;
BindPaths = [ "/mnt/data/${srvName}" ]; SystemCallArchitectures = "native";
ExecStart = "${cfg.package}/bin/conduit"; SystemCallFilter = [
Restart = "on-failure"; "@system-service"
RestartSec = 10; "~@privileged"
StartLimitBurst = 5; ];
}; # StateDirectory = "/mnt/data/${srvName}";
} BindPaths = [ "/mnt/data/${srvName}" ];
)) ExecStart = "${cfg.package}/bin/conduit";
cfg.instances); Restart = "on-failure";
RestartSec = 10;
StartLimitBurst = 5;
};
}
)
) cfg.instances
);
config.cloud.traefik.hosts = mkIf cfg.enable ( config.cloud.traefik.hosts = mkIf cfg.enable (
(lib.attrsets.mapAttrs' (lib.attrsets.mapAttrs' (
(name: instance: lib.attrsets.nameValuePair "conduit-${name}" ({ name: instance:
lib.attrsets.nameValuePair "conduit-${name}" ({
inherit (instance) host port noCloudflare; inherit (instance) host port noCloudflare;
})) })
cfg.instances) ) cfg.instances)
); );
} }

View file

@ -1,9 +1,15 @@
{ pkgs, lib, config, ... }: {
pkgs,
lib,
config,
...
}:
let let
cfg = config.cloud.conduit.heisenbridge; cfg = config.cloud.conduit.heisenbridge;
cfgConduit = config.cloud.conduit; cfgConduit = config.cloud.conduit;
in in
with lib; { with lib;
{
options.cloud.conduit.heisenbridge = { options.cloud.conduit.heisenbridge = {
enable = mkEnableOption "Enable heisenbridge for conduit"; enable = mkEnableOption "Enable heisenbridge for conduit";
package = mkPackageOption pkgs "heisenbridge" { }; package = mkPackageOption pkgs "heisenbridge" { };
@ -23,17 +29,26 @@ with lib; {
}; };
config = mkIf cfg.enable ( config = mkIf cfg.enable (
let let
cfgFile = if cfg.port == null then cfg.appserviceFile else cfgFile =
pkgs.runCommand "heisenbridge-config" { } '' if cfg.port == null then
cp ${cfg.appserviceFile} $out cfg.appserviceFile
${pkgs.sd}/bin/sd '^url: .*$' "url: http://127.0.0.1:${cfg.port}" else
''; pkgs.runCommand "heisenbridge-config" { } ''
listenArgs = lists.optionals (cfg.port != null) [ "--listen-port" (toString cfg.port) ]; cp ${cfg.appserviceFile} $out
${pkgs.sd}/bin/sd '^url: .*$' "url: http://127.0.0.1:${cfg.port}"
'';
listenArgs = lists.optionals (cfg.port != null) [
"--listen-port"
(toString cfg.port)
];
in in
{ {
systemd.services.heisenbridge = { systemd.services.heisenbridge = {
description = "Matrix<->IRC bridge"; description = "Matrix<->IRC bridge";
requires = [ "matrix-conduit-nkagami.service" "matrix-synapse.service" ]; # So the registration file can be used by Synapse requires = [
"matrix-conduit-nkagami.service"
"matrix-synapse.service"
]; # So the registration file can be used by Synapse
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
serviceConfig = rec { serviceConfig = rec {
@ -77,12 +92,18 @@ with lib; {
RemoveIPC = true; RemoveIPC = true;
UMask = "0077"; UMask = "0077";
CapabilityBoundingSet = [ "CAP_CHOWN" ] ++ optional (cfg.port != null && cfg.port < 1024) "CAP_NET_BIND_SERVICE"; CapabilityBoundingSet = [
"CAP_CHOWN"
] ++ optional (cfg.port != null && cfg.port < 1024) "CAP_NET_BIND_SERVICE";
AmbientCapabilities = CapabilityBoundingSet; AmbientCapabilities = CapabilityBoundingSet;
NoNewPrivileges = true; NoNewPrivileges = true;
LockPersonality = true; LockPersonality = true;
RestrictRealtime = true; RestrictRealtime = true;
SystemCallFilter = [ "@system-service" "~@privileged" "@chown" ]; SystemCallFilter = [
"@system-service"
"~@privileged"
"@chown"
];
SystemCallArchitectures = "native"; SystemCallArchitectures = "native";
RestrictAddressFamilies = "AF_INET AF_INET6"; RestrictAddressFamilies = "AF_INET AF_INET6";
}; };
@ -97,4 +118,3 @@ with lib; {
} }
); );
} }

View file

@ -1,11 +1,15 @@
{ pkgs, config, lib, ... }: {
pkgs,
config,
lib,
...
}:
with lib; with lib;
let let
cfg = config.cloud.firezone; cfg = config.cloud.firezone;
mkImage = mkImage = { imageName, imageDigest, ... }: "${imageName}@${imageDigest}";
{ imageName, imageDigest, ... }: "${imageName}@${imageDigest}";
# If we can pullImage we can just do # If we can pullImage we can just do
# mkImage = pkgs.dockerTools.pullImage; # mkImage = pkgs.dockerTools.pullImage;
@ -48,7 +52,10 @@ in
image = images.postgresql; image = images.postgresql;
restart = "unless-stopped"; restart = "unless-stopped";
healthcheck = { healthcheck = {
test = [ "CMD-SHELL" "pg_isready -d $\${POSTGRES_DB} -U $\${POSTGRES_USER}" ]; test = [
"CMD-SHELL"
"pg_isready -d $\${POSTGRES_DB} -U $\${POSTGRES_USER}"
];
start_period = "20s"; start_period = "20s";
interval = "30s"; interval = "30s";
retries = 5; retries = 5;
@ -89,7 +96,10 @@ in
driver = "bridge"; driver = "bridge";
ipam.config = [ ipam.config = [
{ subnet = "172.25.0.0/16"; } { subnet = "172.25.0.0/16"; }
{ subnet = "2001:3990:3990::/64"; gateway = "2001:3990:3990::1"; } {
subnet = "2001:3990:3990::/64";
gateway = "2001:3990:3990::1";
}
]; ];
}; };
}; };

View file

@ -1,4 +1,9 @@
{ pkgs, config, lib, ... }: {
pkgs,
config,
lib,
...
}:
with lib; with lib;
let let
cfg = config.cloud.gotosocial; cfg = config.cloud.gotosocial;
@ -41,13 +46,21 @@ in
# Postgres # Postgres
cloud.postgresql.databases = [ dbUser ]; cloud.postgresql.databases = [ dbUser ];
# Traefik # Traefik
cloud.traefik.hosts = { gotosocial = { inherit (cfg) host port; }; } // cloud.traefik.hosts =
(if cfg.accountDomain != cfg.host && cfg.accountDomain != "" then { {
gotosocial-wellknown = { gotosocial = { inherit (cfg) host port; };
inherit (cfg) port; }
filter = "Host(`${cfg.accountDomain}`) && (PathPrefix(`/.well-known/webfinger`) || PathPrefix(`/.well-known/nodeinfo`) || PathPrefix(`/.well-known/host-meta`))"; // (
}; if cfg.accountDomain != cfg.host && cfg.accountDomain != "" then
} else { }); {
gotosocial-wellknown = {
inherit (cfg) port;
filter = "Host(`${cfg.accountDomain}`) && (PathPrefix(`/.well-known/webfinger`) || PathPrefix(`/.well-known/nodeinfo`) || PathPrefix(`/.well-known/host-meta`))";
};
}
else
{ }
);
# The service itself # The service itself
services.gotosocial = { services.gotosocial = {
enable = true; enable = true;
@ -60,7 +73,10 @@ in
bind-address = "localhost"; bind-address = "localhost";
port = cfg.port; port = cfg.port;
# Instance # Instance
instance-languages = [ "en-ca" "vi" ]; instance-languages = [
"en-ca"
"vi"
];
# Accounts # Accounts
accounts-registration-open = false; accounts-registration-open = false;
accounts-allow-custom-css = true; accounts-allow-custom-css = true;
@ -73,15 +89,23 @@ in
web-template-base-dir = "${cfg.package}/share/gotosocial/web/template"; web-template-base-dir = "${cfg.package}/share/gotosocial/web/template";
web-asset-base-dir = "${cfg.package}/share/gotosocial/web/assets"; web-asset-base-dir = "${cfg.package}/share/gotosocial/web/assets";
# Media # Media
media-emoji-remote-max-size = 256 * 1024 /* bytes */; media-emoji-remote-max-size =
media-emoji-local-max-size = 256 * 1024 /* bytes */; 256 * 1024 # bytes
;
media-emoji-local-max-size =
256 * 1024 # bytes
;
media-remote-cache-days = 7; media-remote-cache-days = 7;
media-cleanup-from = "00:00"; media-cleanup-from = "00:00";
media-cleanup-every = "24h"; media-cleanup-every = "24h";
# OIDC # OIDC
oidc-enabled = true; oidc-enabled = true;
oidc-idp-name = "DTTH"; oidc-idp-name = "DTTH";
oidc-scopes = [ "openid" "email" "profile" ]; oidc-scopes = [
"openid"
"email"
"profile"
];
# HTTP Client # HTTP Client
http-client.block-ips = [ "11.0.0.0/24" ]; http-client.block-ips = [ "11.0.0.0/24" ];
# Advanced # Advanced
@ -92,8 +116,14 @@ in
# instance-inject-mastodon-version = true; # instance-inject-mastodon-version = true;
}; };
}; };
systemd.services.gotosocial.requires = mkAfter [ "postgresql.service" "arion-authentik.service" ]; systemd.services.gotosocial.requires = mkAfter [
systemd.services.gotosocial.after = mkAfter [ "postgresql.service" "arion-authentik.service" ]; "postgresql.service"
"arion-authentik.service"
];
systemd.services.gotosocial.after = mkAfter [
"postgresql.service"
"arion-authentik.service"
];
systemd.services.gotosocial.unitConfig = { systemd.services.gotosocial.unitConfig = {
RequiresMountsFor = [ storageLocation ]; RequiresMountsFor = [ storageLocation ];
ReadWritePaths = [ storageLocation ]; ReadWritePaths = [ storageLocation ];

View file

@ -1,4 +1,9 @@
{ config, pkgs, lib, ... }: {
config,
pkgs,
lib,
...
}:
with lib; with lib;
let let
@ -238,7 +243,12 @@ in
# MTA-STS server # MTA-STS server
services.nginx.enable = true; services.nginx.enable = true;
services.nginx.virtualHosts.maddy-mta-sts = { services.nginx.virtualHosts.maddy-mta-sts = {
listen = [{ addr = "127.0.0.1"; port = mtaStsPort; }]; listen = [
{
addr = "127.0.0.1";
port = mtaStsPort;
}
];
root = mtaStsDir; root = mtaStsDir;
}; };
@ -273,7 +283,10 @@ in
# maddy itself # maddy itself
systemd.services."${name}" = { systemd.services."${name}" = {
after = [ "network.target" "traefik-certs-dumper.service" ]; after = [
"network.target"
"traefik-certs-dumper.service"
];
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
requires = [ "postgresql.service" ]; requires = [ "postgresql.service" ];
@ -327,7 +340,6 @@ in
KillMode = "mixed"; KillMode = "mixed";
KillSignal = "SIGTERM"; KillSignal = "SIGTERM";
# Required to bind on ports lower than 1024. # Required to bind on ports lower than 1024.
AmbientCapabilities = "CAP_NET_BIND_SERVICE"; AmbientCapabilities = "CAP_NET_BIND_SERVICE";
CapabilityBoundingSet = "CAP_NET_BIND_SERVICE"; CapabilityBoundingSet = "CAP_NET_BIND_SERVICE";

View file

@ -1,4 +1,9 @@
{ pkgs, config, lib, ... }: {
pkgs,
config,
lib,
...
}:
with lib; with lib;
let let

View file

@ -1,4 +1,9 @@
{ pkgs, config, lib, ... }: {
pkgs,
config,
lib,
...
}:
with lib; with lib;
let let

View file

@ -1,4 +1,9 @@
{ pkgs, lib, config, ... }: {
pkgs,
lib,
config,
...
}:
with lib; with lib;
let let
@ -9,126 +14,169 @@ let
}; };
# Copied from traefik.nix # Copied from traefik.nix
jsonValue = with types; jsonValue =
with types;
let let
valueType = nullOr valueType =
(oneOf [ nullOr (oneOf [
bool bool
int int
float float
str str
(lazyAttrsOf valueType) (lazyAttrsOf valueType)
(listOf valueType) (listOf valueType)
]) // { ])
description = "JSON value"; // {
emptyValue.value = { }; description = "JSON value";
}; emptyValue.value = { };
};
in in
valueType; valueType;
hostType = with types; submodule { hostType =
options = { with types;
host = mkOption { submodule {
type = str; options = {
description = "The host for the router filter"; host = mkOption {
}; type = str;
path = mkOption { description = "The host for the router filter";
type = nullOr str; };
default = null; path = mkOption {
description = "The path for the router filter (exact path is matched)"; type = nullOr str;
}; default = null;
filter = mkOption { description = "The path for the router filter (exact path is matched)";
type = nullOr str; };
default = null; filter = mkOption {
description = "The filter syntax for the router. Overrides `host` and `path` if provided"; type = nullOr str;
}; default = null;
localHost = mkOption { description = "The filter syntax for the router. Overrides `host` and `path` if provided";
type = types.nullOr types.str; };
description = "The local host of the service. Must be an IP if protocol is TCP. Default to localhost/127.0.0.1"; localHost = mkOption {
default = null; type = types.nullOr types.str;
}; description = "The local host of the service. Must be an IP if protocol is TCP. Default to localhost/127.0.0.1";
port = mkOption { default = null;
type = types.port; };
description = "The port that the service is listening on"; port = mkOption {
}; type = types.port;
entrypoints = mkOption { description = "The port that the service is listening on";
type = listOf (enum [ "http" "https" "smtp-submission" "smtp-submission-ssl" "imap" "wireguard" ]); };
default = [ "https" ]; entrypoints = mkOption {
description = "The entrypoints that will serve the host"; type = listOf (enum [
}; "http"
middlewares = mkOption { "https"
type = listOf jsonValue; "smtp-submission"
default = [ ]; "smtp-submission-ssl"
description = "The middlewares to be used with the host."; "imap"
}; "wireguard"
protocol = mkOption { ]);
type = enum [ "http" "tcp" "udp" ]; default = [ "https" ];
default = "http"; description = "The entrypoints that will serve the host";
description = "The protocol of the router and service"; };
}; middlewares = mkOption {
tlsPassthrough = mkOption { type = listOf jsonValue;
type = types.bool; default = [ ];
default = true; description = "The middlewares to be used with the host.";
description = "Sets the TCP passthrough value. Defaults to `true` if the connection is tcp"; };
}; protocol = mkOption {
noCloudflare = mkOption { type = enum [
type = types.bool; "http"
default = false; "tcp"
description = "Bypasses the client cert requirement, enable if you don't route things through cloudflare"; "udp"
];
default = "http";
description = "The protocol of the router and service";
};
tlsPassthrough = mkOption {
type = types.bool;
default = true;
description = "Sets the TCP passthrough value. Defaults to `true` if the connection is tcp";
};
noCloudflare = mkOption {
type = types.bool;
default = false;
description = "Bypasses the client cert requirement, enable if you don't route things through cloudflare";
};
}; };
}; };
};
# Returns the filter given a host configuration # Returns the filter given a host configuration
filterOfHost = host: filterOfHost =
host:
let let
hostFilter = if host.protocol == "http" then "Host" else "HostSNI"; hostFilter = if host.protocol == "http" then "Host" else "HostSNI";
in in
if host.filter != null then host.filter if host.filter != null then
else if host.path == null then "${hostFilter}(`${host.host}`)" host.filter
else "${hostFilter}(`${host.host}`) && Path(`${host.path}`)"; else if host.path == null then
"${hostFilter}(`${host.host}`)"
else
"${hostFilter}(`${host.host}`) && Path(`${host.path}`)";
# Turns a host configuration into dynamic traefik configuration # Turns a host configuration into dynamic traefik configuration
hostToConfig = name: host: { hostToConfig = name: host: {
"${host.protocol}" = { "${host.protocol}" =
routers."${name}-router" = (if (host.protocol != "udp") then { {
rule = filterOfHost host; routers."${name}-router" =
tls = { certResolver = "le"; } (
// (if host.protocol == "tcp" then { passthrough = if (host ? tlsPassthrough) then host.tlsPassthrough else true; } else { }) if (host.protocol != "udp") then
// (if host.noCloudflare then tlsNoCloudflare else { }); {
} else { }) // { rule = filterOfHost host;
entryPoints = host.entrypoints; tls =
service = "${name}-service"; {
} // ( certResolver = "le";
if host.protocol == "http" then }
{ middlewares = lists.imap0 (id: m: "${name}-middleware-${toString id}") host.middlewares; } // (
else if host.middlewares == [ ] then if host.protocol == "tcp" then
{ passthrough = if (host ? tlsPassthrough) then host.tlsPassthrough else true; }
else
{ }
)
// (if host.noCloudflare then tlsNoCloudflare else { });
}
else
{ }
)
// {
entryPoints = host.entrypoints;
service = "${name}-service";
}
// (
if host.protocol == "http" then
{ middlewares = lists.imap0 (id: m: "${name}-middleware-${toString id}") host.middlewares; }
else if host.middlewares == [ ] then
{ }
else
abort "Cannot have middlewares on non-http routers"
);
services."${name}-service".loadBalancer.servers = [
(
let
localhost =
if isNull host.localHost then
(if host.protocol == "http" then "localhost" else "127.0.0.1")
else
host.localHost;
in
if host.protocol == "http" then
{ url = "http://${localhost}:${toString host.port}"; }
else
{ address = "${localhost}:${toString host.port}"; }
)
];
}
// (
if (host.middlewares != [ ]) then
{
middlewares = builtins.listToAttrs (
lists.imap0 (id: v: {
name = "${name}-middleware-${toString id}";
value = v;
}) host.middlewares
);
}
else
{ } { }
else abort "Cannot have middlewares on non-http routers"
); );
services."${name}-service".loadBalancer.servers = [
(
let
localhost =
if isNull host.localHost then
(
if host.protocol == "http" then "localhost"
else "127.0.0.1"
) else host.localHost;
in
if host.protocol == "http" then
{ url = "http://${localhost}:${toString host.port}"; }
else { address = "${localhost}:${toString host.port}"; }
)
];
} // (if (host.middlewares != [ ]) then {
middlewares = builtins.listToAttrs (lists.imap0
(id: v: {
name = "${name}-middleware-${toString id}";
value = v;
})
host.middlewares);
} else { });
}; };
tlsConfig = { tlsConfig = {

View file

@ -1,4 +1,9 @@
{ pkgs, config, lib, ... }: {
pkgs,
config,
lib,
...
}:
with lib; with lib;
let let
@ -28,7 +33,8 @@ in
# Dynamic configuration # Dynamic configuration
# --------------------- # ---------------------
## Middleware ## Middleware
services.traefik.dynamicConfigOptions.http.middlewares.dashboard-auth.basicAuth.usersFile = cfg.usersFile; services.traefik.dynamicConfigOptions.http.middlewares.dashboard-auth.basicAuth.usersFile =
cfg.usersFile;
## Router ## Router
services.traefik.dynamicConfigOptions.http.routers.dashboard = { services.traefik.dynamicConfigOptions.http.routers.dashboard = {
rule = "Host(`${cfg.host}`)"; rule = "Host(`${cfg.host}`)";

View file

@ -1,22 +1,29 @@
{ pkgs, config, lib, ... }: {
pkgs,
config,
lib,
...
}:
with lib; with lib;
let let
# Copied from traefik.nix # Copied from traefik.nix
jsonValue = with types; jsonValue =
with types;
let let
valueType = nullOr valueType =
(oneOf [ nullOr (oneOf [
bool bool
int int
float float
str str
(lazyAttrsOf valueType) (lazyAttrsOf valueType)
(listOf valueType) (listOf valueType)
]) // { ])
description = "JSON value"; // {
emptyValue.value = { }; description = "JSON value";
}; emptyValue.value = { };
};
in in
valueType; valueType;
@ -41,7 +48,11 @@ let
cfg = config.cloud.traefik; cfg = config.cloud.traefik;
in in
{ {
imports = [ ./config.nix ./dashboard.nix ./certs-dumper.nix ]; imports = [
./config.nix
./dashboard.nix
./certs-dumper.nix
];
options.cloud.traefik = { options.cloud.traefik = {
cloudflareKeyFile = mkOption { cloudflareKeyFile = mkOption {
type = types.path; type = types.path;
@ -104,7 +115,12 @@ in
config.systemd.services.traefik.environment.CF_DNS_API_TOKEN_FILE = cfg.cloudflareKeyFile; config.systemd.services.traefik.environment.CF_DNS_API_TOKEN_FILE = cfg.cloudflareKeyFile;
# Set up firewall to allow traefik traffic. # Set up firewall to allow traefik traffic.
config.networking.firewall.allowedTCPPorts = [ 443 993 587 465 ]; config.networking.firewall.allowedTCPPorts = [
443
993
587
465
];
config.networking.firewall.allowedUDPPorts = [ config.networking.firewall.allowedUDPPorts = [
443 # QUIC 443 # QUIC
51820 # Wireguard 51820 # Wireguard

View file

@ -1,4 +1,9 @@
{ config, pkgs, lib, ... }: {
config,
pkgs,
lib,
...
}:
with lib; with lib;
let let
cfg = config.cloud.writefreely; cfg = config.cloud.writefreely;
@ -62,4 +67,3 @@ in
} }
); );
} }

View file

@ -1,4 +1,9 @@
{ pkgs, config, lib, ... }: {
pkgs,
config,
lib,
...
}:
with lib; with lib;
let let
@ -6,118 +11,142 @@ let
# Modules # Modules
modules = { modules = {
adb = { config, ... }: mkIf config.common.linux.enable { adb =
services.udev.packages = with pkgs; [ android-udev-rules ]; { config, ... }:
programs.adb.enable = true; mkIf config.common.linux.enable {
users.users.${config.common.linux.username}.extraGroups = [ "adbusers" ]; services.udev.packages = with pkgs; [ android-udev-rules ];
}; programs.adb.enable = true;
ios = { config, pkgs, ... }: mkIf config.common.linux.enable { users.users.${config.common.linux.username}.extraGroups = [ "adbusers" ];
services.usbmuxd.enable = true;
services.usbmuxd.package = pkgs.usbmuxd2;
environment.systemPackages = with pkgs; [
libimobiledevice
ifuse
];
users.users.${config.common.linux.username}.extraGroups = [ config.services.usbmuxd.group ];
systemd.network.networks."05-ios-tethering" = {
matchConfig.Driver = "ipheth";
networkConfig.DHCP = "yes";
linkConfig.RequiredForOnline = "no";
}; };
}; ios =
{ config, pkgs, ... }:
graphics = { config, pkgs, ... }: { mkIf config.common.linux.enable {
hardware.graphics.enable = true; services.usbmuxd.enable = true;
hardware.graphics.enable32Bit = true; services.usbmuxd.package = pkgs.usbmuxd2;
# Monitor backlight environment.systemPackages = with pkgs; [
hardware.i2c.enable = true; libimobiledevice
services.ddccontrol.enable = true; ifuse
environment.systemPackages = [ pkgs.luminance pkgs.ddcutil ]; ];
}; users.users.${config.common.linux.username}.extraGroups = [ config.services.usbmuxd.group ];
systemd.network.networks."05-ios-tethering" = {
accounts = { pkgs, ... }: mkIf (config.common.linux.enable && !pkgs.stdenv.isAarch64) { matchConfig.Driver = "ipheth";
environment.systemPackages = [ pkgs.glib (pkgs.gnome-control-center or pkgs.gnome.gnome-control-center) ]; networkConfig.DHCP = "yes";
services.accounts-daemon.enable = true; linkConfig.RequiredForOnline = "no";
services.gnome.gnome-online-accounts.enable = true; };
# programs.evolution.enable = true;
# programs.evolution.plugins = with pkgs; [ evolution-ews ];
# services.gnome.evolution-data-server.enable = true;
# services.gnome.evolution-data-server.plugins = with pkgs; [ evolution-ews ];
};
wlr = { lib, config, ... }: mkIf config.common.linux.enable {
# swaync disable notifications on screencast
xdg.portal.wlr.settings.screencast = {
exec_before = ''which swaync-client && swaync-client --inhibitor-add "xdg-desktop-portal-wlr" || true'';
exec_after = ''which swaync-client && swaync-client --inhibitor-remove "xdg-desktop-portal-wlr" || true'';
}; };
# Niri stuff graphics =
# https://github.com/sodiboo/niri-flake/blob/main/docs.md { config, pkgs, ... }:
programs.niri.enable = true; {
programs.niri.package = pkgs.niri-stable; hardware.graphics.enable = true;
# Override gnome-keyring disabling hardware.graphics.enable32Bit = true;
services.gnome.gnome-keyring.enable = lib.mkForce false; # Monitor backlight
}; hardware.i2c.enable = true;
services.ddccontrol.enable = true;
logitech = { pkgs, ... }: mkIf cfg.enable { environment.systemPackages = [
services.ratbagd.enable = true; pkgs.luminance
environment.systemPackages = with pkgs; [ piper ]; pkgs.ddcutil
}; ];
kwallet = { pkgs, lib, ... }: mkIf cfg.enable {
environment.systemPackages = [ pkgs.kdePackages.kwallet ];
services.dbus.packages = [ pkgs.kdePackages.kwallet ];
xdg.portal = {
extraPortals = [ pkgs.kdePackages.kwallet ];
}; };
};
virtualisation = { pkgs, ... }: mkIf cfg.enable { accounts =
virtualisation.podman = { { pkgs, ... }:
mkIf (config.common.linux.enable && !pkgs.stdenv.isAarch64) {
environment.systemPackages = [
pkgs.glib
(pkgs.gnome-control-center or pkgs.gnome.gnome-control-center)
];
services.accounts-daemon.enable = true;
services.gnome.gnome-online-accounts.enable = true;
# programs.evolution.enable = true;
# programs.evolution.plugins = with pkgs; [ evolution-ews ];
# services.gnome.evolution-data-server.enable = true;
# services.gnome.evolution-data-server.plugins = with pkgs; [ evolution-ews ];
};
wlr =
{ lib, config, ... }:
mkIf config.common.linux.enable {
# swaync disable notifications on screencast
xdg.portal.wlr.settings.screencast = {
exec_before = ''which swaync-client && swaync-client --inhibitor-add "xdg-desktop-portal-wlr" || true'';
exec_after = ''which swaync-client && swaync-client --inhibitor-remove "xdg-desktop-portal-wlr" || true'';
};
# Niri stuff
# https://github.com/sodiboo/niri-flake/blob/main/docs.md
programs.niri.enable = true;
programs.niri.package = pkgs.niri-stable;
# Override gnome-keyring disabling
services.gnome.gnome-keyring.enable = lib.mkForce false;
};
logitech =
{ pkgs, ... }:
mkIf cfg.enable {
services.ratbagd.enable = true;
environment.systemPackages = with pkgs; [ piper ];
};
kwallet =
{ pkgs, lib, ... }:
mkIf cfg.enable {
environment.systemPackages = [ pkgs.kdePackages.kwallet ];
services.dbus.packages = [ pkgs.kdePackages.kwallet ];
xdg.portal = {
extraPortals = [ pkgs.kdePackages.kwallet ];
};
};
virtualisation =
{ pkgs, ... }:
mkIf cfg.enable {
virtualisation.podman = {
enable = true;
extraPackages = [ pkgs.slirp4netns ];
dockerCompat = true;
defaultNetwork.settings.dns_enabled = true;
};
virtualisation.oci-containers.backend = "podman";
virtualisation.virtualbox.host.enable = false;
users.extraGroups.vboxusers.members = [ cfg.username ];
};
};
rt-audio =
{ pkgs, ... }:
mkIf cfg.enable {
services.pipewire.lowLatency = {
# enable this module
enable = true; enable = true;
extraPackages = [ pkgs.slirp4netns ]; # defaults (no need to be set unless modified)
dockerCompat = true; quantum = 32;
defaultNetwork.settings.dns_enabled = true; rate = 44100;
}; };
security.rtkit.enable = true;
virtualisation.oci-containers.backend = "podman"; # Real time configurations
boot.kernel.sysctl = {
virtualisation.virtualbox.host.enable = false; "vm.swappiness" = 10;
users.extraGroups.vboxusers.members = [ cfg.username ]; "fs.inotify.max_user_watches" = 524288;
};
security.pam.loginLimits = [
{
domain = "@audio";
item = "rtprio";
type = "-";
value = "90";
}
{
domain = "@audio";
item = "memlock";
type = "-";
value = "unlimited";
}
];
}; };
};
rt-audio = { pkgs, ... }: mkIf cfg.enable {
services.pipewire.lowLatency = {
# enable this module
enable = true;
# defaults (no need to be set unless modified)
quantum = 32;
rate = 44100;
};
security.rtkit.enable = true;
# Real time configurations
boot.kernel.sysctl = {
"vm.swappiness" = 10;
"fs.inotify.max_user_watches" = 524288;
};
security.pam.loginLimits = [
{
domain = "@audio";
item = "rtprio";
type = "-";
value = "90";
}
{
domain = "@audio";
item = "memlock";
type = "-";
value = "unlimited";
}
];
};
in in
{ {
imports = with modules; [ imports = with modules; [
@ -155,23 +184,30 @@ in
dnsServers = mkOption { dnsServers = mkOption {
type = types.listOf types.str; type = types.listOf types.str;
description = "DNS server list"; description = "DNS server list";
default = [ "1.1.1.1" "2606:4700:4700:1111" ]; default = [
"1.1.1.1"
"2606:4700:4700:1111"
];
}; };
networks = mkOption { networks = mkOption {
type = types.attrsOf (types.submodule { type = types.attrsOf (
options.match = mkOption { types.submodule {
type = types.str; options.match = mkOption {
description = "The interface name to match"; type = types.str;
}; description = "The interface name to match";
options.isRequired = mkOption { };
type = types.bool; options.isRequired = mkOption {
description = "Require this interface to be connected for network-online.target"; type = types.bool;
default = false; description = "Require this interface to be connected for network-online.target";
}; default = false;
}); };
}
);
description = "Network configuration"; description = "Network configuration";
default = { default = {
default = { match = "*"; }; default = {
match = "*";
};
}; };
}; };
}; };
@ -196,18 +232,16 @@ in
}; };
boot.initrd.systemd.enable = builtins.length (builtins.attrNames (cfg.luksDevices)) > 0; boot.initrd.systemd.enable = builtins.length (builtins.attrNames (cfg.luksDevices)) > 0;
# LUKS devices # LUKS devices
boot.initrd.luks.devices = builtins.mapAttrs boot.initrd.luks.devices = builtins.mapAttrs (name: path: {
(name: path: { device = path;
device = path; preLVM = true;
preLVM = true; allowDiscards = true;
allowDiscards = true;
crypttabExtraOpts = [ crypttabExtraOpts = [
"tpm2-device=auto" "tpm2-device=auto"
"fido2-device=auto" "fido2-device=auto"
]; ];
}) }) cfg.luksDevices;
cfg.luksDevices;
## Hardware-related ## Hardware-related
@ -251,7 +285,10 @@ in
]; ];
shell = pkgs.fish; shell = pkgs.fish;
}; };
nix.settings.trusted-users = [ "root" cfg.username ]; nix.settings.trusted-users = [
"root"
cfg.username
];
## Network configuration ## Network configuration
systemd.network.enable = true; systemd.network.enable = true;
@ -262,13 +299,11 @@ in
networking.hostName = cfg.networking.hostname; networking.hostName = cfg.networking.hostname;
networking.wireless.iwd.enable = true; networking.wireless.iwd.enable = true;
networking.wireless.iwd.settings.General.EnableNetworkConfiguration = true; networking.wireless.iwd.settings.General.EnableNetworkConfiguration = true;
systemd.network.networks = builtins.mapAttrs systemd.network.networks = builtins.mapAttrs (name: cfg: {
(name: cfg: { matchConfig.Name = cfg.match;
matchConfig.Name = cfg.match; networkConfig.DHCP = "yes";
networkConfig.DHCP = "yes"; linkConfig.RequiredForOnline = if cfg.isRequired then "yes" else "no";
linkConfig.RequiredForOnline = if cfg.isRequired then "yes" else "no"; }) cfg.networking.networks;
})
cfg.networking.networks;
# Leave DNS to systemd-resolved # Leave DNS to systemd-resolved
services.resolved.enable = true; services.resolved.enable = true;
services.resolved.domains = cfg.networking.dnsServers; services.resolved.domains = cfg.networking.dnsServers;
@ -285,19 +320,26 @@ in
console.keyMap = "jp106"; # Console key layout console.keyMap = "jp106"; # Console key layout
i18n.defaultLocale = "ja_JP.UTF-8"; i18n.defaultLocale = "ja_JP.UTF-8";
# Input methods (only fcitx5 works reliably on Wayland) # Input methods (only fcitx5 works reliably on Wayland)
i18n.inputMethod = { i18n.inputMethod =
fcitx5.waylandFrontend = true; {
fcitx5.addons = with pkgs; [ fcitx5.waylandFrontend = true;
fcitx5-mozc fcitx5.addons = with pkgs; [
fcitx5-unikey fcitx5-mozc
fcitx5-gtk fcitx5-unikey
]; fcitx5-gtk
} // (if config.system.nixos.release == "24.05" then { ];
enabled = "fcitx5"; }
} else { // (
enable = true; if config.system.nixos.release == "24.05" then
type = "fcitx5"; {
}); enabled = "fcitx5";
}
else
{
enable = true;
type = "fcitx5";
}
);
# Default packages # Default packages
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
@ -335,7 +377,10 @@ in
programs.gamescope = { programs.gamescope = {
enable = true; enable = true;
# capSysNice = true; # https://github.com/NixOS/nixpkgs/issues/351516 # capSysNice = true; # https://github.com/NixOS/nixpkgs/issues/351516
args = [ "--adaptive-sync" "--rt" ]; args = [
"--adaptive-sync"
"--rt"
];
}; };
## Services ## Services
@ -353,11 +398,22 @@ in
wlr.enable = true; wlr.enable = true;
xdgOpenUsePortal = true; xdgOpenUsePortal = true;
# gtk portal needed to make gtk apps happy # gtk portal needed to make gtk apps happy
extraPortals = [ pkgs.kdePackages.xdg-desktop-portal-kde pkgs.xdg-desktop-portal-gtk ]; extraPortals = [
pkgs.kdePackages.xdg-desktop-portal-kde
pkgs.xdg-desktop-portal-gtk
];
config.sway.default = [ "wlr" "kde" "kwallet" ]; config.sway.default = [
"wlr"
"kde"
"kwallet"
];
config.niri = { config.niri = {
default = [ "kde" "gnome" "gtk" ]; default = [
"kde"
"gnome"
"gtk"
];
# "org.freedesktop.impl.portal.Access" = "gtk"; # "org.freedesktop.impl.portal.Access" = "gtk";
# "org.freedesktop.impl.portal.Notification" = "gtk"; # "org.freedesktop.impl.portal.Notification" = "gtk";
"org.freedesktop.impl.portal.ScreenCast" = "gnome"; "org.freedesktop.impl.portal.ScreenCast" = "gnome";

View file

@ -1,4 +1,9 @@
{ config, pkgs, lib, ... }: {
config,
pkgs,
lib,
...
}:
with lib; with lib;
let let
@ -36,72 +41,89 @@ in
}; };
}; };
config = mkIf cfg.enable (builtins.seq config = mkIf cfg.enable (
(mkIf (isNull cfg.rsaPrivateKey && isNull cfg.ed25519PrivateKey) (builtins.abort "one of the keys must be defined")) builtins.seq
( (mkIf (isNull cfg.rsaPrivateKey && isNull cfg.ed25519PrivateKey) (
let builtins.abort "one of the keys must be defined"
networkName = "my-tinc"; ))
(
let
networkName = "my-tinc";
myHost = builtins.getAttr cfg.hostName hosts; myHost = builtins.getAttr cfg.hostName hosts;
myMeshIp = myHost.subnetAddr; myMeshIp = myHost.subnetAddr;
in in
{ {
# Scripts that set up the tinc services # Scripts that set up the tinc services
environment.etc = { environment.etc = {
"tinc/${networkName}/tinc-up".source = pkgs.writeScript "tinc-up-${networkName}" '' "tinc/${networkName}/tinc-up".source = pkgs.writeScript "tinc-up-${networkName}" ''
#!${pkgs.stdenv.shell} #!${pkgs.stdenv.shell}
${pkgs.nettools}/bin/ifconfig $INTERFACE ${myMeshIp} netmask 255.255.255.0 ${pkgs.nettools}/bin/ifconfig $INTERFACE ${myMeshIp} netmask 255.255.255.0
''; '';
"tinc/${networkName}/tinc-down".source = pkgs.writeScript "tinc-down-${networkName}" '' "tinc/${networkName}/tinc-down".source = pkgs.writeScript "tinc-down-${networkName}" ''
#!${pkgs.stdenv.shell} #!${pkgs.stdenv.shell}
/run/wrappers/bin/sudo ${pkgs.nettools}/bin/ifconfig $INTERFACE down /run/wrappers/bin/sudo ${pkgs.nettools}/bin/ifconfig $INTERFACE down
''; '';
}; };
# Allow the tinc service to call ifconfig without sudo password. # Allow the tinc service to call ifconfig without sudo password.
security.sudo.extraRules = [ security.sudo.extraRules = [
{ {
users = [ "tinc.${networkName}" ]; users = [ "tinc.${networkName}" ];
commands = [ commands = [
{
command = "${pkgs.nettools}/bin/ifconfig";
options = [ "NOPASSWD" ];
}
];
}
];
# simple interface setup
# ----------------------
networking.interfaces."tinc.${networkName}".ipv4.addresses = [
{
address = myMeshIp;
prefixLength = 24;
}
];
# firewall
networking.firewall.allowedUDPPorts = [ 655 ];
networking.firewall.allowedTCPPorts = [ 655 ];
networking.firewall.interfaces."tinc.${networkName}" = {
allowedUDPPortRanges = [
{ {
command = "${pkgs.nettools}/bin/ifconfig"; from = 0;
options = [ "NOPASSWD" ]; to = 65535;
} }
]; ];
} allowedTCPPortRanges = [
]; {
from = 0;
to = 65535;
}
];
};
# simple interface setup # configure tinc service
# ---------------------- # ----------------------
networking.interfaces."tinc.${networkName}".ipv4.addresses = [{ address = myMeshIp; prefixLength = 24; }]; services.tinc.networks."${networkName}" = {
# firewall name = cfg.hostName; # who are we in this network.
networking.firewall.allowedUDPPorts = [ 655 ];
networking.firewall.allowedTCPPorts = [ 655 ];
networking.firewall.interfaces."tinc.${networkName}" = {
allowedUDPPortRanges = [{ from = 0; to = 65535; }];
allowedTCPPortRanges = [{ from = 0; to = 65535; }];
};
debugLevel = 3; # the debug level for journal -u tinc.private
chroot = false; # otherwise addresses can't be a DNS
interfaceType = "tap"; # tun might also work.
# configure tinc service bindToAddress = "* ${toString cfg.bindPort}";
# ----------------------
services.tinc.networks."${networkName}" = {
name = cfg.hostName; # who are we in this network. ed25519PrivateKeyFile = cfg.ed25519PrivateKey;
rsaPrivateKeyFile = cfg.rsaPrivateKey;
debugLevel = 3; # the debug level for journal -u tinc.private settings.ExperimentalProtocol = "yes";
chroot = false; # otherwise addresses can't be a DNS };
interfaceType = "tap"; # tun might also work. }
)
bindToAddress = "* ${toString cfg.bindPort}";
ed25519PrivateKeyFile = cfg.ed25519PrivateKey;
rsaPrivateKeyFile = cfg.rsaPrivateKey;
settings.ExperimentalProtocol = "yes";
};
}
)
); );
} }

View file

@ -1,4 +1,9 @@
{ config, pkgs, lib, ... }: {
config,
pkgs,
lib,
...
}:
with lib; with lib;
let let
@ -6,30 +11,34 @@ let
cfg = config.services.my-tinc; cfg = config.services.my-tinc;
mapAttrs = f: attrs: builtins.listToAttrs ( mapAttrs =
map (name: { inherit name; value = f name (builtins.getAttr name attrs); }) (builtins.attrNames attrs) f: attrs:
); builtins.listToAttrs (
map (name: {
inherit name;
value = f name (builtins.getAttr name attrs);
}) (builtins.attrNames attrs)
);
in in
{ {
config = mkIf cfg.enable { config = mkIf cfg.enable {
# All hosts we know of # All hosts we know of
services.tinc.networks.my-tinc.hostSettings = mapAttrs services.tinc.networks.my-tinc.hostSettings = mapAttrs (name: host: {
(name: host: { addresses = if (host ? address) then [ { address = host.address; } ] else [ ];
addresses = if (host ? address) then [{ address = host.address; }] else [ ]; subnets = [ { address = host.subnetAddr; } ];
subnets = [{ address = host.subnetAddr; }]; rsaPublicKey = mkIf (host ? "rsaPublicKey") host.rsaPublicKey;
rsaPublicKey = mkIf (host ? "rsaPublicKey") host.rsaPublicKey; settings.Ed25519PublicKey = mkIf (host ? "ed25519PublicKey") host.ed25519PublicKey;
settings.Ed25519PublicKey = mkIf (host ? "ed25519PublicKey") host.ed25519PublicKey; }) hosts;
})
hosts;
# Add all of them to host # Add all of them to host
nki.services.edns = { nki.services.edns = {
enable = true; enable = true;
cloaking-rules = cloaking-rules = (
(lib.attrsets.mapAttrs' lib.attrsets.mapAttrs' (name: host: {
(name: host: { name = "${name}.tinc"; value = host.subnetAddr; }) name = "${name}.tinc";
hosts) value = host.subnetAddr;
; }) hosts
);
}; };
}; };
} }

View file

@ -1,4 +1,9 @@
{ pkgs, lib, config, ... }: {
pkgs,
lib,
config,
...
}:
with lib; with lib;
let let
@ -11,46 +16,76 @@ in
{ {
imports = [ ./mounting.nix ]; imports = [ ./mounting.nix ];
# Fonts # Fonts
config.fonts = { config.fonts =
packages = with pkgs; mkForce [ {
noto-fonts-emoji-blob-bin packages =
ibm-plex with pkgs;
nerd-fonts mkForce [
noto-fonts noto-fonts-emoji-blob-bin
(pkgs.noto-fonts-cjk-sans or pkgs.noto-fonts-cjk) ibm-plex
merriweather nerd-fonts
corefonts noto-fonts
font-awesome (pkgs.noto-fonts-cjk-sans or pkgs.noto-fonts-cjk)
hack-font # for Plasma merriweather
]; corefonts
} // (if pkgs.stdenv.isLinux then { font-awesome
enableDefaultPackages = false; hack-font # for Plasma
fontconfig = { ];
defaultFonts = { }
emoji = lib.mkBefore [ "Blobmoji" ]; // (
serif = lib.mkBefore [ "IBM Plex Serif" "IBM Plex Sans JP" "IBM Plex Sans KR" "Blobmoji" ]; if pkgs.stdenv.isLinux then
sansSerif = lib.mkBefore [ "IBM Plex Sans" "IBM Plex Sans JP" "IBM Plex Sans KR" "Blobmoji" ]; {
monospace = lib.mkBefore [ "IBM Plex Mono" "Font Awesome 6 Free" "Symbols Nerd Font" "Blobmoji" "IBM Plex Sans JP" ]; enableDefaultPackages = false;
}; fontconfig = {
localConf = '' defaultFonts = {
<?xml version="1.0"?> emoji = lib.mkBefore [ "Blobmoji" ];
<!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd"> serif = lib.mkBefore [
<fontconfig> "IBM Plex Serif"
<alias binding="same"> "IBM Plex Sans JP"
<family>system-ui</family> "IBM Plex Sans KR"
<prefer> "Blobmoji"
<family>IBM Plex Sans</family> ];
<family>IBM Plex Sans JP</family> sansSerif = lib.mkBefore [
<family>IBM Plex Sans KR</family> "IBM Plex Sans"
<family>Blobmoji</family> "IBM Plex Sans JP"
</prefer> "IBM Plex Sans KR"
</alias> "Blobmoji"
</fontconfig> ];
''; monospace = lib.mkBefore [
}; "IBM Plex Mono"
fontDir.enable = true; "Font Awesome 6 Free"
} else { }) // (if pkgs.stdenv.isDarwin then { "Symbols Nerd Font"
fontDir.enable = true; "Blobmoji"
} else { }); "IBM Plex Sans JP"
];
};
localConf = ''
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd">
<fontconfig>
<alias binding="same">
<family>system-ui</family>
<prefer>
<family>IBM Plex Sans</family>
<family>IBM Plex Sans JP</family>
<family>IBM Plex Sans KR</family>
<family>Blobmoji</family>
</prefer>
</alias>
</fontconfig>
'';
};
fontDir.enable = true;
}
else
{ }
)
// (
if pkgs.stdenv.isDarwin then
{
fontDir.enable = true;
}
else
{ }
);
} }

View file

@ -1,4 +1,9 @@
{ pkgs, config, lib, ... }: {
pkgs,
config,
lib,
...
}:
lib.mkIf pkgs.stdenv.isLinux { lib.mkIf pkgs.stdenv.isLinux {
system.fsPackages = [ pkgs.bindfs ]; system.fsPackages = [ pkgs.bindfs ];
fileSystems = fileSystems =
@ -6,7 +11,11 @@ lib.mkIf pkgs.stdenv.isLinux {
mkRoSymBind = path: { mkRoSymBind = path: {
device = path; device = path;
fsType = "fuse.bindfs"; fsType = "fuse.bindfs";
options = [ "ro" "resolve-symlinks" "x-gvfs-hide" ]; options = [
"ro"
"resolve-symlinks"
"x-gvfs-hide"
];
}; };
aggregatedIcons = pkgs.buildEnv { aggregatedIcons = pkgs.buildEnv {
name = "system-icons"; name = "system-icons";

View file

@ -1,4 +1,9 @@
{ config, pkgs, lib, ... }: {
config,
pkgs,
lib,
...
}:
with lib; with lib;
let let

View file

@ -1,4 +1,9 @@
{ pkgs, config, lib, ... }: {
pkgs,
config,
lib,
...
}:
with lib; with lib;
let let
@ -34,7 +39,10 @@ in
# Sources # Sources
sources.public_resolvers = { sources.public_resolvers = {
urls = [ "https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v3/public-resolvers.md" "https://download.dnscrypt.info/resolvers-list/v3/public-resolvers.md" ]; urls = [
"https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v3/public-resolvers.md"
"https://download.dnscrypt.info/resolvers-list/v3/public-resolvers.md"
];
cache_file = "/var/lib/dnscrypt-proxy/public_resolvers.md"; cache_file = "/var/lib/dnscrypt-proxy/public_resolvers.md";
minisign_key = "RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3"; minisign_key = "RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3";
}; };
@ -44,14 +52,22 @@ in
# Anonymized DNS # Anonymized DNS
anonymized_dns.routes = [ anonymized_dns.routes = [
{ server_name = "*"; via = [ "anon-plan9-dns" "anon-v.dnscrypt.up-ipv4" ]; } {
server_name = "*";
via = [
"anon-plan9-dns"
"anon-v.dnscrypt.up-ipv4"
];
}
]; ];
anonymized_dns.skip_incompatible = true; anonymized_dns.skip_incompatible = true;
# Cloaking rules # Cloaking rules
cloaking_rules = pkgs.writeText "cloaking_rules.txt" (lib.strings.concatStringsSep cloaking_rules = pkgs.writeText "cloaking_rules.txt" (
"\n" lib.strings.concatStringsSep "\n" (
(lib.attrsets.mapAttrsToList (name: ip: "${name} ${ip}") cfg.cloaking-rules)); lib.attrsets.mapAttrsToList (name: ip: "${name} ${ip}") cfg.cloaking-rules
)
);
}; };
}; };
}; };

View file

@ -40,20 +40,24 @@ in
in in
{ {
nix.distributedBuilds = true; nix.distributedBuilds = true;
nix.buildMachines = lib.mapAttrsToList nix.buildMachines = lib.mapAttrsToList (
(name: host: { name: host:
{
hostName = host.host; hostName = host.host;
sshUser = build-user; sshUser = build-user;
sshKey = cfg.privateKeyFile; sshKey = cfg.privateKeyFile;
} // host.builder) }
otherBuilders; // host.builder
) otherBuilders;
users = mkIf (isBuilder host) { users = mkIf (isBuilder host) {
users.${build-user} = { users.${build-user} = {
description = "Nix build farm user"; description = "Nix build farm user";
group = build-user; group = build-user;
isNormalUser = true; isNormalUser = true;
openssh.authorizedKeys.keys = lib.mapAttrsToList (_: host: ''from="${cfg.ipAddrs}" ${host.pubKey}'') otherHosts; openssh.authorizedKeys.keys = lib.mapAttrsToList (
_: host: ''from="${cfg.ipAddrs}" ${host.pubKey}''
) otherHosts;
}; };
groups.${build-user} = { }; groups.${build-user} = { };
}; };
@ -62,5 +66,3 @@ in
} }
); );
} }

View file

@ -10,10 +10,18 @@
builder = { builder = {
publicHostKey = "c3NoLWVkMjU1MTkgQUFBQUMzTnphQzFsWkRJMU5URTVBQUFBSUhiVTh2NlNBa0kyOTBCc1QzVG1IRVVJQWdXcVFyNm9jRmpjakRRczRoT2ggcm9vdEBrYWdhbWlQQwo="; publicHostKey = "c3NoLWVkMjU1MTkgQUFBQUMzTnphQzFsWkRJMU5URTVBQUFBSUhiVTh2NlNBa0kyOTBCc1QzVG1IRVVJQWdXcVFyNm9jRmpjakRRczRoT2ggcm9vdEBrYWdhbWlQQwo=";
systems = [ "x86_64-linux" "aarch64-linux" ]; systems = [
"x86_64-linux"
"aarch64-linux"
];
maxJobs = 16; maxJobs = 16;
speedFactor = 2; speedFactor = 2;
supportedFeatures = [ "nixos-test" "benchmark" "big-parallel" "kvm" ]; supportedFeatures = [
"nixos-test"
"benchmark"
"big-parallel"
"kvm"
];
}; };
}; };
@ -28,10 +36,18 @@
builder = { builder = {
publicHostKey = "c3NoLWVkMjU1MTkgQUFBQUMzTnphQzFsWkRJMU5URTVBQUFBSUdOUlBCVFRkNTVVMXY1U1Jac0FjYVdhS3JGZTY0ZjIxOVViODVTQ2NWd28gcm9vdEBua2ktZnJhbWV3b3JrCg=="; publicHostKey = "c3NoLWVkMjU1MTkgQUFBQUMzTnphQzFsWkRJMU5URTVBQUFBSUdOUlBCVFRkNTVVMXY1U1Jac0FjYVdhS3JGZTY0ZjIxOVViODVTQ2NWd28gcm9vdEBua2ktZnJhbWV3b3JrCg==";
systems = [ "x86_64-linux" "aarch64-linux" ]; systems = [
"x86_64-linux"
"aarch64-linux"
];
maxJobs = 16; maxJobs = 16;
speedFactor = 3; speedFactor = 3;
supportedFeatures = [ "nixos-test" "benchmark" "big-parallel" "kvm" ]; supportedFeatures = [
"nixos-test"
"benchmark"
"big-parallel"
"kvm"
];
}; };
}; };
} }

View file

@ -1,6 +1,18 @@
{ config, pkgs, lib, ... }: {
config,
pkgs,
lib,
...
}:
with { inherit (lib) mkEnableOption mkOption types mkIf; }; with {
inherit (lib)
mkEnableOption
mkOption
types
mkIf
;
};
let let
cfg = config.nki.services.nix-cache; cfg = config.nki.services.nix-cache;

View file

@ -1,4 +1,9 @@
{ config, pkgs, lib, ... }: {
config,
pkgs,
lib,
...
}:
with lib; with lib;
let let
cfg = config.services.swaylock; cfg = config.services.swaylock;

View file

@ -2,26 +2,32 @@
# your system. Help is available in the configuration.nix(5) man page # your system. Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running nixos-help). # and in the NixOS manual (accessible by running nixos-help).
{ config, pkgs, lib, ... }: {
config,
pkgs,
lib,
...
}:
{ {
imports = imports = [
[ # Include the results of the hardware scan.
# Include the results of the hardware scan. ./hardware-configuration.nix
./hardware-configuration.nix # Fonts
# Fonts ../modules/personal/fonts
../modules/personal/fonts # Encrypted DNS
# Encrypted DNS ../modules/services/edns
../modules/services/edns # Wireless card
# Wireless card ./wireless.nix
./wireless.nix ];
];
# Sops # Sops
common.linux.sops.enable = true; common.linux.sops.enable = true;
common.linux.sops.file = ./secrets.yaml; common.linux.sops.file = ./secrets.yaml;
sops.secrets."nix-build-farm/private-key" = { mode = "0400"; }; sops.secrets."nix-build-farm/private-key" = {
mode = "0400";
};
services.nix-build-farm.hostname = "framework"; services.nix-build-farm.hostname = "framework";
services.nix-build-farm.privateKeyFile = config.sops.secrets."nix-build-farm/private-key".path; services.nix-build-farm.privateKeyFile = config.sops.secrets."nix-build-farm/private-key".path;
@ -94,7 +100,6 @@
bindPort = 6565; bindPort = 6565;
}; };
# Secrets # Secrets
# sops.defaultSopsFile = ./secrets.yaml; # sops.defaultSopsFile = ./secrets.yaml;
# sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ]; # sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
@ -129,4 +134,3 @@
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "22.05"; # Did you read the comment? system.stateVersion = "22.05"; # Did you read the comment?
} }

View file

@ -1,15 +1,26 @@
# Do not modify this file! It was generated by nixos-generate-config # Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes # and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead. # to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }: {
config,
lib,
pkgs,
modulesPath,
...
}:
{ {
imports = imports = [
[ (modulesPath + "/installer/scan/not-detected.nix")
(modulesPath + "/installer/scan/not-detected.nix") ];
];
boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "thunderbolt" "usb_storage" "sd_mod" ]; boot.initrd.availableKernelModules = [
"nvme"
"xhci_pci"
"thunderbolt"
"usb_storage"
"sd_mod"
];
boot.initrd.kernelModules = [ ]; boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-amd" ]; boot.kernelModules = [ "kvm-amd" ];
boot.kernelParams = [ boot.kernelParams = [
@ -18,12 +29,14 @@
"resume_offset=5776640" # btrfs inspect-internal map-swapfile -r /var/swapfile "resume_offset=5776640" # btrfs inspect-internal map-swapfile -r /var/swapfile
]; ];
fileSystems."/" = fileSystems."/" = {
{ device = "/dev/disk/by-uuid/fa8aaf51-b99f-4fb4-9230-8c0957d8af3f";
device = "/dev/disk/by-uuid/fa8aaf51-b99f-4fb4-9230-8c0957d8af3f"; fsType = "btrfs";
fsType = "btrfs"; options = [
options = [ "subvol=root" "compress=zstd" ]; "subvol=root"
}; "compress=zstd"
];
};
services.btrfs.autoScrub = { services.btrfs.autoScrub = {
enable = true; enable = true;
interval = "monthly"; interval = "monthly";
@ -31,28 +44,35 @@
common.linux.luksDevices."cryptroot" = "/dev/disk/by-uuid/94226aae-6d1c-401a-bfad-3aa5f371a365"; common.linux.luksDevices."cryptroot" = "/dev/disk/by-uuid/94226aae-6d1c-401a-bfad-3aa5f371a365";
fileSystems."/home" = fileSystems."/home" = {
{ device = "/dev/disk/by-uuid/fa8aaf51-b99f-4fb4-9230-8c0957d8af3f";
device = "/dev/disk/by-uuid/fa8aaf51-b99f-4fb4-9230-8c0957d8af3f"; fsType = "btrfs";
fsType = "btrfs"; options = [
options = [ "subvol=home" "compress=zstd" ]; "subvol=home"
}; "compress=zstd"
];
};
fileSystems."/nix" = fileSystems."/nix" = {
{ device = "/dev/disk/by-uuid/fa8aaf51-b99f-4fb4-9230-8c0957d8af3f";
device = "/dev/disk/by-uuid/fa8aaf51-b99f-4fb4-9230-8c0957d8af3f"; fsType = "btrfs";
fsType = "btrfs"; options = [
options = [ "subvol=nix" "compress=zstd" ]; "subvol=nix"
}; "compress=zstd"
];
};
fileSystems."/boot" = fileSystems."/boot" = {
{ device = "/dev/disk/by-uuid/6A0E-4D23";
device = "/dev/disk/by-uuid/6A0E-4D23"; fsType = "vfat";
fsType = "vfat"; };
};
swapDevices = [ swapDevices = [
{ device = "/var/swapfile"; size = 32 * 1024; priority = 10; } {
device = "/var/swapfile";
size = 32 * 1024;
priority = 10;
}
]; ];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking # Enables DHCP on each ethernet and wireless interface. In case of scripted networking

View file

@ -1,4 +1,5 @@
{ pkgs, lib, ... }: { { pkgs, lib, ... }:
{
environment.systemPackages = with pkgs; [ iw ]; environment.systemPackages = with pkgs; [ iw ];
# Disable power_save on boot # Disable power_save on boot
services.udev.packages = [ services.udev.packages = [

View file

@ -1,4 +1,10 @@
{ config, pkgs, lib, ... }: { {
config,
pkgs,
lib,
...
}:
{
environment.etc = { environment.etc = {
"wireplumber/wireplumber.conf.d/51-sdac.conf".source = ./sdac.conf.json; "wireplumber/wireplumber.conf.d/51-sdac.conf".source = ./sdac.conf.json;
}; };

View file

@ -2,33 +2,39 @@
# your system. Help is available in the configuration.nix(5) man page # your system. Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running nixos-help). # and in the NixOS manual (accessible by running nixos-help).
{ lib, config, pkgs, ... }: {
lib,
config,
pkgs,
...
}:
with lib; with lib;
let let
openrazer = { pkgs, ... }: { openrazer =
# Razer stuff { pkgs, ... }:
hardware.openrazer = { {
enable = true; # Razer stuff
users = [ "nki" ]; hardware.openrazer = {
enable = true;
users = [ "nki" ];
};
environment.systemPackages = with pkgs; [ polychromatic ];
}; };
environment.systemPackages = with pkgs; [ polychromatic ];
};
in in
{ {
imports = imports = [
[ # Include the results of the hardware scan.
# Include the results of the hardware scan. ./hardware-configuration.nix
./hardware-configuration.nix # Fonts
# Fonts ../modules/personal/fonts
../modules/personal/fonts # Encrypted DNS
# Encrypted DNS ../modules/services/edns
../modules/services/edns # Other services
# Other services ../modules/personal/u2f.nix
../modules/personal/u2f.nix ./peertube-runner.nix
./peertube-runner.nix openrazer
openrazer ];
];
# Kernel # Kernel
boot.kernelPackages = pkgs.linuxKernel.packages.linux_xanmod_stable; boot.kernelPackages = pkgs.linuxKernel.packages.linux_xanmod_stable;
@ -43,35 +49,48 @@ in
common.linux.sops.file = ./secrets.yaml; common.linux.sops.file = ./secrets.yaml;
# Nix cache server # Nix cache server
sops.secrets."nix-cache/private-key" = { owner = "harmonia"; group = "harmonia"; mode = "0600"; }; sops.secrets."nix-cache/private-key" = {
owner = "harmonia";
group = "harmonia";
mode = "0600";
};
nki.services.nix-cache = { nki.services.nix-cache = {
enableServer = true; enableServer = true;
privateKeyFile = config.sops.secrets."nix-cache/private-key".path; privateKeyFile = config.sops.secrets."nix-cache/private-key".path;
}; };
sops.secrets."nix-build-farm/private-key" = { mode = "0400"; }; sops.secrets."nix-build-farm/private-key" = {
mode = "0400";
};
services.nix-build-farm.hostname = "home"; services.nix-build-farm.hostname = "home";
services.nix-build-farm.privateKeyFile = config.sops.secrets."nix-build-farm/private-key".path; services.nix-build-farm.privateKeyFile = config.sops.secrets."nix-build-farm/private-key".path;
# Networking # Networking
common.linux.networking = common.linux.networking = {
{ hostname = "kagamiPC"; # Define your hostname.
hostname = "kagamiPC"; # Define your hostname. networks = {
networks = { "10-wired" = {
"10-wired" = { match = "enp*";
match = "enp*"; isRequired = true;
isRequired = true;
};
"20-wireless".match = "wlan*";
}; };
dnsServers = [ "127.0.0.1" ]; "20-wireless".match = "wlan*";
}; };
dnsServers = [ "127.0.0.1" ];
};
nki.services.edns.enable = true; nki.services.edns.enable = true;
nki.services.edns.ipv6 = true; nki.services.edns.ipv6 = true;
## DTTH Wireguard ## DTTH Wireguard
# #
sops.secrets."dtth-wg/private-key" = { owner = "root"; group = "systemd-network"; mode = "0640"; }; sops.secrets."dtth-wg/private-key" = {
sops.secrets."dtth-wg/preshared-key" = { owner = "root"; group = "systemd-network"; mode = "0640"; }; owner = "root";
group = "systemd-network";
mode = "0640";
};
sops.secrets."dtth-wg/preshared-key" = {
owner = "root";
group = "systemd-network";
mode = "0640";
};
systemd.network.netdevs."10-dtth-wg" = { systemd.network.netdevs."10-dtth-wg" = {
netdevConfig = { netdevConfig = {
Kind = "wireguard"; Kind = "wireguard";
@ -81,20 +100,31 @@ in
wireguardConfig = { wireguardConfig = {
PrivateKeyFile = config.sops.secrets."dtth-wg/private-key".path; PrivateKeyFile = config.sops.secrets."dtth-wg/private-key".path;
}; };
wireguardPeers = [{ wireguardPeers = [
PublicKey = "+7iI4jwmM1Qr+/DKB1Hv8JgFkGu7lSV0PAoo+O5d3yQ="; {
PresharedKeyFile = config.sops.secrets."dtth-wg/preshared-key".path; PublicKey = "+7iI4jwmM1Qr+/DKB1Hv8JgFkGu7lSV0PAoo+O5d3yQ=";
AllowedIPs = [ "100.64.0.0/10" "fd00::/106" ]; PresharedKeyFile = config.sops.secrets."dtth-wg/preshared-key".path;
Endpoint = "vpn.dtth.ch:51820"; AllowedIPs = [
PersistentKeepalive = 25; "100.64.0.0/10"
}]; "fd00::/106"
];
Endpoint = "vpn.dtth.ch:51820";
PersistentKeepalive = 25;
}
];
}; };
systemd.network.networks."dtth-wg" = { systemd.network.networks."dtth-wg" = {
matchConfig.Name = "dtth-wg"; matchConfig.Name = "dtth-wg";
address = [ "100.73.146.80/32" "fd00::33:105b/128" ]; address = [
"100.73.146.80/32"
"fd00::33:105b/128"
];
DHCP = "no"; DHCP = "no";
routes = [ routes = [
{ Destination = "100.64.0.0/10"; Scope = "link"; } {
Destination = "100.64.0.0/10";
Scope = "link";
}
{ Destination = "fd00::/106"; } { Destination = "fd00::/106"; }
]; ];
}; };
@ -117,7 +147,11 @@ in
ntfsMount = path: { ntfsMount = path: {
device = path; device = path;
fsType = "ntfs"; fsType = "ntfs";
options = [ "rw" "uid=${toString config.users.users.nki.uid}" "nofail" ]; options = [
"rw"
"uid=${toString config.users.users.nki.uid}"
"nofail"
];
}; };
in in
{ {
@ -149,7 +183,6 @@ in
bindPort = 6565; bindPort = 6565;
}; };
# Music server # Music server
services.navidrome.enable = true; services.navidrome.enable = true;
services.navidrome.settings = { services.navidrome.settings = {
@ -157,7 +190,10 @@ in
MusicFolder = "/mnt/Stuff/Music"; MusicFolder = "/mnt/Stuff/Music";
}; };
systemd.services.navidrome.serviceConfig.BindReadOnlyPaths = lib.mkAfter [ "/etc" ]; systemd.services.navidrome.serviceConfig.BindReadOnlyPaths = lib.mkAfter [ "/etc" ];
networking.firewall.allowedTCPPorts = [ 4533 8000 ]; networking.firewall.allowedTCPPorts = [
4533
8000
];
# Printers # Printers
services.printing.enable = true; services.printing.enable = true;
@ -201,4 +237,3 @@ in
virtualisation.spiceUSBRedirection.enable = true; virtualisation.spiceUSBRedirection.enable = true;
} }

View file

@ -1,42 +1,57 @@
# Do not modify this file! It was generated by nixos-generate-config # Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes # and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead. # to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }: {
config,
lib,
pkgs,
modulesPath,
...
}:
{ {
imports = imports = [
[ (modulesPath + "/installer/scan/not-detected.nix")
(modulesPath + "/installer/scan/not-detected.nix") ./audio
./audio ];
];
boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" ]; boot.initrd.availableKernelModules = [
boot.initrd.kernelModules = [ "dm-snapshot" "amdgpu" ]; "nvme"
"xhci_pci"
"ahci"
"usbhid"
"usb_storage"
"sd_mod"
];
boot.initrd.kernelModules = [
"dm-snapshot"
"amdgpu"
];
boot.kernelModules = [ "kvm-amd" ]; boot.kernelModules = [ "kvm-amd" ];
boot.extraModulePackages = [ ]; boot.extraModulePackages = [ ];
fileSystems."/" = fileSystems."/" = {
{ device = "/dev/disk/by-uuid/32a74827-4624-43ef-b066-b52e1f11793d";
device = "/dev/disk/by-uuid/32a74827-4624-43ef-b066-b52e1f11793d"; fsType = "ext4";
fsType = "ext4"; };
}; fileSystems."/home/nki/Projects" = {
fileSystems."/home/nki/Projects" = device = "/dev/disk/by-uuid/025cb533-e21b-47f2-b7d5-322b7b95b831";
{ fsType = "btrfs";
device = "/dev/disk/by-uuid/025cb533-e21b-47f2-b7d5-322b7b95b831"; options = [ "compress=zstd" ];
fsType = "btrfs"; };
options = [ "compress=zstd" ];
};
fileSystems."/boot" = fileSystems."/boot" = {
{ device = "/dev/disk/by-uuid/549C-7877";
device = "/dev/disk/by-uuid/549C-7877"; fsType = "vfat";
fsType = "vfat"; };
};
fileSystems."/mnt/steam" = { fileSystems."/mnt/steam" = {
device = "/dev/disk/by-uuid/d1db9f65-6add-4714-b9d7-16e16f687396"; device = "/dev/disk/by-uuid/d1db9f65-6add-4714-b9d7-16e16f687396";
fsType = "btrfs"; fsType = "btrfs";
options = [ "compress=zstd" "subvol=steam" ]; options = [
"compress=zstd"
"subvol=steam"
];
encrypted = { encrypted = {
enable = true; enable = true;
label = "encdata"; label = "encdata";
@ -45,8 +60,7 @@
}; };
}; };
swapDevices = swapDevices = [ { device = "/dev/disk/by-uuid/561f6441-1915-4059-a5e1-76a449b0c9bf"; } ];
[{ device = "/dev/disk/by-uuid/561f6441-1915-4059-a5e1-76a449b0c9bf"; }];
# bluetooth usb # bluetooth usb
hardware.firmware = [ pkgs.rtl8761b-firmware ]; hardware.firmware = [ pkgs.rtl8761b-firmware ];

View file

@ -1,4 +1,9 @@
{ config, pkgs, lib, ... }: {
config,
pkgs,
lib,
...
}:
let let
user = "peertube-runner-nodejs"; user = "peertube-runner-nodejs";
instance = "systemd-instance"; instance = "systemd-instance";
@ -27,8 +32,8 @@ in
runnerName = "kagamipc" runnerName = "kagamipc"
''; '';
environment.etc."${user}/${instance}/config.toml".source = config.sops.templates."peertube-config.toml".path; environment.etc."${user}/${instance}/config.toml".source =
config.sops.templates."peertube-config.toml".path;
systemd.services.peertube-runner = { systemd.services.peertube-runner = {
description = "PeerTube runner daemon"; description = "PeerTube runner daemon";
@ -36,20 +41,19 @@ in
after = [ "network.target" ]; after = [ "network.target" ];
requires = [ ]; requires = [ ];
serviceConfig = serviceConfig = {
{ ExecStart = "${lib.getExe' pkgs.peertube.runner "peertube-runner"} server --id ${instance}";
ExecStart = "${lib.getExe' pkgs.peertube.runner "peertube-runner"} server --id ${instance}"; User = user;
User = user; RuntimeDirectory = user;
RuntimeDirectory = user; StateDirectory = user;
StateDirectory = user; CacheDirectory = user;
CacheDirectory = user; # Hardening
# Hardening ProtectSystem = "full";
ProtectSystem = "full"; PrivateDevices = false;
PrivateDevices = false; NoNewPrivileges = true;
NoNewPrivileges = true; ProtectHome = true;
ProtectHome = true; CapabilityBoundingSet = "~CAP_SYS_ADMIN";
CapabilityBoundingSet = "~CAP_SYS_ADMIN"; };
};
environment = { environment = {
NODE_ENV = "production"; NODE_ENV = "production";
@ -61,7 +65,9 @@ in
XDG_STATE_HOME = "/var/lib"; XDG_STATE_HOME = "/var/lib";
}; };
path = with pkgs; [ nodejs ffmpeg ]; path = with pkgs; [
nodejs
ffmpeg
];
}; };
} }

View file

@ -1,4 +1,10 @@
{ pkgs, config, lib, ... }: { {
pkgs,
config,
lib,
...
}:
{
imports = [ imports = [
./hardware-configuration.nix ./hardware-configuration.nix
@ -88,13 +94,19 @@
services.my-tinc.rsaPrivateKey = config.sops.secrets."tinc/rsa-private-key".path; services.my-tinc.rsaPrivateKey = config.sops.secrets."tinc/rsa-private-key".path;
services.my-tinc.ed25519PrivateKey = config.sops.secrets."tinc/ed25519-private-key".path; services.my-tinc.ed25519PrivateKey = config.sops.secrets."tinc/ed25519-private-key".path;
sops.secrets."nix-build-farm/private-key" = { mode = "0400"; }; sops.secrets."nix-build-farm/private-key" = {
mode = "0400";
};
services.nix-build-farm.hostname = "home"; services.nix-build-farm.hostname = "home";
services.nix-build-farm.privateKeyFile = config.sops.secrets."nix-build-farm/private-key".path; services.nix-build-farm.privateKeyFile = config.sops.secrets."nix-build-farm/private-key".path;
# Set up traefik # Set up traefik
sops.secrets.cloudflare-dns-api-token = { owner = "traefik"; }; sops.secrets.cloudflare-dns-api-token = {
sops.secrets.traefik-dashboard-users = { owner = "traefik"; }; owner = "traefik";
};
sops.secrets.traefik-dashboard-users = {
owner = "traefik";
};
cloud.traefik.cloudflareKeyFile = config.sops.secrets.cloudflare-dns-api-token.path; cloud.traefik.cloudflareKeyFile = config.sops.secrets.cloudflare-dns-api-token.path;
cloud.traefik.dashboard = { cloud.traefik.dashboard = {
enable = true; enable = true;
@ -108,9 +120,19 @@
settings.HOST = "127.0.0.1"; settings.HOST = "127.0.0.1";
settings.PORT = "16904"; settings.PORT = "16904";
}; };
cloud.traefik.hosts.uptime-kuma = { host = "status.nkagami.me"; port = 16904; noCloudflare = true; }; cloud.traefik.hosts.uptime-kuma = {
cloud.traefik.hosts.uptime-kuma-dtth = { host = "status.dtth.ch"; port = 16904; }; host = "status.nkagami.me";
cloud.traefik.hosts.uptime-kuma-codefun = { host = "status.codefun.vn"; port = 16904; }; port = 16904;
noCloudflare = true;
};
cloud.traefik.hosts.uptime-kuma-dtth = {
host = "status.dtth.ch";
port = 16904;
};
cloud.traefik.hosts.uptime-kuma-codefun = {
host = "status.codefun.vn";
port = 16904;
};
# Bitwarden # Bitwarden
sops.secrets.vaultwarden-env = { }; sops.secrets.vaultwarden-env = { };
@ -120,7 +142,9 @@
virtualisation.arion.backend = "docker"; virtualisation.arion.backend = "docker";
# Conduit # Conduit
sops.secrets.heisenbridge = { owner = "heisenbridge"; }; sops.secrets.heisenbridge = {
owner = "heisenbridge";
};
cloud.conduit.enable = true; cloud.conduit.enable = true;
cloud.conduit.instances = { cloud.conduit.instances = {
"nkagami" = { "nkagami" = {
@ -155,7 +179,10 @@
}; };
# Mail # Mail
sops.secrets.mail-users = { owner = "maddy"; reloadUnits = [ "maddy.service" ]; }; sops.secrets.mail-users = {
owner = "maddy";
reloadUnits = [ "maddy.service" ];
};
cloud.mail = { cloud.mail = {
enable = true; enable = true;
debug = true; debug = true;
@ -177,7 +204,10 @@
sops.secrets.authentik-env = { }; sops.secrets.authentik-env = { };
cloud.authentik.enable = true; cloud.authentik.enable = true;
cloud.authentik.envFile = config.sops.secrets.authentik-env.path; cloud.authentik.envFile = config.sops.secrets.authentik-env.path;
cloud.traefik.hosts.authentik = { host = "auth.dtth.ch"; port = config.cloud.authentik.port; }; cloud.traefik.hosts.authentik = {
host = "auth.dtth.ch";
port = config.cloud.authentik.port;
};
# Firezone # Firezone
sops.secrets.firezone-env = { }; sops.secrets.firezone-env = { };
@ -197,14 +227,18 @@
}; };
# GoToSocial # GoToSocial
sops.secrets.gts-env = { restartUnits = [ "gotosocial.service" ]; }; sops.secrets.gts-env = {
restartUnits = [ "gotosocial.service" ];
};
cloud.gotosocial = { cloud.gotosocial = {
enable = true; enable = true;
envFile = config.sops.secrets.gts-env.path; envFile = config.sops.secrets.gts-env.path;
}; };
# Grist # Grist
sops.secrets."grist/env" = { restartUnits = [ "arion-grist.service" ]; }; sops.secrets."grist/env" = {
restartUnits = [ "arion-grist.service" ];
};
cloud.grist = { cloud.grist = {
enable = true; enable = true;
envFile = config.sops.secrets."grist/env".path; envFile = config.sops.secrets."grist/env".path;
@ -212,9 +246,12 @@
dataDir = "/mnt/data/grist"; dataDir = "/mnt/data/grist";
}; };
# ntfy # ntfy
cloud.traefik.hosts.ntfy-sh = { host = "ntfy.nkagami.me"; port = 11161; noCloudflare = true; }; cloud.traefik.hosts.ntfy-sh = {
host = "ntfy.nkagami.me";
port = 11161;
noCloudflare = true;
};
services.ntfy-sh = { services.ntfy-sh = {
enable = true; enable = true;
settings = { settings = {
@ -238,4 +275,3 @@
mkdir -p /var/lib/ntfy-sh/attachments mkdir -p /var/lib/ntfy-sh/attachments
''; '';
} }

View file

@ -1,4 +1,9 @@
{ pkgs, config, lib, ... }: {
pkgs,
config,
lib,
...
}:
with lib; with lib;
let let
user = "gitea"; user = "gitea";
@ -126,7 +131,11 @@ in
}; };
repository = { repository = {
DEFAULT_PRIVATE = "private"; DEFAULT_PRIVATE = "private";
PREFERRED_LICENSES = strings.concatStringsSep "," [ "AGPL-3.0-or-later" "GPL-3.0-or-later" "Apache-2.0" ]; PREFERRED_LICENSES = strings.concatStringsSep "," [
"AGPL-3.0-or-later"
"GPL-3.0-or-later"
"Apache-2.0"
];
# DISABLE_HTTP_GIT = true; # DISABLE_HTTP_GIT = true;
DEFAULT_BRANCH = "master"; DEFAULT_BRANCH = "master";
ENABLE_PUSH_CREATE_USER = true; ENABLE_PUSH_CREATE_USER = true;
@ -216,18 +225,17 @@ in
environment.GNUPGHOME = "${config.services.gitea.stateDir}/.gnupg"; environment.GNUPGHOME = "${config.services.gitea.stateDir}/.gnupg";
# https://github.com/NixOS/nixpkgs/commit/93c1d370db28ad4573fb9890c90164ba55391ce7 # https://github.com/NixOS/nixpkgs/commit/93c1d370db28ad4573fb9890c90164ba55391ce7
serviceConfig.SystemCallFilter = mkForce "~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @setuid @swap"; serviceConfig.SystemCallFilter = mkForce "~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @setuid @swap";
preStart = preStart = ''
'' # Import the signing subkey
# Import the signing subkey if cat ${config.services.forgejo.stateDir}/.gnupg/gpg.conf | grep -q ${signingKey}; then
if cat ${config.services.forgejo.stateDir}/.gnupg/gpg.conf | grep -q ${signingKey}; then echo "Keys already imported"
echo "Keys already imported" # imported
# imported else
else echo "Import your keys!"
echo "Import your keys!" ${pkgs.gnupg}/bin/gpg --quiet --import ${secrets."gitea/signing-key".path}
${pkgs.gnupg}/bin/gpg --quiet --import ${secrets."gitea/signing-key".path} echo "trusted-key ${signingKey}" >> ${config.services.forgejo.stateDir}/.gnupg/gpg.conf
echo "trusted-key ${signingKey}" >> ${config.services.forgejo.stateDir}/.gnupg/gpg.conf exit 1
exit 1 fi
fi '';
'';
}; };
} }

View file

@ -1,11 +1,15 @@
{ pkgs, config, lib, ... }: {
pkgs,
config,
lib,
...
}:
with lib; with lib;
let let
cfg = config.cloud.grist; cfg = config.cloud.grist;
mkImage = mkImage = { imageName, imageDigest, ... }: "${imageName}@${imageDigest}";
{ imageName, imageDigest, ... }: "${imageName}@${imageDigest}";
# If we can pullImage we can just do # If we can pullImage we can just do
# mkImage = pkgs.dockerTools.pullImage; # mkImage = pkgs.dockerTools.pullImage;
@ -24,7 +28,12 @@ let
}; };
}; };
defaultEnv = { defaultEnv = {
GRIST_HIDE_UI_ELEMENTS = lib.concatStringsSep "," [ "helpCenter" "billing" "multiAccounts" "supportGrist" ]; GRIST_HIDE_UI_ELEMENTS = lib.concatStringsSep "," [
"helpCenter"
"billing"
"multiAccounts"
"supportGrist"
];
GRIST_PAGE_TITLE_SUFFIX = " - DTTH Grist"; GRIST_PAGE_TITLE_SUFFIX = " - DTTH Grist";
GRIST_FORCE_LOGIN = "true"; GRIST_FORCE_LOGIN = "true";
GRIST_WIDGET_LIST_URL = "https://github.com/gristlabs/grist-widget/releases/download/latest/manifest.json"; GRIST_WIDGET_LIST_URL = "https://github.com/gristlabs/grist-widget/releases/download/latest/manifest.json";
@ -60,7 +69,11 @@ in
allowedWebhookDomains = mkOption { allowedWebhookDomains = mkOption {
type = types.listOf types.str; type = types.listOf types.str;
description = "List of domains to be allowed in webhooks"; description = "List of domains to be allowed in webhooks";
default = [ "dtth.ch" "nkagami.me" "discord.com" ]; default = [
"dtth.ch"
"nkagami.me"
"discord.com"
];
}; };
defaultEmail = mkOption { defaultEmail = mkOption {
type = types.str; type = types.str;
@ -105,7 +118,10 @@ in
command = "--save 60 1 --loglevel warning"; command = "--save 60 1 --loglevel warning";
restart = "unless-stopped"; restart = "unless-stopped";
healthcheck = { healthcheck = {
test = [ "CMD-SHELL" "valkey-cli ping | grep PONG" ]; test = [
"CMD-SHELL"
"valkey-cli ping | grep PONG"
];
start_period = "20s"; start_period = "20s";
interval = "30s"; interval = "30s";
retries = 5; retries = 5;
@ -124,4 +140,3 @@ in
}; };
}; };
} }

View file

@ -2,11 +2,25 @@
{ {
imports = [ (modulesPath + "/profiles/qemu-guest.nix") ]; imports = [ (modulesPath + "/profiles/qemu-guest.nix") ];
boot.loader.grub.device = "/dev/sda"; boot.loader.grub.device = "/dev/sda";
boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "xen_blkfront" "vmw_pvscsi" ]; boot.initrd.availableKernelModules = [
"ata_piix"
"uhci_hcd"
"xen_blkfront"
"vmw_pvscsi"
];
boot.initrd.kernelModules = [ "nvme" ]; boot.initrd.kernelModules = [ "nvme" ];
fileSystems."/" = { device = "/dev/sda1"; fsType = "ext4"; }; fileSystems."/" = {
device = "/dev/sda1";
fsType = "ext4";
};
# swap # swap
swapDevices = [{ device = "/var/swapfile"; size = 4 * 1024; priority = 1024; }]; swapDevices = [
{
device = "/var/swapfile";
size = 4 * 1024;
priority = 1024;
}
];
zramSwap.enable = true; zramSwap.enable = true;
# volumes # volumes
services.btrfs.autoScrub.enable = true; services.btrfs.autoScrub.enable = true;

View file

@ -1,4 +1,9 @@
{ pkgs, config, lib, ... }: {
pkgs,
config,
lib,
...
}:
let let
secrets = config.sops.secrets; secrets = config.sops.secrets;
@ -7,9 +12,14 @@ let
webuiPort = 19877; webuiPort = 19877;
in in
rec { rec {
sops.secrets."headscale/client_secret" = { owner = "headscale"; }; sops.secrets."headscale/client_secret" = {
owner = "headscale";
};
sops.secrets."headscale/webui-env" = { }; sops.secrets."headscale/webui-env" = { };
sops.secrets."headscale/derp-servers/vnm" = { owner = "headscale"; name = "headscale/derp-servers/vnm.yaml"; }; sops.secrets."headscale/derp-servers/vnm" = {
owner = "headscale";
name = "headscale/derp-servers/vnm.yaml";
};
# database # database
cloud.postgresql.databases = [ "headscale" ]; cloud.postgresql.databases = [ "headscale" ];
# traefik # traefik
@ -27,8 +37,14 @@ rec {
noCloudflare = true; noCloudflare = true;
}; };
systemd.services.headscale.requires = [ "postgresql.service" "arion-authentik.service" ]; systemd.services.headscale.requires = [
systemd.services.headscale.after = [ "postgresql.service" "arion-authentik.service" ]; "postgresql.service"
"arion-authentik.service"
];
systemd.services.headscale.after = [
"postgresql.service"
"arion-authentik.service"
];
services.headscale = { services.headscale = {
enable = true; enable = true;
inherit port; inherit port;

View file

@ -1,4 +1,9 @@
{ config, pkgs, lib, ... }: {
config,
pkgs,
lib,
...
}:
let let
ipv6-rotator = ipv6-rotator =
let let
@ -11,7 +16,14 @@ let
in in
pkgs.writeShellApplication { pkgs.writeShellApplication {
name = "smart-ipv6-rotator"; name = "smart-ipv6-rotator";
runtimeInputs = [ (pkgs.python3.withPackages (p: with p; [ pyroute2 requests ])) ]; runtimeInputs = [
(pkgs.python3.withPackages (
p: with p; [
pyroute2
requests
]
))
];
text = '' text = ''
if [ -z "$IPV6_ROTATOR_RANGE" ]; then if [ -z "$IPV6_ROTATOR_RANGE" ]; then
echo "Range required" echo "Range required"
@ -22,10 +34,17 @@ let
}; };
in in
{ {
sops.secrets."invidious" = { mode = "0444"; }; sops.secrets."invidious" = {
sops.secrets."invidious-rotator-env" = { mode = "0444"; }; mode = "0444";
};
sops.secrets."invidious-rotator-env" = {
mode = "0444";
};
cloud.postgresql.databases = [ "invidious" ]; cloud.postgresql.databases = [ "invidious" ];
cloud.traefik.hosts.invidious = { host = "invi.dtth.ch"; port = 61191; }; cloud.traefik.hosts.invidious = {
host = "invi.dtth.ch";
port = 61191;
};
services.invidious = { services.invidious = {
enable = true; enable = true;
domain = "invi.dtth.ch"; domain = "invi.dtth.ch";
@ -54,8 +73,13 @@ in
}; };
systemd.timers.smart-ipv6-rotator = { systemd.timers.smart-ipv6-rotator = {
description = "Rotate ipv6 routes to Google"; description = "Rotate ipv6 routes to Google";
timerConfig = { OnCalendar = "*-*-* 00,06,12,18:00:00"; }; timerConfig = {
wantedBy = [ "invidious.service" "timers.target" ]; OnCalendar = "*-*-* 00,06,12,18:00:00";
};
wantedBy = [
"invidious.service"
"timers.target"
];
unitConfig = { }; unitConfig = { };
}; };
systemd.services.smart-ipv6-rotator = { systemd.services.smart-ipv6-rotator = {
@ -68,4 +92,3 @@ in
}; };
}; };
} }

View file

@ -1,4 +1,9 @@
{ pkgs, config, lib, ... }: {
pkgs,
config,
lib,
...
}:
with lib; with lib;
let let
user = "miniflux"; user = "miniflux";
@ -42,7 +47,10 @@ in
systemd.services.miniflux = { systemd.services.miniflux = {
description = "Miniflux service"; description = "Miniflux service";
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
after = [ "network.target" "postgresql.service" ]; after = [
"network.target"
"postgresql.service"
];
requires = [ "postgresql.service" ]; requires = [ "postgresql.service" ];
serviceConfig = { serviceConfig = {
@ -72,16 +80,22 @@ in
ProtectKernelModules = true; ProtectKernelModules = true;
ProtectKernelTunables = true; ProtectKernelTunables = true;
ProtectProc = "invisible"; ProtectProc = "invisible";
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ]; RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
"AF_UNIX"
];
RestrictNamespaces = true; RestrictNamespaces = true;
RestrictRealtime = true; RestrictRealtime = true;
RestrictSUIDSGID = true; RestrictSUIDSGID = true;
SystemCallArchitectures = "native"; SystemCallArchitectures = "native";
SystemCallFilter = [ "@system-service" "~@privileged" ]; SystemCallFilter = [
"@system-service"
"~@privileged"
];
UMask = "0077"; UMask = "0077";
}; };
environment = configEnv; environment = configEnv;
}; };
} }

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }: {
config,
lib,
pkgs,
...
}:
let let
secrets = config.sops.secrets; secrets = config.sops.secrets;
@ -12,7 +17,9 @@ let
plugins = pkgs.callPackage ./n8n/plugins/package.nix { }; plugins = pkgs.callPackage ./n8n/plugins/package.nix { };
in in
{ {
sops.secrets."n8n/env" = { reloadUnits = [ "n8n.service" ]; }; sops.secrets."n8n/env" = {
reloadUnits = [ "n8n.service" ];
};
cloud.postgresql.databases = [ db ]; cloud.postgresql.databases = [ db ];
cloud.traefik.hosts.n8n = { cloud.traefik.hosts.n8n = {
inherit port host; inherit port host;

View file

@ -1,4 +1,5 @@
{ nodejs, importNpmLock }: importNpmLock.buildNodeModules { { nodejs, importNpmLock }:
importNpmLock.buildNodeModules {
inherit nodejs; inherit nodejs;
npmRoot = ./.; npmRoot = ./.;
} }

View file

@ -1,7 +1,14 @@
{ config, pkgs, ... }: { { config, pkgs, ... }:
sops.secrets.authentik-oidc-client-secret = { owner = "outline"; }; {
sops.secrets."outline/smtp-password" = { owner = "outline"; }; sops.secrets.authentik-oidc-client-secret = {
sops.secrets."outline/s3-secret-key" = { owner = "outline"; }; owner = "outline";
};
sops.secrets."outline/smtp-password" = {
owner = "outline";
};
sops.secrets."outline/s3-secret-key" = {
owner = "outline";
};
services.outline = { services.outline = {
enable = true; enable = true;
@ -52,5 +59,8 @@
AWS_S3_R2 = "true"; AWS_S3_R2 = "true";
AWS_S3_R2_PUBLIC_URL = "https://s3.wiki.dtth.ch"; AWS_S3_R2_PUBLIC_URL = "https://s3.wiki.dtth.ch";
}; };
cloud.traefik.hosts.outline = { host = "wiki.dtth.ch"; port = 18729; }; cloud.traefik.hosts.outline = {
host = "wiki.dtth.ch";
port = 18729;
};
} }

View file

@ -1,4 +1,9 @@
{ pkgs, config, lib, ... }: {
pkgs,
config,
lib,
...
}:
let let
host = "owncast.nkagami.me"; host = "owncast.nkagami.me";
port = 61347; port = 61347;

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }: {
config,
lib,
pkgs,
...
}:
let let
secrets = config.sops.secrets; secrets = config.sops.secrets;
cfg = config.services.peertube; cfg = config.services.peertube;
@ -9,8 +14,14 @@ let
port = 19878; port = 19878;
in in
{ {
sops.secrets."peertube" = { owner = cfg.user; restartUnits = [ "peertube.service" ]; }; sops.secrets."peertube" = {
sops.secrets."peertube-env" = { owner = cfg.user; restartUnits = [ "peertube.service" ]; }; owner = cfg.user;
restartUnits = [ "peertube.service" ];
};
sops.secrets."peertube-env" = {
owner = cfg.user;
restartUnits = [ "peertube.service" ];
};
# database # database
cloud.postgresql.databases = [ "peertube" ]; cloud.postgresql.databases = [ "peertube" ];
# traefik # traefik
@ -61,7 +72,9 @@ in
}; };
# Trust proxy # Trust proxy
settings.trust_proxy = [ "loopback" ] ++ config.services.traefik.staticConfigOptions.entrypoints.https.forwardedHeaders.trustedIPs; settings.trust_proxy = [
"loopback"
] ++ config.services.traefik.staticConfigOptions.entrypoints.https.forwardedHeaders.trustedIPs;
# Federation # Federation
settings.federation = { settings.federation = {
@ -70,7 +83,10 @@ in
videos.cleanup_remote_interactions = true; videos.cleanup_remote_interactions = true;
}; };
dataDirs = [ "/var/lib/peertube" "/mnt/data/peertube" ]; dataDirs = [
"/var/lib/peertube"
"/mnt/data/peertube"
];
}; };
systemd.services.peertube = { systemd.services.peertube = {
@ -90,4 +106,3 @@ in
}; };
}; };
} }

View file

@ -1,4 +1,9 @@
{ config, pkgs, lib, ... }: {
config,
pkgs,
lib,
...
}:
let let
host = "social.dtth.ch"; host = "social.dtth.ch";
port = 61010; port = 61010;
@ -6,11 +11,12 @@ in
{ {
cloud.traefik.hosts.phanpy = { inherit host port; }; cloud.traefik.hosts.phanpy = { inherit host port; };
services.nginx.virtualHosts.phanpy = { services.nginx.virtualHosts.phanpy = {
listen = [{ listen = [
inherit port; {
addr = "127.0.0.1"; inherit port;
}]; addr = "127.0.0.1";
}
];
root = "${pkgs.dtth-phanpy}/lib/phanpy"; root = "${pkgs.dtth-phanpy}/lib/phanpy";
}; };
} }

View file

@ -1,4 +1,9 @@
{ pkgs, lib, config, ... }: {
pkgs,
lib,
config,
...
}:
let let
port = 61001; port = 61001;
user = "matrix-synapse"; user = "matrix-synapse";
@ -10,7 +15,9 @@ in
{ {
sops.secrets."matrix-synapse-dtth/oidc-config".owner = user; sops.secrets."matrix-synapse-dtth/oidc-config".owner = user;
sops.secrets."matrix-synapse-dtth/appservice-discord".owner = user; sops.secrets."matrix-synapse-dtth/appservice-discord".owner = user;
sops.secrets.matrix-discord-bridge = { mode = "0644"; }; sops.secrets.matrix-discord-bridge = {
mode = "0644";
};
cloud.postgresql.databases = [ user ]; cloud.postgresql.databases = [ user ];
cloud.traefik.hosts.matrix-synapse = { cloud.traefik.hosts.matrix-synapse = {
@ -29,20 +36,33 @@ in
enable = true; enable = true;
withJemalloc = true; withJemalloc = true;
dataDir = "${config.fileSystems.data.mountPoint}/matrix-synapse-dtth"; dataDir = "${config.fileSystems.data.mountPoint}/matrix-synapse-dtth";
extras = [ "systemd" "url-preview" "oidc" "postgres" ]; extras = [
"systemd"
"url-preview"
"oidc"
"postgres"
];
settings = { settings = {
server_name = "dtth.ch"; server_name = "dtth.ch";
enable_registration = false; enable_registration = false;
public_baseurl = "https://${host}/"; public_baseurl = "https://${host}/";
listeners = [{ listeners = [
inherit port; {
x_forwarded = true; inherit port;
tls = false; x_forwarded = true;
resources = [ tls = false;
{ names = [ "client" "federation" ]; compress = false; } resources = [
]; {
}]; names = [
"client"
"federation"
];
compress = false;
}
];
}
];
database = { database = {
name = "psycopg2"; name = "psycopg2";
args = { args = {
@ -96,25 +116,32 @@ in
}; };
services.nginx.virtualHosts.synapse-dtth-wellknown = { services.nginx.virtualHosts.synapse-dtth-wellknown = {
listen = [{ addr = "127.0.0.1"; port = port + 1; }]; listen = [
{
addr = "127.0.0.1";
port = port + 1;
}
];
# Check https://github.com/spantaleev/matrix-docker-ansible-deploy/blob/master/docs/configuring-well-known.md # Check https://github.com/spantaleev/matrix-docker-ansible-deploy/blob/master/docs/configuring-well-known.md
# for the file structure. # for the file structure.
root = pkgs.symlinkJoin root = pkgs.symlinkJoin {
{ name = "well-known-files-for-synapse";
name = "well-known-files-for-synapse"; paths = [
paths = [ (pkgs.writeTextDir ".well-known/matrix/client" (
(pkgs.writeTextDir ".well-known/matrix/client" (builtins.toJSON { builtins.toJSON {
"m.homeserver".base_url = "https://${host}"; "m.homeserver".base_url = "https://${host}";
})) }
(pkgs.writeTextDir ".well-known/matrix/server" (builtins.toJSON { ))
(pkgs.writeTextDir ".well-known/matrix/server" (
builtins.toJSON {
"m.server" = "${host}:443"; "m.server" = "${host}:443";
})) }
]; ))
}; ];
};
# Enable CORS from anywhere since we want all clients to find us out # Enable CORS from anywhere since we want all clients to find us out
extraConfig = '' extraConfig = ''
add_header 'Access-Control-Allow-Origin' "*"; add_header 'Access-Control-Allow-Origin' "*";
''; '';
}; };
} }

View file

@ -1,4 +1,9 @@
{ pkgs, lib, config, ... }: {
pkgs,
lib,
config,
...
}:
let let
secrets = config.sops.secrets; secrets = config.sops.secrets;
@ -9,8 +14,12 @@ let
storageMount = "/mnt/data/vikunja"; storageMount = "/mnt/data/vikunja";
in in
{ {
sops.secrets."vikunja/env" = { restartUnits = [ "vikunja.service" ]; }; sops.secrets."vikunja/env" = {
sops.secrets."vikunja/provider-clientsecret" = { restartUnits = [ "vikunja.service" ]; }; restartUnits = [ "vikunja.service" ];
};
sops.secrets."vikunja/provider-clientsecret" = {
restartUnits = [ "vikunja.service" ];
};
cloud.postgresql.databases = [ user ]; cloud.postgresql.databases = [ user ];
cloud.traefik.hosts.vikunja = { cloud.traefik.hosts.vikunja = {
inherit port host; inherit port host;
@ -23,7 +32,6 @@ in
}; };
users.groups."${user}" = { }; users.groups."${user}" = { };
services.vikunja = { services.vikunja = {
inherit port; inherit port;
enable = true; enable = true;
@ -81,7 +89,11 @@ in
}; };
systemd.services.vikunja = { systemd.services.vikunja = {
serviceConfig.LoadCredential = [ "VIKUNJA_AUTH_OPENID_PROVIDERS_AUTHENTIK_CLIENTSECRET_FILE:${secrets."vikunja/provider-clientsecret".path}" ]; serviceConfig.LoadCredential = [
"VIKUNJA_AUTH_OPENID_PROVIDERS_AUTHENTIK_CLIENTSECRET_FILE:${
secrets."vikunja/provider-clientsecret".path
}"
];
serviceConfig.User = user; serviceConfig.User = user;
serviceConfig.DynamicUser = lib.mkForce false; serviceConfig.DynamicUser = lib.mkForce false;
serviceConfig.ReadWritePaths = [ storageMount ]; serviceConfig.ReadWritePaths = [ storageMount ];
@ -96,4 +108,3 @@ in
mode = "0700"; mode = "0700";
}; };
} }

View file

@ -1,4 +1,9 @@
{ config, pkgs, lib, ... }: {
config,
pkgs,
lib,
...
}:
with lib; with lib;
let let
host = "blog.dtth.ch"; host = "blog.dtth.ch";
@ -11,7 +16,9 @@ in
# traefik # traefik
cloud.traefik.hosts.writefreely-dtth = { inherit host port; }; cloud.traefik.hosts.writefreely-dtth = { inherit host port; };
sops.secrets."writefreely-oauth-secret" = { owner = user; }; sops.secrets."writefreely-oauth-secret" = {
owner = user;
};
users.users.${user} = { users.users.${user} = {
isSystemUser = true; isSystemUser = true;
@ -65,16 +72,18 @@ in
tokenEndpoint = "/application/o/token/"; tokenEndpoint = "/application/o/token/";
inspectEndpoint = "/application/o/userinfo/"; inspectEndpoint = "/application/o/userinfo/";
authEndpoint = "/application/o/authorize/"; authEndpoint = "/application/o/authorize/";
scopes = [ "email" "openid" "profile" ]; scopes = [
"email"
"openid"
"profile"
];
mapUserId = "nickname"; mapUserId = "nickname";
mapUsername = "preferred_username"; mapUsername = "preferred_username";
mapDisplayName = "name"; mapDisplayName = "name";
}; };
database.type = "sqlite3"; database.type = "sqlite3";
admin.name = "nki"; admin.name = "nki";
}; };
} }

View file

@ -1,21 +1,36 @@
{ config, lib, pkgs, ... }: {
config,
lib,
pkgs,
...
}:
let let
inherit (builtins) toString; inherit (builtins) toString;
inherit (lib) types mkIf mkOption mkDefault; inherit (lib)
inherit (lib) optional optionals optionalAttrs optionalString; types
mkIf
mkOption
mkDefault
;
inherit (lib)
optional
optionals
optionalAttrs
optionalString
;
inherit (pkgs) sqlite; inherit (pkgs) sqlite;
format = pkgs.formats.ini { format = pkgs.formats.ini {
mkKeyValue = key: value: mkKeyValue =
key: value:
let let
value' = lib.optionalString (value != null) value' = lib.optionalString (value != null) (
(if builtins.isBool value then if builtins.isBool value then if value == true then "true" else "false" else toString value
if value == true then "true" else "false" );
else in
toString value); "${key} = ${value'}";
in "${key} = ${value'}";
}; };
cfg = config.nki.services.writefreely; cfg = config.nki.services.writefreely;
@ -31,49 +46,58 @@ let
host = cfg.settings.app.host or "${hostProtocol}://${cfg.host}"; host = cfg.settings.app.host or "${hostProtocol}://${cfg.host}";
}; };
database = if cfg.database.type == "sqlite3" then { database =
type = "sqlite3"; if cfg.database.type == "sqlite3" then
filename = cfg.settings.database.filename or "writefreely.db"; {
database = cfg.database.name; type = "sqlite3";
} else { filename = cfg.settings.database.filename or "writefreely.db";
type = "mysql"; database = cfg.database.name;
username = cfg.database.user; }
password = "#dbpass#"; else
database = cfg.database.name; {
host = cfg.database.host; type = "mysql";
port = cfg.database.port; username = cfg.database.user;
tls = cfg.database.tls; password = "#dbpass#";
}; database = cfg.database.name;
host = cfg.database.host;
port = cfg.database.port;
tls = cfg.database.tls;
};
server = cfg.settings.server or { } // { server = cfg.settings.server or { } // {
bind = cfg.settings.server.bind or "localhost"; bind = cfg.settings.server.bind or "localhost";
gopher_port = cfg.settings.server.gopher_port or 0; gopher_port = cfg.settings.server.gopher_port or 0;
autocert = !cfg.nginx.enable && cfg.acme.enable; autocert = !cfg.nginx.enable && cfg.acme.enable;
templates_parent_dir = templates_parent_dir = cfg.settings.server.templates_parent_dir or cfg.package.src;
cfg.settings.server.templates_parent_dir or cfg.package.src;
static_parent_dir = cfg.settings.server.static_parent_dir or assets; static_parent_dir = cfg.settings.server.static_parent_dir or assets;
pages_parent_dir = pages_parent_dir = cfg.settings.server.pages_parent_dir or cfg.package.src;
cfg.settings.server.pages_parent_dir or cfg.package.src;
keys_parent_dir = cfg.settings.server.keys_parent_dir or cfg.stateDir; keys_parent_dir = cfg.settings.server.keys_parent_dir or cfg.stateDir;
}; };
"oauth.generic" = cfg.settings."oauth.generic" or { } // (if cfg.oauth.enable then { "oauth.generic" =
client_id = cfg.oauth.clientId; cfg.settings."oauth.generic" or { }
client_secret = "#oauth_client_secret#"; // (
host = cfg.oauth.host; if cfg.oauth.enable then
display_name = cfg.oauth.displayName; {
callback_proxy = cfg.oauth.callbackProxy; client_id = cfg.oauth.clientId;
callback_proxy_api = cfg.oauth.callbackProxyApi; client_secret = "#oauth_client_secret#";
token_endpoint = cfg.oauth.tokenEndpoint; host = cfg.oauth.host;
inspect_endpoint = cfg.oauth.inspectEndpoint; display_name = cfg.oauth.displayName;
auth_endpoint = cfg.oauth.authEndpoint; callback_proxy = cfg.oauth.callbackProxy;
scope = lib.concatStringsSep " " cfg.oauth.scopes; callback_proxy_api = cfg.oauth.callbackProxyApi;
allow_disconnect = cfg.oauth.allowDisconnect; token_endpoint = cfg.oauth.tokenEndpoint;
map_user_id = cfg.oauth.mapUserId; inspect_endpoint = cfg.oauth.inspectEndpoint;
map_username = cfg.oauth.mapUsername; auth_endpoint = cfg.oauth.authEndpoint;
map_display_name = cfg.oauth.mapDisplayName; scope = lib.concatStringsSep " " cfg.oauth.scopes;
map_email = cfg.oauth.mapEmail; allow_disconnect = cfg.oauth.allowDisconnect;
} else { }); map_user_id = cfg.oauth.mapUserId;
map_username = cfg.oauth.mapUsername;
map_display_name = cfg.oauth.mapDisplayName;
map_email = cfg.oauth.mapEmail;
}
else
{ }
);
}; };
configFile = format.generate "config.ini" settings; configFile = format.generate "config.ini" settings;
@ -104,13 +128,9 @@ let
withConfigFile = text: '' withConfigFile = text: ''
db_pass=${ db_pass=${
optionalString (cfg.database.passwordFile != null) optionalString (cfg.database.passwordFile != null) "$(head -n1 ${cfg.database.passwordFile})"
"$(head -n1 ${cfg.database.passwordFile})"
}
oauth_client_secret=${
optionalString cfg.oauth.enable
"$(head -n1 ${cfg.oauth.clientSecretFile})"
} }
oauth_client_secret=${optionalString cfg.oauth.enable "$(head -n1 ${cfg.oauth.clientSecretFile})"}
cp -f ${configFile} '${cfg.stateDir}/config.ini' cp -f ${configFile} '${cfg.stateDir}/config.ini'
sed -e "s,#dbpass#,$db_pass,g" -i '${cfg.stateDir}/config.ini' sed -e "s,#dbpass#,$db_pass,g" -i '${cfg.stateDir}/config.ini'
@ -120,7 +140,8 @@ let
${text} ${text}
''; '';
withMysql = text: withMysql =
text:
withConfigFile '' withConfigFile ''
query () { query () {
local result=$(${config.services.mysql.package}/bin/mysql \ local result=$(${config.services.mysql.package}/bin/mysql \
@ -139,7 +160,8 @@ let
${text} ${text}
''; '';
withSqlite = text: withSqlite =
text:
withConfigFile '' withConfigFile ''
query () { query () {
local result=$(${sqlite}/bin/sqlite3 \ local result=$(${sqlite}/bin/sqlite3 \
@ -152,10 +174,10 @@ let
${text} ${text}
''; '';
in { in
{
options.nki.services.writefreely = { options.nki.services.writefreely = {
enable = enable = lib.mkEnableOption "Writefreely, build a digital writing community";
lib.mkEnableOption "Writefreely, build a digital writing community";
package = lib.mkOption { package = lib.mkOption {
type = lib.types.package; type = lib.types.package;
@ -223,7 +245,10 @@ in {
database = { database = {
type = mkOption { type = mkOption {
type = types.enum [ "sqlite3" "mysql" ]; type = types.enum [
"sqlite3"
"mysql"
];
default = "sqlite3"; default = "sqlite3";
description = "The database provider to use."; description = "The database provider to use.";
}; };
@ -416,13 +441,11 @@ in {
} }
{ {
assertion = isMysqlLocal -> cfg.database.passwordFile != null; assertion = isMysqlLocal -> cfg.database.passwordFile != null;
message = message = "services.writefreely.database.passwordFile must be set if services.writefreely.database.createLocally is set to true";
"services.writefreely.database.passwordFile must be set if services.writefreely.database.createLocally is set to true";
} }
{ {
assertion = isSqlite -> !cfg.database.createLocally; assertion = isSqlite -> !cfg.database.createLocally;
message = message = "services.writefreely.database.createLocally has no use when services.writefreely.database.type is set to sqlite3";
"services.writefreely.database.createLocally has no use when services.writefreely.database.type is set to sqlite3";
} }
]; ];
@ -435,8 +458,7 @@ in {
}; };
}; };
groups = groups = optionalAttrs (cfg.group == "writefreely") { writefreely = { }; };
optionalAttrs (cfg.group == "writefreely") { writefreely = { }; };
}; };
systemd.tmpfiles.settings."10-writefreely".${cfg.stateDir}.d = { systemd.tmpfiles.settings."10-writefreely".${cfg.stateDir}.d = {
@ -445,7 +467,8 @@ in {
}; };
systemd.services.writefreely = { systemd.services.writefreely = {
after = [ "network.target" ] after =
[ "network.target" ]
++ optional isSqlite "writefreely-sqlite-init.service" ++ optional isSqlite "writefreely-sqlite-init.service"
++ optional isMysql "writefreely-mysql-init.service" ++ optional isMysql "writefreely-mysql-init.service"
++ optional isMysqlLocal "mysql.service"; ++ optional isMysqlLocal "mysql.service";
@ -458,10 +481,8 @@ in {
WorkingDirectory = cfg.stateDir; WorkingDirectory = cfg.stateDir;
Restart = "always"; Restart = "always";
RestartSec = 20; RestartSec = 20;
ExecStart = ExecStart = "${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' serve";
"${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' serve"; AmbientCapabilities = optionalString (settings.server.port < 1024) "cap_net_bind_service";
AmbientCapabilities =
optionalString (settings.server.port < 1024) "cap_net_bind_service";
}; };
preStart = '' preStart = ''
@ -485,31 +506,32 @@ in {
User = cfg.user; User = cfg.user;
Group = cfg.group; Group = cfg.group;
WorkingDirectory = cfg.stateDir; WorkingDirectory = cfg.stateDir;
ReadOnlyPaths = optional (cfg.admin.initialPasswordFile != null) ReadOnlyPaths = optional (cfg.admin.initialPasswordFile != null) cfg.admin.initialPasswordFile;
cfg.admin.initialPasswordFile;
}; };
script = let script =
migrateDatabase = optionalString cfg.database.migrate '' let
${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' db migrate migrateDatabase = optionalString cfg.database.migrate ''
''; ${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' db migrate
'';
createAdmin = optionalString (cfg.admin.name != null) '' createAdmin = optionalString (cfg.admin.name != null) ''
if [[ $(query "SELECT COUNT(*) FROM users") == 0 ]]; then if [[ $(query "SELECT COUNT(*) FROM users") == 0 ]]; then
admin_pass=$(head -n1 ${cfg.admin.initialPasswordFile}) admin_pass=$(head -n1 ${cfg.admin.initialPasswordFile})
${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' --create-admin ${cfg.admin.name}:$admin_pass ${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' --create-admin ${cfg.admin.name}:$admin_pass
fi
'';
in
withSqlite ''
if ! test -f '${settings.database.filename}'; then
${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' db init
fi fi
${migrateDatabase}
${createAdmin}
''; '';
in withSqlite ''
if ! test -f '${settings.database.filename}'; then
${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' db init
fi
${migrateDatabase}
${createAdmin}
'';
}; };
systemd.services.writefreely-mysql-init = mkIf isMysql { systemd.services.writefreely-mysql-init = mkIf isMysql {
@ -521,57 +543,61 @@ in {
User = cfg.user; User = cfg.user;
Group = cfg.group; Group = cfg.group;
WorkingDirectory = cfg.stateDir; WorkingDirectory = cfg.stateDir;
ReadOnlyPaths = optional isMysqlLocal cfg.database.passwordFile ReadOnlyPaths =
++ optional (cfg.admin.initialPasswordFile != null) optional isMysqlLocal cfg.database.passwordFile
cfg.admin.initialPasswordFile; ++ optional (cfg.admin.initialPasswordFile != null) cfg.admin.initialPasswordFile;
}; };
script = let script =
updateUser = optionalString isMysqlLocal '' let
# WriteFreely currently *requires* a password for authentication, so we updateUser = optionalString isMysqlLocal ''
# need to update the user in MySQL accordingly. By default MySQL users # WriteFreely currently *requires* a password for authentication, so we
# authenticate with auth_socket or unix_socket. # need to update the user in MySQL accordingly. By default MySQL users
# See: https://github.com/writefreely/writefreely/issues/568 # authenticate with auth_socket or unix_socket.
${config.services.mysql.package}/bin/mysql --skip-column-names --execute "ALTER USER '${cfg.database.user}'@'localhost' IDENTIFIED VIA unix_socket OR mysql_native_password USING PASSWORD('$db_pass'); FLUSH PRIVILEGES;" # See: https://github.com/writefreely/writefreely/issues/568
''; ${config.services.mysql.package}/bin/mysql --skip-column-names --execute "ALTER USER '${cfg.database.user}'@'localhost' IDENTIFIED VIA unix_socket OR mysql_native_password USING PASSWORD('$db_pass'); FLUSH PRIVILEGES;"
'';
migrateDatabase = optionalString cfg.database.migrate '' migrateDatabase = optionalString cfg.database.migrate ''
${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' db migrate ${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' db migrate
''; '';
createAdmin = optionalString (cfg.admin.name != null) '' createAdmin = optionalString (cfg.admin.name != null) ''
if [[ $(query 'SELECT COUNT(*) FROM users') == 0 ]]; then if [[ $(query 'SELECT COUNT(*) FROM users') == 0 ]]; then
admin_pass=$(head -n1 ${cfg.admin.initialPasswordFile}) admin_pass=$(head -n1 ${cfg.admin.initialPasswordFile})
${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' --create-admin ${cfg.admin.name}:$admin_pass ${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' --create-admin ${cfg.admin.name}:$admin_pass
fi
'';
in
withMysql ''
${updateUser}
if [[ $(query "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '${cfg.database.name}'") == 0 ]]; then
${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' db init
fi fi
${migrateDatabase}
${createAdmin}
''; '';
in withMysql ''
${updateUser}
if [[ $(query "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '${cfg.database.name}'") == 0 ]]; then
${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' db init
fi
${migrateDatabase}
${createAdmin}
'';
}; };
services.mysql = mkIf isMysqlLocal { services.mysql = mkIf isMysqlLocal {
enable = true; enable = true;
package = mkDefault pkgs.mariadb; package = mkDefault pkgs.mariadb;
ensureDatabases = [ cfg.database.name ]; ensureDatabases = [ cfg.database.name ];
ensureUsers = [{ ensureUsers = [
name = cfg.database.user; {
ensurePermissions = { name = cfg.database.user;
"${cfg.database.name}.*" = "ALL PRIVILEGES"; ensurePermissions = {
# WriteFreely requires the use of passwords, so we need permissions "${cfg.database.name}.*" = "ALL PRIVILEGES";
# to `ALTER` the user to add password support and also to reload # WriteFreely requires the use of passwords, so we need permissions
# permissions so they can be used. # to `ALTER` the user to add password support and also to reload
"*.*" = "CREATE USER, RELOAD"; # permissions so they can be used.
}; "*.*" = "CREATE USER, RELOAD";
}]; };
}
];
}; };
services.nginx = lib.mkIf cfg.nginx.enable { services.nginx = lib.mkIf cfg.nginx.enable {

View file

@ -5,15 +5,14 @@
{ config, pkgs, ... }: { config, pkgs, ... }:
{ {
imports = imports = [
[ # Include the results of the hardware scan.
# Include the results of the hardware scan. ./hardware-configuration.nix
./hardware-configuration.nix # Fonts
# Fonts ../modules/personal/fonts
../modules/personal/fonts # Some PAM stuff
# Some PAM stuff ../modules/services/swaylock.nix
../modules/services/swaylock.nix ];
];
# Use the latest kernel # Use the latest kernel
boot.kernelPackages = pkgs.linuxPackages_latest; boot.kernelPackages = pkgs.linuxPackages_latest;
@ -54,7 +53,6 @@
services.xserver.enable = true; services.xserver.enable = true;
services.xserver.autorun = false; services.xserver.autorun = false;
# Enable the Plasma 5 Desktop Environment. # Enable the Plasma 5 Desktop Environment.
# services.xserver.displayManager.sddm.enable = true; # services.xserver.displayManager.sddm.enable = true;
# services.xserver.desktopManager.plasma5.enable = true; # services.xserver.desktopManager.plasma5.enable = true;
@ -65,13 +63,18 @@
fi fi
''; '';
# Configure keymap in X11 # Configure keymap in X11
# services.xserver.layout = "us"; # services.xserver.layout = "us";
# services.xserver.xkbOptions = "eurosign:e"; # services.xserver.xkbOptions = "eurosign:e";
i18n.inputMethod.enabled = "ibus"; i18n.inputMethod.enabled = "ibus";
i18n.inputMethod.ibus.engines = (with pkgs.ibus-engines; [ bamboo mozc libpinyin ]); i18n.inputMethod.ibus.engines = (
with pkgs.ibus-engines;
[
bamboo
mozc
libpinyin
]
);
# Enable CUPS to print documents. # Enable CUPS to print documents.
# services.printing.enable = true; # services.printing.enable = true;

View file

@ -1,39 +1,47 @@
# Do not modify this file! It was generated by nixos-generate-config # Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes # and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead. # to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }: {
config,
lib,
pkgs,
modulesPath,
...
}:
{ {
imports = imports = [
[ (modulesPath + "/installer/scan/not-detected.nix")
(modulesPath + "/installer/scan/not-detected.nix") ];
];
boot.initrd.availableKernelModules = [ "xhci_pci" "ehci_pci" "ahci" "usb_storage" "sd_mod" "sdhci_pci" ]; boot.initrd.availableKernelModules = [
"xhci_pci"
"ehci_pci"
"ahci"
"usb_storage"
"sd_mod"
"sdhci_pci"
];
boot.initrd.kernelModules = [ ]; boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ]; boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ]; boot.extraModulePackages = [ ];
fileSystems."/" = fileSystems."/" = {
{ device = "/dev/disk/by-uuid/bc8b0807-c3d6-4893-bcc2-02f059a51a80";
device = "/dev/disk/by-uuid/bc8b0807-c3d6-4893-bcc2-02f059a51a80"; fsType = "ext4";
fsType = "ext4"; };
};
fileSystems."/boot" = fileSystems."/boot" = {
{ device = "/dev/disk/by-uuid/885D-D058";
device = "/dev/disk/by-uuid/885D-D058"; fsType = "vfat";
fsType = "vfat"; };
};
fileSystems."/home" = fileSystems."/home" = {
{ device = "/dev/disk/by-uuid/a981870f-db1d-4441-81da-f1bab1ecc37c";
device = "/dev/disk/by-uuid/a981870f-db1d-4441-81da-f1bab1ecc37c"; fsType = "btrfs";
fsType = "btrfs"; };
};
swapDevices = swapDevices = [ { device = "/dev/disk/by-uuid/2694d189-2ff6-4719-a449-367c52ed3ad6"; } ];
[{ device = "/dev/disk/by-uuid/2694d189-2ff6-4719-a449-367c52ed3ad6"; }];
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
} }

View file

@ -5,22 +5,23 @@
{ config, pkgs, ... }: { config, pkgs, ... }:
{ {
imports = imports = [
[ # Include the results of the hardware scan.
# Include the results of the hardware scan. ./hardware-configuration.nix
./hardware-configuration.nix # Fonts
# Fonts ../modules/personal/fonts
../modules/personal/fonts # Encrypted DNS
# Encrypted DNS ../modules/services/edns
../modules/services/edns ];
];
# Secrets # Secrets
common.linux.sops.enable = true; common.linux.sops.enable = true;
common.linux.sops.file = ./secrets.yaml; common.linux.sops.file = ./secrets.yaml;
# Build farm # Build farm
sops.secrets."nix-build-farm/private-key" = { mode = "0400"; }; sops.secrets."nix-build-farm/private-key" = {
mode = "0400";
};
services.nix-build-farm.hostname = "yoga"; services.nix-build-farm.hostname = "yoga";
services.nix-build-farm.privateKeyFile = config.sops.secrets."nix-build-farm/private-key".path; services.nix-build-farm.privateKeyFile = config.sops.secrets."nix-build-farm/private-key".path;
@ -141,4 +142,3 @@
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "22.05"; # Did you read the comment? system.stateVersion = "22.05"; # Did you read the comment?
} }

View file

@ -1,15 +1,24 @@
# Do not modify this file! It was generated by nixos-generate-config # Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes # and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead. # to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }: {
config,
lib,
pkgs,
modulesPath,
...
}:
{ {
imports = imports = [
[ (modulesPath + "/installer/scan/not-detected.nix")
(modulesPath + "/installer/scan/not-detected.nix") ];
];
boot.initrd.availableKernelModules = [ "xhci_pci" "thunderbolt" "nvme" ]; boot.initrd.availableKernelModules = [
"xhci_pci"
"thunderbolt"
"nvme"
];
boot.initrd.kernelModules = [ ]; boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ]; boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ]; boot.extraModulePackages = [ ];
@ -19,11 +28,10 @@
"resume_offset=9731998" # btrfs inspect-internal map-swapfile -r /var/swapfile "resume_offset=9731998" # btrfs inspect-internal map-swapfile -r /var/swapfile
]; ];
fileSystems."/" = fileSystems."/" = {
{ device = "/dev/disk/by-uuid/b32d27bf-9df6-43c1-8b93-c0693811bf5b";
device = "/dev/disk/by-uuid/b32d27bf-9df6-43c1-8b93-c0693811bf5b"; fsType = "btrfs";
fsType = "btrfs"; };
};
services.btrfs.autoScrub = { services.btrfs.autoScrub = {
enable = true; enable = true;
interval = "monthly"; interval = "monthly";
@ -31,14 +39,17 @@
common.linux.luksDevices."nixroot" = "/dev/disk/by-uuid/09114015-79bc-4a40-bf60-b4022e969acb"; common.linux.luksDevices."nixroot" = "/dev/disk/by-uuid/09114015-79bc-4a40-bf60-b4022e969acb";
fileSystems."/boot" = fileSystems."/boot" = {
{ device = "/dev/disk/by-uuid/E820-D6C7";
device = "/dev/disk/by-uuid/E820-D6C7"; fsType = "vfat";
fsType = "vfat"; };
};
swapDevices = [ swapDevices = [
{ device = "/var/swapfile"; size = 32 * 1024; priority = 10; } {
device = "/var/swapfile";
size = 32 * 1024;
priority = 10;
}
]; ];
boot.blacklistedKernelModules = [ boot.blacklistedKernelModules = [

View file

@ -1,9 +1,18 @@
{ nixpkgs, nixpkgs-unstable, ... }@inputs: { nixpkgs, nixpkgs-unstable, ... }@inputs:
let let
overlay-unstable = final: prev: { overlay-unstable = final: prev: {
stable = import nixpkgs { config.allowUnfree = true; system = prev.system; }; stable = import nixpkgs {
unstable = import nixpkgs-unstable { config.allowUnfree = true; system = prev.system; }; config.allowUnfree = true;
x86 = import nixpkgs-unstable { system = prev.system; config.allowUnsupportedSystem = true; }; system = prev.system;
};
unstable = import nixpkgs-unstable {
config.allowUnfree = true;
system = prev.system;
};
x86 = import nixpkgs-unstable {
system = prev.system;
config.allowUnsupportedSystem = true;
};
}; };
overlay-needs-unstable = final: prev: { overlay-needs-unstable = final: prev: {
# Typst updates really quickly. # Typst updates really quickly.
@ -50,19 +59,20 @@ let
input-remapper = final.unstable.input-remapper; input-remapper = final.unstable.input-remapper;
kakoune-unwrapped = kakoune-unwrapped = prev.kakoune-unwrapped.overrideAttrs (attrs: {
prev.kakoune-unwrapped.overrideAttrs (attrs: { version = "r${builtins.substring 0 6 inputs.kakoune.rev}";
version = "r${builtins.substring 0 6 inputs.kakoune.rev}"; src = inputs.kakoune;
src = inputs.kakoune; patches = [
patches = [ # patches in the original package was already applied
# patches in the original package was already applied ];
];
});
librewolf = (prev.librewolf.override {
nativeMessagingHosts = with final; [ kdePackages.plasma-browser-integration ];
}); });
librewolf = (
prev.librewolf.override {
nativeMessagingHosts = with final; [ kdePackages.plasma-browser-integration ];
}
);
vikunja = vikunja =
# builtins.seq # builtins.seq
# (final.lib.assertMsg (prev.vikunja.version == "0.24.5") "Vikunja probably doesn't need custom versions anymore") # (final.lib.assertMsg (prev.vikunja.version == "0.24.5") "Vikunja probably doesn't need custom versions anymore")
@ -71,20 +81,28 @@ let
luminance = prev.luminance.overrideAttrs (attrs: { luminance = prev.luminance.overrideAttrs (attrs: {
nativeBuildInputs = attrs.nativeBuildInputs ++ [ final.wrapGAppsHook ]; nativeBuildInputs = attrs.nativeBuildInputs ++ [ final.wrapGAppsHook ];
buildInputs = attrs.buildInputs ++ [ final.glib ]; buildInputs = attrs.buildInputs ++ [ final.glib ];
postInstall = attrs.postInstall + '' postInstall =
glib-compile-schemas $out/share/glib-2.0/schemas attrs.postInstall
''; + ''
glib-compile-schemas $out/share/glib-2.0/schemas
'';
}); });
vesktop = prev.vesktop.overrideAttrs (attrs: { vesktop = prev.vesktop.overrideAttrs (attrs: {
postFixup = postFixup =
let let
flagToReplace = if final.lib.hasInfix "--enable-wayland-ime=true" attrs.postFixup then "--enable-wayland-ime=true" else "--enable-wayland-ime"; flagToReplace =
if final.lib.hasInfix "--enable-wayland-ime=true" attrs.postFixup then
"--enable-wayland-ime=true"
else
"--enable-wayland-ime";
in in
builtins.replaceStrings [ "NIXOS_OZONE_WL" flagToReplace ] [ "WAYLAND_DISPLAY" "${flagToReplace} --wayland-text-input-version=3" ] attrs.postFixup; builtins.replaceStrings
[ "NIXOS_OZONE_WL" flagToReplace ]
[ "WAYLAND_DISPLAY" "${flagToReplace} --wayland-text-input-version=3" ]
attrs.postFixup;
}); });
editline-lix = editline-lix =
assert final.lib.assertMsg (final.lix.version == "2.92.0") "we only need to patch this for 2.92"; assert final.lib.assertMsg (final.lix.version == "2.92.0") "we only need to patch this for 2.92";
final.editline.overrideAttrs (prev: { final.editline.overrideAttrs (prev: {
@ -106,7 +124,9 @@ let
}; };
overlay-packages = final: prev: { overlay-packages = final: prev: {
kak-tree-sitter = final.callPackage ./packages/common/kak-tree-sitter { rustPlatform = final.unstable.rustPlatform; }; kak-tree-sitter = final.callPackage ./packages/common/kak-tree-sitter {
rustPlatform = final.unstable.rustPlatform;
};
kak-lsp = final.unstable.rustPlatform.buildRustPackage { kak-lsp = final.unstable.rustPlatform.buildRustPackage {
name = "kak-lsp"; name = "kak-lsp";
@ -129,9 +149,14 @@ let
zen-browser-bin = inputs.zen-browser.packages.${final.stdenv.system}.zen-browser.override { zen-browser-bin = inputs.zen-browser.packages.${final.stdenv.system}.zen-browser.override {
inherit (inputs.zen-browser.packages.${final.stdenv.system}) zen-browser-unwrapped; inherit (inputs.zen-browser.packages.${final.stdenv.system}) zen-browser-unwrapped;
wrapFirefox = opts: final.wrapFirefox (opts // { wrapFirefox =
nativeMessagingHosts = with final; [ kdePackages.plasma-browser-integration ]; opts:
}); final.wrapFirefox (
opts
// {
nativeMessagingHosts = with final; [ kdePackages.plasma-browser-integration ];
}
);
# zen-browser-unwrapped = final.callPackage inputs.zen-browser.packages.${final.stdenv.system}.zen-browser-unwrapped.override { # zen-browser-unwrapped = final.callPackage inputs.zen-browser.packages.${final.stdenv.system}.zen-browser-unwrapped.override {
# sources = inputs.zen-browser.inputs; # sources = inputs.zen-browser.inputs;
# }; # };

View file

@ -1,4 +1,10 @@
{ pkgs, runCommand, zstd, lib, buildFHSEnvChroot }: {
pkgs,
runCommand,
zstd,
lib,
buildFHSEnvChroot,
}:
let let
typora-tar = builtins.fetchurl { typora-tar = builtins.fetchurl {
@ -13,35 +19,39 @@ let
in in
buildFHSEnvChroot { buildFHSEnvChroot {
name = "typora"; name = "typora";
targetPkgs = pkgs: with pkgs; [ targetPkgs =
glib pkgs:
nss with pkgs;
nspr [
at-spi2-atk glib
cups nss
dbus nspr
gtk3 at-spi2-atk
pango cups
cairo dbus
mesa gtk3
expat pango
libdrm cairo
libxkbcommon mesa
alsa-lib expat
freefont_ttf libdrm
liberation_ttf libxkbcommon
wayland alsa-lib
libglvnd freefont_ttf
electron liberation_ttf
] ++ (with pkgs.xorg; [ wayland
libX11 libglvnd
libXcomposite electron
libXdamage ]
libXext ++ (with pkgs.xorg; [
libXfixes libX11
libXrandr libXcomposite
libxcb libXdamage
]); libXext
libXfixes
libXrandr
libxcb
]);
extraBuildCommands = '' extraBuildCommands = ''
# ldd ${typora-src}/bin/Typora-linux-arm64/Typora && false # ldd ${typora-src}/bin/Typora-linux-arm64/Typora && false
''; '';

View file

@ -1,4 +1,10 @@
{ pkgs, runCommandLocal, zstd, lib, buildFHSEnvChroot }: {
pkgs,
runCommandLocal,
zstd,
lib,
buildFHSEnvChroot,
}:
let let
zotero-tar = builtins.fetchurl { zotero-tar = builtins.fetchurl {
@ -14,7 +20,19 @@ let
in in
buildFHSEnvChroot { buildFHSEnvChroot {
name = "zotero"; name = "zotero";
targetPkgs = pkgs: with pkgs; [ gtk3 dbus-glib libstartup_notification libpaper ] ++ (with pkgs.xorg; [ libX11 libXt ]); targetPkgs =
pkgs:
with pkgs;
[
gtk3
dbus-glib
libstartup_notification
libpaper
]
++ (with pkgs.xorg; [
libX11
libXt
]);
runScript = "env QT_SCALE_FACTOR=2 ${zotero-src}/usr/lib/zotero/zotero"; runScript = "env QT_SCALE_FACTOR=2 ${zotero-src}/usr/lib/zotero/zotero";
extraInstallCommands = '' extraInstallCommands = ''

View file

@ -1,6 +1,6 @@
{ pkgs, runCommand, ... }: runCommand "epfl-cups-drivers" { } '' { pkgs, runCommand, ... }:
runCommand "epfl-cups-drivers" { } ''
mkdir -p $out/share/cups/model mkdir -p $out/share/cups/model
cp ${./PPD-C5860-bw-EN.PPD} $out/share/cups/model cp ${./PPD-C5860-bw-EN.PPD} $out/share/cups/model
cp ${./PPD-C5860-color-EN.PPD} $out/share/cups/model cp ${./PPD-C5860-color-EN.PPD} $out/share/cups/model
'' ''

View file

@ -1,4 +1,13 @@
{ lib, rustPlatform, fetchFromSourcehut, symlinkJoin, clang, git, writeText, ... }: {
lib,
rustPlatform,
fetchFromSourcehut,
symlinkJoin,
clang,
git,
writeText,
...
}:
let let
src = fetchFromSourcehut { src = fetchFromSourcehut {
owner = "~hadronized"; owner = "~hadronized";
@ -12,9 +21,17 @@ let
pname = "kak-tree-sitter"; pname = "kak-tree-sitter";
version = "1.1.3"; version = "1.1.3";
cargoHash = "sha256-1OwPfl1446SYt1556jwR9mvWOWEv+ab+wH7GZQeS4/E="; cargoHash = "sha256-1OwPfl1446SYt1556jwR9mvWOWEv+ab+wH7GZQeS4/E=";
cargoBuildOptions = [ "--package" "kak-tree-sitter" "--package" "ktsctl" ]; cargoBuildOptions = [
"--package"
"kak-tree-sitter"
"--package"
"ktsctl"
];
nativeBuildInputs = [ clang git ]; nativeBuildInputs = [
clang
git
];
patches = [ patches = [
# Allow absolute-path style repos # Allow absolute-path style repos
@ -40,4 +57,3 @@ let
}; };
in in
kak-tree-sitter kak-tree-sitter

View file

@ -1,25 +1,32 @@
{ callPackage, kakoune, kakoune-unwrapped, ... }: {
callPackage,
kakoune,
kakoune-unwrapped,
...
}:
let let
lsp = callPackage ./lsp.nix { }; lsp = callPackage ./lsp.nix { };
rc = (callPackage ./rc.nix { }); rc = (callPackage ./rc.nix { });
in in
(kakoune.override { (kakoune.override {
plugins = callPackage ./plugins.nix { } plugins =
callPackage ./plugins.nix { }
++ callPackage ./themes.nix { } ++ callPackage ./themes.nix { }
++ [ ++ [
(callPackage ./kaktex { }) (callPackage ./kaktex { })
(callPackage ./faces.nix { }) (callPackage ./faces.nix { })
rc rc
lsp.plugin lsp.plugin
]; ];
}).overrideAttrs (attrs: { }).overrideAttrs
buildCommand = '' (attrs: {
${attrs.buildCommand or ""} buildCommand = ''
# location of kak binary is used to find ../share/kak/autoload, ${attrs.buildCommand or ""}
# unless explicitly overriden with KAKOUNE_RUNTIME # location of kak binary is used to find ../share/kak/autoload,
rm "$out/bin/kak" # unless explicitly overriden with KAKOUNE_RUNTIME
makeWrapper "${kakoune-unwrapped}/bin/kak" "$out/bin/kak" \ rm "$out/bin/kak"
--set KAKOUNE_RUNTIME "$out/share/kak" \ makeWrapper "${kakoune-unwrapped}/bin/kak" "$out/bin/kak" \
--suffix PATH ":" "${lsp.extraPaths}" --set KAKOUNE_RUNTIME "$out/share/kak" \
''; --suffix PATH ":" "${lsp.extraPaths}"
}) '';
})

View file

@ -1,7 +1,7 @@
{ callPackage, ... } : { callPackage, ... }:
let let
utils = callPackage ./utils.nix { }; utils = callPackage ./utils.nix { };
faces = { faces = {
Default = "%opt{text},%opt{base}"; Default = "%opt{text},%opt{base}";
BufferPadding = "%opt{base},%opt{base}"; BufferPadding = "%opt{base},%opt{base}";
MenuForeground = "%opt{blue},white+bF"; MenuForeground = "%opt{blue},white+bF";
@ -27,5 +27,6 @@ faces = {
format_specifier = "+i@string"; format_specifier = "+i@string";
mutable_variable = "+i@variable"; mutable_variable = "+i@variable";
class = "+b@variable"; class = "+b@variable";
}; };
in utils.mkFacesScript "default-faces" faces in
utils.mkFacesScript "default-faces" faces

Some files were not shown because too many files have changed in this diff Show more