├── .gitignore ├── cloudtf ├── Makefile ├── mymachine.tf ├── shell.nix ├── terraform.tf ├── terraform.tfvars ├── upstream-amis.auto.tfvars.json ├── variables.tf └── vpc.tf ├── configuration.nix ├── devices ├── morbo │ ├── configuration.nix │ └── hardware-configuration.nix └── petunia │ ├── configuration.nix │ ├── hardware-configuration.nix │ ├── upload-to-cache.sh │ └── wireguard-ensure.nix ├── nixos-nineish.png ├── packages ├── 0001-Pass-explicitly-resolved-IP-port.patch ├── 0001-swaynag-allow-specifying-more-buttons-which-execute-.patch ├── abathur-resholved │ └── default.nix ├── aenea │ ├── default.nix │ └── service.nix ├── autorandr-configs │ ├── default.nix │ ├── generated-configs │ │ ├── docked-home │ │ │ ├── config │ │ │ └── setup │ │ └── undocked │ │ │ ├── config │ │ │ └── setup │ ├── scripts │ │ └── move-frames.sh │ └── service.nix ├── b612-font │ └── default.nix ├── backlight-locker │ ├── backlight.sh │ └── default.nix ├── backlight │ ├── backlight.sh │ └── default.nix ├── bash-config │ ├── bashrc │ └── default.nix ├── default.nix ├── did-graham-commit-his-repos │ ├── check.sh │ ├── default.nix │ ├── service.nix │ └── summary.sh ├── direnv-hook │ ├── default.nix │ └── zshrc.local ├── dunst │ ├── default.nix │ └── dunstrc ├── emacs │ ├── default.el │ ├── default.nix │ └── minimal.el ├── freeze-focused │ ├── default.nix │ └── freeze.sh ├── gitconfig │ ├── default.nix │ ├── gitattributes │ ├── gitconfig │ └── gitignore ├── gnupgconfig │ ├── default.nix │ ├── gpg.conf │ └── scdaemon.conf ├── guiduck │ ├── .envrc │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.nix │ ├── Cargo.toml │ ├── nix │ │ ├── default.nix │ │ ├── sources.json │ │ └── sources.nix │ ├── shell.nix │ └── src │ │ ├── bogus.rs │ │ ├── interface.rs │ │ ├── proxy.rs │ │ ├── receive.rs │ │ └── send.rs ├── guilauncher │ ├── default.nix │ └── launch.sh ├── h │ └── default.nix ├── helvetica │ └── default.nix ├── i3config │ ├── config │ ├── default.nix │ └── i3status ├── is-nix-channel-up-to-date │ ├── default.nix │ ├── is-nix-channel-up-to-date.sh │ └── service.nix ├── kensington-slimblade-trackball │ └── service.nix ├── kill-focused │ ├── default.nix │ └── kill.sh ├── motd │ ├── default.nix │ └── motd.sh ├── mutate │ └── default.nix ├── nitrokey │ └── service.nix ├── nix │ ├── 0001-Add-a-post-build-hook.patch │ ├── 0001-badly-fix-2801.patch │ ├── 0001-build-move-needsHashRewrite-initialization-to-startB.patch │ ├── 0001-pipe-stdout-stderr-to-the-user.patch │ ├── 0001-use-a-stderr-sink-too.patch │ ├── 0002-build-add-test-for-sandboxed-check.patch │ ├── 0002-build-run-diff-hook-under-check-and-document-diff-ho.patch │ ├── 0002-fixup-Add-a-post-build-hook.patch │ ├── 0003-build-run-diff-hook-under-check-and-document-diff-ho.patch │ ├── 0003-diff-hook-execute-as-the-build-user-and-pass-the-tem.patch │ ├── 0004-chdir-setgroups.patch │ ├── 0004-diff-hook-execute-as-the-build-user-and-pass-the-tem.patch │ ├── 0005-chdir-setgroups.patch │ ├── 0005-runProgram-support-gid-uid-chdir.patch │ ├── 0006-runProgram-support-gid-uid-chdir.patch │ ├── 2931.patch │ └── post-build-hook.patch ├── nixos-software-manager │ ├── default.nix │ ├── prompt-upgrade.sh │ ├── service.nix │ ├── stage-upgrade.sh │ └── switch-to ├── nixos-unstable-packages │ └── default.nix ├── nixpkgs-maintainer-tools │ ├── bin │ │ ├── cpToOldStable │ │ ├── cpToRelease │ │ ├── git-am-pr │ │ ├── rebranch │ │ ├── remaster │ │ └── try-pr │ └── default.nix ├── nixpkgs-pre-push │ ├── default.nix │ └── pre-push ├── otf2bdf │ ├── 0001-Remove-deprecated-MKINSTALLDIRS.patch │ ├── 0002-Fix-generate_font-return-value.patch │ └── default.nix ├── overlay.nix ├── pass-0001-clip-support-single-binary-coreutils.patch ├── passff-host │ ├── default.nix │ └── paths.patch ├── power-targets │ └── service.nix ├── recognize-thunderbolt │ ├── default.nix │ ├── recognize-thunderbolt │ └── service.nix ├── screenshot │ ├── default.nix │ └── screenshot.sh ├── services.nix ├── snoop │ ├── default.nix │ └── snoop.sh ├── spawn │ ├── default.nix │ └── spawn.sh ├── sway-cycle-workspace │ ├── cycle-workspace.sh │ └── default.nix ├── swayconfig │ ├── config │ ├── default.nix │ └── waybar ├── symlinks │ ├── service.nix │ └── update-symlinks.sh ├── systemd-boot │ ├── systemd-boot-builder.py │ └── systemd-boot.nix ├── systemd-lock-handler │ ├── default.nix │ ├── locker.py │ └── service.nix ├── timeout │ ├── default.nix │ └── timeout.tcl ├── ttf-console-font │ ├── default.nix │ └── service.nix ├── vault-plugin-secrets-oauthapp │ └── default.nix ├── volume │ ├── default.nix │ └── volume.sh ├── wl-freeze │ ├── default.nix │ └── wl-freeze.sh └── zsh-config │ ├── default.nix │ └── zshrc ├── pubkey └── warning /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | .#* 3 | secrets.nix 4 | helvetica.ttc 5 | -------------------------------------------------------------------------------- /cloudtf/Makefile: -------------------------------------------------------------------------------- 1 | upstream-amis.auto.tfvars.json: 2 | nix-instantiate \ 3 | --eval --json --strict \ 4 | '' \ 5 | | jq '{ nixos_amis: . }' > $@ 6 | -------------------------------------------------------------------------------- /cloudtf/mymachine.tf: -------------------------------------------------------------------------------- 1 | 2 | resource "aws_key_pair" "petunia" { 3 | public_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDBSfZUb2FwLdSh2iOyETlWhez+vsJ+lBgQ8GrUEjc5Cm6ChY5HSxw+78w+P6Dm3t3w3ThxKsdb7Yt/l5nVG1B+pRKTB1z6ND1BNNm6LsNCFw6E2q8O8HwMz4CeN1pgZNFB8v2USTRgXGZd/b/Q1gBK9W9lcASouvnnIHaRA17nBm30NcicEG8hcnp81Jgo3Ml6YJx6nj4rmTecFNoTQVo/w6JBRMIM9A3x575cy54sB6Q6hX+Gb7KiiV5WH1hivJqwDBovqs86RBxJdbygnc2iwf2u30ltH0LH/YFxET4yK6n2bPCCwANLHXk+7/3+0k4r0O8m5l8B1k1i8pxwVtQ2/GLnUs0IQPftthFQ2QpyRL/mCjz4uPSZuzXk1WwsR7atvfKd1+cmrtH3s17QH+KDU3fL5zXGsWsCtMoUUy4fM1YQAzmOVSURgtJ9Uf1NJYlS9Fw/SMB2v5nPiTB5HbKy3OmHcwIyms2vQ4yqfxpGUAETWZCDzKplCIRMVliF3rk=" 4 | } 5 | 6 | resource "aws_instance" "mymachine" { 7 | ami = var.nixos_amis.latest[var.region].hvm-ebs 8 | instance_type = "t3.micro" 9 | vpc_security_group_ids = [ aws_security_group.default.id ] 10 | subnet_id = aws_subnet.subnet_a.id 11 | key_name = aws_key_pair.petunia.key_name 12 | associate_public_ip_address = false 13 | root_block_device { 14 | volume_size = 20 15 | } 16 | } 17 | 18 | resource "aws_eip" "mymachine" { 19 | vpc = true 20 | 21 | instance = aws_instance.mymachine.id 22 | depends_on = [ aws_internet_gateway.default ] 23 | } 24 | -------------------------------------------------------------------------------- /cloudtf/shell.nix: -------------------------------------------------------------------------------- 1 | let pkgs = import {}; in pkgs.mkShell { 2 | buildInputs = [ 3 | (pkgs.terraform_0_12.withPlugins(p: [ p.aws ])) 4 | ]; 5 | } 6 | -------------------------------------------------------------------------------- /cloudtf/terraform.tf: -------------------------------------------------------------------------------- 1 | 2 | provider "aws" { 3 | region = var.region 4 | } 5 | 6 | 7 | -------------------------------------------------------------------------------- /cloudtf/terraform.tfvars: -------------------------------------------------------------------------------- 1 | region = "us-east-1" 2 | -------------------------------------------------------------------------------- /cloudtf/variables.tf: -------------------------------------------------------------------------------- 1 | variable "region" {} 2 | 3 | variable "nixos_amis" { 4 | type = map(map(object({ 5 | hvm-ebs = string 6 | }))) 7 | } 8 | -------------------------------------------------------------------------------- /cloudtf/vpc.tf: -------------------------------------------------------------------------------- 1 | 2 | resource "aws_vpc" "default" { 3 | cidr_block = "172.16.0.0/16" 4 | assign_generated_ipv6_cidr_block = true 5 | } 6 | 7 | resource "aws_internet_gateway" "default" { 8 | vpc_id = aws_vpc.default.id 9 | } 10 | 11 | resource "aws_route_table" "default" { 12 | vpc_id = aws_vpc.default.id 13 | } 14 | 15 | resource "aws_route" "outgoing_ipv4" { 16 | destination_cidr_block = "0.0.0.0/0" 17 | gateway_id = aws_internet_gateway.default.id 18 | route_table_id = aws_route_table.default.id 19 | } 20 | 21 | resource "aws_route" "outgoing_ipv6" { 22 | destination_ipv6_cidr_block = "::/0" 23 | gateway_id = aws_internet_gateway.default.id 24 | route_table_id = aws_route_table.default.id 25 | } 26 | 27 | resource "aws_subnet" "subnet_a" { 28 | vpc_id = aws_vpc.default.id 29 | cidr_block = "172.16.1.0/24" 30 | map_public_ip_on_launch = false 31 | ipv6_cidr_block = cidrsubnet(aws_vpc.default.ipv6_cidr_block, 8, 254) 32 | assign_ipv6_address_on_creation = true 33 | } 34 | 35 | resource "aws_route_table_association" "subnet_a" { 36 | route_table_id = aws_route_table.default.id 37 | 38 | subnet_id = aws_subnet.subnet_a.id 39 | } 40 | 41 | resource "aws_default_security_group" "default" { 42 | vpc_id = aws_vpc.default.id 43 | } 44 | 45 | resource "aws_security_group" "default" { 46 | vpc_id = aws_vpc.default.id 47 | } 48 | 49 | resource "aws_security_group_rule" "ssh" { 50 | security_group_id = aws_security_group.default.id 51 | 52 | type = "ingress" 53 | from_port = 22 54 | to_port = 22 55 | protocol = "tcp" 56 | cidr_blocks = [ "0.0.0.0/0" ] 57 | } 58 | 59 | -------------------------------------------------------------------------------- /configuration.nix: -------------------------------------------------------------------------------- 1 | { pkgs, ... }: 2 | let 3 | sourceTree = ./.; 4 | gitTree = builtins.fetchGit sourceTree; 5 | 6 | verifyCleanTree = srcTree: pkgs.runCommand "clean-tree" 7 | { buildInputs = [ pkgs.git ]; } 8 | '' 9 | cd ${srcTree} 10 | if ! git diff --quiet --exit-code; then 11 | echo "FAIL FAIL FAIL"; 12 | echo "MUST COMMIT YOUR CHANGES! DIRTY TREE DETECTED!" 13 | exit 1 14 | fi 15 | 16 | touch $out 17 | ''; 18 | in 19 | { 20 | imports = [ "${gitTree}/main-configuration.nix" ]; 21 | system.activationScripts.maybeBreak = 22 | pkgs.lib.addContextFrom (verifyCleanTree sourceTree) ""; 23 | } 24 | -------------------------------------------------------------------------------- /devices/morbo/configuration.nix: -------------------------------------------------------------------------------- 1 | # Edit this configuration file to define what should be installed on 2 | # your system. Help is available in the configuration.nix(5) man page 3 | # and in the NixOS manual (accessible by running ‘nixos-help’). 4 | 5 | { config, pkgs, lib, ... }: 6 | let 7 | root = /home/grahamc/projects/grahamc/nixos-config; 8 | secrets = import "${root}/secrets.nix"; 9 | in { 10 | nixpkgs = { 11 | system = "x86_64-linux"; 12 | config = { 13 | allowUnfree = true; 14 | }; 15 | overlays = [ 16 | (import ../../packages/overlay.nix { inherit secrets; }) 17 | ]; 18 | }; 19 | 20 | imports = 21 | [ 22 | ./hardware-configuration.nix 23 | ../../packages/services.nix 24 | ]; 25 | 26 | boot = { 27 | zfs.enableUnstable = true; 28 | kernelParams = [ "acpi_rev_override=5" ]; # "acpi_rev_override=1" "pcie_port_pm=off" 29 | kernel.sysctl = { 30 | "net.ipv6.conf.all.use_tempaddr" = 2; 31 | }; 32 | kernelPackages = pkgs.linuxPackages_latest; 33 | loader = { 34 | systemd-boot = { 35 | enable = true; 36 | signed = true; 37 | signing-key = secrets.secure-boot.key; 38 | signing-certificate = secrets.secure-boot.certificate; 39 | }; 40 | efi.canTouchEfiVariables = true; 41 | }; 42 | 43 | cleanTmpDir = true; 44 | }; 45 | 46 | networking.hostName = "Morbo"; # Define your hostname. 47 | networking.networkmanager.enable = true; 48 | 49 | networking.extraHosts = '' 50 | 127.0.0.1 www.facebook.com facebook.com x.facebook.com 51 | ''; 52 | 53 | hardware = { 54 | u2f.enable = true; 55 | pulseaudio = { 56 | enable = true; 57 | package = pkgs.pulseaudioFull; 58 | }; 59 | mcelog.enable = true; 60 | nvidiaOptimus.disable = true; 61 | bluetooth = { 62 | enable = true; 63 | extraConfig = '' 64 | [general] 65 | Enable=Source,Sink,Media,Socket 66 | ''; 67 | }; 68 | }; 69 | 70 | i18n = { 71 | consoleFont = "latarcyrheb-sun32"; 72 | consoleKeyMap = "dvorak"; 73 | }; 74 | 75 | time.timeZone = secrets.timezone; 76 | security.pam.services.lightdm.enableKwallet = true; 77 | 78 | environment = { 79 | variables = { 80 | EDITOR = "emacs -nw"; 81 | }; 82 | systemPackages = with pkgs; [ 83 | git 84 | file 85 | gnupg 86 | (if false then firefox-devedition-bin else firefox) 87 | google-chrome 88 | xclip 89 | custom-emacs 90 | ripgrep 91 | nixpkgs-maintainer-tools 92 | pass 93 | slack 94 | direnv 95 | h 96 | ]; 97 | 98 | etc."i3/config".source = pkgs.i3config; 99 | 100 | # Wacky erase-root-on-every-boot stuff. 101 | etc."NetworkManager/system-connections".source = "/rpool/persist/etc/NetworkManager/system-connections/"; 102 | }; 103 | 104 | powerManagement.powertop.enable = true; 105 | powerManagement.cpuFreqGovernor = "powersave"; 106 | 107 | services = { 108 | openssh = { 109 | enable = true; 110 | }; 111 | 112 | emacs = { 113 | enable = true; 114 | package = pkgs.custom-emacs; 115 | }; 116 | 117 | redshift = { 118 | enable = true; 119 | latitude = secrets.latitude; 120 | longitude = secrets.longitude; 121 | temperature.night = 3400; 122 | }; 123 | 124 | xserver = { 125 | enable = true; 126 | autorun = true; 127 | layout = "dvorak"; 128 | xkbOptions = "compose:ralt"; 129 | libinput = { 130 | enable = true; 131 | naturalScrolling = true; 132 | disableWhileTyping = true; 133 | }; 134 | 135 | displayManager.lightdm.enable = true; 136 | desktopManager.default = "none"; 137 | windowManager.default = "i3"; 138 | windowManager.i3 = { 139 | enable = true; 140 | configFile = "/etc/i3/config"; 141 | }; 142 | 143 | inputClassSections = [ 144 | '' 145 | Identifier "libinput touchscreen catchall" 146 | MatchIsTouchscreen "on" 147 | MatchDevicePath "/dev/input/event*" 148 | Driver "libinput" 149 | Option "DisableWhileTyping" "true" 150 | '' 151 | 152 | '' 153 | Identifier "yubikey" 154 | MatchIsKeyboard "on" 155 | MatchProduct "Yubikey" 156 | Option "XkbLayout" "us" 157 | '' 158 | ]; 159 | 160 | monitorSection = '' 161 | Modeline "1920x1080_60.00" 173.00 1920 2048 2248 2576 1080 1083 1088 1120 -hsync +vsync 162 | Option "PreferredMode" "1920x1080_60.00" 163 | DisplaySize 345 191 164 | ''; 165 | }; 166 | }; 167 | 168 | fonts = { 169 | enableFontDir = true; 170 | fonts = with pkgs; [ 171 | powerline-fonts 172 | source-code-pro 173 | twemoji-color-font 174 | 175 | # Consider just symbola instead of noto-* 176 | noto-fonts 177 | noto-fonts-extra 178 | noto-fonts-emoji 179 | noto-fonts-cjk 180 | 181 | helvetica 182 | vegur # the official NixOS font 183 | font-b612 184 | ]; 185 | }; 186 | 187 | programs = { 188 | zsh.enable = true; 189 | zsh.interactiveShellInit = '' 190 | eval "$(${pkgs.direnv}/bin/direnv hook zsh)" 191 | if [ "$(cat "''${XDG_CACHE_HOME:-$HOME/.cache}/shell-warning/"* | wc -l)" -gt 0 ]; then 192 | cat ${../../warning} 193 | for f in "''${XDG_CACHE_HOME:-$HOME/.cache}/shell-warning/"*; do 194 | printf "\n\n\n"; 195 | cat "$f"; 196 | done 197 | printf "\n\n\n"; 198 | echo " ^^^ go fix those before your computer breaks ^^^" 199 | fi 200 | ''; 201 | gnupg.agent = { 202 | enable = true; 203 | enableSSHSupport = true; 204 | }; 205 | }; 206 | 207 | users.mutableUsers = false; 208 | users.users.root.hashedPassword = secrets.hashedPassword; 209 | 210 | users.users.grahamc = rec { 211 | isNormalUser = true; 212 | uid = 1000; 213 | extraGroups = [ "wheel" "pcscd" "networkmanager" ]; 214 | createHome = true; 215 | home = "/home/grahamc"; 216 | shell = "/run/current-system/sw/bin/zsh"; 217 | hashedPassword = secrets.hashedPassword; 218 | symlinks = { 219 | ".bashrc" = pkgs.bash-config; 220 | ".zshrc" = pkgs.zsh-config; 221 | ".background-image" = "${pkgs.nixos-artwork.wallpapers.gnome-dark}/share/artwork/gnome/nix-wallpaper-simple-dark-gray_bottom.png"; 222 | ".gitconfig" = pkgs.gitconfig; 223 | ".gnupg/gpg.conf" = pkgs.gnupgconfig.gpgconf; 224 | ".gnupg/scdaemon.conf" = pkgs.gnupgconfig.scdaemonconf; 225 | ".mozilla/native-messaging-hosts/passff.json" = "${pkgs.passff-host}/share/passff-host/passff.json"; 226 | } // (if (builtins.pathExists "${home}/projects/nixpkgs") then { 227 | "projects/nixpkgs/.git/hooks/pre-push" = pkgs.nixpkgs-pre-push; 228 | "projects/nix/.git/hooks/pre-push" = pkgs.nixpkgs-pre-push; 229 | } else {}); 230 | }; 231 | 232 | nix = { 233 | useSandbox = true; 234 | distributedBuilds = true; 235 | buildMachines = secrets.buildMachines; 236 | nixPath = [ 237 | "nixpkgs=/nix/var/nix/profiles/per-user/root/channels/nixos" 238 | "nixos-config=${toString root}/devices/morbo/configuration.nix" 239 | ]; 240 | 241 | gc = { 242 | automatic = true; 243 | dates = "*:0/10"; 244 | }; 245 | }; 246 | systemd.services.nix-gc.unitConfig.ConditionACPower = true; 247 | 248 | programs.dconf.enable = true; 249 | services.dbus.packages = [ pkgs.gnome3.dconf ]; 250 | 251 | programs.zsh.promptInit = '' 252 | # Lifted from programs.bash.promptInit 253 | # Provide a nice prompt if the terminal supports it. 254 | if [ "$TERM" != "dumb" -o -n "$INSIDE_EMACS" ]; then 255 | PROMPT_COLOR="red" 256 | let $UID && PROMPT_COLOR="green" 257 | 258 | PS1=$'\n'"%B%F{$PROMPT_COLOR}[%n@%m:%~]$%f%b " 259 | if test "$TERM" = "xterm"; then 260 | PS1="$'\n'[%n@%m:%~]$ " 261 | fi 262 | fi 263 | ''; 264 | 265 | # The NixOS release to be compatible w/ for stateful data such 266 | system.stateVersion = "18.09"; 267 | 268 | # Only start emacs for actual users, lol 269 | systemd.user.services.emacs.unitConfig = { 270 | ConditionGroup = "users"; 271 | }; 272 | 273 | virtualisation.virtualbox.host.enable = true; 274 | virtualisation.docker.enable = true; 275 | 276 | 277 | services.printing.enable = true; 278 | services.printing.drivers = [ pkgs.gutenprint pkgs.gutenprintBin ]; 279 | 280 | services.zfs.autoScrub.enable = true; 281 | services.zfs.autoScrub.interval = "weekly"; 282 | systemd.services.zfs-scrub.unitConfig.ConditionACPower = true; 283 | hardware.cpu.intel.updateMicrocode = true; 284 | } 285 | -------------------------------------------------------------------------------- /devices/morbo/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, ... }: 5 | 6 | { 7 | imports = 8 | [ 9 | ]; 10 | 11 | hardware.cpu.intel.updateMicrocode = true; 12 | boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usb_storage" "sd_mod" "rtsx_pci_sdmmc" ]; 13 | boot.kernelModules = [ "kvm-intel" ]; 14 | boot.extraModulePackages = [ ]; 15 | 16 | boot.initrd.luks.devices = { 17 | cryptkey = { 18 | device = "/dev/disk/by-uuid/0c1e8ef4-4b84-404f-a7c8-0871017aa086"; 19 | }; 20 | 21 | cryptroot = { 22 | device = "/dev/disk/by-uuid/9782f25f-d655-4718-9b37-d96a932dd10a"; 23 | keyFile = "/dev/mapper/cryptkey"; 24 | }; 25 | 26 | cryptswap = { 27 | device = "/dev/disk/by-uuid/eedde382-4b96-420e-8489-c581b6af1eac"; 28 | keyFile = "/dev/mapper/cryptkey"; 29 | }; 30 | }; 31 | 32 | fileSystems."/" = 33 | { device = "rpool/danger-root"; 34 | fsType = "zfs"; 35 | }; 36 | 37 | fileSystems."/nix" = 38 | { device = "rpool/nix"; 39 | fsType = "zfs"; 40 | }; 41 | 42 | fileSystems."/home" = 43 | { device = "rpool/home"; 44 | fsType = "zfs"; 45 | }; 46 | 47 | fileSystems."/boot" = 48 | { device = "/dev/disk/by-uuid/55DE-4951"; 49 | fsType = "vfat"; 50 | }; 51 | 52 | swapDevices = 53 | [ { device = "/dev/disk/by-uuid/cef80b32-0d52-48bd-9957-add0a948d1fa"; } 54 | ]; 55 | 56 | nix.maxJobs = lib.mkDefault 8; 57 | powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; 58 | networking.hostId = "e9d9c1f1"; 59 | 60 | boot.initrd.postDeviceCommands = lib.mkAfter '' 61 | zfs rollback rpool/danger-root@blank 62 | ''; 63 | 64 | boot.initrd.postMountCommands = '' 65 | # Don't keep the cryptkey available all the time 66 | cryptsetup close /dev/mapper/cryptkey 67 | ''; 68 | } 69 | -------------------------------------------------------------------------------- /devices/petunia/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, ... }: 5 | 6 | { 7 | networking.hostId = "a28d9fb2"; 8 | imports = 9 | [ 10 | ]; 11 | 12 | boot.initrd.availableKernelModules = [ "xhci_pci" "nvme" "usb_storage" "sd_mod" "rtsx_pci_sdmmc" ]; 13 | boot.kernelModules = [ "kvm-intel" ]; 14 | boot.extraModulePackages = [ ]; 15 | boot.kernelParams = [ "mem_sleep_default=deep" ]; 16 | 17 | boot.initrd.postDeviceCommands = lib.mkAfter '' 18 | zfs rollback -r tank/system/blank-root@blank 19 | ''; 20 | 21 | fileSystems."/" = 22 | { device = "tank/system/blank-root"; 23 | fsType = "zfs"; 24 | options = [ "nodev" "nosuid" "noexec" ]; 25 | }; 26 | 27 | fileSystems."/home" = 28 | { device = "tank/user/home"; 29 | fsType = "zfs"; 30 | options = [ "nodev" "nosuid" ]; 31 | }; 32 | 33 | fileSystems."/nix" = 34 | { device = "tank/local/nix"; 35 | fsType = "zfs"; 36 | options = [ "nodev" "nosuid" ]; 37 | }; 38 | 39 | fileSystems."/boot" = 40 | { device = "/dev/disk/by-uuid/3A62-0D0D"; 41 | fsType = "vfat"; 42 | options = [ "nodev" "nosuid" "noexec" ]; 43 | }; 44 | 45 | nix.maxJobs = lib.mkDefault 8; 46 | powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; 47 | } 48 | -------------------------------------------------------------------------------- /devices/petunia/upload-to-cache.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eu 4 | 5 | # Shift off arguments to the hook until the only remaining arguments 6 | # are output paths 7 | while [ "${1:---}" != "--" ]; do 8 | shift 9 | done 10 | shift # pop off the "--" 11 | 12 | echo "Signing paths" "$@" 13 | nix sign-paths --key-file /rpool/persist/etc/nix/key.secret "$@" 14 | echo "Uploading paths" "$@" 15 | exec nix copy --to 's3://example-nix-cache?region=eu-west-2' "$@" 16 | -------------------------------------------------------------------------------- /devices/petunia/wireguard-ensure.nix: -------------------------------------------------------------------------------- 1 | { secrets }: 2 | { lib, ... }: 3 | let 4 | inherit (lib) replaceChars escapeShellArg; 5 | mapToAttrs = f: l: builtins.listToAttrs (map f l); 6 | interface = "wg0"; 7 | keyToUnitName = replaceChars 8 | [ "/" "-" " " "+" "=" ] 9 | [ "-" "\\x2d" "\\x20" "\\x2b" "\\x3d" ]; 10 | 11 | peerUnitName = interfaceName: peer: 12 | let 13 | unitName = keyToUnitName peer.publicKey; 14 | in "wireguard-${interfaceName}-peer-${unitName}"; 15 | in { 16 | networking.extraHosts = '' 17 | 10.10.2.15 ogden # wireguard now 18 | 10.10.2.16 kif 19 | ''; 20 | 21 | networking.wireguard.interfaces."${interface}" = secrets.wireguard; 22 | networking.nameservers = [ "4.2.2.2" "4.2.2.3" ]; 23 | systemd.services = mapToAttrs (peer: { 24 | name = "ensure-${interface}-peer-${keyToUnitName peer.publicKey}"; 25 | value = { 26 | wantedBy = [ "multi-user.target" ]; 27 | script = '' 28 | systemctl start ${escapeShellArg (peerUnitName interface peer)} 29 | ''; 30 | serviceConfig = { 31 | RemainAfterExit = true; 32 | Type = "simple"; 33 | Restart = "on-failure"; 34 | RestartSec = "5s"; 35 | }; 36 | }; 37 | }) (builtins.filter (peer: peer ? endpoint) secrets.wireguard.peers); 38 | } 39 | -------------------------------------------------------------------------------- /nixos-nineish.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahamc/nixos-config/35388280d3b06ada5882d37c5b4f6d3baa43da69/nixos-nineish.png -------------------------------------------------------------------------------- /packages/0001-Pass-explicitly-resolved-IP-port.patch: -------------------------------------------------------------------------------- 1 | From a643e06168a848c452e0879cee414930bebd5802 Mon Sep 17 00:00:00 2001 2 | From: Graham Christensen 3 | Date: Mon, 13 Jul 2020 14:45:34 -0400 4 | Subject: [PATCH] Pass explicitly resolved IP/port 5 | 6 | --- 7 | src/nm-openconnect-service.c | 27 ++++++++++++++++++++++----- 8 | 1 file changed, 22 insertions(+), 5 deletions(-) 9 | 10 | diff --git a/src/nm-openconnect-service.c b/src/nm-openconnect-service.c 11 | index 348c19a..af05815 100644 12 | --- a/src/nm-openconnect-service.c 13 | +++ b/src/nm-openconnect-service.c 14 | @@ -394,7 +394,9 @@ nm_openconnect_start_openconnect_binary (NMOpenconnectPlugin *plugin, 15 | GSource *openconnect_watch; 16 | gint stdin_fd; 17 | char csd_user_arg[60]; 18 | - const char *props_vpn_gw, *props_cookie, *props_cacert, *props_mtu, *props_gwcert, *props_proxy; 19 | + char resolved_arg[1024]; // totally made up this number obviously 20 | + char *gw_ip, *gw_ip_pos; 21 | + const char *props_vpn_resolved_gw, *props_vpn_original_gw, *props_cookie, *props_cacert, *props_mtu, *props_gwcert, *props_proxy; 22 | const char *props_csd_enable, *props_csd_wrapper; 23 | const char *protocol; 24 | 25 | @@ -415,10 +417,12 @@ nm_openconnect_start_openconnect_binary (NMOpenconnectPlugin *plugin, 26 | return -1; 27 | } 28 | 29 | + props_vpn_original_gw = nm_setting_vpn_get_data_item (s_vpn, NM_OPENCONNECT_KEY_GATEWAY); 30 | + 31 | /* The actual gateway to use (after redirection) comes from the auth 32 | dialog, so it's in the secrets hash not the properties */ 33 | - props_vpn_gw = nm_setting_vpn_get_secret (s_vpn, NM_OPENCONNECT_KEY_GATEWAY); 34 | - if (!props_vpn_gw || !strlen (props_vpn_gw) ) { 35 | + props_vpn_resolved_gw = nm_setting_vpn_get_secret (s_vpn, NM_OPENCONNECT_KEY_GATEWAY); 36 | + if (!props_vpn_resolved_gw || !strlen (props_vpn_resolved_gw) ) { 37 | g_set_error (error, 38 | NM_VPN_PLUGIN_ERROR, 39 | NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED, 40 | @@ -460,7 +464,9 @@ nm_openconnect_start_openconnect_binary (NMOpenconnectPlugin *plugin, 41 | if (props_gwcert && strlen(props_gwcert)) { 42 | g_ptr_array_add (openconnect_argv, (gpointer) "--servercert"); 43 | g_ptr_array_add (openconnect_argv, (gpointer) props_gwcert); 44 | - } else if (props_cacert && strlen(props_cacert)) { 45 | + } 46 | + 47 | + if (props_cacert && strlen(props_cacert)) { 48 | g_ptr_array_add (openconnect_argv, (gpointer) "--cafile"); 49 | g_ptr_array_add (openconnect_argv, (gpointer) props_cacert); 50 | } 51 | @@ -510,7 +516,18 @@ nm_openconnect_start_openconnect_binary (NMOpenconnectPlugin *plugin, 52 | } 53 | } 54 | 55 | - g_ptr_array_add (openconnect_argv, (gpointer) props_vpn_gw); 56 | + g_ptr_array_add (openconnect_argv, (gpointer) "--resolve"); 57 | + gw_ip = strdup(props_vpn_resolved_gw); 58 | + gw_ip_pos = strchr(gw_ip, ':'); 59 | + if (!gw_ip_pos) { 60 | + _LOGW ("openconnect didn't find a colon in the vpn-secrets gateway data"); 61 | + return -1; 62 | + } 63 | + *gw_ip_pos = 0; 64 | + 65 | + g_ptr_array_add (openconnect_argv, (gpointer) nm_sprintf_buf (resolved_arg, "%s:%s", props_vpn_original_gw, gw_ip)); 66 | + 67 | + g_ptr_array_add (openconnect_argv, (gpointer) props_vpn_original_gw); 68 | 69 | if (gl.log_level >= LOG_INFO) { 70 | g_ptr_array_add (openconnect_argv, (gpointer) "--verbose"); 71 | -- 72 | 2.25.4 73 | 74 | -------------------------------------------------------------------------------- /packages/0001-swaynag-allow-specifying-more-buttons-which-execute-.patch: -------------------------------------------------------------------------------- 1 | From f4e311b30f78a8580f9395f0d0802c79201ce3c4 Mon Sep 17 00:00:00 2001 2 | From: Graham Christensen 3 | Date: Sun, 7 Jun 2020 10:47:56 -0400 4 | Subject: [PATCH] swaynag: allow specifying more buttons which execute and 5 | dismiss 6 | 7 | I don't love -z / -Z, but I figure this patch is far from being 8 | accepted for other reasons too. 9 | --- 10 | include/swaynag/swaynag.h | 1 + 11 | swaynag/config.c | 12 +++++++++++- 12 | swaynag/swaynag.c | 5 +++++ 13 | 3 files changed, 17 insertions(+), 1 deletion(-) 14 | 15 | diff --git a/include/swaynag/swaynag.h b/include/swaynag/swaynag.h 16 | index 496e883a..9e39e716 100644 17 | --- a/include/swaynag/swaynag.h 18 | +++ b/include/swaynag/swaynag.h 19 | @@ -53,6 +53,7 @@ struct swaynag_button { 20 | int width; 21 | int height; 22 | bool terminal; 23 | + bool dismiss; 24 | }; 25 | 26 | struct swaynag_details { 27 | diff --git a/swaynag/config.c b/swaynag/config.c 28 | index f1161b39..d702cc95 100644 29 | --- a/swaynag/config.c 30 | +++ b/swaynag/config.c 31 | @@ -52,6 +52,8 @@ int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag, 32 | static struct option opts[] = { 33 | {"button", required_argument, NULL, 'b'}, 34 | {"button-no-terminal", required_argument, NULL, 'B'}, 35 | + {"button-dismiss", required_argument, NULL, 'z'}, 36 | + {"button-dismiss-no-terminal", required_argument, NULL, 'Z'}, 37 | {"config", required_argument, NULL, 'c'}, 38 | {"debug", no_argument, NULL, 'd'}, 39 | {"edge", required_argument, NULL, 'e'}, 40 | @@ -90,6 +92,11 @@ int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag, 41 | "be defined.\n" 42 | " -B, --button-no-terminal Like --button, but does" 43 | "not run the action in a terminal.\n" 44 | + " -z, --button-dismiss Create a button with text that " 45 | + "dismisses swaynag, and executes action in a terminal when pressed. " 46 | + "Multiple buttons can be defined.\n" 47 | + " -Z, --button-dismiss-no-terminal Like " 48 | + "--button-dismiss, but does not run the action in a terminal.\n" 49 | " -c, --config Path to config file.\n" 50 | " -d, --debug Enable debugging.\n" 51 | " -e, --edge top|bottom Set the edge to use.\n" 52 | @@ -120,13 +127,15 @@ int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag, 53 | 54 | optind = 1; 55 | while (1) { 56 | - int c = getopt_long(argc, argv, "b:B:c:de:f:hlL:m:o:s:t:v", opts, NULL); 57 | + int c = getopt_long(argc, argv, "b:B:z:Z:c:de:f:hlL:m:o:s:t:v", opts, NULL); 58 | if (c == -1) { 59 | break; 60 | } 61 | switch (c) { 62 | case 'b': // Button 63 | case 'B': // Button (No Terminal) 64 | + case 'z': // Button (Dismiss) 65 | + case 'Z': // Button (Dismiss, No Terminal) 66 | if (swaynag) { 67 | if (optind >= argc) { 68 | fprintf(stderr, "Missing action for button %s\n", optarg); 69 | @@ -138,6 +147,7 @@ int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag, 70 | button->type = SWAYNAG_ACTION_COMMAND; 71 | button->action = strdup(argv[optind]); 72 | button->terminal = c == 'b'; 73 | + button->dismiss = c == 'z' || c == 'Z'; 74 | list_add(swaynag->buttons, button); 75 | } 76 | optind++; 77 | diff --git a/swaynag/swaynag.c b/swaynag/swaynag.c 78 | index 4e692b14..6c326ca8 100644 79 | --- a/swaynag/swaynag.c 80 | +++ b/swaynag/swaynag.c 81 | @@ -76,6 +76,11 @@ static void swaynag_button_execute(struct swaynag *swaynag, 82 | } 83 | _exit(EXIT_SUCCESS); 84 | } 85 | + 86 | + if (button->dismiss) { 87 | + swaynag->run_display = false; 88 | + } 89 | + 90 | if (waitpid(pid, NULL, 0) < 0) { 91 | sway_log_errno(SWAY_DEBUG, "waitpid failed"); 92 | } 93 | -- 94 | 2.25.4 95 | 96 | -------------------------------------------------------------------------------- /packages/abathur-resholved/default.nix: -------------------------------------------------------------------------------- 1 | { callPackage }: 2 | let 3 | src = builtins.fetchGit { 4 | url = "https://github.com/abathur/resholved"; 5 | ref = "master"; 6 | rev = "1a7144b2ea831b75cad0af3482c3fae04e705577"; 7 | }; 8 | in 9 | (callPackage src {}).resholved 10 | -------------------------------------------------------------------------------- /packages/aenea/default.nix: -------------------------------------------------------------------------------- 1 | { stdenv, fetchFromGitHub, python2, makeWrapper, buildEnv, xdotool, 2 | xsel, xprop, libnotify }: 3 | let 4 | python = python2.withPackages (p: [ 5 | p.jsonrpclib 6 | ]); 7 | 8 | binpath = buildEnv { 9 | name = "aenea-bin-path"; 10 | paths = [ 11 | xprop 12 | xdotool 13 | xsel 14 | libnotify 15 | ]; 16 | }; 17 | 18 | in stdenv.mkDerivation { 19 | name = "aenea-2018-12-15"; 20 | 21 | src = fetchFromGitHub { 22 | owner = "dictation-toolbox"; 23 | repo = "aenea"; 24 | rev = "78ce8aff2507bd0d6a2960ba40b5329034b96a5d"; 25 | sha256 = "031zwn2ra15c3s0b3bic4fk3rq85cqlhh1f78xidnk4hvziarcn1"; 26 | }; 27 | 28 | buildInputs = [ 29 | makeWrapper 30 | python 31 | ]; 32 | 33 | configurePhase = '' 34 | 35 | ''; 36 | 37 | buildPhase = '' 38 | ( 39 | cd ./server/linux_x11 40 | patchShebangs ./ 41 | ) 42 | ''; 43 | 44 | installPhase = '' 45 | mkdir $out 46 | mv ./* $out/ 47 | find $out -name '*.pyc' -delete 48 | wrapProgram $out/server/linux_x11/server_x11.py \ 49 | --prefix PATH : "${binpath}/bin" \ 50 | --set LANG en_US.UTF-8 51 | cp $out/server/linux_x11/config.py.example $out/server/linux_x11/config.py 52 | echo "HOST = \"255.255.255.255\" " >> $out/server/linux_x11/config.py 53 | 54 | 55 | ln -s $out/server/linux_x11/server_x11.py $out/server.py 56 | ''; 57 | } 58 | -------------------------------------------------------------------------------- /packages/aenea/service.nix: -------------------------------------------------------------------------------- 1 | { pkgs, lib, ... }: { 2 | systemd.user.services."aenea" = { 3 | description = "DNS Aenea"; 4 | 5 | serviceConfig = { 6 | ExecStart = ''${pkgs.ip2unix}/bin/ip2unix -r in,path=''${XDG_RUNTIME_DIR}/aenea.sock ${pkgs.aenea}/server.py''; 7 | }; 8 | }; 9 | 10 | systemd.user.services."dragon" = { 11 | description = "DNS"; 12 | 13 | path = with pkgs; [ qemu cdrkit netcat python2 ]; 14 | 15 | script = let 16 | opts = [ 17 | "user" 18 | "ipv4=on" 19 | "ipv6=off" 20 | "restrict=on" 21 | "guestfwd=tcp:10.0.2.43:8240-cmd:nc -N -U $XDG_RUNTIME_DIR/aenea.sock" 22 | ]; 23 | in '' 24 | #export QEMU_AUDIO_ADC_FIXED_FREQ=48000 25 | #export QEMU_AUDIO_ADC_FIXED_CHANNELS=2 26 | #export QEMU_AUDIO_ADC_FIXED_FMT=S16 27 | export QEMU_AUDIO_DRV="pa" 28 | export QEMU_PA_SAMPLES=1024 29 | 30 | ( 31 | rm -rf /tmp/cdr 32 | cp -r ~/windows10 /tmp/cdr 33 | cd /tmp/cdr 34 | find . -name '*.pyc' -delete 35 | genisoimage -v -J -r -V CONFIG -o /tmp/config.iso . 36 | ) 37 | 38 | if true; then 39 | # fast 40 | echo "Running in unsafe mode" 41 | cache=unsafe 42 | else 43 | # safe 44 | echo "Running in safe mode" 45 | cache=writeback 46 | fi 47 | 48 | qemu-system-x86_64 \ 49 | -enable-kvm \ 50 | -cpu host \ 51 | -smp cpus=4,cores=4,threads=1,sockets=1 \ 52 | -m 4096 \ 53 | -device ide-drive,bus=ide.1,drive=C \ 54 | -drive id=C,cache=$cache,if=none,file=/dev/rpool/windows10,format=raw \ 55 | -device ide-drive,bus=ide.0,drive=config \ 56 | -drive id=config,if=none,snapshot=on,media=cdrom,file=/tmp/config.iso \ 57 | -vnc 127.0.0.1:0 \ 58 | -uuid 883d6155-9dea-42c7-94bf-a123cb71c3cd \ 59 | -soundhw hda \ 60 | -device hda-micro \ 61 | -nic "${lib.concatStringsSep "," opts}" 62 | 63 | ''; 64 | }; 65 | 66 | } 67 | -------------------------------------------------------------------------------- /packages/autorandr-configs/default.nix: -------------------------------------------------------------------------------- 1 | { mutate, runCommand, lib, i3, xorg, jq, coreutils }: 2 | let 3 | generated = ./generated-configs; 4 | 5 | move-frames = mutate ./scripts/move-frames.sh { 6 | binpath = lib.makeBinPath [ 7 | i3 jq coreutils 8 | ]; 9 | }; 10 | in runCommand "autorandr-merged-configs" { 11 | postswitch_scripts = [ 12 | move-frames 13 | ]; 14 | } 15 | '' 16 | mkdir -p $out/autorandr 17 | cp -r ${generated}/* $out/autorandr 18 | 19 | mkdir $out/autorandr/postswitch.d 20 | for script in $postswitch_scripts; do 21 | cp -r $script $out/autorandr/postswitch.d 22 | done 23 | chmod +x $out/autorandr/postswitch.d/* 24 | '' 25 | -------------------------------------------------------------------------------- /packages/autorandr-configs/generated-configs/docked-home/config: -------------------------------------------------------------------------------- 1 | output DP1 2 | off 3 | output DP2 4 | off 5 | output DP2-1 6 | off 7 | output DP2-3 8 | off 9 | output VIRTUAL1 10 | off 11 | output eDP1 12 | gamma 1.0:0.714:0.526 13 | mode 1920x1080 14 | pos 0x0 15 | rate 59.96 16 | output DP2-2 17 | gamma 1.0:0.714:0.526 18 | mode 2560x1440 19 | pos 1920x0 20 | primary 21 | rate 59.95 22 | -------------------------------------------------------------------------------- /packages/autorandr-configs/generated-configs/docked-home/setup: -------------------------------------------------------------------------------- 1 | DP2-2 00ffffffffffff0010ac7e40533933350c180103803c2278ea4bb5a7564ba3250a5054a54b008100b300d100714fa9408180d1c00101565e00a0a0a029503020350055502100001a000000ff00374a4e5935343349353339530a000000fc0044454c4c205532373133484d0a000000fd0031561d711c000a20202020202000ce 2 | eDP1 00ffffffffffff0006af2b2800000000001c0104a51d117802ee95a3544c99260f50540000000101010101010101010101010101010152d000a0f0703e803020350025a51000001a000000000000000000000000000000000000000000fe0039304e544880423133335a414e0000000000024103a8011100000b010a20200006 3 | -------------------------------------------------------------------------------- /packages/autorandr-configs/generated-configs/undocked/config: -------------------------------------------------------------------------------- 1 | output DP1 2 | off 3 | output DP2 4 | off 5 | output DP2-1 6 | off 7 | output DP2-2 8 | off 9 | output DP2-3 10 | off 11 | output VIRTUAL1 12 | off 13 | output eDP1 14 | gamma 1.0:0.714:0.526 15 | mode 1920x1080 16 | pos 0x0 17 | primary 18 | rate 59.96 19 | -------------------------------------------------------------------------------- /packages/autorandr-configs/generated-configs/undocked/setup: -------------------------------------------------------------------------------- 1 | eDP1 00ffffffffffff0006af2b2800000000001c0104a51d117802ee95a3544c99260f50540000000101010101010101010101010101010152d000a0f0703e803020350025a51000001a000000000000000000000000000000000000000000fe0039304e544880423133335a414e0000000000024103a8011100000b010a20200006 2 | -------------------------------------------------------------------------------- /packages/autorandr-configs/scripts/move-frames.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eux 4 | 5 | export PATH=@binpath@ 6 | 7 | 8 | function external_space() { 9 | i3-msg -t get_outputs \ 10 | | jq -r '.[] 11 | | select((.name != "eDP1") and .active == true) 12 | | .current_workspace' 13 | } 14 | 15 | # When plugging in the external monitor, i3 will always give it a 16 | # workspace, with nothing on it. Figure out what it is, so we can use 17 | # it as a jumping off point to access other workspaces on that monitor 18 | i=0 19 | while : ; do 20 | monitor_space="$(external_space)" 21 | 22 | if [ "$monitor_space" == "" ]; then 23 | if [ $i -gt 30 ]; then 24 | echo "failed to find the new monitor :(" 25 | exit 1 26 | fi 27 | i=$((i + 1)) 28 | sleep .5; 29 | else 30 | break 31 | fi 32 | done 33 | 34 | # Find two unused workspaces which we can use as "scratch" workspaces, 35 | # one for each display 36 | readonly max_workspace=$(i3-msg -t get_workspaces | jq '.[] .num' | sort -nr | uniq | head -n1) 37 | readonly laptop_scratch_workspace=$((max_workspace + 1)) 38 | readonly monitor_scratch_workspace=$((laptop_scratch_workspace + 1)) 39 | 40 | function move_to_other_monitor() { 41 | 42 | source_workspace="$1" 43 | 44 | # Create an empty scratch workspace on the monitor side, first by 45 | # moving the focus to the monitor side, then jumping to a new 46 | # workspace (the scratch workspace) on the monitor 47 | echo "workspace $monitor_space"; 48 | echo "workspace $monitor_scratch_workspace"; 49 | 50 | # Return to the source workspace which we're moving to the monitor 51 | echo "workspace $source_workspace"; 52 | 53 | # Select all of the windows on the source... a bit janky-like, but 54 | # since I3 supports nested containers of windows, focus on parents 55 | # a few times to "ensure" we're at the top. I only use like 2 max 56 | # so this should be fine. 57 | echo "focus parent"; 58 | echo "focus parent"; 59 | echo "focus parent"; 60 | echo "focus parent"; 61 | echo "focus parent"; 62 | 63 | # Move all the windows to the scratch space on the monitor, 64 | # so now the laptop is still on workspace SOURCE but all the 65 | # windows from SOURCE are now on the monitor's SCRATCH 66 | echo "move container to workspace $monitor_scratch_workspace"; 67 | 68 | # Leave the source workspace on the laptop 69 | # Now, nothing should be on the SOURCE workspace's number, 70 | # allowing it to be recreated on the monitor side 71 | echo "workspace $laptop_scratch_workspace" 72 | 73 | # Focus on the monitor's SCRATCH workspace so that the next `move` 74 | # command will create the SOURCE workspace again on the monitor 75 | echo "workspace $monitor_scratch_workspace" 76 | 77 | # Select everything on the scratch workspace 78 | echo "focus parent"; 79 | echo "focus parent"; 80 | echo "focus parent"; 81 | echo "focus parent"; 82 | echo "focus parent"; 83 | 84 | # move them to the SOURCE workspace, which will be allocated on 85 | # the monitor 86 | echo "move container to workspace $source_workspace"; 87 | 88 | # focus back again in to the SOURCE workspace 89 | echo "workspace $source_workspace" 90 | } 91 | 92 | function srcs() { 93 | i3-msg -t get_workspaces | jq -r '.[] | select(.output == "eDP1") | .num' 94 | } 95 | 96 | for space in $(srcs); do 97 | i3-msg "$(move_to_other_monitor "$space" | tr '\n' ';')" 98 | done 99 | -------------------------------------------------------------------------------- /packages/autorandr-configs/service.nix: -------------------------------------------------------------------------------- 1 | { pkgs, ... }: { 2 | # this never worked 3 | #services.udev.extraRules = '' 4 | # ACTION=="change", SUBSYSTEM=="drm" TAG+="systemd" 5 | #''; 6 | #, ENV{SYSTEMD_USER_WANTS}="hello.service" 7 | #, KERNEL=="card0-DP-2", 8 | 9 | systemd.user.targets.docked = { 10 | wants = [ "autorandr@docked-home.service" ]; 11 | }; 12 | 13 | systemd.user.targets.undocked = { 14 | wants = [ "autorandr@undocked.service" ]; 15 | }; 16 | 17 | systemd.user.services."autorandr@" = { 18 | description = "Autorandr execution hook"; 19 | 20 | serviceConfig = { 21 | StartLimitInterval = 5; 22 | StartLimitBurst = 1; 23 | ExecStart = "${pkgs.autorandr}/bin/autorandr -l %i"; 24 | Type = "oneshot"; 25 | RemainAfterExit = false; 26 | Environment = [ 27 | "XDG_CONFIG_HOME=${pkgs.autorandr-configs}" 28 | "XDG_CONFIG_DIRS=" 29 | ]; 30 | }; 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /packages/b612-font/default.nix: -------------------------------------------------------------------------------- 1 | { stdenv, fetchgit }: 2 | stdenv.mkDerivation { 3 | name = "b612-font-2019-01-21"; 4 | 5 | src = fetchgit { 6 | url = "git://git.polarsys.org/gitroot/b612/b612.git"; 7 | rev = "bd14fde2544566e620eab106eb8d6f2b7fb1347e"; 8 | sha256 = "1w1w9za599w3asmdkhng9amb9w0riq6mg400p43w1qnj0zqazy3d"; 9 | }; 10 | 11 | buildPhase = ":"; 12 | 13 | installPhase = '' 14 | mkdir -p $out/share/fonts 15 | cp ./TTF/*.ttf $out/share/fonts 16 | ''; 17 | 18 | meta = { 19 | homepage = "http://b612-font.com/"; 20 | platforms = stdenv.lib.platforms.all; 21 | license = stdenv.lib.licenses.epl10; 22 | maintainers = [ stdenv.lib.maintainers.grahamc ]; 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /packages/backlight-locker/backlight.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eux 4 | 5 | PATH="@light@/bin/:@bc@/bin/" 6 | 7 | CURPCT=$(light) 8 | echo "CUR: $CURPCT" 9 | 10 | 11 | 12 | if [ "$1" = "up" ]; then 13 | TO=$(echo "$CURPCT / 0.3" | bc) 14 | light -S $TO; 15 | else 16 | TO=$(echo "$CURPCT * 0.3" | bc) 17 | light -S $TO; 18 | fi 19 | 20 | printf "now: %s\n" "$(light)" 21 | -------------------------------------------------------------------------------- /packages/backlight-locker/default.nix: -------------------------------------------------------------------------------- 1 | { mutate, light, bc, coreutils }: 2 | mutate ./backlight.sh { 3 | inherit bc light coreutils; 4 | } 5 | -------------------------------------------------------------------------------- /packages/backlight/backlight.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eu 4 | 5 | PATH=":" 6 | 7 | CURPCT=$(light) 8 | echo "CUR: $CURPCT" 9 | 10 | if [ "$1" = "up" ]; then 11 | CMP=">=" 12 | else 13 | CMP=">" 14 | fi 15 | 16 | echo "CMP: $CMP" 17 | 18 | if [ $(echo "$CURPCT $CMP 30" | bc) -eq 1 ]; then 19 | incr=10; 20 | elif [ $(echo "$CURPCT $CMP 5" | bc) -eq 1 ]; then 21 | incr=5 22 | else 23 | incr=1 24 | fi 25 | echo "incr: $incr" 26 | 27 | if [ $(echo "$CURPCT >= 100" | bc) -eq 1 ] && [ "$1" = "up" ]; then 28 | # Don't go up! 29 | incr=0 30 | fi 31 | echo "protected incr: $incr" 32 | 33 | if [ "$1" = "up" ]; then 34 | echo "inc" 35 | light -A $incr; 36 | else 37 | echo "dec" 38 | light -U $incr; 39 | fi 40 | -------------------------------------------------------------------------------- /packages/backlight/default.nix: -------------------------------------------------------------------------------- 1 | { resholve, mutate, light, bc, coreutils }: 2 | resholve { 3 | src = ./backlight.sh; 4 | inputs = [ bc light coreutils ]; 5 | } 6 | -------------------------------------------------------------------------------- /packages/bash-config/bashrc: -------------------------------------------------------------------------------- 1 | shopt -s histappend 2 | -------------------------------------------------------------------------------- /packages/bash-config/default.nix: -------------------------------------------------------------------------------- 1 | { mutate }: 2 | mutate ./bashrc {} 3 | -------------------------------------------------------------------------------- /packages/default.nix: -------------------------------------------------------------------------------- 1 | (import { overlays = [ (import ./overlay.nix { secrets = import ../secrets.nix; }) ]; }) 2 | -------------------------------------------------------------------------------- /packages/did-graham-commit-his-repos/check.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Redirect all stdout output to stderr 4 | # but create a third pipe which lets us print to stdout 5 | # 6 | # If this program were to run after the execs: 7 | # 8 | # echo "stdout" >&1 9 | # echo "stderr" >&2 10 | # echo "third" >&3 11 | # 12 | # "stdout" and "stderr" would go to stderr, and "third" 13 | # would go to stdout. 14 | 15 | set -euo pipefail 16 | 17 | exec 3>&1 18 | exec 1>&2 19 | 20 | emit() { 21 | echo "$@" >&3 22 | } 23 | 24 | no_lines() { 25 | lines=$(cat | wc -l) 26 | [ "$lines" -eq 0 ] 27 | } 28 | 29 | main() { 30 | PATH=@git@/bin:@coreutils@/bin:$PATH 31 | repo=$(dirname "$1") 32 | 33 | if [ "$(basename "$1")" != ".git" ]; then 34 | emit "not .git: $1" 35 | exit 1 36 | fi 37 | 38 | export GIT_DIR="$1" 39 | export GIT_WORK_TREE="$repo" 40 | 41 | flags="" 42 | flag() { 43 | if [ "x$flags" = "x" ]; then 44 | flags="$1" 45 | else 46 | flags="$1,$flags" 47 | fi 48 | } 49 | 50 | if ! git diff --exit-code --quiet HEAD --; then 51 | flag "dirty" 52 | fi 53 | 54 | if ! git ls-files --others --exclude-standard | no_lines; then 55 | flag "untracked" 56 | fi 57 | 58 | if [ "x$flags" != "x" ]; then 59 | emit "$flags $GIT_WORK_TREE" 60 | fi 61 | } 62 | main "$@" 63 | -------------------------------------------------------------------------------- /packages/did-graham-commit-his-repos/default.nix: -------------------------------------------------------------------------------- 1 | { stdenv, mutate, shellcheck, findutils, coreutils, gnused, git }: 2 | stdenv.mkDerivation rec { 3 | name = "did-graham-commit-his-repos"; 4 | buildInputs = [ shellcheck ]; 5 | 6 | src = mutate ./summary.sh { inherit checker findutils coreutils gnused; }; 7 | checker = mutate ./check.sh { inherit coreutils git; }; 8 | 9 | unpackPhase = '' 10 | cp $src ./ 11 | ''; 12 | 13 | buildPhase = '' 14 | shellcheck $src $checker 15 | ''; 16 | 17 | installPhase = '' 18 | cp $src $out 19 | ''; 20 | } 21 | -------------------------------------------------------------------------------- /packages/did-graham-commit-his-repos/service.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | { 3 | systemd.user.timers.did-graham-commit-his-repos = { 4 | description = "Check if graham is being lazy about committing"; 5 | partOf = [ "did-graham-commit-his-repos.service" ]; 6 | wantedBy = [ "graphical-session.target" ]; 7 | timerConfig.OnCalendar = "*:0/20"; 8 | }; 9 | 10 | systemd.user.services.did-graham-commit-his-repos = { 11 | enable = true; 12 | wantedBy = [ "graphical-session.target" ]; 13 | 14 | unitConfig = { 15 | ConditionACPower = true; 16 | ConditionGroup = "users"; 17 | }; 18 | 19 | script = '' 20 | mkdir -p "''${XDG_CACHE_HOME:-$HOME/.cache}/shell-warning" 21 | ${pkgs.did-graham-commit-his-repos} $HOME /etc/nixos > "''${XDG_CACHE_HOME:-$HOME/.cache}/shell-warning/git" 22 | ''; 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /packages/did-graham-commit-his-repos/summary.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | PATH=@findutils@/bin:@coreutils@/bin:@gnused@/bin 4 | 5 | lines=$(find "$@" \ 6 | -mindepth 1 \ 7 | -type d -name .git -print0 \ 8 | -o -name '.*' -prune \ 9 | | xargs -0 -n1 -P"$(nproc)" @checker@ 2> /dev/null \ 10 | | sed -e 's/^/ - /') 11 | 12 | if [ "x$lines" != "x" ]; then 13 | echo "The following repositories have uncommitted stuff:" 14 | echo "$lines" 15 | fi 16 | -------------------------------------------------------------------------------- /packages/direnv-hook/default.nix: -------------------------------------------------------------------------------- 1 | { mutate, direnv }: 2 | mutate ./zshrc.local { 3 | inherit direnv; 4 | } 5 | -------------------------------------------------------------------------------- /packages/direnv-hook/zshrc.local: -------------------------------------------------------------------------------- 1 | export PATH="$PATH:@direnv@/bin/" 2 | eval "$(direnv hook zsh)" 3 | -------------------------------------------------------------------------------- /packages/dunst/default.nix: -------------------------------------------------------------------------------- 1 | { mutate, dmenu }: 2 | mutate ./dunstrc { 3 | inherit dmenu; 4 | i3status_conf = ./dunstrc; 5 | } 6 | -------------------------------------------------------------------------------- /packages/dunst/dunstrc: -------------------------------------------------------------------------------- 1 | [global] 2 | font = Monospace 14 3 | 4 | # The format of the message. Possible variables are: 5 | # %a appname 6 | # %s summary 7 | # %b body 8 | # %i iconname (including its path) 9 | # %I iconname (without its path) 10 | # %p progress value if set ([ 0%] to [100%]) or nothing 11 | format = "[%a] %s \n %b" 12 | 13 | # Sort messages by urgency 14 | sort = yes 15 | 16 | # Show how many messages are currently hidden (because of geometry) 17 | indicate_hidden = yes 18 | 19 | # alignment of message text. 20 | # Possible values are "left", "center" and "right" 21 | alignment = left 22 | 23 | # The frequency with wich text that is longer than the notification 24 | # window allows bounces back and forth. 25 | # This option conflicts with 'word_wrap'. 26 | # Set to 0 to disable 27 | bounce_freq = 1 28 | 29 | # show age of message if message is older than show_age_threshold seconds. 30 | # set to -1 to disable 31 | show_age_threshold = 40 32 | 33 | # split notifications into multiple lines if they don't fit into geometry 34 | word_wrap = yes 35 | 36 | # ignore newlines '\n' in notifications 37 | ignore_newline = no 38 | 39 | 40 | # the geometry of the window 41 | # geometry [{width}]x{height}][+/-{x}+/-{y}] 42 | # The geometry of the message window. 43 | # The height is measured in number of notifications everything else in pixels. If the width 44 | # is omitted but the height is given ("-geometry x2"), the message window 45 | # expands over the whole screen (dmenu-like). If width is 0, 46 | # the window expands to the longest message displayed. 47 | # A positive x is measured from the left, a negative from the 48 | # right side of the screen. Y is measured from the top and down respectevly. 49 | # The width can be negative. In this case the actual width is the 50 | # screen width minus the width defined in within the geometry option. 51 | geometry = "400x7-0+50" 52 | 53 | # The transparency of the window. range: [0; 100] 54 | # This option will only work if a compositing windowmanager is present (e.g. xcompmgr, compiz, etc..) 55 | transparency = 20 56 | 57 | # Don't remove messages, if the user is idle (no mouse or keyboard input) 58 | # for longer than idle_threshold seconds. 59 | # Set to 0 to disable. 60 | idle_threshold = 40 61 | 62 | # Which monitor should the notifications be displayed on. 63 | monitor = 0 64 | 65 | # Display notification on focused monitor. Possible modes are: 66 | # mouse: follow mouse pointer 67 | # keyboard: follow window with keyboard focus 68 | # none: don't follow anything 69 | # 70 | # "keyboard" needs a windowmanager that exports the _NET_ACTIVE_WINDOW property. 71 | # This should be the case for almost all modern windowmanagers. 72 | # 73 | # If this option is set to mouse or keyboard, the monitor option will be 74 | # ignored. 75 | follow = mouse 76 | 77 | # should a notification popped up from history be sticky or 78 | # timeout as if it would normally do. 79 | sticky_history = yes 80 | 81 | # The height of a single line. If the height is smaller than the font height, 82 | # it will get raised to the font height. 83 | # This adds empty space above and under the text. 84 | line_height = 20 85 | 86 | # Draw a line of 'separatpr_height' pixel height between two notifications. 87 | # Set to 0 to disable 88 | separator_height = 1; 89 | 90 | # padding between text and separator 91 | padding = 8 92 | 93 | # horizontal padding 94 | horizontal_padding = 8 95 | 96 | # Define a color for the separator. 97 | # possible values are: 98 | # * auto: dunst tries to find a color fitting to the background 99 | # * foreground: use the same color as the foreground 100 | # * frame: use the same color as the frame. 101 | # * anything else will be interpreted as a X color 102 | separator_color = auto 103 | 104 | # print a notification on startup 105 | # This is mainly for error detection, since dbus (re-)starts dunst 106 | # automatically after a crash. 107 | startup_notification = true 108 | 109 | # dmenu path 110 | dmenu = %dmenu%/bin/dmenu -p dunst: 111 | 112 | # browser for opening urls in context menu 113 | browser = firefox -new-tab 114 | 115 | [frame] 116 | width = 0 117 | Color = "#aaaaaa" 118 | 119 | [shortcuts] 120 | # shortcuts are specified as [modifier+][modifier+]...key 121 | # available modifiers are 'ctrl', 'mod1' (the alt-key), 'mod2', 'mod3' 122 | # and 'mod4' (windows-key) 123 | # xev might be helpful to find names for keys 124 | 125 | # close notification 126 | close = ctrl+space 127 | 128 | # close all notifications 129 | close_all = ctrl+shift+space 130 | 131 | # redisplay last message(s) 132 | # On the US keyboard layout 'grave' is normally above TAB and left of '1'. 133 | history = ctrl+grave 134 | 135 | # context menu 136 | context = ctrl+shift+period 137 | 138 | [urgency_low] 139 | # IMPORTANT: colors have to be defined in quotation marks. 140 | # Otherwise the '#' and following would be interpreted as a comment. 141 | background = "#485F6E" 142 | foreground = "#CCCCCC" 143 | -------------------------------------------------------------------------------- /packages/emacs/default.el: -------------------------------------------------------------------------------- 1 | (setq max-lisp-eval-depth 4000) 2 | (setq max-specpdl-size 5000) 3 | 4 | ;; Added because pgtk branch gets this wrong 5 | ;; https://www.gnu.org/software/emacs/manual/html_node/emacs/DEL-Does-Not-Delete.html 6 | (normal-erase-is-backspace-mode 1) 7 | (add-hook 'tty-setup-hook 'graham-in-tty) 8 | (defun graham-in-tty () 9 | (normal-erase-is-backspace-mode 0) 10 | ) 11 | 12 | 13 | 14 | (global-set-key (kbd "") 'end-of-line) 15 | (global-set-key (kbd "") 'beginning-of-line) 16 | (global-set-key (kbd " ") 'dabbrev-expand) 17 | (column-number-mode) 18 | 19 | 20 | (setq-default sentence-end-double-space nil) 21 | 22 | (set-face-background 'region "LightBlue") 23 | 24 | (add-hook 'before-save-hook 'delete-trailing-whitespace) 25 | (prefer-coding-system 'utf-8) 26 | (set-default-coding-systems 'utf-8) 27 | (set-terminal-coding-system 'utf-8) 28 | (set-keyboard-coding-system 'utf-8) 29 | (set-language-environment 'utf-8) 30 | 31 | (defvar backup-dir (expand-file-name "~/.emacs.d/backup/")) 32 | (defvar autosave-dir (expand-file-name "~/.emacs.d/autosave/")) 33 | (setq backup-directory-alist (list (cons ".*" backup-dir)) 34 | auto-save-list-file-prefix autosave-dir 35 | auto-save-file-name-transforms `((".*" ,autosave-dir t))) 36 | 37 | 38 | ;; after this is less minimal 39 | 40 | 41 | (setq user-mail-address "graham@grahamc.com" 42 | graphviz-dot-dot-program "@graphviz@/bin/dot" 43 | graphviz-dot-view-command "@graphviz@/bin/dotty" 44 | graphviz-dot-preview-extension "svg" 45 | graphviz-dot-auto-preview-on-save t 46 | user-full-name "Graham Christensen" 47 | nix-indent-function 'nix-indent-line 48 | ) 49 | 50 | (setq-default indent-tabs-mode nil 51 | ispell-program-name "@spelling@/bin/hunspell" 52 | ) 53 | 54 | (defun grahams-loader-after-plugins () 55 | (define-globalized-minor-mode global-fci-mode fci-mode (lambda () (fci-mode 1))) 56 | (global-fci-mode 1) 57 | (editorconfig-mode 1) 58 | (auto-fill-mode 1) 59 | (require 'direnv) 60 | (direnv-mode) 61 | (global-flycheck-mode) 62 | 63 | (require 'yasnippet) 64 | (yas-global-mode 1) 65 | 66 | ;; this stuff was good, but broke after switching to pgtk in 2020-02-18 67 | ;; and I didn't care enough to fix it. Something about the hooks 68 | ;; caused infinite lisp evaluation errors. blah blah blah. 69 | (ivy-mode 1) 70 | (counsel-mode 1) 71 | 72 | (eval-after-load 'rng-loc 73 | '(add-to-list 'rng-schema-locating-files "@schemas@")) 74 | 75 | 76 | (global-set-key (kbd "C-s") 'swiper) 77 | (global-set-key (kbd "M-x") 'counsel-M-x) 78 | (global-set-key (kbd "C-x C-f") 'counsel-find-file) ;; 'counsel-projectile-find-file) 79 | (global-set-key (kbd " f") 'counsel-describe-function) 80 | (global-set-key (kbd " v") 'counsel-describe-variable) 81 | (global-set-key (kbd " l") 'counsel-find-library) 82 | (global-set-key (kbd " i") 'counsel-info-lookup-symbol) 83 | (global-set-key (kbd " u") 'counsel-unicode-char) 84 | 85 | (setq ivy-use-virtual-buffers t 86 | ivy-use-selectable-prompt t) 87 | (add-hook 'text-mode-hook 'artbollocks-mode) 88 | 89 | (require 'lsp-ui) 90 | (require 'lsp-mode) 91 | (add-hook 'lsp-mode-hook #'lsp-ui-mode) 92 | ;; (add-hook 'rust-mode-hook #'lsp) 93 | ) 94 | 95 | (add-hook 'after-init-hook #'grahams-loader-after-plugins) 96 | -------------------------------------------------------------------------------- /packages/emacs/default.nix: -------------------------------------------------------------------------------- 1 | { lib, emacsPackagesNg, mutate, msmtp, writeText, docbook5 2 | , graphviz, hunspellWithDicts, hunspellDicts, fetchFromGitHub 3 | , fetchpatch }: 4 | 5 | let 6 | nix-mode-overrides = { 7 | none = x: {}; 8 | 9 | local-clone = oldAttrs: { 10 | src = /home/grahamc/projects/nixos/nix-mode; 11 | }; 12 | 13 | master-floating = oldAttrs: { 14 | src = builtins.fetchGit { 15 | url = "https://github.com/nixos/nix-mode.git"; 16 | ref = "master"; 17 | }; 18 | }; 19 | 20 | master-2019-01-29 = oldAttrs: { 21 | src = builtins.fetchGit { 22 | url = "https://github.com/nixos/nix-mode.git"; 23 | ref = "master"; 24 | rev = "1e53bed4d47c526c71113569f592c82845a17784"; 25 | }; 26 | }; 27 | 28 | etu-master-floating = oldAttrs: { 29 | src = builtins.fetchGit { 30 | url = "https://github.com/etu/nix-mode.git"; 31 | ref = "master"; 32 | }; 33 | }; 34 | }; 35 | in 36 | emacsPackagesNg.emacsWithPackages (epkgs: ( [] 37 | ++ (lib.optionals true (with epkgs.melpaPackages; [ 38 | (nix-mode.overrideAttrs nix-mode-overrides.master-2019-01-29) 39 | artbollocks-mode 40 | counsel 41 | counsel-projectile 42 | diff-hl 43 | direnv 44 | editorconfig 45 | elixir-mode 46 | elm-mode 47 | erlang 48 | fill-column-indicator 49 | flycheck 50 | ghc 51 | go-mode 52 | graphviz-dot-mode 53 | hcl-mode 54 | ivy 55 | js2-mode 56 | json-mode 57 | magit 58 | markdown-mode 59 | php-mode 60 | projectile 61 | python-mode 62 | rust-mode 63 | super-save 64 | swiper 65 | yaml-mode 66 | yasnippet 67 | ])) 68 | ++ (lib.optionals (true) (with emacsPackagesNg; [ 69 | lsp-mode 70 | lsp-ui 71 | wsd-mode 72 | ])) 73 | ++ (lib.optionals (true) [ 74 | (emacsPackagesNg.trivialBuild { 75 | pname = "grahams-mode"; 76 | version = "1970-01-01"; 77 | src = mutate ./default.el { 78 | inherit msmtp graphviz; 79 | spelling = hunspellWithDicts ([hunspellDicts.en-us]); 80 | 81 | schemas = writeText "schemas.xml" '' 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | ''; 90 | }; 91 | }) 92 | ]) 93 | )) 94 | -------------------------------------------------------------------------------- /packages/emacs/minimal.el: -------------------------------------------------------------------------------- 1 | 2 | ;; Added because pgtk branch gets this wrong 3 | ;; https://www.gnu.org/software/emacs/manual/html_node/emacs/DEL-Does-Not-Delete.html 4 | (normal-erase-is-backspace-mode 1) 5 | 6 | 7 | (global-set-key (kbd "") 'end-of-line) 8 | (global-set-key (kbd "") 'beginning-of-line) 9 | (global-set-key (kbd " ") 'dabbrev-expand) 10 | (column-number-mode) 11 | 12 | 13 | (setq-default sentence-end-double-space nil) 14 | 15 | (set-face-background 'region "LightBlue") 16 | 17 | (add-hook 'before-save-hook 'delete-trailing-whitespace) 18 | (prefer-coding-system 'utf-8) 19 | (set-default-coding-systems 'utf-8) 20 | (set-terminal-coding-system 'utf-8) 21 | (set-keyboard-coding-system 'utf-8) 22 | (set-language-environment 'utf-8) 23 | 24 | (defvar backup-dir (expand-file-name "~/.emacs.d/backup/")) 25 | (defvar autosave-dir (expand-file-name "~/.emacs.d/autosave/")) 26 | (setq backup-directory-alist (list (cons ".*" backup-dir)) 27 | auto-save-list-file-prefix autosave-dir 28 | auto-save-file-name-transforms `((".*" ,autosave-dir t))) 29 | -------------------------------------------------------------------------------- /packages/freeze-focused/default.nix: -------------------------------------------------------------------------------- 1 | { resholve, coreutils, utillinux, jq, systemd, sway, gawk }: 2 | # Freeze the cgroup of the focused window 3 | resholve { 4 | src = ./freeze.sh; 5 | inputs = [ coreutils utillinux jq systemd sway gawk ]; 6 | } 7 | 8 | -------------------------------------------------------------------------------- /packages/freeze-focused/freeze.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eux 4 | 5 | pid=$(swaymsg -t get_tree | jq '.. | select(.type?) | select(.focused==true).pid') 6 | cgroup=$(cat "/proc/${pid}/cgroup" | cut -d: -f3- | rev | cut -d/ -f1 | rev) 7 | 8 | state=$(systemctl --user show "$cgroup" | \ 9 | awk -v FS== '$1 == "FreezerState" { print $2; }') 10 | 11 | if [ "x$state" = "xfrozen" ]; then 12 | echo "Thawing $cgroup" 13 | systemctl --user thaw "$cgroup" 14 | elif [ "x$state" = "xrunning" ]; then 15 | echo "Freezing $cgroup" 16 | systemctl --user freeze "$cgroup" 17 | else 18 | echo "Unknown state: $state" 19 | exit 1 20 | fi 21 | 22 | 23 | -------------------------------------------------------------------------------- /packages/gitconfig/default.nix: -------------------------------------------------------------------------------- 1 | { mutate, gnupg }: 2 | mutate ./gitconfig { 3 | inherit gnupg; 4 | 5 | gitattributes = ./gitattributes; 6 | gitignore = ./gitignore; 7 | } 8 | -------------------------------------------------------------------------------- /packages/gitconfig/gitattributes: -------------------------------------------------------------------------------- 1 | makefile text whitespace=-tab-in-indent,trailing-space,tabwidth=4 2 | Makefile text whitespace=-tab-in-indent,trailing-space,tabwidth=4 3 | -------------------------------------------------------------------------------- /packages/gitconfig/gitconfig: -------------------------------------------------------------------------------- 1 | [advice] 2 | statusHints = false 3 | 4 | [color] 5 | branch = auto 6 | diff = auto 7 | interactive = auto 8 | status = auto 9 | ui = auto 10 | 11 | [diff] 12 | algorithm = patience 13 | 14 | [core] 15 | attributesfile = @gitattributes@ 16 | excludesfile = @gitignore@ 17 | whitespace = -blank-at-eof, tab-in-indent 18 | 19 | [help] 20 | autocorrect = 1 21 | 22 | [user] 23 | email = graham@grahamc.com 24 | name = Graham Christensen 25 | signingkey = FE918C3A98C1030F 26 | 27 | [transfer] 28 | fsckObjects = true 29 | 30 | [fetch] 31 | fsckObjects = true 32 | 33 | [receive] 34 | fsckObjects = true 35 | 36 | [gpg] 37 | program = @gnupg@/bin/gpg 38 | 39 | [commit] 40 | gpgsign = true 41 | -------------------------------------------------------------------------------- /packages/gitconfig/gitignore: -------------------------------------------------------------------------------- 1 | *.sw* 2 | .DS_Store 3 | .#* 4 | \#*# 5 | *~ 6 | result 7 | result-* 8 | -------------------------------------------------------------------------------- /packages/gnupgconfig/default.nix: -------------------------------------------------------------------------------- 1 | {}: 2 | { 3 | gpgconf = ./gpg.conf; 4 | scdaemonconf = ./scdaemon.conf; 5 | } 6 | -------------------------------------------------------------------------------- /packages/gnupgconfig/gpg.conf: -------------------------------------------------------------------------------- 1 | fixed-list-mode 2 | keyid-format 0xlong 3 | use-agent 4 | verify-options show-uid-validity 5 | list-options show-uid-validity 6 | cert-digest-algo SHA256 7 | no-emit-version 8 | require-cross-certification 9 | keyserver hkp://keys.gnupg.net -------------------------------------------------------------------------------- /packages/gnupgconfig/scdaemon.conf: -------------------------------------------------------------------------------- 1 | log-file /home/grahamc/.gnupg/scdaemon.log 2 | verbose 3 | debug ipc,cardio 4 | card-timeout 0 5 | -------------------------------------------------------------------------------- /packages/guiduck/.envrc: -------------------------------------------------------------------------------- 1 | eval "$(lorri direnv)" -------------------------------------------------------------------------------- /packages/guiduck/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /packages/guiduck/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "ansi_term" 5 | version = "0.11.0" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" 8 | dependencies = [ 9 | "winapi", 10 | ] 11 | 12 | [[package]] 13 | name = "atty" 14 | version = "0.2.14" 15 | source = "registry+https://github.com/rust-lang/crates.io-index" 16 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 17 | dependencies = [ 18 | "hermit-abi", 19 | "libc", 20 | "winapi", 21 | ] 22 | 23 | [[package]] 24 | name = "bitflags" 25 | version = "1.2.1" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" 28 | 29 | [[package]] 30 | name = "byteorder" 31 | version = "1.3.4" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" 34 | 35 | [[package]] 36 | name = "cc" 37 | version = "1.0.61" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "ed67cbde08356238e75fc4656be4749481eeffb09e19f320a25237d5221c985d" 40 | 41 | [[package]] 42 | name = "cfg-if" 43 | version = "0.1.10" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 46 | 47 | [[package]] 48 | name = "clap" 49 | version = "2.33.3" 50 | source = "registry+https://github.com/rust-lang/crates.io-index" 51 | checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" 52 | dependencies = [ 53 | "ansi_term", 54 | "atty", 55 | "bitflags", 56 | "strsim", 57 | "textwrap", 58 | "unicode-width", 59 | "vec_map", 60 | ] 61 | 62 | [[package]] 63 | name = "derivative" 64 | version = "2.1.1" 65 | source = "registry+https://github.com/rust-lang/crates.io-index" 66 | checksum = "cb582b60359da160a9477ee80f15c8d784c477e69c217ef2cdd4169c24ea380f" 67 | dependencies = [ 68 | "proc-macro2", 69 | "quote", 70 | "syn", 71 | ] 72 | 73 | [[package]] 74 | name = "enumflags2" 75 | version = "0.6.4" 76 | source = "registry+https://github.com/rust-lang/crates.io-index" 77 | checksum = "83c8d82922337cd23a15f88b70d8e4ef5f11da38dd7cdb55e84dd5de99695da0" 78 | dependencies = [ 79 | "enumflags2_derive", 80 | "serde", 81 | ] 82 | 83 | [[package]] 84 | name = "enumflags2_derive" 85 | version = "0.6.4" 86 | source = "registry+https://github.com/rust-lang/crates.io-index" 87 | checksum = "946ee94e3dbf58fdd324f9ce245c7b238d46a66f00e86a020b71996349e46cce" 88 | dependencies = [ 89 | "proc-macro2", 90 | "quote", 91 | "syn", 92 | ] 93 | 94 | [[package]] 95 | name = "fastrand" 96 | version = "1.4.0" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "ca5faf057445ce5c9d4329e382b2ce7ca38550ef3b73a5348362d5f24e0c7fe3" 99 | dependencies = [ 100 | "instant", 101 | ] 102 | 103 | [[package]] 104 | name = "guiduck" 105 | version = "0.1.0" 106 | dependencies = [ 107 | "clap", 108 | "zbus", 109 | "zvariant", 110 | ] 111 | 112 | [[package]] 113 | name = "hermit-abi" 114 | version = "0.1.17" 115 | source = "registry+https://github.com/rust-lang/crates.io-index" 116 | checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8" 117 | dependencies = [ 118 | "libc", 119 | ] 120 | 121 | [[package]] 122 | name = "instant" 123 | version = "0.1.7" 124 | source = "registry+https://github.com/rust-lang/crates.io-index" 125 | checksum = "63312a18f7ea8760cdd0a7c5aac1a619752a246b833545e3e36d1f81f7cd9e66" 126 | dependencies = [ 127 | "cfg-if", 128 | ] 129 | 130 | [[package]] 131 | name = "libc" 132 | version = "0.2.79" 133 | source = "registry+https://github.com/rust-lang/crates.io-index" 134 | checksum = "2448f6066e80e3bfc792e9c98bf705b4b0fc6e8ef5b43e5889aff0eaa9c58743" 135 | 136 | [[package]] 137 | name = "nix" 138 | version = "0.17.0" 139 | source = "registry+https://github.com/rust-lang/crates.io-index" 140 | checksum = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363" 141 | dependencies = [ 142 | "bitflags", 143 | "cc", 144 | "cfg-if", 145 | "libc", 146 | "void", 147 | ] 148 | 149 | [[package]] 150 | name = "once_cell" 151 | version = "1.4.1" 152 | source = "registry+https://github.com/rust-lang/crates.io-index" 153 | checksum = "260e51e7efe62b592207e9e13a68e43692a7a279171d6ba57abd208bf23645ad" 154 | 155 | [[package]] 156 | name = "proc-macro-crate" 157 | version = "0.1.5" 158 | source = "registry+https://github.com/rust-lang/crates.io-index" 159 | checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" 160 | dependencies = [ 161 | "toml", 162 | ] 163 | 164 | [[package]] 165 | name = "proc-macro2" 166 | version = "1.0.24" 167 | source = "registry+https://github.com/rust-lang/crates.io-index" 168 | checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" 169 | dependencies = [ 170 | "unicode-xid", 171 | ] 172 | 173 | [[package]] 174 | name = "quote" 175 | version = "1.0.7" 176 | source = "registry+https://github.com/rust-lang/crates.io-index" 177 | checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" 178 | dependencies = [ 179 | "proc-macro2", 180 | ] 181 | 182 | [[package]] 183 | name = "scoped-tls" 184 | version = "1.0.0" 185 | source = "registry+https://github.com/rust-lang/crates.io-index" 186 | checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" 187 | 188 | [[package]] 189 | name = "serde" 190 | version = "1.0.117" 191 | source = "registry+https://github.com/rust-lang/crates.io-index" 192 | checksum = "b88fa983de7720629c9387e9f517353ed404164b1e482c970a90c1a4aaf7dc1a" 193 | dependencies = [ 194 | "serde_derive", 195 | ] 196 | 197 | [[package]] 198 | name = "serde_derive" 199 | version = "1.0.117" 200 | source = "registry+https://github.com/rust-lang/crates.io-index" 201 | checksum = "cbd1ae72adb44aab48f325a02444a5fc079349a8d804c1fc922aed3f7454c74e" 202 | dependencies = [ 203 | "proc-macro2", 204 | "quote", 205 | "syn", 206 | ] 207 | 208 | [[package]] 209 | name = "serde_repr" 210 | version = "0.1.6" 211 | source = "registry+https://github.com/rust-lang/crates.io-index" 212 | checksum = "2dc6b7951b17b051f3210b063f12cc17320e2fe30ae05b0fe2a3abb068551c76" 213 | dependencies = [ 214 | "proc-macro2", 215 | "quote", 216 | "syn", 217 | ] 218 | 219 | [[package]] 220 | name = "strsim" 221 | version = "0.8.0" 222 | source = "registry+https://github.com/rust-lang/crates.io-index" 223 | checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" 224 | 225 | [[package]] 226 | name = "syn" 227 | version = "1.0.45" 228 | source = "registry+https://github.com/rust-lang/crates.io-index" 229 | checksum = "ea9c5432ff16d6152371f808fb5a871cd67368171b09bb21b43df8e4a47a3556" 230 | dependencies = [ 231 | "proc-macro2", 232 | "quote", 233 | "unicode-xid", 234 | ] 235 | 236 | [[package]] 237 | name = "textwrap" 238 | version = "0.11.0" 239 | source = "registry+https://github.com/rust-lang/crates.io-index" 240 | checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" 241 | dependencies = [ 242 | "unicode-width", 243 | ] 244 | 245 | [[package]] 246 | name = "toml" 247 | version = "0.5.7" 248 | source = "registry+https://github.com/rust-lang/crates.io-index" 249 | checksum = "75cf45bb0bef80604d001caaec0d09da99611b3c0fd39d3080468875cdb65645" 250 | dependencies = [ 251 | "serde", 252 | ] 253 | 254 | [[package]] 255 | name = "unicode-width" 256 | version = "0.1.8" 257 | source = "registry+https://github.com/rust-lang/crates.io-index" 258 | checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" 259 | 260 | [[package]] 261 | name = "unicode-xid" 262 | version = "0.2.1" 263 | source = "registry+https://github.com/rust-lang/crates.io-index" 264 | checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" 265 | 266 | [[package]] 267 | name = "vec_map" 268 | version = "0.8.2" 269 | source = "registry+https://github.com/rust-lang/crates.io-index" 270 | checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" 271 | 272 | [[package]] 273 | name = "void" 274 | version = "1.0.2" 275 | source = "registry+https://github.com/rust-lang/crates.io-index" 276 | checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" 277 | 278 | [[package]] 279 | name = "winapi" 280 | version = "0.3.9" 281 | source = "registry+https://github.com/rust-lang/crates.io-index" 282 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 283 | dependencies = [ 284 | "winapi-i686-pc-windows-gnu", 285 | "winapi-x86_64-pc-windows-gnu", 286 | ] 287 | 288 | [[package]] 289 | name = "winapi-i686-pc-windows-gnu" 290 | version = "0.4.0" 291 | source = "registry+https://github.com/rust-lang/crates.io-index" 292 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 293 | 294 | [[package]] 295 | name = "winapi-x86_64-pc-windows-gnu" 296 | version = "0.4.0" 297 | source = "registry+https://github.com/rust-lang/crates.io-index" 298 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 299 | 300 | [[package]] 301 | name = "zbus" 302 | version = "1.2.1" 303 | source = "registry+https://github.com/rust-lang/crates.io-index" 304 | checksum = "3a8a1a98eac87778308d7b2725cee6543a13936a3913b98e37fcf8ce9e4362da" 305 | dependencies = [ 306 | "byteorder", 307 | "derivative", 308 | "enumflags2", 309 | "fastrand", 310 | "nix", 311 | "once_cell", 312 | "scoped-tls", 313 | "serde", 314 | "serde_repr", 315 | "zbus_macros", 316 | "zvariant", 317 | ] 318 | 319 | [[package]] 320 | name = "zbus_macros" 321 | version = "1.2.1" 322 | source = "registry+https://github.com/rust-lang/crates.io-index" 323 | checksum = "9ca4d050be67f3b7a29878a6f0788a8dcd100c7297e619dcb91051f94679a8a4" 324 | dependencies = [ 325 | "proc-macro-crate", 326 | "proc-macro2", 327 | "quote", 328 | "syn", 329 | ] 330 | 331 | [[package]] 332 | name = "zvariant" 333 | version = "2.2.0" 334 | source = "registry+https://github.com/rust-lang/crates.io-index" 335 | checksum = "fb79b31a454101beda19e64082dfd9ad59c5ff8afa41e1de1065333105b02740" 336 | dependencies = [ 337 | "byteorder", 338 | "enumflags2", 339 | "serde", 340 | "zvariant_derive", 341 | ] 342 | 343 | [[package]] 344 | name = "zvariant_derive" 345 | version = "2.2.0" 346 | source = "registry+https://github.com/rust-lang/crates.io-index" 347 | checksum = "605bf414a59d93a3d55055e72ea066c5c0bc578ed2227df15c407207b1c780ef" 348 | dependencies = [ 349 | "proc-macro-crate", 350 | "proc-macro2", 351 | "quote", 352 | "syn", 353 | ] 354 | -------------------------------------------------------------------------------- /packages/guiduck/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "guiduck" 3 | version = "0.1.0" 4 | authors = ["Graham Christensen "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [[bin]] 10 | name = "receive" 11 | path = "src/receive.rs" 12 | 13 | [[bin]] 14 | name = "send" 15 | path = "src/send.rs" 16 | 17 | [[bin]] 18 | name = "bogus" 19 | path = "src/bogus.rs" 20 | 21 | [dependencies] 22 | clap = "2.33.1" 23 | zbus = "1.0.0" 24 | zvariant = "2.0.0" 25 | -------------------------------------------------------------------------------- /packages/guiduck/nix/default.nix: -------------------------------------------------------------------------------- 1 | { sources ? import ./sources.nix, config ? {} }: 2 | with 3 | { 4 | overlay = self: super: 5 | { 6 | overlayed = { 7 | niv = import sources.niv {}; 8 | crate2nix = import sources.crate2nix {}; 9 | }; 10 | }; 11 | }; 12 | import sources.nixpkgs { 13 | overlays = [ overlay ]; 14 | inherit config; 15 | } 16 | -------------------------------------------------------------------------------- /packages/guiduck/nix/sources.json: -------------------------------------------------------------------------------- 1 | { 2 | "crate2nix": { 3 | "branch": "master", 4 | "description": "nix build file generator for rust crates", 5 | "homepage": "", 6 | "owner": "kolloch", 7 | "repo": "crate2nix", 8 | "rev": "a861e48206beb66937b2d3ae9d1fae47f82e2270", 9 | "sha256": "03y8h9x4805pkrqk46ggf4ynsd237w8yqgi5pd35amsm34nc1mwm", 10 | "type": "tarball", 11 | "url": "https://github.com/kolloch/crate2nix/archive/a861e48206beb66937b2d3ae9d1fae47f82e2270.tar.gz", 12 | "url_template": "https://github.com///archive/.tar.gz" 13 | }, 14 | "niv": { 15 | "branch": "master", 16 | "description": "Easy dependency management for Nix projects", 17 | "homepage": "https://github.com/nmattia/niv", 18 | "owner": "nmattia", 19 | "repo": "niv", 20 | "rev": "ab9cc41caf44d1f1d465d8028e4bc0096fd73238", 21 | "sha256": "17k52n8zwp832cqifsc4458mhy4044wmk22f807171hf6p7l4xvr", 22 | "type": "tarball", 23 | "url": "https://github.com/nmattia/niv/archive/ab9cc41caf44d1f1d465d8028e4bc0096fd73238.tar.gz", 24 | "url_template": "https://github.com///archive/.tar.gz" 25 | }, 26 | "nixpkgs": { 27 | "branch": "nixos-unstable", 28 | "description": "A read-only mirror of NixOS/nixpkgs tracking the released channels. Send issues and PRs to", 29 | "homepage": "https://github.com/NixOS/nixpkgs", 30 | "owner": "NixOS", 31 | "repo": "nixpkgs-channels", 32 | "rev": "28fce082c8ca1a8fb3dfac5c938829e51fb314c8", 33 | "sha256": "1pzmqgby1g9ypdn6wgxmbhp6hr55dhhrccn67knrpy93vib9wf8r", 34 | "type": "tarball", 35 | "url": "https://github.com/NixOS/nixpkgs-channels/archive/28fce082c8ca1a8fb3dfac5c938829e51fb314c8.tar.gz", 36 | "url_template": "https://github.com///archive/.tar.gz" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/guiduck/nix/sources.nix: -------------------------------------------------------------------------------- 1 | # This file has been generated by Niv. 2 | 3 | let 4 | 5 | # 6 | # The fetchers. fetch_ fetches specs of type . 7 | # 8 | 9 | fetch_file = pkgs: spec: 10 | if spec.builtin or true then 11 | builtins_fetchurl { inherit (spec) url sha256; } 12 | else 13 | pkgs.fetchurl { inherit (spec) url sha256; }; 14 | 15 | fetch_tarball = pkgs: spec: 16 | if spec.builtin or true then 17 | builtins_fetchTarball { inherit (spec) url sha256; } 18 | else 19 | pkgs.fetchzip { inherit (spec) url sha256; }; 20 | 21 | fetch_git = spec: 22 | builtins.fetchGit { url = spec.repo; inherit (spec) rev ref; }; 23 | 24 | fetch_builtin-tarball = spec: 25 | builtins.trace 26 | '' 27 | WARNING: 28 | The niv type "builtin-tarball" will soon be deprecated. You should 29 | instead use `builtin = true`. 30 | 31 | $ niv modify -a type=tarball -a builtin=true 32 | '' 33 | builtins_fetchTarball { inherit (spec) url sha256; }; 34 | 35 | fetch_builtin-url = spec: 36 | builtins.trace 37 | '' 38 | WARNING: 39 | The niv type "builtin-url" will soon be deprecated. You should 40 | instead use `builtin = true`. 41 | 42 | $ niv modify -a type=file -a builtin=true 43 | '' 44 | (builtins_fetchurl { inherit (spec) url sha256; }); 45 | 46 | # 47 | # Various helpers 48 | # 49 | 50 | # The set of packages used when specs are fetched using non-builtins. 51 | mkPkgs = sources: 52 | let 53 | sourcesNixpkgs = 54 | import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) {}; 55 | hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath; 56 | hasThisAsNixpkgsPath = == ./.; 57 | in 58 | if builtins.hasAttr "nixpkgs" sources 59 | then sourcesNixpkgs 60 | else if hasNixpkgsPath && ! hasThisAsNixpkgsPath then 61 | import {} 62 | else 63 | abort 64 | '' 65 | Please specify either (through -I or NIX_PATH=nixpkgs=...) or 66 | add a package called "nixpkgs" to your sources.json. 67 | ''; 68 | 69 | # The actual fetching function. 70 | fetch = pkgs: name: spec: 71 | 72 | if ! builtins.hasAttr "type" spec then 73 | abort "ERROR: niv spec ${name} does not have a 'type' attribute" 74 | else if spec.type == "file" then fetch_file pkgs spec 75 | else if spec.type == "tarball" then fetch_tarball pkgs spec 76 | else if spec.type == "git" then fetch_git spec 77 | else if spec.type == "builtin-tarball" then fetch_builtin-tarball spec 78 | else if spec.type == "builtin-url" then fetch_builtin-url spec 79 | else 80 | abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}"; 81 | 82 | # Ports of functions for older nix versions 83 | 84 | # a Nix version of mapAttrs if the built-in doesn't exist 85 | mapAttrs = builtins.mapAttrs or ( 86 | f: set: with builtins; 87 | listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set)) 88 | ); 89 | 90 | # fetchTarball version that is compatible between all the versions of Nix 91 | builtins_fetchTarball = { url, sha256 }@attrs: 92 | let 93 | inherit (builtins) lessThan nixVersion fetchTarball; 94 | in 95 | if lessThan nixVersion "1.12" then 96 | fetchTarball { inherit url; } 97 | else 98 | fetchTarball attrs; 99 | 100 | # fetchurl version that is compatible between all the versions of Nix 101 | builtins_fetchurl = { url, sha256 }@attrs: 102 | let 103 | inherit (builtins) lessThan nixVersion fetchurl; 104 | in 105 | if lessThan nixVersion "1.12" then 106 | fetchurl { inherit url; } 107 | else 108 | fetchurl attrs; 109 | 110 | # Create the final "sources" from the config 111 | mkSources = config: 112 | mapAttrs ( 113 | name: spec: 114 | if builtins.hasAttr "outPath" spec 115 | then abort 116 | "The values in sources.json should not have an 'outPath' attribute" 117 | else 118 | spec // { outPath = fetch config.pkgs name spec; } 119 | ) config.sources; 120 | 121 | # The "config" used by the fetchers 122 | mkConfig = 123 | { sourcesFile ? ./sources.json 124 | , sources ? builtins.fromJSON (builtins.readFile sourcesFile) 125 | , pkgs ? mkPkgs sources 126 | }: rec { 127 | # The sources, i.e. the attribute set of spec name to spec 128 | inherit sources; 129 | 130 | # The "pkgs" (evaluated nixpkgs) to use for e.g. non-builtin fetchers 131 | inherit pkgs; 132 | }; 133 | in 134 | mkSources (mkConfig {}) // { __functor = _: settings: mkSources (mkConfig settings); } 135 | -------------------------------------------------------------------------------- /packages/guiduck/shell.nix: -------------------------------------------------------------------------------- 1 | let 2 | pkgs = import ./nix {}; 3 | in 4 | pkgs.mkShell { 5 | buildInputs = [ 6 | pkgs.overlayed.niv.niv 7 | pkgs.overlayed.crate2nix 8 | pkgs.entr 9 | pkgs.cargo 10 | pkgs.rustfmt 11 | pkgs.clippy 12 | pkgs.hello 13 | ]; 14 | } 15 | -------------------------------------------------------------------------------- /packages/guiduck/src/bogus.rs: -------------------------------------------------------------------------------- 1 | use std::convert::TryInto; 2 | use std::error::Error; 3 | use zbus::{dbus_interface, fdo}; 4 | 5 | struct Foo; 6 | 7 | #[dbus_interface(name = "com.grahamc.Foo1")] 8 | impl Foo { 9 | fn bar(&self, name: &str, arg: &str) -> String { 10 | format!("Hello {} {}!", name, arg) 11 | } 12 | } 13 | 14 | fn main() -> Result<(), Box> { 15 | let connection = zbus::Connection::new_session()?; 16 | fdo::DBusProxy::new(&connection)?.request_name( 17 | "com.grahamc.Foo", 18 | fdo::RequestNameFlags::ReplaceExisting.into(), 19 | )?; 20 | 21 | let mut object_server = zbus::ObjectServer::new(&connection); 22 | object_server.at(&"/com/grahamc/Foo".try_into()?, Foo)?; 23 | loop { 24 | println!("hello"); 25 | if let Err(err) = object_server.try_handle_next() { 26 | eprintln!("{}", err); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/guiduck/src/interface.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | use std::path::{Path, PathBuf}; 3 | use std::process::{Child, Command, Stdio}; 4 | use std::thread; 5 | use zbus::dbus_interface; 6 | fn ugly_reap_in_background(mut child: Child) { 7 | thread::spawn(move || match child.wait() { 8 | Ok(status) => { 9 | println!("Utility exited: «{:?}»", status); 10 | } 11 | Err(e) => { 12 | println!("Waiting on a command failed?: «{:?}»", e); 13 | } 14 | }); 15 | } 16 | 17 | pub struct GuiDuckInterface { 18 | executables: HashMap, 19 | } 20 | 21 | impl GuiDuckInterface { 22 | pub fn with_executables(executables: HashMap) -> Self { 23 | GuiDuckInterface { executables } 24 | } 25 | 26 | fn handle_request(&self, cwd: PathBuf, utility: String, arg: Option<&str>) -> bool { 27 | self.log_launch_request(&cwd, &utility, arg); 28 | let ret = self.spawn(cwd, utility, arg); 29 | 30 | match ret { 31 | Ok(child) => { 32 | ugly_reap_in_background(child); 33 | return true; 34 | } 35 | 36 | Err(e) => { 37 | self.log_launch_error(e); 38 | return false; 39 | } 40 | } 41 | } 42 | 43 | fn spawn( 44 | &self, 45 | cwd: PathBuf, 46 | utility: String, 47 | arg: Option<&str>, 48 | ) -> Result { 49 | let program = self 50 | .executables 51 | .get(&utility) 52 | .ok_or_else(|| LaunchError::UnknownUtility(utility.clone()))?; 53 | 54 | let mut cmd = Command::new(program); 55 | cmd.current_dir(cwd); 56 | cmd.stdin(Stdio::null()); 57 | cmd.stdout(Stdio::inherit()); 58 | cmd.stderr(Stdio::inherit()); 59 | 60 | if let Some(arg) = arg { 61 | cmd.arg(arg); 62 | } 63 | 64 | cmd.spawn().map_err(|e| LaunchError::FailedToStart { 65 | cmd: program.to_string(), 66 | utility, 67 | e, 68 | }) 69 | } 70 | 71 | fn log_launch_error(&self, e: LaunchError) { 72 | match e { 73 | LaunchError::UnknownUtility(util) => { 74 | println!("Received a request to spawn an unknown utility «{}»", util); 75 | } 76 | LaunchError::FailedToStart { utility, cmd, e } => { 77 | println!( 78 | "Failed to spawn «{}» with command «{}»: «{:?}»", 79 | utility, cmd, e 80 | ); 81 | } 82 | } 83 | } 84 | 85 | fn log_launch_request(&self, cwd: &Path, utility: &str, arg: Option<&str>) { 86 | println!( 87 | "Launch request for «{}» and arg: {} in «{}»", 88 | utility, 89 | arg.map_or_else(|| String::from("-none-"), |a| format!("«{}»", a)), 90 | cwd.display() 91 | ); 92 | } 93 | } 94 | 95 | #[dbus_interface(name = "com.grahamc.GuiDuck1")] 96 | impl GuiDuckInterface { 97 | fn xdg_open(&self, cwd: String, utility: String) -> bool { 98 | self.handle_request(PathBuf::from(cwd), utility, None) 99 | } 100 | 101 | fn xdg_open_arg(&self, cwd: String, utility: String, arg: &str) -> bool { 102 | self.handle_request(PathBuf::from(cwd), utility, Some(arg)) 103 | } 104 | } 105 | 106 | enum LaunchError { 107 | UnknownUtility(String), 108 | FailedToStart { 109 | utility: String, 110 | cmd: String, 111 | e: std::io::Error, 112 | }, 113 | } 114 | -------------------------------------------------------------------------------- /packages/guiduck/src/proxy.rs: -------------------------------------------------------------------------------- 1 | use zbus::dbus_proxy; 2 | 3 | #[dbus_proxy( 4 | interface = "com.grahamc.GuiDuck1", 5 | default_service = "com.grahamc.guiduck", 6 | default_path = "/com/grahamc/guiduck1" 7 | )] 8 | trait GuiDuck { 9 | fn xdg_open(&self, cwd: &str, utility: &str) -> zbus::Result; 10 | 11 | fn xdg_open_arg(&self, cwd: &str, utility: &str, arg: &str) -> zbus::Result; 12 | } 13 | -------------------------------------------------------------------------------- /packages/guiduck/src/receive.rs: -------------------------------------------------------------------------------- 1 | use clap::{App, Arg}; 2 | use std::collections::HashMap; 3 | use std::convert::TryInto; 4 | use std::error::Error; 5 | use zbus::fdo; 6 | mod interface; 7 | 8 | pub const INTERFACE: &str = "com.grahamc.GuiDuck1"; 9 | pub const SERVICE: &str = "com.grahamc.guiduck"; 10 | pub const PATH: &str = "/com/grahamc/guiduck1"; 11 | 12 | fn main() -> Result<(), Box> { 13 | let matches = App::new("guiduck-launcher") 14 | .version("1.0") 15 | .author("Graham Christensen ") 16 | .about("Launch GUI programs over dbus, by pretending to be xdg-open's targets") 17 | .arg( 18 | Arg::with_name("map") 19 | .long("map") 20 | .multiple(true) 21 | .required(true) 22 | .number_of_values(2), 23 | ) 24 | .get_matches(); 25 | let map: HashMap = matches 26 | .values_of("map") 27 | .unwrap() 28 | .collect::>() 29 | .chunks(2) 30 | .into_iter() 31 | .map(|chunks| { 32 | // If the following error handling triggers, the clap configuration is bad. 33 | let key: &str = chunks 34 | .get(0) 35 | .expect("Converting --map args to a hashmap: no key"); 36 | let value: &str = chunks.get(1).unwrap_or_else(|| { 37 | panic!( 38 | "Converting --map args to a hashmap: no value for key «{}»", 39 | key 40 | ) 41 | }); 42 | (key.to_owned(), value.to_owned()) 43 | }) 44 | .collect(); 45 | 46 | let connection = zbus::Connection::new_session()?; 47 | fdo::DBusProxy::new(&connection)? 48 | .request_name(SERVICE, fdo::RequestNameFlags::ReplaceExisting.into())?; 49 | 50 | let mut object_server = zbus::ObjectServer::new(&connection); 51 | object_server.at( 52 | &PATH.try_into()?, 53 | interface::GuiDuckInterface::with_executables(map), 54 | )?; 55 | loop { 56 | if let Err(err) = object_server.try_handle_next() { 57 | eprintln!("{}", err); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /packages/guiduck/src/send.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use std::error::Error; 3 | use std::process::exit; 4 | mod proxy; 5 | 6 | fn main() -> Result<(), Box> { 7 | let mut args = env::args(); 8 | let orig_utility = args.next().expect("No argv0 -- how does this happen?"); 9 | let utility = orig_utility 10 | .split("/") 11 | .last() 12 | .expect("final path segment is empty somehow"); 13 | let arg = args.next(); 14 | if args.next().is_some() { 15 | println!("Too many arguments, only argv0 and argv1 are considered."); 16 | exit(1); 17 | } 18 | 19 | let connection = zbus::Connection::new_session()?; 20 | 21 | let proxy = proxy::GuiDuckProxy::new(&connection)?; 22 | 23 | let current_dir_path: std::path::PathBuf = std::env::current_dir()?; 24 | let cwd = current_dir_path.to_str().expect("cwd isn't stringy"); 25 | 26 | if let Some(arg) = arg { 27 | let reply = proxy.xdg_open_arg(cwd, &utility, &arg)?; 28 | dbg!(reply); 29 | } else { 30 | let reply = proxy.xdg_open(cwd, &utility)?; 31 | dbg!(reply); 32 | } 33 | 34 | Ok(()) 35 | } 36 | -------------------------------------------------------------------------------- /packages/guilauncher/default.nix: -------------------------------------------------------------------------------- 1 | { mutate, resholve, grahamc, bemenu, utillinux, systemd }: 2 | resholve { 3 | src = mutate ./launch.sh { bins = "${grahamc.guis}/bin"; }; 4 | inputs = [ bemenu utillinux systemd ]; 5 | } 6 | -------------------------------------------------------------------------------- /packages/guilauncher/launch.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eux 4 | 5 | bins=@bins@ 6 | 7 | program=$(PATH="$bins" bemenu-run -i --no-exec) 8 | if [ -n "$program" ]; then 9 | uuid=$(uuidgen) 10 | systemd-run --user --scope --unit "run-${program}-${uuid}" \ 11 | --setenv=BEMENU_BACKEND=wayland \ 12 | --setenv=PATH=":" \ 13 | "$bins/$program" 14 | fi 15 | -------------------------------------------------------------------------------- /packages/h/default.nix: -------------------------------------------------------------------------------- 1 | 2 | { fetchFromGitHub, ruby, stdenv, ifd }: 3 | let 4 | src = fetchFromGitHub { 5 | owner = "zimbatm"; 6 | repo = "h"; 7 | rev = "6ead1888af579531a4e9282207ba55724086d795"; 8 | sha256 = "1hzv3hwiv86v5k936691g6lzd8drrqnjc7hy7bjgc2qcnvf6xi8z"; 9 | }; 10 | in ifd src (import src { pkgs = { inherit ruby stdenv; }; }) 11 | -------------------------------------------------------------------------------- /packages/helvetica/default.nix: -------------------------------------------------------------------------------- 1 | { runCommand, secrets }: 2 | runCommand "helvetica" {} 3 | '' 4 | mkdir -p $out/share/fonts 5 | cp ${secrets.helvetica_location} $out/share/fonts 6 | '' 7 | -------------------------------------------------------------------------------- /packages/i3config/config: -------------------------------------------------------------------------------- 1 | # This file has been auto-generated by i3-config-wizard(1). 2 | # It will not be overwritten, so edit it as you like. 3 | # 4 | # Should you change your keyboard layout some time, delete 5 | # this file and re-run i3-config-wizard(1). 6 | # 7 | 8 | # i3 config file (v4) 9 | # 10 | # Please see http://i3wm.org/docs/userguide.html for a complete reference! 11 | 12 | set $mod Mod4 13 | 14 | # Font for window titles. Will also be used by the bar unless a different font 15 | # is used in the bar {} block below. 16 | font pango:monospace 12 17 | 18 | # This font is widely installed, provides lots of unicode glyphs, right-to-left 19 | # text rendering and scalability on retina/hidpi displays (thanks to pango). 20 | #font pango:DejaVu Sans Mono 8 21 | 22 | # Before i3 v4.8, we used to recommend this one as the default: 23 | # font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1 24 | # The font above is very space-efficient, that is, it looks good, sharp and 25 | # clear in small sizes. However, its unicode glyph coverage is limited, the old 26 | # X core fonts rendering does not support right-to-left and this being a bitmap 27 | # font, it doesn’t scale on retina/hidpi displays. 28 | 29 | # Use Mouse+$mod to drag floating windows to their wanted position 30 | floating_modifier $mod 31 | 32 | # start a terminal 33 | bindsym $mod+Return exec @sakura@/bin/sakura 34 | 35 | # kill focused window 36 | bindsym $mod+Shift+apostrophe kill 37 | 38 | # start dmenu (a program launcher) 39 | bindsym $mod+e exec @dmenu@/bin/dmenu_run 40 | bindsym --release $mod+Ctrl+3 exec @screenshot@ full-screen 41 | bindsym --release $mod+Ctrl+4 exec @screenshot@ select 42 | # There also is the (new) i3-dmenu-desktop which only displays applications 43 | # shipping a .desktop file. It is a wrapper around dmenu, so you need that 44 | # installed. 45 | # bindsym $mod+d exec --no-startup-id i3-dmenu-desktop 46 | 47 | 48 | 49 | bindsym XF86AudioRaiseVolume exec --no-startup-id @volume@ up 50 | bindsym XF86AudioLowerVolume exec --no-startup-id @volume@ down 51 | bindsym XF86AudioMute exec --no-startup-id @pulseaudioFull@/bin/pactl set-sink-mute @DEFAULT_SINK@ toggle 52 | 53 | bindsym XF86MonBrightnessUp exec @backlight@ up 54 | bindsym XF86MonBrightnessDown exec @backlight@ down 55 | 56 | bindsym XF86KbdBrightnessUp exec kbdlight up 20 57 | bindsym XF86KbdBrightnessDown exec kbdlight down 20 58 | 59 | # the F9/Find icon? 60 | bindsym XF86Search exec loginctl lock-session 61 | 62 | # change focus 63 | bindsym $mod+h focus left 64 | bindsym $mod+t focus down 65 | bindsym $mod+n focus up 66 | bindsym $mod+s focus right 67 | 68 | # alternatively, you can use the cursor keys: 69 | bindsym $mod+Left focus left 70 | bindsym $mod+Down focus down 71 | bindsym $mod+Up focus up 72 | bindsym $mod+Right focus right 73 | 74 | # move focused window 75 | bindsym $mod+Shift+h move left 76 | bindsym $mod+Shift+t move down 77 | bindsym $mod+Shift+n move up 78 | bindsym $mod+Shift+s move right 79 | 80 | # alternatively, you can use the cursor keys: 81 | bindsym $mod+Shift+Left move left 82 | bindsym $mod+Shift+Down move down 83 | bindsym $mod+Shift+Up move up 84 | bindsym $mod+Shift+Right move right 85 | 86 | # split in horizontal orientation 87 | bindsym $mod+d split h 88 | 89 | # split in vertical orientation 90 | bindsym $mod+k split v 91 | 92 | # enter fullscreen mode for the focused container 93 | bindsym $mod+u fullscreen toggle 94 | 95 | # change container layout (stacked, tabbed, toggle split) 96 | bindsym $mod+o layout stacking 97 | bindsym $mod+comma layout tabbed 98 | bindsym $mod+period layout toggle split 99 | 100 | # toggle tiling / floating 101 | bindsym $mod+Shift+space floating toggle 102 | 103 | # change focus between tiling / floating windows 104 | bindsym $mod+space focus mode_toggle 105 | 106 | # focus the parent container 107 | bindsym $mod+a focus parent 108 | 109 | # focus the child container 110 | #bindsym $mod+d focus child 111 | 112 | # switch to workspace 113 | bindsym $mod+1 workspace 1 114 | bindsym $mod+2 workspace 2 115 | bindsym $mod+3 workspace 3 116 | bindsym $mod+4 workspace 4 117 | bindsym $mod+5 workspace 5 118 | bindsym $mod+6 workspace 6 119 | bindsym $mod+7 workspace 7 120 | bindsym $mod+8 workspace 8 121 | bindsym $mod+9 workspace 9 122 | bindsym $mod+0 workspace 10 123 | 124 | # move focused container to workspace 125 | bindsym $mod+Shift+1 move container to workspace 1 126 | bindsym $mod+Shift+2 move container to workspace 2 127 | bindsym $mod+Shift+3 move container to workspace 3 128 | bindsym $mod+Shift+4 move container to workspace 4 129 | bindsym $mod+Shift+5 move container to workspace 5 130 | bindsym $mod+Shift+6 move container to workspace 6 131 | bindsym $mod+Shift+7 move container to workspace 7 132 | bindsym $mod+Shift+8 move container to workspace 8 133 | bindsym $mod+Shift+9 move container to workspace 9 134 | bindsym $mod+Shift+0 move container to workspace 10 135 | 136 | # reload the configuration file 137 | bindsym $mod+Shift+j reload 138 | # restart i3 inplace (preserves your layout/session, can be used to upgrade i3) 139 | bindsym $mod+Shift+p restart 140 | # exit i3 (logs you out of your X session) 141 | bindsym $mod+Shift+period exec "i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' -b 'Yes, exit i3' 'i3-msg exit'" 142 | 143 | # resize window (you can also use the mouse for that) 144 | mode "resize" { 145 | # These bindings trigger as soon as you enter the resize mode 146 | 147 | # Pressing left will shrink the window’s width. 148 | # Pressing right will grow the window’s width. 149 | # Pressing up will shrink the window’s height. 150 | # Pressing down will grow the window’s height. 151 | bindsym h resize shrink width 10 px or 10 ppt 152 | bindsym t resize grow height 10 px or 10 ppt 153 | bindsym n resize shrink height 10 px or 10 ppt 154 | bindsym s resize grow width 10 px or 10 ppt 155 | 156 | # same bindings, but for the arrow keys 157 | bindsym Left resize shrink width 10 px or 10 ppt 158 | bindsym Down resize grow height 10 px or 10 ppt 159 | bindsym Up resize shrink height 10 px or 10 ppt 160 | bindsym Right resize grow width 10 px or 10 ppt 161 | 162 | # back to normal: Enter or Escape 163 | bindsym Return mode "default" 164 | bindsym Escape mode "default" 165 | } 166 | 167 | bindsym $mod+p mode "resize" 168 | 169 | # Start i3bar to display a workspace bar (plus the system information i3status 170 | # finds out, if available) 171 | bar { 172 | status_command @i3status@/bin/i3status -c @i3status_conf@ 173 | } 174 | 175 | 176 | exec @dunst@/bin/dunst -config @dunst_config@ -------------------------------------------------------------------------------- /packages/i3config/default.nix: -------------------------------------------------------------------------------- 1 | { mutate, sakura, xorg, i3status, dmenu, pulseaudioFull, 2 | volume, backlight, dunst, dunst_config, lib, screenshot, secrets }: 3 | mutate ./config { 4 | inherit sakura i3status dmenu pulseaudioFull volume 5 | backlight dunst dunst_config screenshot; 6 | i3status_conf = mutate ./i3status { 7 | remote_tzs = lib.lists.imap0 (i: tz: '' 8 | tztime remote${toString i} { 9 | format = "-%d %H:%M:%S %Z" 10 | timezone = "${tz}" 11 | } 12 | order += "tztime remote${toString i}" 13 | 14 | '') secrets.location.remote_timezones; 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /packages/i3config/i3status: -------------------------------------------------------------------------------- 1 | general { 2 | output_format = "i3bar" 3 | colors = true 4 | interval = 5 5 | } 6 | 7 | order += "wireless wlp2s0" 8 | order += "path_exists channel" 9 | order += "volume master" 10 | order += "battery 0" 11 | 12 | volume master { 13 | format = "🔊%volume" 14 | format_muted = "🔇(%volume)" 15 | device = "pulse" 16 | } 17 | 18 | wireless wlp2s0 { 19 | format_up = "W: (%quality at %essid) %ip" 20 | format_down = "W: down" 21 | } 22 | 23 | path_exists channel { 24 | format = "" 25 | format_down = "Upgrade!" 26 | path = "/var/lib/is-nix-channel-up-to-date/up-to-date" 27 | } 28 | 29 | battery 0 { 30 | format = "%status%percentage %remaining" 31 | format_down = "No battery" 32 | status_chr = "🔌" # (AC power plug UTF-8 glyph) 33 | status_bat = "🔋" # (Battery glyph) 34 | status_full = "👍" # (Thumbs up glyph) 35 | path = "/sys/class/power_supply/BAT%d/uevent" 36 | low_threshold = 10 37 | 38 | last_full_capacity = true 39 | integer_battery_capacity = true 40 | } 41 | 42 | @remote_tzs@ 43 | 44 | tztime local { 45 | format = "%Y-%m-%d %H:%M:%S %Z" 46 | } 47 | order += "tztime local" -------------------------------------------------------------------------------- /packages/is-nix-channel-up-to-date/default.nix: -------------------------------------------------------------------------------- 1 | { stdenv, shellcheck }: 2 | stdenv.mkDerivation { 3 | name = "is-nix-channel-up-to-date.sh"; 4 | buildInputs = [ shellcheck ]; 5 | 6 | src = ./is-nix-channel-up-to-date.sh; 7 | 8 | unpackPhase = '' 9 | cp $src ./ 10 | ''; 11 | 12 | buildPhase = '' 13 | shellcheck ./*.sh 14 | ''; 15 | 16 | installPhase = '' 17 | ls 18 | cp ./*.sh $out 19 | ''; 20 | } 21 | -------------------------------------------------------------------------------- /packages/is-nix-channel-up-to-date/is-nix-channel-up-to-date.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eux 4 | 5 | CHAN=$1 6 | VERSION_LOCAL=$2 7 | SENTINAL=$3 8 | 9 | fetch_channel_version() { 10 | curl "https://channels.nix.gsc.io/nixos-$CHAN/latest" \ 11 | | cut -d' ' -f1 12 | } 13 | 14 | remove_sentinal() { 15 | echo "Removing sentinal from $SENTINAL" 16 | rm -f "$SENTINAL" 17 | exit 0 18 | } 19 | 20 | VERSION_CHAN=$(fetch_channel_version) 21 | 22 | echo "Channel is at $VERSION_CHAN" 23 | echo "System is at $VERSION_LOCAL" 24 | 25 | if [ "$VERSION_CHAN" == "$VERSION_LOCAL" ]; then 26 | touch "$SENTINAL" 27 | elif [ "x$VERSION_CHAN" == "x" ]; then 28 | echo "Bogus version" 29 | elif [ "$VERSION_CHAN" != "$VERSION_LOCAL" ]; then 30 | printf "Channel changed to %s\\n" "$VERSION_CHAN" 31 | remove_sentinal 32 | fi 33 | -------------------------------------------------------------------------------- /packages/is-nix-channel-up-to-date/service.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | { 3 | # note this doesn't really work right 4 | 5 | 6 | users = { 7 | users.is-nix-up2date = { 8 | description = "Is-Nix-Channel-Up-To-Date"; 9 | home = "/var/lib/is-nix-channel-up-to-date"; 10 | createHome = true; 11 | group = "is-nix-up2date"; 12 | uid = 400; 13 | }; 14 | 15 | groups.is-nix-up2date.gid = 400; 16 | }; 17 | 18 | systemd.timers.is-nix-channel-up-to-date = { 19 | description = "Run the Nix Channel Update Check"; 20 | partOf = [ "is-nix-channel-up-to-date.service" ]; 21 | wantedBy = [ "timers.target" ]; 22 | timerConfig.OnCalendar = "*:0/7"; 23 | }; 24 | 25 | systemd.services.is-nix-channel-up-to-date = { 26 | enable = true; 27 | after = [ "network.target" "network-online.target" ]; 28 | wants = [ "network-online.target" ]; 29 | wantedBy = [ "multi-user.target" ]; 30 | 31 | path = with pkgs; [ curl coreutils ]; 32 | 33 | unitConfig = { 34 | ConditionACPower = true; 35 | ConditionPathExists = "/var/lib/is-nix-channel-up-to-date/up-to-date"; 36 | }; 37 | 38 | serviceConfig = { 39 | User = "is-nix-up2date"; 40 | Group = "is-nix-up2date"; 41 | PrivateTmp = true; 42 | WorkingDirectory = "/var/lib/is-nix-channel-up-to-date"; 43 | }; 44 | 45 | preStart = '' 46 | chmod 755 /var/lib/is-nix-channel-up-to-date 47 | ''; 48 | script = '' 49 | ${pkgs.is-nix-channel-up-to-date} \ 50 | ${config.system.nixos.release} \ 51 | ${config.system.nixos.revision} \ 52 | /var/lib/is-nix-channel-up-to-date/up-to-date 53 | ''; 54 | }; 55 | 56 | system.activationScripts.up-to-date = '' 57 | touch /var/lib/is-nix-channel-up-to-date/up-to-date || true 58 | chown is-nix-up2date:is-nix-up2date /var/lib/is-nix-channel-up-to-date/up-to-date 59 | ''; 60 | } 61 | -------------------------------------------------------------------------------- /packages/kensington-slimblade-trackball/service.nix: -------------------------------------------------------------------------------- 1 | { 2 | # Kensington SlimBlade trackball sometimes auto-power-off's. 3 | services.udev.extraRules = '' 4 | ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idProduct}=="2041", ATTRS{idVendor}=="047d", TEST=="power/control", ATTR{power/control}="on" 5 | ''; 6 | } 7 | -------------------------------------------------------------------------------- /packages/kill-focused/default.nix: -------------------------------------------------------------------------------- 1 | { resholve, coreutils, utillinux, jq, systemd, sway }: 2 | # Kill the cgroup of the focused window 3 | resholve { 4 | src = ./kill.sh; 5 | inputs = [ coreutils utillinux jq systemd sway ]; 6 | } 7 | 8 | -------------------------------------------------------------------------------- /packages/kill-focused/kill.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eux 4 | 5 | pid=$(swaymsg -t get_tree | jq '.. | select(.type?) | select(.focused==true).pid') 6 | cgroup=$(cat "/proc/${pid}/cgroup" | cut -d: -f3- | rev | cut -d/ -f1 | rev) 7 | 8 | systemctl --user kill "$cgroup" 9 | 10 | -------------------------------------------------------------------------------- /packages/motd/default.nix: -------------------------------------------------------------------------------- 1 | { runCommand, ncurses }: 2 | runCommand "motd-massive" { 3 | buildInputs = [ ncurses ]; 4 | } 5 | '' 6 | ${./motd.sh} > $out 7 | '' 8 | -------------------------------------------------------------------------------- /packages/motd/motd.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export TERM=xterm 4 | #Background Colors 5 | E=$(tput sgr0); R=$(tput setab 1); G=$(tput setab 2); Y=$(tput setab 3); 6 | B=$(tput setab 4); M=$(tput setab 5); C=$(tput setab 6); W=$(tput setab 7); 7 | 8 | # normal 9 | width=" "; 10 | height=1; 11 | clear=0 12 | 13 | # for super high res / low font size screens: 14 | width=" "; 15 | height=5; 16 | clear=1 17 | 18 | function e() { echo -e "$E"; } 19 | function x() { echo -n "$E$width"; } 20 | function r() { echo -n "$R$width"; } 21 | function g() { echo -n "$G$width"; } 22 | function y() { echo -n "$Y$width"; } 23 | function b() { echo -n "$B$width"; } 24 | function m() { echo -n "$M$width"; } 25 | function c() { echo -n "$C$width"; } 26 | function w() { echo -n "$W$width"; } 27 | 28 | #putpixels 29 | function u() { 30 | h="$*";o=${h:0:1};v=${h:1}; 31 | for i in `seq $v` 32 | do 33 | $o; 34 | done 35 | } 36 | 37 | img="\ 38 | r40 e1 y39 r1 e1 g38 y1 r1 e1 b37 g1 y1 r1 e1 c36 b1 g1 y1 r1 e1 m35 c1 b1 g1 y1 r1 e1 r6 w28 m1 c1 b1 g1 y1 r1 e1 r1 y6 w7 x3 w4 x4 w4 x2 w3 m1 c1 b1 g1 y1 r1 e1 r1 y1 g6 w6 x1 w1 x2 w3 x1 w2 x1 w3 x2 w1 x1 w2 m1 c1 b1 g1 y1 r1 e1 r1 y1 g1 b6 w4 x2 w6 x1 w5 x2 w3 x1 w1 m1 c1 b1 g1 y1 r1 e1 r1 y1 g1 b1 c6 w3 x1 w7 x2 w4 x1 w6 m1 c1 b1 g1 y1 r1 e1 r1 y1 g1 b1 c1 m6 w2 x1 w8 x2 w3 x1 w6 m1 c1 b1 g1 y1 r1 e1 r1 y1 g1 b1 c1 m1 w7 x1 w2 x3 w4 x2 w2 x1 w6 m1 c1 b1 g1 y1 r1 e1 r1 y1 g1 b1 c1 m1 w7 x1 w4 x1 w5 x1 w2 x1 w4 x1 w1 m1 c1 b1 g1 y1 r1 e1 r1 y1 g1 b1 c1 m1 w7 x3 w2 x1 w2 x1 w3 x1 w1 x3 w2 x1 w1 m1 c1 b1 g1 y1 r1 e1 r1 y1 g1 b1 c1 m1 w9 x4 w3 x3 w4 x3 w2 m1 c1 b1 g1 y1 r1 e1 r1 y1 g1 b1 c1 m1 w28 m1 c1 b1 g1 y1 r1 e1 r1 y1 g1 b1 c1 m30 c1 b1 g1 y1 r1 e1 r1 y1 g1 b1 c32 b1 g1 y1 r1 e1 r1 y1 g1 b34 g1 y1 r1 e1 r1 y1 g36 y1 r1 e1 r1 y38 r1 e1 r40" 39 | 40 | for i in `seq 0 $clear`; do 41 | for i in `seq 1 $height`; do 42 | e 43 | done 44 | done 45 | 46 | 47 | line="" 48 | for n in $img 49 | do 50 | if [ "$n" = "e1" ]; then 51 | for i in `seq 1 $height`; do 52 | echo -n "$line" 53 | e 54 | done 55 | line="" 56 | else 57 | line="${line}$(u "$n")"; 58 | fi 59 | done 60 | for i in `seq 1 $height`; do 61 | echo -n "$line" 62 | e 63 | done 64 | 65 | exit 0; 66 | -------------------------------------------------------------------------------- /packages/mutate/default.nix: -------------------------------------------------------------------------------- 1 | { stdenvNoCC }: 2 | script: args: 3 | (stdenvNoCC.mkDerivation (args // { 4 | name = baseNameOf script; 5 | phases = [ "installPhase" ]; 6 | 7 | installPhase = '' 8 | cp ${script} $out 9 | substituteAllInPlace $out 10 | patchShebangs $out 11 | ''; 12 | })) 13 | -------------------------------------------------------------------------------- /packages/nitrokey/service.nix: -------------------------------------------------------------------------------- 1 | { pkgs, ... }: 2 | let 3 | src = pkgs.fetchurl { 4 | url = "https://www.nitrokey.com/sites/default/files/40-nitrokey.rules"; 5 | sha256 = "1208956k294hfc0jfb6p1ypascdylsyizbc7051b5ixj0w3d3shg"; 6 | }; 7 | in { 8 | services.udev.extraRules = '' 9 | # ${src} 10 | ${builtins.readFile src} 11 | ''; 12 | 13 | services.pcscd = { 14 | enable = true; 15 | }; 16 | 17 | environment.systemPackages = with pkgs; [ 18 | pcsctools 19 | ]; 20 | } 21 | -------------------------------------------------------------------------------- /packages/nix/0001-Add-a-post-build-hook.patch: -------------------------------------------------------------------------------- 1 | From 4df11e3e2358f83109e096942c3c2163b2e75bc1 Mon Sep 17 00:00:00 2001 2 | From: regnat 3 | Date: Thu, 11 Jul 2019 20:23:03 +0200 4 | Subject: [PATCH] Add a post-build-hook 5 | 6 | --- 7 | src/libstore/build.cc | 12 ++++++++++++ 8 | src/libstore/globals.hh | 2 ++ 9 | 2 files changed, 14 insertions(+) 10 | 11 | diff --git a/src/libstore/build.cc b/src/libstore/build.cc 12 | index 350ac409..23b56a0a 100644 13 | --- a/src/libstore/build.cc 14 | +++ b/src/libstore/build.cc 15 | @@ -1629,6 +1629,16 @@ void DerivationGoal::buildDone() 16 | being valid. */ 17 | registerOutputs(); 18 | 19 | + if (settings.postBuildHook != "") { 20 | + printMsg(lvlChatty, format("executing post-build hook '%1%'") 21 | + % settings.postBuildHook); 22 | + auto outputPaths = drv->outputPaths(); 23 | + Strings args; 24 | + for (auto outputPath: outputPaths) 25 | + args.push_front(outputPath); 26 | + auto lines = runProgram(settings.postBuildHook, false, args); 27 | + } 28 | + 29 | if (buildMode == bmCheck) { 30 | done(BuildResult::Built); 31 | return; 32 | @@ -2363,6 +2373,7 @@ void DerivationGoal::startBuilder() 33 | } 34 | debug(msg); 35 | } 36 | + 37 | } 38 | 39 | 40 | @@ -4631,3 +4642,4 @@ void LocalStore::repairPath(const Path & path) 41 | 42 | 43 | } 44 | + 45 | diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh 46 | index 0af8215d..391a5989 100644 47 | --- a/src/libstore/globals.hh 48 | +++ b/src/libstore/globals.hh 49 | @@ -315,6 +315,8 @@ public: 50 | "pre-build-hook", 51 | "A program to run just before a build to set derivation-specific build settings."}; 52 | 53 | + Setting postBuildHook{this, "", "post-build-hook", "TODO"}; 54 | + 55 | Setting netrcFile{this, fmt("%s/%s", nixConfDir, "netrc"), "netrc-file", 56 | "Path to the netrc file used to obtain usernames/passwords for downloads."}; 57 | 58 | -- 59 | 2.19.2 60 | 61 | -------------------------------------------------------------------------------- /packages/nix/0001-badly-fix-2801.patch: -------------------------------------------------------------------------------- 1 | From 72e4a17a0171cbaf6cd4a07fabe8e2fdcfe8f4c9 Mon Sep 17 00:00:00 2001 2 | From: Graham Christensen 3 | Date: Sun, 12 May 2019 09:49:27 -0400 4 | Subject: [PATCH 1/5] badly fix #2801 5 | 6 | --- 7 | src/libstore/build.cc | 3 +++ 8 | 1 file changed, 3 insertions(+) 9 | 10 | diff --git a/src/libstore/build.cc b/src/libstore/build.cc 11 | index 91eb97df..b3ca8068 100644 12 | --- a/src/libstore/build.cc 13 | +++ b/src/libstore/build.cc 14 | @@ -1837,11 +1837,13 @@ void DerivationGoal::startBuilder() 15 | "but this is only allowed when 'sandbox' is 'relaxed'") % drvPath); 16 | #endif 17 | useChroot = true; 18 | + needsHashRewrite = !useChroot; 19 | } 20 | else if (settings.sandboxMode == smDisabled) 21 | useChroot = false; 22 | else if (settings.sandboxMode == smRelaxed) 23 | useChroot = !fixedOutput && !noChroot; 24 | + needsHashRewrite = !useChroot; 25 | } 26 | 27 | if (worker.store.storeDir != worker.store.realStoreDir) { 28 | @@ -1850,6 +1852,7 @@ void DerivationGoal::startBuilder() 29 | #else 30 | throw Error("building using a diverted store is not supported on this platform"); 31 | #endif 32 | + needsHashRewrite = !useChroot; 33 | } 34 | 35 | /* If `build-users-group' is not empty, then we have to build as 36 | -- 37 | 2.19.2 38 | 39 | -------------------------------------------------------------------------------- /packages/nix/0001-build-move-needsHashRewrite-initialization-to-startB.patch: -------------------------------------------------------------------------------- 1 | From ff6867ab94cbe9ddcb4ba18d68a4a2dcb79b865d Mon Sep 17 00:00:00 2001 2 | From: Daiderd Jordan 3 | Date: Sun, 12 May 2019 15:53:40 +0200 4 | Subject: [PATCH 1/6] build: move needsHashRewrite initialization to 5 | startBuilder 6 | 7 | The value of useChroot is not set yet in the constructor, resulting in 8 | hash rewriting being enabled in certain cases where it should not be. 9 | 10 | Fixes #2801 11 | --- 12 | src/libstore/build.cc | 14 +++++++------- 13 | 1 file changed, 7 insertions(+), 7 deletions(-) 14 | 15 | diff --git a/src/libstore/build.cc b/src/libstore/build.cc 16 | index 91eb97df..30825add 100644 17 | --- a/src/libstore/build.cc 18 | +++ b/src/libstore/build.cc 19 | @@ -997,13 +997,6 @@ DerivationGoal::DerivationGoal(const Path & drvPath, const StringSet & wantedOut 20 | , wantedOutputs(wantedOutputs) 21 | , buildMode(buildMode) 22 | { 23 | -#if __linux__ 24 | - needsHashRewrite = !useChroot; 25 | -#else 26 | - /* Darwin requires hash rewriting even when sandboxing is enabled. */ 27 | - needsHashRewrite = true; 28 | -#endif 29 | - 30 | state = &DerivationGoal::getDerivation; 31 | name = (format("building of '%1%'") % drvPath).str(); 32 | trace("created"); 33 | @@ -1852,6 +1845,13 @@ void DerivationGoal::startBuilder() 34 | #endif 35 | } 36 | 37 | +#if __linux__ 38 | + needsHashRewrite = !useChroot; 39 | +#else 40 | + /* Darwin requires hash rewriting even when sandboxing is enabled. */ 41 | + needsHashRewrite = true; 42 | +#endif 43 | + 44 | /* If `build-users-group' is not empty, then we have to build as 45 | one of the members of that group. */ 46 | if (settings.buildUsersGroup != "" && getuid() == 0) { 47 | -- 48 | 2.19.2 49 | 50 | -------------------------------------------------------------------------------- /packages/nix/0001-pipe-stdout-stderr-to-the-user.patch: -------------------------------------------------------------------------------- 1 | From cbb8f289d9fbc7a1f0eeab3f0f5bb2ac5134feaa Mon Sep 17 00:00:00 2001 2 | From: Graham Christensen 3 | Date: Tue, 16 Jul 2019 16:14:28 -0400 4 | Subject: [PATCH] pipe stdout / stderr to the user 5 | 6 | --- 7 | src/libstore/build.cc | 38 ++++++++++++++++++++++++++++---------- 8 | 1 file changed, 28 insertions(+), 10 deletions(-) 9 | 10 | diff --git a/src/libstore/build.cc b/src/libstore/build.cc 11 | index c5a7dfd6..0d62c096 100644 12 | --- a/src/libstore/build.cc 13 | +++ b/src/libstore/build.cc 14 | @@ -1630,16 +1630,35 @@ void DerivationGoal::buildDone() 15 | registerOutputs(); 16 | 17 | if (settings.postBuildHook != "") { 18 | - printMsg(lvlChatty, format("executing post-build hook '%1%'") 19 | + printError(format("executing post-build hook '%1%'") 20 | % settings.postBuildHook); 21 | - auto outputPaths = drv->outputPaths(); 22 | - Strings args; 23 | - for (auto outputPath: outputPaths) 24 | - args.push_front(outputPath); 25 | - args.push_front("--"); 26 | - args.push_front(drvPath); 27 | - RunOptions opts(settings.postBuildHook, args); 28 | - runProgram2(opts); 29 | + 30 | + Pipe postBuildHookOutput; 31 | + postBuildHookOutput.create(); 32 | + 33 | + Pid postBuildHookRunner = startProcess([&]() { 34 | + auto outputPaths = drv->outputPaths(); 35 | + Strings args; 36 | + for (auto outputPath: outputPaths) 37 | + args.push_front(outputPath); 38 | + args.push_front("--"); 39 | + args.push_front(drvPath); 40 | + 41 | + 42 | + RunOptions opts(settings.postBuildHook, args); 43 | + auto sink = FdSink(postBuildHookOutput.writeSide.get()); 44 | + opts.standardOut = &sink; 45 | + runProgram2(opts); 46 | + 47 | + }); 48 | + 49 | + string msg; 50 | + while (true) { 51 | + string s = readLine(postBuildHookOutput.readSide.get()); 52 | + s += "\n"; 53 | + 54 | + writeToStderr(s); 55 | + } 56 | } 57 | 58 | if (buildMode == bmCheck) { 59 | @@ -4645,4 +4664,3 @@ void LocalStore::repairPath(const Path & path) 60 | 61 | 62 | } 63 | - 64 | -- 65 | 2.19.2 66 | 67 | -------------------------------------------------------------------------------- /packages/nix/0001-use-a-stderr-sink-too.patch: -------------------------------------------------------------------------------- 1 | From 53d452d11367a5cc00d16da625086c414795e774 Mon Sep 17 00:00:00 2001 2 | From: Graham Christensen 3 | Date: Tue, 16 Jul 2019 17:04:51 -0400 4 | Subject: [PATCH] use a stderr sink too 5 | 6 | --- 7 | src/libstore/build.cc | 1 + 8 | src/libutil/util.cc | 5 ++++- 9 | src/libutil/util.hh | 1 + 10 | 3 files changed, 6 insertions(+), 1 deletion(-) 11 | 12 | diff --git a/src/libstore/build.cc b/src/libstore/build.cc 13 | index 0d62c096..d2283df1 100644 14 | --- a/src/libstore/build.cc 15 | +++ b/src/libstore/build.cc 16 | @@ -1648,6 +1648,7 @@ void DerivationGoal::buildDone() 17 | RunOptions opts(settings.postBuildHook, args); 18 | auto sink = FdSink(postBuildHookOutput.writeSide.get()); 19 | opts.standardOut = &sink; 20 | + opts.standardErr = &sink; 21 | runProgram2(opts); 22 | 23 | }); 24 | diff --git a/src/libutil/util.cc b/src/libutil/util.cc 25 | index 17aee2d5..e57f1dbf 100644 26 | --- a/src/libutil/util.cc 27 | +++ b/src/libutil/util.cc 28 | @@ -1015,14 +1015,17 @@ void runProgram2(const RunOptions & options) 29 | } 30 | 31 | /* Create a pipe. */ 32 | - Pipe out, in; 33 | + Pipe out, err, in; 34 | if (options.standardOut) out.create(); 35 | + if (options.standardErr) err.create(); 36 | if (source) in.create(); 37 | 38 | /* Fork. */ 39 | Pid pid = startProcess([&]() { 40 | if (options.standardOut && dup2(out.writeSide.get(), STDOUT_FILENO) == -1) 41 | throw SysError("dupping stdout"); 42 | + if (options.standardErr && dup2(err.writeSide.get(), STDERR_FILENO) == -1) 43 | + throw SysError("dupping stderr"); 44 | if (source && dup2(in.readSide.get(), STDIN_FILENO) == -1) 45 | throw SysError("dupping stdin"); 46 | 47 | diff --git a/src/libutil/util.hh b/src/libutil/util.hh 48 | index fce3cab8..7a0155d4 100644 49 | --- a/src/libutil/util.hh 50 | +++ b/src/libutil/util.hh 51 | @@ -276,6 +276,7 @@ struct RunOptions 52 | std::optional input; 53 | Source * standardIn = nullptr; 54 | Sink * standardOut = nullptr; 55 | + Sink * standardErr = nullptr; 56 | bool _killStderr = false; 57 | 58 | RunOptions(const Path & program, const Strings & args) 59 | -- 60 | 2.19.2 61 | 62 | -------------------------------------------------------------------------------- /packages/nix/0002-build-add-test-for-sandboxed-check.patch: -------------------------------------------------------------------------------- 1 | From d75bdb5793e5ebf9e480f5a0012d141347725801 Mon Sep 17 00:00:00 2001 2 | From: Daiderd Jordan 3 | Date: Sun, 12 May 2019 16:46:21 +0200 4 | Subject: [PATCH 2/6] build: add test for sandboxed --check 5 | 6 | --- 7 | tests/linux-sandbox.sh | 3 +++ 8 | 1 file changed, 3 insertions(+) 9 | 10 | diff --git a/tests/linux-sandbox.sh b/tests/linux-sandbox.sh 11 | index acfd46c5..52967d07 100644 12 | --- a/tests/linux-sandbox.sh 13 | +++ b/tests/linux-sandbox.sh 14 | @@ -25,3 +25,6 @@ nix path-info -r $outPath | grep input-2 15 | nix ls-store -R -l $outPath | grep foobar 16 | 17 | nix cat-store $outPath/foobar | grep FOOBAR 18 | + 19 | +# Test --check without hash rewriting. 20 | +nix-build dependencies.nix --no-out-link --check --sandbox-paths /nix/store 21 | -- 22 | 2.19.2 23 | 24 | -------------------------------------------------------------------------------- /packages/nix/0002-fixup-Add-a-post-build-hook.patch: -------------------------------------------------------------------------------- 1 | From 9b55c672873b089a05bbac1039d0b4694745ad34 Mon Sep 17 00:00:00 2001 2 | From: regnat 3 | Date: Fri, 12 Jul 2019 00:49:39 +0200 4 | Subject: [PATCH 2/2] fixup! Add a post-build-hook 5 | 6 | --- 7 | src/libstore/build.cc | 5 ++++- 8 | 1 file changed, 4 insertions(+), 1 deletion(-) 9 | 10 | diff --git a/src/libstore/build.cc b/src/libstore/build.cc 11 | index 23b56a0a..c5a7dfd6 100644 12 | --- a/src/libstore/build.cc 13 | +++ b/src/libstore/build.cc 14 | @@ -1636,7 +1636,10 @@ void DerivationGoal::buildDone() 15 | Strings args; 16 | for (auto outputPath: outputPaths) 17 | args.push_front(outputPath); 18 | - auto lines = runProgram(settings.postBuildHook, false, args); 19 | + args.push_front("--"); 20 | + args.push_front(drvPath); 21 | + RunOptions opts(settings.postBuildHook, args); 22 | + runProgram2(opts); 23 | } 24 | 25 | if (buildMode == bmCheck) { 26 | -- 27 | 2.21.0 28 | 29 | -------------------------------------------------------------------------------- /packages/nix/0003-diff-hook-execute-as-the-build-user-and-pass-the-tem.patch: -------------------------------------------------------------------------------- 1 | From 4fce8498f5d69537878b7e4fb764d607c092f430 Mon Sep 17 00:00:00 2001 2 | From: Graham Christensen 3 | Date: Fri, 10 May 2019 20:59:39 -0400 4 | Subject: [PATCH 3/5] diff hook: execute as the build user, and pass the temp 5 | dir 6 | 7 | --- 8 | doc/manual/advanced-topics/diff-hook.xml | 12 +++---- 9 | doc/manual/command-ref/conf-file.xml | 20 ++++++++---- 10 | src/libstore/build.cc | 41 +++++++++++++++++------- 11 | src/libutil/util.cc | 4 +-- 12 | src/libutil/util.hh | 2 ++ 13 | 5 files changed, 51 insertions(+), 28 deletions(-) 14 | 15 | diff --git a/doc/manual/advanced-topics/diff-hook.xml b/doc/manual/advanced-topics/diff-hook.xml 16 | index d2613f6d..fb4bf819 100644 17 | --- a/doc/manual/advanced-topics/diff-hook.xml 18 | +++ b/doc/manual/advanced-topics/diff-hook.xml 19 | @@ -46,17 +46,15 @@ file containing: 20 | #!/bin/sh 21 | exec >&2 22 | echo "For derivation $3:" 23 | -/run/current-system/sw/bin/runuser -u nobody -- /run/current-system/sw/bin/diff -r "$1" "$2" 24 | +/run/current-system/sw/bin/diff -r "$1" "$2" 25 | 26 | 27 | - 28 | - The diff hook can be run as root. Take care to run as little 29 | - as possible as root, for this example we use runuser 30 | - to drop privileges. 31 | - 32 | - 33 | 34 | 35 | +The diff hook is executed by the same user and group who ran the 36 | +build. However, the diff hook does not have write access to the store 37 | +path just built. 38 | + 39 |
40 | 41 | Spot-Checking Build Determinism 42 | diff --git a/doc/manual/command-ref/conf-file.xml b/doc/manual/command-ref/conf-file.xml 43 | index a1a5d6e1..c5f90481 100644 44 | --- a/doc/manual/command-ref/conf-file.xml 45 | +++ b/doc/manual/command-ref/conf-file.xml 46 | @@ -252,13 +252,11 @@ false</literal>.</para> 47 | same. 48 | </para> 49 | 50 | - <warning> 51 | - <para> 52 | - The root user executes the diff hook in a daemonised 53 | - installation. See <xref linkend="chap-diff-hook" /> for 54 | - information on using the diff hook safely. 55 | - </para> 56 | - </warning> 57 | + <para> 58 | + The diff hook is executed by the same user and group who ran the 59 | + build. However, the diff hook does not have write access to the 60 | + store path just built. 61 | + </para> 62 | 63 | <para>The diff hook program receives three parameters:</para> 64 | 65 | @@ -280,6 +278,14 @@ false</literal>.</para> 66 | The path to the build's derivation 67 | </para> 68 | </listitem> 69 | + 70 | + <listitem> 71 | + <para> 72 | + The path to the build's scratch directory. This directory 73 | + will exist only if the build was run with 74 | + <option>--keep-failed</option>. 75 | + </para> 76 | + </listitem> 77 | </orderedlist> 78 | 79 | <para>The diff hook should not print data to stderr or stdout, as 80 | diff --git a/src/libstore/build.cc b/src/libstore/build.cc 81 | index e2e67764..8c0a58c1 100644 82 | --- a/src/libstore/build.cc 83 | +++ b/src/libstore/build.cc 84 | @@ -461,17 +461,26 @@ static void commonChildInit(Pipe & logPipe) 85 | close(fdDevNull); 86 | } 87 | 88 | -void handleDiffHook(Path tryA, Path tryB, Path drvPath) 89 | +void handleDiffHook(bool allowVfork, uid_t uid, uid_t gid, Path tryA, Path tryB, Path drvPath, Path tmpDir) 90 | { 91 | auto diffHook = settings.diffHook; 92 | if (diffHook != "" && settings.runDiffHook) { 93 | - try { 94 | - auto diff = runProgram(diffHook, true, {tryA, tryB, drvPath}); 95 | - if (diff != "") 96 | - printError(chomp(diff)); 97 | - } catch (Error & error) { 98 | - printError("diff hook execution failed: %s", error.what()); 99 | - } 100 | + auto wrapper = [&]() { 101 | + if (setgid(gid) == -1) 102 | + throw SysError("setgid failed"); 103 | + if (setuid(uid) == -1) 104 | + throw SysError("setuid failed"); 105 | + 106 | + try { 107 | + auto diff = runProgram(diffHook, true, {tryA, tryB, drvPath, tmpDir}); 108 | + if (diff != "") 109 | + printError(chomp(diff)); 110 | + } catch (Error & error) { 111 | + printError("diff hook execution failed: %s", error.what()); 112 | + } 113 | + }; 114 | + 115 | + doFork(allowVfork, wrapper); 116 | } 117 | } 118 | 119 | @@ -3200,14 +3209,18 @@ void DerivationGoal::registerOutputs() 120 | if (!worker.store.isValidPath(path)) continue; 121 | auto info = *worker.store.queryPathInfo(path); 122 | if (hash.first != info.narHash) { 123 | - handleDiffHook(path, actualPath, drvPath); 124 | - 125 | - if (settings.keepFailed) { 126 | + if (settings.runDiffHook || settings.keepFailed) { 127 | Path dst = worker.store.toRealPath(path + checkSuffix); 128 | deletePath(dst); 129 | if (rename(actualPath.c_str(), dst.c_str())) 130 | throw SysError(format("renaming '%1%' to '%2%'") % actualPath % dst); 131 | 132 | + handleDiffHook( 133 | + !buildUser && !drv->isBuiltin(), 134 | + buildUser ? buildUser->getUID() : getuid(), 135 | + buildUser ? buildUser->getGID() : getgid(), 136 | + path, dst, drvPath, tmpDir); 137 | + 138 | throw Error(format("derivation '%1%' may not be deterministic: output '%2%' differs from '%3%'") 139 | % drvPath % path % dst); 140 | } else 141 | @@ -3272,7 +3285,11 @@ void DerivationGoal::registerOutputs() 142 | ? fmt("output '%1%' of '%2%' differs from '%3%' from previous round", i->second.path, drvPath, prev) 143 | : fmt("output '%1%' of '%2%' differs from previous round", i->second.path, drvPath); 144 | 145 | - handleDiffHook(prev, i->second.path, drvPath); 146 | + handleDiffHook( 147 | + !buildUser && !drv->isBuiltin(), 148 | + buildUser ? buildUser->getUID() : getuid(), 149 | + buildUser ? buildUser->getGID() : getgid(), 150 | + prev, i->second.path, drvPath, tmpDir); 151 | 152 | if (settings.enforceDeterminism) 153 | throw NotDeterministic(msg); 154 | diff --git a/src/libutil/util.cc b/src/libutil/util.cc 155 | index a7170566..0f4d3d92 100644 156 | --- a/src/libutil/util.cc 157 | +++ b/src/libutil/util.cc 158 | @@ -914,8 +914,8 @@ void killUser(uid_t uid) 159 | 160 | /* Wrapper around vfork to prevent the child process from clobbering 161 | the caller's stack frame in the parent. */ 162 | -static pid_t doFork(bool allowVfork, std::function<void()> fun) __attribute__((noinline)); 163 | -static pid_t doFork(bool allowVfork, std::function<void()> fun) 164 | +pid_t doFork(bool allowVfork, std::function<void()> fun) __attribute__((noinline)); 165 | +pid_t doFork(bool allowVfork, std::function<void()> fun) 166 | { 167 | #ifdef __linux__ 168 | pid_t pid = allowVfork ? vfork() : fork(); 169 | diff --git a/src/libutil/util.hh b/src/libutil/util.hh 170 | index 54936a5c..824a35b9 100644 171 | --- a/src/libutil/util.hh 172 | +++ b/src/libutil/util.hh 173 | @@ -265,6 +265,8 @@ string runProgram(Path program, bool searchPath = false, 174 | const Strings & args = Strings(), 175 | const std::optional<std::string> & input = {}); 176 | 177 | +pid_t doFork(bool allowVfork, std::function<void()> fun); 178 | + 179 | struct RunOptions 180 | { 181 | Path program; 182 | -- 183 | 2.19.2 184 | 185 | -------------------------------------------------------------------------------- /packages/nix/0004-chdir-setgroups.patch: -------------------------------------------------------------------------------- 1 | From f014243cf86d9dd9a9aa6274a1d6adbd706d1c36 Mon Sep 17 00:00:00 2001 2 | From: Graham Christensen <graham@grahamc.com> 3 | Date: Sat, 11 May 2019 15:57:38 -0400 4 | Subject: [PATCH 4/5] chdir, setgroups 5 | 6 | --- 7 | src/libstore/build.cc | 4 ++++ 8 | 1 file changed, 4 insertions(+) 9 | 10 | diff --git a/src/libstore/build.cc b/src/libstore/build.cc 11 | index 8c0a58c1..ebd90a0c 100644 12 | --- a/src/libstore/build.cc 13 | +++ b/src/libstore/build.cc 14 | @@ -466,8 +466,12 @@ void handleDiffHook(bool allowVfork, uid_t uid, uid_t gid, Path tryA, Path tryB, 15 | auto diffHook = settings.diffHook; 16 | if (diffHook != "" && settings.runDiffHook) { 17 | auto wrapper = [&]() { 18 | + if (chdir("/") == -1) 19 | + throw SysError("chdir / failed"); 20 | if (setgid(gid) == -1) 21 | throw SysError("setgid failed"); 22 | + if (setgroups(0, 0) == -1) 23 | + throw SysError("setgroups failed"); 24 | if (setuid(uid) == -1) 25 | throw SysError("setuid failed"); 26 | 27 | -- 28 | 2.19.2 29 | 30 | -------------------------------------------------------------------------------- /packages/nix/0004-diff-hook-execute-as-the-build-user-and-pass-the-tem.patch: -------------------------------------------------------------------------------- 1 | From fb52754935ab5314344ba93cb8c5869f5738db6a Mon Sep 17 00:00:00 2001 2 | From: Graham Christensen <graham@grahamc.com> 3 | Date: Fri, 10 May 2019 20:59:39 -0400 4 | Subject: [PATCH 4/6] diff hook: execute as the build user, and pass the temp 5 | dir 6 | 7 | --- 8 | doc/manual/advanced-topics/diff-hook.xml | 12 +++---- 9 | doc/manual/command-ref/conf-file.xml | 20 ++++++++---- 10 | src/libstore/build.cc | 41 +++++++++++++++++------- 11 | src/libutil/util.cc | 4 +-- 12 | src/libutil/util.hh | 2 ++ 13 | 5 files changed, 51 insertions(+), 28 deletions(-) 14 | 15 | diff --git a/doc/manual/advanced-topics/diff-hook.xml b/doc/manual/advanced-topics/diff-hook.xml 16 | index d2613f6d..fb4bf819 100644 17 | --- a/doc/manual/advanced-topics/diff-hook.xml 18 | +++ b/doc/manual/advanced-topics/diff-hook.xml 19 | @@ -46,17 +46,15 @@ file containing: 20 | #!/bin/sh 21 | exec >&2 22 | echo "For derivation $3:" 23 | -/run/current-system/sw/bin/runuser -u nobody -- /run/current-system/sw/bin/diff -r "$1" "$2" 24 | +/run/current-system/sw/bin/diff -r "$1" "$2" 25 | </programlisting> 26 | 27 | -<warning> 28 | - <para>The diff hook can be run as root. Take care to run as little 29 | - as possible as root, for this example we use <command>runuser</command> 30 | - to drop privileges. 31 | - </para> 32 | -</warning> 33 | </para> 34 | 35 | +<para>The diff hook is executed by the same user and group who ran the 36 | +build. However, the diff hook does not have write access to the store 37 | +path just built.</para> 38 | + 39 | <section> 40 | <title> 41 | Spot-Checking Build Determinism 42 | diff --git a/doc/manual/command-ref/conf-file.xml b/doc/manual/command-ref/conf-file.xml 43 | index a1a5d6e1..c5f90481 100644 44 | --- a/doc/manual/command-ref/conf-file.xml 45 | +++ b/doc/manual/command-ref/conf-file.xml 46 | @@ -252,13 +252,11 @@ false</literal>.</para> 47 | same. 48 | </para> 49 | 50 | - <warning> 51 | - <para> 52 | - The root user executes the diff hook in a daemonised 53 | - installation. See <xref linkend="chap-diff-hook" /> for 54 | - information on using the diff hook safely. 55 | - </para> 56 | - </warning> 57 | + <para> 58 | + The diff hook is executed by the same user and group who ran the 59 | + build. However, the diff hook does not have write access to the 60 | + store path just built. 61 | + </para> 62 | 63 | <para>The diff hook program receives three parameters:</para> 64 | 65 | @@ -280,6 +278,14 @@ false</literal>.</para> 66 | The path to the build's derivation 67 | </para> 68 | </listitem> 69 | + 70 | + <listitem> 71 | + <para> 72 | + The path to the build's scratch directory. This directory 73 | + will exist only if the build was run with 74 | + <option>--keep-failed</option>. 75 | + </para> 76 | + </listitem> 77 | </orderedlist> 78 | 79 | <para>The diff hook should not print data to stderr or stdout, as 80 | diff --git a/src/libstore/build.cc b/src/libstore/build.cc 81 | index 8492e79b..bfa00f3c 100644 82 | --- a/src/libstore/build.cc 83 | +++ b/src/libstore/build.cc 84 | @@ -461,17 +461,26 @@ static void commonChildInit(Pipe & logPipe) 85 | close(fdDevNull); 86 | } 87 | 88 | -void handleDiffHook(Path tryA, Path tryB, Path drvPath) 89 | +void handleDiffHook(bool allowVfork, uid_t uid, uid_t gid, Path tryA, Path tryB, Path drvPath, Path tmpDir) 90 | { 91 | auto diffHook = settings.diffHook; 92 | if (diffHook != "" && settings.runDiffHook) { 93 | - try { 94 | - auto diff = runProgram(diffHook, true, {tryA, tryB, drvPath}); 95 | - if (diff != "") 96 | - printError(chomp(diff)); 97 | - } catch (Error & error) { 98 | - printError("diff hook execution failed: %s", error.what()); 99 | - } 100 | + auto wrapper = [&]() { 101 | + if (setgid(gid) == -1) 102 | + throw SysError("setgid failed"); 103 | + if (setuid(uid) == -1) 104 | + throw SysError("setuid failed"); 105 | + 106 | + try { 107 | + auto diff = runProgram(diffHook, true, {tryA, tryB, drvPath, tmpDir}); 108 | + if (diff != "") 109 | + printError(chomp(diff)); 110 | + } catch (Error & error) { 111 | + printError("diff hook execution failed: %s", error.what()); 112 | + } 113 | + }; 114 | + 115 | + doFork(allowVfork, wrapper); 116 | } 117 | } 118 | 119 | @@ -3197,14 +3206,18 @@ void DerivationGoal::registerOutputs() 120 | if (!worker.store.isValidPath(path)) continue; 121 | auto info = *worker.store.queryPathInfo(path); 122 | if (hash.first != info.narHash) { 123 | - handleDiffHook(path, actualPath, drvPath); 124 | - 125 | - if (settings.keepFailed) { 126 | + if (settings.runDiffHook || settings.keepFailed) { 127 | Path dst = worker.store.toRealPath(path + checkSuffix); 128 | deletePath(dst); 129 | if (rename(actualPath.c_str(), dst.c_str())) 130 | throw SysError(format("renaming '%1%' to '%2%'") % actualPath % dst); 131 | 132 | + handleDiffHook( 133 | + !buildUser && !drv->isBuiltin(), 134 | + buildUser ? buildUser->getUID() : getuid(), 135 | + buildUser ? buildUser->getGID() : getgid(), 136 | + path, dst, drvPath, tmpDir); 137 | + 138 | throw Error(format("derivation '%1%' may not be deterministic: output '%2%' differs from '%3%'") 139 | % drvPath % path % dst); 140 | } else 141 | @@ -3269,7 +3282,11 @@ void DerivationGoal::registerOutputs() 142 | ? fmt("output '%1%' of '%2%' differs from '%3%' from previous round", i->second.path, drvPath, prev) 143 | : fmt("output '%1%' of '%2%' differs from previous round", i->second.path, drvPath); 144 | 145 | - handleDiffHook(prev, i->second.path, drvPath); 146 | + handleDiffHook( 147 | + !buildUser && !drv->isBuiltin(), 148 | + buildUser ? buildUser->getUID() : getuid(), 149 | + buildUser ? buildUser->getGID() : getgid(), 150 | + prev, i->second.path, drvPath, tmpDir); 151 | 152 | if (settings.enforceDeterminism) 153 | throw NotDeterministic(msg); 154 | diff --git a/src/libutil/util.cc b/src/libutil/util.cc 155 | index a7170566..0f4d3d92 100644 156 | --- a/src/libutil/util.cc 157 | +++ b/src/libutil/util.cc 158 | @@ -914,8 +914,8 @@ void killUser(uid_t uid) 159 | 160 | /* Wrapper around vfork to prevent the child process from clobbering 161 | the caller's stack frame in the parent. */ 162 | -static pid_t doFork(bool allowVfork, std::function<void()> fun) __attribute__((noinline)); 163 | -static pid_t doFork(bool allowVfork, std::function<void()> fun) 164 | +pid_t doFork(bool allowVfork, std::function<void()> fun) __attribute__((noinline)); 165 | +pid_t doFork(bool allowVfork, std::function<void()> fun) 166 | { 167 | #ifdef __linux__ 168 | pid_t pid = allowVfork ? vfork() : fork(); 169 | diff --git a/src/libutil/util.hh b/src/libutil/util.hh 170 | index 54936a5c..824a35b9 100644 171 | --- a/src/libutil/util.hh 172 | +++ b/src/libutil/util.hh 173 | @@ -265,6 +265,8 @@ string runProgram(Path program, bool searchPath = false, 174 | const Strings & args = Strings(), 175 | const std::optional<std::string> & input = {}); 176 | 177 | +pid_t doFork(bool allowVfork, std::function<void()> fun); 178 | + 179 | struct RunOptions 180 | { 181 | Path program; 182 | -- 183 | 2.19.2 184 | 185 | -------------------------------------------------------------------------------- /packages/nix/0005-chdir-setgroups.patch: -------------------------------------------------------------------------------- 1 | From 2de35ba3332f2bc6d8e2834bdc55b1d949d30824 Mon Sep 17 00:00:00 2001 2 | From: Graham Christensen <graham@grahamc.com> 3 | Date: Sat, 11 May 2019 15:57:38 -0400 4 | Subject: [PATCH 5/6] chdir, setgroups 5 | 6 | --- 7 | src/libstore/build.cc | 4 ++++ 8 | 1 file changed, 4 insertions(+) 9 | 10 | diff --git a/src/libstore/build.cc b/src/libstore/build.cc 11 | index bfa00f3c..c2cc6f87 100644 12 | --- a/src/libstore/build.cc 13 | +++ b/src/libstore/build.cc 14 | @@ -466,8 +466,12 @@ void handleDiffHook(bool allowVfork, uid_t uid, uid_t gid, Path tryA, Path tryB, 15 | auto diffHook = settings.diffHook; 16 | if (diffHook != "" && settings.runDiffHook) { 17 | auto wrapper = [&]() { 18 | + if (chdir("/") == -1) 19 | + throw SysError("chdir / failed"); 20 | if (setgid(gid) == -1) 21 | throw SysError("setgid failed"); 22 | + if (setgroups(0, 0) == -1) 23 | + throw SysError("setgroups failed"); 24 | if (setuid(uid) == -1) 25 | throw SysError("setuid failed"); 26 | 27 | -- 28 | 2.19.2 29 | 30 | -------------------------------------------------------------------------------- /packages/nix/0005-runProgram-support-gid-uid-chdir.patch: -------------------------------------------------------------------------------- 1 | From 650734798f7d94187c9f4325a7cec38aae2cfa49 Mon Sep 17 00:00:00 2001 2 | From: Graham Christensen <graham@grahamc.com> 3 | Date: Sat, 11 May 2019 16:35:53 -0400 4 | Subject: [PATCH 5/5] runProgram: support gid, uid, chdir 5 | 6 | --- 7 | src/libstore/build.cc | 32 ++++++++++++++------------------ 8 | src/libutil/util.cc | 15 +++++++++++++-- 9 | src/libutil/util.hh | 5 +++-- 10 | 3 files changed, 30 insertions(+), 22 deletions(-) 11 | 12 | diff --git a/src/libstore/build.cc b/src/libstore/build.cc 13 | index ebd90a0c..3eb7ad50 100644 14 | --- a/src/libstore/build.cc 15 | +++ b/src/libstore/build.cc 16 | @@ -465,26 +465,22 @@ void handleDiffHook(bool allowVfork, uid_t uid, uid_t gid, Path tryA, Path tryB, 17 | { 18 | auto diffHook = settings.diffHook; 19 | if (diffHook != "" && settings.runDiffHook) { 20 | - auto wrapper = [&]() { 21 | - if (chdir("/") == -1) 22 | - throw SysError("chdir / failed"); 23 | - if (setgid(gid) == -1) 24 | - throw SysError("setgid failed"); 25 | - if (setgroups(0, 0) == -1) 26 | - throw SysError("setgroups failed"); 27 | - if (setuid(uid) == -1) 28 | - throw SysError("setuid failed"); 29 | + try { 30 | + RunOptions diffHookOptions(diffHook,{tryA, tryB, drvPath, tmpDir}); 31 | + diffHookOptions.searchPath = true; 32 | + diffHookOptions.uid = uid; 33 | + diffHookOptions.gid = gid; 34 | + diffHookOptions.chdir = "/"; 35 | 36 | - try { 37 | - auto diff = runProgram(diffHook, true, {tryA, tryB, drvPath, tmpDir}); 38 | - if (diff != "") 39 | - printError(chomp(diff)); 40 | - } catch (Error & error) { 41 | - printError("diff hook execution failed: %s", error.what()); 42 | - } 43 | - }; 44 | + auto diffRes = runProgram(diffHookOptions); 45 | + if (!statusOk(diffRes.first)) 46 | + throw ExecError(diffRes.first, fmt("diff-hook program '%1%' %2%", diffHook, statusToString(diffRes.first))); 47 | 48 | - doFork(allowVfork, wrapper); 49 | + if (diffRes.second != "") 50 | + printError(chomp(diffRes.second)); 51 | + } catch (Error & error) { 52 | + printError("diff hook execution failed: %s", error.what()); 53 | + } 54 | } 55 | } 56 | 57 | diff --git a/src/libutil/util.cc b/src/libutil/util.cc 58 | index 0f4d3d92..55b9144f 100644 59 | --- a/src/libutil/util.cc 60 | +++ b/src/libutil/util.cc 61 | @@ -16,6 +16,7 @@ 62 | #include <future> 63 | 64 | #include <fcntl.h> 65 | +#include <grp.h> 66 | #include <limits.h> 67 | #include <pwd.h> 68 | #include <sys/ioctl.h> 69 | @@ -914,8 +915,8 @@ void killUser(uid_t uid) 70 | 71 | /* Wrapper around vfork to prevent the child process from clobbering 72 | the caller's stack frame in the parent. */ 73 | -pid_t doFork(bool allowVfork, std::function<void()> fun) __attribute__((noinline)); 74 | -pid_t doFork(bool allowVfork, std::function<void()> fun) 75 | +static pid_t doFork(bool allowVfork, std::function<void()> fun) __attribute__((noinline)); 76 | +static pid_t doFork(bool allowVfork, std::function<void()> fun) 77 | { 78 | #ifdef __linux__ 79 | pid_t pid = allowVfork ? vfork() : fork(); 80 | @@ -1025,6 +1026,16 @@ void runProgram2(const RunOptions & options) 81 | if (source && dup2(in.readSide.get(), STDIN_FILENO) == -1) 82 | throw SysError("dupping stdin"); 83 | 84 | + //if (options.chdir && chdir((*options.chdir).c_str()) == -1) 85 | + // throw SysError("chdir failed"); 86 | + if (options.gid && setgid(*options.gid) == -1) 87 | + throw SysError("setgid failed"); 88 | + /* Drop all other groups if we're setgid. */ 89 | + if (options.gid && setgroups(0, 0) == -1) 90 | + throw SysError("setgroups failed"); 91 | + if (options.uid && setuid(*options.uid) == -1) 92 | + throw SysError("setuid failed"); 93 | + 94 | Strings args_(options.args); 95 | args_.push_front(options.program); 96 | 97 | diff --git a/src/libutil/util.hh b/src/libutil/util.hh 98 | index 824a35b9..7c57d0af 100644 99 | --- a/src/libutil/util.hh 100 | +++ b/src/libutil/util.hh 101 | @@ -265,10 +265,11 @@ string runProgram(Path program, bool searchPath = false, 102 | const Strings & args = Strings(), 103 | const std::optional<std::string> & input = {}); 104 | 105 | -pid_t doFork(bool allowVfork, std::function<void()> fun); 106 | - 107 | struct RunOptions 108 | { 109 | + std::optional<uid_t> uid; 110 | + std::optional<uid_t> gid; 111 | + std::optional<Path> chdir; 112 | Path program; 113 | bool searchPath = true; 114 | Strings args; 115 | -- 116 | 2.19.2 117 | 118 | -------------------------------------------------------------------------------- /packages/nix/0006-runProgram-support-gid-uid-chdir.patch: -------------------------------------------------------------------------------- 1 | From a8e5bf80712c09c41430d790615db6e14a211754 Mon Sep 17 00:00:00 2001 2 | From: Graham Christensen <graham@grahamc.com> 3 | Date: Sat, 11 May 2019 16:35:53 -0400 4 | Subject: [PATCH 6/6] runProgram: support gid, uid, chdir 5 | 6 | --- 7 | src/libstore/build.cc | 32 ++++++++++++++------------------ 8 | src/libutil/util.cc | 15 +++++++++++++-- 9 | src/libutil/util.hh | 5 +++-- 10 | 3 files changed, 30 insertions(+), 22 deletions(-) 11 | 12 | diff --git a/src/libstore/build.cc b/src/libstore/build.cc 13 | index c2cc6f87..27254a69 100644 14 | --- a/src/libstore/build.cc 15 | +++ b/src/libstore/build.cc 16 | @@ -465,26 +465,22 @@ void handleDiffHook(bool allowVfork, uid_t uid, uid_t gid, Path tryA, Path tryB, 17 | { 18 | auto diffHook = settings.diffHook; 19 | if (diffHook != "" && settings.runDiffHook) { 20 | - auto wrapper = [&]() { 21 | - if (chdir("/") == -1) 22 | - throw SysError("chdir / failed"); 23 | - if (setgid(gid) == -1) 24 | - throw SysError("setgid failed"); 25 | - if (setgroups(0, 0) == -1) 26 | - throw SysError("setgroups failed"); 27 | - if (setuid(uid) == -1) 28 | - throw SysError("setuid failed"); 29 | + try { 30 | + RunOptions diffHookOptions(diffHook,{tryA, tryB, drvPath, tmpDir}); 31 | + diffHookOptions.searchPath = true; 32 | + diffHookOptions.uid = uid; 33 | + diffHookOptions.gid = gid; 34 | + diffHookOptions.chdir = "/"; 35 | 36 | - try { 37 | - auto diff = runProgram(diffHook, true, {tryA, tryB, drvPath, tmpDir}); 38 | - if (diff != "") 39 | - printError(chomp(diff)); 40 | - } catch (Error & error) { 41 | - printError("diff hook execution failed: %s", error.what()); 42 | - } 43 | - }; 44 | + auto diffRes = runProgram(diffHookOptions); 45 | + if (!statusOk(diffRes.first)) 46 | + throw ExecError(diffRes.first, fmt("diff-hook program '%1%' %2%", diffHook, statusToString(diffRes.first))); 47 | 48 | - doFork(allowVfork, wrapper); 49 | + if (diffRes.second != "") 50 | + printError(chomp(diffRes.second)); 51 | + } catch (Error & error) { 52 | + printError("diff hook execution failed: %s", error.what()); 53 | + } 54 | } 55 | } 56 | 57 | diff --git a/src/libutil/util.cc b/src/libutil/util.cc 58 | index 0f4d3d92..55b9144f 100644 59 | --- a/src/libutil/util.cc 60 | +++ b/src/libutil/util.cc 61 | @@ -16,6 +16,7 @@ 62 | #include <future> 63 | 64 | #include <fcntl.h> 65 | +#include <grp.h> 66 | #include <limits.h> 67 | #include <pwd.h> 68 | #include <sys/ioctl.h> 69 | @@ -914,8 +915,8 @@ void killUser(uid_t uid) 70 | 71 | /* Wrapper around vfork to prevent the child process from clobbering 72 | the caller's stack frame in the parent. */ 73 | -pid_t doFork(bool allowVfork, std::function<void()> fun) __attribute__((noinline)); 74 | -pid_t doFork(bool allowVfork, std::function<void()> fun) 75 | +static pid_t doFork(bool allowVfork, std::function<void()> fun) __attribute__((noinline)); 76 | +static pid_t doFork(bool allowVfork, std::function<void()> fun) 77 | { 78 | #ifdef __linux__ 79 | pid_t pid = allowVfork ? vfork() : fork(); 80 | @@ -1025,6 +1026,16 @@ void runProgram2(const RunOptions & options) 81 | if (source && dup2(in.readSide.get(), STDIN_FILENO) == -1) 82 | throw SysError("dupping stdin"); 83 | 84 | + if (options.chdir && chdir((*options.chdir).c_str()) == -1) 85 | + throw SysError("chdir failed"); 86 | + if (options.gid && setgid(*options.gid) == -1) 87 | + throw SysError("setgid failed"); 88 | + /* Drop all other groups if we're setgid. */ 89 | + if (options.gid && setgroups(0, 0) == -1) 90 | + throw SysError("setgroups failed"); 91 | + if (options.uid && setuid(*options.uid) == -1) 92 | + throw SysError("setuid failed"); 93 | + 94 | Strings args_(options.args); 95 | args_.push_front(options.program); 96 | 97 | diff --git a/src/libutil/util.hh b/src/libutil/util.hh 98 | index 824a35b9..7c57d0af 100644 99 | --- a/src/libutil/util.hh 100 | +++ b/src/libutil/util.hh 101 | @@ -265,10 +265,11 @@ string runProgram(Path program, bool searchPath = false, 102 | const Strings & args = Strings(), 103 | const std::optional<std::string> & input = {}); 104 | 105 | -pid_t doFork(bool allowVfork, std::function<void()> fun); 106 | - 107 | struct RunOptions 108 | { 109 | + std::optional<uid_t> uid; 110 | + std::optional<uid_t> gid; 111 | + std::optional<Path> chdir; 112 | Path program; 113 | bool searchPath = true; 114 | Strings args; 115 | -- 116 | 2.19.2 117 | -------------------------------------------------------------------------------- /packages/nix/2931.patch: -------------------------------------------------------------------------------- 1 | From 89a2189cc98c55ae50f8b41cdf23e870de8427fb Mon Sep 17 00:00:00 2001 2 | From: =?UTF-8?q?F=C3=A9lix=20Baylac-Jacqu=C3=A9?= <felix@alternativebit.fr> 3 | Date: Sat, 8 Jun 2019 00:41:19 +0200 4 | Subject: [PATCH] Daemon: warn when an untrusted user cannot override a setting 5 | 6 | In daemon-based Nix setup, some options cannot be overridden by a 7 | client unless the client's user is considered as trusted. 8 | 9 | Currently, if an untrusted user tries to override one of those 10 | options, we are silently ignoring it. 11 | 12 | This can be pretty confusing in certain situations. 13 | 14 | e.g. a user thinks he disabled the sandbox when in reality he did not. 15 | 16 | We are now sending a warning message letting know the user some options 17 | have been ignored. 18 | 19 | Related to #1761. 20 | --- 21 | src/nix-daemon/nix-daemon.cc | 2 +- 22 | 1 file changed, 1 insertion(+), 1 deletion(-) 23 | 24 | diff --git a/src/nix-daemon/nix-daemon.cc b/src/nix-daemon/nix-daemon.cc 25 | index 8368c326..4a1b3e54 100644 26 | --- a/src/nix-daemon/nix-daemon.cc 27 | +++ b/src/nix-daemon/nix-daemon.cc 28 | @@ -566,7 +566,7 @@ static void performOp(TunnelLogger * logger, ref<Store> store, 29 | else if (setSubstituters(settings.extraSubstituters)) 30 | ; 31 | else 32 | - debug("ignoring untrusted setting '%s'", name); 33 | + warn("ignoring the user-specified setting '%s', because it is a restricted setting and you are not a trusted user.", name); 34 | } catch (UsageError & e) { 35 | warn(e.what()); 36 | } 37 | -- 38 | 2.18.1 39 | 40 | -------------------------------------------------------------------------------- /packages/nixos-software-manager/default.nix: -------------------------------------------------------------------------------- 1 | { resholve, mutate, coreutils, sway, nix, nix-diff, gnome3 }: 2 | let 3 | switchto = resholve { 4 | src = ./switch-to; 5 | inputs = [ nix ]; 6 | allow = { 7 | resholved_inputs = [ 8 | "/nix/var/nix/profiles/system/bin/switch-to-configuration" 9 | ]; 10 | }; 11 | }; 12 | 13 | stage-upgrade = resholve { 14 | src = ./stage-upgrade.sh; 15 | inputs = [ coreutils nix ]; 16 | }; 17 | 18 | prompt-upgrade = resholve { 19 | src = mutate ./prompt-upgrade.sh { 20 | inherit switchto; 21 | }; 22 | inputs = [ coreutils sway gnome3.zenity nix nix-diff ]; 23 | allow = { 24 | resholved_inputs = [ 25 | "/run/wrappers/bin/pkexec" 26 | "/run/current-system/sw/bin/nixos-version" 27 | ]; 28 | }; 29 | }; 30 | in { inherit stage-upgrade prompt-upgrade; } 31 | -------------------------------------------------------------------------------- /packages/nixos-software-manager/prompt-upgrade.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eux 4 | 5 | NIXPKGS="$1" 6 | 7 | cache="${2:-${XDG_CACHE_HOME:-$HOME/.cache}}" 8 | update_manager_dir="$cache/nixos-update-manager" 9 | channel_link=$update_manager_dir/channel 10 | new_system=$update_manager_dir/system 11 | 12 | mkdir -p "$update_manager_dir" 13 | 14 | newsyspath=$(readlink -f "$new_system") 15 | prevsyspath=$(readlink -f /nix/var/nix/profiles/system) 16 | 17 | if [ ! -e "$newsyspath" ]; then 18 | echo "No new system." 19 | exit 0 20 | fi 21 | 22 | if [ "$newsyspath" = "$prevsyspath" ]; then 23 | echo "System remains unchanged." 24 | exit 0 25 | fi 26 | 27 | agecurrentsystem=$(stat -c '%Y' /run/current-system) 28 | agenewsystem=$(stat -c '%Y' /var/cache/nixos-software-manager/nixos-update-manager/system) 29 | if [ "$agecurrentsystem" -gt "$agenewsystem" ]; then 30 | echo "Current system is newer than the staged system upgrade, not nagging." 31 | exit 1 32 | fi 33 | 34 | prevversion="$(/run/current-system/sw/bin/nixos-version)" 35 | newversion="$($newsyspath/sw/bin/nixos-version)" 36 | 37 | choice=$(swaynag \ 38 | --button-dismiss-no-terminal "What Changed?" "echo diff" \ 39 | --button-dismiss-no-terminal "Next Boot" "echo later" \ 40 | --button-dismiss-no-terminal "Now" "echo now" \ 41 | --message "Upgrade from $prevversion to $newversion?") 42 | 43 | withchoice() ( 44 | /run/wrappers/bin/pkexec @switchto@ "$newsyspath" "$1" 2>&1 | zenity --text-info 45 | ) 46 | 47 | promptdiff() ( 48 | set +x 49 | ( 50 | echo "Service Changes" 51 | "$newsyspath/bin/switch-to-configuration" dry-activate 52 | printf "\n\n\nDerivation Diff\n" 53 | prevdrv=$(nix-store --query --deriver "$prevsyspath") 54 | newdrv=$(nix-store --query --deriver "$newsyspath") 55 | nix-diff "$prevdrv" "$newdrv" 56 | ) 2>&1 | diffzenity 57 | ) 58 | 59 | diffzenity() ( 60 | set +e 61 | 62 | result=$(zenity --text-info \ 63 | --ok-label "Next Boot" \ 64 | --extra-button "Switch Now") 65 | code=$? 66 | if [ "$code" -eq 0 ] && [ "x$result" == "x" ]; then 67 | # "OK" button was pressed, ie: nextboot 68 | withchoice boot 69 | elif [ "$code" -eq 1 ] && [ "x$result" == "xSwitch Now" ]; then 70 | # "Switch Now" button selected 71 | withchoice switch 72 | elif [ "$code" -eq 1 ] && [ "x" == "x" ]; then 73 | # "Cancel" button selected 74 | : 75 | fi 76 | ) 77 | 78 | case "$choice" in 79 | now) 80 | withchoice switch 81 | ;; 82 | later) 83 | withchoice boot 84 | ;; 85 | diff) 86 | promptdiff 87 | ;; 88 | esac 89 | -------------------------------------------------------------------------------- /packages/nixos-software-manager/service.nix: -------------------------------------------------------------------------------- 1 | { pkgs, ... }: 2 | let 3 | scratch = "/var/cache/nixos-software-manager"; 4 | channel = "channel:nixos-20.09"; 5 | nixos_config = "/home/grahamc/projects/grahamc/nixos-config/devices/petunia/configuration.nix"; 6 | in 7 | { 8 | environment.etc.nixpkgs.source = pkgs.path; 9 | nix.nixPath = [ "nixpkgs=/etc/nixpkgs" ]; 10 | 11 | systemd.tmpfiles.rules = [ "d ${scratch} 0755 root root -" ]; 12 | 13 | systemd.services.stage-upgrade = { 14 | unitConfig = { 15 | # Not sure why I copy-pasted this from another module, but 16 | # I'd like this process to be killed if we leave ac.target. 17 | # Instead it seemed to stop immediately. Maybe this needs a 18 | # wantedBy or something.... but I don't want it to start 19 | # on every plug-in. 20 | # StopWhenUnneeded = true; 21 | 22 | # I was thinking I'd only stage one upgrade at a time, but 23 | # that could cause conditions where I upgrade and immediately 24 | # need to upgrade again, which would be annoying. 25 | # ConditionPathExists = "!${scratch}/nixos-update-manager/system"; 26 | }; 27 | path = [ pkgs.gnutar pkgs.xz pkgs.git pkgs.openssh ]; 28 | script = "${pkgs.grahamc.nixos-software-manager.stage-upgrade} ${channel} ${scratch}"; 29 | environment.NIX_PATH = "nixos-config=${nixos_config}"; 30 | }; 31 | 32 | systemd.timers.stage-upgrade = { 33 | wantedBy = [ "ac.target" ]; 34 | partOf = [ "ac.target" ]; 35 | timerConfig.OnCalendar = "hourly"; 36 | unitConfig = { 37 | StopWhenUnneeded = true; 38 | }; 39 | }; 40 | 41 | systemd.user.services.prompt-upgrade = { 42 | unitConfig = { 43 | ConditionPathExists = "${scratch}/nixos-update-manager/system"; 44 | ConditionGroup = "users"; 45 | 46 | # See comment for systemd.services.stage-upgrade for StopWhenUnneeded, and delete this 47 | # if that one doens't exist. 48 | # StopWhenUnneeded = true; 49 | }; 50 | script = "${pkgs.grahamc.nixos-software-manager.prompt-upgrade} ${channel} ${scratch}"; 51 | environment.XDG_SESSION_TYPE = "wayland"; 52 | }; 53 | 54 | systemd.user.timers.prompt-upgrade = { 55 | wantedBy = [ "ac.target" ]; 56 | partOf = [ "ac.target" ]; 57 | timerConfig.OnCalendar = "*:0/5"; #"hourly"; 58 | unitConfig = { 59 | StopWhenUnneeded = true; 60 | }; 61 | }; 62 | } 63 | -------------------------------------------------------------------------------- /packages/nixos-software-manager/stage-upgrade.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eux 4 | 5 | NIXPKGS="$1" 6 | 7 | cache="${2:-${XDG_CACHE_HOME:-$HOME/.cache}}" 8 | update_manager_dir="$cache/nixos-update-manager" 9 | channel_link=$update_manager_dir/channel 10 | channel_failed=$update_manager_dir/channel.failed 11 | new_system=$update_manager_dir/system 12 | 13 | mkdir -p "$update_manager_dir" 14 | nix-build -I "nixpkgs=$NIXPKGS" --expr ' 15 | let pkgs = import <nixpkgs> {}; in pkgs.runCommand "channel" {} " 16 | ln -s ${pkgs.path} $out 17 | "' --out-link "$channel_link" 18 | 19 | 20 | set -eux 21 | 22 | if [ -e "$channel_failed" ]; then 23 | currentpath=$(realpath "$channel_link") 24 | failedpath=$(realpath "$channel_failed") 25 | 26 | if [ "$currentpath" = "$failedpath" ]; then 27 | echo "Current channel fails." 28 | exit 1 29 | fi 30 | fi 31 | 32 | if ! nix-build \ 33 | -I nixpkgs="$channel_link" \ 34 | '<nixpkgs/nixos>' \ 35 | -A system \ 36 | --keep-going \ 37 | --out-link "$new_system"; then 38 | echo "Marking the channel as broken" 39 | ln -nfs "$channel_link" "$channel_failed" 40 | exit 1 41 | 42 | fi 43 | 44 | # switch the profile: 45 | # nix-env --profile /nix/var/nix/profiles/system --set "$new_system" 46 | # switch now: 47 | # /nix/var/nix/profiles/system/bin/switch-to-configuration switch 48 | # switch at next boot: 49 | # /nix/var/nix/profiles/system/bin/switch-to-configuration boot 50 | -------------------------------------------------------------------------------- /packages/nixos-software-manager/switch-to: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eux 4 | 5 | sys="$1" 6 | todo="$2" 7 | 8 | nix-env --profile /nix/var/nix/profiles/system --set "$sys" 9 | /nix/var/nix/profiles/system/bin/switch-to-configuration "$todo" 10 | echo "Upgrade exited with: $?" 11 | 12 | -------------------------------------------------------------------------------- /packages/nixos-unstable-packages/default.nix: -------------------------------------------------------------------------------- 1 | {}: 2 | import 3 | (builtins.fetchGit { 4 | url = "https://github.com/NixOS/nixpkgs-channels.git"; 5 | rev = "190727db4ea7e0d083e7dbcb66ced11f31b340f0"; # nixos-unstable as of 2019-01-24 6 | }) 7 | {} 8 | -------------------------------------------------------------------------------- /packages/nixpkgs-maintainer-tools/bin/cpToOldStable: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PATH="@tpath@:@out@/bin" 4 | 5 | set -eu 6 | 7 | rebranch @oldstable@ --hard 8 | 9 | git cherry-pick -x "$@" 10 | git push origin @oldstable@ 11 | -------------------------------------------------------------------------------- /packages/nixpkgs-maintainer-tools/bin/cpToRelease: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PATH="@tpath@:@out@/bin" 4 | 5 | set -eu 6 | 7 | rebranch @stable@ --hard 8 | 9 | git cherry-pick -x "$@" 10 | git push origin @stable@ 11 | -------------------------------------------------------------------------------- /packages/nixpkgs-maintainer-tools/bin/git-am-pr: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | PATH="@tpath@" 4 | 5 | set -eu 6 | set -o pipefail 7 | 8 | for arg in "$@"; do 9 | curl -L "${arg}.patch" | git am --no-gpg-sign - 10 | done 11 | -------------------------------------------------------------------------------- /packages/nixpkgs-maintainer-tools/bin/rebranch: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eu 4 | 5 | PATH="@tpath@" 6 | branch="$1" 7 | 8 | if [ "x${2:-x}" == "x--hard" ]; then 9 | git clean -dfx 10 | git reset --hard 11 | git rebase --abort || true 12 | git am --abort || true 13 | fi 14 | 15 | git fetch origin 16 | git checkout $(git rev-parse HEAD) 17 | git branch -D "$branch" 18 | git checkout origin/"$branch" 19 | git checkout -b "$branch" 20 | -------------------------------------------------------------------------------- /packages/nixpkgs-maintainer-tools/bin/remaster: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eu 4 | 5 | PATH="@tpath@:@out@/bin" 6 | rebranch "master" "$@" 7 | -------------------------------------------------------------------------------- /packages/nixpkgs-maintainer-tools/bin/try-pr: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | PATH="@tpath@:@out@/bin" 4 | 5 | set -eu 6 | 7 | git am-pr "$1" 8 | 9 | set +e 10 | 11 | logline=$(git log --pretty=oneline --abbrev-commit HEAD~1...HEAD | cut -d' ' -f2 | cut -d: -f1) 12 | 13 | nix-build . -A "${logline}" 14 | 15 | git log --pretty=oneline --abbrev-commit HEAD~1...HEAD | cat 16 | -------------------------------------------------------------------------------- /packages/nixpkgs-maintainer-tools/default.nix: -------------------------------------------------------------------------------- 1 | { stdenv, git, coreutils, curl, nix }: 2 | stdenv.mkDerivation { 3 | name = "nixpkgs-maintainer-tools"; 4 | src = ./bin; 5 | 6 | stable = "release-18.03"; 7 | oldstable = "release-17.09"; 8 | tpath = "${curl}/bin:${git}/bin/:${coreutils}/bin:${nix}/bin"; 9 | 10 | buildPhase = '' 11 | for f in $(ls); do 12 | substituteAllInPlace "$f" 13 | done 14 | ''; 15 | 16 | installPhase = '' 17 | mkdir -p $out/ 18 | cp -r . $out/bin 19 | chmod +x $out/bin/* 20 | ''; 21 | } 22 | -------------------------------------------------------------------------------- /packages/nixpkgs-pre-push/default.nix: -------------------------------------------------------------------------------- 1 | { mutate, bash, git, coreutils }: 2 | mutate ./pre-push { 3 | inherit bash git coreutils; 4 | } 5 | -------------------------------------------------------------------------------- /packages/nixpkgs-pre-push/pre-push: -------------------------------------------------------------------------------- 1 | #!@bash@/bin/bash 2 | # 3 | # This hook is called with the following parameters: 4 | # 5 | # $1 -- Name of the remote to which the push is being done 6 | # $2 -- URL to which the push is being done 7 | # 8 | # If pushing without using a named remote those arguments will be equal. 9 | 10 | PATH="@coreutils@/bin:@git@/bin" 11 | 12 | set -eu 13 | 14 | remote="$1" 15 | url="$2" 16 | 17 | z40=0000000000000000000000000000000000000000 18 | 19 | pass() { 20 | echo "@"; 21 | exit 0 22 | } 23 | 24 | fail() { 25 | echo "$@"; 26 | exit 1 27 | } 28 | 29 | debug() { 30 | if [ "x${SAFE_MODE:-x}" != "xx" ]; then 31 | echo "DEBUG: $@" >&2 32 | fi 33 | } 34 | 35 | debug "Inputs:" 36 | debug " remote=$remote" 37 | debug " url=$url" 38 | 39 | if [ "x${SAFE_MODE:-x}" != "xx" ]; then 40 | debug "Enabling safe-mode because SAFE_MODE is set" 41 | else 42 | # Don't push new branches to NixOS/Nixpkgs 43 | case "$url" in 44 | *NixOS/nixpkgs.git) 45 | debug "Safe mode activated." 46 | ;; 47 | *NixOS/nix.git) 48 | debug "Safe mode activated." 49 | ;; 50 | *) 51 | debug "$url doesn't appear to be upstream, go wild" 52 | exit 0 53 | esac 54 | fi 55 | 56 | 57 | while read local_ref local_sha remote_ref remote_sha 58 | do 59 | debug "Handling:" 60 | debug " local_ref=$local_ref" 61 | debug " local_sha=$local_sha" 62 | debug " remote_ref=$remote_ref" 63 | debug " remote_sha=$remote_sha" 64 | if [ "$local_sha" = $z40 ] 65 | then 66 | case "$remote_ref" in 67 | 'refs/heads/master') 68 | fail "Refusing to delete master" 69 | ;; 70 | refs/heads/release-*) 71 | fail "Don't delete releases!" 72 | ;; 73 | *) 74 | pass "Delete permitted by fall-through" 75 | ;; 76 | esac 77 | else 78 | if [ "$remote_sha" = $z40 ] 79 | then 80 | fail "Don't create new branches upstream" 81 | else 82 | # Update to existing branch, examine new commits 83 | range="$remote_sha..$local_sha" 84 | 85 | # Check for WIP commit 86 | commits=`git rev-list "$range"` 87 | count=$(echo "$commits" | wc -l) 88 | if [ "$count" -gt 1 ]; then 89 | git log "$range" 90 | echo "-----------------------------------" 91 | echo "You tried to push ${count} commits." 92 | echo "Please review the above diff, and if you still" 93 | echo "want to push, run git push with --no-verify" 94 | fail 95 | fi 96 | fi 97 | fi 98 | done 99 | -------------------------------------------------------------------------------- /packages/otf2bdf/0001-Remove-deprecated-MKINSTALLDIRS.patch: -------------------------------------------------------------------------------- 1 | From 8d490c410de5b760e8af218633783627e6f359f6 Mon Sep 17 00:00:00 2001 2 | From: Andrew Childs <lorne@cons.org.nz> 3 | Date: Sat, 3 Feb 2018 01:45:51 +0900 4 | Subject: [PATCH 1/2] Remove deprecated MKINSTALLDIRS 5 | 6 | --- 7 | Makefile.in | 3 +-- 8 | 1 file changed, 1 insertion(+), 2 deletions(-) 9 | 10 | diff --git a/Makefile.in b/Makefile.in 11 | index 5e8b6fd..fc7adc5 100644 12 | --- a/Makefile.in 13 | +++ b/Makefile.in 14 | @@ -22,7 +22,6 @@ 15 | 16 | RM = @RM@ 17 | CP = @CP@ 18 | -MKINSTALLDIRS = ./mkinstalldirs 19 | 20 | CC = @CC@ 21 | CFLAGS = @XX_CFLAGS@ @CFLAGS@ 22 | @@ -60,7 +59,7 @@ distclean: clean 23 | $(CC) $(CFLAGS) $(INCS) -c $< -o $@ 24 | 25 | install: otf2bdf 26 | - $(MKINSTALLDIRS) $(bindir) $(mandir)/man1 27 | + mkdir -p $(bindir) $(mandir)/man1 28 | $(CP) otf2bdf $(bindir)/otf2bdf 29 | $(CP) otf2bdf.man $(mandir)/man1/otf2bdf.1 30 | 31 | -- 32 | 2.16.1 33 | 34 | -------------------------------------------------------------------------------- /packages/otf2bdf/0002-Fix-generate_font-return-value.patch: -------------------------------------------------------------------------------- 1 | From 7720ca0da2550141afcf452c83257c80dc250274 Mon Sep 17 00:00:00 2001 2 | From: Andrew Childs <lorne@cons.org.nz> 3 | Date: Sat, 3 Feb 2018 01:46:03 +0900 4 | Subject: [PATCH 2/2] Fix generate_font return value 5 | 6 | --- 7 | otf2bdf.c | 7 ++++++- 8 | 1 file changed, 6 insertions(+), 1 deletion(-) 9 | 10 | diff --git a/otf2bdf.c b/otf2bdf.c 11 | index 9f1cb0c..463f924 100644 12 | --- a/otf2bdf.c 13 | +++ b/otf2bdf.c 14 | @@ -1102,8 +1102,13 @@ generate_font(FILE *out, char *iname, char *oname) 15 | * End the font and do memory cleanup on the glyph and raster structures. 16 | */ 17 | eof = fprintf(out, "ENDFONT\n"); 18 | + if (eof < 0) { 19 | + fprintf(stderr, "%s: problem writing to output file '%s'.\n", 20 | + prog, oname); 21 | + return -1; 22 | + } 23 | 24 | - return eof; 25 | + return 0; 26 | } 27 | 28 | static int 29 | -- 30 | 2.16.1 31 | 32 | -------------------------------------------------------------------------------- /packages/otf2bdf/default.nix: -------------------------------------------------------------------------------- 1 | # from https://github.com/thefloweringash/kevin-nix/tree/master/packages/otf2bdf 2 | { stdenv, fetchFromGitHub, freetype }: 3 | 4 | stdenv.mkDerivation rec { 5 | name = "otf2bdf-${version}"; 6 | version = "3.1"; 7 | 8 | buildInputs = [ freetype ]; 9 | 10 | patches = [ 11 | ./0001-Remove-deprecated-MKINSTALLDIRS.patch 12 | ./0002-Fix-generate_font-return-value.patch 13 | ]; 14 | 15 | src = fetchFromGitHub { 16 | owner = "jirutka"; 17 | repo = "otf2bdf"; 18 | rev = "cc7f1b5a1220b3a3ffe356e056e6627c64bdf122"; 19 | sha256 = "1q4k75wmxbdbby542glsckyycghlf1sgp9gl0qf1d1hagjp5kbqw"; 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /packages/pass-0001-clip-support-single-binary-coreutils.patch: -------------------------------------------------------------------------------- 1 | From f8a5f0638b821ef2a3ad1bbea2257dff04cc7b28 Mon Sep 17 00:00:00 2001 2 | From: Graham Christensen <graham@grahamc.com> 3 | Date: Thu, 19 Dec 2019 21:40:22 -0500 4 | Subject: [PATCH] clip(): support single-binary coreutils 5 | 6 | --- 7 | src/password-store.sh | 4 ++-- 8 | src/platform/cygwin.sh | 4 ++-- 9 | src/platform/darwin.sh | 4 ++-- 10 | 3 files changed, 6 insertions(+), 6 deletions(-) 11 | 12 | diff --git a/src/password-store.sh b/src/password-store.sh 13 | index 77f3eda..76bbecc 100755 14 | --- a/src/password-store.sh 15 | +++ b/src/password-store.sh 16 | @@ -173,11 +173,11 @@ clip() { 17 | # This base64 business is because bash cannot store binary data in a shell 18 | # variable. Specifically, it cannot store nulls nor (non-trivally) store 19 | # trailing new lines. 20 | - pkill -f "^$sleep_argv0" 2>/dev/null && sleep 0.5 21 | + pkill -P $(pgrep -f "^$sleep_argv0") 2>/dev/null && sleep 0.5 22 | local before="$("${paste_cmd[@]}" 2>/dev/null | $BASE64)" 23 | echo -n "$1" | "${copy_cmd[@]}" || die "Error: Could not copy data to the clipboard" 24 | ( 25 | - ( exec -a "$sleep_argv0" bash <<<"trap 'kill %1' TERM; sleep '$CLIP_TIME' & wait" ) 26 | + ( exec -a "$sleep_argv0" bash <(echo trap 'kill %1' TERM\; sleep "$CLIP_TIME & wait") ) 27 | local now="$("${paste_cmd[@]}" | $BASE64)" 28 | [[ $now != $(echo -n "$1" | $BASE64) ]] && before="$now" 29 | 30 | diff --git a/src/platform/cygwin.sh b/src/platform/cygwin.sh 31 | index 5a8d5ea..423e0ce 100644 32 | --- a/src/platform/cygwin.sh 33 | +++ b/src/platform/cygwin.sh 34 | @@ -3,11 +3,11 @@ 35 | 36 | clip() { 37 | local sleep_argv0="password store sleep on display $DISPLAY" 38 | - pkill -f "^$sleep_argv0" 2>/dev/null && sleep 0.5 39 | + pkill -P $(pgrep -f "^$sleep_argv0") 2>/dev/null && sleep 0.5 40 | local before="$($BASE64 < /dev/clipboard)" 41 | echo -n "$1" > /dev/clipboard 42 | ( 43 | - ( exec -a "$sleep_argv0" sleep "$CLIP_TIME" ) 44 | + ( exec -a "$sleep_argv0" bash <(echo sleep "$CLIP_TIME") ) 45 | local now="$($BASE64 < /dev/clipboard)" 46 | [[ $now != $(echo -n "$1" | $BASE64) ]] && before="$now" 47 | echo "$before" | $BASE64 -d > /dev/clipboard 48 | diff --git a/src/platform/darwin.sh b/src/platform/darwin.sh 49 | index 342ecce..9e12837 100644 50 | --- a/src/platform/darwin.sh 51 | +++ b/src/platform/darwin.sh 52 | @@ -3,11 +3,11 @@ 53 | 54 | clip() { 55 | local sleep_argv0="password store sleep for user $(id -u)" 56 | - pkill -f "^$sleep_argv0" 2>/dev/null && sleep 0.5 57 | + pkill -P $(pgrep -f "^$sleep_argv0") 2>/dev/null && sleep 0.5 58 | local before="$(pbpaste | $BASE64)" 59 | echo -n "$1" | pbcopy 60 | ( 61 | - ( exec -a "$sleep_argv0" sleep "$CLIP_TIME" ) 62 | + ( exec -a "$sleep_argv0" bash <(echo sleep "$CLIP_TIME") ) 63 | local now="$(pbpaste | $BASE64)" 64 | [[ $now != $(echo -n "$1" | $BASE64) ]] && before="$now" 65 | echo "$before" | $BASE64 -d | pbcopy 66 | -- 67 | 2.23.1 68 | 69 | -------------------------------------------------------------------------------- /packages/passff-host/default.nix: -------------------------------------------------------------------------------- 1 | { stdenv, fetchFromGitHub, python3, pass }: 2 | stdenv.mkDerivation { 3 | name = "passff-host-1.3"; 4 | 5 | src = fetchFromGitHub { 6 | owner = "passff"; 7 | repo = "passff-host"; 8 | rev = "1.0.1"; 9 | sha256 = "1rka47v0apjrj2h0d9vqp7lzjkh75chjk0fpl3bpa67d2197vsah"; 10 | }; 11 | 12 | buildInputs = [ python3 ]; 13 | 14 | patches = [ 15 | ./paths.patch 16 | ]; 17 | 18 | buildPhase = '' 19 | patchShebangs . 20 | ''; 21 | 22 | installPhase = '' 23 | mkdir -p $out/bin 24 | cp ./src/passff.py $out/bin/passff.py 25 | 26 | mkdir -p $out/share/passff-host 27 | cp ./src/passff.json $out/share/passff-host/passff.json 28 | 29 | substituteInPlace $out/bin/passff.py \ 30 | --replace "@PATH@" "" 31 | substituteInPlace $out/bin/passff.py \ 32 | --replace "@PASS@" "${pass}/bin/pass" 33 | substituteInPlace $out/bin/passff.py \ 34 | --replace "@VERSION@" "1.0.1" 35 | 36 | 37 | substituteInPlace $out/share/passff-host/passff.json \ 38 | --replace PLACEHOLDER $out/bin/passff.py 39 | ''; 40 | } 41 | -------------------------------------------------------------------------------- /packages/passff-host/paths.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/passff.py b/src/passff.py 2 | index 1760707..d60a937 100755 3 | --- a/src/passff.py 4 | +++ b/src/passff.py 5 | @@ -7,19 +7,16 @@ 6 | 7 | import os, sys, json, struct, subprocess 8 | 9 | -VERSION = "_VERSIONHOLDER_" 10 | +VERSION = "@VERSION@" 11 | 12 | ################################################################################ 13 | ######################## Begin preferences section ############################# 14 | ################################################################################ 15 | -# Default command for MacOS: 16 | -#command = "/usr/local/bin/pass" 17 | -command = "/usr/bin/pass" 18 | +command = "@PASS@" 19 | commandArgs = [] 20 | commandEnv = { 21 | "TREE_CHARSET": "ISO-8859-1", 22 | - # Default PATH for MacOS: 23 | - #"PATH": "/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin", 24 | + "PATH": "@PATH@", 25 | } 26 | charset = "UTF-8" 27 | ################################################################################ 28 | -------------------------------------------------------------------------------- /packages/power-targets/service.nix: -------------------------------------------------------------------------------- 1 | let 2 | makeTarget = type: other: { 3 | description = "On ${type} Power"; 4 | conflicts = [ other ]; 5 | unitConfig = { 6 | DefaultDependencies = false; 7 | }; 8 | }; 9 | in { 10 | services.udev.extraRules = '' 11 | SUBSYSTEM=="power_supply", KERNEL=="AC", ATTR{online}=="0", TAG+="systemd", ENV{SYSTEMD_WANTS}="battery.target", ENV{SYSTEMD_USER_WANTS}="battery.target" 12 | SUBSYSTEM=="power_supply", KERNEL=="AC", ATTR{online}=="1", TAG+="systemd", ENV{SYSTEMD_WANTS}="ac.target", ENV{SYSTEMD_USER_WANTS}="ac.target" 13 | ''; 14 | 15 | systemd.targets.ac = makeTarget "AC" "battery.target"; 16 | systemd.user.targets.ac = makeTarget "AC" "battery.target"; 17 | systemd.targets.battery = makeTarget "Battery" "ac.target"; 18 | systemd.user.targets.battery = makeTarget "Battery" "ac.target"; 19 | } 20 | -------------------------------------------------------------------------------- /packages/recognize-thunderbolt/default.nix: -------------------------------------------------------------------------------- 1 | { mutate, coreutils, bash, openssl 2 | , runCommand, findutils, diffutils}: 3 | let src = mutate ./recognize-thunderbolt { 4 | inherit coreutils bash openssl findutils diffutils; 5 | }; in runCommand "recognize-thunderbolt" {} '' 6 | mkdir -p $out/bin 7 | cp ${src} $out/bin/recognize-thunderbolt 8 | '' 9 | -------------------------------------------------------------------------------- /packages/recognize-thunderbolt/recognize-thunderbolt: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | PATH=@coreutils@/bin:@openssl@/bin:@findutils@/bin:@diffutils@/bin 4 | set -euo pipefail 5 | 6 | cache=/rpool/persist/private/thunderbolt 7 | mkdir --mode 0700 -p $cache 8 | 9 | sleep 2 10 | 11 | interactive() ( 12 | tty -s 13 | ) 14 | 15 | cachekey() ( 16 | echo "$1" | sha256sum | cut -d' ' -f1 17 | ) 18 | 19 | description_file() ( 20 | id=$(cachekey "$1") 21 | echo "$cache/$id.description" 22 | ) 23 | 24 | description_file_scratch() ( 25 | id=$(cachekey "$1") 26 | echo "$cache/$id.description.scratch" 27 | ) 28 | 29 | key_generate() ( 30 | id=$(cachekey "$1") 31 | key=$(openssl rand -hex 32) 32 | echo -n "$id" > "$cache/$id" 33 | ) 34 | 35 | key_exists() ( 36 | id=$(cachekey "$1") 37 | if [ -f "$cache/$id" ]; then 38 | return 0 39 | else 40 | return 1 41 | fi 42 | ) 43 | 44 | key_fetch() ( 45 | id=$(cachekey "$1") 46 | if [ ! -f "$cache/$id" ]; then 47 | echo "No cache key for $1" 48 | exit 1 49 | fi 50 | cat "$cache/$id" 51 | ) 52 | 53 | describe_device() ( 54 | cd "$1" 55 | cat <<EOF 56 | Vendor: $(cat vendor_name) ($(cat vendor)) 57 | Device: $(cat device_name) ($(cat device)) 58 | Unique ID: $(cat unique_id) 59 | NVM Version: $(cat nvm_version) 60 | EOF 61 | ) 62 | 63 | new_authorizations=0 64 | for d in $(find /sys/bus/thunderbolt/devices/ -name '*-*'); do 65 | echo "$d" 66 | id="$(cat "$d/unique_id")" 67 | description_scratch="$(description_file_scratch "$id")" 68 | 69 | if [ "$(cat "$d/authorized")" -eq 1 ]; then 70 | echo "$d: already authorized" 71 | continue 72 | fi 73 | 74 | describe_device "$d" > "$description_scratch" 75 | 76 | if ! key_exists "$id"; then 77 | echo "New device:" 78 | cat "$description_scratch" 79 | 80 | echo "" 81 | 82 | if interactive; then 83 | echo -n "Authorize? [y/N]: " 84 | read x 85 | if [ "$x" = "y" ]; then 86 | key_generate "$id" 87 | mv "$(description_file_scratch "$id")" "$(description_file "$id")" 88 | 89 | key_fetch "$id" | tee "$d/key" > /dev/null 90 | echo 1 | tee "$d/authorized" > /dev/null 91 | new_authorizations=1 92 | fi 93 | fi 94 | else 95 | if ! diff -q "$(description_file "$id")" "$(description_file_scratch "$id")"; then 96 | echo "device description for $d changed:" 97 | diff "$(description_file "$id")" "$(description_file_scratch "$id")" 98 | 99 | if interactive; then 100 | echo -n "Update our cached description and attempt to authorize? [y/N]: " 101 | read x 102 | if [ "$x" = "y" ]; then 103 | mv "$(description_file_scratch "$id")" "$(description_file "$id")" 104 | else 105 | continue 106 | fi 107 | else 108 | continue 109 | fi 110 | fi 111 | 112 | echo "Attempting to authorize $d" 113 | key_fetch "$id" | tee "$d/key" > /dev/null 114 | echo 2 | tee "$d/authorized" > /dev/null 115 | new_authorizations=1 116 | fi 117 | done 118 | 119 | if [ "$new_authorizations" -eq 0 ] && interactive; then 120 | echo "no new authorizations." 121 | echo -n "unload, reload thunderbolt, and try again? [y/N]: " 122 | read x 123 | if [ "$x" = "y" ]; then 124 | modprobe -r thunderbolt 125 | modprobe thunderbolt 126 | "$0" 127 | fi 128 | fi 129 | -------------------------------------------------------------------------------- /packages/recognize-thunderbolt/service.nix: -------------------------------------------------------------------------------- 1 | { pkgs, ... }: { 2 | services.udev.extraRules = '' 3 | ACTION=="add", SUBSYSTEM=="thunderbolt", ATTR{authorized}=="0", TAG+="systemd", ENV{SYSTEMD_WANTS}="recognize-thunderbolt.service" 4 | ''; 5 | 6 | systemd.services."recognize-thunderbolt" = { 7 | enable = true; 8 | serviceConfig = { 9 | ExecStart = "${pkgs.recognize-thunderbolt}/bin/recognize-thunderbolt"; 10 | Type = "oneshot"; 11 | RemainAfterExit = false; 12 | }; 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /packages/screenshot/default.nix: -------------------------------------------------------------------------------- 1 | { mutate, bash, coreutils, libnotify, scrot, xclip, openssh, utillinux }: 2 | mutate ./screenshot.sh { 3 | inherit bash coreutils scrot libnotify xclip openssh utillinux; 4 | } 5 | -------------------------------------------------------------------------------- /packages/screenshot/screenshot.sh: -------------------------------------------------------------------------------- 1 | #!@bash@/bin/bash 2 | 3 | PATH="@coreutils@/bin:@scrot@/bin:@libnotify@/bin:@openssh@/bin:@xclip@/bin:@utillinux@/bin" 4 | 5 | set -eux 6 | set -o pipefail 7 | 8 | LOCAL_DIR=~/Screenshots 9 | REMOTE_SCP=gsc.io:/home/grahamc/gsc.io/public/scratch 10 | REMOTE_HTTP=http://gsc.io/scratch 11 | 12 | timestamp() { 13 | TZ=utc date '+%Y-%m-%dT%H:%M:%SZ' 14 | } 15 | 16 | filename() { 17 | echo "$(timestamp)-$1-$(uuidgen).png" 18 | } 19 | 20 | snapshot() { 21 | # with a png, 1 means highly compressed, not actually low quality 22 | QUALITY=1 23 | scrot \ 24 | --quality "$QUALITY" \ 25 | "$@" 26 | } 27 | 28 | main() { 29 | mkdir -p "$LOCAL_DIR" 30 | cd "$LOCAL_DIR" 31 | 32 | mode=$1 33 | 34 | case "$mode" in 35 | full-screen) 36 | dest=$(filename "full-screen") 37 | snapshot "$dest" 38 | ;; 39 | select) 40 | dest=$(filename "selection") 41 | snapshot --border --select "$dest" 42 | ;; 43 | *) 44 | echo "?? mode: $mode" >&2 45 | exit 1 46 | ;; 47 | esac 48 | 49 | notify-send "Screenshot taken at $dest! :)" 50 | if scp "$LOCAL_DIR/$dest" "$REMOTE_SCP/$dest"; then 51 | url="$REMOTE_HTTP/$dest" 52 | echo "$url" | xclip -in -selection clipboard 53 | notify-send "Screenshot uploaded to $url, and has been copied to your clipboard" 54 | else 55 | notify-send "Uploading $LOCAL_DIR/$dest to $REMOTE_SCP/$dest failed" 56 | fi 57 | } 58 | 59 | main "$1" 60 | -------------------------------------------------------------------------------- /packages/services.nix: -------------------------------------------------------------------------------- 1 | { 2 | imports = [ 3 | ./nixos-software-manager/service.nix 4 | ./kensington-slimblade-trackball/service.nix 5 | ./recognize-thunderbolt/service.nix 6 | # ./aenea/service.nix 7 | ./autorandr-configs/service.nix 8 | # ./nitrokey/service.nix 9 | ./symlinks/service.nix 10 | ./is-nix-channel-up-to-date/service.nix 11 | ./did-graham-commit-his-repos/service.nix 12 | ./systemd-lock-handler/service.nix 13 | # ./systemd-boot/systemd-boot.nix 14 | ./ttf-console-font/service.nix 15 | ./power-targets/service.nix 16 | ]; 17 | } 18 | -------------------------------------------------------------------------------- /packages/snoop/default.nix: -------------------------------------------------------------------------------- 1 | { resholve, mutate, vim, oil, gzip, coreutils, pstree, jq, utillinux }: 2 | # decode the logs from this via: 3 | # journalctl -t snoopy -o json --output-fields _PID,MESSAGE | jq -rs '. | group_by(._PID) | .[] | [ .[] | .MESSAGE ] | join("") | @base64d' 4 | target: 5 | resholve { 6 | src = mutate ./snoop.sh { 7 | buildInputs = [ oil ]; 8 | inherit target oil; 9 | }; 10 | 11 | inputs = [ gzip coreutils jq vim pstree utillinux ]; 12 | allow = { resholved_inputs = [ target ]; }; 13 | } 14 | -------------------------------------------------------------------------------- /packages/snoop/snoop.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env osh 2 | 3 | ( 4 | pstree -w -p "$$" 5 | echo "$@" 6 | ) | base64 | logger -t snoopy 7 | 8 | exec @target@ "$@" 9 | -------------------------------------------------------------------------------- /packages/spawn/default.nix: -------------------------------------------------------------------------------- 1 | {resholve, utillinux, coreutils, systemd }: 2 | resholve { 3 | src = ./spawn.sh; 4 | inputs = [ utillinux coreutils systemd ]; 5 | } 6 | -------------------------------------------------------------------------------- /packages/spawn/spawn.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eux 4 | program=$1 5 | 6 | exec systemd-run --user --scope --unit "run-$(basename "$program")-$(uuidgen)" "$@" 7 | 8 | -------------------------------------------------------------------------------- /packages/sway-cycle-workspace/cycle-workspace.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Cycle a workspace between outputs 4 | 5 | set -eu 6 | 7 | if [ "x@pkg_path@" != "x" ]; then 8 | PATH=@pkg_path@ 9 | fi 10 | 11 | 12 | currently_focused_output() ( 13 | swaymsg -rt get_outputs | jq -r '.[] | select(.focused) | .name' 14 | ) 15 | 16 | workspaces_on_other_screens() ( 17 | current_output=$(currently_focused_output) 18 | swaymsg -rt get_workspaces | jq -r '.[] | select(.output != $output) | .name' --arg output "$current_output" 19 | ) 20 | 21 | next_output() ( 22 | workspace_name="$1" 23 | 24 | all_outputs=$(swaymsg -rt get_outputs | jq -r '.[] | .name' | sort) 25 | current_output=$(swaymsg -rt get_workspaces | jq -r '.[] | select(.name == $name) | .output' --arg name "$workspace_name") 26 | 27 | # Print the list of all outputs twice, find the workspaces' current 28 | # output plus the following line, then get the second line -- which 29 | # will be the next workspace to try. 30 | # 31 | # If the workspace is on DP-3, and the output list is like: 32 | # 33 | # DP-1 34 | # DP-2 35 | # DP-3 36 | # 37 | # Then we'll print: 38 | # 39 | # DP-1 40 | # DP-2 41 | # DP-3 42 | # DP-1 43 | # DP-2 44 | # DP-3 45 | # 46 | # and grep will find: 47 | # DP-3 48 | # DP-1 49 | # DP-3 50 | # 51 | # and the head / tail combo will extract DP-1. 52 | # 53 | # On the next run when the workspace is on DP-1, we will still 54 | # print the same outputs: 55 | # 56 | # DP-1 57 | # DP-2 58 | # DP-3 59 | # DP-1 60 | # DP-2 61 | # DP-3 62 | # 63 | # and grep will find: 64 | # 65 | # DP-1 66 | # DP-2 67 | # DP-1 68 | # DP-2 69 | # 70 | # and head / tail will extract DP-2. 71 | printf "%s\n%s\n" "$all_outputs" "$all_outputs" \ 72 | | grep -A1 "$current_output" \ 73 | | head -n2 \ 74 | | tail -n1 75 | ) 76 | 77 | move_workspace() { 78 | swaymsg workspace "$1" 79 | swaymsg move workspace to output "$(next_output "$1")" 80 | } 81 | 82 | main() { 83 | if [ "${1:-x}" == "--all-to-focused" ]; then 84 | # Move all workspaces to the output currently focused 85 | dest_output=$(currently_focused_output) 86 | 87 | for workspace in $(workspaces_on_other_screens); do 88 | move_workspace "$workspace" 89 | done 90 | else 91 | # Move just the current workspace to the next output 92 | current_workspace=$(swaymsg -rt get_workspaces | jq -r '.[] | select(.focused) | .name') 93 | move_workspace "$current_workspace" 94 | fi 95 | } 96 | 97 | main "$@" 98 | -------------------------------------------------------------------------------- /packages/sway-cycle-workspace/default.nix: -------------------------------------------------------------------------------- 1 | { mutate, lib, sway, jq, coreutils, gnugrep }: 2 | mutate ./cycle-workspace.sh { 3 | pkg_path = lib.makeBinPath [ 4 | sway 5 | jq 6 | coreutils 7 | gnugrep 8 | ]; 9 | } 10 | -------------------------------------------------------------------------------- /packages/swayconfig/config: -------------------------------------------------------------------------------- 1 | input * { 2 | tap enabled 3 | natural_scroll enabled 4 | xkb_layout dvorak 5 | xkb_options compose:ralt 6 | } 7 | 8 | input 1149:8257:Kensington_Kensington_Slimblade_Trackball { 9 | natural_scroll off 10 | } 11 | 12 | input '1267:10543:ELAN292F:00_04F3:292F' { 13 | map_to_output eDP-1 14 | } 15 | 16 | # Treat external kinesis keyboards as US, since they are in hardware 17 | # dvorak mode. This is because of RDP, VNC, etc. 18 | input '10730:258:Kinesis_Advantage2_Keyboard' xkb_layout us 19 | input '1523:7:HID_05f3:0007' xkb_layout us 20 | input '1452:516:HID_05ac:0204' xkb_layout us 21 | 22 | output '*' { 23 | background @bgimage@ fill 24 | } 25 | 26 | output 'Unknown 0x282B 0x00000000' { 27 | scale 3 28 | pos 0 0 29 | } 30 | output 'Dell Inc. DELL U2713HM 7JNY543I539S' { 31 | scale 1.5 32 | pos 1280 0 33 | } 34 | output 'Synaptics Inc Non-PnP 0x00000101' disable 35 | 36 | # This file has been auto-generated by i3-config-wizard(1). 37 | # It will not be overwritten, so edit it as you like. 38 | # 39 | # Should you change your keyboard layout some time, delete 40 | # this file and re-run i3-config-wizard(1). 41 | # 42 | 43 | # i3 config file (v4) 44 | # 45 | # Please see http://i3wm.org/docs/userguide.html for a complete reference! 46 | 47 | set $mod Mod4 48 | 49 | # Font for window titles. Will also be used by the bar unless a different font 50 | # is used in the bar {} block below. 51 | font pango:monospace 12 52 | 53 | # This font is widely installed, provides lots of unicode glyphs, right-to-left 54 | # text rendering and scalability on retina/hidpi displays (thanks to pango). 55 | #font pango:DejaVu Sans Mono 8 56 | 57 | # Before i3 v4.8, we used to recommend this one as the default: 58 | # font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1 59 | # The font above is very space-efficient, that is, it looks good, sharp and 60 | # clear in small sizes. However, its unicode glyph coverage is limited, the old 61 | # X core fonts rendering does not support right-to-left and this being a bitmap 62 | # font, it doesn’t scale on retina/hidpi displays. 63 | 64 | # Use Mouse+$mod to drag floating windows to their wanted position 65 | floating_modifier $mod 66 | 67 | # start a terminal 68 | bindsym $mod+Return exec @spawn@ @alacritty@/bin/alacritty 69 | 70 | # kill focused window 71 | bindsym $mod+Shift+apostrophe kill 72 | 73 | # start dmenu (a program launcher) 74 | bindsym $mod+e exec @guilauncher@ 75 | bindsym --release $mod+Ctrl+3 exec @spawn@ @screenshot@ full-screen 76 | bindsym --release $mod+Ctrl+4 exec @spawn@ @screenshot@ select 77 | 78 | 79 | bindsym XF86AudioRaiseVolume exec --no-startup-id @spawn@ @volume@ up 80 | bindsym XF86AudioLowerVolume exec --no-startup-id @spawn@ @volume@ down 81 | bindsym XF86AudioMute exec --no-startup-id @spawn@ @pulseaudioFull@/bin/pactl set-sink-mute @DEFAULT_SINK@ toggle 82 | 83 | bindsym XF86MonBrightnessUp exec @spawn@ @backlight@ up 84 | bindsym XF86MonBrightnessDown exec @spawn@ @backlight@ down 85 | 86 | bindsym XF86KbdBrightnessUp exec @spawn@ kbdlight up 20 87 | bindsym XF86KbdBrightnessDown exec @spawn@ kbdlight down 20 88 | 89 | # the F9/Find icon 90 | bindsym XF86Search exec @spawn@ @killFocused@ 91 | bindsym XF86AudioPlay exec @spawn@ @freezeFocused@ 92 | 93 | # change focus 94 | bindsym $mod+h focus left 95 | bindsym $mod+t focus down 96 | bindsym $mod+n focus up 97 | bindsym $mod+s focus right 98 | 99 | # alternatively, you can use the cursor keys: 100 | bindsym $mod+Left focus left 101 | bindsym $mod+Down focus down 102 | bindsym $mod+Up focus up 103 | bindsym $mod+Right focus right 104 | 105 | # move focused window 106 | bindsym $mod+Shift+h move left 107 | bindsym $mod+Shift+t move down 108 | bindsym $mod+Shift+n move up 109 | bindsym $mod+Shift+s move right 110 | 111 | # alternatively, you can use the cursor keys: 112 | bindsym $mod+Shift+Left move left 113 | bindsym $mod+Shift+Down move down 114 | bindsym $mod+Shift+Up move up 115 | bindsym $mod+Shift+Right move right 116 | 117 | # split in horizontal orientation 118 | bindsym $mod+d split h 119 | 120 | # split in vertical orientation 121 | bindsym $mod+k split v 122 | 123 | # enter fullscreen mode for the focused container 124 | bindsym $mod+u fullscreen toggle 125 | 126 | # change container layout (stacked, tabbed, toggle split) 127 | bindsym $mod+o layout stacking 128 | bindsym $mod+comma layout tabbed 129 | bindsym $mod+period layout toggle split 130 | 131 | # toggle tiling / floating 132 | bindsym $mod+Shift+space floating toggle 133 | 134 | # change focus between tiling / floating windows 135 | bindsym $mod+space focus mode_toggle 136 | 137 | # focus the parent container 138 | bindsym $mod+a focus parent 139 | 140 | # move a workspace to another workspace (corresponds to the alt of F8) 141 | bindsym $mod+l exec --no-startup-id @spawn@ @sway_cycle_workspace@ 142 | 143 | # focus the child container 144 | #bindsym $mod+d focus child 145 | 146 | # switch to workspace 147 | bindsym $mod+1 workspace 1 148 | bindsym $mod+2 workspace 2 149 | bindsym $mod+3 workspace 3 150 | bindsym $mod+4 workspace 4 151 | bindsym $mod+5 workspace 5 152 | bindsym $mod+6 workspace 6 153 | bindsym $mod+7 workspace 7 154 | bindsym $mod+8 workspace 8 155 | bindsym $mod+9 workspace 9 156 | bindsym $mod+0 workspace 10 157 | 158 | # move focused container to workspace 159 | bindsym $mod+Shift+1 move container to workspace 1 160 | bindsym $mod+Shift+2 move container to workspace 2 161 | bindsym $mod+Shift+3 move container to workspace 3 162 | bindsym $mod+Shift+4 move container to workspace 4 163 | bindsym $mod+Shift+5 move container to workspace 5 164 | bindsym $mod+Shift+6 move container to workspace 6 165 | bindsym $mod+Shift+7 move container to workspace 7 166 | bindsym $mod+Shift+8 move container to workspace 8 167 | bindsym $mod+Shift+9 move container to workspace 9 168 | bindsym $mod+Shift+0 move container to workspace 10 169 | 170 | # reload the configuration file 171 | bindsym $mod+Shift+j reload 172 | # restart i3 inplace (preserves your layout/session, can be used to upgrade i3) 173 | bindsym $mod+Shift+p restart 174 | # exit i3 (logs you out of your X session) 175 | bindsym $mod+Shift+period exec @spawn@ "i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' -b 'Yes, exit i3' 'i3-msg exit'" 176 | 177 | # resize window (you can also use the mouse for that) 178 | mode "resize" { 179 | # These bindings trigger as soon as you enter the resize mode 180 | 181 | # Pressing left will shrink the window’s width. 182 | # Pressing right will grow the window’s width. 183 | # Pressing up will shrink the window’s height. 184 | # Pressing down will grow the window’s height. 185 | bindsym h resize shrink width 10 px or 10 ppt 186 | bindsym t resize grow height 10 px or 10 ppt 187 | bindsym n resize shrink height 10 px or 10 ppt 188 | bindsym s resize grow width 10 px or 10 ppt 189 | 190 | # same bindings, but for the arrow keys 191 | bindsym Left resize shrink width 10 px or 10 ppt 192 | bindsym Down resize grow height 10 px or 10 ppt 193 | bindsym Up resize shrink height 10 px or 10 ppt 194 | bindsym Right resize grow width 10 px or 10 ppt 195 | 196 | # back to normal: Enter or Escape 197 | bindsym Return mode "default" 198 | bindsym Escape mode "default" 199 | } 200 | 201 | bindsym $mod+p mode "resize" 202 | 203 | # don't lock the screen if I'm watching TV 204 | for_window [app_id="firefox"] inhibit_idle fullscreen 205 | 206 | for_window [app_id="firefox" title="Firefox - Sharing Indicator"] floating enable 207 | for_window [app_id="firefox" title="Picture-in-Picture"] floating enable 208 | for_window [app_id="firefox" title="Picture-in-Picture"] sticky enable 209 | 210 | 211 | # Start i3bar to display a workspace bar (plus the system information i3status 212 | # finds out, if available) 213 | bar { 214 | swaybar_command @spawn@ @waybar@/bin/waybar -c @waybar_conf@ 215 | } 216 | 217 | exec systemctl --user import-environment WAYLAND_DISPLAY SWAYSOCK 218 | exec systemctl --user start graphical-session.target 219 | -------------------------------------------------------------------------------- /packages/swayconfig/default.nix: -------------------------------------------------------------------------------- 1 | { mutate, xorg, bemenu, waybar, pulseaudioFull, 2 | volume, backlight, mako, lib, screenshot, sway-cycle-workspace, 3 | systemd, secrets, grahamc, kill-focused, freeze-focused, pavucontrol }: 4 | mutate ./config { 5 | inherit bemenu pulseaudioFull volume 6 | backlight mako screenshot systemd; 7 | alacritty = grahamc.alacritty; 8 | killFocused = kill-focused; 9 | freezeFocused = freeze-focused; 10 | guilauncher = grahamc.guilauncher; 11 | spawn = grahamc.spawn; 12 | waybar = waybar.override { pulseSupport = true; }; 13 | 14 | sway_cycle_workspace = sway-cycle-workspace; 15 | waybar_conf = mutate ./waybar { 16 | inherit pavucontrol; 17 | inherit (grahamc) spawn; 18 | }; 19 | 20 | bgimage = ../../nixos-nineish.png; 21 | 22 | guis = grahamc.guis; 23 | } 24 | -------------------------------------------------------------------------------- /packages/swayconfig/waybar: -------------------------------------------------------------------------------- 1 | { 2 | // "layer": "top", // Waybar at top layer 3 | "position": "top", // Waybar position (top|bottom|left|right) 4 | "height": 20, // Waybar height (to be removed for auto height) 5 | // "width": 1280, // Waybar width 6 | // Choose the order of the modules 7 | "modules-left": ["sway/workspaces", "sway/mode" ], 8 | "modules-center": ["sway/window"], 9 | "modules-right": [ "idle_inhibitor", "pulseaudio", "network", "battery", "clock#Europe/Paris", "clock", "tray"], 10 | "sway/mode": { 11 | "format": "<span style=\"italic\">{}</span>" 12 | }, 13 | "idle_inhibitor": { 14 | "format": "{icon}", 15 | "format-icons": { 16 | "activated": "", 17 | "deactivated": "" 18 | } 19 | }, 20 | "tray": { 21 | // "icon-size": 21, 22 | "spacing": 10 23 | }, 24 | "clock": { 25 | // "timezone": "America/New_York", 26 | "format": "{:%Y-%m-%d %H:%M %Z}", 27 | "tooltip-format": "<big>{:%Y %B}</big>\n<tt><small>{calendar}</small></tt>" 28 | }, 29 | "clock#Europe/Paris": { 30 | "timezone": "Europe/Paris", 31 | "format": "{:%H:%M %Z}", 32 | "tooltip-format": "<big>{:%Y-%m-%d %H:%M %Z}</big>\n<tt><small>{calendar}</small></tt>", 33 | "format-alt": "{:%H:%M %Z}" 34 | 35 | }, 36 | "battery": { 37 | "states": { 38 | // "good": 95, 39 | "warning": 30, 40 | "critical": 15 41 | }, 42 | "format": "{capacity}% {icon}", 43 | "format-charging": "{capacity}% ", 44 | "format-plugged": "{capacity}% ", 45 | "format-alt": "{time} {icon}", 46 | // "format-good": "", // An empty format will hide the module 47 | // "format-full": "", 48 | "format-icons": ["", "", "", "", ""] 49 | }, 50 | "network": { 51 | // "interface": "wlp2*", // (Optional) To force the use of this interface 52 | "format-wifi": "", 53 | "tooltip-format-wifi": "{essid} ({signalStrength}%) ", 54 | "format-ethernet": "{ifname}: {ipaddr}/{cidr} ", 55 | "format-linked": "{ifname} (No IP) ", 56 | "format-disconnected": "⚠", 57 | "format-alt": "{ifname}: {ipaddr}/{cidr}" 58 | }, 59 | "pulseaudio": { 60 | "format": "{volume}% {icon} {format_source}", 61 | "format-bluetooth": "{volume}% {icon} {format_source}", 62 | "format-bluetooth-muted": "🔇 {icon} {format_source}", 63 | "format-muted": "🔇 {format_source}", 64 | "format-source": "{volume}% ", 65 | "format-source-muted": "", 66 | "format-icons": { 67 | "headphone": "", 68 | "hands-free": "", 69 | "headset": "", 70 | "phone": "", 71 | "portable": "", 72 | "car": "", 73 | "default": ["", "", ""] 74 | }, 75 | "on-click": "@spawn@ @pavucontrol@/bin/pavucontrol", 76 | // scrolling is backwards, so disable it 77 | "scroll-step": 0 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /packages/symlinks/service.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, ... }: 2 | 3 | with lib; 4 | 5 | let 6 | usersWithKeys = attrValues (flip filterAttrs config.users.users (n: u: 7 | u.symlinks != {} 8 | )); 9 | 10 | activationScriptForUser = user: flip mapAttrsToList user.symlinks (reltarget: src: 11 | "update_symlink \"${src}\" \"${user.home}/${reltarget}\"" 12 | ); 13 | 14 | activationScript = '' 15 | ${builtins.readFile ./update-symlinks.sh} 16 | ${concatStringsSep "\n" (flatten (map activationScriptForUser usersWithKeys))} 17 | ''; 18 | in { 19 | ###### interface 20 | 21 | options = { 22 | 23 | users.users = mkOption { 24 | type = with types; loaOf (submodule { 25 | options.symlinks = mkOption { 26 | default = {}; 27 | description = '' 28 | An attrset of relative paths and targets to symlink in to 29 | the user's HOME. 30 | ''; 31 | }; 32 | }); 33 | }; 34 | }; 35 | 36 | ###### implementation 37 | 38 | config = ({ 39 | system.activationScripts.usersymlinks = activationScript; 40 | }); 41 | } 42 | -------------------------------------------------------------------------------- /packages/symlinks/update-symlinks.sh: -------------------------------------------------------------------------------- 1 | 2 | scratch=$(mktemp -d -t tmp.XXXXXXXXXX); 3 | update_symlink() { 4 | local SRC 5 | local DEST 6 | local OUTDIR 7 | 8 | SRC="$1" 9 | DEST="$2" 10 | OUTDIR=$(dirname "$DEST"); 11 | if [ ! -d "$OUTDIR" ]; then 12 | if [ ! -z "${SUDO:-}" ]; then 13 | sudo mkdir -p "$OUTDIR" 14 | else 15 | mkdir -p "$OUTDIR" 16 | fi 17 | fi 18 | 19 | if [ ! -h "$DEST" ] && [ -d "$DEST" ]; then 20 | echo "DEST ($DEST) is a directory??" 21 | return 1 22 | fi 23 | 24 | if [ -f "$DEST" ]; then 25 | local CURSRC 26 | CURSRC=$(realpath "$DEST") 27 | if [ "x$CURSRC" == "x$SRC" ]; then 28 | return 0 29 | fi 30 | fi 31 | 32 | if [ -d "$DEST" ]; then 33 | rm "$DEST" 34 | fi 35 | 36 | ln -s "$SRC" "$scratch/tmp" 37 | if [ ! -z "${SUDO:-}" ]; then 38 | sudo mv "$scratch/tmp" "$DEST" 39 | else 40 | mv "$scratch/tmp" "$DEST" 41 | fi 42 | } 43 | -------------------------------------------------------------------------------- /packages/systemd-boot/systemd-boot.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, ... }: 2 | 3 | with lib; 4 | 5 | let 6 | cfg = config.boot.loader.systemd-boot; 7 | 8 | efi = config.boot.loader.efi; 9 | 10 | gummibootBuilder = pkgs.substituteAll { 11 | src = ./systemd-boot-builder.py; 12 | 13 | isExecutable = true; 14 | 15 | inherit (pkgs) python3 sbsigntool; 16 | 17 | binutils = pkgs.binutils-unwrapped; 18 | 19 | systemd = config.systemd.package; 20 | 21 | nix = config.nix.package.out; 22 | 23 | timeout = if config.boot.loader.timeout != null then config.boot.loader.timeout else ""; 24 | 25 | editor = if cfg.editor then "True" else "False"; 26 | 27 | inherit (cfg) consoleMode; 28 | 29 | inherit (efi) efiSysMountPoint canTouchEfiVariables; 30 | 31 | inherit (cfg) signed; 32 | signingKey = if cfg.signed then cfg.signing-key else "/no-signing-key"; 33 | signingCertificate = if cfg.signed then cfg.signing-certificate else "/no-signing-crt"; 34 | }; 35 | in { 36 | disabledModules = [ 37 | "system/boot/loader/systemd-boot/systemd-boot.nix" 38 | ]; 39 | 40 | # disabledModules doesn't remove imports, so comment it out here. 41 | # 42 | # imports = 43 | # [ (mkRenamedOptionModule [ "boot" "loader" "gummiboot" "enable" ] [ "boot" "loader" "systemd-boot" "enable" ]) 44 | # ]; 45 | 46 | options.boot.loader.systemd-boot = { 47 | enable = mkOption { 48 | default = false; 49 | 50 | type = types.bool; 51 | 52 | description = "Whether to enable the systemd-boot (formerly gummiboot) EFI boot manager"; 53 | }; 54 | 55 | signed = mkOption { 56 | default = false; 57 | type = types.bool; 58 | description = '' 59 | Whether or not the bootloader files, including systemd-boot 60 | EFI programs should be signed. 61 | ''; 62 | }; 63 | 64 | signing-key = mkOption { 65 | type = types.path; 66 | example = "/root/secure-boot/db.key"; 67 | description = '' 68 | The <literal>db.key</literal> signing key, for signing EFI 69 | programs. Note: Do not pass a store path. Passing the key like 70 | <literal>signing-key = ./db.key;</literal> will copy the 71 | private key in to the Nix store and make it world-readable. 72 | 73 | Instead, pass the path as an absolute path string, like: 74 | <literal>signing-key = "/root/secure-boot/db.key";</literal>. 75 | ''; 76 | }; 77 | 78 | signing-certificate = mkOption { 79 | type = types.path; 80 | example = "/root/secure-boot/db.crt"; 81 | description = '' 82 | The <literal>db.crt</literal> signing certificate, for signing 83 | EFI programs. Note: certificate files are not private. 84 | ''; 85 | }; 86 | 87 | editor = mkOption { 88 | default = true; 89 | 90 | type = types.bool; 91 | 92 | description = '' 93 | Whether to allow editing the kernel command-line before 94 | boot. It is recommended to set this to false, as it allows 95 | gaining root access by passing init=/bin/sh as a kernel 96 | parameter. However, it is enabled by default for backwards 97 | compatibility. 98 | ''; 99 | }; 100 | 101 | consoleMode = mkOption { 102 | default = "keep"; 103 | 104 | type = types.enum [ "0" "1" "2" "auto" "max" "keep" ]; 105 | 106 | description = '' 107 | The resolution of the console. The following values are valid: 108 | </para> 109 | <para> 110 | <itemizedlist> 111 | <listitem><para> 112 | <literal>"0"</literal>: Standard UEFI 80x25 mode 113 | </para></listitem> 114 | <listitem><para> 115 | <literal>"1"</literal>: 80x50 mode, not supported by all devices 116 | </para></listitem> 117 | <listitem><para> 118 | <literal>"2"</literal>: The first non-standard mode provided by the device firmware, if any 119 | </para></listitem> 120 | <listitem><para> 121 | <literal>"auto"</literal>: Pick a suitable mode automatically using heuristics 122 | </para></listitem> 123 | <listitem><para> 124 | <literal>"max"</literal>: Pick the highest-numbered available mode 125 | </para></listitem> 126 | <listitem><para> 127 | <literal>"keep"</literal>: Keep the mode selected by firmware (the default) 128 | </para></listitem> 129 | </itemizedlist> 130 | ''; 131 | }; 132 | }; 133 | 134 | config = mkIf cfg.enable { 135 | assertions = [ 136 | { 137 | assertion = (config.boot.kernelPackages.kernel.features or { efiBootStub = true; }) ? efiBootStub; 138 | 139 | message = "This kernel does not support the EFI boot stub"; 140 | } 141 | ]; 142 | 143 | boot.loader.grub.enable = mkDefault false; 144 | 145 | boot.loader.supportsInitrdSecrets = true; 146 | 147 | system = { 148 | build.installBootLoader = gummibootBuilder; 149 | 150 | boot.loader.id = "systemd-boot"; 151 | 152 | requiredKernelConfig = with config.lib.kernelConfig; [ 153 | (isYes "EFI_STUB") 154 | ]; 155 | }; 156 | }; 157 | } 158 | -------------------------------------------------------------------------------- /packages/systemd-lock-handler/default.nix: -------------------------------------------------------------------------------- 1 | { runCommand, python3 }: 2 | runCommand "systemd-lock-handler" { 3 | # locker.py is from 4 | # https://github.com/grawity/code/blob/master/desktop/systemd-lock-handler 5 | # with my own patches to remove the need for an XDG_SESSION_ID. 6 | buildInputs = [ 7 | (python3.withPackages (ps: with ps; [ dbus-python pygobject3 ])) 8 | ]; 9 | } 10 | '' 11 | cp ${./locker.py} ./locker.py 12 | chmod 777 ./locker.py 13 | patchShebangs ./locker.py 14 | cp ./locker.py $out 15 | '' 16 | -------------------------------------------------------------------------------- /packages/systemd-lock-handler/locker.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # systemd-lock-handler -- proxy between systemd-logind's "Lock" signal and your 3 | # favourite screen lock command 4 | 5 | from __future__ import print_function 6 | import os, sys, dbus, dbus.mainloop.glib 7 | from gi.repository import GLib 8 | from pprint import pprint 9 | 10 | def trace(*args): 11 | global arg0 12 | print("%s:" % arg0, *args) 13 | 14 | def setup_signal(signal_handler): 15 | bus = dbus.SystemBus() 16 | manager = bus.get_object("org.freedesktop.login1", "/org/freedesktop/login1") 17 | # yecch 18 | manager = dbus.Interface(manager, "org.freedesktop.login1.Manager") 19 | all_sessions = manager.ListSessions() 20 | session_ids = [session[0] for session in all_sessions if session[1] == os.getuid()] 21 | if len(session_ids) > 1: 22 | print("Found multiple session IDs but this only supports one, bailing:") 23 | pprint(session_ids) 24 | pprint(all_sessions) 25 | abort 26 | elif not session_ids: 27 | print("Found no session IDs, bailing:") 28 | pprint(session_ids) 29 | pprint(all_sessions) 30 | abort 31 | 32 | session_path = manager.GetSession(session_ids[0]) 33 | session = bus.get_object("org.freedesktop.login1", session_path) 34 | session.connect_to_signal("Lock", signal_handler) 35 | 36 | def handler_dbus_fdo(): 37 | trace("locking session using DBus") 38 | bus = dbus.SessionBus() 39 | screensaver = bus.get_object("org.freedesktop.ScreenSaver", "/ScreenSaver") 40 | screensaver.Lock() 41 | 42 | def handler_external(): 43 | global lock_command 44 | trace("locking session using %r" % lock_command[0]) 45 | os.spawnvp(os.P_NOWAIT, lock_command[0], lock_command) 46 | 47 | def main(): 48 | global arg0, lock_command 49 | arg0 = sys.argv[0].split("/")[-1] 50 | lock_command = sys.argv[1:] or ["--dbus"] 51 | dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) 52 | if lock_command == ["--dbus"]: 53 | trace("using freedesktop.org DBus API") 54 | setup_signal(handler_dbus_fdo) 55 | else: 56 | trace("using external command %r" % lock_command[0]) 57 | setup_signal(handler_external) 58 | trace("waiting for lock signals") 59 | try: 60 | loop = GLib.MainLoop() 61 | loop.run() 62 | except KeyboardInterrupt: 63 | sys.exit(0) 64 | 65 | main() 66 | -------------------------------------------------------------------------------- /packages/systemd-lock-handler/service.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | { 3 | systemd.services.loginctl-trigger-lock-on-sleep = { 4 | before = [ "sleep.target" ]; 5 | wantedBy = [ "sleep.target" ]; 6 | script = "loginctl lock-sessions"; 7 | }; 8 | 9 | systemd.user.services.lock-screen-hook = { 10 | wantedBy = [ "graphical-session.target" ]; 11 | script = '' 12 | ${pkgs.systemd-lock-handler} ${pkgs.i3lock}/bin/i3lock -fi ${pkgs.nixos-artwork.wallpapers.gnome-dark}/share/artwork/gnome/nix-wallpaper-simple-dark-gray_bottom.png 13 | ''; 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /packages/timeout/default.nix: -------------------------------------------------------------------------------- 1 | { mutate, expect }: 2 | mutate ./timeout.tcl { 3 | inherit expect; 4 | } 5 | -------------------------------------------------------------------------------- /packages/timeout/timeout.tcl: -------------------------------------------------------------------------------- 1 | #!@expect@/bin/expect 2 | 3 | if {$argc < "2"} { 4 | send_user "$argv0 timeout script\n" 5 | send_user "\n" 6 | send_user "Example: $argv 5 fetchmail.sh\n" 7 | exit 1 8 | } 9 | 10 | 11 | set timeout [lindex $argv 0] 12 | exit -onexit { 13 | catch {close} 14 | wait 15 | } 16 | 17 | spawn {*}[lrange $argv 1 end] 18 | 19 | 20 | expect { 21 | -re ".+" { 22 | exp_continue 23 | } 24 | 25 | timeout { 26 | send_user "\n<timeout>\n" 27 | } 28 | 29 | eof { 30 | send_user "\n<eof>\n" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/ttf-console-font/default.nix: -------------------------------------------------------------------------------- 1 | # from githubusercontent.com/thefloweringash/kevin-nix/master/packages/ttf-console-font.nix 2 | # Ported from http://urchlay.naptime.net/repos/ttf-console-fonts 3 | # Upstream license is WTFPL (http://www.wtfpl.net/txt/copying) 4 | 5 | { stdenv, lib, runCommand, otf2bdf, bdf2psf }: 6 | 7 | { fontfile, dpi, ptSize }: 8 | 9 | let 10 | bdf2psf-data = "${bdf2psf}/usr/share/bdf2psf"; 11 | in 12 | 13 | runCommand "ttf-console-font" { 14 | buildInputs = [ otf2bdf bdf2psf ]; 15 | sets = lib.concatStringsSep "+" (map (x: "${bdf2psf-data}/${x}") [ 16 | "ascii.set" 17 | "linux.set" 18 | "fontsets/Lat2.256" 19 | "fontsets/Uni1.512" 20 | "useful.set" 21 | ]); 22 | } '' 23 | otf2bdf ${fontfile} -r ${toString dpi} -p ${toString ptSize} -o tmp.bdf 24 | 25 | AV=$( sed -n 's,AVERAGE_WIDTH ,,p' tmp.bdf ) 26 | AV=$(( ( AV + 30 ) / 10 * 10 )) 27 | sed -i "/AVERAGE_WIDTH/s, .*, $AV," tmp.bdf 28 | 29 | bdf2psf --fb tmp.bdf ${bdf2psf-data}/standard.equivalents $sets 512 $out 30 | '' 31 | -------------------------------------------------------------------------------- /packages/ttf-console-font/service.nix: -------------------------------------------------------------------------------- 1 | # from https://raw.githubusercontent.com/thefloweringash/kevin-nix/master/modules/console-font.nix 2 | { config, pkgs, lib, ... }: 3 | 4 | let 5 | cfg = config.hardware.kevin.console-font; 6 | in 7 | 8 | { 9 | options = { 10 | hardware.kevin.console-font = with lib; { 11 | fontfile = mkOption { 12 | type = types.nullOr types.path; 13 | default = null; 14 | description = '' 15 | Path to ttf font to be used as the console font. 16 | ''; 17 | example = '' 18 | ''${pkgs.source-code-pro}/share/fonts/opentype/SourceCodePro-Regular.otf 19 | ''; 20 | }; 21 | 22 | dpi = mkOption { 23 | type = types.int; 24 | default = 192; 25 | description = '' 26 | DPI to render console font at. 27 | ''; 28 | }; 29 | 30 | ptSize = mkOption { 31 | type = types.int; 32 | default = 9; 33 | description = '' 34 | Font size in points of console font. 35 | ''; 36 | }; 37 | }; 38 | }; 39 | 40 | config = lib.mkIf (cfg.fontfile != null) { 41 | boot.earlyVconsoleSetup = true; 42 | 43 | i18n.consoleFont = toString (pkgs.ttf-console-font { 44 | inherit (cfg) fontfile dpi ptSize; 45 | }); 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /packages/vault-plugin-secrets-oauthapp/default.nix: -------------------------------------------------------------------------------- 1 | { buildGoModule, fetchFromGitHub }: 2 | buildGoModule { 3 | name = "vault-plugin-secrets-oauthapp"; 4 | version = "1.1.1"; 5 | src = fetchFromGitHub { 6 | owner = "puppetlabs"; 7 | repo = "vault-plugin-secrets-oauthapp"; 8 | rev = "v1.1.1"; 9 | sha256 = "1i0mp6br6n4pyxkfd4w3pccfdawfj7zwia5xn52dabqdjb54m39h"; 10 | }; 11 | modSha256 = "1ymbxnvxp0xa611mz010an3mjqh4asd6b1wc401jmq5rrmf9lnjx"; 12 | vendorSha256 = "03s2s28a660i4laf0cmcvpkc3hvdvjayvzbznd9rhqp8fvw48d1a"; 13 | subPackages = [ "cmd/vault-plugin-secrets-oauthapp" ]; 14 | } 15 | -------------------------------------------------------------------------------- /packages/volume/default.nix: -------------------------------------------------------------------------------- 1 | { mutate, pulseaudioFull, coreutils, gnugrep }: 2 | mutate ./volume.sh { 3 | inherit pulseaudioFull coreutils gnugrep; 4 | } 5 | -------------------------------------------------------------------------------- /packages/volume/volume.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eu 4 | 5 | PATH="@pulseaudioFull@/bin/:@gnugrep@/bin/:@coreutils@/bin" 6 | 7 | CURVOL=$(pactl list sinks | grep Volume | cut -d"/" -f4 | cut -d% -f1) 8 | 9 | if [ "$1" = "up" ]; then 10 | CMP="-ge" 11 | else 12 | CMP="-gt" 13 | fi 14 | 15 | if [ $CURVOL $CMP 30 ]; then 16 | incr=10; 17 | elif [ $CURVOL $CMP 5 ]; then 18 | incr=5 19 | else 20 | incr=1 21 | fi 22 | 23 | if [ $CURVOL -ge 100 ] && [ "$1" = "up" ]; then 24 | # Don't go up! 25 | incr=0 26 | fi 27 | 28 | if [ "$1" = "up" ]; then 29 | pactl set-sink-volume @DEFAULT_SINK@ +$incr% 30 | else 31 | pactl set-sink-volume @DEFAULT_SINK@ -$incr% 32 | fi 33 | -------------------------------------------------------------------------------- /packages/wl-freeze/default.nix: -------------------------------------------------------------------------------- 1 | { resholve, coreutils, gnugrep, utillinux, jq, systemd, sway, gnused }: 2 | # Kill the cgroup of the focused window 3 | resholve { 4 | src = ./wl-freeze.sh; 5 | inputs = [ coreutils jq gnugrep utillinux systemd sway gnused ]; 6 | } 7 | 8 | -------------------------------------------------------------------------------- /packages/wl-freeze/wl-freeze.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env nix-shell 2 | #!nix-shell -i bash -p jq shellcheck 3 | # shellcheck shell=bash 4 | 5 | 6 | set -eu 7 | 8 | if [ -z "${NOT_BUFFERED:-}" ]; then 9 | export NOT_BUFFERED=1 10 | exec stdbuf -oL -eL bash "$0" 11 | fi 12 | 13 | err() { 14 | echo "$@" >&2 15 | } 16 | 17 | scope_cache=$(mktemp freezer.XXXX -t) 18 | trap cleanup EXIT 19 | 20 | cleanup() { 21 | local scope 22 | while read -r scope; do 23 | echo 0 > "$scope/cgroup.freeze" || true 24 | done < "$scope_cache" 25 | rm "$scope_cache" 26 | } 27 | 28 | scopedirforpid() { 29 | local pid=$1 30 | local scope 31 | 32 | scope=$(cut -d: -f3- "/proc/$pid/cgroup") 33 | if [ -z "$scope" ]; then 34 | err "Determining scope failed: empty. Too dangerous. Aborting." 35 | exit 1 36 | fi 37 | 38 | local cgroupdir="/sys/fs/cgroup/$scope" 39 | 40 | if [ ! -d "$cgroupdir" ]; then 41 | err "Determining my scope failed: not a dir: $cgroupdir" 42 | exit 1 43 | fi 44 | 45 | echo "$cgroupdir" 46 | } 47 | 48 | 49 | freezer() { 50 | local my_scopedir="$1" 51 | local last_scopedir="" 52 | local scope 53 | while read -r scope; do 54 | printf "Entering %s\n" "$scope" 55 | if [ -z "$last_scopedir" ]; then 56 | printf "\tprevious scope unknown\n" 57 | printf "\t=> not freezing\n" 58 | elif [ "$last_scopedir" == "$my_scopedir" ]; then 59 | printf "\tprevious scope was our protected scope\n" 60 | printf "\t=> not freezing\n" 61 | else 62 | printf "\tprevious scope: %s\n" "$last_scopedir" 63 | printf "\t=> freezing\n" 64 | 65 | # Race condition: if these processes are exiting, these 66 | # freeze files may no longer exist. Ignore failures. 67 | echo 1 > "$last_scopedir/cgroup.freeze" || true 68 | echo "$last_scopedir" >> "$scope_cache" 69 | fi 70 | 71 | # Race condition: if these processes are exiting, these 72 | # freeze files may no longer exist. Ignore failures. 73 | echo 0 > "$scope/cgroup.freeze" || true 74 | sed -i "\_${scope}_d" "$scope_cache" 75 | last_scopedir="$scope" 76 | done 77 | } 78 | 79 | main() { 80 | # check if kernel parameter is set 81 | if ! grep -Fq "cgroup_no_v1=all" "/proc/cmdline"; then 82 | err "To use this script you have to set the kernel paramet 'cgroup_no_v1' to 'all'" 83 | err "Please add this to your kernel parameters:" 84 | printf '"cgroup_no_v1=all"' 85 | exit 2 86 | fi 87 | 88 | local myscopedir 89 | myscopedir=$(scopedirforpid "$PPID") 90 | echo "Will not freeze $myscopedir" 91 | 92 | swaymsg -m -t subscribe '["window"]' \ 93 | | tee /dev/stderr \ 94 | | jq '.container.pid' \ 95 | | (while read -r pid; do scopedirforpid "$pid"; done) \ 96 | | grep -E 'run-[[:alnum:]].*\.scope$' \ 97 | | freezer "$myscopedir" 98 | 99 | } 100 | 101 | 102 | main 103 | -------------------------------------------------------------------------------- /packages/zsh-config/default.nix: -------------------------------------------------------------------------------- 1 | { mutate }: 2 | mutate ./zshrc {} 3 | -------------------------------------------------------------------------------- /packages/zsh-config/zshrc: -------------------------------------------------------------------------------- 1 | export RPROMPT= 2 | eval "$(h --setup ~/projects)" 3 | -------------------------------------------------------------------------------- /pubkey: -------------------------------------------------------------------------------- 1 | ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDUy2CGT6P3q2kApZEuyCHsuCruwdRzeWMdQe/WjdCak grahamc@Petunia 2 | -------------------------------------------------------------------------------- /warning: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | .i;;;;i. 6 | iYcviii;vXY: 7 | .YXi .i1c. 8 | .YC. . in7. 9 | .vc. ...... ;1c. 10 | i7, .. .;1; 11 | i7, .. ... .Y1i 12 | ,7v .6MMM@; .YX, 13 | .7;. ..IMMMMMM1 :t7. 14 | .;Y. ;$MMMMMM9. :tc. 15 | vY. .. .nMMM@MMU. ;1v. 16 | i7i ... .#MM@M@C. .....:71i 17 | it: .... $MMM@9;.,i;;;i,;tti 18 | :t7. ..... 0MMMWv.,iii:::,,;St. 19 | .nC. ..... IMMMQ..,::::::,.,czX. 20 | .ct: ....... .ZMMMI..,:::::::,,:76Y. 21 | c2: ......,i..Y$M@t..:::::::,,..inZY 22 | vov ......:ii..c$MBc..,,,,,,,,,,..iI9i 23 | i9Y ......iii:..7@MA,..,,,,,,,,,....;AA: 24 | iIS. ......:ii::..;@MI....,............;Ez. 25 | .I9. ......:i::::...8M1..................C0z. 26 | .z9; ......:i::::,.. .i:...................zWX. 27 | vbv ......,i::::,,. ................. :AQY 28 | c6Y. .,...,::::,,..:t0@@QY. ................ :8bi 29 | :6S. ..,,...,:::,,,..EMMMMMMI. ............... .;bZ, 30 | :6o, .,,,,..:::,,,..i#MMMMMM#v................. YW2. 31 | .n8i ..,,,,,,,::,,,,.. tMMMMM@C:.................. .1Wn 32 | 7Uc. .:::,,,,,::,,,,.. i1t;,..................... .UEi 33 | 7C...::::::::::::,,,,.. .................... vSi. 34 | ;1;...,,::::::,......... .................. Yz: 35 | v97,......... .voC. 36 | izAotX7777777777777777777777777777777777777777Y7n92: 37 | .;CoIIIIIUAA666666699999ZZZZZZZZZZZZZZZZZZZZ6ov. 38 | --------------------------------------------------------------------------------