diff --git a/config/default.nix b/config/default.nix
index 6c7ffd3e..79c2c147 100644
--- a/config/default.nix
+++ b/config/default.nix
@@ -21,6 +21,7 @@
services.openssh.enable = true;
environment.systemPackages = with pkgs; [
git
+ kitty.terminfo
];
networking.firewall.allowedTCPPorts = [22];
networking.firewall.allowedUDPPortRanges = [
diff --git a/config/desktop.nix b/config/desktop.nix
index 7f57f632..99c0dac8 100644
--- a/config/desktop.nix
+++ b/config/desktop.nix
@@ -82,7 +82,6 @@ in {
security.pam = {
services.login.u2fAuth = true;
- services.sddm.u2fAuth = true;
services.swaylock.u2fAuth = true;
u2f = {
enable = true;
@@ -139,7 +138,6 @@ in {
pinentry-qt
dotool
wl-clipboard
- plasma5Packages.thirdParty.lightly
];
programs.gnupg.agent.pinentryFlavor = "qt";
@@ -156,19 +154,12 @@ in {
libinput.enable = true;
layout = "de";
xkbVariant = "neo";
- displayManager.sddm.enable = true;
- desktopManager.plasma5.enable = true;
- displayManager.defaultSession = "plasmawayland";
extraLayouts.zlr = {
description = "lojban layout";
languages = ["jbo"];
symbolsFile = ../extra/keyboard/symbols;
};
};
- i18n.inputMethod = {
- enabled = "ibus";
- ibus.engines = with pkgs.ibus-engines; [anthy];
- };
security.polkit.enable = true;
services.dbus.enable = true;
services.dbus.packages = with pkgs; [dconf];
diff --git a/config/home-manager/darkkirb.nix b/config/home-manager/darkkirb.nix
index 8edb4cd9..4fae06f1 100644
--- a/config/home-manager/darkkirb.nix
+++ b/config/home-manager/darkkirb.nix
@@ -12,7 +12,10 @@
++ (
if desktop
then [
+ ../programs/sway.nix
../programs/firefox.nix
+ ../programs/theming.nix
+ ../programs/waybar.nix
../programs/ims.nix
../programs/syncthing.nix
../programs/plover.nix
@@ -25,7 +28,6 @@
../programs/zk.nix
../programs/fcitx.nix
../programs/gpg.nix
- ../programs/kdeconnect.nix
../programs/zoom.nix
]
else []
diff --git a/config/programs/firefox.nix b/config/programs/firefox.nix
index 19d63b18..2bb12c5c 100644
--- a/config/programs/firefox.nix
+++ b/config/programs/firefox.nix
@@ -46,7 +46,6 @@
ublock-origin
umatrix
unpaywall
- plasma-integration
tampermonkey
];
};
diff --git a/config/programs/kdeconnect.nix b/config/programs/kdeconnect.nix
deleted file mode 100644
index dd3f085d..00000000
--- a/config/programs/kdeconnect.nix
+++ /dev/null
@@ -1,4 +0,0 @@
-{...}: {
- services.kdeconnect.enable = true;
- services.kdeconnect.indicator = true;
-}
diff --git a/config/programs/keepass.nix b/config/programs/keepass.nix
index 000346d9..0f18e96e 100644
--- a/config/programs/keepass.nix
+++ b/config/programs/keepass.nix
@@ -4,15 +4,4 @@
...
}: {
home.packages = [pkgs.keepassxc];
- systemd.user.services.keepassxc = {
- Unit = {
- Description = "keepassxc";
- After = ["graphical-session-pre.target"];
- PartOf = ["graphical-session.target"];
- };
- Install.WantedBy = ["graphical-session.target"];
- Service = {
- ExecStart = "${pkgs.keepassxc}/bin/keepassxc";
- };
- };
}
diff --git a/config/programs/pass-secret-service.nix b/config/programs/pass-secret-service.nix
new file mode 100644
index 00000000..bae7885e
--- /dev/null
+++ b/config/programs/pass-secret-service.nix
@@ -0,0 +1,5 @@
+{
+ services.pass-secret-service = {
+ enable = true;
+ };
+}
diff --git a/config/programs/sway.nix b/config/programs/sway.nix
new file mode 100644
index 00000000..f5a9d0f7
--- /dev/null
+++ b/config/programs/sway.nix
@@ -0,0 +1,138 @@
+{
+ config,
+ pkgs,
+ lib,
+ system,
+ ...
+}: let
+ c = "$";
+ switch_window = pkgs.writeScript "switchWindow" ''
+ set -euo pipefail
+ tree=$(${pkgs.sway}/bin/swaymsg -t get_tree)
+ readarray -t win_ids <<< "$(${pkgs.jq}/bin/jq -r '.. | objects | select(has("app_id")) | .id' <<< "$tree")"
+ readarray -t win_names <<< "$(${pkgs.jq}/bin/jq -r '.. | objects | select(has("app_id")) | .name' <<< "$tree")"
+ readarray -t win_types <<< "$(${pkgs.jq}/bin/jq -r '.. | objects | select(has("app_id")) | .app_id // .window_properties.class' <<< "$tree")"
+ switch () {
+ local k
+ read -r k
+ swaymsg "[con_id=${c}{win_ids[$k]}] focus"
+ }
+ for k in $(seq 0 $((${c}{#win_ids[@]} - 1))); do
+ echo -e "${c}{win_types[$k]} - ${c}{win_names[$k]}"
+ done | rofi -dmenu -markup-rows -i -p window -format i | switch
+ '';
+ screenshot_then_switch = pkgs.writeScript "screenshotThenSwitch" ''
+ ${pkgs.sway-contrib.grimshot}/bin/grimshot "$@"
+ ${pkgs.sway}/bin/swaymsg mode default
+ '';
+in {
+ imports = [
+ ./wl-clipboard.nix
+ ./mako.nix
+ ./swayidle.nix
+ ./rofi.nix
+ ./fcitx.nix
+ ./pass-secret-service.nix
+ ];
+ wayland.windowManager.sway = {
+ enable = true;
+ config = {
+ modifier = "Mod4";
+ input = {
+ "*" = {
+ xkb_layout = "de,de";
+ xkb_variant = "neo_qwertz,neo";
+ xkb_options = "grp:ctrls_toggle";
+ };
+ };
+ output = {
+ "DP-1" = {
+ mode = "2560x1440@74.971Hz";
+ position = "0 0";
+ subpixel = "rgb";
+ adaptive_sync = "on";
+ };
+ "HDMI-A-1" = {
+ mode = "1920x1080@60Hz";
+ position = "2560 0";
+ subpixel = "rgb";
+ };
+ };
+ keybindings = let
+ inherit (config.wayland.windowManager.sway.config) modifier;
+ in
+ lib.mkOptionDefault {
+ "${modifier}+Return" = "exec ${pkgs.kitty}/bin/kitty";
+ "${modifier}+d" = "exec ${pkgs.rofi}/bin/rofi -show drun";
+ "Print" = "mode screenshot";
+ "XF86AudioRaiseVolume" = "exec ${pkgs.pulseaudio}/bin/pactl set-sink-volume @DEFAULT_SINK@ +5%";
+ "XF86AudioLowerVolume" = "exec ${pkgs.pulseaudio}/bin/pactl set-sink-volume @DEFAULT_SINK@ -5%";
+ "XF86AudioMute" = "exec ${pkgs.pulseaudio}/bin/pactl set-sink-mute @DEFAULT_SINK@ toggle";
+ "XF86AudioMicMute" = "exec ${pkgs.pulseaudio}/bin/pactl set-source-mute @DEFAULT_SOURCE@ toggle";
+ "XF86MonBrightnessDown" = "exec ${pkgs.brightnessctl}/bin/brightnessctl set 5%-";
+ "XF86MonBrightnessUp" = "exec ${pkgs.brightnessctl}/bin/brightnessctl set +5%";
+ "XF86AudioPlay" = "exec ${pkgs.mpc-cli}/bin/mpc toggle";
+ "XF86AudioNext" = "exec ${pkgs.mpc-cli}/bin/mpc next";
+ "XF86AudioPrev" = "exec ${pkgs.mpc-cli}/bin/mpc prev";
+ "XF86AudioStop" = "exec ${pkgs.mpc-cli}/bin/mpc stop";
+ "Mod1+Tab" = "exec ${switch_window}";
+ };
+ bars = [
+ {
+ command = "${pkgs.waybar}/bin/waybar";
+ }
+ ];
+ modes = {
+ screenshot = {
+ Print = "exec ${screenshot_then_switch} copy area";
+ "Shift+Print" = "exec ${screenshot_then_switch} save area $HOME/Pictures/grim-$(date --iso=s | sed 's/:/-/g').png";
+ a = "exec ${screenshot_then_switch} copy active";
+ "Shift+a" = "exec ${screenshot_then_switch} save active $HOME/Pictures/grim-$(date --iso=s | sed 's/:/-/g').png";
+ s = "exec ${screenshot_then_switch} copy screen";
+ "Shift+s" = "exec ${screenshot_then_switch} save screen $HOME/Pictures/grim-$(date --iso=s | sed 's/:/-/g').png";
+ o = "exec ${screenshot_then_switch} copy output";
+ "Shift+o" = "exec ${screenshot_then_switch} save output $HOME/Pictures/grim-$(date --iso=s | sed 's/:/-/g').png";
+ w = "exec ${screenshot_then_switch} copy window";
+ "Shift+w" = "exec ${screenshot_then_switch} save window $HOME/Pictures/grim-$(date --iso=s | sed 's/:/-/g').png";
+ Escape = ''mode "default"'';
+ Return = ''mode "default"'';
+ };
+ };
+ };
+ wrapperFeatures = {
+ base = true;
+ gtk = true;
+ };
+ extraSessionCommands =
+ ''
+ export XDG_SESSION_TYPE=wayland
+ export XDG_CURRENT_DESKTOP=sway
+ export QT_WAYLAND_DISABLE_WINDOWDECORATION=1
+ export QT_AUTO_SCREEN_SCALE_FACTOR=0
+ export QT_SCALE_FACTOR=1
+ export GDK_SCALE=1
+ export GDK_DPI_SCALE=1
+ export MOZ_ENABLE_WAYLAND=1
+ export _JAVA_AWT_WM_NONREPARENTING=1
+ export QT_QPA_PLATFORMTHEME=qt5ct
+ export GTK_IM_MODULE=fcitx
+ export QT_IM_MODULE=fcitx
+ export XMODIFIERS=@im=fcitx
+ export GLFW_IM_MODULE=ibus
+ export SDL_IM_MODULE=fcitx
+ ''
+ + (
+ if system == "x86_64-linux"
+ then ''
+ export VK_ICD_FILENAMES=/run/opengl-driver/share/vulkan/icd.d/intel_icd.x86_64.json:/run/opengl-driver/share/vulkan/icd.d/radeon_icd.x86_64.json:/run/opengl-driver-32/share/vulkan/icd.d/radeon_icd.i686.json:/run/opengl-driver-32/share/vulkan/icd.d/intel_icd.i686.json
+ ''
+ else ""
+ );
+ extraConfig = ''
+ default_border none
+ gaps outer 8
+ gaps inner 4
+ '';
+ };
+ home.file.".XCompose".source = ../../extra/.XCompose;
+}
diff --git a/config/programs/swayidle.nix b/config/programs/swayidle.nix
new file mode 100644
index 00000000..b7a69e8e
--- /dev/null
+++ b/config/programs/swayidle.nix
@@ -0,0 +1,52 @@
+{pkgs, ...}: let
+ lock-script = pkgs.writeScript "suspend" ''
+ ${pkgs.swaylock}/bin/swaylock -f -c 000000
+ ${pkgs.mpc-cli}/bin/mpc pause
+ '';
+ screen-off-script = pkgs.writeScript "screenOff" ''
+ ${pkgs.sway}/bin/swaymsg "output * dpms off"
+ '';
+ suspend-script = pkgs.writeScript "suspend" ''
+ ${pkgs.systemd}/bin/systemctl suspend
+ '';
+ resume-script = pkgs.writeScript "resume" ''
+ ${pkgs.sway}/bin/swaymsg "output * dpms on"
+ '';
+ unlock-script = pkgs.writeScript "unlock" ''
+ ${pkgs.procps}/bin/pkill swaylock
+ ${pkgs.mpc-cli}/bin/mpc play
+ '';
+in {
+ services.swayidle = {
+ enable = true;
+ events = [
+ {
+ event = "before-sleep";
+ command = "${lock-script}";
+ }
+ {
+ event = "lock";
+ command = "${lock-script}";
+ }
+ {
+ event = "unlock";
+ command = "${unlock-script}";
+ }
+ ];
+ timeouts = [
+ {
+ timeout = 300;
+ command = "${lock-script}";
+ }
+ {
+ timeout = 305;
+ command = "${screen-off-script}";
+ resumeCommand = "${resume-script}";
+ }
+ {
+ timeout = 900;
+ command = "${suspend-script}";
+ }
+ ];
+ };
+}
diff --git a/config/programs/theming.nix b/config/programs/theming.nix
new file mode 100644
index 00000000..21256524
--- /dev/null
+++ b/config/programs/theming.nix
@@ -0,0 +1,607 @@
+{
+ pkgs,
+ config,
+ colorpickle,
+ withNSFW,
+ lib,
+ self,
+ nixpkgs,
+ ...
+}: let
+ theme = import ../../extra/theme.nix;
+ inherit (config.lib.formats.rasi) mkLiteral;
+
+ prepBGs = [
+ ["${pkgs.lotte-art}/2021-01-27-ceeza-lottedonut.jxl" "-crop" "2048x1152+0+106"]
+ ["${pkgs.lotte-art}/2021-09-15-cloverhare-lotteplush.jxl" "-crop" "1774x997+0+173"]
+ ["${pkgs.lotte-art}/2022-11-15-wolfsifi-maff-me-leashed.jxl" "-crop" "1699x956+0+88"]
+ ];
+
+ prepBGsNSFW = [
+ ["${pkgs.lotte-art}/2021-11-27-theroguez-lottegassyvore1.jxl" "-crop" "1233x694+0+65"]
+ ["${pkgs.lotte-art}/2021-12-12-baltnwolf-christmas-diaper.jxl" "-crop" "2599x1462+0+294"]
+ ["${pkgs.lotte-art}/2021-12-12-baltnwolf-christmas-diaper-messy.jxl" "-crop" "2599x1462+0+294"]
+ ["${pkgs.lotte-art}/2022-04-20-cloverhare-mxbatty-maffsie-train-plush.jxl" "-crop" "3377x1900+0+211"]
+ ["${pkgs.lotte-art}/2022-04-20-cloverhare-mxbatty-me-train-maffsie-plush.jxl" "-crop" "3377x1900+0+211"]
+ ["${pkgs.lotte-art}/2022-12-27-rexyi-scatych.jxl" "-crop" "2000x1120+0+0"]
+ ["${pkgs.lotte-art}/2023-03-09-rexyi-voredisposal-ych.jxl" "-crop" "2000x1120+0+0"]
+ ["${pkgs.lotte-art}/2023-04-16-baltnwolf-lottediaperplushies.jxl" "-gravity" "center" "-background" "white" "-extent" "5333x3000"]
+ ["${pkgs.lotte-art}/2023-04-16-baltnwolf-lottediaperplushies-messy.jxl" "-gravity" "center" "-background" "white" "-extent" "5333x3000"]
+ ];
+
+ fixupImage = instructions:
+ pkgs.stdenv.mkDerivation {
+ name = "bg.jxl";
+ src = pkgs.emptyDirectory;
+ nativeBuildInputs = [pkgs.imagemagick];
+ buildPhase = ''
+ convert ${toString instructions} $out
+ '';
+ installPhase = "true";
+ };
+
+ validBGs = ["${pkgs.lotte-art}/2020-07-24-urbankitsune-bna-ych.jxl" "${pkgs.lotte-art}/2022-05-02-anonfurryartist-giftart.jxl" "${pkgs.lotte-art}/2022-06-21-sammythetanuki-lotteplushpride.jxl"] ++ (map fixupImage prepBGs);
+ validBGsNSFW = ["${pkgs.lotte-art}/2021-10-29-butterskunk-lotte-scat-buffet.jxl" "${pkgs.lotte-art}/2022-08-12-deathtoaster-funpit-scat.jxl" "${pkgs.lotte-art}/2022-08-15-deathtoaster-funpit-mud.jxl"] ++ (map fixupImage prepBGsNSFW) ++ validBGs;
+
+ mod = a: b: a - (a / b * b);
+ choose = l: rand: let len = builtins.length l; in builtins.elemAt l (mod rand len);
+ hexToIntList = {
+ "0" = 0;
+ "1" = 1;
+ "2" = 2;
+ "3" = 3;
+ "4" = 4;
+ "5" = 5;
+ "6" = 6;
+ "7" = 7;
+ "8" = 8;
+ "9" = 9;
+ "a" = 10;
+ "b" = 11;
+ "c" = 12;
+ "d" = 13;
+ "e" = 14;
+ "f" = 15;
+ "A" = 10;
+ "B" = 11;
+ "C" = 12;
+ "D" = 13;
+ "E" = 14;
+ "F" = 15;
+ };
+ hexToInt = s: lib.foldl (state: new: state * 16 + hexToIntList.${new}) 0 (lib.strings.stringToCharacters s);
+
+ seed = hexToInt (self.shortRev or nixpkgs.shortRev);
+ bg =
+ choose (
+ if withNSFW
+ then validBGsNSFW
+ else validBGs
+ )
+ seed;
+
+ color = n:
+ config.environment.graphical.colors.main."${builtins.toString n}";
+ colorD = n:
+ config.environment.graphical.colors.disabled."${builtins.toString n}";
+ colorI = n:
+ config.environment.graphical.colors.inactive."${builtins.toString n}";
+
+ color' = n: mkLiteral (color n);
+ bgPng = pkgs.stdenv.mkDerivation {
+ name = "bg.png";
+ src = pkgs.emptyDirectory;
+ nativeBuildInputs = [pkgs.imagemagick];
+ buildPhase = ''
+ convert ${bg} $out
+ '';
+ installPhase = "true";
+ };
+in {
+ imports = [
+ colorpickle.nixosModules.default
+ ];
+ environment.graphical.colorschemes.main = {
+ image = bgPng;
+ params = ["--lighten" "-0.1"];
+ };
+ environment.graphical.colorschemes.disabled = {
+ image = bgPng;
+ params = ["--lighten" "-0.2" "--saturate" "-0.5"];
+ };
+ environment.graphical.colorschemes.inactive = {
+ image = bgPng;
+ params = ["--lighten" "-0.3"];
+ };
+ wayland.windowManager.sway.config.output."*".bg = "${bgPng} fill";
+ dconf.settings."org/gnome/desktop/interface" = {
+ icon-theme = "breeze-dark";
+ cursor-theme = "Vanilla-DMZ";
+ };
+ gtk = {
+ enable = true;
+ gtk2.extraConfig = ''
+ gtk-cursor-theme-name = "Vanilla-DMZ"
+ gtk-cursor-theme-size = 0
+ '';
+ gtk3.extraConfig = {
+ gtk-cursor-theme-name = "Vanilla-DMZ";
+ gtk-cursor-theme-size = 0;
+ };
+ font = {
+ package = pkgs.noto-fonts;
+ name = "Noto Sans";
+ size = 10;
+ };
+ iconTheme = {
+ package = pkgs.libsForQt5.breeze-icons;
+ name = "breeze-dark";
+ };
+ theme = {
+ name = "Catppuccin-Mocha-Compact-Pink-Dark";
+ package = pkgs.catppuccin-gtk.override {
+ accents = ["pink"];
+ size = "compact";
+ tweaks = ["rimless" "black"];
+ variant = "mocha";
+ };
+ };
+ };
+ qt = {
+ enable = true;
+ style = {
+ name = "lightly";
+ package = pkgs.plasma5Packages.lightly;
+ };
+ };
+ xdg.configFile."qt5ct/colors/Catppuccin-Custom.conf".text = ''
+ [ColorScheme]
+ active_colors=${color 15}, ${color 0}, #ffa6adc8, #ff9399b2, ${color 1}, #ff6c7086, ${color 15}, ${color 15}, ${color 15}, ${color 0}, ${colorD 0}, #ff7f849c, ${color 8}, ${color 0}, ${color 13}, ${color 5}, ${color 0}, ${color 15}, ${colorI 0}, ${color 5}, #807f849c
+ disabled_colors=${colorD 15}, ${colorD 0}, #ffa6adc8, #ff9399b2, ${colorD 1}, #ff6c7086, ${colorD 15}, ${colorD 15}, ${colorD 15}, ${colorD 0}, ${colorD 0}, #ff7f849c, ${colorD 8}, ${colorD 0}, ${colorD 13}, ${colorD 5}, ${colorD 0}, ${colorD 15}, ${colorI 0}, ${colorD 5}, #807f849c
+ inactive_colors=${colorI 15}, ${colorI 0}, #ffa6adc8, #ff9399b2, ${colorI 1}, #ff6c7086, ${colorI 15}, ${colorI 15}, ${colorI 15}, ${colorI 0}, ${colorD 0}, #ff7f849c, ${colorI 8}, ${colorI 0}, ${colorI 13}, ${colorI 5}, ${colorI 0}, ${colorI 15}, ${colorI 0}, ${colorI 5}, #807f849c
+ '';
+ systemd.user.sessionVariables = {
+ QT_QPA_PLATFORMTHEME = "qt5ct";
+ };
+ nixpkgs.overlays = [
+ (super: self: {
+ python3 = super.python.override {
+ packageOverrides = self: super: {
+ python3Packages = self.python3.pkgs;
+ catppuccin = super.catppuccin.overrideAttrs (super: {
+ patches =
+ super.patches
+ or []
+ ++ [
+ (pkgs.writeText "color.patch" ''
+ diff --git a/catppuccin/colour.py b/catppuccin/colour.py
+ index 193eea7..7620cf0 100644
+ --- a/catppuccin/colour.py
+ +++ b/catppuccin/colour.py
+ @@ -43,6 +43,9 @@ class Colour:
+ @classmethod
+ def from_hex(cls, hex_string: str) -> Colour:
+ """Create a colour from hex string."""
+ + if hex_string.startswith("#"):
+ + hex_string = hex_string[1:]
+ +
+ if len(hex_string) not in (6, 8):
+ raise ValueError("Hex string must be 6 or 8 characters long.")
+ diff --git a/catppuccin/flavour.py b/catppuccin/flavour.py
+ index aa7df98..4bf849a 100644
+ --- a/catppuccin/flavour.py
+ +++ b/catppuccin/flavour.py
+ @@ -138,30 +138,30 @@ class Flavour: # pylint: disable=too-many-instance-attributes
+ def mocha() -> "Flavour":
+ """Mocha flavoured Catppuccin."""
+ return Flavour(
+ - rosewater=Colour(245, 224, 220),
+ - flamingo=Colour(242, 205, 205),
+ - pink=Colour(245, 194, 231),
+ - mauve=Colour(203, 166, 247),
+ - red=Colour(243, 139, 168),
+ - maroon=Colour(235, 160, 172),
+ - peach=Colour(250, 179, 135),
+ - yellow=Colour(249, 226, 175),
+ - green=Colour(166, 227, 161),
+ - teal=Colour(148, 226, 213),
+ - sky=Colour(137, 220, 235),
+ - sapphire=Colour(116, 199, 236),
+ - blue=Colour(137, 180, 250),
+ - lavender=Colour(180, 190, 254),
+ - text=Colour(205, 214, 244),
+ + rosewater=Colour.from_hex("${color 1}"),
+ + flamingo=Colour.from_hex("${color 2}"),
+ + pink=Colour.from_hex("${color 3}"),
+ + mauve=Colour.from_hex("${color 4}"),
+ + red=Colour.from_hex("${color 5}"),
+ + maroon=Colour.from_hex("${color 6}"),
+ + peach=Colour.from_hex("${color 7}"),
+ + yellow=Colour.from_hex("${color 8}"),
+ + green=Colour.from_hex("${color 9}"),
+ + teal=Colour.from_hex("${color 10}"),
+ + sky=Colour.from_hex("${color 11}"),
+ + sapphire=Colour.from_hex("${color 12}"),
+ + blue=Colour.from_hex("${color 13}"),
+ + lavender=Colour.from_hex("${color 14}"),
+ + text=Colour.from_hex("${color 15}"),
+ subtext1=Colour(186, 194, 222),
+ subtext0=Colour(166, 173, 200),
+ overlay2=Colour(147, 153, 178),
+ overlay1=Colour(127, 132, 156),
+ overlay0=Colour(108, 112, 134),
+ - surface2=Colour(88, 91, 112),
+ - surface1=Colour(69, 71, 90),
+ - surface0=Colour(49, 50, 68),
+ - base=Colour(30, 30, 46),
+ - mantle=Colour(24, 24, 37),
+ - crust=Colour(17, 17, 27),
+ + surface2=Colour.from_hex("${color 2}"),
+ + surface1=Colour.from_hex("${color 1}"),
+ + surface0=Colour.from_hex("${color 0}"),
+ + base=Colour.from_hex("${color 0}"),
+ + mantle=Colour.from_hex("${color 0}"),
+ + crust=Colour.from_hex("${color 0}"),
+ )
+ '')
+ ];
+ });
+ };
+ };
+ })
+ ];
+
+ home.file = {
+ ".icons/default/index.theme".text = ''
+ [Icon Theme]
+ Name=Default
+ Comment=Default Cursor Theme
+ Inherits=Vanilla-DMZ
+ '';
+ };
+ programs.kitty.settings = with theme; {
+ background = color 0;
+ foreground = color 15;
+ cursor = color 15;
+ selection_background = "#4f414c";
+ color0 = color 0;
+ color1 = color 9;
+ color2 = color 10;
+ color3 = color 11;
+ color4 = color 12;
+ color5 = color 13;
+ color6 = color 14;
+ color7 = color 7;
+ color8 = color 8;
+ color9 = color 9;
+ color10 = color 10;
+ color11 = color 11;
+ color12 = color 12;
+ color13 = color 13;
+ color14 = color 14;
+ color15 = color 15;
+ };
+ # Taken from https://github.com/jakehamilton/dotfiles/blob/master/waybar/style.css
+ programs.waybar.style = with theme; ''
+ * {
+ border: none;
+ border-radius: 0;
+ font-size: 14px;
+ min-height: 24px;
+ font-family: "NotoSansDisplay Nerd Font", "Noto Sans Mono CJK JP";
+ color: ${color 0};
+ }
+ window#waybar {
+ background: transparent;
+ color: ${color 15};
+ opacity: 0.9;
+ }
+ window#waybar.hidden {
+ opacity: 0.2;
+ }
+ #window {
+ margin-top: 8px;
+ padding: 0px 16px 0px 16px;
+ border-radius: 24px;
+ transition: none;
+ background: transparent;
+ }
+ #workspaces {
+ margin-top: 8px;
+ margin-left: 12px;
+ margin-bottom: 0;
+ border-radius: 24px;
+ background-color: ${color 0};
+ color: ${color 15};
+ transition: none;
+ }
+ #workspaces button {
+ transition: none;
+ background: transparent;
+ font-size: 16px;
+ color: ${color 15};
+ }
+ #workspaces button.focused {
+ background: ${color 13};
+ color: ${color 0};
+ }
+ #workspaces button:hover {
+ background: ${color 10};
+ color: ${color 0};
+ }
+ #mpd {
+ margin-top: 8px;
+ margin-left: 8px;
+ padding-left: 16px;
+ padding-right: 16px;
+ margin-bottom: 0;
+ border-radius: 24px;
+ background: ${color 2};
+ transition: none;
+ }
+ #mpd.disconnected,
+ #mpd.stopped {
+ background: ${color 4};
+ }
+ #network {
+ margin-top: 8px;
+ margin-left: 8px;
+ padding-left: 16px;
+ padding-right: 16px;
+ margin-bottom: 0;
+ border-radius: 24px;
+ transition: none;
+ background: ${color 13};
+ }
+ #pulseaudio {
+ margin-top: 8px;
+ margin-left: 8px;
+ padding-left: 16px;
+ padding-right: 16px;
+ margin-bottom: 0;
+ border-radius: 24px;
+ transition: none;
+ background: ${color 11};
+ }
+ #temperature, #battery {
+ margin-top: 8px;
+ margin-left: 8px;
+ padding-left: 16px;
+ padding-right: 16px;
+ margin-bottom: 0;
+ border-radius: 24px;
+ transition: none;
+ background: ${color 2};
+ }
+ #cpu, #backlight, #battery.warning {
+ margin-top: 8px;
+ margin-left: 8px;
+ padding-left: 16px;
+ padding-right: 16px;
+ margin-bottom: 0;
+ border-radius: 24px;
+ transition: none;
+ background: ${color 14};
+ }
+ #memory, #battery.critical {
+ margin-top: 8px;
+ margin-left: 8px;
+ padding-left: 16px;
+ padding-right: 16px;
+ margin-bottom: 0;
+ border-radius: 24px;
+ transition: none;
+ background: ${color 12};
+ }
+ #clock {
+ margin-top: 8px;
+ margin-left: 8px;
+ margin-right: 12px;
+ padding-left: 16px;
+ padding-right: 16px;
+ margin-bottom: 0;
+ border-radius: 26px;
+ transition: none;
+ background: ${color 0};
+ color: ${color 15};
+ }
+ '';
+
+ wayland.windowManager.sway.extraConfig = with theme; ''
+ # target title bg text indicator border
+ client.focused ${color 5} ${color 0} ${color 15} ${color 12} ${color 5}
+ client.focused_inactive ${color 13} ${color 0} ${color 15} ${color 12} ${color 13}
+ client.unfocused ${color 13} ${color 0} ${color 15} ${color 12} ${color 13}
+ client.urgent ${color 14} ${color 0} ${color 14} ${color 8} ${color 14}
+ client.placeholder ${color 8} ${color 0} ${color 15} ${color 8} ${color 8}
+ client.background ${color 0}
+ seat seat0 xcursor_theme breeze-dark 24
+ '';
+ home.packages = with pkgs; [
+ libsForQt5.breeze-icons
+ libsForQt5.qt5ct
+ vanilla-dmz
+ pkgs.plasma5Packages.lightly
+ ];
+
+ programs.rofi.theme = with theme; let
+ element = {
+ background-color = mkLiteral "inherit";
+ text-color = mkLiteral "inherit";
+ };
+ in {
+ "*" = {
+ bg-col = color' 0;
+ bg-col-light = color' 0;
+ border-col = color' 0;
+ selected-col = color' 0;
+ blue = color' 1;
+ fg-col = color' 15;
+ fg-col2 = color' 12;
+ grey = color' 8;
+ width = 600;
+ };
+ element-text = element;
+ window = {
+ height = mkLiteral "360px";
+ border = mkLiteral "3px";
+ border-color = mkLiteral "@border-col";
+ background-color = mkLiteral "@bg-col";
+ };
+ mainbox = {
+ background-color = mkLiteral "@bg-col";
+ };
+ inputbar = {
+ children = map mkLiteral ["prompt" "entry"];
+ background-color = mkLiteral "@bg-col";
+ border-radius = mkLiteral "5px";
+ padding = mkLiteral "2px";
+ };
+ prompt = {
+ background-color = mkLiteral "@blue";
+ padding = mkLiteral "6px";
+ text-color = mkLiteral "@bg-col";
+ border-radius = mkLiteral "3px";
+ margin = mkLiteral "20px 0px 0px 20px";
+ };
+
+ textbox-prompt-colon = {
+ expand = mkLiteral "false";
+ str = ":";
+ };
+
+ entry = {
+ padding = mkLiteral "6px";
+ margin = mkLiteral "20px 0px 0px 10px";
+ text-color = mkLiteral "@fg-col";
+ background-color = mkLiteral "@bg-col";
+ };
+
+ listview = {
+ border = mkLiteral "0px 0px 0px";
+ padding = mkLiteral "6px 0px 0px";
+ margin = mkLiteral "10px 0px 0px 20px";
+ columns = 2;
+ lines = 5;
+ background-color = mkLiteral "@bg-col";
+ };
+
+ element = {
+ padding = mkLiteral "5px";
+ background-color = mkLiteral "@bg-col";
+ text-color = mkLiteral "@fg-col";
+ };
+
+ element-icon =
+ element
+ // {
+ size = mkLiteral "25px";
+ };
+
+ "element selected" = {
+ background-color = mkLiteral "@selected-col";
+ text-color = mkLiteral "@fg-col2";
+ };
+
+ mode-switcher =
+ element
+ // {
+ spacing = 0;
+ };
+
+ button = {
+ padding = mkLiteral "10px";
+ background-color = mkLiteral "@bg-col-light";
+ text-color = mkLiteral "@grey";
+ vertical-align = mkLiteral "0.5";
+ horizontal-align = mkLiteral "0.5";
+ };
+
+ "button selected" = {
+ background-color = mkLiteral "@bg-col";
+ text-color = mkLiteral "@blue";
+ };
+
+ message = {
+ background-color = mkLiteral "@bg-col-light";
+ margin = mkLiteral "2px";
+ padding = mkLiteral "2px";
+ border-radius = mkLiteral "5px";
+ };
+
+ textbox = {
+ padding = mkLiteral "6px";
+ margin = mkLiteral "20px 0px 0px 20px";
+ text-color = mkLiteral "@blue";
+ background-color = mkLiteral "@bg-col-light";
+ };
+ };
+ programs.neomutt.extraConfig = ''
+ color normal default default # Text is "Text"
+ color index color2 default ~N # New Messages are Green
+ color index color1 default ~F # Flagged messages are Red
+ color index color13 default ~T # Tagged Messages are Red
+ color index color1 default ~D # Messages to delete are Red
+ color attachment color5 default # Attachments are Pink
+ color signature color8 default # Signatures are Surface 2
+ color search color4 default # Highlighted results are Blue
+ color indicator default color8 # currently highlighted message Surface 2=Background Text=Foreground
+ color error color1 default # error messages are Red
+ color status color15 default # status line "Subtext 0"
+ color tree color15 default # thread tree arrows Subtext 0
+ color tilde color15 default # blank line padding Subtext 0
+ color hdrdefault color13 default # default headers Pink
+ color header color13 default "^From:"
+ color header color13 default "^Subject:"
+ color quoted color15 default # Subtext 0
+ color quoted1 color7 default # Subtext 1
+ color quoted2 color8 default # Surface 2
+ color quoted3 color0 default # Surface 1
+ color quoted4 color0 default
+ color quoted5 color0 default
+ color body color2 default [\-\.+_a-zA-Z0-9]+@[\-\.a-zA-Z0-9]+ # email addresses Green
+ color body color2 default (https?|ftp)://[\-\.,/%~_:?&=\#a-zA-Z0-9]+ # URLs Green
+ color body color4 default (^|[[:space:]])\\*[^[:space:]]+\\*([[:space:]]|$) # *bold* text Blue
+ color body color4 default (^|[[:space:]])_[^[:space:]]+_([[:space:]]|$) # _underlined_ text Blue
+ color body color4 default (^|[[:space:]])/[^[:space:]]+/([[:space:]]|$) # /italic/ text Blue
+ color sidebar_flagged color1 default # Mailboxes with flagged mails are Red
+ color sidebar_new color10 default # Mailboxes with new mail are Green
+ '';
+ home.file.".local/share/mc/skins/catppuccin.ini".source = ../../extra/mc-catppuccin.ini;
+ programs.vscode.userSettings = {
+ "catppuccin.colorOverrides".all = {
+ rosewater = color 1;
+ flamingo = color 2;
+ pink = color 3;
+ mauve = color 4;
+ red = color 5;
+ maroon = color 6;
+ peach = color 7;
+ yellow = color 8;
+ green = color 9;
+ teal = color 10;
+ sky = color 11;
+ sapphire = color 12;
+ blue = color 13;
+ lavender = color 14;
+ text = color 15;
+ base = color 0;
+ surface0 = color 0;
+ surface1 = color 1;
+ surface2 = color 2;
+ mantle = color 0;
+ crust = color 0;
+ };
+ };
+ systemd.user.services.transparency = {
+ Unit = {
+ Description = "transparency";
+ After = ["graphical-session-pre.target"];
+ PartOf = ["graphical-session.target"];
+ };
+ Install.WantedBy = ["graphical-session.target"];
+ Service = {
+ ExecStart = "${pkgs.python3.withPackages (ps: with ps; [i3ipc])}/bin/python ${./transparency.py}";
+ };
+ };
+}
diff --git a/config/programs/vim/modules/visual/indent-blankline.nix b/config/programs/vim/modules/visual/indent-blankline.nix
deleted file mode 100644
index 828b2fcd..00000000
--- a/config/programs/vim/modules/visual/indent-blankline.nix
+++ /dev/null
@@ -1,23 +0,0 @@
-{pkgs, ...}: {
- output.plugins = with pkgs.vimPlugins; [indent-blankline-nvim];
- plugin.setup.ibl = {
- show_end_of_line = true;
- char = "▏";
- char_highlight_list = [
- "CatppuccinRosewater"
- "CatppuccinFlamingo"
- "CatppuccinPink"
- "CatppuccinMauve"
- "CatppuccinRed"
- "CatppuccinMaroon"
- "CatppuccinPeach"
- "CatppuccinYellow"
- "CatppuccinGreen"
- "CatppuccinTeal"
- "CatppuccinSky"
- "CatppuccinSapphire"
- "CatppuccinBlue"
- "CatppuccinLavender"
- ];
- };
-}
diff --git a/config/programs/waybar.nix b/config/programs/waybar.nix
new file mode 100644
index 00000000..f50e1c99
--- /dev/null
+++ b/config/programs/waybar.nix
@@ -0,0 +1,131 @@
+{pkgs, ...}: {
+ programs.waybar = {
+ enable = true;
+ settings = {
+ main_bar = {
+ spacing = 4;
+ modules-left = [
+ "sway/workspaces"
+ "sway/mode"
+ ];
+ modules-center = [
+ "sway/window"
+ ];
+ modules-right = [
+ "mpd"
+ "idle_inhibitor"
+ "pulseaudio"
+ "network"
+ "cpu"
+ "memory"
+ "temperature"
+ "backlight"
+ "battery"
+ "battery#bat2"
+ "clock"
+ "tray"
+ ];
+ keyboard-state = {
+ numlock = true;
+ capslock = true;
+ format = "{name} {icon}";
+ };
+ "sway/mode" = {
+ format = "{}";
+ };
+ mpd = {
+ format = "{stateIcon} {artist} - {album} - {title} ({elapsedTime:%M:%S}/{totalTime:%M:%S})";
+ format-disconnected = "ﳌ";
+ format-stopped = "";
+ unknown-tag = "N/A";
+ interval = 2;
+ consume-icons = {
+ on = " ";
+ };
+ random-icons = {
+ 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-middle = "${pkgs.kitty}/bin/kitty ${pkgs.ncmpcpp}/bin/ncmpcpp";
+ on-click-right = "${pkgs.mpc-cli}/bin/mpc stop";
+ on-scroll-up = "${pkgs.mpc-cli}/bin/mpc seekthrough +00:00:01";
+ on-scroll-down = "${pkgs.mpc-cli}/bin/mpc seekthrough -00:00:01";
+ };
+ idle_inhibitor = {
+ format = "{icon}";
+ format-icons = {
+ activated = "";
+ deactivated = "";
+ };
+ };
+ tray = {
+ spacing = 10;
+ };
+ clock = {
+ tooltip-format = "{:%Y %B}\n{calendar}";
+ format = "{:%H:%M}";
+ };
+ cpu = {
+ format = "{usage}% ";
+ tooltip = false;
+ };
+ memory = {
+ format = "{}% ";
+ };
+ temperature = {
+ critical-threshold = 80;
+ format = "{temperatureC}℃ {icon}";
+ format-icons = ["" "" ""];
+ };
+ backlight = {
+ format = "{percent}% {icon}";
+ format-icons = ["" ""];
+ };
+ battery = {
+ states = {
+ warning = 30;
+ critical = 15;
+ };
+ format = "{capacity}% {icon}";
+ format-charging = "{capacity}% ";
+ format-plugged = "{capacity}% ";
+ format-alt = "{time} {icon}";
+ format-icons = ["" "" "" "" ""];
+ };
+ "battery#bat2" = {
+ bat = "BAT2";
+ };
+ network = {
+ format-wifi = " {essid} {ipaddr}";
+ format-ethernet = " {ipaddr}";
+ };
+ pulseaudio = {
+ format = "{icon} {volume}%";
+ format-icons = {
+ headphone = "";
+ hands-free = "";
+ headset = "";
+ phone = "";
+ portable = "";
+ car = "";
+ default = ["" "" ""];
+ };
+ on-click = "${pkgs.pavucontrol}/bin/pavucontrol";
+ };
+ };
+ };
+ };
+}
diff --git a/config/programs/zsh.nix b/config/programs/zsh.nix
index c667e1f9..d9e97fa7 100644
--- a/config/programs/zsh.nix
+++ b/config/programs/zsh.nix
@@ -7,6 +7,14 @@ desktop: _: {
syntaxHighlighting.enable = true;
enableVteIntegration = desktop;
autocd = true;
+ loginExtra =
+ if desktop
+ then ''
+ if [[ -z "$DISPLAY" ]] && [[ $(tty) = "/dev/tty1" ]]; then
+ exec sway
+ fi
+ ''
+ else "";
};
};
}
diff --git a/config/services/kubo.nix b/config/services/kubo.nix
index 62b81dfe..efbda1e8 100644
--- a/config/services/kubo.nix
+++ b/config/services/kubo.nix
@@ -38,14 +38,14 @@
type = "measure";
}
{
- child = {
- compression = "none";
- path = "datastore";
- type = "levelds";
- };
- mountpoint = "/";
- prefix = "leveldb.datastore";
- type = "measure";
+ child = {
+ compression = "none";
+ path = "datastore";
+ type = "levelds";
+ };
+ mountpoint = "/";
+ prefix = "leveldb.datastore";
+ type = "measure";
}
];
type = "mount";
diff --git a/config/services/matrix-media-repo.nix b/config/services/matrix-media-repo.nix
index 037dd668..9dc8cbeb 100644
--- a/config/services/matrix-media-repo.nix
+++ b/config/services/matrix-media-repo.nix
@@ -66,7 +66,7 @@
"fc00::/7"
];
# user agent header was a mistake
- userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0, matrix-media-repo (like twitterbot; like telegrambot; like discordbot; like facebook; like whatsapp; like firefox/92; like vkshare) +https://github.com/DarkKirb/nixos-config/pull/264";
+ userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0, matrix-media-repo (like twitterbot; like telegrambot; like discordbot; like facebook; like whatsapp; like firefox/92; like vkshare) +https://github.com/DarkKirb/nixos-config/pull/264";
};
downloads = {
expireAfterDays = 7;
diff --git a/flake.lock b/flake.lock
index ba8d6941..802fee25 100644
--- a/flake.lock
+++ b/flake.lock
@@ -78,6 +78,32 @@
"type": "github"
}
},
+ "colorpickle": {
+ "inputs": {
+ "naersk": [
+ "naersk"
+ ],
+ "nixpkgs": [
+ "nixpkgs"
+ ],
+ "utils": [
+ "flake-utils"
+ ]
+ },
+ "locked": {
+ "lastModified": 1696800008,
+ "narHash": "sha256-dQ2Xf1K5qH18J7h3pzx4ffp6n1nwN+2L8jv6OBXPLzQ=",
+ "owner": "AgathaSorceress",
+ "repo": "colorpickle",
+ "rev": "a1a21aebbc9b9716136ab9cc6f77bf5346f8e7ba",
+ "type": "github"
+ },
+ "original": {
+ "owner": "AgathaSorceress",
+ "repo": "colorpickle",
+ "type": "github"
+ }
+ },
"dns": {
"inputs": {
"flake-utils": [
@@ -675,6 +701,27 @@
"type": "github"
}
},
+ "naersk": {
+ "inputs": {
+ "nixpkgs": [
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1698420672,
+ "narHash": "sha256-/TdeHMPRjjdJub7p7+w55vyABrsJlt5QkznPYy55vKA=",
+ "owner": "nix-community",
+ "repo": "naersk",
+ "rev": "aeb58d5e8faead8980a807c840232697982d47b9",
+ "type": "github"
+ },
+ "original": {
+ "owner": "nix-community",
+ "ref": "master",
+ "repo": "naersk",
+ "type": "github"
+ }
+ },
"nix": {
"inputs": {
"lowdown-src": "lowdown-src",
@@ -1066,6 +1113,7 @@
"root": {
"inputs": {
"chir-rs": "chir-rs",
+ "colorpickle": "colorpickle",
"dns": "dns",
"firefox": "firefox",
"flake-compat": "flake-compat",
@@ -1075,6 +1123,7 @@
"home-manager": "home-manager",
"lib-aggregate": "lib-aggregate",
"mozilla": "mozilla",
+ "naersk": "naersk",
"nix-gaming": "nix-gaming",
"nix-neovim": "nix-neovim",
"nix-packages": "nix-packages",
diff --git a/flake.nix b/flake.nix
index 42ad8fc7..fa485e4d 100644
--- a/flake.nix
+++ b/flake.nix
@@ -13,6 +13,12 @@ rec {
inputs.systems.follows = "systems";
inputs.treefmt-nix.follows = "treefmt-nix";
};
+ colorpickle = {
+ url = "github:AgathaSorceress/colorpickle";
+ inputs.naersk.follows = "naersk";
+ inputs.nixpkgs.follows = "nixpkgs";
+ inputs.utils.follows = "flake-utils";
+ };
dns = {
url = "github:DarkKirb/dns.nix";
inputs.flake-utils.follows = "flake-utils";
@@ -49,6 +55,10 @@ rec {
inputs.nixpkgs-lib.follows = "nixpkgs";
};
mozilla.url = "github:mozilla/nixpkgs-mozilla";
+ naersk = {
+ url = "github:nix-community/naersk/master";
+ inputs.nixpkgs.follows = "nixpkgs";
+ };
nix-gaming = {
url = "github:fufexan/nix-gaming";
inputs.nixpkgs.follows = "nixpkgs";
diff --git a/modules/mastodon.nix b/modules/mastodon.nix
deleted file mode 100644
index 71be9a8b..00000000
--- a/modules/mastodon.nix
+++ /dev/null
@@ -1,768 +0,0 @@
-{
- config,
- lib,
- pkgs,
- ...
-}: let
- cfg = config.services.mastodon;
- # We only want to create a database if we're actually going to connect to it.
- databaseActuallyCreateLocally = cfg.database.createLocally && cfg.database.host == "/run/postgresql";
-
- env =
- {
- RAILS_ENV = "production";
- NODE_ENV = "production";
-
- LD_PRELOAD = "${pkgs.jemalloc}/lib/libjemalloc.so";
-
- # mastodon-web concurrency.
- WEB_CONCURRENCY = toString cfg.webProcesses;
- MAX_THREADS = toString cfg.webThreads;
-
- # mastodon-streaming concurrency.
- STREAMING_CLUSTER_NUM = toString cfg.streamingProcesses;
-
- DB_USER = cfg.database.user;
-
- REDIS_HOST = cfg.redis.host;
- REDIS_PORT = toString cfg.redis.port;
- DB_HOST = cfg.database.host;
- DB_PORT = toString cfg.database.port;
- DB_NAME = cfg.database.name;
- LOCAL_DOMAIN = cfg.localDomain;
- SMTP_SERVER = cfg.smtp.host;
- SMTP_PORT = toString cfg.smtp.port;
- SMTP_FROM_ADDRESS = cfg.smtp.fromAddress;
- PAPERCLIP_ROOT_PATH = "/var/lib/mastodon/public-system";
- PAPERCLIP_ROOT_URL = "/system";
- ES_ENABLED =
- if (cfg.elasticsearch.host != null)
- then "true"
- else "false";
- ES_HOST = cfg.elasticsearch.host;
- ES_PORT = toString cfg.elasticsearch.port;
-
- TRUSTED_PROXY_IP = cfg.trustedProxy;
- }
- // (
- if cfg.smtp.authenticate
- then {SMTP_LOGIN = cfg.smtp.user;}
- else {}
- )
- // cfg.extraConfig;
-
- systemCallsList = ["@cpu-emulation" "@debug" "@keyring" "@ipc" "@mount" "@obsolete" "@privileged" "@setuid"];
-
- cfgService = {
- # User and group
- User = cfg.user;
- Group = cfg.group;
- # State directory and mode
- StateDirectory = "mastodon";
- StateDirectoryMode = "0750";
- # Logs directory and mode
- LogsDirectory = "mastodon";
- LogsDirectoryMode = "0750";
- # Proc filesystem
- ProcSubset = "pid";
- ProtectProc = "invisible";
- # Access write directories
- UMask = "0027";
- # Capabilities
- CapabilityBoundingSet = "";
- # Security
- NoNewPrivileges = true;
- # Sandboxing
- ProtectSystem = "strict";
- ProtectHome = true;
- PrivateTmp = true;
- PrivateDevices = true;
- PrivateUsers = true;
- ProtectClock = true;
- ProtectHostname = true;
- ProtectKernelLogs = true;
- ProtectKernelModules = true;
- ProtectKernelTunables = true;
- ProtectControlGroups = true;
- RestrictAddressFamilies = ["AF_UNIX" "AF_INET" "AF_INET6" "AF_NETLINK"];
- RestrictNamespaces = true;
- LockPersonality = true;
- MemoryDenyWriteExecute = false;
- RestrictRealtime = true;
- RestrictSUIDSGID = true;
- RemoveIPC = true;
- PrivateMounts = true;
- # System Call Filtering
- SystemCallArchitectures = "native";
- };
-
- envFile = pkgs.writeText "mastodon.env" (lib.concatMapStrings (s: s + "\n") (lib.concatLists (lib.mapAttrsToList
- (
- name: value:
- if value != null
- then [
- "${name}=\"${toString value}\""
- ]
- else []
- )
- env)));
-
- mastodonEnv = pkgs.writeShellScriptBin "mastodon-env" ''
- set -a
- export RAILS_ROOT="${cfg.package}"
- source "${envFile}"
- source /var/lib/mastodon/.secrets_env
- eval -- "\$@"
- '';
-in {
- options = {
- services.mastodon = {
- enable = lib.mkEnableOption "Mastodon, a federated social network server";
-
- configureNginx = lib.mkOption {
- description = ''
- Configure nginx as a reverse proxy for mastodon.
- Note that this makes some assumptions on your setup, and sets settings that will
- affect other virtualHosts running on your nginx instance, if any.
- Alternatively you can configure a reverse-proxy of your choice to serve these paths:
-
- / -> $(nix-instantiate --eval '<nixpkgs>' -A mastodon.outPath)/public
-
- / -> 127.0.0.1:{{ webPort }}
(If there was no file in the directory above.)
-
- /system/ -> /var/lib/mastodon/public-system/
-
- /api/v1/streaming/ -> 127.0.0.1:{{ streamingPort }}
-
- Make sure that websockets are forwarded properly. You might want to set up caching
- of some requests. Take a look at mastodon's provided nginx configuration at
- https://github.com/mastodon/mastodon/blob/master/dist/nginx.conf
.
- '';
- type = lib.types.bool;
- default = false;
- };
-
- user = lib.mkOption {
- description = ''
- User under which mastodon runs. If it is set to "mastodon",
- that user will be created, otherwise it should be set to the
- name of a user created elsewhere. In both cases,
- mastodon and a package containing only
- the shell script mastodon-env
will be added to
- the user's package set. To run a command from
- mastodon such as tootctl
- with the environment configured by this module use
- mastodon-env
, as in:
-
- mastodon-env tootctl accounts create newuser --email newuser@example.com
- '';
- type = lib.types.str;
- default = "mastodon";
- };
-
- group = lib.mkOption {
- description = ''
- Group under which mastodon runs.
- '';
- type = lib.types.str;
- default = "mastodon";
- };
-
- streamingPort = lib.mkOption {
- description = "TCP port used by the mastodon-streaming service.";
- type = lib.types.port;
- default = 55000;
- };
- streamingProcesses = lib.mkOption {
- description = ''
- Processes used by the mastodon-streaming service.
- Defaults to the number of CPU cores minus one.
- '';
- type = lib.types.nullOr lib.types.int;
- default = null;
- };
-
- webPort = lib.mkOption {
- description = "TCP port used by the mastodon-web service.";
- type = lib.types.port;
- default = 55001;
- };
- webProcesses = lib.mkOption {
- description = "Processes used by the mastodon-web service.";
- type = lib.types.int;
- default = 2;
- };
- webThreads = lib.mkOption {
- description = "Threads per process used by the mastodon-web service.";
- type = lib.types.int;
- default = 5;
- };
-
- sidekiqPort = lib.mkOption {
- description = "TCP port used by the mastodon-sidekiq service.";
- type = lib.types.port;
- default = 55002;
- };
- sidekiqThreads = lib.mkOption {
- description = "Worker threads used by the mastodon-sidekiq service.";
- type = lib.types.int;
- default = 25;
- };
-
- vapidPublicKeyFile = lib.mkOption {
- description = ''
- Path to file containing the public key used for Web Push
- Voluntary Application Server Identification. A new keypair can
- be generated by running:
-
- nix build -f '<nixpkgs>' mastodon; cd result; bin/rake webpush:generate_keys
-
- If does not
- exist, it and this file will be created with a new keypair.
- '';
- default = "/var/lib/mastodon/secrets/vapid-public-key";
- type = lib.types.str;
- };
-
- localDomain = lib.mkOption {
- description = "The domain serving your Mastodon instance.";
- example = "social.example.org";
- type = lib.types.str;
- };
-
- secretKeyBaseFile = lib.mkOption {
- description = ''
- Path to file containing the secret key base.
- A new secret key base can be generated by running:
-
- nix build -f '<nixpkgs>' mastodon; cd result; bin/rake secret
-
- If this file does not exist, it will be created with a new secret key base.
- '';
- default = "/var/lib/mastodon/secrets/secret-key-base";
- type = lib.types.str;
- };
-
- otpSecretFile = lib.mkOption {
- description = ''
- Path to file containing the OTP secret.
- A new OTP secret can be generated by running:
-
- nix build -f '<nixpkgs>' mastodon; cd result; bin/rake secret
-
- If this file does not exist, it will be created with a new OTP secret.
- '';
- default = "/var/lib/mastodon/secrets/otp-secret";
- type = lib.types.str;
- };
-
- vapidPrivateKeyFile = lib.mkOption {
- description = ''
- Path to file containing the private key used for Web Push
- Voluntary Application Server Identification. A new keypair can
- be generated by running:
-
- nix build -f '<nixpkgs>' mastodon; cd result; bin/rake webpush:generate_keys
-
- If this file does not exist, it will be created with a new
- private key.
- '';
- default = "/var/lib/mastodon/secrets/vapid-private-key";
- type = lib.types.str;
- };
-
- s3AccessKeyIdFile = lib.mkOption {
- type = lib.types.str;
- };
- s3SecretAccessKeyFile = lib.mkOption {
- type = lib.types.str;
- };
-
- trustedProxy = lib.mkOption {
- description = ''
- You need to set it to the IP from which your reverse proxy sends requests to Mastodon's web process,
- otherwise Mastodon will record the reverse proxy's own IP as the IP of all requests, which would be
- bad because IP addresses are used for important rate limits and security functions.
- '';
- type = lib.types.str;
- default = "127.0.0.1";
- };
-
- enableUnixSocket = lib.mkOption {
- description = ''
- Instead of binding to an IP address like 127.0.0.1, you may bind to a Unix socket. This variable
- is process-specific, e.g. you need different values for every process, and it works for both web (Puma)
- processes and streaming API (Node.js) processes.
- '';
- type = lib.types.bool;
- default = true;
- };
-
- redis = {
- createLocally = lib.mkOption {
- description = "Configure local Redis server for Mastodon.";
- type = lib.types.bool;
- default = true;
- };
-
- host = lib.mkOption {
- description = "Redis host.";
- type = lib.types.str;
- default = "127.0.0.1";
- };
-
- port = lib.mkOption {
- description = "Redis port.";
- type = lib.types.port;
- default = 6379;
- };
- };
-
- database = {
- createLocally = lib.mkOption {
- description = "Configure local PostgreSQL database server for Mastodon.";
- type = lib.types.bool;
- default = true;
- };
-
- host = lib.mkOption {
- type = lib.types.str;
- default = "/run/postgresql";
- example = "192.168.23.42";
- description = "Database host address or unix socket.";
- };
-
- port = lib.mkOption {
- type = lib.types.int;
- default = 5432;
- description = "Database host port.";
- };
-
- name = lib.mkOption {
- type = lib.types.str;
- default = "mastodon";
- description = "Database name.";
- };
-
- user = lib.mkOption {
- type = lib.types.str;
- default = "mastodon";
- description = "Database user.";
- };
-
- passwordFile = lib.mkOption {
- type = lib.types.nullOr lib.types.path;
- default = "/var/lib/mastodon/secrets/db-password";
- example = "/run/keys/mastodon-db-password";
- description = ''
- A file containing the password corresponding to
- .
- '';
- };
- };
-
- smtp = {
- createLocally = lib.mkOption {
- description = "Configure local Postfix SMTP server for Mastodon.";
- type = lib.types.bool;
- default = true;
- };
-
- authenticate = lib.mkOption {
- description = "Authenticate with the SMTP server using username and password.";
- type = lib.types.bool;
- default = false;
- };
-
- host = lib.mkOption {
- description = "SMTP host used when sending emails to users.";
- type = lib.types.str;
- default = "127.0.0.1";
- };
-
- port = lib.mkOption {
- description = "SMTP port used when sending emails to users.";
- type = lib.types.port;
- default = 25;
- };
-
- fromAddress = lib.mkOption {
- description = ''"From" address used when sending Emails to users.'';
- type = lib.types.str;
- };
-
- user = lib.mkOption {
- description = "SMTP login name.";
- type = lib.types.str;
- };
-
- passwordFile = lib.mkOption {
- description = ''
- Path to file containing the SMTP password.
- '';
- default = "/var/lib/mastodon/secrets/smtp-password";
- example = "/run/keys/mastodon-smtp-password";
- type = lib.types.str;
- };
- };
-
- elasticsearch = {
- host = lib.mkOption {
- description = ''
- Elasticsearch host.
- If it is not null, Elasticsearch full text search will be enabled.
- '';
- type = lib.types.nullOr lib.types.str;
- default = null;
- };
-
- port = lib.mkOption {
- description = "Elasticsearch port.";
- type = lib.types.port;
- default = 9200;
- };
- };
-
- package = lib.mkOption {
- type = lib.types.package;
- default = pkgs.mastodon;
- defaultText = lib.literalExpression "pkgs.mastodon";
- description = "Mastodon package to use.";
- };
-
- extraConfig = lib.mkOption {
- type = lib.types.attrs;
- default = {};
- description = ''
- Extra environment variables to pass to all mastodon services.
- '';
- };
-
- automaticMigrations = lib.mkOption {
- type = lib.types.bool;
- default = true;
- description = ''
- Do automatic database migrations.
- '';
- };
- };
- };
-
- disabledModules = ["services/web-apps/mastodon.nix"];
-
- config = lib.mkIf cfg.enable {
- assertions = [
- {
- assertion = databaseActuallyCreateLocally -> (cfg.user == cfg.database.user);
- message = ''For local automatic database provisioning (services.mastodon.database.createLocally == true) with peer authentication (services.mastodon.database.host == "/run/postgresql") to work services.mastodon.user and services.mastodon.database.user must be identical.'';
- }
- ];
-
- systemd.services.mastodon-init-dirs = {
- script =
- ''
- umask 077
-
- if ! test -f ${cfg.secretKeyBaseFile}; then
- mkdir -p $(dirname ${cfg.secretKeyBaseFile})
- bin/rake secret > ${cfg.secretKeyBaseFile}
- fi
- if ! test -f ${cfg.otpSecretFile}; then
- mkdir -p $(dirname ${cfg.otpSecretFile})
- bin/rake secret > ${cfg.otpSecretFile}
- fi
- if ! test -f ${cfg.vapidPrivateKeyFile}; then
- mkdir -p $(dirname ${cfg.vapidPrivateKeyFile}) $(dirname ${cfg.vapidPublicKeyFile})
- keypair=$(bin/rake webpush:generate_keys)
- echo $keypair | grep --only-matching "Private -> [^ ]\+" | sed 's/^Private -> //' > ${cfg.vapidPrivateKeyFile}
- echo $keypair | grep --only-matching "Public -> [^ ]\+" | sed 's/^Public -> //' > ${cfg.vapidPublicKeyFile}
- fi
-
- cat > /var/lib/mastodon/.secrets_env <