├── .envrc ├── .gitignore ├── .projectile ├── .vscode └── tasks.json ├── LICENSE ├── README.md ├── compat └── default.nix ├── default.nix ├── flake.lock ├── flake.nix ├── lib.nix ├── machines ├── AMD-Workstation │ ├── default.nix │ ├── hardware-configuration.nix │ └── system ├── Librem5-Phone │ ├── default.nix │ ├── hardware-configuration.nix │ └── system ├── RasPi-Server │ ├── default.nix │ ├── hardware-configuration.nix │ └── system ├── T420-Laptop │ ├── default.nix │ ├── hardware-configuration.nix │ └── system ├── T490s-Laptop │ ├── default.nix │ ├── hardware-configuration.nix │ └── system ├── X2100-Laptop │ ├── default.nix │ ├── hardware-configuration.nix │ └── system ├── iso-image │ ├── default.nix │ └── system ├── server │ ├── default.nix │ └── system └── usb-persist │ ├── default.nix │ ├── hardware-configuration.nix │ └── system ├── modules ├── applications.nix ├── bt-agent.nix ├── devices.nix ├── ezwg.nix ├── persist.nix ├── plasma5.nix ├── secrets-envsubst.nix ├── secrets.nix └── themes.nix ├── overlay.nix ├── profiles ├── applications-setup.nix ├── applications │ ├── aerc.nix │ ├── alacritty.nix │ ├── angelfish.nix │ ├── cantata.nix │ ├── emacs │ │ ├── default.nix │ │ ├── init.el │ │ └── org-gcal-config.el │ ├── firefox.nix │ ├── geary.nix │ ├── github.nix │ ├── gwenview.nix │ ├── helix.nix │ ├── himalaya.nix │ ├── josm.nix │ ├── nheko.nix │ ├── okular.nix │ ├── packages.nix │ ├── qmlkonsole.nix │ ├── slack.nix │ ├── sylpheed.nix │ └── vscodium │ │ ├── default.nix │ │ ├── extensions.nix │ │ └── theme.nix ├── bluetooth.nix ├── boot.nix ├── hardware.nix ├── network.nix ├── nix │ ├── default.nix │ └── expr-context.patch ├── opengl.nix ├── power.nix ├── security │ ├── pass-secret-service.nix │ ├── user.nix │ ├── vlock.nix │ └── yubikey.nix ├── servers │ ├── gitea.nix │ ├── home-assistant.nix │ ├── irc.nix │ ├── jitsi.nix │ ├── mailserver.nix │ ├── mastodon.nix │ ├── matrix-synapse.nix │ ├── minidlna.nix │ ├── nextcloud.nix │ ├── nginx.nix │ ├── ntfy.nix │ ├── remapper.nix │ └── vsftpd.nix ├── sound.nix ├── virtualisation.nix └── workspace │ ├── autoRun.nix │ ├── aws.nix │ ├── btop │ └── default.nix │ ├── cage.nix │ ├── copyq.nix │ ├── cursor.nix │ ├── direnv.nix │ ├── fonts.nix │ ├── git.nix │ ├── gnome3 │ ├── accounts.conf │ ├── default.nix │ └── nextcloud.source │ ├── gpg.nix │ ├── gtk.nix │ ├── i3blocks │ ├── default.nix │ └── scripts │ │ ├── battery.nix │ │ ├── bluetooth.nix │ │ ├── brightness.nix │ │ ├── connections.nix │ │ ├── default.nix │ │ ├── emacs.nix │ │ ├── email.nix │ │ ├── free.hs │ │ ├── free.nix │ │ ├── hydra-status.nix │ │ ├── music.nix │ │ ├── network.hs │ │ ├── sound.nix │ │ ├── temperature.hs │ │ ├── temperature.nix │ │ └── weather.nix │ ├── kanshi.nix │ ├── kde │ ├── kdeconnect.nix │ ├── plasma-mobile.nix │ └── qt.nix │ ├── light.nix │ ├── locale │ ├── compose │ └── default.nix │ ├── mako.nix │ ├── misc.nix │ ├── mopidy.nix │ ├── openvpn.nix │ ├── print-scan │ └── default.nix │ ├── rclone.nix │ ├── shadowsocks.nix │ ├── simple-osd-daemons.nix │ ├── ssh.nix │ ├── sway │ └── default.nix │ ├── xdg.nix │ ├── yubikey-touch-detector.nix │ └── zsh │ ├── default.nix │ └── p10k.zsh ├── roles ├── base.nix ├── default.nix ├── desktop.nix └── server.nix └── shell.nix /.envrc: -------------------------------------------------------------------------------- 1 | use flake 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | \#*\# 3 | auto-save-list 4 | tramp 5 | .\#* 6 | result 7 | *\.qcow2 8 | .direnv -------------------------------------------------------------------------------- /.projectile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balsoft/nixos-config/d3a2e32bbf74d779629803965e945fcf29d1c1ec/.projectile -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "Build", 6 | "type": "shell", 7 | "command": "nixos-rebuild", 8 | "args": [ 9 | "build", 10 | "--flake", 11 | "${workspaceFolder}" 12 | ], 13 | "problemMatcher": [], 14 | "group": { 15 | "kind": "build", 16 | "isDefault": true 17 | } 18 | }, 19 | { 20 | "label": "Switch", 21 | "type": "shell", 22 | "command": "nixos-rebuild", 23 | "args": [ 24 | "switch", 25 | "--flake", 26 | "${workspaceFolder}", 27 | "--use-remote-sudo" 28 | ], 29 | "problemMatcher": [] 30 | } 31 | ] 32 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | 26 | This software was originally created by Alexander Bantyev aka balsoft, 27 | but you may omit any notices of original author in your dealings with 28 | software. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # balsoft’s nixos configuration 2 | 3 | ## License 4 | 5 | Most of this config is in public domain (see [LICENSE](./LICENSE)). 6 | 7 | ## Stuff that may be useful 8 | 9 | ### Secrets 10 | 11 | Secrets are kept in a separate (private) git repository, encrypted with 12 | gpg and decrypted at runtime using [secrets.nix](./modules/secrets.nix) 13 | and [secrets-envsubst.nix](./modules/secrets-envsubst.nix). The repo is 14 | `pass(1)`-compatible, so passwords are also stored there. 15 | 16 | _pls no pwn_ 17 | 18 | ### Themes 19 | 20 | Themes for everything are generated from a custom base16 theme. The theme 21 | is defined in [themes.nix](./modules/themes.nix), and the generation is spread all around 22 | [modules](./modules). 23 | 24 | ### Tmpfs root 25 | 26 | To prevent extraneous state from clinging on the drive, I am using tmpfs 27 | root on my two main devices. It is implemented in [persist.nix](./modules/persist.nix). 28 | 29 | ### Easy Wireguard setup module 30 | 31 | Copied from notgne2 with permission to redistribute as public domain software. 32 | Can be found in [ezwg.nix](./modules/ezwg.nix) 33 | 34 | ## Installing it on your machine 35 | 36 | 1. Add a config for your device to `machines` (it has to set `deviceSpecific.devInfo`, import your `hardware-configuration.nix` and one of the profiles, and contain a `system` file); 37 | 2. `sudo nixos-rebuild test --flake .` 38 | -------------------------------------------------------------------------------- /compat/default.nix: -------------------------------------------------------------------------------- 1 | { ... }: (builtins.getFlake (toString ../.)).legacyPackages.${builtins.currentSystem} 2 | -------------------------------------------------------------------------------- /default.nix: -------------------------------------------------------------------------------- 1 | { ... }: 2 | let 3 | self = (import (let lock = builtins.fromJSON (builtins.readFile ./flake.lock); 4 | in fetchTarball { 5 | url = 6 | "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; 7 | sha256 = lock.nodes.flake-compat.locked.narHash; 8 | }) { src = ./.; }).defaultNix; 9 | in self // self.legacyPackages.${builtins.currentSystem} 10 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = 3 | "A collection of crap, hacks and copy-paste to make my localhosts boot"; 4 | 5 | nixConfig.substituters = [ "https://cache.nixos.org" ]; 6 | 7 | inputs = { 8 | nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; 9 | # For NUR 10 | nixpkgs-old = { 11 | url = "github:nixos/nixpkgs/nixos-19.09"; 12 | flake = false; 13 | }; 14 | # For aerc 15 | nixpkgs-24-05.url = "github:nixos/nixpkgs/nixos-24.05"; 16 | 17 | lambda-launcher.url = "github:balsoft/lambda-launcher"; 18 | deploy-rs.url = "github:serokell/deploy-rs"; 19 | flake-compat = { 20 | url = "github:edolstra/flake-compat"; 21 | flake = false; 22 | }; 23 | NUR = { 24 | url = "github:nix-community/NUR"; 25 | flake = false; 26 | }; 27 | base16-black-metal-scheme = { 28 | url = "github:metalelf0/base16-black-metal-scheme"; 29 | flake = false; 30 | }; 31 | home-manager.url = "github:rycee/home-manager"; 32 | materia-theme = { 33 | url = "github:nana-4/materia-theme"; 34 | flake = false; 35 | }; 36 | simple-nixos-mailserver = { 37 | url = "gitlab:simple-nixos-mailserver/nixos-mailserver"; 38 | flake = false; 39 | }; 40 | nixpkgs-wayland = { 41 | url = "github:colemickens/nixpkgs-wayland"; 42 | flake = false; 43 | }; 44 | nixos-fhs-compat.url = "github:balsoft/nixos-fhs-compat"; 45 | simple-osd-daemons.url = "github:balsoft/simple-osd-daemons"; 46 | impermanence.url = "github:nix-community/impermanence"; 47 | 48 | rycee = { 49 | url = "gitlab:rycee/nur-expressions"; 50 | flake = false; 51 | }; 52 | 53 | nix-direnv = { url = "github:nix-community/nix-direnv"; }; 54 | 55 | flake-registry = { 56 | url = "github:nixos/flake-registry"; 57 | flake = false; 58 | }; 59 | 60 | remapper.url = "github:balsoft/remapper"; 61 | 62 | helix.url = "github:helix-editor/helix"; 63 | 64 | nixos-hardware.url = "github:nixos/nixos-hardware"; 65 | }; 66 | 67 | outputs = { nixpkgs, self, nix, deploy-rs, ... }@inputs: 68 | let 69 | findModules = dir: 70 | builtins.concatLists (builtins.attrValues (builtins.mapAttrs 71 | (name: type: 72 | if type == "regular" then [{ 73 | name = builtins.elemAt (builtins.match "(.*)\\.nix" name) 0; 74 | value = dir + "/${name}"; 75 | }] else if (builtins.readDir (dir + "/${name}")) 76 | ? "default.nix" then [{ 77 | inherit name; 78 | value = dir + "/${name}"; 79 | }] else 80 | findModules (dir + "/${name}")) (builtins.readDir dir))); 81 | pkgsFor = system: 82 | import inputs.nixpkgs { 83 | overlays = [ self.overlay ]; 84 | localSystem = { inherit system; }; 85 | config = { 86 | android_sdk.accept_license = true; 87 | permittedInsecurePackages = [ "openssl-1.1.1v" "olm-3.2.16" ]; 88 | allowUnfreePredicate = (pkg: pkg.pname or null == "firmware-imx"); 89 | allowlistedLicenses = with inputs.nixpkgs.lib.licenses; [ epson ]; 90 | }; 91 | }; 92 | in { 93 | nixosModules = builtins.listToAttrs (findModules ./modules); 94 | 95 | nixosProfiles = builtins.listToAttrs (findModules ./profiles); 96 | 97 | nixosRoles = import ./roles; 98 | 99 | nixosConfigurations = with nixpkgs.lib; 100 | let 101 | hosts = builtins.attrNames (builtins.readDir ./machines); 102 | 103 | mkHost = name: 104 | let 105 | system = builtins.readFile (./machines + "/${name}/system"); 106 | pkgs = pkgsFor system; 107 | in nixosSystem { 108 | inherit system; 109 | modules = __attrValues self.nixosModules ++ [ 110 | inputs.home-manager.nixosModules.home-manager 111 | 112 | { 113 | disabledModules = 114 | [ "services/x11/desktop-managers/plasma5.nix" ]; 115 | } 116 | 117 | (import (./machines + "/${name}")) 118 | { nixpkgs.pkgs = pkgs; } 119 | { device = name; } 120 | ]; 121 | specialArgs = { inherit inputs; }; 122 | }; 123 | in genAttrs hosts mkHost; 124 | 125 | legacyPackages.x86_64-linux = pkgsFor "x86_64-linux"; 126 | 127 | defaultApp = deploy-rs.defaultApp; 128 | 129 | overlay = import ./overlay.nix inputs; 130 | 131 | lib = import ./lib.nix nixpkgs.lib; 132 | 133 | devShell.x86_64-linux = with nixpkgs.legacyPackages.x86_64-linux; 134 | mkShell { 135 | buildInputs = [ 136 | nix.packages.x86_64-linux.default 137 | deploy-rs.defaultPackage.x86_64-linux 138 | nixfmt-rfc-style 139 | nil 140 | ]; 141 | shellHook = '' 142 | linkFile() { 143 | source="$(nix build --print-out-paths "$1.source" || nix eval --raw "$1.source")" 144 | target="$(nix eval --raw "$1.target")" 145 | ln -fs "$source" "$HOME/$target" 146 | } 147 | linkHomeManagerFile() { 148 | linkFile ".#nixosConfigurations.$(hostname).config.home-manager.users.$(whoami).$1" 149 | } 150 | linkConfigFile() { 151 | linkHomeManagerFile "xdg.configFile.\"$1\"" 152 | } 153 | linkDataFile() { 154 | linkHomeManagerFile "xdg.dataFile.\"$1\"" 155 | } 156 | linkHomeFile() { 157 | linkHomeManagerFile "home.file.\"$1\"" 158 | } 159 | ''; 160 | }; 161 | 162 | deploy = { 163 | user = "root"; 164 | nodes = (builtins.mapAttrs (name: machine: 165 | let activateable = name == "T420-Laptop" || name == "RasPi-Server"; 166 | in { 167 | hostname = machine.config.networking.hostName; 168 | profiles.system = { 169 | user = if activateable then "root" else "balsoft"; 170 | path = with deploy-rs.lib.${machine.pkgs.system}.activate; 171 | if activateable then 172 | nixos machine 173 | else 174 | noop machine.config.system.build.toplevel; 175 | }; 176 | }) self.nixosConfigurations); 177 | }; 178 | }; 179 | } 180 | -------------------------------------------------------------------------------- /lib.nix: -------------------------------------------------------------------------------- 1 | lib: rec { 2 | mkKeyValue = key: value: 3 | let 4 | mvalue = if builtins.isBool value then 5 | (if value then "true" else "false") 6 | else if builtins.isString value then 7 | value 8 | else 9 | builtins.toString value; 10 | in "${key}=${mvalue}"; 11 | attrsToList = with builtins; 12 | x: 13 | (map (key: { 14 | name = key; 15 | value = getAttr key x; 16 | }) (attrNames x)); 17 | 18 | genIni = lib.generators.toINI { inherit mkKeyValue; }; 19 | genIniOrdered = lst: 20 | (builtins.concatStringsSep "\n" (map ({ name ? "widget", ... }@attrs: 21 | builtins.concatStringsSep "\n" ([ "[${name}]" ] 22 | ++ (map ({ name, value }: mkKeyValue name value) 23 | (attrsToList (builtins.removeAttrs attrs [ "name" ]))))) lst)) + "\n"; 24 | splitHex = hexStr: 25 | map (x: builtins.elemAt x 0) 26 | (builtins.filter (a: a != "" && a != [ ]) (builtins.split "(.{2})" hexStr)); 27 | hex2decDigits = rec { 28 | "0" = 0; 29 | "1" = 1; 30 | "2" = 2; 31 | "3" = 3; 32 | "4" = 4; 33 | "5" = 5; 34 | "6" = 6; 35 | "7" = 7; 36 | "8" = 8; 37 | "9" = 9; 38 | "a" = 10; 39 | "b" = 11; 40 | "c" = 12; 41 | "d" = 13; 42 | "e" = 14; 43 | "f" = 15; 44 | A = a; 45 | B = b; 46 | C = c; 47 | D = d; 48 | E = e; 49 | F = f; 50 | }; 51 | 52 | dec2hexDigits = lib.mapAttrs' (lib.flip lib.nameValuePair) 53 | (builtins.mapAttrs (_: toString) hex2decDigits); 54 | 55 | doubleDigitHexToDec = hex: 56 | 16 * hex2decDigits."${builtins.substring 0 1 hex}" 57 | + hex2decDigits."${builtins.substring 1 2 hex}"; 58 | 59 | decToHex = n: dec2hexDigits.${toString (builtins.div n 16)} + dec2hexDigits.${toString (builtins.mod n 16)}; 60 | 61 | thmDec = builtins.mapAttrs (name: color: colorHex2Dec color); 62 | thmHash = builtins.mapAttrs (name: color: "#${color}"); 63 | 64 | triplet2RGB = lst: { 65 | r = builtins.elemAt lst 0; 66 | g = builtins.elemAt lst 1; 67 | b = builtins.elemAt lst 2; 68 | }; 69 | 70 | hex2RGB = color: triplet2RGB (map doubleDigitHexToDec (splitHex color)); 71 | dec2RGB = color: triplet2RGB (map (builtins.fromJSON) (lib.splitString "," color)); 72 | 73 | RGB2hex = { r, g, b }: decToHex r + decToHex g + decToHex b; 74 | RGB2dec = { r, g, b }: lib.concatMapStringsSep "," toString [ r g b ]; 75 | 76 | mulRGB = factor: builtins.mapAttrs (_: x: builtins.floor (x * factor)); 77 | 78 | mulHex = factor: color: RGB2hex (mulRGB factor (hex2RGB color)); 79 | 80 | mulDec = factor: color: RGB2dec (mulRGB factor (dec2RGB color)); 81 | 82 | colorHex2Dec = color: 83 | builtins.concatStringsSep "," 84 | (map (x: toString (doubleDigitHexToDec x)) (splitHex color)); 85 | 86 | } 87 | -------------------------------------------------------------------------------- /machines/AMD-Workstation/default.nix: -------------------------------------------------------------------------------- 1 | { config, inputs, pkgs, ... }: { 2 | imports = [ 3 | ./hardware-configuration.nix 4 | inputs.self.nixosRoles.desktop 5 | inputs.self.nixosProfiles.print-scan 6 | inputs.self.nixosProfiles.aws 7 | ]; 8 | deviceSpecific.devInfo = { 9 | cpu = { 10 | vendor = "amd"; 11 | clock = 4200; 12 | cores = 8; 13 | }; 14 | drive = { 15 | type = "ssd"; 16 | speed = 6000; 17 | size = 250; 18 | }; 19 | bigScreen = true; 20 | ram = 32; 21 | }; 22 | deviceSpecific.isHost = true; 23 | boot.binfmt.emulatedSystems = [ "aarch64-linux" ]; 24 | 25 | # services.apcupsd = { 26 | # enable = true; 27 | # configText = '' 28 | # UPSTYPE usb 29 | # NISIP 127.0.0.1 30 | # BATTERYLEVEL 10 31 | # MINUTES 1 32 | # ''; 33 | # }; 34 | 35 | secrets.wireguard-wg0 = { }; 36 | 37 | environment.sessionVariables.WINEPREFIX = 38 | "/home/balsoft/.local/share/wineprefixes/default"; 39 | 40 | services.bt-agent = { 41 | enable = true; 42 | capability = "NoInputNoOutput"; 43 | }; 44 | 45 | secrets.restic-backup-password = { }; 46 | secrets.restic-backup-environment = { }; 47 | 48 | services.restic.backups.b2 = { 49 | inhibitsSleep = true; 50 | passwordFile = config.secrets.restic-backup-password.decrypted; 51 | environmentFile = config.secrets.restic-backup-environment.decrypted; 52 | paths = [ 53 | "/home/balsoft/Documents" # Documents, typically not in git 54 | "/etc/NetworkManager/system-connections" # NetworkManager's wifi networks and stuff 55 | ]; 56 | # Find all projects with uncommited changes 57 | dynamicFilesFrom = '' 58 | ${pkgs.git}/bin/git config set --global safe.directory '*' # Git dirs owned by another users, should be fine 59 | for gitdir in $(${pkgs.findutils}/bin/find /home/balsoft/projects -name .git -type d -prune); do 60 | dir="$(dirname "$gitdir")"; 61 | if \ 62 | [[ -n "$(${pkgs.git}/bin/git -C "$dir" status --untracked-files=no --porcelain)" ]] \ 63 | || [[ -n "$(${pkgs.git}/bin/git -C "$dir" log --format=short --branches --not --remotes)" ]]; 64 | then printf "%s\n" "$dir"; 65 | fi; 66 | done; 67 | ${pkgs.git}/bin/git config unset --global safe.directory 68 | ''; 69 | repository = "s3:s3.eu-central-003.backblazeb2.com/balsoft-backups"; 70 | pruneOpts = [ "--keep-daily 7" "--keep-weekly 3" "--keep-monthly 3" ]; 71 | # Typically I'm done writing stuff by then, save the day's work 72 | timerConfig = { 73 | OnCalendar = "22:00"; 74 | Persistent = true; 75 | }; 76 | }; 77 | 78 | systemd.services.restic-backups-b2.wants = [ 79 | "restic-backup-password-secrets.service" 80 | "restic-backup-environment-secrets.service" 81 | ]; 82 | systemd.services.restic-backups-b2.requires = [ 83 | "restic-backup-password-secrets.service" 84 | "restic-backup-environment-secrets.service" 85 | ]; 86 | 87 | hardware.bluetooth.input.General.UserspaceHID = true; 88 | 89 | persist = { 90 | enable = true; 91 | cache.clean.enable = false; # Scary... 92 | 93 | state.directories = [ "/home/balsoft/.local/share/Steam" ]; 94 | 95 | derivative.directories = 96 | [ "/home/balsoft/.local/share/wineprefixes/default" ]; 97 | }; 98 | } 99 | -------------------------------------------------------------------------------- /machines/AMD-Workstation/hardware-configuration.nix: -------------------------------------------------------------------------------- 1 | # Do not modify this file! It was generated by ‘nixos-generate-config’ 2 | # and may be overwritten by future invocations. Please make changes 3 | # to /etc/nixos/configuration.nix instead. 4 | { config, lib, pkgs, inputs, ... }: 5 | 6 | { 7 | imports = 8 | [ "${inputs.nixpkgs}/nixos/modules/installer/scan/not-detected.nix" ]; 9 | 10 | boot.initrd.availableKernelModules = 11 | [ "nvme" "xhci_pci" "ahci" "usb_storage" "sd_mod" ]; 12 | boot.kernelModules = [ "kvm-amd" ]; 13 | boot.extraModulePackages = [ ]; 14 | powerManagement.cpuFreqGovernor = lib.mkDefault "performance"; 15 | 16 | fileSystems."/persist" = { 17 | device = "/dev/nvme0n1p2"; 18 | fsType = "ext4"; 19 | neededForBoot = true; 20 | }; 21 | 22 | fileSystems."/persist/home" = { 23 | device = "/dev/disk/by-label/Home"; 24 | fsType = "ext4"; 25 | neededForBoot = true; 26 | }; 27 | 28 | fileSystems."/boot" = { 29 | device = "/dev/nvme0n1p1"; 30 | fsType = "vfat"; 31 | }; 32 | 33 | swapDevices = [ ]; 34 | 35 | nix.settings.max-jobs = lib.mkDefault 32; 36 | } 37 | -------------------------------------------------------------------------------- /machines/AMD-Workstation/system: -------------------------------------------------------------------------------- 1 | x86_64-linux -------------------------------------------------------------------------------- /machines/Librem5-Phone/default.nix: -------------------------------------------------------------------------------- 1 | { inputs, pkgs, lib, ... }: { 2 | imports = with inputs.self; 3 | with nixosProfiles; [ 4 | ./hardware-configuration.nix 5 | 6 | nixosRoles.base 7 | 8 | inputs.nixos-hardware.nixosModules.purism-librem-5r4 9 | 10 | # applications-setup 11 | bluetooth 12 | power 13 | hardware 14 | sound 15 | 16 | # plasma-mobile 17 | # phosh 18 | 19 | # nheko 20 | # okular 21 | # gwenview 22 | # aerc 23 | # helix 24 | # angelfish 25 | nix 26 | # qmlkonsole 27 | 28 | # kdeconnect 29 | # cursor 30 | # fonts 31 | # gtk 32 | # qt 33 | # shadowsocks 34 | 35 | pass-secret-service 36 | ]; 37 | 38 | hardware.librem5.audio = false; 39 | 40 | programs.ssh.askPassword = 41 | "${pkgs.plasma5Packages.ksshaskpass.out}/bin/ksshaskpass"; 42 | 43 | users.users.balsoft.password = lib.mkForce "0"; 44 | 45 | system.stateVersion = "23.05"; 46 | home-manager.users.balsoft.home.stateVersion = "22.11"; 47 | 48 | themes.fonts = { 49 | main.size = 10; 50 | serif.size = 10; 51 | mono.size = 11; 52 | }; 53 | 54 | environment.systemPackages = [ pkgs.pure-maps (pkgs.organicmaps.overrideAttrs (_: {meta = {};})) pkgs.plasma5Packages.elisa ]; 55 | 56 | environment.etc."gnss-share.conf".text = '' 57 | # Socket to sent NMEA location to 58 | socket="/var/run/gnss-share.sock" 59 | # Group to set as owner for the socket 60 | group="geoclue" 61 | 62 | # GPS device driver to use 63 | # Supported values: stm, stm_serial 64 | device_driver="stm" 65 | 66 | # Path to GPS device to use 67 | device_path="/dev/gnss0" 68 | 69 | # Baud rate for GPS serial device 70 | device_baud_rate=9600 71 | 72 | # Directory to load/store almanac and ephemeris data 73 | agps_directory="/var/cache/gnss-share" 74 | ''; 75 | 76 | systemd.services.gnss-share = { 77 | script = "gnss-share"; 78 | description = "GNSS location manager"; 79 | path = [ pkgs.gnss-share ]; 80 | wantedBy = [ "multi-user.target" ]; 81 | before = [ "geoclue.service" ]; 82 | }; 83 | 84 | environment.etc."geoclue/geoclue.conf".text = lib.mkForce 85 | (lib.generators.toINI { } { 86 | network-nmea = { 87 | enable = true; 88 | nmea-socket = "/var/run/gnss-share.sock"; 89 | }; 90 | modem-gps.enable = true; 91 | cdma.enable = true; 92 | "3g".enable = true; 93 | agent.whitelist = "geoclue-demo-agent"; 94 | wifi = { 95 | enable = true; 96 | url = "https://location.services.mozilla.com/v1/geolocate?key=geoclue"; 97 | }; 98 | }); 99 | 100 | home-manager.users.balsoft.programs.git.signing.signByDefault = 101 | lib.mkForce false; 102 | } 103 | -------------------------------------------------------------------------------- /machines/Librem5-Phone/hardware-configuration.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, modulesPath, ... }: 2 | 3 | { 4 | imports = 5 | [ (modulesPath + "/installer/scan/not-detected.nix") 6 | ]; 7 | 8 | 9 | fileSystems."/" = { 10 | device = "/dev/mmcblk0p2"; 11 | fsType = "ext4"; 12 | }; 13 | 14 | fileSystems."/boot" = { 15 | device = "/dev/mmcblk0p1"; 16 | fsType = "ext2"; 17 | }; 18 | 19 | swapDevices = [ ]; 20 | 21 | # Enables DHCP on each ethernet and wireless interface. In case of scripted networking 22 | # (the default) this is the recommended approach. When using systemd-networkd it's 23 | # still possible to use this option, but it's recommended to use it in conjunction 24 | # with explicit per-interface declarations with `networking.interfaces..useDHCP`. 25 | networking.useDHCP = lib.mkDefault true; 26 | # networking.interfaces.wlan0.useDHCP = lib.mkDefault true; 27 | 28 | nixpkgs.hostPlatform = lib.mkDefault "aarch64-linux"; 29 | powerManagement.cpuFreqGovernor = lib.mkDefault "ondemand"; 30 | 31 | nix.settings.max-jobs = 4; 32 | } 33 | -------------------------------------------------------------------------------- /machines/Librem5-Phone/system: -------------------------------------------------------------------------------- 1 | aarch64-linux -------------------------------------------------------------------------------- /machines/RasPi-Server/default.nix: -------------------------------------------------------------------------------- 1 | { inputs, pkgs, lib, ... }: { 2 | imports = with inputs.self.nixosModules; with inputs.self.nixosProfiles; [ 3 | ./hardware-configuration.nix 4 | inputs.self.nixosRoles.server 5 | themes 6 | fonts 7 | cage 8 | gtk 9 | alacritty 10 | ]; 11 | 12 | boot.loader.raspberryPi = { 13 | enable = true; 14 | version = 3; 15 | }; 16 | 17 | nix.package = lib.mkForce pkgs.nixUnstable; 18 | 19 | deviceSpecific.devInfo = { 20 | cpu = { 21 | vendor = "broadcom"; 22 | clock = 4200; 23 | cores = 8; 24 | }; 25 | drive = { 26 | type = "ssd"; 27 | speed = 6000; 28 | size = 250; 29 | }; 30 | bigScreen = true; 31 | ram = 32; 32 | }; 33 | } 34 | -------------------------------------------------------------------------------- /machines/RasPi-Server/hardware-configuration.nix: -------------------------------------------------------------------------------- 1 | # Do not modify this file! It was generated by ‘nixos-generate-config’ 2 | # and may be overwritten by future invocations. Please make changes 3 | # to /etc/nixos/configuration.nix instead. 4 | { config, lib, pkgs, modulesPath, ... }: 5 | 6 | { 7 | imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; 8 | 9 | boot.initrd.availableKernelModules = [ ]; 10 | boot.initrd.kernelModules = [ ]; 11 | boot.kernelModules = [ ]; 12 | boot.extraModulePackages = [ ]; 13 | 14 | fileSystems."/" = { 15 | device = "/dev/disk/by-uuid/44444444-4444-4444-8888-888888888888"; 16 | fsType = "ext4"; 17 | }; 18 | 19 | swapDevices = [ ]; 20 | 21 | powerManagement.cpuFreqGovernor = lib.mkDefault "ondemand"; 22 | # high-resolution display 23 | hardware.video.hidpi.enable = lib.mkDefault true; 24 | } 25 | -------------------------------------------------------------------------------- /machines/RasPi-Server/system: -------------------------------------------------------------------------------- 1 | aarch64-linux -------------------------------------------------------------------------------- /machines/T420-Laptop/default.nix: -------------------------------------------------------------------------------- 1 | { inputs, lib, ... }: { 2 | imports = with inputs.self.nixosModules; with inputs.self.nixosProfiles; [ 3 | ./hardware-configuration.nix 4 | inputs.self.nixosRoles.server 5 | gitea 6 | # jitsi 7 | mailserver 8 | matrix-synapse 9 | # minidlna 10 | nextcloud 11 | nginx 12 | vsftpd 13 | # home-assistant 14 | # mastodon 15 | irc 16 | remapper 17 | ntfy 18 | ]; 19 | 20 | services.logind.lidSwitch = "ignore"; 21 | 22 | system.stateVersion = "21.11"; 23 | 24 | boot.loader = { 25 | systemd-boot.enable = lib.mkForce false; 26 | grub = { 27 | enable = lib.mkForce true; 28 | device = "/dev/disk/by-path/pci-0000:06:00.0-scsi-0:0:0:0"; 29 | }; 30 | }; 31 | 32 | deviceSpecific.devInfo = { 33 | legacy = true; 34 | cpu = { 35 | vendor = "intel"; 36 | clock = 2500; 37 | cores = 2; 38 | }; 39 | drive = { 40 | type = "ssd"; 41 | speed = 1000; 42 | size = 120; 43 | }; 44 | ram = 8; 45 | }; 46 | } 47 | -------------------------------------------------------------------------------- /machines/T420-Laptop/hardware-configuration.nix: -------------------------------------------------------------------------------- 1 | # Do not modify this file! It was generated by ‘nixos-generate-config’ 2 | # and may be overwritten by future invocations. Please make changes 3 | # to /etc/nixos/configuration.nix instead. 4 | { config, lib, pkgs, modulesPath, ... }: 5 | 6 | { 7 | imports = 8 | [ (modulesPath + "/profiles/qemu-guest.nix") 9 | ]; 10 | 11 | boot.initrd.availableKernelModules = [ "ahci" "xhci_pci" "virtio_pci" "sd_mod" "sr_mod" ]; 12 | boot.initrd.kernelModules = [ ]; 13 | boot.kernelModules = [ ]; 14 | boot.extraModulePackages = [ ]; 15 | 16 | fileSystems."/" = 17 | { device = "/dev/disk/by-uuid/1364826d-5333-4ec9-93cf-aba2925e41d0"; 18 | fsType = "ext4"; 19 | }; 20 | 21 | fileSystems."/var/lib" = 22 | { device = "/dev/disk/by-uuid/e4122adb-3f73-44b5-8763-7fb91e9a52e7"; 23 | fsType = "ext4"; 24 | }; 25 | 26 | swapDevices = [ ]; 27 | 28 | # Enables DHCP on each ethernet and wireless interface. In case of scripted networking 29 | # (the default) this is the recommended approach. When using systemd-networkd it's 30 | # still possible to use this option, but it's recommended to use it in conjunction 31 | # with explicit per-interface declarations with `networking.interfaces..useDHCP`. 32 | networking.useDHCP = lib.mkDefault true; 33 | # networking.interfaces.enp1s0.useDHCP = lib.mkDefault true; 34 | 35 | # nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; 36 | nix.settings.max-jobs = 4; 37 | hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; 38 | } 39 | -------------------------------------------------------------------------------- /machines/T420-Laptop/system: -------------------------------------------------------------------------------- 1 | x86_64-linux -------------------------------------------------------------------------------- /machines/T490s-Laptop/default.nix: -------------------------------------------------------------------------------- 1 | { inputs, ... }: { 2 | imports = [ ./hardware-configuration.nix inputs.self.nixosRoles.desktop inputs.self.nixosProfiles.print-scan ]; 3 | deviceSpecific.devInfo = { 4 | cpu = { 5 | vendor = "intel"; 6 | clock = 4600; 7 | cores = 4; 8 | }; 9 | drive = { 10 | type = "ssd"; 11 | speed = 2000; 12 | size = 250; 13 | }; 14 | ram = 16; 15 | }; 16 | 17 | persist = { 18 | enable = true; 19 | cache.clean.enable = true; 20 | }; 21 | 22 | home-manager.users.balsoft.wayland.windowManager.sway.config.input."*".natural_scroll = "enable"; 23 | 24 | services.throttled = { 25 | enable = true; 26 | extraConfig = '' 27 | [GENERAL] 28 | # Enable or disable the script execution 29 | Enabled: True 30 | # SYSFS path for checking if the system is running on AC power 31 | Sysfs_Power_Path: /sys/class/power_supply/AC*/online 32 | 33 | ## Settings to apply while connected to Battery power 34 | [BATTERY] 35 | # Update the registers every this many seconds 36 | Update_Rate_s: 30 37 | # Max package power for time window #1 38 | PL1_Tdp_W: 29 39 | # Time window #1 duration 40 | PL1_Duration_s: 28 41 | # Max package power for time window #2 42 | PL2_Tdp_W: 44 43 | # Time window #2 duration 44 | PL2_Duration_S: 0.002 45 | # Max allowed temperature before throttling 46 | Trip_Temp_C: 85 47 | # Set cTDP to normal=0, down=1 or up=2 (EXPERIMENTAL) 48 | cTDP: 1 49 | 50 | ## Settings to apply while connected to AC power 51 | [AC] 52 | # Update the registers every this many seconds 53 | Update_Rate_s: 5 54 | # Max package power for time window #1 55 | PL1_Tdp_W: 44 56 | # Time window #1 duration 57 | PL1_Duration_s: 28 58 | # Max package power for time window #2 59 | PL2_Tdp_W: 44 60 | # Time window #2 duration 61 | PL2_Duration_S: 0.002 62 | # Max allowed temperature before throttling 63 | Trip_Temp_C: 95 64 | # Set HWP energy performance hints to 'performance' on high load (EXPERIMENTAL) 65 | HWP_Mode: True 66 | # Set cTDP to normal=0, down=1 or up=2 (EXPERIMENTAL) 67 | cTDP: 2 68 | 69 | [UNDERVOLT] 70 | # CPU core voltage offset (mV) 71 | CORE: -200 72 | # Integrated GPU voltage offset (mV) 73 | GPU: -60 74 | # CPU cache voltage offset (mV) 75 | CACHE: -50 76 | # System Agent voltage offset (mV) 77 | UNCORE: 0 78 | # Analog I/O voltage offset (mV) 79 | ANALOGIO: 0 80 | ''; 81 | }; 82 | 83 | } 84 | -------------------------------------------------------------------------------- /machines/T490s-Laptop/hardware-configuration.nix: -------------------------------------------------------------------------------- 1 | # Do not modify this file! It was generated by ‘nixos-generate-config’ 2 | # and may be overwritten by future invocations. Please make changes 3 | # to /etc/nixos/configuration.nix instead. 4 | { config, lib, pkgs, inputs, ... }: 5 | 6 | { 7 | imports = 8 | [ "${inputs.nixpkgs}/nixos/modules/installer/scan/not-detected.nix" ]; 9 | 10 | boot.initrd.availableKernelModules = 11 | [ "xhci_pci" "nvme" "usb_storage" "sd_mod" "rtsx_pci_sdmmc" ]; 12 | boot.initrd.kernelModules = [ ]; 13 | boot.kernelModules = [ "kvm-intel" ]; 14 | boot.extraModulePackages = [ ]; 15 | 16 | fileSystems."/persist" = { 17 | device = "/dev/disk/by-uuid/7c16955c-8414-4971-bf37-6492e8c0cb61"; 18 | fsType = "ext4"; 19 | neededForBoot = true; 20 | }; 21 | 22 | boot.initrd.luks.devices."root".device = 23 | "/dev/disk/by-uuid/234de44d-b2d4-44d0-a4e3-b3ef6b159424"; 24 | 25 | fileSystems."/boot" = { 26 | device = "/dev/disk/by-uuid/66D2-DC8B"; 27 | fsType = "vfat"; 28 | }; 29 | 30 | swapDevices = [ ]; 31 | 32 | nix.settings.max-jobs = lib.mkDefault 8; 33 | powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; 34 | } 35 | -------------------------------------------------------------------------------- /machines/T490s-Laptop/system: -------------------------------------------------------------------------------- 1 | x86_64-linux -------------------------------------------------------------------------------- /machines/X2100-Laptop/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs, 3 | lib, 4 | config, 5 | pkgs, 6 | ... 7 | }: 8 | { 9 | imports = [ 10 | ./hardware-configuration.nix 11 | inputs.self.nixosRoles.desktop 12 | ]; 13 | deviceSpecific.devInfo = { 14 | cpu = { 15 | vendor = "intel"; 16 | clock = 4800; 17 | cores = 4; 18 | }; 19 | drive = { 20 | type = "ssd"; 21 | speed = 6000; 22 | size = 256; 23 | }; 24 | ram = 16; 25 | }; 26 | 27 | fileSystems."/persist" = { 28 | device = "/dev/disk/by-uuid/e50bd1d6-3613-465e-895a-9dde6ffaad46"; 29 | fsType = "ext4"; 30 | neededForBoot = true; 31 | }; 32 | fileSystems."/boot" = { 33 | device = "/dev/disk/by-uuid/621A-6414"; 34 | fsType = "vfat"; 35 | }; 36 | 37 | boot.resumeDevice = config.fileSystems."/persist".device; 38 | boot.kernelParams = [ "resume_offset=4294656" ]; # from sudo filefrag -v /persist/swapfile 39 | services.logind.lidSwitch = "hibernate"; 40 | services.logind.powerKey = "hibernate"; 41 | 42 | # boot.initrd.systemd.enable = true; 43 | 44 | swapDevices = [ 45 | { 46 | device = "/persist/swapfile"; 47 | size = 16 * 1024; # 16 GB 48 | } 49 | ]; 50 | 51 | persist = { 52 | enable = true; 53 | cache.clean.enable = true; 54 | }; 55 | 56 | nix.settings.max-jobs = lib.mkDefault 8; 57 | 58 | home-manager.users.balsoft.xdg.configFile."simple-osd/brightness".text = pkgs.my-lib.genIni { 59 | default = { 60 | "backlight backend" = "/sys/class/backlight/acpi_video0"; 61 | "refresh interval" = 1000; 62 | }; 63 | }; 64 | } 65 | -------------------------------------------------------------------------------- /machines/X2100-Laptop/hardware-configuration.nix: -------------------------------------------------------------------------------- 1 | # Do not modify this file! It was generated by ‘nixos-generate-config’ 2 | # and may be overwritten by future invocations. Please make changes 3 | # to /etc/nixos/configuration.nix instead. 4 | { config, lib, pkgs, modulesPath, ... }: 5 | 6 | { 7 | imports = 8 | [ (modulesPath + "/installer/scan/not-detected.nix") 9 | ]; 10 | 11 | boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" ]; 12 | boot.initrd.kernelModules = [ ]; 13 | boot.kernelModules = [ "kvm-intel" ]; 14 | boot.extraModulePackages = [ ]; 15 | 16 | # Enables DHCP on each ethernet and wireless interface. In case of scripted networking 17 | # (the default) this is the recommended approach. When using systemd-networkd it's 18 | # still possible to use this option, but it's recommended to use it in conjunction 19 | # with explicit per-interface declarations with `networking.interfaces..useDHCP`. 20 | networking.useDHCP = lib.mkDefault true; 21 | # networking.interfaces.eth0.useDHCP = lib.mkDefault true; 22 | # networking.interfaces.wlan0.useDHCP = lib.mkDefault true; 23 | 24 | nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; 25 | hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; 26 | } 27 | -------------------------------------------------------------------------------- /machines/X2100-Laptop/system: -------------------------------------------------------------------------------- 1 | x86_64-linux -------------------------------------------------------------------------------- /machines/iso-image/default.nix: -------------------------------------------------------------------------------- 1 | { modulesPath, lib, inputs, pkgs, ... }: { 2 | imports = with inputs.self.nixosModules; with inputs.self.nixosProfiles; [ 3 | "${modulesPath}/installer/cd-dvd/iso-image.nix" 4 | inputs.self.nixosRoles.base 5 | themes 6 | fonts 7 | cage 8 | gtk 9 | alacritty 10 | ]; 11 | nix.settings.max-jobs = 4; 12 | isoImage.makeEfiBootable = true; 13 | isoImage.makeUsbBootable = true; 14 | } 15 | -------------------------------------------------------------------------------- /machines/iso-image/system: -------------------------------------------------------------------------------- 1 | x86_64-linux -------------------------------------------------------------------------------- /machines/server/default.nix: -------------------------------------------------------------------------------- 1 | { inputs, lib, ... }: { 2 | imports = with inputs.self.nixosModules; with inputs.self.nixosProfiles; [ 3 | inputs.self.nixosRoles.base 4 | ]; 5 | 6 | nix.nrBuildUsers = lib.mkForce 16; 7 | 8 | deviceSpecific.devInfo = { 9 | legacy = true; 10 | cpu = { 11 | vendor = "intel"; 12 | clock = 2500; 13 | cores = 2; 14 | }; 15 | drive = { 16 | type = "ssd"; 17 | speed = 1000; 18 | size = 120; 19 | }; 20 | ram = 8; 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /machines/server/system: -------------------------------------------------------------------------------- 1 | x86_64-linux -------------------------------------------------------------------------------- /machines/usb-persist/default.nix: -------------------------------------------------------------------------------- 1 | { lib, inputs, pkgs, config, ... }: { 2 | imports = with inputs.self.nixosModules; with inputs.self.nixosProfiles; [ 3 | ./hardware-configuration.nix 4 | 5 | inputs.self.nixosRoles.base 6 | 7 | themes 8 | fonts 9 | gtk 10 | 11 | sway 12 | i3blocks 13 | himalaya 14 | bluetooth 15 | power 16 | 17 | simple-osd-daemons 18 | alacritty 19 | firefox 20 | emacs 21 | ]; 22 | 23 | deviceSpecific.devInfo = { 24 | cpu = { 25 | vendor = "intel"; 26 | clock = 2000; 27 | cores = 2; 28 | }; 29 | drive = { 30 | type = "ssd"; 31 | speed = 6000; 32 | size = 16; 33 | }; 34 | bigScreen = false; 35 | ram = 2; 36 | }; 37 | 38 | networking.wireless.enable = lib.mkForce false; 39 | services.openssh.permitRootLogin = lib.mkForce "no"; 40 | services.getty.autologinUser = lib.mkForce "balsoft"; 41 | boot.kernelPackages = lib.mkForce pkgs.linuxPackages_latest; 42 | boot.supportedFilesystems = lib.mkForce [ "ext4" "vfat" ]; 43 | boot.loader.systemd-boot.enable = lib.mkForce false; 44 | boot.loader.grub = { 45 | enable = lib.mkForce true; 46 | devices = [ "/dev/sdc" ]; 47 | }; 48 | security.sudo.wheelNeedsPassword = false; 49 | persist = { 50 | enable = true; 51 | }; 52 | 53 | defaultApplications = { 54 | monitor.cmd = "${pkgs.alacritty}/bin/alacritty -e top"; 55 | }; 56 | 57 | startupApplications = [ config.defaultApplications.browser.cmd ]; 58 | 59 | } 60 | -------------------------------------------------------------------------------- /machines/usb-persist/hardware-configuration.nix: -------------------------------------------------------------------------------- 1 | # Do not modify this file! It was generated by ‘nixos-generate-config’ 2 | # and may be overwritten by future invocations. Please make changes 3 | # to /etc/nixos/configuration.nix instead. 4 | { config, lib, pkgs, modulesPath, ... }: 5 | 6 | { 7 | imports = 8 | [ (modulesPath + "/installer/scan/not-detected.nix") 9 | ]; 10 | 11 | boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" ]; 12 | boot.initrd.kernelModules = [ ]; 13 | boot.kernelModules = [ "kvm-amd" ]; 14 | boot.extraModulePackages = [ ]; 15 | 16 | fileSystems."/persist" = 17 | { device = "/dev/disk/by-uuid/315c1e94-7395-4a7e-ada8-40e3409f1a2b"; 18 | fsType = "ext4"; 19 | neededForBoot = true; 20 | }; 21 | 22 | fileSystems."/boot" = 23 | { device = "/dev/disk/by-uuid/08B0-2766"; 24 | fsType = "vfat"; 25 | }; 26 | 27 | swapDevices = [ ]; 28 | 29 | # high-resolution display 30 | hardware.video.hidpi.enable = lib.mkDefault false; 31 | } 32 | -------------------------------------------------------------------------------- /machines/usb-persist/system: -------------------------------------------------------------------------------- 1 | x86_64-linux -------------------------------------------------------------------------------- /modules/applications.nix: -------------------------------------------------------------------------------- 1 | { pkgs, config, lib, ... }: { 2 | options = with lib; 3 | with types; { 4 | defaultApplications = mkOption { 5 | type = attrsOf (submodule ({ name, ... }: { 6 | options = { 7 | cmd = mkOption { type = path; }; 8 | desktop = mkOption { type = str; }; 9 | }; 10 | })); 11 | description = "Preferred applications"; 12 | }; 13 | 14 | startupApplications = mkOption { 15 | type = listOf path; 16 | description = "Applications to run on startup"; 17 | }; 18 | }; 19 | config = rec { 20 | defaultApplications = { 21 | text_processor = { 22 | cmd = "${pkgs.abiword}/bin/abiword"; 23 | desktop = "abiword"; 24 | }; 25 | spreadsheet = { 26 | cmd = "${pkgs.gnumeric}/bin/gnumeric"; 27 | desktop = "gnumeric"; 28 | }; 29 | }; 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /modules/bt-agent.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, lib, ... }: { 2 | options.services.bt-agent = with lib; { 3 | enable = mkEnableOption "Bluetooth authentication agent"; 4 | package = mkOption { 5 | default = pkgs.bluez-tools; 6 | type = types.package; 7 | }; 8 | capability = mkOption { 9 | default = "DisplayYesNo"; 10 | description = "Agent capability"; 11 | type = types.enum [ 12 | "DisplayOnly" 13 | "DisplayYesNo" 14 | "KeyboardOnly" 15 | "NoInputNoOutput" 16 | ]; 17 | }; 18 | pinFile = mkOption { 19 | default = null; 20 | type = types.nullOr types.path; 21 | description = "Path to the PIN's file"; 22 | }; 23 | }; 24 | config = let 25 | cfg = config.services.bt-agent; 26 | args = [ "--capability=${cfg.capability}" ] 27 | ++ lib.optional (!isNull cfg.pinFile) "--pin=${cfg.pinFile}"; 28 | in lib.mkIf cfg.enable { 29 | systemd.services.bt-agent = { 30 | path = [ cfg.package ]; 31 | serviceConfig.Type = "forking"; 32 | serviceConfig.KillSignal = "SIGKILL"; 33 | script = "bt-agent -d ${lib.escapeShellArgs args}"; 34 | wantedBy = [ "bluetooth.target" ]; 35 | after = [ "bluetooth.service" ]; 36 | }; 37 | }; 38 | } 39 | -------------------------------------------------------------------------------- /modules/devices.nix: -------------------------------------------------------------------------------- 1 | { pkgs, lib, config, ... }: 2 | with lib; 3 | with types; { 4 | options = { 5 | device = mkOption { type = str; }; 6 | deviceSpecific = { 7 | isLaptop = mkOption { 8 | type = bool; 9 | default = 10 | !isNull (builtins.match ".*Laptop" config.networking.hostName); 11 | }; 12 | isPhone = mkOption { 13 | type = bool; 14 | default = !isNull (builtins.match ".*Phone" config.networking.hostName); 15 | }; 16 | devInfo = { 17 | cpu = { 18 | arch = mkOption { type = enum [ "x86_64" "aarch64" ]; }; 19 | vendor = mkOption { type = enum [ "amd" "intel" "broadcom" ]; }; 20 | clock = mkOption { type = int; }; 21 | cores = mkOption { type = int; }; 22 | }; 23 | drive = { 24 | type = mkOption { type = enum [ "hdd" "ssd" ]; }; 25 | speed = mkOption { type = int; }; 26 | size = mkOption { type = int; }; 27 | }; 28 | ram = mkOption { type = int; }; 29 | legacy = mkOption { type = bool; default = false; }; 30 | bigScreen = mkOption { 31 | type = bool; 32 | default = true; 33 | }; 34 | }; 35 | # Whether machine is powerful enough for heavy stuff 36 | goodMachine = with config.deviceSpecific; 37 | mkOption { 38 | type = bool; 39 | default = devInfo.cpu.clock * devInfo.cpu.cores >= 4000 40 | && devInfo.drive.size >= 100 && devInfo.ram >= 8; 41 | }; 42 | isHost = mkOption { 43 | type = bool; 44 | default = false; 45 | }; 46 | bigScreen = mkOption { 47 | type = bool; 48 | default = config.deviceSpecific.devInfo ? bigScreen; 49 | }; 50 | }; 51 | }; 52 | } 53 | -------------------------------------------------------------------------------- /modules/ezwg.nix: -------------------------------------------------------------------------------- 1 | # Kudos to https://github.com/notgne2 2 | 3 | { config, lib, pkgs, ... }: 4 | with lib; 5 | let cfg = config.services.ezwg; 6 | in { 7 | options.services.ezwg = { 8 | enable = mkEnableOption "Enable simple Wireguard connection"; 9 | proxy = mkOption { 10 | type = types.bool; 11 | default = true; 12 | description = "Route all your traffic through this connection"; 13 | }; 14 | lanSize = mkOption { 15 | type = types.int; 16 | default = 24; 17 | description = "Size of your VLAN (only relevant if proxy is false)"; 18 | }; 19 | serverIP = mkOption { 20 | type = types.str; 21 | description = "The IP of the wg server"; 22 | }; 23 | serverPort = mkOption { 24 | type = types.int; 25 | default = 51820; 26 | description = "The port of the wg server"; 27 | }; 28 | serverKey = mkOption { 29 | type = types.str; 30 | description = "The public key of the wg server"; 31 | }; 32 | privateKeyFile = mkOption { 33 | type = types.str; 34 | description = "Private wg key"; 35 | }; 36 | vlanIP = mkOption { 37 | type = types.str; 38 | description = "The IP to use on the wg VLAN"; 39 | }; 40 | }; 41 | config = mkIf cfg.enable { 42 | networking.firewall.checkReversePath = false; 43 | systemd.services.wireguard-wg0.wantedBy = lib.mkForce [ ]; 44 | systemd.paths.wireguard-wg0.wantedBy = lib.mkForce [ ]; 45 | systemd.services."wireguard-wg0-peer-${ 46 | lib.replaceChars [ "/" "-" " " "+" "=" ] [ 47 | "-" 48 | "\\x2d" 49 | "\\x20" 50 | "\\x2b" 51 | "\\x3d" 52 | ] cfg.serverKey 53 | }".wantedBy = lib.mkForce [ ]; 54 | 55 | networking.wireguard.interfaces.wg0 = let 56 | generateRangesScript = 57 | builtins.toFile "exclusionary-wildcard-ranges-generator.py" '' 58 | import ipaddress 59 | n1 = ipaddress.ip_network('0.0.0.0/0') 60 | n2 = ipaddress.ip_network('${cfg.serverIP}/32') 61 | print(':'.join(list(map(lambda x: str(x), list(n1.address_exclude(n2))))), end="") 62 | ''; 63 | rangesOutput = pkgs.runCommandNoCC "exclusionary-wildcard-ranges" { } '' 64 | ${pkgs.python3}/bin/python3 ${generateRangesScript} > $out 65 | ''; 66 | generateSubnetScript = 67 | builtins.toFile "subnet-without-host-bits-generator.py" '' 68 | import ipaddress 69 | n1 = ipaddress.ip_network('${cfg.vlanIP}/${ 70 | toString cfg.lanSize 71 | }', False) 72 | print(n1, end="") 73 | ''; 74 | subnetOutput = pkgs.runCommandNoCC "subnet-without-host-bits" { } '' 75 | ${pkgs.python3}/bin/python3 ${generateSubnetScript} > $out 76 | ''; 77 | ranges = lib.splitString ":" (builtins.readFile "${rangesOutput}"); 78 | subnet = builtins.readFile "${subnetOutput}"; 79 | in { 80 | ips = [ "${cfg.vlanIP}/${toString cfg.lanSize}" ]; 81 | privateKeyFile = cfg.privateKeyFile; 82 | peers = [{ 83 | publicKey = cfg.serverKey; 84 | allowedIPs = if cfg.proxy then ranges else [ subnet ]; 85 | endpoint = "${cfg.serverIP}:${toString cfg.serverPort}"; 86 | persistentKeepalive = 25; 87 | }]; 88 | }; 89 | }; 90 | } 91 | -------------------------------------------------------------------------------- /modules/persist.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, lib, inputs, ... }: 2 | let 3 | cfg = config.persist; 4 | 5 | takeAll = what: concatMap (x: x.${what}); 6 | 7 | persists = with cfg; [ state derivative cache ]; 8 | 9 | absoluteHomeFiles = map (x: "${cfg.homeDir}/${x}"); 10 | 11 | allHomeFiles = takeAll "homeFiles" persists; 12 | 13 | absoluteEtcFiles = map (x: "/etc/${x}"); 14 | 15 | allEtcFiles = absoluteEtcFiles (takeAll "etcFiles" persists); 16 | 17 | allDirectories = takeAll "directories" persists; 18 | 19 | inherit (builtins) concatMap; 20 | inherit (lib) mkIf; 21 | 22 | in { 23 | options = let 24 | inherit (lib) mkOption mkEnableOption; 25 | inherit (lib.types) listOf path str; 26 | common = { 27 | directories = mkOption { 28 | type = listOf path; 29 | default = [ ]; 30 | }; 31 | etcFiles = mkOption { 32 | type = listOf str; 33 | default = [ ]; 34 | }; 35 | homeFiles = mkOption { 36 | type = listOf str; 37 | default = [ ]; 38 | }; 39 | }; 40 | in { 41 | persist = { 42 | 43 | enable = mkEnableOption "a tmpfs root with explicit opt-in state"; 44 | 45 | persistRoot = mkOption { 46 | type = path; 47 | default = "/persist"; 48 | }; 49 | 50 | homeDir = mkOption { 51 | type = path; 52 | default = "/home/balsoft"; 53 | }; 54 | 55 | # Stuff that matters 56 | # TODO backups of this stuff 57 | state = { 58 | # backup = {...}; 59 | } // common; 60 | 61 | # Stuff that can be computed from declarative+state, but is never invalidated (so shouldn't be cleaned up) 62 | derivative = common; 63 | 64 | # Stuff that's just there to speed up the system 65 | # It's cleaned up regularly, to solve the cache invalidation problem once and for all 66 | cache = { 67 | clean = { 68 | enable = mkEnableOption "cleaning the cache files and directories"; 69 | dates = mkOption { 70 | type = str; 71 | default = "weekly"; 72 | description = 73 | "A systemd.time calendar description of when to clean the cache files"; 74 | }; 75 | }; 76 | } // common; 77 | 78 | }; 79 | }; 80 | 81 | imports = [ 82 | inputs.impermanence.nixosModules.impermanence 83 | # Eugh 84 | (let 85 | module = (import "${inputs.impermanence}/home-manager.nix" { 86 | inherit pkgs lib; 87 | config = lib.recursiveUpdate config.home-manager.users.balsoft { 88 | home.persistence."${cfg.persistRoot}${cfg.homeDir}" = { 89 | enable = true; 90 | directories = [ ]; 91 | files = allHomeFiles; 92 | allowOther = false; 93 | removePrefixDirectory = false; 94 | }; 95 | }; 96 | }); 97 | in { 98 | config.home-manager.users.balsoft = lib.mkIf cfg.enable module.config; 99 | }) 100 | ]; 101 | 102 | config = mkIf cfg.enable { 103 | environment.persistence.${cfg.persistRoot} = { 104 | directories = allDirectories; 105 | files = allEtcFiles; 106 | }; 107 | 108 | fileSystems."/" = { 109 | device = "none"; 110 | options = [ "defaults" "size=4G" "mode=755" ]; 111 | fsType = "tmpfs"; 112 | }; 113 | 114 | boot.initrd.postMountCommands = assert config.fileSystems 115 | ? ${cfg.persistRoot} 116 | && config.fileSystems.${cfg.persistRoot}.neededForBoot; '' 117 | mkdir -p /mnt-root/nix 118 | mount --bind /mnt-root${cfg.persistRoot}/nix /mnt-root/nix 119 | chmod 755 /mnt-root 120 | ''; 121 | 122 | # Euuuugh 123 | systemd.services.persist-cache-cleanup = lib.mkIf cfg.cache.clean.enable { 124 | description = "Cleaning up cache files and directories"; 125 | script = '' 126 | ${builtins.concatStringsSep "\n" (map (x: "rm ${lib.escapeShellArg x}") 127 | (absoluteEtcFiles cfg.cache.etcFiles 128 | ++ absoluteHomeFiles cfg.cache.homeFiles))} 129 | 130 | ${builtins.concatStringsSep "\n" 131 | (map (x: "rm -rf ${lib.escapeShellArg x}") cfg.cache.directories)} 132 | ''; 133 | startAt = cfg.cache.clean.dates; 134 | }; 135 | 136 | system.activationScripts = { 137 | homedir.text = builtins.concatStringsSep "\n" (map (dir: '' 138 | mkdir -p ${cfg.persistRoot}${dir} 139 | chown balsoft:users ${cfg.persistRoot}${dir} 140 | '') (builtins.filter (lib.hasPrefix "/home/balsoft") allDirectories)); 141 | }; 142 | }; 143 | } 144 | -------------------------------------------------------------------------------- /modules/secrets-envsubst.nix: -------------------------------------------------------------------------------- 1 | { pkgs, config, lib, inputs, ... }: 2 | with lib; 3 | with types; 4 | let 5 | envsubstSecrets = { name, ... }: { 6 | options = { 7 | directory = mkOption { 8 | type = nullOr str; 9 | default = name; 10 | }; 11 | secrets = mkOption { type = listOf str; }; 12 | template = mkOption { type = str; }; 13 | prefix = mkOption { 14 | type = nullOr str; 15 | default = null; 16 | }; 17 | substituted = mkOption { 18 | type = path; 19 | default = "/var/secrets/${name}-envsubst"; 20 | }; 21 | envsubst = mkOption { 22 | type = str; 23 | default = "${pkgs.envsubst}/bin/envsubst -no-unset -no-empty"; 24 | }; 25 | owner = mkOption { 26 | type = str; 27 | default = "root:root"; 28 | }; 29 | permissions = mkOption { 30 | type = lib.types.addCheck lib.types.str 31 | (perm: !isNull (builtins.match "[0-7]{3}" perm)); 32 | default = "400"; 33 | }; 34 | services = mkOption { 35 | type = listOf str; 36 | default = [ "${name}.service" ]; 37 | }; 38 | __toString = mkOption { 39 | readOnly = true; 40 | default = s: s.substituted; 41 | }; 42 | }; 43 | }; 44 | 45 | exportSecrets = name: cfg: 46 | let prefix = lib.optionalString (!isNull cfg.prefix) "${cfg.prefix}_"; 47 | in map (secret: 48 | '' 49 | export ${prefix}${secret}="$(cat ${ 50 | config.secrets."${name}-envsubst-${secret}".decrypted 51 | })"'') cfg.secrets; 52 | 53 | envsubst = name: cfg: 54 | with cfg; { 55 | "${name}-envsubst" = rec { 56 | 57 | requires = [ "user@1000.service" ] 58 | ++ map (secret: "${name}-envsubst-${secret}-secrets.service") 59 | cfg.secrets; 60 | after = requires; 61 | bindsTo = requires; 62 | 63 | preStart = "mkdir -p '${builtins.dirOf substituted}'"; 64 | 65 | script = '' 66 | ${builtins.concatStringsSep "\n" (exportSecrets name cfg)} 67 | 68 | if cat '${ 69 | builtins.toFile "template" template 70 | }' | ${cfg.envsubst} > '${substituted}.tmp'; then 71 | mv -f '${substituted}.tmp' '${substituted}' 72 | chown '${owner}' '${substituted}' 73 | chmod '${permissions}' '${substituted}' 74 | else 75 | echo "Failed to run the substition" 76 | rm '${substituted}.tmp' 77 | exit 1 78 | fi 79 | ''; 80 | 81 | serviceConfig = { 82 | Type = "oneshot"; 83 | RemainAfterExit = "yes"; 84 | }; 85 | }; 86 | }; 87 | 88 | addDependencies = name: cfg: 89 | with cfg; 90 | genAttrs services (service: rec { 91 | requires = [ "${name}-envsubst.service" ]; 92 | after = requires; 93 | bindsTo = requires; 94 | }); 95 | mkServices = name: cfg: [ (envsubst name cfg) (addDependencies name cfg) ]; 96 | 97 | mkIndividualSecrets = name: cfg: 98 | map (x: { 99 | "${name}-envsubst-${x}" = { 100 | encrypted = "${config.environment.sessionVariables.PASSWORD_STORE_DIR}/${ 101 | lib.optionalString (!isNull cfg.directory) "${cfg.directory}/" 102 | }${x}.gpg"; 103 | services = [ ]; 104 | }; 105 | }) cfg.secrets; 106 | in { 107 | options.secrets-envsubst = lib.mkOption { 108 | type = attrsOf (submodule envsubstSecrets); 109 | default = { }; 110 | }; 111 | config.systemd.services = 112 | mkMerge (concatLists (mapAttrsToList mkServices config.secrets-envsubst)); 113 | config.secrets = mkMerge 114 | (concatLists (mapAttrsToList mkIndividualSecrets config.secrets-envsubst)); 115 | } 116 | -------------------------------------------------------------------------------- /modules/secrets.nix: -------------------------------------------------------------------------------- 1 | { pkgs, config, lib, inputs, ... }: 2 | with lib; 3 | with types; 4 | let 5 | password-store = config.secretsConfig.password-store; 6 | secret = { name, ... }: { 7 | options = { 8 | encrypted = mkOption { 9 | type = path; 10 | default = "${password-store}/${name}.gpg"; 11 | }; 12 | decrypted = mkOption { 13 | type = path; 14 | default = "${config.secretsConfig.decryptedDir}/${name}"; 15 | }; 16 | decrypt = mkOption { 17 | default = pkgs.writeShellScript "gpg-decrypt" '' 18 | set -euo pipefail 19 | export GPG_TTY="$(tty)" 20 | ${pkgs.gnupg}/bin/gpg-connect-agent updatestartuptty /bye 1>&2 21 | ${pkgs.gnupg}/bin/gpg --batch --no-tty --decrypt 22 | ''; 23 | }; 24 | user = mkOption { 25 | type = str; 26 | default = "balsoft"; 27 | }; 28 | owner = mkOption { 29 | type = str; 30 | default = "root:root"; 31 | }; 32 | permissions = mkOption { 33 | type = lib.types.addCheck lib.types.str 34 | (perm: !isNull (builtins.match "[0-7]{3}" perm)); 35 | default = "400"; 36 | }; 37 | services = mkOption { 38 | type = listOf str; 39 | default = [ "${name}" ]; 40 | }; 41 | __toString = mkOption { 42 | readOnly = true; 43 | default = s: s.decrypted; 44 | }; 45 | }; 46 | }; 47 | 48 | restartAll = "${pkgs.systemd}/bin/systemctl restart ${allServices}"; 49 | 50 | activate-secrets = pkgs.writeShellApplication { 51 | name = "activate-secrets"; 52 | text = '' 53 | set -euo pipefail 54 | # wait for network 55 | while ! ping -c1 github.com; do sleep 1; done 56 | # Make sure card is available and unlocked 57 | echo fetch | gpg --card-edit --no-tty --command-fd=0 58 | gpg --card-status 59 | SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)" 60 | export SSH_AUTH_SOCK 61 | if [ -d "${password-store}/.git" ]; then 62 | cd "${password-store}"; git pull 63 | else 64 | git clone ${ 65 | lib.escapeShellArg config.secretsConfig.repo 66 | } "${password-store}" 67 | fi 68 | gpg --decrypt < ${password-store}/unlock.gpg > /dev/null 69 | /run/wrappers/bin/sudo ${restartAll} 70 | ''; 71 | runtimeInputs = [ pkgs.gnupg pkgs.git pkgs.systemd pkgs.openssh pkgs.iputils pkgs.coreutils ]; 72 | 73 | }; 74 | decrypt = name: cfg: 75 | with cfg; { 76 | "${name}-secrets" = rec { 77 | 78 | wantedBy = [ "multi-user.target" ]; 79 | 80 | requires = [ "user@1000.service" ]; 81 | after = requires; 82 | 83 | preStart = '' 84 | stat '${encrypted}' 85 | mkdir -p '${builtins.dirOf decrypted}' 86 | ''; 87 | 88 | script = '' 89 | if cat '${encrypted}' | /run/wrappers/bin/sudo -u ${user} ${cfg.decrypt} > '${decrypted}.tmp'; then 90 | mv -f '${decrypted}.tmp' '${decrypted}' 91 | chown '${owner}' '${decrypted}' 92 | chmod '${permissions}' '${decrypted}' 93 | else 94 | echo "Failed to decrypt the secret" 95 | rm '${decrypted}.tmp' 96 | if [[ -f '${decrypted}' ]]; then 97 | echo "The decrypted file exists anyways, not failing" 98 | exit 0 99 | else 100 | exit 1 101 | fi 102 | fi 103 | ''; 104 | 105 | serviceConfig = { 106 | Type = "oneshot"; 107 | RemainAfterExit = "yes"; 108 | }; 109 | }; 110 | }; 111 | 112 | addDependencies = name: cfg: 113 | with cfg; 114 | genAttrs services (service: rec { 115 | requires = [ "${name}-secrets.service" ]; 116 | after = requires; 117 | bindsTo = requires; 118 | }); 119 | 120 | mkServices = name: cfg: [ (decrypt name cfg) (addDependencies name cfg) ]; 121 | 122 | allServices = toString (map (name: "${name}-envsubst.service") 123 | (builtins.attrNames config.secrets-envsubst) 124 | ++ map (name: "${name}-secrets.service") 125 | (builtins.attrNames config.secrets)); 126 | in { 127 | options = { 128 | secrets = lib.mkOption { 129 | type = attrsOf (submodule secret); 130 | default = { }; 131 | }; 132 | 133 | secretsConfig = { 134 | password-store = lib.mkOption { 135 | type = lib.types.path; 136 | default = "/home/balsoft/.local/share/password-store"; 137 | }; 138 | repo = lib.mkOption { 139 | type = str; 140 | default = "ssh://git@github.com/balsoft/pass"; 141 | }; 142 | decryptedDir = lib.mkOption { 143 | type = lib.types.path; 144 | default = "/var/secrets"; 145 | }; 146 | }; 147 | }; 148 | 149 | config = { 150 | 151 | systemd.services = 152 | mkMerge (concatLists (mapAttrsToList mkServices config.secrets)); 153 | 154 | security.sudo.extraRules = [{ 155 | users = [ "balsoft" ]; 156 | commands = [{ 157 | command = restartAll; 158 | options = [ "NOPASSWD" ]; 159 | }]; 160 | }]; 161 | 162 | persist.derivative.directories = [ config.secretsConfig.decryptedDir password-store ]; 163 | 164 | home-manager.users.balsoft = { 165 | systemd.user.services.activate-secrets = { 166 | Service = { 167 | ExecStart = "${activate-secrets}/bin/activate-secrets"; 168 | Type = "oneshot"; 169 | }; 170 | Unit = { PartOf = [ "graphical-session-pre.target" ]; }; 171 | Install.WantedBy = [ "graphical-session-pre.target" ]; 172 | }; 173 | systemd.user.services.pass-store-sync = { 174 | Service = { 175 | Environment = [ 176 | "PASSWORD_STORE_DIR=${password-store}" 177 | "PATH=${ 178 | lib.makeBinPath [ pkgs.pass pkgs.inotify-tools pkgs.gnupg ] 179 | }" 180 | ]; 181 | ExecStart = toString (pkgs.writeShellScript "pass-store-sync" '' 182 | export SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)" 183 | while inotifywait "$PASSWORD_STORE_DIR" -r -e move -e close_write -e create -e delete --exclude .git; do 184 | sleep 0.1 185 | { 186 | pass git add --all 187 | pass git commit -m "Change" 188 | pass git pull --rebase 189 | pass git push 190 | } & 191 | done 192 | ''); 193 | }; 194 | Unit = rec { 195 | After = [ "activate-secrets.service" ]; 196 | Wants = After; 197 | }; 198 | Install.WantedBy = [ "graphical-session-pre.target" ]; 199 | }; 200 | programs.password-store = { 201 | enable = true; 202 | package = pkgs.pass-wayland; 203 | settings.PASSWORD_STORE_DIR = password-store; 204 | }; 205 | }; 206 | }; 207 | } 208 | -------------------------------------------------------------------------------- /modules/themes.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, inputs, ... }: 2 | with lib; 3 | let 4 | colorType = 5 | types.addCheck types.str (x: !isNull (builtins.match "[0-9a-fA-F]{6}" x)); 6 | color = mkOption { type = colorType; }; 7 | 8 | font = { 9 | family = mkOption { type = types.str; }; 10 | size = mkOption { type = types.int; }; 11 | }; 12 | 13 | fromYAML = yaml: 14 | builtins.fromJSON (builtins.readFile (pkgs.stdenv.mkDerivation { 15 | name = "fromYAML"; 16 | phases = [ "buildPhase" ]; 17 | buildPhase = "echo '${yaml}' | ${pkgs.yaml2json}/bin/yaml2json > $out"; 18 | })); 19 | in { 20 | options = { 21 | themes = { 22 | colors = builtins.listToAttrs (map (name: { 23 | inherit name; 24 | value = color; 25 | }) [ 26 | "base00" 27 | "base01" 28 | "base02" 29 | "base03" 30 | "base04" 31 | "base05" 32 | "base06" 33 | "base07" 34 | "base08" 35 | "base09" 36 | "base0A" 37 | "base0B" 38 | "base0C" 39 | "base0D" 40 | "base0E" 41 | "base0F" 42 | ]); 43 | fonts = { 44 | main = font; 45 | serif = font; 46 | mono = font; 47 | }; 48 | }; 49 | }; 50 | config = { 51 | themes.colors = { 52 | # H = 0, S = 0% 53 | base00 = "000000"; # L = 0% 54 | base01 = "1a1a1a"; # L = 10% 55 | base02 = "333333"; # L = 20% 56 | base03 = "808080"; # L = 50% 57 | base04 = "cccccc"; # L = 80% 58 | base05 = "ffffff"; # L = 100% 59 | base06 = "e6e6e6"; # L = 90% 60 | base07 = "e6e6e6"; # L = 90% 61 | # L = 50%, S = 50% 62 | base08 = "bf4040"; # H = 0 RED 63 | base09 = "bf8040"; # H = 30 ORANGE 64 | base0A = "bfbf40"; # H = 60 YELLOW-ish 65 | base0B = "80bf40"; # H = 90 GREEN 66 | # Whoa, a lot of hues are green! 67 | base0C = "40bfbf"; # H = 180 TEAL 68 | base0D = "407fbf"; # H = 210 BLUE 69 | base0E = "7f40bf"; # H = 270 PURPLE 70 | base0F = "bf40bf"; # H = 300 MAGENTA 71 | }; 72 | }; 73 | } 74 | -------------------------------------------------------------------------------- /profiles/applications-setup.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: { 2 | startupApplications = with config.defaultApplications; [ 3 | browser.cmd 4 | ]; 5 | 6 | environment.sessionVariables = { 7 | EDITOR = config.defaultApplications.editor.cmd; 8 | VISUAL = config.defaultApplications.editor.cmd; 9 | }; 10 | 11 | home-manager.users.balsoft = { 12 | home.activation."mimeapps-remove" = { 13 | before = [ "checkLinkTargets" ]; 14 | after = [ ]; 15 | data = "rm -f /home/balsoft/.config/mimeapps.list"; 16 | }; 17 | 18 | xdg.mimeApps = { 19 | enable = true; 20 | defaultApplications = with config.defaultApplications; 21 | builtins.mapAttrs (name: value: 22 | if value ? desktop then [ "${value.desktop}.desktop" ] else value) { 23 | "inode/directory" = fm; 24 | "text/html" = browser; 25 | "image/*" = { desktop = "org.kde.gwenview"; }; 26 | "application/zip" = archive; 27 | "application/rar" = archive; 28 | "application/7z" = archive; 29 | "application/*tar" = archive; 30 | "x-scheme-handler/http" = browser; 31 | "x-scheme-handler/https" = browser; 32 | "x-scheme-handler/about" = browser; 33 | "x-scheme-handler/mailto" = mail; 34 | "x-scheme-handler/matrix" = matrix; 35 | "application/pdf" = { desktop = "org.kde.okular"; }; 36 | "application/vnd.openxmlformats-officedocument.wordprocessingml.document" = 37 | text_processor; 38 | "application/msword" = text_processor; 39 | "application/vnd.oasis.opendocument.text" = text_processor; 40 | "text/csv" = spreadsheet; 41 | "application/vnd.oasis.opendocument.spreadsheet" = spreadsheet; 42 | "text/plain" = editor; 43 | "text/*" = editor; 44 | }; 45 | }; 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /profiles/applications/aerc.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: { 2 | defaultApplications.mail = { 3 | cmd = "${pkgs.aerc}/bin/aerc"; 4 | desktop = "aerc"; 5 | }; 6 | startupApplications = [ "${config.defaultApplications.term.cmd} -T aerc -e ${pkgs.aerc}/bin/aerc" ]; 7 | home-manager.users.balsoft = { 8 | programs.aerc = { 9 | enable = true; 10 | extraBinds = { 11 | global = { 12 | "" = ":prev-tab"; 13 | "" = ":next-tab"; 14 | "?" = ":help keys"; 15 | }; 16 | 17 | messages = { 18 | "h" = ":prev-tab"; 19 | "l" = ":next-tab"; 20 | 21 | "j" = ":next"; 22 | "" = ":next"; 23 | "" = ":next 50%"; 24 | "" = ":next 100%"; 25 | "" = ":next 100%"; 26 | 27 | "k" = ":prev"; 28 | "" = ":prev"; 29 | "" = ":prev 50%"; 30 | "" = ":prev 100%"; 31 | "" = ":prev 100%"; 32 | "g" = ":select 0"; 33 | "G" = ":select -1"; 34 | 35 | "J" = ":next-folder"; 36 | "K" = ":prev-folder"; 37 | "H" = ":collapse-folder"; 38 | "L" = ":expand-folder"; 39 | 40 | "v" = ":mark -t"; 41 | "x" = ":mark -t:next"; 42 | "V" = ":mark -v"; 43 | 44 | "T" = ":toggle-threads"; 45 | 46 | "" = ":view"; 47 | "d" = ":prompt 'Really delete this message?' 'delete-message'"; 48 | "D" = ":delete"; 49 | "A" = ":archive flat"; 50 | 51 | "C" = ":compose"; 52 | 53 | "rr" = ":reply -a"; 54 | "rq" = ":reply -aq"; 55 | "Rr" = ":reply"; 56 | "Rq" = ":reply -q"; 57 | 58 | "c" = ":cf"; 59 | "$" = ":term"; 60 | "!" = ":term"; 61 | "|" = ":pipe"; 62 | 63 | "/" = ":search"; 64 | "\\" = ":filter"; 65 | "n" = ":next-result"; 66 | "N" = ":prev-result"; 67 | "" = ":clear"; 68 | }; 69 | 70 | "messages:folder=Drafts" = { "" = ":recall"; }; 71 | 72 | view = { 73 | 74 | "/" = ":toggle-key-passthrough/"; 75 | "q" = ":close"; 76 | "O" = ":open"; 77 | "S" = ":save"; 78 | "|" = ":pipe"; 79 | "D" = ":delete"; 80 | "A" = ":archive flat"; 81 | 82 | "" = ":open-link "; 83 | 84 | "f" = ":forward"; 85 | "rr" = ":reply -a"; 86 | "rq" = ":reply -aq"; 87 | "Rr" = ":reply"; 88 | "Rq" = ":reply -q"; 89 | 90 | "H" = ":toggle-headers"; 91 | "" = ":prev-part"; 92 | "" = ":next-part"; 93 | "J" = ":next"; 94 | "K" = ":prev"; 95 | }; 96 | 97 | "view::passthrough" = { 98 | "$noinherit" = true; 99 | "$ex" = ""; 100 | "" = ":toggle-key-passthrough"; 101 | }; 102 | 103 | compose = { 104 | "$noinherit" = "true"; 105 | "$ex" = ""; 106 | "" = ":prev-field"; 107 | "" = ":next-field"; 108 | "" = ":switch-account -p"; 109 | "" = ":switch-account -n"; 110 | "" = ":next-field"; 111 | "" = ":prev-tab"; 112 | "" = ":next-tab"; 113 | }; 114 | 115 | "compose::editor" = { 116 | "$noinherit" = "true"; 117 | "$ex" = ""; 118 | "" = ":prev-field"; 119 | "" = ":next-field"; 120 | "" = ":prev-tab"; 121 | "" = ":next-tab"; 122 | }; 123 | 124 | "compose::review" = { 125 | "y" = ":send"; 126 | "n" = ":abort"; 127 | "p" = ":postpone"; 128 | "q" = ":choose -o d discard abort -o p postpone postpone"; 129 | "e" = ":edit"; 130 | "a" = ":attach"; 131 | "d" = ":detach"; 132 | }; 133 | 134 | terminal = { 135 | "$noinherit" = "true"; 136 | "$ex" = ""; 137 | 138 | "" = ":prev-tab"; 139 | "" = ":next-tab"; 140 | }; 141 | }; 142 | extraConfig = { 143 | general.unsafe-accounts-conf = true; 144 | ui = { 145 | reverse-thread-order = true; 146 | threading-enabled = true; 147 | show-thread-context = true; 148 | this-day-time-format = ''" 15:04"''; 149 | this-year-time-format = "Mon Jan 02 15:04"; 150 | timestamp-format = "2006-01-02 15:04"; 151 | 152 | spinner = "[ ⡿ ],[ ⣟ ],[ ⣯ ],[ ⣷ ],[ ⣾ ],[ ⣽ ],[ ⣻ ],[ ⢿ ]"; 153 | border-char-vertical = "┃"; 154 | border-char-horizontal = "━"; 155 | }; 156 | viewer = { always-show-mime = true; }; 157 | compose = { no-attachment-warning = "^[^>]*attach(ed|ment)"; }; 158 | triggers = { 159 | email-received = ''exec notify-send --icon=mail-message "Mail from %n" "%s"''; 160 | }; 161 | filters = { 162 | "text/plain" = "colorize"; 163 | "text/html" = "html"; 164 | "text/calendar" = "calendar"; 165 | "message/delivery-status" = "colorize"; 166 | "message/rfc822" = "colorize"; 167 | "image/*" = "${pkgs.catimg}/bin/catimg -"; 168 | }; 169 | }; 170 | stylesets = { 171 | default = { 172 | "border.bg" = 0; 173 | "border.fg" = 7; 174 | "border.reverse" = "false"; 175 | "msglist_default.bg" = 0; 176 | "msglist_unread.fg" = 3; 177 | "msglist_unread.bold" = "true"; 178 | "msglist_marked.bg" = 4; 179 | "dirlist_default.bg" = 0; 180 | "dirlist_unread.fg" = 3; 181 | }; 182 | }; 183 | }; 184 | accounts.email.accounts = { 185 | Personal = { 186 | primary = true; 187 | aerc.enable = true; 188 | realName = "Alexander Bantyev"; 189 | address = "balsoft@balsoft.ru"; 190 | imap.host = "balsoft.ru"; 191 | smtp.host = "balsoft.ru"; 192 | 193 | userName = "balsoft@balsoft.ru"; 194 | passwordCommand = "pass email/balsoft@balsoft.ru"; 195 | 196 | folders.inbox = "virtual.all"; 197 | }; 198 | Work = { 199 | aerc.enable = true; 200 | address = "alexander.bantyev@moduscreate.com"; 201 | realName = "Alexander Bantyev"; 202 | imap.host = "imap.gmail.com"; 203 | smtp.host = "smtp.gmail.com"; 204 | 205 | userName = "alexander.bantyev@moduscreate.com"; 206 | passwordCommand = "pass aerc/alexander.bantyev@moduscreate.com"; 207 | 208 | folders.inbox = "[Gmail]/All Mail"; 209 | }; 210 | }; 211 | }; 212 | } 213 | -------------------------------------------------------------------------------- /profiles/applications/alacritty.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: { 2 | defaultApplications.term = { 3 | cmd = "${pkgs.alacritty}/bin/alacritty"; 4 | desktop = "alacritty"; 5 | }; 6 | home-manager.users.balsoft.programs.alacritty = { 7 | enable = true; 8 | settings = { 9 | keyboard.bindings = [{ 10 | key = "Return"; 11 | mods = "Control"; 12 | action = "SpawnNewInstance"; 13 | }]; 14 | 15 | font = { 16 | normal.family = config.themes.fonts.mono.family; 17 | size = config.themes.fonts.mono.size; 18 | bold = { style = "Bold"; }; 19 | }; 20 | 21 | window.padding = { 22 | x = 2; 23 | y = 2; 24 | }; 25 | 26 | terminal.shell.program = "${pkgs.zsh}/bin/zsh"; 27 | 28 | cursor.style = "Beam"; 29 | 30 | colors = with pkgs.my-lib.thmHash config.themes.colors; { 31 | primary = { 32 | background = base00; 33 | foreground = base05; 34 | dim_foreground = base04; 35 | }; 36 | cursor = { 37 | text = base02; 38 | cursor = base05; 39 | }; 40 | normal = { 41 | black = base00; 42 | red = base08; 43 | green = base0B; 44 | yellow = base0A; 45 | blue = base0D; 46 | magenta = base0E; 47 | white = base07; 48 | }; 49 | }; 50 | }; 51 | }; 52 | 53 | } 54 | -------------------------------------------------------------------------------- /profiles/applications/angelfish.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: { 2 | environment.systemPackages = [ pkgs.plasma5Packages.angelfish ]; 3 | defaultApplications.browser = { 4 | cmd = "${pkgs.plasma5Packages.angelfish}/bin/angelfish"; 5 | desktop = "org.kde.angelfish"; 6 | }; 7 | home-manager.users.balsoft = { 8 | xdg.configFile.angelfishrc.text = pkgs.lib.generators.toGitINI { 9 | NavigationBar = { 10 | navBarReload = true; 11 | }; 12 | }; 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /profiles/applications/cantata.nix: -------------------------------------------------------------------------------- 1 | { pkgs, config, ... }: { 2 | home-manager.users.balsoft = { 3 | home.packages = [ pkgs.cantata ]; 4 | wayland.windowManager.sway = { 5 | config = { 6 | assigns."ﱘ" = [{ app_id = "cantata"; }]; 7 | }; 8 | }; 9 | xdg.configFile."cantata/cantata.conf".text = pkgs.my-lib.genIni { 10 | General = { 11 | lyricProviders = "azlyrics.com, chartlyrics.com, lyrics.wikia.com"; 12 | wikipediaLangs = "en:en"; 13 | mpris = "true"; 14 | currentConnection = "Default"; 15 | 16 | version = pkgs.cantata.version; 17 | 18 | hiddenPages = "PlayQueuePage, LibraryPage, PlaylistsPage, OnlineServicesPage, DevicesPage"; 19 | }; 20 | 21 | AlbumView.fullWidthCover = false; 22 | 23 | Connection-Default = { 24 | host = "localhost"; 25 | passwd = ""; 26 | port = "6600"; 27 | }; 28 | 29 | VolumeControl.control = "mpd"; 30 | }; 31 | }; 32 | 33 | startupApplications = [ "${pkgs.cantata}/bin/cantata" ]; 34 | } 35 | -------------------------------------------------------------------------------- /profiles/applications/emacs/default.nix: -------------------------------------------------------------------------------- 1 | { pkgs, config, lib, inputs, ... }: 2 | let 3 | emacs = pkgs.emacsPgtk; 4 | in { 5 | # secrets-envsubst.emacs = { 6 | # owner = "balsoft:users"; 7 | # directory = "emacs"; 8 | # }; 9 | 10 | persist.state.homeFiles = 11 | [ ".config/emacs/custom" ".config/emacs/eshell/history" ]; 12 | 13 | defaultApplications.editor = { 14 | cmd = toString (pkgs.writeShellScript "emacsclient-newwindow" '' 15 | ${config.home-manager.users.balsoft.programs.emacs.finalPackage}/bin/emacsclient -c "$@" 16 | ''); 17 | desktop = "emacsclient"; 18 | }; 19 | 20 | home-manager.users.balsoft = { 21 | programs.emacs = { 22 | enable = true; 23 | package = emacs; 24 | extraPackages = epkgs: 25 | with epkgs; [ 26 | use-package 27 | nix-mode 28 | haskell-mode 29 | exec-path-from-shell 30 | counsel 31 | projectile 32 | which-key 33 | markdown-mode 34 | frames-only-mode 35 | company 36 | rainbow-delimiters 37 | diff-hl 38 | mode-line-bell 39 | flycheck 40 | flycheck-pkg-config 41 | auto-indent-mode 42 | company-ghci 43 | expand-region 44 | ivy 45 | smex 46 | quickrun 47 | counsel-tramp 48 | ix 49 | magit 50 | elixir-mode 51 | company-box 52 | ws-butler 53 | yaml-mode 54 | gitlab-ci-mode 55 | gitlab-ci-mode-flycheck 56 | gitlab 57 | undo-tree 58 | rust-mode 59 | edit-indirect 60 | idris-mode 61 | lsp-mode 62 | envrc 63 | lsp-haskell 64 | treemacs 65 | lsp-treemacs 66 | treemacs-projectile 67 | dap-mode 68 | # forge 69 | crdt 70 | base16-theme 71 | org-caldav 72 | evil 73 | tuareg 74 | fira-code-mode 75 | terraform-mode 76 | dhall-mode 77 | ]; 78 | }; 79 | 80 | home.packages = [ pkgs.clang ]; 81 | 82 | services.emacs.enable = true; 83 | 84 | systemd.user.services.emacs = { 85 | Service = { 86 | Environment = 87 | "PATH=/run/current-system/sw/bin:/etc/profiles/per-user/balsoft/bin"; 88 | }; 89 | Unit.After = [ "sway-session.target" ]; 90 | Install = { 91 | WantedBy = lib.mkForce [ "sway-session.target" ]; 92 | }; 93 | }; 94 | 95 | xdg.configFile."emacs/init.el".source = pkgs.substituteAll ({ 96 | src = ./init.el; 97 | font = with config.themes.fonts; "${mono.family} ${toString mono.size}"; 98 | } // pkgs.my-lib.thmHash config.themes.colors); 99 | }; 100 | } 101 | -------------------------------------------------------------------------------- /profiles/applications/emacs/init.el: -------------------------------------------------------------------------------- 1 | ;;; init.el --- balsoft's config 2 | 3 | ;;; Commentary: 4 | 5 | ;;; None 6 | 7 | ;; -*- lexical-binding: t -*- 8 | 9 | ;;; Code: 10 | 11 | (require 'package) 12 | 13 | (package-initialize) 14 | 15 | (eval-when-compile 16 | (require 'use-package)) 17 | (setq use-package-always-ensure nil) 18 | 19 | (setq-default tab-width 2) 20 | 21 | (mode-line-bell-mode) 22 | 23 | (line-number-mode) 24 | (column-number-mode) 25 | 26 | (setq-default indent-tabs-mode nil) 27 | 28 | (setq-default tab-always-indent 't) 29 | 30 | (setq-default compilation-scroll-output 'first-error) 31 | 32 | (use-package ws-butler 33 | :config 34 | (ws-butler-global-mode) 35 | ) 36 | 37 | (global-auto-revert-mode) 38 | 39 | (setq auto-save-interval 5) 40 | 41 | (auto-save-visited-mode) 42 | 43 | (setq make-backup-files nil) 44 | 45 | ;; (use-package xah-fly-keys 46 | ;; :config 47 | ;; (xah-fly-keys-set-layout "qwerty") 48 | ;; (xah-fly-keys 1) 49 | ;; (define-key xah-fly-insert-map (kbd "M-SPC") 'xah-fly-command-mode-activate) 50 | ;; ) 51 | 52 | (use-package evil 53 | :config 54 | (evil-mode 1)) 55 | 56 | (global-set-key (kbd "C-b") 'switch-to-buffer) 57 | 58 | (global-display-line-numbers-mode) 59 | 60 | (electric-pair-mode) 61 | 62 | (electric-indent-mode) 63 | 64 | (use-package flycheck 65 | :config 66 | (global-flycheck-mode)) 67 | 68 | (menu-bar-mode -1) 69 | (scroll-bar-mode -1) 70 | (tool-bar-mode -1) 71 | (cua-selection-mode 1) 72 | 73 | 74 | (setq auto-revert-check-vc-info t) 75 | 76 | (vc-mode-line t) 77 | 78 | (when (not window-system) 79 | (xterm-mouse-mode 1)) 80 | 81 | (use-package fira-code-mode 82 | :custom (fira-code-mode-disabled-ligatures '("[]" "#{" "#(" "#_" "#_(" "x")) ;; List of ligatures to turn off 83 | :config (global-fira-code-mode)) 84 | 85 | (use-package company-ghci 86 | :config 87 | (push 'company-ghci company-backends)) 88 | 89 | (global-set-key [home] 'smart-beginning-of-line) 90 | 91 | (global-unset-key [menu-bar options cua-mode]) 92 | (global-unset-key (kbd "C-x C-f")) 93 | (global-set-key (kbd "C-x C-f") 'find-file-other-frame) 94 | (global-unset-key (kbd "C-x b")) ;; Old habits die hard 95 | 96 | (fringe-mode '(0 . 0)) 97 | 98 | ;; scroll one line at a time (less "jumpy" than defaults) 99 | 100 | (setq mouse-wheel-scroll-amount '(1 ((shift) . 1))) ;; one line at a time 101 | 102 | (setq mouse-wheel-progressive-speed nil) ;; don't accelerate scrolling 103 | 104 | (setq mouse-wheel-follow-mouse 't) ;; scroll window under mouse 105 | 106 | (setq scroll-step 1) ;; keyboard scroll one line at a time 107 | 108 | (use-package frames-only-mode) 109 | ;; Make new frames instead of new windows 110 | (setq pop-up-frames 'graphic-only) 111 | (setq gdb-use-separate-io-buffer nil) 112 | (setq gdb-many-windows nil) 113 | 114 | ;; ------------------- 115 | ;; Projectile 116 | ;; ------------------- 117 | ;; No deferred loading as bind-keymap 118 | ;; doesn't handle wakib C-d keymaps 119 | (use-package projectile 120 | :config 121 | (define-key projectile-mode-map (kbd "C-c p") nil) 122 | (define-key projectile-mode-map (kbd "C-x p") 'projectile-command-map) 123 | (projectile-mode 1) 124 | (global-unset-key [menu-bar tools Projectile]) 125 | (projectile-register-project-type 'flake '("flake.nix") 126 | :compile "nix build" 127 | :run "nix run") 128 | (setq projectile-project-search-path '("~/projects/")) 129 | 130 | (global-set-key (kbd "") 'projectile-compile-project) 131 | (global-set-key (kbd "") 'projectile-run-project)) 132 | 133 | (use-package nix-mode 134 | :hook 135 | ((nix-mode . (lambda () (local-set-key (kbd "") 'nix-format-buffer)))) 136 | ((nix-mode . (lambda () (setq indent-line-function 'nix-indent-line))))) 137 | 138 | (use-package company 139 | :config 140 | (global-company-mode 1) 141 | ;; Number the candidates (use M-1, M-2 etc to select completions). 142 | (setq company-show-numbers t) 143 | (setq company-idle-delay 0) 144 | ) 145 | 146 | (use-package company-box 147 | :hook (company-mode . company-box-mode)) 148 | 149 | 150 | ;; ------------------- 151 | ;; Ivy 152 | ;; ------------------- 153 | (use-package ivy 154 | :config 155 | (ivy-mode 1) 156 | (setq ivy-use-virtual-buffers t) 157 | (define-key ivy-minibuffer-map [remap keyboard-quit] 'minibuffer-keyboard-quit) 158 | (setq ivy-count-format "") 159 | (setq ivy-initial-inputs-alist nil)) 160 | 161 | (use-package counsel 162 | :config 163 | counsel-mode) 164 | 165 | (use-package smex) 166 | 167 | (show-paren-mode 1) 168 | ;; TODO - MOVE Electric Pair Mode to user local 169 | 170 | 171 | ;; MAJOR MODES 172 | 173 | (use-package markdown-mode 174 | :mode "\\.\\(m\\(ark\\)?down\\|md\\)$") 175 | 176 | 177 | ;; Setup Splash Screen 178 | ;; (setq inhibit-startup-screen t) 179 | ;; (setq-default major-mode 'fundamental-mode) 180 | ;; (setq-default initial-scratch-message "") 181 | 182 | (setq custom-file (expand-file-name "custom" user-emacs-directory)) 183 | (load custom-file t t) 184 | 185 | (auto-fill-mode) 186 | 187 | 188 | (add-to-list 'default-frame-alist '(font . "@font@")) 189 | (set-face-attribute 'default nil :font "@font@") 190 | 191 | (setq inhibit-startup-screen t) 192 | 193 | (use-package lsp-mode 194 | :config 195 | ) 196 | 197 | 198 | (use-package envrc 199 | :config 200 | (envrc-global-mode) 201 | (advice-add 'lsp :before (lambda (&optional n) (envrc--update)))) 202 | 203 | (setq treemacs-position 'right) 204 | 205 | (use-package treemacs) 206 | 207 | (use-package lsp-treemacs) 208 | 209 | (use-package treemacs-projectile) 210 | 211 | (setq initial-major-mode 'text-mode) 212 | 213 | (defun compile-on-save-start () 214 | (let ((buffer (compilation-find-buffer))) 215 | (unless (get-buffer-process buffer) 216 | (recompile)))) 217 | 218 | (define-minor-mode compile-on-save-mode 219 | "Minor mode to automatically call `recompile' whenever the 220 | current buffer is saved. When there is ongoing compilation, 221 | nothing happens." 222 | :lighter " CoS" 223 | (if compile-on-save-mode 224 | (progn (make-local-variable 'after-save-hook) 225 | (add-hook 'after-save-hook 'compile-on-save-start nil t)) 226 | (kill-local-variable 'after-save-hook))) 227 | 228 | (defun maybe-delete-frame-buffer (frame) 229 | "When a dedicated FRAME is deleted, also kill its buffer. 230 | A dedicated frame contains a single window whose buffer is not 231 | displayed anywhere else." 232 | (let ((windows (window-list frame))) 233 | (when (eq 1 (length windows)) 234 | (let ((buffer (window-buffer (car windows)))) 235 | (when (eq 1 (length (get-buffer-window-list buffer nil t))) 236 | (kill-buffer buffer)))))) 237 | 238 | (add-to-list 'delete-frame-functions #'maybe-delete-frame-buffer) 239 | 240 | (require 'base16-theme) 241 | 242 | (defvar base16-generated-colors 243 | '(:base00 "@base00@" 244 | :base01 "@base01@" 245 | :base02 "@base02@" 246 | :base03 "@base03@" 247 | :base04 "@base04@" 248 | :base05 "@base05@" 249 | :base06 "@base06@" 250 | :base07 "@base07@" 251 | :base08 "@base08@" 252 | :base09 "@base09@" 253 | :base0A "@base0A@" 254 | :base0B "@base0B@" 255 | :base0C "@base0C@" 256 | :base0D "@base0D@" 257 | :base0E "@base0E@" 258 | :base0F "@base0F@") 259 | "All colors for Base16 are defined here.") 260 | 261 | ;; Define the theme 262 | (deftheme base16-generated) 263 | 264 | ;; Add all the faces to the theme 265 | (base16-theme-define 'base16-generated base16-generated-colors) 266 | 267 | ;; Mark the theme as provided 268 | (provide-theme 'base16-generated) 269 | 270 | (enable-theme 'base16-generated) 271 | ;;; init.el ends here 272 | -------------------------------------------------------------------------------- /profiles/applications/emacs/org-gcal-config.el: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balsoft/nixos-config/d3a2e32bbf74d779629803965e945fcf29d1c1ec/profiles/applications/emacs/org-gcal-config.el -------------------------------------------------------------------------------- /profiles/applications/firefox.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, lib, inputs, ... }: 2 | let 3 | thm = pkgs.my-lib.thmHash config.themes.colors; 4 | fonts = config.themes.fonts; 5 | in { 6 | services.dbus.packages = [ pkgs.librewolf ]; 7 | 8 | environment.sessionVariables = { 9 | MOZ_USE_XINPUT2 = "1"; 10 | MOZ_DBUS_REMOTE = "1"; 11 | }; 12 | programs.browserpass.enable = true; 13 | 14 | persist.state.directories = [ "/home/balsoft/.librewolf/default" ]; 15 | 16 | defaultApplications.browser = { 17 | cmd = "${pkgs.librewolf}/bin/librewolf"; 18 | desktop = "librewolf"; 19 | }; 20 | 21 | home-manager.users.balsoft = { 22 | programs.browserpass = { 23 | enable = true; 24 | browsers = [ "librewolf" ]; 25 | }; 26 | wayland.windowManager.sway.config = { 27 | window.commands = [ 28 | { 29 | criteria = { title = "Firefox — Sharing Indicator"; }; 30 | command = "floating enable"; 31 | } 32 | { 33 | criteria = { title = "Firefox — Sharing Indicator"; }; 34 | command = "no_focus"; 35 | } 36 | { 37 | criteria = { title = "Firefox — Sharing Indicator"; }; 38 | command = "resize set 0 0"; 39 | } 40 | { 41 | criteria = { title = "Firefox — Sharing Indicator"; }; 42 | command = "move absolute position 10 10"; 43 | } 44 | ]; 45 | }; 46 | 47 | # home.file.".mozilla/native-messaging-hosts/tridactyl.json".text = let 48 | # tridactyl = with pkgs.nimPackages; 49 | # buildNimPackage { 50 | # pname = "tridactyl_native"; 51 | # version = "dev"; 52 | # nimBinOnly = true; 53 | # src = inputs.tridactyl-native-messenger; 54 | # buildInputs = [ tempfile regex unicodedb ]; 55 | # }; 56 | # in builtins.toJSON { 57 | # name = "tridactyl"; 58 | # description = "Tridactyl native command handler"; 59 | # path = "${tridactyl}/bin/native_main"; 60 | # type = "stdio"; 61 | 62 | # allowed_extensions = [ 63 | # "tridactyl.vim@cmcaine.co.uk" 64 | # "tridactyl.vim.betas@cmcaine.co.uk" 65 | # "tridactyl.vim.betas.nonewtab@cmcaine.co.uk" 66 | # ]; 67 | # }; 68 | 69 | programs.librewolf = { 70 | enable = true; 71 | package = pkgs.librewolf; 72 | profiles.default = { 73 | extensions.packages = with pkgs.nur.rycee.firefox-addons; [ 74 | adsum-notabs 75 | ublock-origin 76 | sponsorblock 77 | browserpass 78 | darkreader 79 | ]; 80 | id = 0; 81 | userChrome = '' 82 | #TabsToolbar { 83 | visibility: collapse; 84 | } 85 | // toolbar#nav-bar, nav-bar-customization-target { 86 | // background: ${thm.base00} !important; 87 | // } 88 | // @-moz-document url("about:newtab") { 89 | // * { background-color: ${thm.base00} !important; } 90 | // } 91 | ''; 92 | settings = { 93 | "toolkit.legacyUserProfileCustomizations.stylesheets" = true; 94 | 95 | "extensions.autoDisableScopes" = 0; 96 | 97 | "browser.search.defaultenginename" = "Google"; 98 | "browser.search.selectedEngine" = "Google"; 99 | "browser.urlbar.placeholderName" = "Google"; 100 | "browser.search.region" = "US"; 101 | 102 | "browser.uidensity" = 1; 103 | "browser.search.openintab" = true; 104 | "xpinstall.signatures.required" = false; 105 | "extensions.update.enabled" = false; 106 | 107 | "font.name.monospace.x-western" = "${fonts.mono.family}"; 108 | "font.name.sans-serif.x-western" = "${fonts.main.family}"; 109 | "font.name.serif.x-western" = "${fonts.serif.family}"; 110 | 111 | "browser.anchor_color" = thm.base0D; 112 | "browser.visited_color" = thm.base0C; 113 | "browser.display.use_document_fonts" = true; 114 | "pdfjs.disabled" = true; 115 | "media.videocontrols.picture-in-picture.enabled" = true; 116 | 117 | "widget.non-native-theme.enabled" = false; 118 | 119 | "browser.newtabpage.enabled" = false; 120 | "browser.startup.homepage" = "about:blank"; 121 | 122 | "browser.newtabpage.activity-stream.feeds.telemetry" = false; 123 | "browser.newtabpage.activity-stream.telemetry" = false; 124 | "browser.ping-centre.telemetry" = false; 125 | "toolkit.telemetry.archive.enabled" = false; 126 | "toolkit.telemetry.bhrPing.enabled" = false; 127 | "toolkit.telemetry.enabled" = false; 128 | "toolkit.telemetry.firstShutdownPing.enabled" = false; 129 | "toolkit.telemetry.hybridContent.enabled" = false; 130 | "toolkit.telemetry.newProfilePing.enabled" = false; 131 | "toolkit.telemetry.reportingpolicy.firstRun" = false; 132 | "toolkit.telemetry.shutdownPingSender.enabled" = false; 133 | "toolkit.telemetry.unified" = false; 134 | "toolkit.telemetry.updatePing.enabled" = false; 135 | 136 | "experiments.activeExperiment" = false; 137 | "experiments.enabled" = false; 138 | "experiments.supported" = false; 139 | "network.allow-experiments" = false; 140 | 141 | "privacy.clearOnShutdown_v2.cookiesAndStorage" = false; 142 | }; 143 | }; 144 | }; 145 | }; 146 | } 147 | -------------------------------------------------------------------------------- /profiles/applications/geary.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, lib, ... }: 2 | let 3 | gearyConfig = { 4 | Account = { 5 | label = ""; 6 | ordinal = 6; 7 | prefetch_days = -1; 8 | save_drafts = true; 9 | save_sent = true; 10 | sender_mailboxes = "Alexander Bantyev ;"; 11 | service_provider = "other"; 12 | signature = builtins.replaceStrings [ "\n" ] [ "\\n" ] '' 13 | -- 14 | Александр Бантьев /Alexander Bantyev/ aka balsoft 15 | 16 | Nix DevOPS/SRE at tweag.io 17 | 18 | 19 | 20 | 21 | matrix://@balsoft:balsoft.ru 22 | (https://matrix.to/#/@balsoft:balsoft.ru) 23 | https://t.me/balsoft 24 | https://github.com/balsoft 25 | ''; 26 | use_signature = true; 27 | }; 28 | Folders = { 29 | archive_folder = "Archive;"; 30 | drafts_folder = ""; 31 | junk_folder = ""; 32 | sent_folder = ""; 33 | trash_folder = ""; 34 | }; 35 | Incoming = { 36 | credentials = "custom"; 37 | host = "balsoft.ru"; 38 | login = "balsoft@balsoft.ru"; 39 | port = 993; 40 | remember_password = true; 41 | transport_security = "transport"; 42 | }; 43 | Metadata = { 44 | status = "enabled"; 45 | version = 1; 46 | }; 47 | Outgoing = { 48 | credentials = "use-incoming"; 49 | host = "balsoft.ru"; 50 | port = 587; 51 | remember_password = true; 52 | transport_security = "start-tls"; 53 | }; 54 | }; 55 | in { 56 | programs.geary.enable = true; 57 | 58 | persist.cache.directories = [ "/home/balsoft/.local/share/geary" ]; 59 | 60 | defaultApplications.mail = { 61 | cmd = "${pkgs.gnome.geary}/bin/geary"; 62 | desktop = "org.gnome.Geary"; 63 | }; 64 | 65 | home-manager.users.balsoft = let 66 | fonts = config.themes.fonts; 67 | thm = pkgs.my-lib.thmHash config.themes.colors; 68 | in { 69 | xdg.configFile."geary/user-style.css".text = '' 70 | *, html, body, body.plain div, body.plain a, body.plain p, body.plain span { 71 | background: ${thm.base00} !important; 72 | color: ${thm.base05} !important; 73 | font-family: '${fonts.mono.family}', monospace !important; 74 | } 75 | *, html, body { 76 | font-size: ${toString fonts.mono.size}pt; 77 | } 78 | ''; 79 | home.activation.geary = '' 80 | mkdir -p "$XDG_CONFIG_HOME/geary/account_03" 81 | $DRY_RUN_CMD ln -sf $VERBOSE_ARG ${ 82 | builtins.toFile "geary.ini" (pkgs.my-lib.genIni gearyConfig) 83 | } "$XDG_CONFIG_HOME/geary/account_03/geary.ini" 84 | ''; 85 | }; 86 | } 87 | -------------------------------------------------------------------------------- /profiles/applications/github.nix: -------------------------------------------------------------------------------- 1 | { pkgs, config, ... }: { 2 | secrets.github_token = { 3 | owner = "balsoft"; 4 | services = [ ]; 5 | }; 6 | 7 | home-manager.users.balsoft = { 8 | home.packages = let 9 | stateless-github-cli = pkgs.writeShellScriptBin "gh" '' 10 | export GITHUB_TOKEN="''${GITHUB_TOKEN-$(cat ${config.secrets.github_token.decrypted})}" 11 | exec ${pkgs.github-cli}/bin/gh "$@" 12 | ''; 13 | in [ stateless-github-cli ]; 14 | 15 | xdg.configFile."gh/config.yaml".text = builtins.toJSON { 16 | git_protocol = "ssh"; 17 | editor = ""; 18 | aliases = { 19 | pv = "pr view --comments"; 20 | }; 21 | }; 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /profiles/applications/gwenview.nix: -------------------------------------------------------------------------------- 1 | { pkgs, lib, config, ... }: 2 | { 3 | home-manager.users.balsoft = { 4 | home.packages = [ pkgs.kdePackages.gwenview ]; 5 | xdg.configFile."gwenviewrc".text = pkgs.my-lib.genIni { 6 | General = { 7 | HistoryEnabled = false; 8 | UrlNavigatorIsEditable = true; 9 | }; 10 | ImageView.EnlargeSmallerImages = true; 11 | ThumbnailView.Sorting = "Sorting::Rating"; 12 | }; 13 | }; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /profiles/applications/helix.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: { 2 | defaultApplications.editor = { 3 | cmd = "${pkgs.helix}/bin/hx"; 4 | desktop = "helix"; 5 | }; 6 | home-manager.users.balsoft = { 7 | home.packages = [ 8 | (pkgs.makeDesktopItem { 9 | name = "helix"; 10 | desktopName = "Helix editor"; 11 | terminal = true; 12 | categories = [ "Utility" "TextEditor" "Development" "IDE" ]; 13 | mimeTypes = [ 14 | "inode/directory" 15 | "text/english" 16 | "text/plain" 17 | "text/x-makefile" 18 | "text/x-c++hdr" 19 | "text/x-c++src" 20 | "text/x-chdr" 21 | "text/x-csrc" 22 | "text/x-java" 23 | "text/x-moc" 24 | "text/x-pascal" 25 | "text/x-tcl" 26 | "text/x-tex" 27 | "application/x-shellscript" 28 | "application/json" 29 | "application/xml" 30 | "text/xml" 31 | "text/x-c" 32 | "text/x-c++" 33 | ]; 34 | exec = "${pkgs.helix}/bin/hx %F"; 35 | icon = "helix"; 36 | }) 37 | ]; 38 | xdg.configFile."helix/languages.toml".text = '' 39 | [language-server.nil] 40 | command = "nil" 41 | args = ["--stdio"] 42 | config = { nix = { maxMemoryMB = 5000, flake = { autoArchive = false, autoEvalInputs = true } } } 43 | [[language]] 44 | name = "nix" 45 | formatter = { command = "nixfmt", args = [] } 46 | ''; 47 | programs.helix = { 48 | enable = true; 49 | settings = { 50 | theme = "base16"; 51 | editor = { 52 | indent-guides.render = true; 53 | lsp.display-messages = true; 54 | cursor-shape = { 55 | insert = "bar"; 56 | normal = "block"; 57 | select = "underline"; 58 | }; 59 | color-modes = true; 60 | }; 61 | keys = { 62 | insert = { 63 | up = "no_op"; 64 | down = "no_op"; 65 | left = "no_op"; 66 | right = "no_op"; 67 | pageup = "no_op"; 68 | pagedown = "no_op"; 69 | home = "no_op"; 70 | end = "no_op"; 71 | }; 72 | normal = { 73 | "A-q" = [ 74 | "goto_prev_paragraph" 75 | "goto_next_paragraph" 76 | "trim_selections" 77 | ":reflow 80" 78 | "collapse_selection" 79 | ]; 80 | "A-h" = "select_prev_sibling"; 81 | "A-j" = "shrink_selection"; 82 | "A-k" = "expand_selection"; 83 | "A-l" = "select_next_sibling"; 84 | "V" = [ "select_mode" "extend_to_line_bounds" ]; 85 | }; 86 | }; 87 | }; 88 | themes.base16 = 89 | with (builtins.mapAttrs (_: v: "#${v}") config.themes.colors); rec { 90 | "ui.menu" = { bg = base01; }; 91 | "ui.menu.selected" = { 92 | bg = base00; 93 | modifiers = [ "reversed" ]; 94 | }; 95 | "ui.linenr" = { 96 | fg = base02; 97 | bg = base00; 98 | }; 99 | "ui.popup" = { modifiers = [ "reversed" ]; }; 100 | "ui.linenr.selected" = { 101 | fg = base05; 102 | bg = base00; 103 | modifiers = [ "bold" ]; 104 | }; 105 | "ui.selection" = { 106 | fg = base00; 107 | bg = base0D; 108 | }; 109 | "ui.selection.primary" = { modifiers = [ "reversed" ]; }; 110 | "comment" = { fg = base03; }; 111 | "ui.statusline" = { 112 | fg = base05; 113 | bg = base02; 114 | }; 115 | "ui.statusline.inactive" = { 116 | fg = base03; 117 | bg = base01; 118 | }; 119 | "ui.help" = { 120 | fg = base01; 121 | bg = base05; 122 | }; 123 | "ui.cursor" = { modifiers = [ "reversed" ]; }; 124 | "ui.cursor.insert" = { 125 | bg = base01; 126 | modifiers = [ "reversed" ]; 127 | }; 128 | "variable" = base05; 129 | "variable.builtin" = { 130 | fg = base06; 131 | modifiers = [ "bold" ]; 132 | }; 133 | "constant.numeric" = base0C; 134 | "constant" = base0A; 135 | "constant.builtin" = base0A; 136 | "constant.character" = { 137 | fg = base0C; 138 | modifiers = [ "bold" ]; 139 | }; 140 | "attributes" = base0A; 141 | "type" = { 142 | fg = base05; 143 | modifiers = [ "bold" ]; 144 | }; 145 | "ui.cursor.match" = { bg = base01; }; 146 | "string" = base0B; 147 | # "variable.other.member" = base0B; 148 | "constant.character.escape" = base0E; 149 | "function" = base05; 150 | "constructor" = base0A; 151 | "special" = base0F; 152 | "keyword" = { 153 | fg = base0D; 154 | modifiers = [ "bold" ]; 155 | }; 156 | "markup.heading" = { 157 | fg = base0A; 158 | modifiers = [ "bold" ]; 159 | }; 160 | "markup.bold" = { modifiers = [ "bold" ]; }; 161 | "markup.italic" = { modifiers = [ "italic" ]; }; 162 | "markup.link" = { 163 | underline.style = "line"; 164 | fg = base0D; 165 | }; 166 | "markup.quote" = { 167 | bg = base01; 168 | modifiers = [ "italic" ]; 169 | }; 170 | "markup.raw" = { bg = base01; }; 171 | "label" = base0B; 172 | "namespace" = base0F; 173 | "diff.plus" = base0B; 174 | "diff.delta" = base0A; 175 | "diff.minus" = base08; 176 | "diagnostic" = { underline = { style = "line"; }; }; 177 | "diagnostic.error" = { fg = base08; } // diagnostic; 178 | "diagnostic.warning" = { fg = base09; } // diagnostic; 179 | "ui.gutter" = { bg = base00; }; 180 | "info" = base0D; 181 | "hint" = base02; 182 | "debug" = base02; 183 | "warning" = base09; 184 | "error" = base08; 185 | "ui.virtual.indent-guide" = base01; 186 | "highlight" = base09; 187 | }; 188 | }; 189 | }; 190 | } 191 | -------------------------------------------------------------------------------- /profiles/applications/himalaya.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, inputs, lib, ... }: { 2 | environment.systemPackages = [ pkgs.himalaya ]; 3 | } 4 | -------------------------------------------------------------------------------- /profiles/applications/josm.nix: -------------------------------------------------------------------------------- 1 | { pkgs, ... }: { 2 | home-manager.users.balsoft.home.packages = [ pkgs.josm ]; 3 | persist.state.directories = 4 | [ "/home/balsoft/.local/share/JOSM" "/home/balsoft/.config/JOSM" ]; 5 | } 6 | -------------------------------------------------------------------------------- /profiles/applications/nheko.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, lib, ... }: { 2 | home-manager.users.balsoft.home.packages = [ pkgs.nheko ]; 3 | defaultApplications.matrix = { 4 | cmd = "${pkgs.nheko}/bin/nheko"; 5 | desktop = "nheko"; 6 | }; 7 | startupApplications = [ 8 | "${pkgs.nheko}/bin/nheko" 9 | ]; 10 | persist.state.directories = 11 | [ "/home/balsoft/.local/share/nheko" "/home/balsoft/.config/nheko" ]; 12 | } 13 | -------------------------------------------------------------------------------- /profiles/applications/okular.nix: -------------------------------------------------------------------------------- 1 | { pkgs, lib, config, ... }: 2 | with (pkgs.my-lib.thmDec config.themes.colors); { 3 | home-manager.users.balsoft = { 4 | home.packages = [ 5 | (if config.deviceSpecific.isPhone then 6 | pkgs.okularMobile 7 | else 8 | pkgs.kdePackages.okular) 9 | ]; 10 | xdg.configFile."okularpartrc".text = pkgs.my-lib.genIni { 11 | "Dlg Accessibility" = { 12 | RecolorBackground = base00; 13 | RecolorForeground = base05; 14 | }; 15 | "Document" = { 16 | ChangeColors = true; 17 | PaperColor = base00; 18 | RenderMode = "Recolor"; 19 | }; 20 | "Main View" = { ShowLeftPanel = false; }; 21 | PageView = { 22 | BackgroundColor = base00; 23 | UseCustomBackgroundColor = true; 24 | }; 25 | }; 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /profiles/applications/packages.nix: -------------------------------------------------------------------------------- 1 | { pkgs, config, lib, inputs, ... }: { 2 | home-manager.users.balsoft.home.packages = with pkgs; 3 | [ 4 | # Internet 5 | wget 6 | curl 7 | 8 | eza 9 | jq 10 | 11 | file 12 | ] ++ lib.optionals config.deviceSpecific.goodMachine [ 13 | # steamcmd 14 | # steam 15 | haskellPackages.hoogle 16 | nixfmt-rfc-style 17 | # nil 18 | nixpkgs-fmt 19 | stdman 20 | libqalculate 21 | # Messaging 22 | libnotify 23 | # Audio/Video 24 | mpv 25 | vlc 26 | pavucontrol 27 | # Tools 28 | zip 29 | kdePackages.plasma-systemmonitor 30 | wl-clipboard 31 | grim 32 | slurp 33 | abiword 34 | gnumeric 35 | gcalcli 36 | xdg-utils 37 | lambda-launcher 38 | nix-patch 39 | gopass 40 | # papirus-icon-theme 41 | kdePackages.breeze-icons 42 | shellcheck 43 | proselint 44 | ripgrep 45 | bat 46 | jless 47 | 48 | pandoc 49 | sioyek 50 | 51 | nil 52 | ]; 53 | } 54 | -------------------------------------------------------------------------------- /profiles/applications/qmlkonsole.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, lib, ... }: { 2 | environment.systemPackages = [ pkgs.plasma5Packages.qmlkonsole ]; 3 | defaultApplications.term = { 4 | cmd = "${pkgs.plasma5Packages.qmlkonsole}/bin/qmlkonsole"; 5 | desktop = "org.kde.qmlkonsole"; 6 | }; 7 | environment.variables.COLORSCHEMES_DIRS = pkgs.writeTextFile { 8 | name = "qmlkonsole-generated-theme"; 9 | destination = "/Generated.colorscheme"; 10 | text = with pkgs.my-lib; 11 | with (thmDec config.themes.colors); 12 | let dim = mulDec 0.66; 13 | in lib.generators.toGitINI { 14 | General.Description = "Generated Color Scheme"; 15 | Background = { 16 | Bold = false; 17 | Color = base00; 18 | }; 19 | BackgroundIntense = { 20 | Bold = false; 21 | Color = base03; 22 | }; 23 | Color0 = { 24 | Bold = false; 25 | Color = base00; 26 | }; 27 | Color1 = { 28 | Bold = false; 29 | Color = base08; 30 | }; 31 | Color2 = { 32 | Bold = false; 33 | Color = base0B; 34 | }; 35 | Color3 = { 36 | Bold = false; 37 | Color = base0A; 38 | }; 39 | Color4 = { 40 | Bold = false; 41 | Color = base0D; 42 | }; 43 | Color5 = { 44 | Bold = false; 45 | Color = base0E; 46 | }; 47 | Color6 = { 48 | Bold = false; 49 | Color = base0C; 50 | }; 51 | Color7 = { 52 | Bold = false; 53 | Color = base07; 54 | }; 55 | Foreground = { 56 | Bold = false; 57 | Color = base05; 58 | }; 59 | Color0Faint = { 60 | Bold = false; 61 | Color = dim base00; 62 | }; 63 | Color1Faint = { 64 | Bold = false; 65 | Color = dim base08; 66 | }; 67 | Color2Faint = { 68 | Bold = false; 69 | Color = dim base0B; 70 | }; 71 | Color3Faint = { 72 | Bold = false; 73 | Color = dim base0A; 74 | }; 75 | Color4Faint = { 76 | Bold = false; 77 | Color = dim base0D; 78 | }; 79 | Color5Faint = { 80 | Bold = false; 81 | Color = dim base0E; 82 | }; 83 | Color6Faint = { 84 | Bold = false; 85 | Color = dim base0C; 86 | }; 87 | Color7Faint = { 88 | Bold = false; 89 | Color = dim base07; 90 | }; 91 | ForegroundFaint = { 92 | Bold = false; 93 | Color = dim base05; 94 | }; 95 | Color0Intense = { 96 | Bold = false; 97 | Color = base00; 98 | }; 99 | Color1Intense = { 100 | Bold = false; 101 | Color = base08; 102 | }; 103 | Color2Intense = { 104 | Bold = false; 105 | Color = base0B; 106 | }; 107 | Color3Intense = { 108 | Bold = false; 109 | Color = base0A; 110 | }; 111 | Color4Intense = { 112 | Bold = false; 113 | Color = base0D; 114 | }; 115 | Color5Intense = { 116 | Bold = false; 117 | Color = base0E; 118 | }; 119 | Color6Intense = { 120 | Bold = false; 121 | Color = base0C; 122 | }; 123 | Color7Intense = { 124 | Bold = false; 125 | Color = base07; 126 | }; 127 | ForegroundIntense = { 128 | Bold = false; 129 | Color = base05; 130 | }; 131 | }; 132 | }; 133 | home-manager.users.balsoft = { 134 | xdg.configFile.qmlkonsolerc.text = lib.generators.toGitINI { 135 | General = { 136 | colorScheme = "Generated"; 137 | fontFamily = config.themes.fonts.mono.family; 138 | fontSize = config.themes.fonts.mono.size; 139 | }; 140 | }; 141 | }; 142 | } 143 | -------------------------------------------------------------------------------- /profiles/applications/slack.nix: -------------------------------------------------------------------------------- 1 | { pkgs, ... }: { 2 | home-manager.users.balsoft.wayland.windowManager.sway.config.startup = [{ 3 | command = toString (pkgs.writeShellScript "slack" '' 4 | librewolf https://tweag.slack.com & 5 | sleep 5 6 | swaymsg '[title=Slack.*] move to workspace 󰍩' 7 | swaymsg '[title=Slack.*] fullscreen disable' 8 | librewolf https://calendar.google.com 9 | ''); 10 | }]; 11 | } 12 | -------------------------------------------------------------------------------- /profiles/applications/sylpheed.nix: -------------------------------------------------------------------------------- 1 | { pkgs, config, ... }: { 2 | home-manager.users.balsoft = { 3 | home.packages = [ pkgs.sylpheed ]; 4 | wayland.windowManager.sway.config.startup = [ 5 | { 6 | command = "${pkgs.sylpheed}/bin/sylpheed"; 7 | } 8 | ]; 9 | home.activation."accountrc" = { 10 | data = '' 11 | $DRY_RUN_CMD rm -f ~/.sylpheed-2.0/accountrc 12 | $DRY_RUN_CMD cp ~/.sylpheed-2.0/accountrc.home ~/.sylpheed-2.0/accountrc 13 | $DRY_RUN_CMD chmod 700 ~/.sylpheed-2.0/accountrc 14 | ''; 15 | before = [ ]; 16 | after = [ "linkGeneration" ]; 17 | }; 18 | home.file.".sylpheed-2.0/accountrc.home".text = '' 19 | [Account: 1] 20 | account_name=balsoft@balsoft.ru 21 | is_default=1 22 | name=Alexander Bantyev 23 | address=balsoft@balsoft.ru 24 | organization= 25 | protocol=3 26 | receive_server=balsoft.ru 27 | smtp_server=balsoft.ru 28 | nntp_server= 29 | use_nntp_auth=0 30 | user_id=balsoft@balsoft.ru 31 | password=${config.secrets.mail.password or ""} 32 | inbox=inbox 33 | use_apop_auth=0 34 | remove_mail=1 35 | message_leave_time=7 36 | get_all_mail=0 37 | enable_size_limit=0 38 | size_limit=1024 39 | filter_on_receive=1 40 | imap_check_inbox_only=0 41 | imap_filter_inbox_on_receive=0 42 | imap_auth_method=0 43 | max_nntp_articles=300 44 | receive_at_get_all=1 45 | add_date=1 46 | generate_msgid=1 47 | add_custom_header=0 48 | use_smtp_auth=1 49 | smtp_auth_method=0 50 | smtp_user_id= 51 | smtp_password= 52 | pop_before_smtp=0 53 | signature_type=2 54 | signature_path=/home/balsoft/.signature 55 | signature_name=Default 56 | signature_name2=Russian 57 | signature_name3=Short 58 | signature_name4= 59 | signature_name5= 60 | signature_name6= 61 | signature_name7= 62 | signature_name8= 63 | signature_name9= 64 | signature_name10= 65 | signature_text=Александр Бантьев /Alexander Bantyev/ aka balsoft\n\nNix DevOPS/SRE at serokell.io\n\n\n\n\nmatrix://@balsoft:balsoft.ru \n(https://matrix.to/#/@balsoft:balsoft.ru)\nhttps://t.me/balsoft\nhttps://github.com/balsoft\n 66 | signature_text2=Александр Бантьев (balsoft)\n\nNix DevOPS/SRE в serokell.io\n\n\n\n\nmatrix://@balsoft:balsoft.ru \n(https://matrix.to/#/@balsoft:balsoft.ru)\nhttps://t.me/balsoft\nhttps://github.com/balsoft\n 67 | signature_text3=Alexander Bantyev aka balsoft 68 | signature_text4= 69 | signature_text5= 70 | signature_text6= 71 | signature_text7= 72 | signature_text8= 73 | signature_text9= 74 | signature_text10= 75 | signature_before_quote=0 76 | set_autocc=0 77 | auto_cc= 78 | set_autobcc=0 79 | auto_bcc= 80 | set_autoreplyto=0 81 | auto_replyto= 82 | default_sign=1 83 | default_encrypt=0 84 | encrypt_reply=1 85 | encrypt_to_self=1 86 | ascii_armored=0 87 | clearsign=0 88 | sign_key=0 89 | sign_key_id= 90 | ssl_pop=0 91 | ssl_imap=2 92 | ssl_nntp=0 93 | ssl_smtp=2 94 | use_nonblocking_ssl=1 95 | use_socks=0 96 | use_socks_for_recv=1 97 | use_socks_for_send=1 98 | socks_type=1 99 | proxy_host= 100 | proxy_port=1080 101 | use_proxy_auth=0 102 | proxy_name= 103 | proxy_pass= 104 | set_smtpport=0 105 | smtp_port=25 106 | set_popport=0 107 | pop_port=110 108 | set_imapport=0 109 | imap_port=143 110 | set_nntpport=0 111 | nntp_port=119 112 | set_domain=0 113 | domain= 114 | imap_directory= 115 | imap_clear_cache_on_exit=0 116 | set_sent_folder=0 117 | sent_folder= 118 | set_draft_folder=0 119 | draft_folder= 120 | set_queue_folder=0 121 | queue_folder= 122 | set_trash_folder=0 123 | trash_folder= 124 | ''; 125 | }; 126 | } 127 | -------------------------------------------------------------------------------- /profiles/applications/vscodium/default.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, inputs, ... }: 2 | let 3 | EDITOR = pkgs.writeShellScript "codium-editor" '' 4 | source "/etc/profiles/per-user/balsoft/etc/profile.d/hm-session-vars.sh" 5 | NIX_OZONE_WL=1 \ 6 | exec \ 7 | ${config.home-manager.users.balsoft.programs.vscode.package}/bin/codium \ 8 | --enable-features=UseOzonePlatform \ 9 | --ozone-platform=wayland \ 10 | -w -n \ 11 | "$@" 12 | ''; 13 | codium-wayland = pkgs.buildEnv { 14 | name = "codium-wayland"; 15 | paths = [ 16 | (pkgs.writeShellScriptBin "codium-wayland" '' 17 | NIX_OZONE_WL=1 \ 18 | exec \ 19 | ${config.home-manager.users.balsoft.programs.vscode.package}/bin/codium \ 20 | --enable-features=UseOzonePlatform \ 21 | --ozone-platform=wayland \ 22 | "$@" 23 | '') 24 | (pkgs.makeDesktopItem { 25 | name = "codium-wayland"; 26 | desktopName = "VSCodium (Wayland)"; 27 | exec = "codium-wayland"; 28 | icon = "code"; 29 | categories = [ "Utility" "TextEditor" "Development" "IDE" ]; 30 | mimeTypes = [ "text/plain" "inode/directory" ]; 31 | extraConfig = { 32 | StartupNotify = "true"; 33 | StartupWMClass = "vscodium"; 34 | }; 35 | }) 36 | ]; 37 | }; 38 | 39 | custom-extensions = import ./extensions.nix { 40 | inherit (pkgs.vscode-utils) buildVscodeMarketplaceExtension; 41 | }; 42 | in { 43 | environment.systemPackages = [ codium-wayland ]; 44 | 45 | defaultApplications.editor = { 46 | cmd = "${EDITOR}"; 47 | desktop = "codium-wayland"; 48 | }; 49 | home-manager.users.balsoft = { 50 | programs.vscode = { 51 | enable = true; 52 | package = pkgs.vscodium; 53 | 54 | mutableExtensionsDir = true; 55 | extensions = 56 | with inputs.nix-vscode-marketplace.packages.${pkgs.system}.vscode; 57 | with inputs.nix-vscode-marketplace.packages.${pkgs.system}.open-vsx; 58 | with pkgs.vscode-extensions; 59 | [ 60 | kahole.magit 61 | 62 | cab404.vscode-direnv 63 | 64 | (pkgs.callPackage ./theme.nix { } config.themes.colors) 65 | 66 | vscodevim.vim 67 | 68 | matklad.rust-analyzer 69 | redhat.vscode-yaml 70 | jnoortheen.nix-ide 71 | dhall.dhall-lang 72 | hashicorp.terraform 73 | timonwong.shellcheck 74 | bungcip.better-toml 75 | haskell.haskell 76 | justusadam.language-haskell 77 | ms-python.python 78 | github.vscode-pull-request-github 79 | eamodio.gitlens 80 | llvm-vs-code-extensions.vscode-clangd 81 | stkb.rewrap 82 | shardulm94.trailing-spaces 83 | meraymond.idris-vscode 84 | ocamllabs.ocaml-platform 85 | bierner.markdown-mermaid 86 | ] ++ pkgs.lib.concatMap builtins.attrValues 87 | (builtins.attrValues custom-extensions); 88 | 89 | userSettings = { 90 | "update.mode" = "none"; 91 | "[nix]"."editor.tabSize" = 2; 92 | "workbench.colorTheme" = "Balsoft's generated theme"; 93 | "terminal.integrated.profiles.linux".bash.path = 94 | "/run/current-system/sw/bin/bash"; 95 | "terminal.integrated.defaultProfile.linux" = "bash"; 96 | "editor.fontFamily" = "IBM Plex Mono"; 97 | "nix.formatterPath" = "nixfmt"; 98 | "git.autofetch" = true; 99 | "redhat.telemetry.enabled" = false; 100 | "security.workspace.trust.untrustedFiles" = "open"; 101 | "window.menuBarVisibility" = "toggle"; 102 | "vim.useSystemClipboard" = true; 103 | "haskell.manageHLS" = "PATH"; 104 | "extensions.autoCheckUpdates" = false; 105 | "extensions.autoUpdate" = false; 106 | }; 107 | keybindings = [{ 108 | key = "ctrl+shift+r"; 109 | command = "workbench.action.tasks.runTask"; 110 | when = "textInputFocus"; 111 | }]; 112 | }; 113 | }; 114 | } 115 | -------------------------------------------------------------------------------- /profiles/applications/vscodium/extensions.nix: -------------------------------------------------------------------------------- 1 | { buildVscodeMarketplaceExtension }: { 2 | dhall.vscode-dhall-lsp-server = buildVscodeMarketplaceExtension { 3 | mktplcRef = { 4 | publisher = "dhall"; 5 | name = "vscode-dhall-lsp-server"; 6 | version = "0.0.4"; 7 | sha256 = "sha256-WopWzMCtiiLrx3pHNiDMZYFdjS359vu3T+6uI5A+Nv4="; 8 | }; 9 | }; 10 | gpoore.codebraid-preview = buildVscodeMarketplaceExtension { 11 | mktplcRef = { 12 | publisher = "gpoore"; 13 | name = "codebraid-preview"; 14 | version = "0.8.0"; 15 | sha256 = "sha256-bw/uzdbLDREwhd0PHOD+Ref3UdaYlkhegsUhkTX1WlI="; 16 | }; 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /profiles/bluetooth.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | lib, 4 | config, 5 | ... 6 | }: 7 | { 8 | hardware.bluetooth = { 9 | enable = true; 10 | package = pkgs.bluez; 11 | }; 12 | 13 | systemd.services.bluetooth.serviceConfig.ExecStart = lib.mkForce [ 14 | "" 15 | "${pkgs.bluez}/libexec/bluetooth/bluetoothd -f /etc/bluetooth/main.conf -E" 16 | ]; 17 | 18 | persist.state.directories = [ "/var/lib/bluetooth" ]; 19 | home-manager.users.balsoft = 20 | let 21 | headphones = "80:99:E7:8B:AE:D5"; 22 | in 23 | { 24 | services.mpris-proxy.enable = true; 25 | programs.zsh.shellAliases = { 26 | "hpc" = "bluetoothctl connect ${headphones}"; 27 | "hpd" = "bluetoothctl disconnect ${headphones}"; 28 | }; 29 | 30 | wayland.windowManager.sway.config.keybindings = 31 | let 32 | inherit (config.home-manager.users.balsoft.wayland.windowManager.sway.config) 33 | modifier 34 | ; 35 | in 36 | { 37 | "${modifier}+F2" = "exec bluetoothctl connect ${headphones}"; 38 | "${modifier}+Shift+F2" = "exec bluetoothctl disconnect ${headphones}"; 39 | }; 40 | }; 41 | } 42 | -------------------------------------------------------------------------------- /profiles/boot.nix: -------------------------------------------------------------------------------- 1 | { lib, pkgs, config, ... }: { 2 | boot = { 3 | loader = { 4 | timeout = lib.mkForce 4; 5 | grub.enable = false; 6 | systemd-boot.enable = pkgs.system == "x86_64-linux"; 7 | }; 8 | kernelParams = [ "modeset" "nofb" "preempt=full" ] 9 | ++ lib.optionals (pkgs.system == "x86_64-linux") [ 10 | "pti=off" 11 | "spectre_v2=off" 12 | ]; 13 | 14 | kernelPackages = pkgs.linuxPackages_latest; 15 | 16 | consoleLogLevel = 3; 17 | kernel.sysctl."vm.swappiness" = 0; 18 | kernel.sysctl."kernel/sysrq" = 1; 19 | }; 20 | persist.state.etcFiles = [ "machine-id" ]; 21 | } 22 | -------------------------------------------------------------------------------- /profiles/hardware.nix: -------------------------------------------------------------------------------- 1 | { 2 | hardware.enableRedistributableFirmware = true; # For some unfree drivers 3 | # systemd.services.systemd-udev-settle.enable = false; 4 | services.fwupd.enable = true; 5 | # sound.enable = true; 6 | services.fstrim.enable = true; 7 | } 8 | -------------------------------------------------------------------------------- /profiles/network.nix: -------------------------------------------------------------------------------- 1 | { pkgs, lib, config, ... }: 2 | let 3 | localRanges = [{ 4 | from = 1714; 5 | to = 1764; 6 | } # KDE connect 7 | ]; 8 | in { 9 | networking = { 10 | networkmanager.enable = true; 11 | firewall = { 12 | enable = true; 13 | allowedTCPPorts = [ 13748 13722 5000 22 80 443 51820 ]; 14 | interfaces.wlan0.allowedTCPPortRanges = localRanges; 15 | interfaces.wlan0.allowedUDPPortRanges = localRanges; 16 | interfaces.eth0.allowedUDPPortRanges = localRanges; 17 | interfaces.eth0.allowedTCPPortRanges = localRanges; 18 | }; 19 | resolvconf.extraConfig = '' 20 | local_nameservers="" 21 | name_server_blacklist="0.0.0.0 127.0.0.1" 22 | resolv_conf_local_only=NO 23 | ''; 24 | usePredictableInterfaceNames = false; 25 | hostName = config.device; 26 | }; 27 | 28 | persist.state.directories = [ "/etc/NetworkManager/system-connections" ]; 29 | 30 | networking.firewall.trustedInterfaces = [ "eth0" ]; 31 | systemd.services.ModemManager.wantedBy = 32 | lib.optional (config.device == "T490s-Laptop") "network.target"; 33 | 34 | } 35 | -------------------------------------------------------------------------------- /profiles/nix/default.nix: -------------------------------------------------------------------------------- 1 | { pkgs, lib, inputs, config, ... }: { 2 | nix = { 3 | nixPath = lib.mkForce [ "self=/etc/self/compat" "nixpkgs=/etc/nixpkgs" ]; 4 | registry.self.flake = inputs.self; 5 | registry.np.flake = inputs.nixpkgs; 6 | 7 | nrBuildUsers = config.nix.settings.max-jobs; 8 | 9 | optimise.automatic = true; 10 | 11 | settings = { 12 | use-xdg-base-directories = true; 13 | builders-use-substitutes = true; 14 | flake-registry = "${inputs.flake-registry}/flake-registry.json"; 15 | experimental-features = [ "nix-command" "flakes" ]; 16 | trusted-users = [ "root" "balsoft" "@wheel" ]; 17 | trusted-public-keys = [ 18 | "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" 19 | "serokell-1:aIojg2Vxgv7MkzPJoftOO/I8HKX622sT+c0fjnZBLj0=" 20 | ]; 21 | substituters = [ "https://cache.nixos.org" ]; 22 | trusted-substituters = [ 23 | "s3://serokell-private-cache?endpoint=s3.eu-central-1.wasabisys.com&profile=serokell-private-cache-wasabi" 24 | ]; 25 | }; 26 | buildMachines = [ 27 | # tweag remote builder 28 | { 29 | hostName = "build01.tweag.io"; 30 | maxJobs = 24; 31 | sshUser = "nix"; 32 | sshKey = "/root/.ssh/id_ed25519"; 33 | system = "x86_64-linux"; 34 | supportedFeatures = [ "benchmark" "big-parallel" "kvm" ]; 35 | } 36 | { 37 | hostName = "build02.tweag.io"; 38 | maxJobs = 24; 39 | sshUser = "nix"; 40 | sshKey = "/root/.ssh/id_ed25519"; 41 | systems = [ "aarch64-darwin" "x86_64-darwin" ]; 42 | } 43 | ]; 44 | }; 45 | 46 | persist.state.directories = [ "/home/balsoft/.local/share/nix" ]; 47 | 48 | environment.etc.nixpkgs.source = inputs.nixpkgs; 49 | environment.etc.self.source = inputs.self; 50 | } 51 | -------------------------------------------------------------------------------- /profiles/opengl.nix: -------------------------------------------------------------------------------- 1 | { pkgs, ... }: { 2 | hardware.graphics.enable = true; 3 | # hardware.opengl.driSupport = true; 4 | hardware.graphics.enable32Bit = true; # For steam 5 | hardware.graphics.package = pkgs.mesa; 6 | } 7 | -------------------------------------------------------------------------------- /profiles/power.nix: -------------------------------------------------------------------------------- 1 | { 2 | services.upower.enable = true; 3 | 4 | services.logind.lidSwitchExternalPower = "ignore"; 5 | 6 | services.logind.extraConfig = "HandlePowerKey=suspend"; 7 | } 8 | -------------------------------------------------------------------------------- /profiles/security/pass-secret-service.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, lib, ... }: { 2 | home-manager.users.balsoft = { 3 | services.pass-secret-service.enable = true; 4 | 5 | systemd.user.services.pass-secret-service = { 6 | Service = { 7 | Type = "dbus"; 8 | Environment = [ "GPG_TTY=/dev/tty1" "DISPLAY=:0" ]; 9 | BusName = "org.freedesktop.secrets"; 10 | }; 11 | Unit = rec { 12 | Wants = [ "gpg-agent.service" ]; 13 | After = Wants; 14 | PartOf = [ "graphical-session-pre.target" ]; 15 | }; 16 | }; 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /profiles/security/user.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, lib, ... }: { 2 | users.mutableUsers = false; 3 | users.users.balsoft = { 4 | isNormalUser = true; 5 | extraGroups = [ 6 | "sudo" 7 | "wheel" 8 | "networkmanager" 9 | "disk" 10 | "dbus" 11 | "audio" 12 | "docker" 13 | "sound" 14 | "pulse" 15 | "adbusers" 16 | "input" 17 | "libvirtd" 18 | "vboxusers" 19 | "wireshark" 20 | "lp" 21 | "scanner" 22 | "feedbackd" 23 | ]; 24 | description = "Александр Бантьев"; 25 | uid = 1000; 26 | password = ""; 27 | }; 28 | 29 | systemd.services."user@" = { serviceConfig = { Restart = "always"; }; }; 30 | 31 | home-manager.users.balsoft = { 32 | systemd.user.services.polkit-agent = { 33 | Unit = { 34 | Description = "Run polkit authentication agent"; 35 | X-RestartIfChanged = true; 36 | }; 37 | 38 | Install.WantedBy = [ "sway-session.target" ]; 39 | 40 | Service = { ExecStart = "${pkgs.mate.mate-polkit}/libexec/polkit-mate-authentication-agent-1"; }; 41 | }; 42 | }; 43 | 44 | 45 | services.getty.autologinUser = "balsoft"; 46 | 47 | home-manager.useUserPackages = true; 48 | } 49 | -------------------------------------------------------------------------------- /profiles/security/vlock.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, lib, ... }: { 2 | environment.loginShellInit = lib.mkBefore '' 3 | [[ "$(tty)" == /dev/tty? ]] && sudo /run/current-system/sw/bin/lock this 4 | ''; 5 | 6 | environment.systemPackages = [ 7 | (pkgs.writeShellScriptBin "lock" '' 8 | set -euo pipefail 9 | if [[ "$1" == this ]] 10 | then args="-s" 11 | else args="-san" 12 | fi 13 | ${lib.optionalString (config.deviceSpecific.isLaptop) 14 | ''USER=balsoft ${pkgs.vlock}/bin/vlock "$args"''} 15 | '') 16 | ]; 17 | 18 | security.sudo = { 19 | enable = true; 20 | extraConfig = '' 21 | balsoft ALL = (root) NOPASSWD: /run/current-system/sw/bin/lock 22 | balsoft ALL = (root) NOPASSWD: /run/current-system/sw/bin/lock this 23 | balsoft ALL = (root) NOPASSWD: ${pkgs.light}/bin/light -A 5 24 | balsoft ALL = (root) NOPASSWD: ${pkgs.light}/bin/light -U 5 25 | ''; 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /profiles/security/yubikey.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: { 2 | home-manager.users.balsoft = { 3 | home.activation.yubi = { 4 | data = '' 5 | mkdir -p .config/Yubico 6 | [ -f /home/balsoft/.config/Yubico/u2f_keys ] || (pamu2fcfg > /home/balsoft/.config/Yubico/u2f_keys) 7 | ''; 8 | after = [ "linkGeneration" ]; 9 | before = [ ]; 10 | }; 11 | }; 12 | 13 | persist.state.directories = [ "/home/balsoft/.config/Yubico" ]; 14 | 15 | security.pam.services = builtins.listToAttrs (builtins.map (name: { 16 | inherit name; 17 | value = { unixAuth = false; }; 18 | }) [ 19 | "chpasswd" 20 | "chsh" 21 | "groupadd" 22 | "groupdel" 23 | "groupmems" 24 | "groupmod" 25 | "i3lock" 26 | "i3lock-color" 27 | "login" 28 | "passwd" 29 | "polkit-1" 30 | "runuser" 31 | "runuser-l" 32 | "su" 33 | "sudo" 34 | "swaylock" 35 | "systemd-user" 36 | "useradd" 37 | "userdel" 38 | "usermod" 39 | "vlock" 40 | "xlock" 41 | "xscreensaver" 42 | ]); 43 | 44 | security.pam.u2f = { 45 | control = "sufficient"; 46 | settings.cue = true; 47 | enable = true; 48 | }; 49 | 50 | } 51 | -------------------------------------------------------------------------------- /profiles/servers/gitea.nix: -------------------------------------------------------------------------------- 1 | { pkgs, config, lib, ... }: 2 | { 3 | services.gitea = { 4 | enable = false; 5 | appName = "code.balsoft.ru"; 6 | settings.server = { 7 | HTTP_PORT = 6000; 8 | ROOT_URL = "https://code.balsoft.ru"; 9 | DISABLE_REGISTRATION = true; 10 | COOKIE_SECURE = true; 11 | DOMAIN = "code.balsoft.ru"; 12 | }; 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /profiles/servers/home-assistant.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, lib, inputs, ... }: { 2 | services.home-assistant = { 3 | enable = true; 4 | package = (pkgs.home-assistant.override { 5 | extraPackages = py: with py; [ aiohttp-cors zeroconf pycrypto ]; 6 | }).overrideAttrs (_: { 7 | tests = []; 8 | doInstallCheck = false; 9 | }); 10 | config = { 11 | homeassistant = { 12 | name = "Home"; 13 | time_zone = "Europe/Moscow"; 14 | latitude = 1; 15 | longitude = 1; 16 | elevation = 1; 17 | unit_system = "metric"; 18 | temperature_unit = "C"; 19 | }; 20 | # Enable the frontend 21 | frontend = { }; 22 | sonoff = { 23 | default_class = "light"; 24 | }; 25 | mobile_app = { }; 26 | }; 27 | }; 28 | systemd.tmpfiles.rules = [ 29 | "C /var/lib/hass/custom_components/sonoff - - - - ${inputs.sonoff-lan}/custom_components/sonoff" 30 | "Z /var/lib/hass 770 hass hass - -" 31 | ]; 32 | services.nginx = { 33 | virtualHosts."hass.balsoft.ru" = { 34 | enableACME = true; 35 | forceSSL = true; 36 | extraConfig = '' 37 | proxy_buffering off; 38 | ''; 39 | locations."/" = { 40 | proxyPass = "http://127.0.0.1:8123"; 41 | proxyWebsockets = true; 42 | extraConfig = '' 43 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 44 | proxy_set_header Upgrade $http_upgrade; 45 | proxy_set_header Connection $connection_upgrade; 46 | ''; 47 | }; 48 | }; 49 | }; 50 | } 51 | -------------------------------------------------------------------------------- /profiles/servers/irc.nix: -------------------------------------------------------------------------------- 1 | { ... }: { 2 | services.ergochat = { 3 | enable = true; 4 | settings = { 5 | accounts = { 6 | authentication-enabled = true; 7 | multiclient = { 8 | allowed-by-default = true; 9 | always-on = "opt-out"; 10 | auto-away = "opt-out"; 11 | enabled = true; 12 | }; 13 | registration = { 14 | allow-before-connect = true; 15 | bcrypt-cost = 4; 16 | email-verification = { enabled = false; }; 17 | enabled = true; 18 | throttling = { 19 | duration = "10m"; 20 | enabled = true; 21 | max-attempts = 30; 22 | }; 23 | }; 24 | }; 25 | channels = { 26 | default-modes = "+ntC"; 27 | registration = { enabled = true; }; 28 | }; 29 | datastore = { 30 | autoupgrade = true; 31 | path = "/var/lib/ergo/ircd.db"; 32 | }; 33 | history = { 34 | autoreplay-on-join = 0; 35 | autoresize-window = "3d"; 36 | channel-length = 2048; 37 | chathistory-maxmessages = 100; 38 | client-length = 256; 39 | enabled = true; 40 | restrictions = { 41 | expire-time = "1w"; 42 | grace-period = "1h"; 43 | query-cutoff = "none"; 44 | }; 45 | retention = { 46 | allow-individual-delete = false; 47 | enable-account-indexing = false; 48 | }; 49 | tagmsg-storage = { 50 | default = false; 51 | whitelist = [ "+draft/react" "+react" ]; 52 | }; 53 | znc-maxmessages = 2048; 54 | }; 55 | limits = { 56 | awaylen = 390; 57 | channellen = 64; 58 | identlen = 20; 59 | kicklen = 390; 60 | nicklen = 32; 61 | topiclen = 390; 62 | }; 63 | network = { name = "balsoftnet"; }; 64 | server = { 65 | casemapping = "permissive"; 66 | check-ident = false; 67 | enforce-utf = true; 68 | forward-confirm-hostnames = false; 69 | ip-cloaking = { enabled = false; }; 70 | ip-limits = { 71 | count = false; 72 | throttle = false; 73 | }; 74 | listeners = { ":6667" = { }; }; 75 | lookup-hostnames = false; 76 | max-sendq = "1M"; 77 | name = "balsoft.ru"; 78 | relaymsg = { enabled = false; }; 79 | }; 80 | }; 81 | }; 82 | services.thelounge = { 83 | enable = true; 84 | extraConfig = { 85 | host = "localhost"; 86 | reverseProxy = true; 87 | lockNetwork = true; 88 | defaults = { 89 | host = "localhost"; 90 | name = "balsoftnet"; 91 | port = 6667; 92 | tls = false; 93 | nick = "user%%%"; 94 | leaveMessage = "<3"; 95 | join = "#klananas"; 96 | }; 97 | }; 98 | port = 9857; 99 | public = true; 100 | }; 101 | services.nginx.virtualHosts."chat.balsoft.ru" = { 102 | forceSSL = true; 103 | enableACME = true; 104 | locations."/".proxyPass = "http://localhost:9857"; 105 | basicAuthFile = "/var/lib/chat.passwd"; 106 | }; 107 | } 108 | -------------------------------------------------------------------------------- /profiles/servers/jitsi.nix: -------------------------------------------------------------------------------- 1 | { config, ... }: { 2 | services.jitsi-meet = { 3 | enable = true; 4 | hostName = "meet.balsoft.ru"; 5 | }; 6 | 7 | services.nginx.virtualHosts.${config.services.jitsi-meet.hostName} = { 8 | enableACME = true; 9 | forceSSL = true; 10 | basicAuthFile = "/var/lib/jitsi-auth"; 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /profiles/servers/mailserver.nix: -------------------------------------------------------------------------------- 1 | { pkgs, config, lib, inputs, ... }: 2 | let module = toString inputs.simple-nixos-mailserver; 3 | in { 4 | imports = [ module ]; 5 | secrets.mailserver = { 6 | owner = "dovecot2:dovecot2"; 7 | services = [ "dovecot2" ]; 8 | }; 9 | secrets.mailserver-mastodon = { 10 | owner = "dovecot2:dovecot2"; 11 | services = [ "dovecot2" ]; 12 | }; 13 | services.postfix = { 14 | dnsBlacklists = [ 15 | "all.s5h.net" 16 | "b.barracudacentral.org" 17 | "bl.spamcop.net" 18 | "blacklist.woody.ch" 19 | # "bogons.cymru.com" 20 | # "cbl.abuseat.org" 21 | # "combined.abuse.ch" 22 | # "db.wpbl.info" 23 | # "dnsbl-1.uceprotect.net" 24 | # "dnsbl-2.uceprotect.net" 25 | # "dnsbl-3.uceprotect.net" 26 | # "dnsbl.anticaptcha.net" 27 | # "dnsbl.dronebl.org" 28 | # "dnsbl.inps.de" 29 | # "dnsbl.sorbs.net" 30 | # "dnsbl.spfbl.net" 31 | # "drone.abuse.ch" 32 | # "duinv.aupads.org" 33 | # "dul.dnsbl.sorbs.net" 34 | # "dyna.spamrats.com" 35 | # "dynip.rothen.com" 36 | # "http.dnsbl.sorbs.net" 37 | # "ips.backscatterer.org" 38 | # "ix.dnsbl.manitu.net" 39 | # "korea.services.net" 40 | # "misc.dnsbl.sorbs.net" 41 | # "noptr.spamrats.com" 42 | # "orvedb.aupads.org" 43 | # "pbl.spamhaus.org" 44 | # "proxy.bl.gweep.ca" 45 | # "psbl.surriel.com" 46 | # "relays.bl.gweep.ca" 47 | # "relays.nether.net" 48 | # "sbl.spamhaus.org" 49 | # "singular.ttk.pte.hu" 50 | # "smtp.dnsbl.sorbs.net" 51 | # "socks.dnsbl.sorbs.net" 52 | # "spam.abuse.ch" 53 | # "spam.dnsbl.anonmails.de" 54 | # "spam.dnsbl.sorbs.net" 55 | # "spam.spamrats.com" 56 | # "spambot.bls.digibase.ca" 57 | # "spamrbl.imp.ch" 58 | # "spamsources.fabel.dk" 59 | # "ubl.lashback.com" 60 | # "ubl.unsubscore.com" 61 | # "virus.rbl.jp" 62 | # "web.dnsbl.sorbs.net" 63 | # "wormrbl.imp.ch" 64 | # "xbl.spamhaus.org" 65 | # "z.mailspike.net" 66 | # "zen.spamhaus.org" 67 | # "zombie.dnsbl.sorbs.net" 68 | ]; 69 | dnsBlacklistOverrides = '' 70 | balsoft.ru OK 71 | 192.168.0.0/16 OK 72 | ${lib.concatMapStringsSep "\n" (machine: "${machine}.lan OK") 73 | (builtins.attrNames inputs.self.nixosConfigurations)} 74 | ''; 75 | }; 76 | services.dovecot2 = { 77 | mailPlugins.globally.enable = [ "virtual" ]; 78 | extraConfig = '' 79 | namespace { 80 | prefix = virtual. 81 | separator = . 82 | location = virtual:~/Maildir/virtual 83 | } 84 | ''; 85 | }; 86 | systemd.tmpfiles.rules = [ 87 | "d /var/vmail/Maildir 700 virtualMail virtualMail - -" 88 | "d /var/vmail/Maildir/virtual 700 virtualMail virtualMail - -" 89 | "d /var/vmail/Maildir/virtual/all 700 virtualMail virtualMail - -" 90 | "d /var/vmail/Maildir/virtual/INBOX 700 virtualMail virtualMail - -" 91 | "L+ /var/vmail/Maildir/virtual/all/dovecot-virtual - - - - ${ 92 | pkgs.writeText "virtual.all" '' 93 | * 94 | all 95 | '' 96 | }" 97 | "L+ /var/vmail/Maildir/virtual/INBOX/dovecot-virtual - - - - ${ 98 | pkgs.writeText "virtual.INBOX" '' 99 | virtual.all 100 | inthread refs x-mailbox INBOX 101 | '' 102 | }" 103 | ]; 104 | mailserver = { 105 | enable = true; 106 | fqdn = "balsoft.ru"; 107 | domains = [ "balsoft.ru" ]; 108 | mailboxes = { 109 | Trash = { 110 | auto = "no"; 111 | specialUse = "Trash"; 112 | }; 113 | Junk = { 114 | auto = "subscribe"; 115 | specialUse = "Junk"; 116 | }; 117 | Drafts = { 118 | auto = "subscribe"; 119 | specialUse = "Drafts"; 120 | }; 121 | Sent = { 122 | auto = "subscribe"; 123 | specialUse = "Sent"; 124 | }; 125 | }; 126 | loginAccounts = { 127 | "balsoft@balsoft.ru" = { 128 | aliases = [ 129 | "balsoft" 130 | "admin@balsoft.ru" 131 | "patches" 132 | "patches@balsoft.ru" 133 | "issues" 134 | "issues@balsoft.ru" 135 | "admin" 136 | "root@balsoft.ru" 137 | "root" 138 | "paypal@balsoft.ru" 139 | "paypal" 140 | ]; 141 | hashedPasswordFile = config.secrets.mailserver.decrypted; 142 | sieveScript = '' 143 | if header :is "X-GitHub-Sender" "serokell-bot" { 144 | discard; 145 | stop; 146 | } 147 | ''; 148 | }; 149 | "mastodon@balsoft.ru" = { 150 | aliases = [ "mastodon" ]; 151 | hashedPasswordFile = config.secrets.mailserver-mastodon.decrypted; 152 | }; 153 | }; 154 | localDnsResolver = false; 155 | certificateScheme = "manual"; 156 | certificateFile = "/var/lib/acme/balsoft.ru/fullchain.pem"; 157 | keyFile = "/var/lib/acme/balsoft.ru/key.pem"; 158 | enableImap = true; 159 | enableImapSsl = true; 160 | virusScanning = false; 161 | }; 162 | } 163 | -------------------------------------------------------------------------------- /profiles/servers/mastodon.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, lib, ... }: { 2 | secrets.email-mastodon = { 3 | owner = "mastodon:mastodon"; 4 | encrypted = "/home/balsoft/.password-store/email/mastodon@balsoft.ru.gpg"; 5 | services = [ "mastodon-web" ]; 6 | }; 7 | services.mastodon = { 8 | enable = true; 9 | configureNginx = true; 10 | localDomain = "social.balsoft.ru"; 11 | smtp = { 12 | createLocally = false; 13 | fromAddress = "mastodon@balsoft.ru"; 14 | user = "mastodon"; 15 | host = "balsoft.ru"; 16 | passwordFile = config.secrets.email-mastodon.decrypted; 17 | }; 18 | }; 19 | } 20 | -------------------------------------------------------------------------------- /profiles/servers/matrix-synapse.nix: -------------------------------------------------------------------------------- 1 | { pkgs, config, lib, ... }: { 2 | services.matrix-synapse = { 3 | enable = true; 4 | settings = { 5 | allow_guest_access = false; 6 | listeners = [{ 7 | # bind_address = "0.0.0.0"; 8 | port = 13748; 9 | resources = [ 10 | { 11 | compress = true; 12 | names = [ "client" ]; 13 | } 14 | { 15 | compress = false; 16 | names = [ "federation" ]; 17 | } 18 | ]; 19 | type = "http"; 20 | tls = false; 21 | x_forwarded = true; 22 | }]; 23 | public_baseurl = "https://balsoft.ru"; 24 | server_name = "balsoft.ru"; 25 | turn_uris = 26 | [ "turn:balsoft.ru?transport=udp" "turn:balsoft.ru?transport=tcp" ]; 27 | # app_service_config_files = 28 | # [ config.secrets-envsubst.mautrix-telegram-registration.substituted ]; 29 | allow_public_rooms_over_federation = true; 30 | }; 31 | extraConfigFiles = [ 32 | config.secrets-envsubst.coturn.substituted 33 | config.secrets-envsubst.matrix.substituted 34 | ]; 35 | }; 36 | 37 | services.postgresql.enable = true; 38 | services.postgresql.package = pkgs.postgresql_15; 39 | 40 | services.mautrix-telegram = { 41 | enable = true; 42 | environmentFile = toString config.secrets-envsubst.mautrix-telegram; 43 | settings = { 44 | appservice = { 45 | address = "http://localhost:29317"; 46 | bot_avatar = "mxc://maunium.net/tJCRmUyJDsgRNgqhOgoiHWbX"; 47 | id = "telegram"; 48 | max_body_size = 1; 49 | port = 29317; 50 | }; 51 | bridge = { 52 | alias_template = "tg_{groupname}"; 53 | allow_matrix_login = true; 54 | bot_messages_as_notices = true; 55 | catch_up = true; 56 | command_prefix = "!tg"; 57 | image_as_file_size = 10; 58 | max_document_size = 100; 59 | max_initial_member_sync = -1; 60 | max_telegram_delete = 10; 61 | permissions = { 62 | "*" = "relaybot"; 63 | "@balsoft:balsoft.ru" = "admin"; 64 | }; 65 | plaintext_highlights = true; 66 | startup_sync = true; 67 | username_template = "tg_{userid}"; 68 | relay_user_distinguishers = [ ]; 69 | state_event_formats = { 70 | leave = ""; 71 | name_change = ""; 72 | }; 73 | }; 74 | homeserver = { 75 | address = "https://matrix.balsoft.ru"; 76 | domain = "balsoft.ru"; 77 | verify_ssl = true; 78 | }; 79 | }; 80 | }; 81 | 82 | secrets-envsubst.mautrix-telegram = { 83 | secrets = [ "as_token" "hs_token" "api_id" "api_hash" "bot_token" ]; 84 | template = '' 85 | MAUTRIX_TELEGRAM_APPSERVICE_AS_TOKEN=$as_token 86 | MAUTRIX_TELEGRAM_APPSERVICE_HS_TOKEN=$hs_token 87 | MAUTRIX_TELEGRAM_TELEGRAM_API_ID=$api_id 88 | MAUTRIX_TELEGRAM_TELEGRAM_API_HASH=$api_hash 89 | MAUTRIX_TELEGRAM_TELEGRAM_BOT_TOKEN=$bot_token 90 | ''; 91 | }; 92 | 93 | secrets-envsubst.mautrix-telegram-registration = { 94 | directory = "mautrix-telegram"; 95 | secrets = [ "as_token" "hs_token" ]; 96 | owner = "matrix-synapse"; 97 | template = builtins.toJSON { 98 | as_token = "$as_token"; 99 | hs_token = "$hs_token"; 100 | id = "telegram"; 101 | namespaces = { 102 | aliases = [{ 103 | exclusive = true; 104 | regex = "#tg_.+:balsoft.ru"; 105 | }]; 106 | users = [{ 107 | exclusive = true; 108 | regex = "@tg_.+:balsoft.ru"; 109 | }]; 110 | }; 111 | rate_limited = false; 112 | sender_localpart = "telegrambot"; 113 | url = "http://localhost:29317"; 114 | }; 115 | }; 116 | 117 | systemd.services.mautrix-telegram.serviceConfig = { 118 | DynamicUser = lib.mkForce false; 119 | Restart = "always"; 120 | RuntimeMaxSec = "1d"; 121 | }; 122 | 123 | systemd.services.mautrix-telegram.serviceConfig.User = "mautrix-telegram"; 124 | 125 | users.users.mautrix-telegram = { 126 | group = "mautrix-telegram"; 127 | isSystemUser = true; 128 | }; 129 | 130 | users.groups.mautrix-telegram = { }; 131 | 132 | users.users.matrix-synapse.name = lib.mkForce "matrix-synapse"; 133 | 134 | services.coturn = { 135 | enable = true; 136 | use-auth-secret = true; 137 | static-auth-secret-file = config.secrets.coturn.decrypted; 138 | no-tls = true; 139 | realm = "balsoft.ru"; 140 | extraConfig = '' 141 | external-ip=94.25.150.197 142 | 143 | denied-peer-ip=10.0.0.0-10.255.255.255 144 | denied-peer-ip=192.168.0.0-192.168.255.255 145 | denied-peer-ip=172.16.0.0-172.31.255.255 146 | 147 | denied-peer-ip=0.0.0.0-0.255.255.255 148 | denied-peer-ip=100.64.0.0-100.127.255.255 149 | denied-peer-ip=127.0.0.0-127.255.255.255 150 | denied-peer-ip=169.254.0.0-169.254.255.255 151 | denied-peer-ip=192.0.0.0-192.0.0.255 152 | denied-peer-ip=192.0.2.0-192.0.2.255 153 | denied-peer-ip=192.88.99.0-192.88.99.255 154 | denied-peer-ip=198.18.0.0-198.19.255.255 155 | denied-peer-ip=198.51.100.0-198.51.100.255 156 | denied-peer-ip=203.0.113.0-203.0.113.255 157 | denied-peer-ip=240.0.0.0-255.255.255.255 158 | 159 | allowed-peer-ip=192.168.8.236 160 | ''; 161 | }; 162 | 163 | secrets.coturn = { 164 | encrypted = 165 | "/home/balsoft/.local/share/password-store/coturn/shared_secret.gpg"; 166 | services = [ "coturn" ]; 167 | owner = "turnserver:turnserver"; 168 | }; 169 | secrets-envsubst.coturn = { 170 | secrets = [ "shared_secret" ]; 171 | services = [ "matrix-synapse" ]; 172 | owner = "matrix-synapse:matrix-synapse"; 173 | template = builtins.toJSON { turn_shared_secret = "$shared_secret"; }; 174 | }; 175 | secrets-envsubst.matrix = { 176 | secrets = [ "registration_shared_secret" ]; 177 | services = [ "matrix-synapse" ]; 178 | owner = "matrix-synapse:matrix-synapse"; 179 | template = builtins.toJSON { 180 | registration_shared_secret = "$registration_shared_secret"; 181 | }; 182 | }; 183 | 184 | networking.firewall = rec { 185 | allowedTCPPorts = [ 3478 5349 ]; 186 | allowedUDPPorts = allowedTCPPorts; 187 | allowedUDPPortRanges = [{ 188 | from = 49152; 189 | to = 65535; 190 | }]; 191 | }; 192 | 193 | } 194 | -------------------------------------------------------------------------------- /profiles/servers/minidlna.nix: -------------------------------------------------------------------------------- 1 | { 2 | services.minidlna = { 3 | enable = true; 4 | announceInterval = 10; 5 | mediaDirs = [ "A,/var/lib/music" ]; 6 | }; 7 | } 8 | -------------------------------------------------------------------------------- /profiles/servers/nextcloud.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | pkgs, 4 | lib, 5 | ... 6 | }: 7 | { 8 | services.nextcloud = { 9 | enable = true; 10 | hostName = "nextcloud.balsoft.ru"; 11 | config.adminpassFile = config.secrets.nextcloud.decrypted; 12 | config.dbtype = "sqlite"; 13 | package = pkgs.nextcloud31; 14 | https = true; 15 | phpOptions.memory_limit = lib.mkForce "1G"; 16 | settings = { 17 | "memories.exiftool" = "${lib.getExe pkgs.exiftool}"; 18 | "memories.vod.ffmpeg" = "${lib.getExe pkgs.ffmpeg-headless}"; 19 | "memories.vod.ffprobe" = "${pkgs.ffmpeg-headless}/bin/ffprobe"; 20 | }; 21 | phpExtraExtensions = all: [ 22 | ((all.pdlib.override { dlib = (pkgs.dlib.override { blas = pkgs.openblas; }); }).overrideAttrs 23 | (oa: { 24 | buildInputs = oa.buildInputs ++ [ 25 | pkgs.openblas 26 | pkgs.liblapack 27 | ]; 28 | }) 29 | ) 30 | ]; 31 | }; 32 | services.phpfpm.pools.nextcloud.phpEnv.PATH = 33 | lib.mkForce "/run/wrappers/bin:${pkgs.ffmpeg-headless}/bin:${pkgs.exiftool}/bin:${pkgs.perl}/bin:/usr/bin:/bin"; 34 | secrets.nextcloud = { 35 | owner = "nextcloud:nextcloud"; 36 | services = [ "nextcloud-setup" ]; 37 | }; 38 | services.nginx.virtualHosts."nextcloud.balsoft.ru" = { 39 | enableACME = true; 40 | forceSSL = true; 41 | locations."/".proxyWebsockets = true; 42 | }; 43 | } 44 | -------------------------------------------------------------------------------- /profiles/servers/nginx.nix: -------------------------------------------------------------------------------- 1 | { pkgs, config, lib, ... }: { 2 | services.nginx = { 3 | enable = true; 4 | appendHttpConfig = "charset utf-8;"; 5 | virtualHosts = let 6 | default = { 7 | forceSSL = true; 8 | enableACME = true; 9 | }; 10 | in { 11 | "balsoft.ru" = { 12 | default = true; 13 | locations."/" = { 14 | root = "/var/lib/balsoft.ru"; 15 | index = "index.txt"; 16 | }; 17 | locations."/.well-known" = { 18 | proxyPass = "http://localhost:13748"; 19 | }; 20 | locations."/_matrix" = { 21 | proxyPass = "http://localhost:13748"; 22 | }; 23 | enableACME = true; 24 | forceSSL = true; 25 | }; 26 | "code.balsoft.ru" = { 27 | locations."/" = { proxyPass = "http://localhost:6000"; }; 28 | } // default; 29 | "cache.balsoft.ru" = { 30 | locations."/" = { proxyPass = "http://localhost:5000"; }; 31 | } // default; 32 | "matrix.balsoft.ru" = { 33 | locations."/" = { 34 | proxyPass = "http://localhost:13748"; 35 | }; 36 | } // default; 37 | "share.balsoft.ru" = { 38 | locations."/" = { root = "/var/lib/share"; }; 39 | } // default; 40 | "things.balsoft.ru" = { 41 | locations."/" = { root = "/nix/var/nix/profiles/per-user/nginx/random-things/www"; }; 42 | } // default; 43 | }; 44 | }; 45 | security.acme.defaults.email = "balsoft@balsoft.ru"; 46 | security.acme.acceptTerms = true; 47 | } 48 | -------------------------------------------------------------------------------- /profiles/servers/ntfy.nix: -------------------------------------------------------------------------------- 1 | { config, ... }: 2 | { 3 | services.ntfy-sh = { 4 | enable = true; 5 | settings = { 6 | base-url = "https://ntfy.balsoft.ru"; 7 | listen-http = "localhost:8111"; 8 | behind-proxy = true; 9 | enable-login = true; 10 | auth-default-access = "read-write"; 11 | }; 12 | }; 13 | 14 | secrets.ntfy_password = { owner = "nginx:nginx"; }; 15 | 16 | services.nginx.virtualHosts."ntfy.balsoft.ru" = { 17 | enableACME = true; 18 | forceSSL = true; 19 | 20 | locations."/" = { 21 | proxyPass = "http://127.0.0.1:8111"; 22 | proxyWebsockets = true; 23 | # basicAuthFile = config.secrets.ntfy_password.decrypted; 24 | }; 25 | }; 26 | } 27 | -------------------------------------------------------------------------------- /profiles/servers/remapper.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: { 2 | systemd.services.remapper = { 3 | path = [ pkgs.remapper ]; 4 | script = "remapper"; 5 | serviceConfig = { 6 | EnvironmentFile = config.secrets.remapper-telegram-token.decrypted; 7 | PrivateTmp = true; 8 | User = "remapper"; 9 | Group = "remapper"; 10 | }; 11 | }; 12 | users.users.remapper = { 13 | isSystemUser = true; 14 | group = "remapper"; 15 | }; 16 | users.groups.remapper = { }; 17 | secrets.remapper-telegram-token = { 18 | owner = "remapper:remapper"; 19 | services = [ "remapper" ]; 20 | }; 21 | } -------------------------------------------------------------------------------- /profiles/servers/vsftpd.nix: -------------------------------------------------------------------------------- 1 | { 2 | services.vsftpd = { 3 | enable = true; 4 | anonymousUser = true; 5 | allowWriteableChroot = true; 6 | anonymousMkdirEnable = true; 7 | anonymousUploadEnable = true; 8 | writeEnable = true; 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /profiles/sound.nix: -------------------------------------------------------------------------------- 1 | { pkgs, config, lib, ... }: { 2 | services.pulseaudio.enable = lib.mkForce false; 3 | 4 | security.rtkit.enable = true; 5 | 6 | services.pipewire = { 7 | enable = true; 8 | alsa.enable = true; 9 | pulse.enable = true; 10 | wireplumber.enable = true; 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /profiles/virtualisation.nix: -------------------------------------------------------------------------------- 1 | { config, lib, ... }: { 2 | # virtualisation.docker.enable = config.deviceSpecific.isHost; 3 | # virtualisation.libvirtd = { 4 | # enable = config.deviceSpecific.isHost; 5 | # allowedBridges = lib.mkForce []; 6 | # }; 7 | 8 | persist.state.directories = [ 9 | "/var/lib/docker" 10 | "/var/lib/libvirt" 11 | ]; 12 | 13 | # virtualisation.spiceUSBRedirection.enable = true; 14 | 15 | # networking.nat = { 16 | # enable = true; 17 | # internalInterfaces = ["ve-+"]; 18 | # }; 19 | } 20 | -------------------------------------------------------------------------------- /profiles/workspace/autoRun.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, lib, ... }: { 2 | home-manager.users.balsoft = { 3 | programs.nix-index.enable = true; 4 | }; 5 | 6 | persist.cache.directories = [ "/home/balsoft/.cache/nix-index" ]; 7 | 8 | environment.sessionVariables = { 9 | NIX_AUTO_RUN = "1"; 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /profiles/workspace/aws.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, lib, ... }: { 2 | secrets.aws_credentials = { 3 | owner = "balsoft:users"; 4 | services = [ ]; 5 | }; 6 | 7 | systemd.tmpfiles.rules = [ "L+ /root/.aws/credentials - - - - ${config.secrets.aws_credentials.decrypted}" ]; 8 | 9 | environment.sessionVariables = { 10 | AWS_SHARED_CREDENTIALS_FILE = config.secrets.aws_credentials.decrypted; 11 | AWS_CONFIG_FILE = toString (pkgs.writeText "aws_config" 12 | (pkgs.my-lib.genIni { default.region = "eu-west-2"; })); 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /profiles/workspace/btop/default.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: { 2 | defaultApplications = { 3 | monitor = { 4 | cmd = 5 | "${config.defaultApplications.term.cmd} -T btop -e ${pkgs.btop}/bin/btop"; 6 | desktop = "alacritty"; 7 | }; 8 | }; 9 | home-manager.users.balsoft = { 10 | programs.btop = { 11 | enable = true; 12 | settings = { 13 | vim_keys = true; 14 | proc_gradient = false; 15 | color_theme = "Default"; 16 | update_ms = 500; 17 | presets = "cpu:0:default,proc:0:default cpu:0:default,mem:0:default"; 18 | }; 19 | }; 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /profiles/workspace/cage.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, lib, ... }: { 2 | services.cage = { 3 | enable = true; 4 | program = config.defaultApplications.term.cmd; 5 | user = "balsoft"; 6 | }; 7 | } 8 | -------------------------------------------------------------------------------- /profiles/workspace/copyq.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: { 2 | environment.systemPackages = [ pkgs.copyq ]; 3 | home-manager.users.balsoft = { 4 | wayland.windowManager.sway.config = { 5 | window.commands = [ 6 | { 7 | criteria = { title = ".*CopyQ"; }; 8 | command = "floating enable"; 9 | } 10 | { 11 | criteria = { title = ".*CopyQ"; }; 12 | command = "move position mouse"; 13 | } 14 | ]; 15 | startup = [{ command = "${pkgs.copyq}/bin/copyq"; }]; 16 | }; 17 | 18 | }; 19 | } 20 | -------------------------------------------------------------------------------- /profiles/workspace/cursor.nix: -------------------------------------------------------------------------------- 1 | { pkgs, lib, ... }: { 2 | 3 | environment.sessionVariables = { 4 | XCURSOR_PATH = lib.mkForce "/home/balsoft/.icons"; 5 | }; 6 | 7 | home-manager.users.balsoft = { 8 | 9 | home.pointerCursor = { 10 | package = pkgs.kdePackages.breeze; 11 | name = "breeze_cursors"; 12 | size = 16; 13 | }; 14 | 15 | home.file."/home/balsoft/.icons/default".source = 16 | "${lib.getBin pkgs.kdePackages.breeze}/share/icons/breeze_cursors"; 17 | 18 | 19 | home.file."/home/balsoft/.icons/Breeze".source = 20 | "${lib.getBin pkgs.kdePackages.breeze}/share/icons/breeze_cursors"; 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /profiles/workspace/direnv.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, lib, inputs, ... }: { 2 | home-manager.users.balsoft = { 3 | programs.direnv = { 4 | enable = true; 5 | nix-direnv = { 6 | enable = true; 7 | }; 8 | }; 9 | }; 10 | persist.state.directories = 11 | [ "/home/balsoft/.local/share/direnv" ]; 12 | } 13 | -------------------------------------------------------------------------------- /profiles/workspace/fonts.nix: -------------------------------------------------------------------------------- 1 | { pkgs, config, lib, ... }: { 2 | fonts = { 3 | packages = with pkgs; [ 4 | ibm-plex 5 | nerdfonts 6 | material-design-icons 7 | material-icons 8 | fira-code 9 | fira-code-symbols 10 | ]; 11 | fontconfig = let fonts = config.themes.fonts; 12 | in { 13 | enable = lib.mkForce true; 14 | defaultFonts = { 15 | monospace = [ "${fonts.mono.family} ${toString fonts.mono.size}" ]; 16 | sansSerif = [ "${fonts.main.family} ${toString fonts.main.size}" ]; 17 | serif = [ "${fonts.serif.family} ${toString fonts.serif.size}" ]; 18 | }; 19 | }; 20 | enableDefaultPackages = true; 21 | }; 22 | themes.fonts = { 23 | main = { 24 | family = "IBM Plex Sans"; 25 | size = lib.mkDefault 13; 26 | }; 27 | serif = { 28 | family = "IBM Plex Serif"; 29 | size = lib.mkDefault 13; 30 | }; 31 | mono = { 32 | family = "IBM Plex Mono"; 33 | size = lib.mkDefault 13; 34 | }; 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /profiles/workspace/git.nix: -------------------------------------------------------------------------------- 1 | { 2 | home-manager.users.balsoft.programs = { 3 | git = { 4 | enable = true; 5 | userEmail = "balsoft@balsoft.ru"; 6 | userName = "Alexander Bantyev"; 7 | extraConfig.pull.rebase = true; 8 | ignores = [ ".envrc" ".direnv" ".shell.nix" ".balsoft" "*~" ".#*" "#*#" ]; 9 | signing = { 10 | signByDefault = true; 11 | key = "687558B21E04FE92B255BED0E081FF12ADCB4AD5"; 12 | }; 13 | }; 14 | lazygit = { 15 | enable = true; 16 | settings = { update.method = "never"; }; 17 | }; 18 | }; 19 | } 20 | -------------------------------------------------------------------------------- /profiles/workspace/gnome3/accounts.conf: -------------------------------------------------------------------------------- 1 | [Account account_1609508064_4] 2 | Provider=owncloud 3 | Identity=balsoft 4 | PresentationIdentity=balsoft@nextcloud.balsoft.ru 5 | CalendarEnabled=true 6 | ContactsEnabled=true 7 | DocumentsEnabled=true 8 | FilesEnabled=true 9 | Uri=https://nextcloud.balsoft.ru/ 10 | AcceptSslErrors=false 11 | 12 | # [Account account_1634567009_0] 13 | # Provider=google 14 | # Identity=balsoft75@gmail.com 15 | # PresentationIdentity=balsoft75@gmail.com 16 | # MailEnabled=false 17 | # CalendarEnabled=true 18 | # ContactsEnabled=true 19 | # DocumentsEnabled=true 20 | # PhotosEnabled=true 21 | # FilesEnabled=true 22 | # PrintersEnabled=true 23 | 24 | [Account account_1635512206_0] 25 | Provider=google 26 | Identity=alexander.bantyev@tweag.io 27 | PresentationIdentity=alexander.bantyev@tweag.io 28 | MailEnabled=true 29 | CalendarEnabled=true 30 | ContactsEnabled=true 31 | DocumentsEnabled=true 32 | PhotosEnabled=true 33 | FilesEnabled=true 34 | PrintersEnabled=true 35 | -------------------------------------------------------------------------------- /profiles/workspace/gnome3/default.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, lib, ... }: { 2 | environment.systemPackages = [ pkgs.pass-secret-service ]; 3 | 4 | environment.gnome.excludePackages = [ pkgs.gnome-console pkgs.gnome.evince pkgs.gnome.eog ]; 5 | 6 | services.dbus.packages = [ pkgs.pass-secret-service ]; 7 | xdg.portal.extraPortals = [ pkgs.pass-secret-service ]; 8 | 9 | services.gvfs.enable = true; 10 | services.geoclue2.enable = true; 11 | 12 | fileSystems = with config.persist; 13 | lib.mkIf enable (builtins.listToAttrs (map (name: { 14 | inherit name; 15 | value.options = [ "x-gvfs-hide" ]; 16 | }) (state.directories ++ cache.directories ++ derivative.directories))); 17 | 18 | defaultApplications = { 19 | fm = { 20 | cmd = "${pkgs.nautilus}/bin/nautilus"; 21 | desktop = "org.gnome.Nautilus"; 22 | }; 23 | archive = { 24 | cmd = "${pkgs.file-roller}/bin/file-roller"; 25 | desktop = "org.gnome.FileRoller"; 26 | }; 27 | }; 28 | home-manager.users.balsoft = { 29 | 30 | home.activation.gnome = '' 31 | $DRY_RUN_CMD mkdir -p "$XDG_CONFIG_HOME/goa-1.0" 32 | $DRY_RUN_CMD ln -sf ${ 33 | ./accounts.conf 34 | } "$XDG_CONFIG_HOME/goa-1.0/accounts.conf" 35 | $DRY_RUN_CMD mkdir -p "$XDG_CONFIG_HOME/evolution/sources" 36 | $DRY_RUN_CMD ln -sf ${ 37 | ./nextcloud.source 38 | } "$XDG_CONFIG_HOME/evolution/sources/nextcloud.source" 39 | ''; 40 | 41 | home.packages = with pkgs; [ nautilus file-roller ]; 42 | 43 | dconf.settings = { 44 | "org/gnome/nautilus/icon-view" = { 45 | captions = [ "size" "date_modified" "none" ]; 46 | }; 47 | "org/gnome/nautilus/list-view" = { 48 | default-column-order = [ 49 | "name" 50 | "size" 51 | "type" 52 | "owner" 53 | "group" 54 | "permissions" 55 | "where" 56 | "date_modified" 57 | "date_modified_with_time" 58 | "date_accessed" 59 | "recency" 60 | "starred" 61 | "detailed_type" 62 | ]; 63 | default-visible-columns = [ "name" "size" "date_modified" "starred" ]; 64 | }; 65 | "org/gnome/nautilus/preferences" = { 66 | default-folder-viewer = "list-view"; 67 | executable-text-activation = "display"; 68 | search-filter-time-type = "last_modified"; 69 | search-view = "list-view"; 70 | show-image-thumbnails = "always"; 71 | thumbnail-limit = 10; 72 | }; 73 | 74 | "org/gnome/evince/default" = { inverted-colors = true; }; 75 | 76 | "org/gnome/maps" = { 77 | night-mode = true; 78 | transportation-type = "car"; 79 | }; 80 | }; 81 | }; 82 | } 83 | -------------------------------------------------------------------------------- /profiles/workspace/gnome3/nextcloud.source: -------------------------------------------------------------------------------- 1 | [Data Source] 2 | DisplayName=balsoft@nextcloud.balsoft.ru 3 | Enabled=true 4 | Parent= 5 | 6 | [Authentication] 7 | Host= 8 | Method=none 9 | Port=0 10 | ProxyUid=system-proxy 11 | RememberPassword=true 12 | User= 13 | CredentialName= 14 | IsExternal=true 15 | 16 | [Collection] 17 | BackendName=webdav 18 | CalendarEnabled=true 19 | ContactsEnabled=true 20 | Identity=balsoft 21 | MailEnabled=true 22 | AllowSourcesRename=false 23 | CalendarUrl= 24 | ContactsUrl= 25 | 26 | [GNOME Online Accounts] 27 | AccountId=account_1609508064_4 28 | CalendarUrl=https://balsoft@nextcloud.balsoft.ru/remote.php/caldav/ 29 | ContactsUrl=https://balsoft@nextcloud.balsoft.ru/remote.php/carddav/ 30 | Name= 31 | Address= 32 | -------------------------------------------------------------------------------- /profiles/workspace/gpg.nix: -------------------------------------------------------------------------------- 1 | { pkgs, lib, config, ... }: { 2 | services.pcscd.enable = true; 3 | services.udev.packages = [ pkgs.yubikey-personalization ]; 4 | 5 | persist.derivative.directories = [ "/home/balsoft/.local/share/gnupg" ]; 6 | 7 | home-manager.users.balsoft = { 8 | services.gpg-agent = { 9 | enable = true; 10 | enableSshSupport = true; 11 | pinentry.package = pkgs.pinentry-qt; 12 | }; 13 | 14 | systemd.user.services.gpg-agent = { 15 | Service = { 16 | Environment = lib.mkForce [ 17 | "GPG_TTY=/dev/tty1" 18 | "DISPLAY=:0" 19 | "GNUPGHOME=${config.home-manager.users.balsoft.xdg.dataHome}/gnupg" 20 | ]; 21 | }; 22 | }; 23 | 24 | programs.gpg = { 25 | enable = true; 26 | homedir = "${config.home-manager.users.balsoft.xdg.dataHome}/gnupg"; 27 | scdaemonSettings = { 28 | disable-ccid = true; 29 | reader-port = "Yubico Yubi"; 30 | }; 31 | }; 32 | }; 33 | } 34 | -------------------------------------------------------------------------------- /profiles/workspace/gtk.nix: -------------------------------------------------------------------------------- 1 | { pkgs, config, inputs, ... }: 2 | let 3 | thm = config.themes.colors; 4 | thm' = builtins.mapAttrs (name: value: { hex.rgb = value; }) thm; 5 | in { 6 | programs.gdk-pixbuf.modulePackages = [ pkgs.librsvg ]; 7 | nixpkgs.overlays = [ 8 | (self: super: { 9 | generated-gtk-theme = 10 | pkgs.callPackage "${inputs.rycee}/pkgs/materia-theme" { 11 | configBase16 = { 12 | name = "Generated"; 13 | kind = "dark"; 14 | colors = thm' // { 15 | base01 = thm'.base00; 16 | base02 = thm'.base00; 17 | }; 18 | }; 19 | }; 20 | }) 21 | ]; 22 | programs.dconf.enable = true; 23 | services.dbus.packages = with pkgs; [ dconf ]; 24 | home-manager.users.balsoft = { 25 | gtk = { 26 | enable = true; 27 | iconTheme = { 28 | name = "breeze-dark"; 29 | package = pkgs.kdePackages.breeze-icons; 30 | }; 31 | theme = { 32 | name = "Generated"; 33 | package = pkgs.generated-gtk-theme; 34 | }; 35 | font = { 36 | name = with config.themes.fonts; "${main.family} ${toString main.size}"; 37 | }; 38 | gtk3 = { 39 | bookmarks = [ 40 | "file:///home/balsoft/projects Projects" 41 | "davs://nextcloud.balsoft.ru/remote.php/dav/files/balsoft nextcloud.balsoft.ru" 42 | "sftp://balsoft.ru/home/balsoft balsoft.ru" 43 | ] ++ map (machine: "sftp://${machine}/home/balsoft ${machine}") 44 | (builtins.attrNames inputs.self.nixosConfigurations); 45 | }; 46 | 47 | }; 48 | home.sessionVariables.GTK_THEME = "Generated"; 49 | }; 50 | } 51 | -------------------------------------------------------------------------------- /profiles/workspace/i3blocks/default.nix: -------------------------------------------------------------------------------- 1 | { pkgs, config, lib, ... }: 2 | with lib; with pkgs.my-lib; 3 | let scripts = import ./scripts pkgs config; 4 | in { 5 | secrets.email = { 6 | owner = "balsoft:users"; 7 | services = [ ]; 8 | encrypted = "${config.environment.sessionVariables.PASSWORD_STORE_DIR}/email/balsoft@balsoft.ru.gpg"; 9 | }; 10 | 11 | home-manager.users.balsoft = { 12 | wayland.windowManager.sway.config.bars = [{ 13 | id = "default"; 14 | trayOutput = "none"; 15 | command = "true"; 16 | colors = let 17 | thm = pkgs.my-lib.thmHash config.themes.colors; 18 | default = { 19 | background = thm.base00; 20 | border = thm.base00; 21 | }; 22 | in { 23 | background = thm.base00; 24 | statusline = thm.base05; 25 | separator = thm.base02; 26 | focusedWorkspace = default // { text = thm.base08; }; 27 | activeWorkspace = default // { text = thm.base0B; }; 28 | inactiveWorkspace = default // { text = thm.base05; }; 29 | urgentWorkspace = default // { text = thm.base09; }; 30 | bindingMode = default // { text = thm.base0A; }; 31 | }; 32 | statusCommand = "${pkgs.i3blocks}/bin/i3blocks -o json"; 33 | fonts = { 34 | names = [ "${config.themes.fonts.main.family}" "Material Icons" "Roboto Mono" ]; 35 | style = "Regular"; 36 | size = 12.0; 37 | }; 38 | mode = "hide"; 39 | position = "bottom"; 40 | workspaceNumbers = false; 41 | }]; 42 | xdg.configFile."i3blocks/config".text = let 43 | scr = x: { 44 | name = x; 45 | command = scripts.${x}; 46 | }; 47 | scrint = x: interval: (scr x) // { inherit interval; }; 48 | in '' 49 | interval=60 50 | markup=pango 51 | '' + pkgs.my-lib.genIniOrdered ([ (scr "email") ] 52 | ++ [ (scrint "weather" 600) (scr "nixos") ] 53 | ++ [ (scrint "music" 3) (scrint "sound" 1) ] 54 | ++ [ 55 | (scrint "cpu" 5) 56 | (scrint "freq" 10) 57 | (scr "temperature") 58 | (scrint "free" 10) 59 | (scr "battery") 60 | ] ++ optionals config.deviceSpecific.isLaptop [ 61 | (scrint "brightness" 5) 62 | ] ++ optional (config.deviceSpecific.devInfo ? bigScreen) 63 | (scrint "network" 1) ++ [ 64 | (scrint "bluetooth" 3) 65 | (scrint "connections" 3) 66 | (scr "df") 67 | (scr "date") 68 | (scrint "time" 1) 69 | ]); 70 | systemd.user.services.swaybar = { 71 | Unit = { 72 | Description = "Start default bar"; 73 | X-RestartIfChanged = true; 74 | }; 75 | 76 | Install.WantedBy = [ "sway-session.target" ]; 77 | 78 | Service = { 79 | ExecStart = "${pkgs.sway}/bin/swaybar -d -b default"; 80 | Environment = [ "PATH=${pkgs.bash}/bin" ]; 81 | }; 82 | }; 83 | }; 84 | } 85 | -------------------------------------------------------------------------------- /profiles/workspace/i3blocks/scripts/battery.nix: -------------------------------------------------------------------------------- 1 | { upower, gnugrep, coreutils-full, lib, bash, iconfont, low_threshold ? 10, ... }: '' 2 | #!${bash}/bin/bash 3 | PATH=$PATH:${lib.makeBinPath [ gnugrep upower coreutils-full ]} 4 | readarray -t DEVICES <<< "$(${upower}/bin/upower -e | grep -v "DisplayDevice$")" 5 | 6 | DELIM="" 7 | STATUS=0 8 | 9 | for dev in "''${DEVICES[@]}"; do 10 | INFO="$(${upower}/bin/upower -i "$dev")" 11 | PERCENTAGE="$(echo "$INFO" | grep 'percentage:' | grep -o '[[:digit:]]*')" 12 | if [ -n "$PERCENTAGE" ]; then 13 | TIME="$(echo "$INFO" | grep 'time to' | tr -s ' ' | cut -d' ' -f5-6)" 14 | STATE="$(echo "$INFO" | grep 'state:' | tr -s ' ' | cut -d' ' -f3)" 15 | MODEL="$(echo "$INFO" | grep 'model:' | tr -s ' ' | cut -d' ' -f3)" 16 | if [[ "x$STATE" == "xfully-charged" ]] || [[ "x$STATE" == "xcharging" ]]; then 17 | case $PERCENTAGE in 18 | [0-9]|1[0-9]) icon=;; 19 | [2-3][0-9]) icon=;; 20 | [4-5][0-9]) icon=;; 21 | [6-7][0-9]) icon=;; 22 | [8-9][0-9]) icon=;; 23 | 100) icon=;; 24 | esac 25 | else 26 | if [[ "$PERCENTAGE" -lt ${toString low_threshold} ]]; then 27 | STATUS=33 28 | fi 29 | case $PERCENTAGE in 30 | [0-9]) icon=;; 31 | 1[0-9]) icon=;; 32 | 2[0-9]) icon=;; 33 | 3[0-9]) icon=;; 34 | 4[0-9]) icon=;; 35 | 5[0-9]) icon=;; 36 | 6[0-9]) icon=;; 37 | 7[0-9]) icon=;; 38 | 8[0-9]) icon=;; 39 | 9[0-9]) icon=;; 40 | 100) icon=;; 41 | esac 42 | fi 43 | if [ -n "$DELIM" ]; then 44 | echo -n "| " 45 | else 46 | DELIM="yes" 47 | fi 48 | echo -n "" 49 | if echo "$INFO" | grep 'native-path:' | grep bluez > /dev/null; then 50 | echo -n "" 51 | fi 52 | echo -n "$icon" 53 | if [ -n "$BLOCK_BUTTON" ]; then 54 | echo -n " $MODEL " 55 | echo -n "$PERCENTAGE% " 56 | if [ -n "$TIME" ]; then echo -n "($TIME) "; fi 57 | fi 58 | fi 59 | done 60 | 61 | echo 62 | exit "$STATUS" 63 | '' 64 | -------------------------------------------------------------------------------- /profiles/workspace/i3blocks/scripts/bluetooth.nix: -------------------------------------------------------------------------------- 1 | { iconfont, gnugrep, bash, bluez, pulseaudio, util-linux, python3, ... }: 2 | '' 3 | #!${bash}/bin/bash 4 | if ${util-linux}/bin/rfkill | ${gnugrep}/bin/grep bluetooth > /dev/null; then 5 | if ${util-linux}/bin/rfkill | ${gnugrep}/bin/grep bluetooth | ${gnugrep}/bin/grep blocked > /dev/null; then 6 | if ${bluez}/bin/bluetoothctl info > /dev/null; then 7 | if ${pulseaudio}/bin/pactl list sinks | ${gnugrep}/bin/grep bluez > /dev/null; then 8 | echo -n "" 9 | else 10 | echo -n "" 11 | fi 12 | else 13 | echo -n "" 14 | fi 15 | else 16 | echo -n "" 17 | fi 18 | fi 19 | '' 20 | -------------------------------------------------------------------------------- /profiles/workspace/i3blocks/scripts/brightness.nix: -------------------------------------------------------------------------------- 1 | { iconfont, light, config, ... }: '' 2 | case $BLOCK_BUTTON in 3 | 4) sudo ${light}/bin/light -A 5;; 4 | 5) sudo ${light}/bin/light -U 5;; 5 | esac 6 | LIGHT=`${light}/bin/light | cut -f 1 -d '.'` 7 | if [[ $LIGHT -lt 33 ]] 8 | then 9 | icon= 10 | else 11 | if [[ $LIGHT -lt 66 ]] 12 | then 13 | icon= 14 | else 15 | icon= 16 | fi 17 | fi 18 | ${if config.device == "ASUS-Laptop" then '' 19 | if [[ `cat /sys/devices/platform/asus-nb-wmi/als_enable` -eq 1 ]] 20 | then 21 | icon="" 22 | fi 23 | '' else 24 | ""} 25 | [[ -n $BLOCK_BUTTON ]] && text=" $LIGHT" 26 | echo "$icon$text" 27 | '' 28 | -------------------------------------------------------------------------------- /profiles/workspace/i3blocks/scripts/connections.nix: -------------------------------------------------------------------------------- 1 | { bash, gnugrep, coreutils-full, util-linux, networkmanager, iconfont, config, modemmanager, lib, ... }: '' 2 | #!${bash}/bin/bash 3 | PATH=$PATH:${lib.makeBinPath [ networkmanager coreutils-full gnugrep modemmanager util-linux.bin ]} 4 | export PATH 5 | CONNECTIONS=$(nmcli con show --active | tail +2 | tr -s ' ' | rev | cut -d' ' -f3 | rev) 6 | text="" 7 | for connection in $CONNECTIONS 8 | do 9 | grep wifi <<< $connection > /dev/null && { 10 | # SIGNAL=$(${networkmanager}/bin/nmcli d w | grep '^\*' | tr -s ' ' | cut -d' ' -f7) 11 | # if [[ $SIGNAL -lt 20 ]] 12 | # then 13 | # text+=冷 14 | # elif [[ $SIGNAL -lt 40 ]] 15 | # then 16 | # text+=爛 17 | # elif [[ $SIGNAL -lt 60 ]] 18 | # then 19 | # text+=嵐 20 | # elif [[ $SIGNAL -lt 80 ]] 21 | # then 22 | # text+=襤 23 | # else 24 | # text+=蠟 25 | # fi 26 | text= 27 | } 28 | grep gsm <<< $connection >/dev/null && { 29 | MODEM=$(mmcli -K -L | tail -1 | cut -d: -f2 | tr -d ' ') 30 | STATUS=$(mmcli -K -m $MODEM) 31 | TECH=$(grep "modem.generic.access-technologies.value\[1\]" <<< $STATUS | cut -d: -f2 | tr -d ' ') 32 | 33 | # SIGNAL=$(grep "modem.generic.signal-quality.value" <<< $STATUS | cut -d: -f2 | tr -d ' ') 34 | # if [[ $SIGNAL -lt 20 ]] 35 | # then 36 | # text+="" 37 | # elif [[ $SIGNAL -lt 40 ]] 38 | # then 39 | # text+="" 40 | # elif [[ $SIGNAL -lt 60 ]] 41 | # then 42 | # text+="" 43 | # elif [[ $SIGNAL -lt 80 ]] 44 | # then 45 | # text+="" 46 | # else 47 | # text+="" 48 | # fi 49 | text+= 50 | if [[ $TECH == lte ]] 51 | then 52 | text+="ﰒ" 53 | else 54 | text+="ﰑ" 55 | fi 56 | } 57 | grep ethernet <<< $connection > /dev/null && text+="" 58 | done 59 | code=0 60 | [[ $text == "" ]] && { 61 | text= 62 | code=33 63 | } 64 | echo "$text" 65 | exit $code 66 | '' 67 | -------------------------------------------------------------------------------- /profiles/workspace/i3blocks/scripts/default.nix: -------------------------------------------------------------------------------- 1 | p: c: 2 | with p; 3 | let 4 | iconfont = "Material Icons"; 5 | buildHaskellScript = name: script: 6 | stdenv.mkDerivation { 7 | inherit name; 8 | src = script; 9 | unpackPhase = "true"; 10 | buildInputs = [ghc]; 11 | buildPhase = "ghc -o $out $src"; 12 | installPhase = "true"; 13 | ICONFONT = iconfont; 14 | }; 15 | writeScript = name: script: 16 | writeTextFile { 17 | inherit name; 18 | text = callPackage script { 19 | inherit iconfont; 20 | config = c; 21 | }; 22 | executable = true; 23 | checkPhase = 24 | "${bash}/bin/bash -n $src || ${python3}/bin/python3 -m compileall $src"; 25 | }; 26 | in 27 | builtins.mapAttrs buildHaskellScript { 28 | free = ./free.hs; 29 | temperature = ./temperature.hs; 30 | network = ./network.hs; 31 | } // builtins.mapAttrs writeScript { 32 | battery = ./battery.nix; 33 | brightness = ./brightness.nix; 34 | email = ./email.nix; 35 | # emacs = ./emacs.nix; 36 | bluetooth = ./bluetooth.nix; 37 | connections = ./connections.nix; 38 | weather = ./weather.nix; 39 | sound = ./sound.nix; 40 | music = ./music.nix; 41 | cpu = {...}: ''${procps}/bin/top -b -n1 -p 1 | ${gnugrep}/bin/fgrep "Cpu(s)" | ${coreutils}/bin/tail -1 | ${gawk}/bin/awk -F'id,' -v prefix="$prefix" '{ split($1, vs, ","); v=vs[length(vs)]; sub("%", "", v); printf "󰍛%s%.1f%%\n", prefix, 100 - v }' ''; 42 | freq = {...}: ''echo $(${pkgs.bc}/bin/bc -l <<< "scale=2; `${coreutils}/bin/cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq|${coreutils}/bin/sort|${coreutils}/bin/tail -1`/1000000") GHz''; 43 | df = {...}: ''echo '' `${coreutils}/bin/df / | ${coreutils}/bin/tail -1 | ${gnugrep}/bin/grep -o '..%'`''; 44 | date = {...}: "${pkgs.coreutils}/bin/date +' %a %y-%m-%d'"; 45 | time = {...}: "${pkgs.coreutils}/bin/date +' %T'"; 46 | nixos = {...}: "echo -n ''; ${coreutils}/bin/cat /run/current-system/nixos-version | ${coreutils-full}/bin/cut -d. -f3"; 47 | #temperature = ./temperature.nix; 48 | #free = ./free.nix; 49 | } 50 | -------------------------------------------------------------------------------- /profiles/workspace/i3blocks/scripts/emacs.nix: -------------------------------------------------------------------------------- 1 | { config, ... }: 2 | let ec = "${config.home-manager.users.balsoft.programs.emacs.finalPackage}/bin/emacsclient"; 3 | in 4 | '' 5 | [[ $BLOCK_BUTTON -eq 2 ]] && ${ec} --eval "(org-clock-out)" > /dev/null 6 | ${ec} --eval "org-mode-line-string" | head -1 | cut -d\" -f 2 7 | '' 8 | -------------------------------------------------------------------------------- /profiles/workspace/i3blocks/scripts/email.nix: -------------------------------------------------------------------------------- 1 | { python3, iconfont, config, ... }: '' 2 | #!${python3}/bin/python3 3 | import imaplib 4 | obj = imaplib.IMAP4_SSL('balsoft.ru', 993) 5 | password = open("${config.secrets.email.decrypted}").read()[:-1:] 6 | obj.login("balsoft@balsoft.ru", password) 7 | obj.select() 8 | l = len(obj.search(None, 'unseen')[1][0].split()) 9 | if l == 0: 10 | print('') 11 | else: 12 | print(' %s' % str(l)) 13 | exit(33) 14 | '' 15 | -------------------------------------------------------------------------------- /profiles/workspace/i3blocks/scripts/free.hs: -------------------------------------------------------------------------------- 1 | import System.Exit 2 | 3 | main :: IO () 4 | main = do 5 | freeMemory <- read 6 | <$> (!!1) <$> words 7 | <$> (!!2) <$> lines 8 | <$> readFile "/proc/meminfo" 9 | putStrLn $ (take 5 $ show $ freeMemory / 1000000) ++ "GB" 10 | exitWith $ if freeMemory > 500000 then ExitSuccess else ExitFailure 33 11 | -------------------------------------------------------------------------------- /profiles/workspace/i3blocks/scripts/free.nix: -------------------------------------------------------------------------------- 1 | { bc, ... }: '' 2 | echo `free | tail -2 | head -1 | awk '{print "scale=3; "$7"/1000000"}' | ${ 3 | bc 4 | }/bin/bc -l`GB 5 | '' 6 | -------------------------------------------------------------------------------- /profiles/workspace/i3blocks/scripts/hydra-status.nix: -------------------------------------------------------------------------------- 1 | { bash, curl, libnotify, sox, iconfont, ... }: 2 | '' 3 | #!${bash}/bin/bash 4 | STATUS=$(${curl}/bin/curl -sw "%{http_code}" https://hydra.typeable.io/ping) 5 | if [ $STATUS -eq 200 ] 6 | then 7 | echo '🐍' 8 | exit 0 9 | else 10 | msg="HYDRA DOWN" 11 | echo $msg 12 | exit 33 13 | fi 14 | '' 15 | -------------------------------------------------------------------------------- /profiles/workspace/i3blocks/scripts/music.nix: -------------------------------------------------------------------------------- 1 | { python3, playerctl, iconfont, ...}: '' 2 | #!${python3}/bin/python 3 | from subprocess import getoutput, call 4 | from os import environ 5 | status = getoutput("${playerctl}/bin/playerctl status") 6 | if "BLOCK_BUTTON" in environ: 7 | BLOCK_BUTTON = environ["BLOCK_BUTTON"] 8 | if BLOCK_BUTTON == "1": call(["${playerctl}/bin/playerctl", "play-pause"]) 9 | if BLOCK_BUTTON == "2": call(["${playerctl}/bin/playerctl", "stop"]) 10 | if BLOCK_BUTTON == "3": call(["${playerctl}/bin/playerctl", "next"]) 11 | if status == "Paused" or status == "Playing": 12 | text = getoutput("${playerctl}/bin/playerctl metadata title")[:20:] 13 | icon = "" 14 | else: 15 | text = "" 16 | icon = "" 17 | print("%s %s" % (icon, text.replace('&', '&'))) 18 | '' 19 | -------------------------------------------------------------------------------- /profiles/workspace/i3blocks/scripts/network.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE BangPatterns, TemplateHaskell #-} 2 | 3 | import Control.Concurrent (threadDelay) 4 | import Control.Monad (mapM, join) 5 | import System.Directory (listDirectory) 6 | import Data.Bool (bool) 7 | import Language.Haskell.TH.Syntax (liftString, runIO) 8 | import System.Environment (getEnv) 9 | import Control.Monad.IO.Class (liftIO) 10 | import Text.Printf (printf) 11 | 12 | path :: String 13 | path = "/sys/class/net/" 14 | 15 | data Statistics = Statistics !Float !Float 16 | 17 | instance Semigroup Statistics where 18 | Statistics a b <> Statistics c d = Statistics (a + c) (b + d) 19 | 20 | instance Monoid Statistics where 21 | mempty = Statistics 0 0 22 | 23 | icon :: String -> String 24 | icon i = "" ++ i ++ "" 25 | 26 | readInterface :: FilePath -> IO Statistics 27 | readInterface interface = do 28 | rx <- read <$> readFile (path ++ interface ++ "/statistics/rx_bytes") 29 | tx <- read <$> readFile (path ++ interface ++ "/statistics/tx_bytes") 30 | return $ Statistics rx tx 31 | 32 | readInterfaces :: [FilePath] -> IO Statistics 33 | readInterfaces interfaces = mconcat <$> (mapM readInterface interfaces) 34 | 35 | renderSpeed :: Float -> String 36 | renderSpeed bits 37 | | bits < 1e6 = (show . round) (bits / 1e3) ++ "kbps" 38 | | otherwise = printf "%0.*f" (1 :: Int) (bits / 1e6) ++ "Mbps" 39 | 40 | main :: IO () 41 | main = do 42 | interfaces <- listDirectory path 43 | Statistics rx tx <- readInterfaces interfaces 44 | threadDelay 1000000 45 | Statistics rx' tx' <- readInterfaces interfaces 46 | putStrLn $ (icon "\58052") ++ renderSpeed (rx' - rx) 47 | ++ (icon "\58054") ++ renderSpeed (tx' - tx) 48 | -------------------------------------------------------------------------------- /profiles/workspace/i3blocks/scripts/sound.nix: -------------------------------------------------------------------------------- 1 | { pamixer, lxqt, iconfont, config, lib, ... }: '' 2 | case $BLOCK_BUTTON in 3 | 2) ${pamixer}/bin/pamixer -t;; 4 | 4) ${pamixer}/bin/pamixer -i 5;; 5 | 5) ${pamixer}/bin/pamixer -d 5;; 6 | esac 7 | code=0 8 | if [[ `${pamixer}/bin/pamixer --get-mute` = "true" ]] 9 | then 10 | volume="" 11 | end="" 12 | icon="婢" 13 | else 14 | volume=`${pamixer}/bin/pamixer --get-volume` 15 | end="%" 16 | if [[ $volume -lt 33 ]] 17 | then 18 | icon="奄" 19 | else 20 | if [[ $volume -lt 66 ]] 21 | then 22 | icon="奔" 23 | else 24 | icon="墳" 25 | code=33 26 | fi 27 | fi 28 | fi 29 | ${lib.optionalString (! config.deviceSpecific.bigScreen) "[[ -n $BLOCK_BUTTON ]] &&"} text=" $volume$end" 30 | echo "$icon$text" 31 | exit $code 32 | '' 33 | -------------------------------------------------------------------------------- /profiles/workspace/i3blocks/scripts/temperature.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE TemplateHaskell, OverloadedStrings #-} 2 | 3 | import Prelude hiding (readFile) 4 | import System.Directory 5 | import System.FilePath 6 | import Control.Monad (forM, join) 7 | import System.Posix.Files 8 | import Data.List (isPrefixOf, isInfixOf) 9 | import System.Exit 10 | import Language.Haskell.TH.Syntax (liftString, runIO) 11 | import System.Environment (getEnv) 12 | import Control.Monad.IO.Class (liftIO) 13 | import Data.Maybe (catMaybes) 14 | import Control.Exception 15 | import Data.Text (unpack) 16 | import Data.Text.IO (readFile) 17 | 18 | -- | Traverse from 'top' directory and return all the files by 19 | -- filtering with 'include' predicate. 20 | traverseDir :: FilePath -> (FilePath -> Bool) -> IO [FilePath] 21 | traverseDir top include = do 22 | ds <- getDirectoryContents top 23 | paths <- forM (filter include ds) $ \d -> do 24 | let path = top d 25 | s <- getFileStatus path 26 | if isDirectory s 27 | then traverseDir path include 28 | else return [path] 29 | return $ concat paths 30 | 31 | 32 | 33 | -- | Get temperatures from hardware sensors in 34 | getTemps :: IO [Int] 35 | getTemps = do 36 | hwmons <- traverseDir "/sys/class/hwmon" 37 | ( 38 | \name 39 | -> ("hwmon" `isPrefixOf` name) 40 | || ("temp" `isInfixOf` name) && ("input" `isInfixOf` name) 41 | ) 42 | fmap (round . (/1000) . read . unpack) <$> traverse (handle (\e -> do pure (e :: IOException); pure "0") . readFile) hwmons 43 | 44 | -- | Get a symbol corresponding to the temperature 45 | getSymbol :: Integral n => n -> String 46 | getSymbol t 47 | | t < 50 = "\57868" --  48 | | t < 80 = "\57866" --  49 | | otherwise = "\57867" --  50 | 51 | icon :: String -> String 52 | icon s = "" ++ s ++ "" 53 | 54 | main :: IO () 55 | main = do 56 | maxTemp <- maximum <$> getTemps 57 | putStrLn $ (getSymbol <> show) maxTemp <> "°" 58 | exitWith $ if maxTemp < 80 then ExitSuccess else ExitFailure 33 59 | -------------------------------------------------------------------------------- /profiles/workspace/i3blocks/scripts/temperature.nix: -------------------------------------------------------------------------------- 1 | { ... }: 2 | '' 3 | temp=$((`cat /sys/class/thermal/thermal_zone*/temp | sort | tail -1`/1000)) 4 | echo $temp ° 5 | [[ $temp -gt 80 ]] && exit 33 6 | '' 7 | -------------------------------------------------------------------------------- /profiles/workspace/i3blocks/scripts/weather.nix: -------------------------------------------------------------------------------- 1 | { bash, config, curl, iconfont, ... }: '' 2 | #!${bash}/bin/bash 3 | WTTR=$(${curl}/bin/curl wttr.in/?format=1) 4 | echo "$WTTR" 5 | '' 6 | -------------------------------------------------------------------------------- /profiles/workspace/kanshi.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, lib, ... }: { 2 | home-manager.users.balsoft = { 3 | xsession.windowManager.i3.config.startup = [{ 4 | command = "${pkgs.kanshi}/bin/kanshi"; 5 | notification = false; 6 | always = true; 7 | }]; 8 | xdg.configFile."kanshi/config".text = '' 9 | { 10 | output "Samsung Electric Company C27JG5x HTOM901267" position 0,1025 11 | output "Dell Inc. DELL E176FP MC0435BH2ATP" position 1400,0 12 | } 13 | { 14 | output "Samsung Electric Company C27JG5x HTOM901267" position 0,0 15 | } 16 | ''; 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /profiles/workspace/kde/kdeconnect.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: { 2 | home-manager.users.balsoft = { 3 | services.kdeconnect.enable = true; 4 | systemd.user.services.kdeconnect = { 5 | Service.Environment = lib.mkForce [ 6 | "PATH=/etc/profiles/per-user/balsoft/bin" 7 | ]; 8 | }; 9 | }; 10 | persist.state.directories = [ "/home/balsoft/.config/kdeconnect" ]; 11 | } 12 | -------------------------------------------------------------------------------- /profiles/workspace/kde/plasma-mobile.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, lib, ... }: { 2 | 3 | environment.sessionVariables = { 4 | _JAVA_AWT_WM_NONREPARENTING = "1"; 5 | XDG_SESSION_TYPE = "wayland"; 6 | QT_QPA_PLATFORM = "wayland"; 7 | QT_WAYLAND_DISABLE_WINDOWDECORATION = "1"; 8 | }; 9 | 10 | nixpkgs.overlays = [ 11 | (final: prev: { 12 | libsForQt5 = prev.libsForQt5 // { 13 | kwallet = null; 14 | kwallet-pam = null; 15 | kwalletmanager = null; 16 | }; 17 | }) 18 | ]; 19 | 20 | services.xserver = { 21 | enable = true; 22 | desktopManager.plasma5 = { 23 | mobile.enable = true; 24 | runUsingSystemd = false; 25 | }; 26 | displayManager = { 27 | autoLogin = { 28 | enable = true; 29 | user = "balsoft"; 30 | }; 31 | defaultSession = "plasma-mobile"; 32 | lightdm = { 33 | enable = true; 34 | extraSeatDefaults = '' 35 | session-cleanup-script=${pkgs.procps}/bin/pkill -P1 -fx ${pkgs.lightdm}/sbin/lightdm 36 | ''; 37 | }; 38 | }; 39 | libinput.enable = true; 40 | }; 41 | 42 | programs.feedbackd.enable = true; 43 | 44 | services.upower.enable = true; 45 | 46 | services.geoclue2.enable = true; 47 | 48 | home-manager.users.balsoft = { 49 | home.activation.removeGtkRc = { 50 | data = "rm -f $HOME/.gtkrc-2.0"; 51 | before = [ "checkLinkTargets" ]; 52 | after = [ ]; 53 | }; 54 | 55 | xdg.configFile."autostart/org_kde_powerdevil.desktop".text = '' 56 | [Desktop Entry] 57 | DBusActivatable=true 58 | Exec=${pkgs.kdePackages.powerdevil}/libexec/org_kde_powerdevil 59 | Name=org_kde_powerdevil 60 | Type=Application 61 | ''; 62 | xdg.configFile."plasmarc".text = 63 | lib.generators.toGitINI { Theme.name = "generated"; }; 64 | xdg.configFile."plasmamobilerc".text = lib.generators.toGitINI { 65 | General = { 66 | actionDrawerTopLeftMode = "1"; 67 | actionDrawerTopRightMode = "0"; 68 | vibrationDuration = "100"; 69 | vibrationIntensity = "0.5"; 70 | vibrationsEnabled = "true"; 71 | navigationPanelEnabled = "false"; 72 | taskSwitcherPreviewsEnabled = "false"; 73 | animationsEnabled = "false"; 74 | }; 75 | QuickSettings = { 76 | disabledQuickSettings = builtins.concatStringsSep "," [ ]; 77 | enabledQuickSettings = builtins.concatStringsSep "," [ 78 | "org.kde.plasma.quicksetting.wifi" 79 | "org.kde.plasma.quicksetting.mobiledata" 80 | "org.kde.plasma.quicksetting.bluetooth" 81 | "org.kde.plasma.quicksetting.flashlight" 82 | "org.kde.plasma.quicksetting.screenrotation" 83 | "org.kde.plasma.quicksetting.settingsapp" 84 | "org.kde.plasma.quicksetting.airplanemode" 85 | "org.kde.plasma.quicksetting.audio" 86 | "org.kde.plasma.quicksetting.battery" 87 | "org.kde.plasma.quicksetting.location" 88 | "org.kde.plasma.quicksetting.nightcolor" 89 | "org.kde.plasma.quicksetting.screenshot" 90 | "org.kde.plasma.quicksetting.powermenu" 91 | "org.kde.plasma.quicksetting.donotdisturb" 92 | "org.kde.plasma.quicksetting.caffeine" 93 | "org.kde.plasma.quicksetting.keyboardtoggle" 94 | "org.kde.plasma.quicksetting.record" 95 | ]; 96 | }; 97 | }; 98 | xdg.configFile."plasmaparc".text = 99 | lib.generators.toGitINI { General.VolumeStep = 2; }; 100 | }; 101 | } 102 | -------------------------------------------------------------------------------- /profiles/workspace/kde/qt.nix: -------------------------------------------------------------------------------- 1 | { pkgs, lib, config, ... }: 2 | with pkgs.my-lib; 3 | let 4 | colorTheme = with (thmDec config.themes.colors); { 5 | "Colors:Button" = { 6 | BackgroundAlternate = base01; 7 | BackgroundNormal = base01; 8 | DecorationFocus = base0D; 9 | DecorationHover = base0D; 10 | ForegroundActive = base0D; 11 | ForegroundInactive = base01; 12 | ForegroundLink = base0D; 13 | ForegroundNegative = base08; 14 | ForegroundNeutral = base09; 15 | ForegroundNormal = base05; 16 | ForegroundPositive = base0B; 17 | ForegroundVisited = base03; 18 | }; 19 | "Colors:Complementary" = { 20 | BackgroundAlternate = base01; 21 | BackgroundNormal = base03; 22 | DecorationFocus = base0D; 23 | DecorationHover = base0D; 24 | ForegroundActive = base0D; 25 | ForegroundInactive = base01; 26 | ForegroundLink = base0D; 27 | ForegroundNegative = base08; 28 | ForegroundNeutral = base0A; 29 | ForegroundNormal = base05; 30 | ForegroundPositive = base0B; 31 | ForegroundVisited = base02; 32 | }; 33 | "Colors:Selection" = { 34 | BackgroundAlternate = base0D; 35 | BackgroundNormal = base0D; 36 | DecorationFocus = base0D; 37 | DecorationHover = base0D; 38 | ForegroundActive = base05; 39 | ForegroundInactive = base05; 40 | ForegroundLink = base0D; 41 | ForegroundNegative = base08; 42 | ForegroundNeutral = base09; 43 | ForegroundNormal = base05; 44 | ForegroundPositive = base0B; 45 | ForegroundVisited = base02; 46 | }; 47 | "Colors:Tooltip" = { 48 | BackgroundAlternate = base01; 49 | BackgroundNormal = base00; 50 | DecorationFocus = base0D; 51 | DecorationHover = base0D; 52 | ForegroundActive = base0D; 53 | ForegroundInactive = base01; 54 | ForegroundLink = base0D; 55 | ForegroundNegative = base08; 56 | ForegroundNeutral = base09; 57 | ForegroundNormal = base05; 58 | ForegroundPositive = base0B; 59 | ForegroundVisited = base03; 60 | }; 61 | "Colors:View" = { 62 | BackgroundAlternate = base01; 63 | BackgroundNormal = base00; 64 | DecorationFocus = base0D; 65 | DecorationHover = base0D; 66 | ForegroundActive = base0D; 67 | ForegroundInactive = base01; 68 | ForegroundLink = base0D; 69 | ForegroundNegative = base08; 70 | ForegroundNeutral = base09; 71 | ForegroundNormal = base05; 72 | ForegroundPositive = base0B; 73 | ForegroundVisited = base03; 74 | }; 75 | "Colors:Window" = { 76 | BackgroundAlternate = base01; 77 | BackgroundNormal = base00; 78 | DecorationFocus = base0D; 79 | DecorationHover = base0D; 80 | ForegroundActive = base0D; 81 | ForegroundInactive = base01; 82 | ForegroundLink = base0D; 83 | ForegroundNegative = base08; 84 | ForegroundNeutral = base09; 85 | ForegroundNormal = base05; 86 | ForegroundPositive = base0B; 87 | ForegroundVisited = base03; 88 | }; 89 | General = { 90 | ColorScheme = "Generated"; 91 | Name = "Generated"; 92 | shadeSortColumn = true; 93 | }; 94 | KDE.contrast = 4; 95 | WM = { 96 | activeBackground = base00; 97 | activeBlend = base06; 98 | activeForeground = base05; 99 | inactiveBackground = base01; 100 | inactiveBlend = base02; 101 | inactiveForeground = base04; 102 | }; 103 | }; 104 | misc = with config.themes; { 105 | Icons.Theme = "breeze-dark"; 106 | 107 | KDE = { 108 | DoubleClickInterval = 400; 109 | ShowDeleteCommand = true; 110 | SingleClick = false; 111 | StartDragDist = 4; 112 | StartDragTime = 500; 113 | WheelScrollLines = 3; 114 | widgetStyle = "Breeze"; 115 | }; 116 | General = { 117 | TerminalApplication = config.defaultApplications.term.cmd; 118 | fixed = 119 | "${fonts.mono.family},${toString fonts.mono.size},-1,5,50,0,0,0,0,0"; 120 | font = 121 | "${fonts.main.family},${toString fonts.main.size},-1,5,50,0,0,0,0,0"; 122 | menuFont = 123 | "${fonts.main.family},${toString fonts.main.size},-1,5,50,0,0,0,0,0"; 124 | smallestReadableFont = "${fonts.main.family},${ 125 | toString fonts.main.size 126 | },-1,5,57,0,0,0,0,0,Medium"; 127 | toolBarFont = 128 | "${fonts.main.family},${toString fonts.main.size},-1,5,50,0,0,0,0,0"; 129 | }; 130 | }; 131 | effects = with (thmDec config.themes.colors); { 132 | "ColorEffects:Disabled" = { 133 | Color = base02; 134 | ColorAmount = "0"; 135 | ColorEffect = "0"; 136 | ContrastAmount = "0.65"; 137 | ContrastEffect = "1"; 138 | IntensityAmount = "0.1"; 139 | IntensityEffect = "2"; 140 | }; 141 | 142 | "ColorEffects:Inactive" = { 143 | ChangeSelectionColor = "true"; 144 | Color = base03; 145 | ColorAmount = "0.025"; 146 | ColorEffect = "2"; 147 | ContrastAmount = "0.1"; 148 | ContrastEffect = "2"; 149 | Enable = "false"; 150 | IntensityAmount = "0"; 151 | IntensityEffect = "0"; 152 | }; 153 | }; 154 | desktopThemeColors = pkgs.writeText "generated-plasma-theme-colors" 155 | (lib.generators.toGitINI 156 | (builtins.foldl' lib.recursiveUpdate { } [ colorTheme effects ])); 157 | desktopThemeRc = pkgs.writeText "generated-plasma-theme-rc" 158 | (lib.generators.toGitINI { 159 | Wallpaper = { 160 | defaultWallpaperTheme = "Next"; 161 | defaultFileSuffix = ".png"; 162 | defaultWidth = "1920"; 163 | defaultHeight = "1080"; 164 | }; 165 | ContrastEffect = { 166 | enabled = "true"; 167 | contrast = "0.17"; 168 | intensity = "1.25"; 169 | saturation = "9"; 170 | }; 171 | AdaptiveTransparency.enabled = "true"; 172 | }); 173 | desktopTheme = pkgs.linkFarm "generated-plasma-theme" [ 174 | { 175 | name = "share/plasma/desktoptheme/generated/plasmarc"; 176 | path = desktopThemeRc; 177 | } 178 | { 179 | name = "share/plasma/desktoptheme/generated/colors"; 180 | path = desktopThemeColors; 181 | } 182 | ]; 183 | in { 184 | environment.systemPackages = [ desktopTheme ]; 185 | 186 | xdg.portal.enable = true; 187 | xdg.portal.extraPortals = [ pkgs.kdePackages.xdg-desktop-portal-kde ]; 188 | services.dbus.packages = [ pkgs.systemd pkgs.kdePackages.breeze-icons ]; 189 | services.udev.packages = [ pkgs.libmtp pkgs.media-player-info ]; 190 | 191 | qt.enable = false; 192 | 193 | environment.sessionVariables = { 194 | QT_XFT = "true"; 195 | QT_SELECT = "5"; 196 | KDE_SESSION_VERSION = "5"; 197 | QT_SCALE_FACTOR = "1"; 198 | QT_AUTO_SCREEN_SCALE_FACTOR = "0"; 199 | QT_QPA_PLATFORMTHEME = "kde"; 200 | KDEDIRS = 201 | "/run/current-system/sw:/run/current-system/sw/share/kservices5:/run/current-system/sw/share/kservicetypes5:/run/current-system/sw/share/kxmlgui5"; 202 | }; 203 | 204 | defaultApplications = { 205 | # fm = { 206 | # cmd = "${pkgs.kdePackages.dolphin}/bin/dolphin"; 207 | # desktop = "org.kde.dolphin"; 208 | # }; 209 | # archive = { 210 | # cmd = "${pkgs.kdePackages.ark}/bin/ark"; 211 | # desktop = "org.kde.ark"; 212 | # }; 213 | }; 214 | 215 | home-manager.users.balsoft = { 216 | # home.packages = [ pkgs.kdePackages.ark pkgs.kdePackages.dolphin ]; 217 | 218 | xdg.configFile."kdeglobals".text = pkgs.my-lib.genIni 219 | (builtins.foldl' lib.recursiveUpdate { } [ colorTheme effects misc ]); 220 | }; 221 | } 222 | -------------------------------------------------------------------------------- /profiles/workspace/light.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, lib, ... }: { 2 | programs.light.enable = config.deviceSpecific.isLaptop; 3 | services.actkbd = { 4 | enable = config.deviceSpecific.isLaptop; 5 | bindings = map (x: 6 | x // { 7 | events = [ "key" ]; 8 | attributes = [ "exec" ]; 9 | }) [ 10 | { 11 | keys = [ 225 ]; 12 | command = "${pkgs.light}/bin/light -A 10"; 13 | } 14 | { 15 | keys = [ 224 ]; 16 | command = "${pkgs.light}/bin/light -U 10"; 17 | } 18 | { 19 | keys = [ 431 ]; 20 | command = (toString (pkgs.writeTextFile { 21 | name = "dark-script"; 22 | text = '' 23 | if [[ `${pkgs.light}/bin/light` -eq 0 ]] 24 | then 25 | ${pkgs.light}/bin/light -I 26 | else 27 | ${pkgs.light}/bin/light -O 28 | ${pkgs.light}/bin/light -S 0 29 | fi''; 30 | executable = true; 31 | })); 32 | } 33 | ]; 34 | }; 35 | } 36 | -------------------------------------------------------------------------------- /profiles/workspace/locale/default.nix: -------------------------------------------------------------------------------- 1 | { pkgs, config, lib, ... }: { 2 | environment.sessionVariables = { 3 | XKB_DEFAULT_LAYOUT = "us,ru"; 4 | XKB_DEFAULT_OPTIONS = 5 | "grp:lctrl_toggle,grp_led:caps,ctrl:nocaps,compose:ralt"; 6 | LANG = lib.mkForce "en_GB.UTF-8"; 7 | XCOMPOSEFILE = "${config.home-manager.users.balsoft.xdg.configHome}/XCompose"; 8 | }; 9 | 10 | i18n.defaultLocale = "en_GB.UTF-8"; 11 | 12 | time.timeZone = "Asia/Tbilisi"; 13 | home-manager.users.balsoft = { 14 | home.file.".XCompose".source = ./compose; 15 | xdg.configFile."gtk-3.0/Compose".source = ./compose; 16 | xdg.configFile."XCompose".source = ./compose; 17 | home.language = let 18 | en = "en_GB.UTF-8"; 19 | ru = "ru_RU.UTF-8"; 20 | in { 21 | address = ru; 22 | monetary = ru; 23 | paper = ru; 24 | time = en; 25 | base = en; 26 | }; 27 | }; 28 | } 29 | -------------------------------------------------------------------------------- /profiles/workspace/mako.nix: -------------------------------------------------------------------------------- 1 | { pkgs, config, ... }: 2 | { 3 | home-manager.users.balsoft = { 4 | systemd.user.services.mako = { 5 | Service = { 6 | ExecStart = "${pkgs.mako}/bin/mako"; 7 | Environment = [ 8 | "PATH=${ 9 | pkgs.lib.makeBinPath [ 10 | pkgs.bash 11 | pkgs.mpv 12 | ] 13 | }" 14 | ]; 15 | }; 16 | Install = { 17 | After = [ "sway-session.target" ]; 18 | WantedBy = [ "sway-session.target" ]; 19 | }; 20 | }; 21 | services.mako = with (pkgs.my-lib.thmHash config.themes.colors); { 22 | enable = true; 23 | settings = 24 | let 25 | play = sound: "mpv ${pkgs.sound-theme-freedesktop}/share/sounds/freedesktop/stereo/${sound}.oga"; 26 | in 27 | { 28 | "urgency=high".border-color = "${base09}AA"; 29 | "urgency=critical" = { 30 | border-color = "${base09}AA"; 31 | on-notify = "exec ${play "message"}"; 32 | }; 33 | "app-name=yubikey-touch-detector".on-notify = "exec ${play "service-login"}"; 34 | "app-name=command_complete summary~=\"✘.*\"".on-notify = "exec ${play "dialog-warning"}"; 35 | "app-name=command_complete summary~=\"✓.*\"".on-notify = "exec ${play "bell"}"; 36 | "category=osd".on-notify = "none"; 37 | "mode=do-not-disturb".invisible = 1; 38 | "mode=do-not-disturb summary=\"Do not disturb: on\"".invisible = 0; 39 | "mode=concentrate".invisible = 1; 40 | "mode=concentrate urgency=critical".invisible = 0; 41 | "mode=concentrate summary=\"Concentrate mode: on\"".invisible = 0; 42 | layer = "overlay"; 43 | font = with config.themes.fonts; "${main.family} ${toString main.size}"; 44 | width = 500; 45 | height = 160; 46 | default-timeout = 10000; 47 | max-visible = 10; 48 | background-color = "${base00}AA"; 49 | text-color = base05; 50 | border-color = "${base0D}AA"; 51 | progress-color = "over ${base0B}"; 52 | icon-path = "${pkgs.kdePackages.breeze-icons}/share/icons/breeze-dark"; 53 | max-icon-size = 24; 54 | }; 55 | }; 56 | }; 57 | } 58 | -------------------------------------------------------------------------------- /profiles/workspace/misc.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | lib, 4 | config, 5 | inputs, 6 | ... 7 | }: 8 | { 9 | 10 | environment.sessionVariables = 11 | builtins.mapAttrs (_: toString) ( 12 | lib.removeAttrs config.home-manager.users.balsoft.home.sessionVariables [ "GIO_EXTRA_MODULES" ] 13 | ) 14 | // rec { 15 | LESS = "MR"; 16 | LESSCHARSET = "utf-8"; 17 | LESSHISTFILE = "~/.local/share/lesshist"; 18 | 19 | CARGO_HOME = "${config.home-manager.users.balsoft.xdg.dataHome}/cargo"; 20 | 21 | SYSTEMD_LESS = LESS; 22 | }; 23 | 24 | home-manager.users.balsoft = { 25 | news.display = "silent"; 26 | 27 | systemd.user.startServices = true; 28 | 29 | home.stateVersion = lib.mkDefault "20.09"; 30 | home.preferXdgDirectories = true; 31 | }; 32 | 33 | home-manager.useGlobalPkgs = true; 34 | 35 | persist.cache.directories = [ 36 | "/home/balsoft/.cache" 37 | "/home/balsoft/.local/share/cargo" 38 | "/var/cache" 39 | ]; 40 | 41 | persist.state.directories = [ 42 | "/var/lib/nixos" 43 | "/var/lib/systemd" 44 | ]; 45 | 46 | system.stateVersion = lib.mkDefault "18.03"; 47 | 48 | systemd.services.systemd-timesyncd.wantedBy = [ "multi-user.target" ]; 49 | 50 | systemd.timers.systemd-timesyncd = { 51 | timerConfig.OnCalendar = "hourly"; 52 | }; 53 | 54 | services.avahi.enable = true; 55 | 56 | environment.systemPackages = [ pkgs.ntfs3g ]; 57 | } 58 | -------------------------------------------------------------------------------- /profiles/workspace/mopidy.nix: -------------------------------------------------------------------------------- 1 | { pkgs, config, lib, ... }: { 2 | secrets.mopidy_ytmusic_auth = { 3 | owner = "mopidy:mopidy"; 4 | services = [ "mopidy" ]; 5 | }; 6 | 7 | services.mopidy = { 8 | enable = true; 9 | extensionPackages = with pkgs; [ mopidy-mpd /*mopidy-ytmusic*/ ]; 10 | configuration = '' 11 | [ytmusic] 12 | enabled=true 13 | auth_json=${config.secrets.mopidy_ytmusic_auth.decrypted} 14 | [mpd] 15 | hostname = 0.0.0.0 16 | port = 6600 17 | [audio] 18 | output = autoaudiosink 19 | ''; 20 | }; 21 | 22 | systemd.services.mopidy = { after = [ "network-online.target" ]; environment.https_proxy = "socks5://localhost:5555"; }; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /profiles/workspace/openvpn.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, lib, ... }: let password-store = config.secretsConfig.password-store; in { 2 | secrets.tawasal_eu1 = { 3 | encrypted = "${password-store}/openvpn/tawasal_eu1.gpg"; 4 | services = [ "openvpn-tawasal-eu1.service" ]; 5 | }; 6 | secrets.tawasal_eu2 = { 7 | encrypted = "${password-store}/openvpn/tawasal_eu2.gpg"; 8 | services = [ "openvpn-tawasal-eu2.service" ]; 9 | }; 10 | 11 | services.openvpn.servers = { 12 | tawasal-eu1.config = "config ${config.secrets.tawasal_eu1.decrypted}"; 13 | tawasal-eu2.config = "config ${config.secrets.tawasal_eu2.decrypted}"; 14 | }; 15 | 16 | systemd.services.openvpn-tawasal-eu1.wantedBy = lib.mkForce []; 17 | systemd.services.openvpn-tawasal-eu2.wantedBy = lib.mkForce []; 18 | } 19 | -------------------------------------------------------------------------------- /profiles/workspace/print-scan/default.nix: -------------------------------------------------------------------------------- 1 | { pkgs, config, inputs, ... }: 2 | let 3 | brother_printer = pkgs.linkFarm "Brother_HL-3170CDW_series" [{ 4 | name = "share/cups/model/hl3170cdw.ppd"; 5 | path = "${inputs.brother-hl-3170cdw-driver}/Brother_HL-3170CDW_series.ppd"; 6 | }]; 7 | in { 8 | # services.printing = { 9 | # enable = true; 10 | # drivers = [ 11 | # brother_printer 12 | # ]; 13 | # }; 14 | 15 | # hardware.printers = { 16 | # ensureDefaultPrinter = "Brother_HL-3170CDW_series"; 17 | # ensurePrinters = [{ 18 | # name = "Brother_HL-3170CDW_series"; 19 | # deviceUri = "usb://Brother/HL-3170CDW%20series?serial=E71798K6J706416"; 20 | # model = "hl3170cdw.ppd"; 21 | # }]; 22 | # }; 23 | 24 | # programs.system-config-printer.enable = true; 25 | 26 | hardware.sane.extraBackends = [ pkgs.epkowa pkgs.utsushi ]; 27 | services.udev.packages = [ pkgs.epkowa pkgs.utsushi ]; 28 | hardware.sane.enable = true; 29 | services.saned.enable = true; 30 | 31 | environment.systemPackages = [ pkgs.simple-scan ]; 32 | } 33 | -------------------------------------------------------------------------------- /profiles/workspace/rclone.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, lib, ... }: { 2 | secrets-envsubst.rclone = { 3 | owner = "balsoft:users"; 4 | secrets = [ "nextcloud" ]; 5 | services = [ "home-manager-balsoft" ]; 6 | template = lib.generators.toINI {} { 7 | nextcloud = { 8 | type = "webdav"; 9 | url = "https://nextcloud.balsoft.ru/remote.php/dav/files/balsoft"; 10 | vendor = "nextcloud"; 11 | user = "balsoft"; 12 | pass = "$nextcloud"; 13 | }; 14 | }; 15 | }; 16 | 17 | home-manager.users.balsoft.home = { 18 | activation.rclone = '' 19 | mkdir -p $XDG_CONFIG_HOME/rclone 20 | ln -sf ${config.secrets-envsubst.rclone.substituted} $XDG_CONFIG_HOME/rclone/rclone.conf 21 | ''; 22 | packages = [ pkgs.rclone ]; 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /profiles/workspace/shadowsocks.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: { 2 | 3 | secrets.shadowsocks_options = { 4 | owner = "shadowsocks:shadowsocks"; 5 | services = [ "shadowsocks" ]; 6 | }; 7 | 8 | users.users.shadowsocks = { 9 | isSystemUser = true; 10 | group = "shadowsocks"; 11 | }; 12 | 13 | users.groups.shadowsocks = { }; 14 | 15 | systemd.services.shadowsocks = { 16 | script = "ss-local -l 5555 $(cat ${config.secrets.shadowsocks_options})"; 17 | path = [ pkgs.shadowsocks-libev ]; 18 | serviceConfig = { 19 | User = "shadowsocks"; 20 | Group = "shadowsocks"; 21 | }; 22 | wantedBy = [ "multi-user.target" ]; 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /profiles/workspace/simple-osd-daemons.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, lib, ... }: 2 | let 3 | simple-osd-daemon = name: { 4 | Install.WantedBy = [ "default.target" ]; 5 | Service = { 6 | ExecStart = "${pkgs.simple-osd.${name}}/bin/simple-osd-${name}"; 7 | Restart = "always"; 8 | After = [ "mako.service" ]; 9 | Wants = [ "mako.service" ]; 10 | }; 11 | }; 12 | inherit (pkgs.my-lib) genIni; 13 | daemons = names: 14 | builtins.listToAttrs (builtins.map (name: { 15 | name = "simple-osd-${name}"; 16 | value = simple-osd-daemon name; 17 | }) names); 18 | in { 19 | home-manager.users.balsoft = { 20 | systemd.user.services = daemons [ "pulseaudio" "mpris" "bluetooth" ] 21 | // pkgs.lib.optionalAttrs (config.deviceSpecific.isLaptop) 22 | (daemons [ "battery" "brightness" ]); 23 | xdg.configFile = { 24 | "simple-osd/common".text = 25 | genIni { progressbar.length = 25; notification."default timeout" = 3; }; 26 | "simple-osd/mpris".text = 27 | genIni { default."notification display time" = 3; }; 28 | }; 29 | }; 30 | } 31 | -------------------------------------------------------------------------------- /profiles/workspace/ssh.nix: -------------------------------------------------------------------------------- 1 | { pkgs, config, lib, ... }: { 2 | services.openssh = { 3 | enable = true; 4 | settings = { 5 | PasswordAuthentication = false; 6 | PermitRootLogin = "no"; 7 | X11Forwarding = true; 8 | }; 9 | extraConfig = "StreamLocalBindUnlink yes"; 10 | ports = [ 22 ]; 11 | }; 12 | 13 | persist.state.etcFiles = [ 14 | "ssh/ssh_host_ed25519_key" 15 | "ssh/ssh_host_ed25519_key.pub" 16 | "ssh/ssh_host_rsa_key" 17 | "ssh/ssh_host_rsa_key.pub" 18 | ]; 19 | 20 | persist.state.directories = [ "/home/balsoft/.ssh" ]; 21 | 22 | users.users.balsoft.openssh.authorizedKeys.keys = [ 23 | "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDd2OdcSHUsgezuV+cpFqk9+Svtup6PxIolv1zokVZdqvS8qxLsA/rwYmQgTnuq4/zK/GIxcUCH4OxYlW6Or4M4G7qrDKcLAUrRPWkectqEooWRflZXkfHduMJhzeOAsBdMfYZQ9024GwKr/4yriw2BGa8GbbAnQxiSeTipzvXHoXuRME+/2GsMFAfHFvxzXRG7dNOiLtLaXEjUPUTcw/fffKy55kHtWxMkEvvcdyR53/24fmO3kLVpEuoI+Mp1XFtX3DvRM9ulgfwZUn8/CLhwSLwWX4Xf9iuzVi5vJOJtMOktQj/MwGk4tY/NPe+sIk+nAUKSdVf0y9k9JrJT98S/ comment" 24 | ]; 25 | 26 | # secrets.ssh_key = { 27 | # services = [ ]; 28 | # decrypted = "/root/.ssh/id_ed25519"; 29 | # }; 30 | 31 | home-manager.users.balsoft.programs.ssh = { 32 | enable = true; 33 | matchBlocks = { "*" = { compression = false; }; }; 34 | }; 35 | } 36 | -------------------------------------------------------------------------------- /profiles/workspace/xdg.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, lib, ... }: { 2 | home-manager.users.balsoft = { 3 | xdg.enable = true; 4 | xdg.userDirs.enable = true; 5 | }; 6 | 7 | environment.sessionVariables = { 8 | XDG_CURRENT_DESKTOP = "X-Generic"; 9 | DE = "generic"; 10 | }; 11 | 12 | persist.state.directories = map (x: "/home/balsoft/${x}") [ 13 | "Pictures" 14 | "Documents" 15 | "Downloads" 16 | "Music" 17 | "projects" 18 | "Videos" 19 | ]; 20 | } 21 | -------------------------------------------------------------------------------- /profiles/workspace/yubikey-touch-detector.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, lib, ... }: { 2 | home-manager.users.balsoft.systemd.user.services.yubikey-touch-detector = { 3 | Service = { 4 | Environment = [ "PATH=${lib.makeBinPath [ pkgs.gnupg pkgs.yubikey-touch-detector ]}" ]; 5 | ExecStart = toString (pkgs.writeShellScript "yubikey-touch-detector" '' 6 | export SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)" 7 | yubikey-touch-detector -libnotify 8 | ''); 9 | }; 10 | Install = rec { 11 | WantedBy = [ "graphical-session.target" ]; 12 | Wants = [ "gpg-agent-ssh.socket" "gpg-agent.socket" ]; 13 | After = Wants; 14 | }; 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /profiles/workspace/zsh/default.nix: -------------------------------------------------------------------------------- 1 | { pkgs, config, lib, ... }: { 2 | 3 | environment.pathsToLink = [ "/share/zsh" ]; 4 | environment.sessionVariables.SHELL = "${pkgs.zsh}/bin/zsh"; 5 | 6 | # A history file is screwed up otherwise :( 7 | persist.state.directories = [ "/home/balsoft/.local/share/zsh" ]; 8 | 9 | home-manager.users.balsoft.programs.zsh = { 10 | enable = true; 11 | # enableAutosuggestions = true; 12 | enableCompletion = true; 13 | oh-my-zsh = { 14 | enable = true; 15 | plugins = [ "git" "dirhistory" ]; 16 | }; 17 | 18 | dotDir = ".config/zsh"; 19 | 20 | history = rec { 21 | size = 10000000; 22 | save = size; 23 | path = "$HOME/.local/share/zsh/history"; 24 | }; 25 | plugins = [ 26 | { 27 | name = "zsh-autosuggestions"; 28 | src = pkgs.fetchFromGitHub { 29 | owner = "zsh-users"; 30 | repo = "zsh-autosuggestions"; 31 | rev = "v0.4.0"; 32 | sha256 = "0z6i9wjjklb4lvr7zjhbphibsyx51psv50gm07mbb0kj9058j6kc"; 33 | }; 34 | } 35 | { 36 | name = "you-should-use"; 37 | src = pkgs.fetchFromGitHub { 38 | owner = "MichaelAquilina"; 39 | repo = "zsh-you-should-use"; 40 | rev = "2be37f376c13187c445ae9534550a8a5810d4361"; 41 | sha256 = "0yhwn6av4q6hz9s34h4m3vdk64ly6s28xfd8ijgdbzic8qawj5p1"; 42 | }; 43 | } 44 | { 45 | name = "async"; 46 | file = "async.zsh"; 47 | src = pkgs.fetchFromGitHub { 48 | owner = "mafredri"; 49 | repo = "zsh-async"; 50 | rev = "3ba6e2d1ea874bfb6badb8522ab86c1ae272923d"; 51 | sha256 = "3hhZXL8/Ml7UlkkHBPpS5NfUGB5BqgO95UvtpptXf8E="; 52 | }; 53 | } 54 | { 55 | name = "powerlevel10k-config"; 56 | src = ./.; 57 | file = "p10k.zsh"; 58 | } 59 | { 60 | name = "zsh-powerlevel10k"; 61 | src = pkgs.zsh-powerlevel10k; 62 | file = "share/zsh-powerlevel10k/powerlevel10k.zsh-theme"; 63 | } 64 | ]; 65 | shellAliases = { 66 | "b" = "nix build"; 67 | "p" = "nix-shell --run zsh -p"; 68 | "s" = "nix shell"; 69 | "e" = "$EDITOR"; 70 | "dog" = "$EDITOR -"; 71 | "d" = "nix develop"; 72 | "r" = "nix run"; 73 | "f" = "nix search"; 74 | "fs" = "nix search self"; 75 | "o" = "xdg-open"; 76 | "post" = ''curl -F"file=@-" https://0x0.st''; 77 | "cat" = "${pkgs.bat}/bin/bat"; 78 | "ls" = "${pkgs.eza}/bin/eza"; 79 | "gp" = "git push && github_status_reset_bg"; 80 | "gpf!" = "git push --force-with-lease && github_status_reset_bg"; 81 | }; 82 | initContent = '' 83 | cmdignore=(htop tmux top vim) 84 | 85 | export GITHUB_TOKEN=$(cat /var/secrets/github_token) 86 | 87 | # end and compare timer, notify-send if needed 88 | function notifyosd-precmd() { 89 | retval=$? 90 | if [ ! -z "$cmd" ]; then 91 | cmd_end=`date +%s` 92 | ((cmd_time=$cmd_end - $cmd_start)) 93 | fi 94 | cleareol="\e[K" 95 | colorreset="\e[1;0m" 96 | if [ $retval -eq 0 ]; then 97 | cmdstat="✓" 98 | bgcolor="\e[1;30;42m" 99 | fgcolor="\e[1;32;40m" 100 | else 101 | cmdstat="✘" 102 | bgcolor="\e[1;41m" 103 | fgcolor="\e[1;31;40m" 104 | printf "$bgcolor $cmdstat $retval $colorreset\n" 105 | fi 106 | if [ ! -z "$cmd" ]; then 107 | if [[ $cmd_time -gt 3 ]]; then 108 | ${pkgs.libnotify}/bin/notify-send -a command_complete -i utilities-terminal -u low "$cmdstat $cmd" "in `date -u -d @$cmd_time +'%T'`" 109 | echo -e '\a' 110 | fi 111 | fi 112 | unset cmd 113 | } 114 | 115 | # make sure this plays nicely with any existing precmd 116 | precmd_functions+=( notifyosd-precmd ) 117 | 118 | # get command name and start the timer 119 | function notifyosd-preexec() { 120 | cmd=$1 121 | cmd_start=`date +%s` 122 | } 123 | 124 | bindkey -v 125 | bindkey -M viins '^H' backward-kill-word 126 | 127 | # make sure this plays nicely with any existing preexec 128 | preexec_functions+=( notifyosd-preexec ) 129 | XDG_DATA_DIRS=$XDG_DATA_DIRS:$GSETTINGS_SCHEMAS_PATH 130 | 131 | function repl() { 132 | source="$(nix flake prefetch --json "$1" | ${pkgs.jq}/bin/jq -r .storePath)" 133 | TEMP="$(mktemp --suffix=.nix)" 134 | echo "let self = builtins.getFlake \"$source\"; in self // self.legacyPackages.\''${builtins.currentSystem} or { } // self.packages.\''${builtins.currentSystem} or { }" > "$TEMP" 135 | nix repl "$TEMP" 136 | rm "$TEMP" 137 | } 138 | 139 | 140 | function ss() { nix shell "self#$1" } 141 | function es() { nix edit "self#$1" } 142 | function bs() { nix build "self#$1" } 143 | function is() { nix search "self#$1" } 144 | function rs() { repl self } 145 | 146 | zle_highlight=(default:bg=#333333,fg=white) 147 | 148 | PS1="$PS1 149 | $ " 150 | ''; 151 | }; 152 | } 153 | -------------------------------------------------------------------------------- /roles/base.nix: -------------------------------------------------------------------------------- 1 | { inputs, ... }: { 2 | imports = with inputs.self.nixosProfiles; [ 3 | # PROFILES 4 | autoRun 5 | xdg 6 | 7 | git 8 | gpg 9 | locale 10 | misc 11 | network 12 | nix 13 | user 14 | ssh 15 | zsh 16 | ]; 17 | } 18 | -------------------------------------------------------------------------------- /roles/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | server = ./server.nix; 3 | desktop = ./desktop.nix; 4 | base = ./base.nix; 5 | } 6 | -------------------------------------------------------------------------------- /roles/desktop.nix: -------------------------------------------------------------------------------- 1 | { inputs, ... }: { 2 | imports = with inputs.self.nixosProfiles; [ 3 | ./base.nix 4 | 5 | boot 6 | 7 | # PROFILES 8 | applications-setup 9 | bluetooth 10 | power 11 | opengl 12 | hardware 13 | sound 14 | virtualisation 15 | 16 | yubikey 17 | vlock 18 | 19 | alacritty 20 | aerc 21 | # cantata 22 | # emacs 23 | # vscodium 24 | helix 25 | firefox 26 | # geary 27 | github 28 | gwenview 29 | himalaya 30 | nheko 31 | packages 32 | okular 33 | josm 34 | 35 | pass-secret-service 36 | rclone 37 | copyq 38 | cursor 39 | direnv 40 | fonts 41 | gnome3 42 | gtk 43 | i3blocks 44 | qt 45 | slack 46 | kdeconnect 47 | light 48 | mako 49 | # mopidy 50 | simple-osd-daemons 51 | sway 52 | yubikey-touch-detector 53 | btop 54 | ]; 55 | } 56 | -------------------------------------------------------------------------------- /roles/server.nix: -------------------------------------------------------------------------------- 1 | { inputs, ... }: { 2 | imports = [ 3 | ./base.nix 4 | 5 | inputs.self.nixosProfiles.boot 6 | ]; 7 | 8 | security.sudo.wheelNeedsPassword = false; 9 | } 10 | -------------------------------------------------------------------------------- /shell.nix: -------------------------------------------------------------------------------- 1 | (import 2 | ( 3 | let 4 | lock = builtins.fromJSON (builtins.readFile ./flake.lock); 5 | in 6 | fetchTarball { 7 | url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; 8 | sha256 = lock.nodes.flake-compat.locked.narHash; 9 | } 10 | ) 11 | { 12 | src = ./.; 13 | }).shellNix 14 | --------------------------------------------------------------------------------