Compare commits

..

1 Commits

Author SHA1 Message Date
a17ad5fbf2 moby: build/deploy kaiteki 2022-10-09 04:17:04 -07:00
142 changed files with 2655 additions and 2869 deletions

View File

@@ -23,7 +23,6 @@ creation_rules:
key_groups: key_groups:
- age: - age:
- *user_desko_colin - *user_desko_colin
- *user_lappy_colin
- *user_servo_colin - *user_servo_colin
- *host_servo - *host_servo
- path_regex: secrets/desko.yaml$ - path_regex: secrets/desko.yaml$
@@ -32,16 +31,3 @@ creation_rules:
- *user_desko_colin - *user_desko_colin
- *user_lappy_colin - *user_lappy_colin
- *host_desko - *host_desko
- path_regex: secrets/lappy.yaml$
key_groups:
- age:
- *user_lappy_colin
- *user_desko_colin
- *host_lappy
- path_regex: secrets/moby.yaml$
key_groups:
- age:
- *user_desko_colin
- *user_lappy_colin
- *user_moby_colin
- *host_moby

16
TODO.md Normal file
View File

@@ -0,0 +1,16 @@
# features/tweaks
- emoji picker application
- find a Masto/Pleroma app which works on mobile
- remove hardcoded uid/gids outside of allocations.nix (used in impermanence code -- replace with username/groupname)
# speed up cross compiling
- <https://nixos.wiki/wiki/Cross_Compiling>
- <https://nixos.wiki/wiki/NixOS_on_ARM>
```nix
overlays = [{ ... }: {
nixpkgs.crossSystem.system = "aarch64-linux";
}];
```
- <https://github.com/nix-community/aarch64-build-box>
- apply for access to the community arm build box

101
flake.lock generated
View File

@@ -1,20 +1,5 @@
{ {
"nodes": { "nodes": {
"flake-utils": {
"locked": {
"lastModified": 1659877975,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"home-manager": { "home-manager": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@@ -22,11 +7,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1667907331, "lastModified": 1656169755,
"narHash": "sha256-bHkAwkYlBjkupPUFcQjimNS8gxWSWjOTevEuwdnp5m0=", "narHash": "sha256-Nlnm4jeQWEGjYrE6hxi/7HYHjBSZ/E0RtjCYifnNsWk=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "6639e3a837fc5deb6f99554072789724997bc8e5", "rev": "4a3d01fb53f52ac83194081272795aa4612c2381",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -38,11 +23,11 @@
}, },
"impermanence": { "impermanence": {
"locked": { "locked": {
"lastModified": 1668668915, "lastModified": 1661933071,
"narHash": "sha256-QjY4ZZbs9shwO4LaLpvlU2bO9J1juYhO9NtV3nrbnYQ=", "narHash": "sha256-RFgfzldpbCvS+H2qwH+EvNejvqs+NhPVD5j1I7HQQPY=",
"owner": "nix-community", "owner": "nix-community",
"repo": "impermanence", "repo": "impermanence",
"rev": "5df9108b346f8a42021bf99e50de89c9caa251c3", "rev": "def994adbdfc28974e87b0e4c949e776207d5557",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -54,11 +39,11 @@
"mobile-nixos": { "mobile-nixos": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1668897543, "lastModified": 1664852186,
"narHash": "sha256-1bjvy5zi/6KDzhN3ihOUEA6y5FFEOf5xvIbf65RWIh0=", "narHash": "sha256-t0FhmTf3qRs8ScR8H9Rq7FAxptNELLSpxZG2ALL1HnE=",
"owner": "nixos", "owner": "nixos",
"repo": "mobile-nixos", "repo": "mobile-nixos",
"rev": "25eec596116553112681d72ee4880107fc3957fa", "rev": "ca872f1a617674c4045e880aab8a45037e73700b",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -69,11 +54,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1668994630, "lastModified": 1665081174,
"narHash": "sha256-1lqx6HLyw6fMNX/hXrrETG1vMvZRGm2XVC9O/Jt0T6c=", "narHash": "sha256-6hsmzdhdy8Kbvl5e0xZNE83pW3fKQvNiobJkM6KQrgA=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "af50806f7c6ab40df3e6b239099e8f8385f6c78b", "rev": "598f83ebeb2235435189cf84d844b8b73e858e0f",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -84,11 +69,11 @@
}, },
"nixpkgs-22_05": { "nixpkgs-22_05": {
"locked": { "locked": {
"lastModified": 1668908668, "lastModified": 1665279158,
"narHash": "sha256-oimCE4rY7Btuo/VYmA8khIyTHSMV7qUWTpz9w8yc9LQ=", "narHash": "sha256-TpbWNzoJ5RaZ302dzvjY2o//WxtOJuYT3CnDj5N69Hs=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "b68a6a27adb452879ab66c0eaac0c133e32823b2", "rev": "b3783bcfb8ec54e0de26feccfc6cc36b8e202ed5",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -100,11 +85,11 @@
}, },
"nixpkgs-stable": { "nixpkgs-stable": {
"locked": { "locked": {
"lastModified": 1668984258, "lastModified": 1665132027,
"narHash": "sha256-0gDMJ2T3qf58xgcSbYoXiRGUkPWmKyr5C3vcathWhKs=", "narHash": "sha256-zoHPqSQSENt96zTk6Mt1AP+dMNqQDshXKQ4I6MfjP80=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "cf63ade6f74bbc9d2a017290f1b2e33e8fbfa70a", "rev": "9ecc270f02b09b2f6a76b98488554dd842797357",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -113,6 +98,22 @@
"type": "indirect" "type": "indirect"
} }
}, },
"nixpkgs_2": {
"locked": {
"lastModified": 1665197809,
"narHash": "sha256-dRUzv/zNYV2EYtnxFG31pPBk0nErT+MBTu6ZJHm1o2A=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "7b06206fa24198912cea58de690aa4943f238fbf",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": { "root": {
"inputs": { "inputs": {
"home-manager": "home-manager", "home-manager": "home-manager",
@@ -120,23 +121,20 @@
"mobile-nixos": "mobile-nixos", "mobile-nixos": "mobile-nixos",
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs",
"nixpkgs-stable": "nixpkgs-stable", "nixpkgs-stable": "nixpkgs-stable",
"sops-nix": "sops-nix", "sops-nix": "sops-nix"
"uninsane": "uninsane"
} }
}, },
"sops-nix": { "sops-nix": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": "nixpkgs_2",
"nixpkgs"
],
"nixpkgs-22_05": "nixpkgs-22_05" "nixpkgs-22_05": "nixpkgs-22_05"
}, },
"locked": { "locked": {
"lastModified": 1668915833, "lastModified": 1665289655,
"narHash": "sha256-7VYPiDJZdGct8Nl3kKhg580XZfoRcViO+zUGPkfBsqM=", "narHash": "sha256-j1Q9mNBhbzeJykhObiXwEGres9qvP4vH7gxdJ+ihkLI=",
"owner": "Mic92", "owner": "Mic92",
"repo": "sops-nix", "repo": "sops-nix",
"rev": "f72e050c3ef148b1131a0d2df55385c045e4166b", "rev": "0ce0449e6404c4ff9d1b7bd657794ae5ca54deb3",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -144,27 +142,6 @@
"repo": "sops-nix", "repo": "sops-nix",
"type": "github" "type": "github"
} }
},
"uninsane": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1666870107,
"narHash": "sha256-b9eXZxSwhzdJI5uQgfrMhu4SY2POrPkinUg7F5gQVYo=",
"ref": "refs/heads/master",
"rev": "80c6ec95bd430e29d231cf745f19279bb76fb382",
"revCount": 164,
"type": "git",
"url": "https://git.uninsane.org/colin/uninsane"
},
"original": {
"type": "git",
"url": "https://git.uninsane.org/colin/uninsane"
}
} }
}, },
"root": "root", "root": "root",

View File

@@ -14,27 +14,13 @@
url = "github:nix-community/home-manager/release-22.05"; url = "github:nix-community/home-manager/release-22.05";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
sops-nix = { # TODO: set these up to follow our nixpkgs?
url = "github:Mic92/sops-nix"; sops-nix.url = "github:Mic92/sops-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
impermanence.url = "github:nix-community/impermanence"; impermanence.url = "github:nix-community/impermanence";
uninsane = {
url = "git+https://git.uninsane.org/colin/uninsane";
inputs.nixpkgs.follows = "nixpkgs";
};
}; };
outputs = { outputs = { self, nixpkgs, nixpkgs-stable, mobile-nixos, home-manager, sops-nix, impermanence }:
self, let
nixpkgs,
nixpkgs-stable,
mobile-nixos,
home-manager,
sops-nix,
impermanence,
uninsane
}: let
patchedPkgs = system: nixpkgs.legacyPackages.${system}.applyPatches { patchedPkgs = system: nixpkgs.legacyPackages.${system}.applyPatches {
name = "nixpkgs-patched-uninsane"; name = "nixpkgs-patched-uninsane";
src = nixpkgs; src = nixpkgs;
@@ -45,7 +31,7 @@
nixpkgsFor = local: target: import (patchedPkgs target) { crossSystem = target; localSystem = local; }; nixpkgsFor = local: target: import (patchedPkgs target) { crossSystem = target; localSystem = local; };
# evaluate ONLY our overlay, for the provided system # evaluate ONLY our overlay, for the provided system
customPackagesFor = local: target: import ./pkgs/overlay.nix (nixpkgsFor local target) (nixpkgsFor local target); customPackagesFor = local: target: import ./pkgs/overlay.nix (nixpkgsFor local target) (nixpkgsFor local target);
decl-host = { name, local, target }: decl-machine = { name, local, target }:
let let
nixosSystem = import ((patchedPkgs target) + "/nixos/lib/eval-config.nix"); nixosSystem = import ((patchedPkgs target) + "/nixos/lib/eval-config.nix");
in (nixosSystem { in (nixosSystem {
@@ -54,14 +40,15 @@
specialArgs = { inherit mobile-nixos home-manager impermanence; }; specialArgs = { inherit mobile-nixos home-manager impermanence; };
modules = [ modules = [
./modules ./modules
(import ./hosts/instantiate.nix name) ./machines/${name}
(import ./helpers/set-hostname.nix name)
home-manager.nixosModule home-manager.nixosModule
impermanence.nixosModule impermanence.nixosModule
sops-nix.nixosModules.sops sops-nix.nixosModules.sops
{ {
nixpkgs.config.allowUnfree = true;
nixpkgs.overlays = [ nixpkgs.overlays = [
(import "${mobile-nixos}/overlay/overlay.nix") (import "${mobile-nixos}/overlay/overlay.nix")
uninsane.overlay
(import ./pkgs/overlay.nix) (import ./pkgs/overlay.nix)
(next: prev: rec { (next: prev: rec {
# non-emulated packages build *from* local *for* target. # non-emulated packages build *from* local *for* target.
@@ -69,16 +56,16 @@
# the config can explicitly pull such packages from `pkgs.cross` to do more efficient cross-compilation. # the config can explicitly pull such packages from `pkgs.cross` to do more efficient cross-compilation.
cross = (nixpkgsFor local target) // (customPackagesFor local target); cross = (nixpkgsFor local target) // (customPackagesFor local target);
stable = import nixpkgs-stable { system = target; }; stable = import nixpkgs-stable { system = target; };
# cross-compatible packages # pinned packages:
# gocryptfs = cross.gocryptfs; electrum = stable.electrum;
}) })
]; ];
} }
]; ];
}); });
decl-bootable-host = { name, local, target }: rec { decl-bootable-machine = { name, local, target }: rec {
nixosConfiguration = decl-host { inherit name local target; }; nixosConfiguration = decl-machine { inherit name local target; };
# this produces a EFI-bootable .img file (GPT with a /boot partition and a system (/ or /nix) partition). # this produces a EFI-bootable .img file (GPT with a /boot partition and a system (/ or /nix) partition).
# after building this: # after building this:
# - flash it to a bootable medium (SD card, flash drive, HDD) # - flash it to a bootable medium (SD card, flash drive, HDD)
@@ -91,31 +78,24 @@
# - boot # - boot
# - if fs wasn't resized automatically, then `sudo btrfs filesystem resize max /` # - if fs wasn't resized automatically, then `sudo btrfs filesystem resize max /`
# - checkout this flake into /etc/nixos AND UPDATE THE FS UUIDS. # - checkout this flake into /etc/nixos AND UPDATE THE FS UUIDS.
# - `nixos-rebuild --flake './#<host>' switch` # - `nixos-rebuild --flake './#<machine>' switch`
img = nixosConfiguration.config.system.build.img; img = nixosConfiguration.config.system.build.img;
}; };
hosts.servo = decl-bootable-host { name = "servo"; local = "x86_64-linux"; target = "x86_64-linux"; }; machines.servo = decl-bootable-machine { name = "servo"; local = "aarch64-linux"; target = "aarch64-linux"; };
hosts.desko = decl-bootable-host { name = "desko"; local = "x86_64-linux"; target = "x86_64-linux"; }; machines.desko = decl-bootable-machine { name = "desko"; local = "x86_64-linux"; target = "x86_64-linux"; };
hosts.lappy = decl-bootable-host { name = "lappy"; local = "x86_64-linux"; target = "x86_64-linux"; }; machines.lappy = decl-bootable-machine { name = "lappy"; local = "x86_64-linux"; target = "x86_64-linux"; };
hosts.moby = decl-bootable-host { name = "moby"; local = "aarch64-linux"; target = "aarch64-linux"; }; machines.moby = decl-bootable-machine { name = "moby"; local = "aarch64-linux"; target = "aarch64-linux"; };
# special cross-compiled variant, to speed up deploys from an x86 box to the arm target # special cross-compiled variant, to speed up deploys from an x86 box to the arm target
# note that these *do* produce different store paths, because the closure for the tools used to cross compile # note that these *do* produce different store paths, because the closure for the tools used to cross compile
# v.s. emulate differ. # v.s. emulate differ.
# so deploying foo-cross and then foo incurs some rebuilding. # so deploying moby-cross and then moby incurs some rebuilding.
hosts.moby-cross = decl-bootable-host { name = "moby"; local = "x86_64-linux"; target = "aarch64-linux"; }; machines.moby-cross = decl-bootable-machine { name = "moby"; local = "x86_64-linux"; target = "aarch64-linux"; };
hosts.rescue = decl-bootable-host { name = "rescue"; local = "x86_64-linux"; target = "x86_64-linux"; }; machines.rescue = decl-bootable-machine { name = "rescue"; local = "x86_64-linux"; target = "x86_64-linux"; };
in { in {
nixosConfigurations = builtins.mapAttrs (name: value: value.nixosConfiguration) hosts; nixosConfigurations = builtins.mapAttrs (name: value: value.nixosConfiguration) machines;
imgs = builtins.mapAttrs (name: value: value.img) hosts; imgs = builtins.mapAttrs (name: value: value.img) machines;
packages = let packages.x86_64-linux = customPackagesFor "x86_64-linux" "x86_64-linux";
allPkgsFor = sys: (customPackagesFor sys sys) // { packages.aarch64-linux = customPackagesFor "aarch64-linux" "aarch64-linux";
nixpkgs = nixpkgsFor sys sys;
uninsane = uninsane.packages."${sys}";
};
in {
x86_64-linux = allPkgsFor "x86_64-linux";
aarch64-linux = allPkgsFor "aarch64-linux";
};
}; };
} }

4
helpers/set-hostname.nix Normal file
View File

@@ -0,0 +1,4 @@
hostName: { ... }:
{
networking.hostName = hostName;
}

View File

@@ -1,74 +0,0 @@
{ pkgs, ... }:
{
imports = [
./fs.nix
./hardware
./machine-id.nix
./net.nix
./secrets.nix
./ssh.nix
./users.nix
./vpn.nix
];
sane.home-manager.enable = true;
sane.nixcache.enable-trusted-keys = true;
sane.packages.enableConsolePkgs = true;
sane.packages.enableSystemPkgs = true;
nixpkgs.config.allowUnfree = true;
# time.timeZone = "America/Los_Angeles";
time.timeZone = "Etc/UTC"; # DST is too confusing for me => use a stable timezone
# allow `nix flake ...` command
nix.extraOptions = ''
experimental-features = nix-command flakes
'';
# TODO: move this into home-manager?
fonts = {
enableDefaultFonts = true;
fonts = with pkgs; [ font-awesome twitter-color-emoji hack-font ];
fontconfig.enable = true;
fontconfig.defaultFonts = {
emoji = [ "Font Awesome 6 Free" "Twitter Color Emoji" ];
monospace = [ "Hack" ];
serif = [ "DejaVu Serif" ];
sansSerif = [ "DejaVu Sans" ];
};
};
# disable non-required packages like nano, perl, rsync, strace
environment.defaultPackages = [];
# programs.vim.defaultEditor = true;
environment.variables = {
EDITOR = "vim";
# git claims it should use EDITOR, but it doesn't!
GIT_EDITOR = "vim";
# TODO: these should be moved to `home.sessionVariables` (home-manager)
# Electron apps should use native wayland backend:
# https://nixos.wiki/wiki/Slack#Wayland
# Discord under sway crashes with this.
# NIXOS_OZONE_WL = "1";
# LIBGL_ALWAYS_SOFTWARE = "1";
};
# enable zsh completions
environment.pathsToLink = [ "/share/zsh" ];
environment.systemPackages = with pkgs; [
# required for pam_mount
gocryptfs
];
# link debug symbols into /run/current-system/sw/lib/debug
# hopefully picked up by gdb automatically?
environment.enableDebugInfo = true;
security.pam.mount.enable = true;
# security.pam.mount.debugLevel = 1;
# security.pam.enableSSHAgentAuth = true; # ??
# needed for `allow_other` in e.g. gocryptfs mounts
# or i guess going through mount.fuse sets suid so that's not necessary?
# programs.fuse.userAllowOther = true;
}

View File

@@ -1,11 +0,0 @@
{ ... }:
{
# we wan't an /etc/machine-id which is consistent across boot so that `journalctl` will actually show us
# logs from previous boots.
# maybe there's a config option for this (since persistent machine-id is bad for reasons listed in impermanence.nix),
# but for now generate it from ssh keys.
system.activationScripts.machine-id = {
deps = [ "persist-ssh-host-keys" ];
text = "sha256sum /etc/ssh/host_keys/ssh_host_ed25519_key | cut -c 1-32 > /etc/machine-id";
};
}

View File

@@ -1,21 +0,0 @@
{ ... }:
{
# we place the host keys (which we want to be persisted) into their own directory so that we can
# bind mount that whole directory instead of doing it per-file.
# otherwise, this is identical to nixos defaults
sane.impermanence.service-dirs = [ "/etc/ssh/host_keys" ];
# we can't naively `mount /etc/ssh/host_keys` directly,
# as /etc/fstab may not be populated yet (since that file depends on e.g. activationScripts.users)
# we can't even depend on impermanence's `createPersistentStorageDirs` to create the source/target directories
# since that also depends on `users`.
system.activationScripts.persist-ssh-host-keys.text = ''
mkdir -p /etc/ssh/host_keys
mount --bind /nix/persist/etc/ssh/host_keys /etc/ssh/host_keys
'';
services.openssh.hostKeys = [
{ type = "rsa"; bits = 4096; path = "/etc/ssh/host_keys/ssh_host_rsa_key"; }
{ type = "ed25519"; path = "/etc/ssh/host_keys/ssh_host_ed25519_key"; }
];
}

View File

@@ -1,10 +0,0 @@
# trampoline from flake.nix into the specific host definition, while doing a tiny bit of common setup
hostName: { ... }: {
imports = [
./${hostName}
./common
];
networking.hostName = hostName;
}

View File

@@ -1,98 +0,0 @@
{ ... }:
{
# root is a tmpfs so that we have an ephemeral system ("impermanence" handles the state)
fileSystems."/" = {
device = "none";
fsType = "tmpfs";
options = [
"mode=755"
"size=1G"
"defaults"
];
};
# we need a /tmp for building large nix things
fileSystems."/tmp" = {
device = "none";
fsType = "tmpfs";
options = [
"mode=777"
"defaults"
];
};
fileSystems."/nix" = {
device = "/dev/disk/by-uuid/cc81cca0-3cc7-4d82-a00c-6243af3e7776";
fsType = "btrfs";
options = [
"compress=zstd"
"defaults"
];
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/6EE3-4171";
fsType = "vfat";
};
# slow, external storage (for archiving, etc)
fileSystems."/nix/persist/ext" = {
device = "/dev/disk/by-uuid/aa272cff-0fcc-498e-a4cb-0d95fb60631b";
fsType = "btrfs";
options = [
"compress=zstd"
"defaults"
];
};
sane.impermanence.service-dirs = [
# TODO: this is overly broad; only need media and share directories to be persisted
{ user = "colin"; group = "users"; directory = "/var/lib/uninsane"; }
];
# direct these media directories to external storage
environment.persistence."/nix/persist/ext/persist" = {
directories = [
({
user = "colin";
group = "users";
mode = "0777";
directory = "/var/lib/uninsane/media/Videos";
})
({
user = "colin";
group = "users";
mode = "0777";
directory = "/var/lib/uninsane/media/freeleech";
})
];
};
# in-memory compressed RAM (seems to be dynamically sized)
# zramSwap = {
# enable = true;
# };
# btrfs doesn't easily support swapfiles
# swapDevices = [
# { device = "/nix/persist/swapfile"; size = 4096; }
# ];
# this can be a partition. create with:
# fdisk <dev>
# n
# <default partno>
# <start>
# <end>
# t
# <partno>
# 19 # set part type to Linux swap
# w # write changes
# mkswap -L swap <part>
# swapDevices = [
# {
# label = "swap";
# # TODO: randomEncryption.enable = true;
# }
# ];
}

View File

@@ -1,48 +0,0 @@
# docs:
# - <https://docs.ejabberd.im/admin/configuration/basic>
{ lib, ... }:
# XXX disabled: fails to start because of `mnesia_tm` dependency
# lib.mkIf false
{
sane.impermanence.service-dirs = [
{ user = "ejabberd"; group = "ejabberd"; directory = "/var/lib/ejabberd"; }
];
networking.firewall.allowedTCPPorts = [
5222 # XMPP client -> server
5269 # XMPP server -> server
];
# provide access to certs
users.users.ejabberd.extraGroups = [ "nginx" ];
# TODO: allocate UIDs/GIDs ?
services.ejabberd.enable = true;
services.ejabberd.configFile = builtins.toFile "ejabberd.yaml" ''
hosts:
- uninsane.org
# none | emergency | alert | critical | error | warning | notice | info | debug
loglevel: debug
acme:
auto: false
certfiles:
- /var/lib/acme/uninsane.org/fullchain.pem
- /var/lib/acme/uninsane.org/key.pem
pam_userinfotype: jid
# see: <https://docs.ejabberd.im/admin/configuration/listen/>
# TODO: host web admin panel
listen:
-
port: 5222
module: ejabberd_c2s
starttls: true
-
port: 5269
module: ejabberd_s2s_in
starttls: true
'';
}

View File

@@ -1,52 +0,0 @@
# import feeds with e.g.
# ```console
# $ nix build '.#nixpkgs.freshrss'
# $ sudo -u freshrss -g freshrss FRESHRSS_DATA_PATH=/var/lib/freshrss ./result/cli/import-for-user.php --user admin --filename /home/colin/.config/newsflashFeeds.opml
# ```
#
# export feeds with
# ```console
# $ sudo -u freshrss -g freshrss FRESHRSS_DATA_PATH=/var/lib/freshrss ./result/cli/export-opml-for-user.php --user admin
# ```
{ config, lib, pkgs, ... }:
{
sops.secrets.freshrss_passwd = {
sopsFile = ../../../secrets/servo.yaml;
owner = config.users.users.freshrss.name;
mode = "400";
};
sane.impermanence.service-dirs = [
{ user = "freshrss"; group = "freshrss"; directory = "/var/lib/freshrss"; }
];
users.users.freshrss.uid = config.sane.allocations.freshrss-uid;
users.groups.freshrss.gid = config.sane.allocations.freshrss-gid;
services.freshrss.enable = true;
services.freshrss.baseUrl = "https://rss.uninsane.org";
services.freshrss.virtualHost = "rss.uninsane.org";
services.freshrss.passwordFile = config.sops.secrets.freshrss_passwd.path;
systemd.services.freshrss-import-feeds =
let
fresh = config.systemd.services.freshrss-config;
feeds = import ../../../modules/home-manager/feeds.nix { inherit lib; };
opml = pkgs.writeText "sane-freshrss.opml" (feeds.feedsToOpml feeds.all);
in {
inherit (fresh) wantedBy environment;
serviceConfig = {
inherit (fresh.serviceConfig) Type User Group StateDirectory WorkingDirectory
# hardening options
CapabilityBoundingSet DeviceAllow LockPersonality NoNewPrivileges PrivateDevices PrivateTmp PrivateUsers ProcSubset ProtectClock ProtectControlGroups ProtectHome ProtectHostname ProtectKernelLogs ProtectKernelModules ProtectKernelTunables ProtectProc ProtectSystem RemoveIPC RestrictNamespaces RestrictRealtime RestrictSUIDSGID SystemCallArchitectures SystemCallFilter UMask;
};
description = "import sane RSS feed list";
after = [ "freshrss-config.service" ];
script = ''
${pkgs.freshrss}/cli/import-for-user.php --user admin --filename ${opml}
'';
};
# the default ("*:0/5") is to run every 5 minutes.
# `systemctl list-timers` to show
systemd.services.freshrss-updater.startAt = lib.mkForce "*:3/30";
}

View File

@@ -1,45 +0,0 @@
{ pkgs, ... }:
{
# based on <https://bytes.fyi/real-time-goaccess-reports-with-nginx/>
# log-format setting can be derived with this tool if custom:
# - <https://github.com/stockrt/nginx2goaccess>
# config options:
# - <https://github.com/allinurl/goaccess/blob/master/config/goaccess.conf>
systemd.services.goaccess = {
description = "GoAccess server monitoring";
serviceConfig = {
ExecStart = ''
${pkgs.goaccess}/bin/goaccess \
-f /var/log/nginx/public.log \
--log-format=VCOMBINED \
--real-time-html \
--html-refresh=30 \
--no-query-string \
--anonymize-ip \
--ignore-panel=HOSTS \
--ws-url=wss://sink.uninsane.org:443/ws \
--port=7890 \
-o /var/lib/uninsane/sink/index.html
'';
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
Type = "simple";
Restart = "on-failure";
# hardening
WorkingDirectory = "/tmp";
NoNewPrivileges = true;
PrivateTmp = true;
ProtectHome = "read-only";
ProtectSystem = "strict";
SystemCallFilter = "~@clock @cpu-emulation @debug @keyring @memlock @module @mount @obsolete @privileged @reboot @resources @setuid @swap @raw-io";
ReadOnlyPaths = "/";
ReadWritePaths = [ "/proc/self" "/var/lib/uninsane/sink" ];
PrivateDevices = "yes";
ProtectKernelModules = "yes";
ProtectKernelTunables = "yes";
};
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
};
}

View File

@@ -1,62 +0,0 @@
# create users with:
# - `sudo -u prosody prosodyctl adduser colin@uninsane.org`
{ lib, ... }:
# XXX disabled: doesn't send messages to nixnet.social (only receives them).
# nixnet runs ejabberd, so revisiting that.
lib.mkIf false
{
sane.impermanence.service-dirs = [
{ user = "prosody"; group = "prosody"; directory = "/var/lib/prosody"; }
];
networking.firewall.allowedTCPPorts = [
5222 # XMPP client -> server
5269 # XMPP server -> server
5280 # Prosody HTTP port (necessary?)
5281 # Prosody HTTPS port (necessary?)
];
# provide access to certs
users.users.prosody.extraGroups = [ "nginx" ];
security.acme.certs."uninsane.org".extraDomainNames = [
"conference.xmpp.uninsane.org"
"upload.xmpp.uninsane.org"
];
services.prosody = {
enable = true;
admins = [ "colin@uninsane.org" ];
# allowRegistration = false;
# extraConfig = ''
# s2s_require_encryption = true
# c2s_require_encryption = true
# '';
# extraModules = [ "private" "vcard" "privacy" "compression" "component" "muc" "pep" "adhoc" "lastactivity" "admin_adhoc" "blocklist"];
ssl.cert = "/var/lib/acme/uninsane.org/fullchain.pem";
ssl.key = "/var/lib/acme/uninsane.org/key.pem";
muc = [
{
domain = "conference.xmpp.uninsane.org";
}
];
uploadHttp.domain = "upload.xmpp.uninsane.org";
virtualHosts = {
localhost = {
domain = "localhost";
enabled = true;
};
"uninsane.org" = {
domain = "uninsane.org";
enabled = true;
ssl.cert = "/var/lib/acme/uninsane.org/fullchain.pem";
ssl.key = "/var/lib/acme/uninsane.org/key.pem";
};
};
};
}

View File

@@ -4,8 +4,6 @@
./fs.nix ./fs.nix
]; ];
# sane.packages.enableDevPkgs = true;
sane.gui.sway.enable = true; sane.gui.sway.enable = true;
sane.services.duplicity.enable = true; sane.services.duplicity.enable = true;
sane.services.nixserve.enable = true; sane.services.nixserve.enable = true;
@@ -20,11 +18,6 @@
users.users.usbmux.uid = config.sane.allocations.usbmux-uid; users.users.usbmux.uid = config.sane.allocations.usbmux-uid;
users.groups.usbmux.gid = config.sane.allocations.usbmux-gid; users.groups.usbmux.gid = config.sane.allocations.usbmux-gid;
sops.secrets.colin-passwd = {
sopsFile = ../../secrets/desko.yaml;
neededForUsers = true;
};
# default config: https://man.archlinux.org/man/snapper-configs.5 # default config: https://man.archlinux.org/man/snapper-configs.5
# defaults to something like: # defaults to something like:
# - hourly snapshots # - hourly snapshots

View File

@@ -4,8 +4,6 @@
./fs.nix ./fs.nix
]; ];
# sane.packages.enableDevPkgs = true;
# sane.users.guest.enable = true; # sane.users.guest.enable = true;
sane.gui.sway.enable = true; sane.gui.sway.enable = true;
sane.impermanence.enable = true; sane.impermanence.enable = true;
@@ -13,11 +11,6 @@
boot.loader.efi.canTouchEfiVariables = false; boot.loader.efi.canTouchEfiVariables = false;
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ]; sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
sops.secrets.colin-passwd = {
sopsFile = ../../secrets/lappy.yaml;
neededForUsers = true;
};
# default config: https://man.archlinux.org/man/snapper-configs.5 # default config: https://man.archlinux.org/man/snapper-configs.5
# defaults to something like: # defaults to something like:
# - hourly snapshots # - hourly snapshots

View File

@@ -13,23 +13,17 @@
# TODO: we could *maybe* inject pkgs.buildPackages.xyz = cross.buildPackages.xyz? # TODO: we could *maybe* inject pkgs.buildPackages.xyz = cross.buildPackages.xyz?
documentation.nixos.enable = false; documentation.nixos.enable = false;
# XXX colin: phosh doesn't work well with passwordless login, # XXX colin: phosh doesn't work well with passwordless login
# so set this more reliable default password should anything go wrong
users.users.colin.initialPassword = "147147"; users.users.colin.initialPassword = "147147";
services.getty.autologinUser = "root"; # allows for emergency maintenance? services.getty.autologinUser = "root"; # allows for emergency maintenance?
sops.secrets.colin-passwd = {
sopsFile = ../../secrets/moby.yaml;
neededForUsers = true;
};
# usability compromises # usability compromises
sane.impermanence.home-dirs = [ sane.impermanence.home-dirs = [
config.sane.web-browser.dotDir ".librewolf"
]; ];
# sane.packages.enableGuiPkgs = false; # XXX faster builds/imaging for debugging # sane.home-packages.enableGuiPkgs = false; # XXX faster builds/imaging for debugging
sane.packages.extraUserPkgs = [ sane.home-manager.extraPackages = [
pkgs.plasma5Packages.konsole # terminal pkgs.plasma5Packages.konsole # terminal
]; ];
@@ -81,5 +75,7 @@
environment.variables.ALSA_CONFIG_UCM2 = "${./ucm2}"; environment.variables.ALSA_CONFIG_UCM2 = "${./ucm2}";
systemd.services.pulseaudio.environment.ALSA_CONFIG_UCM2 = "${./ucm2}"; systemd.services.pulseaudio.environment.ALSA_CONFIG_UCM2 = "${./ucm2}";
users.groups.feedbackd.gid = config.sane.allocations.feedbackd-gid;
hardware.opengl.driSupport = true; hardware.opengl.driSupport = true;
} }

View File

@@ -3,23 +3,26 @@
{ {
imports = [ imports = [
./fs.nix ./fs.nix
./hardware.nix
./net.nix ./net.nix
./users.nix ./users.nix
./services ./services
]; ];
sane.packages.extraUserPkgs = [ sane.home-manager.enable = true;
# for administering services sane.home-manager.extraPackages = [
# for administering matrix
pkgs.matrix-synapse pkgs.matrix-synapse
pkgs.freshrss
]; ];
sane.impermanence.enable = true; sane.impermanence.enable = true;
# sane.services.duplicity.enable = true; # TODO: re-enable after HW upgrade sane.services.duplicity.enable = true;
sane.services.nixserve.enable = true; sane.services.nixserve.enable = true;
sane.services.nixserve.sopsFile = ../../secrets/servo.yaml;
# TODO: look into the EFI stuff
boot.loader.grub.enable = false;
boot.loader.generic-extlinux-compatible.enable = true;
boot.loader.efi.canTouchEfiVariables = false; boot.loader.efi.canTouchEfiVariables = false;
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ]; sane.image.extraBootFiles = [ pkgs.bootpart-u-boot-rpi-aarch64 ];
sops.secrets.duplicity_passphrase = { sops.secrets.duplicity_passphrase = {
sopsFile = ../../secrets/servo.yaml; sopsFile = ../../secrets/servo.yaml;
@@ -28,7 +31,7 @@
# both transmission and ipfs try to set different net defaults. # both transmission and ipfs try to set different net defaults.
# we just use the most aggressive of the two here: # we just use the most aggressive of the two here:
boot.kernel.sysctl = { boot.kernel.sysctl = {
"net.core.rmem_max" = 4194304; # 4MB "net.core.rmem_max" = "4194304"; # 4MB
}; };
# This value determines the NixOS release from which the default # This value determines the NixOS release from which the default
@@ -37,6 +40,6 @@
# this value at the release version of the first install of this system. # this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option # Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "21.11"; system.stateVersion = "21.11"; # Did you read the comment?
} }

69
machines/servo/fs.nix Normal file
View File

@@ -0,0 +1,69 @@
{ ... }:
{
# root is a tmpfs so that we have an ephemeral system ("impermanence" handles the state)
fileSystems."/" = {
device = "none";
fsType = "tmpfs";
options = [
"mode=755"
"size=1G"
"defaults"
];
};
# we need a /tmp for building large nix things
fileSystems."/tmp" = {
device = "none";
fsType = "tmpfs";
options = [
"size=40G"
"mode=777"
"defaults"
];
};
fileSystems."/nix" = {
device = "/dev/disk/by-uuid/aa272cff-0fcc-498e-a4cb-0d95fb60631b";
fsType = "btrfs";
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/31D3-40CB";
fsType = "vfat";
};
# fileSystems."/var/lib/pleroma" = {
# device = "/opt/pleroma";
# options = [ "bind" ];
# };
# in-memory compressed RAM (seems to be dynamically sized)
zramSwap = {
enable = true;
};
# btrfs doesn't easily support swapfiles
# swapDevices = [
# { device = "/nix/persist/swapfile"; size = 4096; }
# ];
# this can be a partition. create with:
# fdisk <dev>
# n
# <default partno>
# <start>
# <end>
# t
# <partno>
# 19 # set part type to Linux swap
# w # write changes
# mkswap -L swap <part>
swapDevices = [
{
label = "swap";
# TODO: randomEncryption.enable = true;
}
];
}

View File

@@ -0,0 +1,75 @@
# this file originates from nixos-generate-config
# but has been heavily modified
{ pkgs, ... }:
{
# i changed this becuse linux 5.10 didn't have rpi-400 device tree blob.
# nixos-22.05 linux 5.15 DOES have these now.
# it should be possible to remove this if desired, but i'm not sure how the rpi-specific kernel differs.
# see: https://github.com/raspberrypi/linux
boot.kernelPackages = pkgs.linuxPackages_rpi4;
# raspberryPi boot loader creates extlinux.conf.
# otherwise, enable the generic-extlinux-compatible loader below.
# note: THESE ARE MUTUALLY EXCLUSIVE. generic-extlinux-compatible causes uboot to not be built
boot.initrd.availableKernelModules = [
"bcm2711_thermal"
"bcm_phy_lib"
"brcmfmac"
"brcmutil"
"broadcom"
"clk_raspberrypi"
"drm" # Direct Render Manager
"enclosure" # SCSI ?
"fuse"
"mdio_bcm_unimac"
"pcie_brcmstb"
"raspberrypi_cpufreq"
"raspberrypi_hwmon"
"ses" # SCSI Enclosure Services
"uas" # USB attached storage
"uio" # userspace IO
"uio_pdrv_genirq"
"xhci_pci"
"xhci_pci_renesas"
];
# boot.initrd.compressor = "gzip"; # defaults to zstd
# ondemand power scaling keeps the cpu at low frequency when idle, and sets to max frequency
# when load is detected. (v.s. the "performance" default, which always uses the max frequency)
powerManagement.cpuFreqGovernor = "ondemand";
# XXX colin: this allows one to `systemctl halt` and then not remove power until the HDD has spun down.
# however, it doesn't work with reboot because systemd will spin the drive up again to read its reboot bin.
# a better solution would be to put the drive behind a powered USB hub (or get a SSD).
# systemd.services.diskguard = {
# description = "Safely power off spinning media";
# before = [ "shutdown.target" ];
# wantedBy = [ "sysinit.target" ];
# # old (creates dep loop, but works)
# # before = [ "systemd-remount-fs.service" "shutdown.target" ];
# # wantedBy = [ "systemd-remount-fs.service" ];
# serviceConfig = {
# Type = "oneshot";
# RemainAfterExit = true;
# ExecStart = "${pkgs.coreutils}/bin/true";
# ExecStop = with pkgs; writeScript "diskguard" ''
# #!${bash}/bin/bash
# if ${procps}/bin/pgrep nixos-rebuild ;
# then
# exit 0 # don't halt drives unless we're actually shutting down. maybe better way to do this (check script args?)
# fi
# # ${coreutils}/bin/sync
# # ${util-linux}/bin/mount -o remount,ro /nix/store
# # ${util-linux}/bin/mount -o remount,ro /
# # -S 1 retracts the spindle after 5 seconds of idle
# # -B 1 spins down the drive after <vendor specific duration>
# ${hdparm}/sbin/hdparm -S 1 -B 1 /dev/sda
# # TODO: monitor smartmonctl until disk is idle? or try hdparm -Y
# # ${coreutils}/bin/sleep 20
# # exec ${util-linux}/bin/umount --all -t ext4,vfat,ext2
# '';
# };
# };
}

View File

@@ -13,7 +13,6 @@
# networking.firewall.enable = false; # networking.firewall.enable = false;
networking.firewall.enable = true; networking.firewall.enable = true;
# TODO: split these into the submodules
networking.firewall.allowedTCPPorts = [ networking.firewall.allowedTCPPorts = [
25 # SMTP 25 # SMTP
80 # HTTP 80 # HTTP

View File

@@ -2,10 +2,7 @@
{ {
imports = [ imports = [
./ddns-he.nix ./ddns-he.nix
./ejabberd.nix
./freshrss.nix
./gitea.nix ./gitea.nix
./goaccess.nix
./ipfs.nix ./ipfs.nix
./jackett.nix ./jackett.nix
./jellyfin.nix ./jellyfin.nix
@@ -15,7 +12,6 @@
./pleroma.nix ./pleroma.nix
./postfix.nix ./postfix.nix
./postgres.nix ./postgres.nix
./prosody.nix
./transmission.nix ./transmission.nix
]; ];
} }

View File

@@ -14,18 +14,18 @@
]; ];
# services.ipfs.enable = true; # services.ipfs.enable = true;
services.kubo.localDiscovery = true; services.kubo.localDiscovery = true;
services.kubo.settings = { services.kubo.swarmAddress = [
Addresses = {
Announce = [
# "/dns4/ipfs.uninsane.org/tcp/4001"
"/dns4/ipfs.uninsane.org/udp/4001/quic"
];
Swarm = [
# "/dns4/ipfs.uninsane.org/tcp/4001" # "/dns4/ipfs.uninsane.org/tcp/4001"
# "/ip4/0.0.0.0/tcp/4001" # "/ip4/0.0.0.0/tcp/4001"
"/dns4/ipfs.uninsane.org/udp/4001/quic" "/dns4/ipfs.uninsane.org/udp/4001/quic"
"/ip4/0.0.0.0/udp/4001/quic" "/ip4/0.0.0.0/udp/4001/quic"
]; ];
services.kubo.extraConfig = {
Addresses = {
Announce = [
# "/dns4/ipfs.uninsane.org/tcp/4001"
"/dns4/ipfs.uninsane.org/udp/4001/quic"
];
}; };
Gateway = { Gateway = {
# the gateway can only be used to serve content already replicated on this host # the gateway can only be used to serve content already replicated on this host

View File

@@ -4,6 +4,7 @@
{ {
imports = [ imports = [
# ./discord-appservice.nix
./discord-puppet.nix ./discord-puppet.nix
# ./irc.nix # ./irc.nix
]; ];

View File

@@ -0,0 +1,69 @@
{ config, lib, ... }:
{
sane.impermanence.service-dirs = [
{ user = "matrix-appservice-discord"; group = "matrix-appservice-discord"; directory = "/var/lib/matrix-appservice-discord"; }
];
sops.secrets.matrix_appservice_discord_env = {
sopsFile = ../../../../secrets/servo/matrix_appservice_discord_env.bin;
owner = config.users.users.matrix-appservice-discord.name;
format = "binary";
};
services.matrix-synapse.settings.app_service_config_files = [
# auto-created by discord appservice
"/var/lib/matrix-appservice-discord/discord-registration.yaml"
];
# Discord bridging
# docs: https://github.com/matrix-org/matrix-appservice-discord
services.matrix-appservice-discord.enable = true;
services.matrix-appservice-discord.settings = {
bridge = {
homeserverUrl = "http://127.0.0.1:8008";
domain = "uninsane.org";
adminMxid = "admin.matrix@uninsane.org";
# self-service bridging is when a Matrix user bridges by DMing @_discord_bot:<HS>
# i don't know what the alternative is :?
enableSelfServiceBridging = true;
presenceInterval = 30000; # milliseconds
# allows matrix users to search for Discord channels (somehow?)
disablePortalBridging = false;
# disableReadReceipts = true;
# these are Matrix -> Discord
disableJoinLeaveNotifications = true;
disableInviteNotifications = true;
disableRoomTopicNotifications = true;
};
# these are marked as required in the yaml schema
auth = {
# apparently not needed if you provide them as env vars (below).
# clientId = "FILLME";
# botToken = "FILLME";
usePrivilegedIntents = false;
};
logging = {
# silly, verbose, info, http, warn, error, silent
console = "verbose";
};
};
# contains what's ordinarily put into auth.clientId, auth.botToken
# i.e. `APPSERVICE_DISCORD_AUTH_CLIENT_I_D=...` and `APPSERVICE_DISCORD_AUTH_BOT_TOKEN=...`
services.matrix-appservice-discord.environmentFile = config.sops.secrets.matrix_appservice_discord_env.path;
systemd.services.matrix-appservice-discord.serviceConfig = {
# fix up to not use /var/lib/private, but just /var/lib
DynamicUser = lib.mkForce false;
User = "matrix-appservice-discord";
Group = "matrix-appservice-discord";
};
users.groups.matrix-appservice-discord = {};
users.users.matrix-appservice-discord = {
description = "User for the Matrix-Discord bridge";
group = "matrix-appservice-discord";
isSystemUser = true;
};
users.users.matrix-appservice-discord.uid = 2134; # TODO: move to allocations
users.groups.matrix-appservice-discord.gid = 2134; # TODO
}

View File

@@ -1,54 +1,17 @@
# docs: https://nixos.wiki/wiki/Nginx # docs: https://nixos.wiki/wiki/Nginx
{ config, pkgs, ... }: { config, pkgs, ... }:
let
# make the logs for this host "public" so that they show up in e.g. metrics
publog = vhost: vhost // {
extraConfig = (vhost.extraConfig or "") + ''
access_log /var/log/nginx/public.log vcombined;
'';
};
kTLS = true; # in-kernel TLS for better perf
in
{ {
services.nginx.enable = true; services.nginx.enable = true;
services.nginx.appendConfig = ''
# use 1 process per core.
# may want to increase worker_connections too, but `ulimit -n` must be increased first.
worker_processes auto;
'';
# this is the standard `combined` log format, with the addition of $host
# so that we have the virtualHost in the log.
# KEEP IN SYNC WITH GOACCESS
# goaccess calls this VCOMBINED:
# - <https://gist.github.com/jyap808/10570005>
services.nginx.commonHttpConfig = ''
log_format vcombined '$host:$server_port $remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referrer" "$http_user_agent"';
access_log /var/log/nginx/private.log vcombined;
'';
# sets gzip_comp_level = 5
services.nginx.recommendedGzipSettings = true;
# enables OCSP stapling (so clients don't need contact the OCSP server -- i do instead)
# caches TLS sessions for 10m
services.nginx.recommendedTlsSettings = true;
# enables sendfile, tcp_nopush, tcp_nodelay, keepalive_timeout 65
services.nginx.recommendedOptimisation = true;
# web blog/personal site # web blog/personal site
services.nginx.virtualHosts."uninsane.org" = publog { services.nginx.virtualHosts."uninsane.org" = {
root = "${pkgs.uninsane-dot-org}/share/uninsane-dot-org"; root = "/var/lib/uninsane/root";
# a lot of places hardcode https://uninsane.org, # a lot of places hardcode https://uninsane.org,
# and then when we mix http + non-https, we get CORS violations # and then when we mix http + non-https, we get CORS violations
# and things don't look right. so force SSL. # and things don't look right. so force SSL.
forceSSL = true; forceSSL = true;
enableACME = true; enableACME = true;
inherit kTLS;
# uninsane.org/share/foo => /var/lib/uninsane/root/share/foo.
# yes, nginx does not strip the prefix when evaluating against the root.
locations."/share".root = "/var/lib/uninsane/root";
# allow matrix users to discover that @user:uninsane.org is reachable via matrix.uninsane.org # allow matrix users to discover that @user:uninsane.org is reachable via matrix.uninsane.org
locations."= /.well-known/matrix/server".extraConfig = locations."= /.well-known/matrix/server".extraConfig =
@@ -90,32 +53,10 @@ in
# }; # };
}; };
# server statistics # Pleroma server and web interface
services.nginx.virtualHosts."sink.uninsane.org" = { services.nginx.virtualHosts."fed.uninsane.org" = {
addSSL = true; addSSL = true;
enableACME = true; enableACME = true;
inherit kTLS;
root = "/var/lib/uninsane/sink";
locations."/ws" = {
proxyPass = "http://127.0.0.1:7890";
# XXX not sure how much of this is necessary
extraConfig = ''
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_buffering off;
proxy_read_timeout 7d;
'';
};
};
# Pleroma server and web interface
services.nginx.virtualHosts."fed.uninsane.org" = publog {
forceSSL = true; # pleroma redirects to https anyway
enableACME = true;
inherit kTLS;
locations."/" = { locations."/" = {
proxyPass = "http://127.0.0.1:4000"; proxyPass = "http://127.0.0.1:4000";
# documented: https://git.pleroma.social/pleroma/pleroma/-/blob/develop/installation/pleroma.nginx # documented: https://git.pleroma.social/pleroma/pleroma/-/blob/develop/installation/pleroma.nginx
@@ -157,7 +98,6 @@ in
# basicAuth is literally cleartext user/pw, so FORCE this to happen over SSL # basicAuth is literally cleartext user/pw, so FORCE this to happen over SSL
forceSSL = true; forceSSL = true;
enableACME = true; enableACME = true;
inherit kTLS;
locations."/" = { locations."/" = {
# proxyPass = "http://ovpns.uninsane.org:9091"; # proxyPass = "http://ovpns.uninsane.org:9091";
proxyPass = "http://10.0.1.6:9091"; proxyPass = "http://10.0.1.6:9091";
@@ -168,7 +108,6 @@ in
services.nginx.virtualHosts."jackett.uninsane.org" = { services.nginx.virtualHosts."jackett.uninsane.org" = {
forceSSL = true; forceSSL = true;
enableACME = true; enableACME = true;
inherit kTLS;
locations."/" = { locations."/" = {
# proxyPass = "http://ovpns.uninsane.org:9117"; # proxyPass = "http://ovpns.uninsane.org:9117";
proxyPass = "http://10.0.1.6:9117"; proxyPass = "http://10.0.1.6:9117";
@@ -176,10 +115,9 @@ in
}; };
# matrix chat server # matrix chat server
services.nginx.virtualHosts."matrix.uninsane.org" = publog { services.nginx.virtualHosts."matrix.uninsane.org" = {
addSSL = true; addSSL = true;
enableACME = true; enableACME = true;
inherit kTLS;
# TODO colin: replace this with something helpful to the viewer # TODO colin: replace this with something helpful to the viewer
# locations."/".extraConfig = '' # locations."/".extraConfig = ''
@@ -206,7 +144,6 @@ in
services.nginx.virtualHosts."web.matrix.uninsane.org" = { services.nginx.virtualHosts."web.matrix.uninsane.org" = {
forceSSL = true; forceSSL = true;
enableACME = true; enableACME = true;
inherit kTLS;
root = pkgs.element-web.override { root = pkgs.element-web.override {
conf = { conf = {
@@ -219,10 +156,9 @@ in
}; };
# hosted git (web view and for `git <cmd>` use # hosted git (web view and for `git <cmd>` use
services.nginx.virtualHosts."git.uninsane.org" = publog { services.nginx.virtualHosts."git.uninsane.org" = {
forceSSL = true; # gitea complains if served over a different protocol than its config file says addSSL = true;
enableACME = true; enableACME = true;
inherit kTLS;
locations."/" = { locations."/" = {
proxyPass = "http://127.0.0.1:3000"; proxyPass = "http://127.0.0.1:3000";
@@ -234,7 +170,6 @@ in
services.nginx.virtualHosts."jelly.uninsane.org" = { services.nginx.virtualHosts."jelly.uninsane.org" = {
addSSL = true; addSSL = true;
enableACME = true; enableACME = true;
inherit kTLS;
locations."/" = { locations."/" = {
proxyPass = "http://127.0.0.1:8096"; proxyPass = "http://127.0.0.1:8096";
@@ -281,23 +216,14 @@ in
services.nginx.virtualHosts."music.uninsane.org" = { services.nginx.virtualHosts."music.uninsane.org" = {
forceSSL = true; forceSSL = true;
enableACME = true; enableACME = true;
inherit kTLS;
locations."/".proxyPass = "http://127.0.0.1:4533"; locations."/".proxyPass = "http://127.0.0.1:4533";
}; };
services.nginx.virtualHosts."rss.uninsane.org" = {
addSSL = true;
enableACME = true;
inherit kTLS;
# the routing is handled by freshrss.nix
};
services.nginx.virtualHosts."ipfs.uninsane.org" = { services.nginx.virtualHosts."ipfs.uninsane.org" = {
# don't default to ssl upgrades, since this may be dnslink'd from a different domain. # don't default to ssl upgrades, since this may be dnslink'd from a different domain.
# ideally we'd disable ssl entirely, but some places assume it? # ideally we'd disable ssl entirely, but some places assume it?
addSSL = true; addSSL = true;
enableACME = true; enableACME = true;
inherit kTLS;
default = true; default = true;
@@ -323,7 +249,6 @@ in
services.nginx.virtualHosts."nixcache.uninsane.org" = { services.nginx.virtualHosts."nixcache.uninsane.org" = {
addSSL = true; addSSL = true;
enableACME = true; enableACME = true;
inherit kTLS;
# serverAliases = [ "nixcache" ]; # serverAliases = [ "nixcache" ];
locations."/".extraConfig = '' locations."/".extraConfig = ''
proxy_pass http://localhost:${toString config.services.nix-serve.port}; proxy_pass http://localhost:${toString config.services.nix-serve.port};
@@ -341,5 +266,6 @@ in
sane.impermanence.service-dirs = [ sane.impermanence.service-dirs = [
# TODO: mode? # TODO: mode?
{ user = "acme"; group = "acme"; directory = "/var/lib/acme"; } { user = "acme"; group = "acme"; directory = "/var/lib/acme"; }
{ user = "colin"; group = "users"; directory = "/var/lib/uninsane"; }
]; ];
} }

View File

@@ -1,6 +1,4 @@
# docs: # docs: https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/networking/pleroma.nix
# - https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/networking/pleroma.nix
# - https://docs.pleroma.social/backend/configuration/cheatsheet/
# #
# to run it in a oci-container: https://github.com/barrucadu/nixfiles/blob/master/services/pleroma.nix # to run it in a oci-container: https://github.com/barrucadu/nixfiles/blob/master/services/pleroma.nix
{ config, pkgs, ... }: { config, pkgs, ... }:
@@ -50,19 +48,16 @@
redirect_on_failure: true redirect_on_failure: true
#base_url: "https://cache.pleroma.social" #base_url: "https://cache.pleroma.social"
# see for reference:
# - `force_custom_plan`: <https://docs.pleroma.social/backend/configuration/postgresql/#disable-generic-query-plans>
config :pleroma, Pleroma.Repo, config :pleroma, Pleroma.Repo,
adapter: Ecto.Adapters.Postgres, adapter: Ecto.Adapters.Postgres,
username: "pleroma", username: "pleroma",
database: "pleroma", database: "pleroma",
hostname: "localhost", hostname: "localhost",
pool_size: 10, pool_size: 10,
prepare: :named,
parameters: [ parameters: [
plan_cache_mode: "force_custom_plan" plan_cache_mode: "force_custom_plan"
] ]
# XXX: prepare: :named is needed only for PG <= 12
# prepare: :named,
# password: "{secrets.pleroma.db_password}", # password: "{secrets.pleroma.db_password}",
# Configure web push notifications # Configure web push notifications
@@ -79,10 +74,9 @@
config :pleroma, configurable_from_database: false config :pleroma, configurable_from_database: false
# strip metadata from uploaded images # strip metadata from uploaded images
config :pleroma, Pleroma.Upload, filters: [Pleroma.Upload.Filter.Exiftool.StripLocation] config :pleroma, Pleroma.Upload, filters: [Pleroma.Upload.Filter.Exiftool]
# TODO: GET /api/pleroma/captcha is broken # TODO: GET /api/pleroma/captcha is broken
# there was a nixpkgs PR to fix this around 2022/10 though.
config :pleroma, Pleroma.Captcha, config :pleroma, Pleroma.Captcha,
enabled: false, enabled: false,
method: Pleroma.Captcha.Native method: Pleroma.Captcha.Native
@@ -98,8 +92,8 @@
backends: [{ExSyslogger, :ex_syslogger}] backends: [{ExSyslogger, :ex_syslogger}]
config :logger, :ex_syslogger, config :logger, :ex_syslogger,
level: :warn level: :debug
# level: :debug # level: :warn
# XXX colin: not sure if this actually _does_ anything # XXX colin: not sure if this actually _does_ anything
config :pleroma, :emoji, config :pleroma, :emoji,

View File

@@ -18,12 +18,8 @@ in
{ {
sane.impermanence.service-dirs = [ sane.impermanence.service-dirs = [
# TODO: mode? could be more granular # TODO: mode? could be more granular
{ user = "opendkim"; group = "opendkim"; directory = "/var/lib/opendkim"; } { user = "221"; group = "221"; directory = "/var/lib/opendkim"; }
{ user = "root"; group = "root"; directory = "/var/lib/postfix"; } { user = "root"; group = "root"; directory = "/var/lib/postfix"; }
{ user = "root"; group = "root"; directory = "/var/spool/mail"; }
# *probably* don't need these dirs:
# "/var/lib/dhparams" # https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/security/dhparams.nix
# "/var/lib/dovecot"
]; ];
services.postfix.enable = true; services.postfix.enable = true;
services.postfix.hostname = "mx.uninsane.org"; services.postfix.hostname = "mx.uninsane.org";

View File

@@ -3,7 +3,7 @@
{ {
sane.impermanence.service-dirs = [ sane.impermanence.service-dirs = [
# TODO: mode? # TODO: mode?
{ user = "postgres"; group = "postgres"; directory = "/var/lib/postgresql"; } { user = "71"; group = "71"; directory = "/var/lib/postgresql"; }
]; ];
services.postgresql.enable = true; services.postgresql.enable = true;
# services.postgresql.dataDir = "/opt/postgresql/13"; # services.postgresql.dataDir = "/opt/postgresql/13";
@@ -17,11 +17,6 @@
# LC_CTYPE = "C"; # LC_CTYPE = "C";
# ''; # '';
# TODO: perf tuning
# - for recommended values see: <https://pgtune.leopard.in.ua/>
# - for official docs (sparse), see: <https://www.postgresql.org/docs/11/config-setting.html#CONFIG-SETTING-CONFIGURATION-FILE>
# services.postgresql.settings = { ... }
# daily backups to /var/backup # daily backups to /var/backup
services.postgresqlBackup.enable = true; services.postgresqlBackup.enable = true;

View File

@@ -3,7 +3,7 @@
{ {
sane.impermanence.service-dirs = [ sane.impermanence.service-dirs = [
# TODO: mode? we need this specifically for the stats tracking in .config/ # TODO: mode? we need this specifically for the stats tracking in .config/
{ user = "transmission"; group = "transmission"; directory = "/var/lib/transmission"; } { user = "70"; group = "70"; directory = "/var/lib/transmission"; }
]; ];
services.transmission.enable = true; services.transmission.enable = true;
services.transmission.settings = { services.transmission.settings = {

View File

@@ -2,13 +2,13 @@
{ {
imports = [ imports = [
./allocations.nix
./gui ./gui
./home-manager ./hardware
./packages.nix
./image.nix ./image.nix
./impermanence.nix ./impermanence.nix
./nixcache.nix ./nixcache.nix
./services ./services/duplicity.nix
./services/nixserve.nix
./universal
]; ];
} }

View File

@@ -8,7 +8,6 @@ in
imports = [ imports = [
./gnome.nix ./gnome.nix
./phosh.nix ./phosh.nix
./plasma.nix
./plasma-mobile.nix ./plasma-mobile.nix
./sway.nix ./sway.nix
]; ];
@@ -22,7 +21,8 @@ in
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
sane.packages.enableGuiPkgs = lib.mkDefault true; sane.home-packages.enableGuiPkgs = lib.mkDefault true;
sane.home-manager.enable = lib.mkDefault true;
# all GUIs use network manager? # all GUIs use network manager?
users.users.nm-iodine.uid = config.sane.allocations.nm-iodine-uid; users.users.nm-iodine.uid = config.sane.allocations.nm-iodine-uid;
}; };

View File

@@ -14,16 +14,6 @@ in
config = mkIf cfg.enable { config = mkIf cfg.enable {
sane.gui.enable = true; sane.gui.enable = true;
users.users.avahi.uid = config.sane.allocations.avahi-uid;
users.groups.avahi.gid = config.sane.allocations.avahi-gid;
users.users.colord.uid = config.sane.allocations.colord-uid;
users.groups.colord.gid = config.sane.allocations.colord-gid;
users.users.geoclue.uid = config.sane.allocations.geoclue-uid;
users.groups.geoclue.gid = config.sane.allocations.geoclue-gid;
users.users.rtkit.uid = config.sane.allocations.rtkit-uid;
users.groups.rtkit.gid = config.sane.allocations.rtkit-gid;
# start gnome/gdm on boot # start gnome/gdm on boot
services.xserver.enable = true; services.xserver.enable = true;
services.xserver.desktopManager.gnome.enable = true; services.xserver.desktopManager.gnome.enable = true;

View File

@@ -10,18 +10,9 @@ in
default = false; default = false;
type = types.bool; type = types.bool;
}; };
sane.gui.phosh.useGreeter = mkOption {
description = ''
launch phosh via a greeter (like lightdm-mobile-greeter).
phosh is usable without a greeter, but skipping the greeter means no PAM session.
'';
default = true;
type = types.bool;
};
}; };
config = mkIf cfg.enable (mkMerge [ config = mkIf cfg.enable {
{
sane.gui.enable = true; sane.gui.enable = true;
users.users.avahi.uid = config.sane.allocations.avahi-uid; users.users.avahi.uid = config.sane.allocations.avahi-uid;
@@ -30,7 +21,6 @@ in
users.users.rtkit.uid = config.sane.allocations.rtkit-uid; users.users.rtkit.uid = config.sane.allocations.rtkit-uid;
users.groups.avahi.gid = config.sane.allocations.avahi-gid; users.groups.avahi.gid = config.sane.allocations.avahi-gid;
users.groups.colord.gid = config.sane.allocations.colord-gid; users.groups.colord.gid = config.sane.allocations.colord-gid;
users.groups.feedbackd.gid = config.sane.allocations.feedbackd-gid;
users.groups.geoclue.gid = config.sane.allocations.geoclue-gid; users.groups.geoclue.gid = config.sane.allocations.geoclue-gid;
users.groups.rtkit.gid = config.sane.allocations.rtkit-gid; users.groups.rtkit.gid = config.sane.allocations.rtkit-gid;
@@ -69,38 +59,11 @@ in
NIXOS_OZONE_WL = "1"; NIXOS_OZONE_WL = "1";
}; };
sane.packages.extraUserPkgs = with pkgs; [ sane.home-manager.extraPackages = with pkgs; [
phosh-mobile-settings phosh-mobile-settings
# TODO: see about removing this if the in-built gnome-settings bluetooth manager can work # TODO: see about removing this if the in-built gnome-settings bluetooth manager can work
gnome.gnome-bluetooth gnome.gnome-bluetooth
]; ];
} };
(mkIf cfg.useGreeter {
services.xserver.enable = true;
# NB: setting defaultSession has the critical side-effect that it lets org.freedesktop.AccountsService
# know that our user exists. this ensures lightdm succeeds when calling /org/freedesktop/AccountsServices ListCachedUsers
# lightdm greeters get the login users from lightdm which gets it from org.freedesktop.Accounts.ListCachedUsers.
# this requires the user we want to login as to be cached.
services.xserver.displayManager.job.preStart = ''
${pkgs.systemd}/bin/busctl call org.freedesktop.Accounts /org/freedesktop/Accounts org.freedesktop.Accounts CacheUser s colin
'';
# services.xserver.displayManager.defaultSession = "sm.puri.Phosh"; # XXX: not sure why this doesn't propagate correctly.
services.xserver.displayManager.lightdm.extraSeatDefaults = ''
user-session = phosh
'';
# services.xserver.displayManager.lightdm.greeters.gtk.enable = false; # gtk greeter overrides our own?
# services.xserver.displayManager.lightdm.greeter = {
# enable = true;
# package = pkgs.lightdm-mobile-greeter.xgreeters;
# name = "lightdm-mobile-greeter";
# };
# # services.xserver.displayManager.lightdm.enable = true;
services.xserver.displayManager.lightdm.enable = true;
services.xserver.displayManager.lightdm.greeters.mobile.enable = true;
systemd.services.phosh.wantedBy = lib.mkForce []; # disable auto-start
})
]);
} }

View File

@@ -1,28 +0,0 @@
{ lib, config, ... }:
with lib;
let
cfg = config.sane.gui.plasma;
in
{
options = {
sane.gui.plasma.enable = mkOption {
default = false;
type = types.bool;
};
};
config = mkIf cfg.enable {
sane.gui.enable = true;
# start plasma on boot
services.xserver.enable = true;
services.xserver.desktopManager.plasma5.enable = true;
services.xserver.displayManager.sddm.enable = true;
# gnome does networking stuff with networkmanager
networking.useDHCP = false;
networking.networkmanager.enable = true;
networking.wireless.enable = lib.mkForce false;
};
}

View File

@@ -11,14 +11,6 @@ in
default = false; default = false;
type = types.bool; type = types.bool;
}; };
sane.gui.sway.useGreeter = mkOption {
description = ''
launch sway via a greeter (like greetd's gtkgreet).
sway is usable without a greeter, but skipping the greeter means no PAM session.
'';
default = true;
type = types.bool;
};
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
sane.gui.enable = true; sane.gui.enable = true;
@@ -29,33 +21,15 @@ in
enable = true; enable = true;
}; };
# alternatively, could use SDDM # TODO: should be able to use SDDM to get interactive login
services.greetd = let services.greetd = {
swayConfig-greeter = pkgs.writeText "greetd-sway-config" '' enable = true;
# `-l` activates layer-shell mode. settings = rec {
exec "${pkgs.greetd.gtkgreet}/bin/gtkgreet -l -c sway" initial_session = {
'';
default_session = {
"01" = {
# greeter session config
command = "${pkgs.sway}/bin/sway --config ${swayConfig-greeter}";
# alternatives:
# - TTY: `command = "${pkgs.greetd.greetd}/bin/agreety --cmd ${pkgs.sway}/bin/sway";`
# - autologin: `command = "${pkgs.sway}/bin/sway"; user = "colin";`
# - Dumb Login (doesn't work)": `command = "${pkgs.greetd.dlm}/bin/dlm";`
};
"0" = {
# no greeter
command = "${pkgs.sway}/bin/sway"; command = "${pkgs.sway}/bin/sway";
user = "colin"; user = "colin";
}; };
}; default_session = initial_session;
in {
# greetd source/docs:
# - <https://git.sr.ht/~kennylevinsen/greetd>
enable = true;
settings = {
default_session = default_session."0${builtins.toString cfg.useGreeter}";
}; };
}; };
@@ -114,22 +88,21 @@ in
"${modifier}+Return" = "exec ${terminal}"; "${modifier}+Return" = "exec ${terminal}";
"${modifier}+Shift+q" = "kill"; "${modifier}+Shift+q" = "kill";
"${modifier}+d" = "exec ${menu}"; "${modifier}+d" = "exec ${menu}";
"${modifier}+l" = "exec ${pkgs.swaylock}/bin/swaylock --indicator-idle-visible --indicator-radius 100 --indicator-thickness 30";
# "${modifier}+${left}" = "focus left"; "${modifier}+${left}" = "focus left";
# "${modifier}+${down}" = "focus down"; "${modifier}+${down}" = "focus down";
# "${modifier}+${up}" = "focus up"; "${modifier}+${up}" = "focus up";
# "${modifier}+${right}" = "focus right"; "${modifier}+${right}" = "focus right";
"${modifier}+Left" = "focus left"; "${modifier}+Left" = "focus left";
"${modifier}+Down" = "focus down"; "${modifier}+Down" = "focus down";
"${modifier}+Up" = "focus up"; "${modifier}+Up" = "focus up";
"${modifier}+Right" = "focus right"; "${modifier}+Right" = "focus right";
# "${modifier}+Shift+${left}" = "move left"; "${modifier}+Shift+${left}" = "move left";
# "${modifier}+Shift+${down}" = "move down"; "${modifier}+Shift+${down}" = "move down";
# "${modifier}+Shift+${up}" = "move up"; "${modifier}+Shift+${up}" = "move up";
# "${modifier}+Shift+${right}" = "move right"; "${modifier}+Shift+${right}" = "move right";
"${modifier}+Shift+Left" = "move left"; "${modifier}+Shift+Left" = "move left";
"${modifier}+Shift+Down" = "move down"; "${modifier}+Shift+Down" = "move down";
@@ -597,9 +570,9 @@ in
# } # }
# ''; # '';
}; };
sane.packages.extraUserPkgs = with pkgs; [ sane.home-manager.extraPackages = with pkgs; [
swaylock swaylock
swayidle # (unused) swayidle
wl-clipboard wl-clipboard
mako # notification daemon mako # notification daemon
xdg-utils # for xdg-open xdg-utils # for xdg-open

View File

@@ -1,16 +0,0 @@
# Terminal UI mail client
{ config, lib, ... }:
lib.mkIf config.sane.home-manager.enable
{
sops.secrets."aerc_accounts" = {
owner = config.users.users.colin.name;
sopsFile = ../../secrets/universal/aerc_accounts.conf;
format = "binary";
};
home-manager.users.colin = let sysconfig = config; in { config, ... }: {
# aerc TUI mail client
xdg.configFile."aerc/accounts.conf".source =
config.lib.file.mkOutOfStoreSymlink sysconfig.sops.secrets.aerc_accounts.path;
};
}

View File

@@ -1,226 +0,0 @@
# docs:
# https://rycee.gitlab.io/home-manager/
# https://rycee.gitlab.io/home-manager/options.html
# man home-configuration.nix
#
{ lib, config, pkgs, ... }:
with lib;
let
cfg = config.sane.home-manager;
# extract package from `sane.packages.enabledUserPkgs`
pkg-list = pkgspec: builtins.map (e: e.pkg or e) pkgspec;
# extract `dir` from `sane.packages.enabledUserPkgs`
dir-list = pkgspec: builtins.concatLists (builtins.map (e: if e ? "dir" then [ e.dir ] else []) pkgspec);
private-list = pkgspec: builtins.concatLists (builtins.map (e: if e ? "private" then [ e.private ] else []) pkgspec);
feeds = import ./feeds.nix { inherit lib; };
in
{
imports = [
./aerc.nix
./discord.nix
./firefox.nix
./git.nix
./kitty.nix
./mpv.nix
./nb.nix
./neovim.nix
./ssh.nix
./sublime-music.nix
./vlc.nix
./zsh.nix
];
options = {
sane.home-manager.enable = mkOption {
default = false;
type = types.bool;
};
# attributes to copy directly to home-manager's `wayland.windowManager` option
sane.home-manager.windowManager = mkOption {
default = {};
type = types.attrs;
};
# extra attributes to include in home-manager's `programs` option
sane.home-manager.programs = mkOption {
default = {};
type = types.attrs;
};
};
config = lib.mkIf cfg.enable {
sane.impermanence.home-dirs = [
"archive"
"dev"
"records"
"ref"
"tmp"
"use"
"Music"
"Pictures"
"Videos"
] ++ (dir-list config.sane.packages.enabledUserPkgs);
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
# XXX this weird rename + closure is to get home-manager's `config.lib.file` to exist.
# see: https://github.com/nix-community/home-manager/issues/589#issuecomment-950474105
home-manager.users.colin = let sysconfig = config; in { config, ... }: {
# run `home-manager-help` to access manpages
# or `man home-configuration.nix`
manual.html.enable = false; # TODO: set to true later (build failure)
manual.manpages.enable = false; # TODO: enable after https://github.com/nix-community/home-manager/issues/3344
home.packages = pkg-list sysconfig.sane.packages.enabledUserPkgs;
wayland.windowManager = cfg.windowManager;
home.stateVersion = "21.11";
home.username = "colin";
home.homeDirectory = "/home/colin";
home.activation = {
initKeyring = {
after = ["writeBoundary"];
before = [];
data = "${../../scripts/init-keyring}";
};
};
home.file = let
privates = builtins.listToAttrs (
builtins.map (path: {
name = path;
value = { source = config.lib.file.mkOutOfStoreSymlink "/home/colin/private/${path}"; };
})
(private-list sysconfig.sane.packages.enabledUserPkgs)
);
in {
# convenience
"knowledge".source = config.lib.file.mkOutOfStoreSymlink "/home/colin/dev/knowledge";
"nixos".source = config.lib.file.mkOutOfStoreSymlink "/home/colin/dev/nixos";
"Videos/servo".source = config.lib.file.mkOutOfStoreSymlink "/mnt/servo-media/Videos";
"Videos/servo-incomplete".source = config.lib.file.mkOutOfStoreSymlink "/mnt/servo-media/incomplete";
"Music/servo".source = config.lib.file.mkOutOfStoreSymlink "/mnt/servo-media/Music";
# used by password managers, e.g. unix `pass`
".password-store".source = config.lib.file.mkOutOfStoreSymlink "/home/colin/dev/knowledge/secrets/accounts";
} // privates;
# XDG defines things like ~/Desktop, ~/Downloads, etc.
# these clutter the home, so i mostly don't use them.
xdg.userDirs = {
enable = true;
createDirectories = false; # on headless systems, most xdg dirs are noise
desktop = "$HOME/.xdg/Desktop";
documents = "$HOME/dev";
download = "$HOME/tmp";
music = "$HOME/Music";
pictures = "$HOME/Pictures";
publicShare = "$HOME/.xdg/Public";
templates = "$HOME/.xdg/Templates";
videos = "$HOME/Videos";
};
# the xdg mime type for a file can be found with:
# - `xdg-mime query filetype path/to/thing.ext`
xdg.mimeApps.enable = true;
xdg.mimeApps.defaultApplications = let
www = sysconfig.sane.web-browser.desktop;
pdf = "org.gnome.Evince.desktop";
md = "obsidian.desktop";
thumb = "org.gnome.gThumb.desktop";
video = "vlc.desktop";
# audio = "mpv.desktop";
audio = "vlc.desktop";
in {
# HTML
"text/html" = [ www ];
"x-scheme-handler/http" = [ www ];
"x-scheme-handler/https" = [ www ];
"x-scheme-handler/about" = [ www ];
"x-scheme-handler/unknown" = [ www ];
# RICH-TEXT DOCUMENTS
"application/pdf" = [ pdf ];
"text/markdown" = [ md ];
# IMAGES
"image/heif" = [ thumb ]; # apple codec
"image/png" = [ thumb ];
"image/jpeg" = [ thumb ];
# VIDEO
"video/mp4" = [ video ];
"video/quicktime" = [ video ];
"video/x-matroska" = [ video ];
# AUDIO
"audio/flac" = [ audio ];
"audio/mpeg" = [ audio ];
"audio/x-vorbis+ogg" = [ audio ];
};
# libreoffice: disable first-run stuff
xdg.configFile."libreoffice/4/user/registrymodifications.xcu".text = ''
<?xml version="1.0" encoding="UTF-8"?>
<oor:items xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<item oor:path="/org.openoffice.Office.Common/Misc"><prop oor:name="FirstRun" oor:op="fuse"><value>false</value></prop></item>
<item oor:path="/org.openoffice.Office.Common/Misc"><prop oor:name="ShowTipOfTheDay" oor:op="fuse"><value>false</value></prop></item>
</oor:items>
'';
# <item oor:path="/org.openoffice.Setup/Product"><prop oor:name="LastTimeDonateShown" oor:op="fuse"><value>1667693880</value></prop></item>
# <item oor:path="/org.openoffice.Setup/Product"><prop oor:name="LastTimeGetInvolvedShown" oor:op="fuse"><value>1667693880</value></prop></item>
xdg.configFile."gpodderFeeds.opml".text = with feeds;
feedsToOpml feeds.podcasts;
# news-flash RSS viewer
xdg.configFile."newsflashFeeds.opml".text = with feeds;
feedsToOpml (feeds.texts ++ feeds.images);
# gnome feeds RSS viewer
xdg.configFile."org.gabmus.gfeeds.json".text =
let
myFeeds = feeds.texts ++ feeds.images;
in builtins.toJSON {
# feed format is a map from URL to a dict,
# with dict["tags"] a list of string tags.
feeds = builtins.foldl' (acc: feed: acc // {
"${feed.url}".tags = [ feed.cat feed.freq ];
}) {} myFeeds;
dark_reader = false;
new_first = true;
# windowsize = {
# width = 350;
# height = 650;
# };
max_article_age_days = 90;
enable_js = false;
max_refresh_threads = 3;
# saved_items = {};
# read_items = [];
show_read_items = true;
full_article_title = true;
# views: "webview", "reader", "rsscont"
default_view = "rsscont";
open_links_externally = true;
full_feed_name = false;
refresh_on_startup = true;
tags = lib.lists.unique (
(builtins.catAttrs "cat" myFeeds) ++ (builtins.catAttrs "freq" myFeeds)
);
open_youtube_externally = false;
media_player = "vlc"; # default: mpv
};
programs = {
home-manager.enable = true; # this lets home-manager manage dot-files in user dirs, i think
# "command not found" will cause the command to be searched in nixpkgs
nix-index.enable = true;
} // cfg.programs;
};
};
}

View File

@@ -1,12 +0,0 @@
{ config, lib, ... }:
lib.mkIf config.sane.home-manager.enable
{
# TODO: this should only be enabled on gui devices
# make Discord usable even when client is "outdated"
home-manager.users.colin.xdg.configFile."discord/settings.json".text = ''
{
"SKIP_HOST_UPDATE": true
}
'';
}

View File

@@ -1,185 +0,0 @@
{ lib }:
let
hourly = { freq = "hourly"; };
daily = { freq = "daily"; };
weekly = { freq = "weekly"; };
infrequent = { freq = "infrequent"; };
art = { cat = "art"; };
humor = { cat = "humor"; };
pol = { cat = "pol"; }; # or maybe just "social"
rat = { cat = "rat"; };
tech = { cat = "tech"; };
uncat = { cat = "uncat"; };
text = { format = "text"; };
image = { format = "image"; };
podcast = { format = "podcast"; };
mkRss = format: url: { inherit url format; } // uncat // infrequent;
# format-specific helpers
mkText = mkRss text;
mkImg = mkRss image;
mkPod = mkRss podcast;
# host-specific helpers
mkSubstack = subdomain: mkText "https://${subdomain}.substack.com/feed";
# merge the attrs `new` into each value of the attrs `addTo`
addAttrs = new: addTo: builtins.mapAttrs (k: v: v // new) addTo;
# for each value in `attrs`, add a value to the child attrs which holds its key within the parent attrs.
withInverseMapping = key: attrs: builtins.mapAttrs (k: v: v // { "${key}" = k; }) attrs;
in rec {
podcasts = [
(mkPod "https://lexfridman.com/feed/podcast/" // rat // weekly)
## Astral Codex Ten
(mkPod "http://feeds.libsyn.com/108018/rss" // rat // daily)
## Econ Talk
(mkPod "https://feeds.simplecast.com/wgl4xEgL" // rat // daily)
## Cory Doctorow
(mkPod "https://feeds.feedburner.com/doctorow_podcast" // pol // infrequent)
(mkPod "https://congressionaldish.libsyn.com/rss" // pol // infrequent)
## Civboot
(mkPod "https://anchor.fm/s/34c7232c/podcast/rss" // tech // infrequent)
(mkPod "https://feeds.feedburner.com/80000HoursPodcast" // rat // weekly)
(mkPod "https://allinchamathjason.libsyn.com/rss" // pol // weekly)
(mkPod "https://acquired.libsyn.com/rss" // tech // infrequent)
(mkPod "https://rss.acast.com/deconstructed" // pol // infrequent)
## The Daily
(mkPod "https://feeds.simplecast.com/54nAGcIl" // pol // daily)
(mkPod "https://rss.acast.com/intercepted-with-jeremy-scahill" // pol // weekly)
(mkPod "https://podcast.posttv.com/itunes/post-reports.xml" // pol // weekly)
## Eric Weinstein
(mkPod "https://rss.art19.com/the-portal" // rat // infrequent)
(mkPod "https://feeds.megaphone.fm/darknetdiaries" // tech // infrequent)
(mkPod "http://feeds.wnyc.org/radiolab" // pol // infrequent)
(mkPod "https://wakingup.libsyn.com/rss" // pol // infrequent)
## 99% Invisible
(mkPod "https://feeds.simplecast.com/BqbsxVfO" // pol // infrequent)
(mkPod "https://rss.acast.com/ft-tech-tonic" // tech // infrequent)
(mkPod "https://feeds.feedburner.com/dancarlin/history?format=xml" // rat // infrequent)
## 60 minutes (NB: this features more than *just* audio?)
(mkPod "https://www.cbsnews.com/latest/rss/60-minutes" // pol // infrequent)
## The Verge - Decoder
(mkPod "https://feeds.megaphone.fm/recodedecode" // tech // weekly)
];
texts = [
# AGGREGATORS (> 1 post/day)
(mkText "https://www.lesswrong.com/feed.xml" // rat // hourly)
(mkText "http://www.econlib.org/index.xml" // pol // hourly)
# AGGREGATORS (< 1 post/day)
(mkText "https://palladiummag.com/feed" // uncat // weekly)
(mkText "https://profectusmag.com/feed" // uncat // weekly)
(mkText "https://semiaccurate.com/feed" // tech // weekly)
(mkText "https://linuxphoneapps.org/blog/atom.xml" // tech // infrequent)
(mkText "https://spectrum.ieee.org/rss" // tech // weekly)
## No Moods, Ads or Cutesy Fucking Icons
(mkText "https://www.rifters.com/crawl/?feed=rss2" // uncat // weekly)
# DEVELOPERS
(mkText "https://uninsane.org/atom.xml" // infrequent // tech)
(mkText "https://mg.lol/blog/rss/" // infrequent // tech)
## Ken Shirriff
(mkText "https://www.righto.com/feeds/posts/default" // tech // infrequent)
## Vitalik Buterin
(mkText "https://vitalik.ca/feed.xml" // tech // infrequent)
## ian (Sanctuary)
(mkText "https://sagacioussuricata.com/feed.xml" // tech // infrequent)
## Bunnie Juang
(mkText "https://www.bunniestudios.com/blog/?feed=rss2" // tech // infrequent)
(mkText "https://blog.danieljanus.pl/atom.xml" // tech // infrequent)
(mkText "https://ianthehenry.com/feed.xml" // tech // infrequent)
(mkText "https://bitbashing.io/feed.xml" // tech // infrequent)
(mkText "https://idiomdrottning.org/feed.xml" // uncat // daily)
(mkText "https://anish.lakhwara.com/home.html" // tech // weekly)
(mkText "https://www.jefftk.com/news.rss" // tech // daily)
# (TECH; POL) COMMENTATORS
(mkSubstack "edwardsnowden" // pol // infrequent)
(mkText "http://benjaminrosshoffman.com/feed" // pol // weekly)
## Ben Thompson
(mkText "https://www.stratechery.com/rss" // pol // weekly)
## Balaji
(mkText "https://balajis.com/rss" // pol // weekly)
(mkText "https://www.ben-evans.com/benedictevans/rss.xml" // pol // weekly)
(mkText "https://www.lynalden.com/feed" // pol // infrequent)
(mkText "https://austinvernon.site/rss.xml" // tech // infrequent)
(mkSubstack "oversharing" // pol // daily)
(mkSubstack "doomberg" // tech // weekly)
## David Rosenthal
(mkText "https://blog.dshr.org/rss.xml" // pol // weekly)
## Matt Levine
(mkText "https://www.bloomberg.com/opinion/authors/ARbTQlRLRjE/matthew-s-levine.rss" // pol // weekly)
# RATIONALITY/PHILOSOPHY/ETC
(mkSubstack "samkriss" // humor // infrequent)
(mkText "https://unintendedconsequenc.es/feed" // rat // infrequent)
(mkText "https://applieddivinitystudies.com/atom.xml" // rat // weekly)
(mkText "https://slimemoldtimemold.com/feed.xml" // rat // weekly)
(mkText "https://www.richardcarrier.info/feed" // rat // weekly)
(mkText "https://www.gwern.net/feed.xml" // uncat // infrequent)
## Jason Crawford
(mkText "https://rootsofprogress.org/feed.xml" // rat // weekly)
## Robin Hanson
(mkText "https://www.overcomingbias.com/feed" // rat // daily)
## Scott Alexander
(mkSubstack "astralcodexten" // rat // daily)
## Paul Christiano
(mkText "https://sideways-view.com/feed" // rat // infrequent)
## Sean Carroll
(mkText "https://www.preposterousuniverse.com/rss" // rat // infrequent)
# CODE
(mkText "https://github.com/Kaiteki-Fedi/Kaiteki/commits/master.atom" // tech // infrequent)
];
images = [
(mkImg "https://www.smbc-comics.com/comic/rss" // humor // daily)
(mkImg "https://xkcd.com/atom.xml" // humor // daily)
(mkImg "http://dilbert.com/feed" // humor // daily)
# ART
(mkImg "https://miniature-calendar.com/feed" // art // daily)
];
all = texts ++ images ++ podcasts;
# return only the feed items which match this category (e.g. "tech")
filterCat = cat: feeds: builtins.filter (item: item.cat == cat) feeds;
# return only the feed items which match this format (e.g. "podcast")
filterFormat = format: feeds: builtins.filter (item: item.format == format) feeds;
# transform a list of feeds into an attrs mapping cat => [ feed0 feed1 ... ]
partitionByCat = feeds: builtins.groupBy (f: f.cat) feeds;
# represents a single RSS feed.
opmlTerminal = feed: ''<outline xmlUrl="${feed.url}" type="rss"/>'';
# a list of RSS feeds.
opmlTerminals = feeds: lib.strings.concatStringsSep "\n" (builtins.map opmlTerminal feeds);
# one node which packages some flat grouping of terminals.
opmlGroup = title: feeds: ''
<outline text="${title}" title="${title}">
${opmlTerminals feeds}
</outline>
'';
# a list of groups (`groupMap` is an attrs mapping groupName => [ feed0 feed1 ... ]).
opmlGroups = groupMap: lib.strings.concatStringsSep "\n" (
builtins.attrValues (builtins.mapAttrs opmlGroup groupMap)
);
# top-level OPML file which could be consumed by something else.
opmlTopLevel = body: ''
<?xml version="1.0" encoding="utf-8"?>
<opml version="2.0">
<body>
${body}
</body>
</opml>
'';
# **primary API**: generate a OPML file from the provided feeds
feedsToOpml = feeds: opmlTopLevel (opmlGroups (partitionByCat feeds));
}

View File

@@ -1,139 +0,0 @@
# common settings to toggle (at runtime, in about:config):
# > security.ssl.require_safe_negotiation
# librewolf is a forked firefox which patches firefox to allow more things
# (like default search engines) to be configurable at runtime.
# many of the settings below won't have effect without those patches.
# see: https://gitlab.com/librewolf-community/settings/-/blob/master/distribution/policies.json
{ config, lib, pkgs, ...}:
with lib;
let
cfg = config.sane.web-browser;
# allow easy switching between firefox and librewolf with `defaultSettings`, below
librewolfSettings = {
browser = pkgs.librewolf-unwrapped;
# browser = pkgs.librewolf-unwrapped.overrideAttrs (drv: {
# # this allows side-loading unsigned addons
# MOZ_REQUIRE_SIGNING = false;
# });
libName = "librewolf";
dotDir = ".librewolf";
desktop = "librewolf.desktop";
};
firefoxSettings = {
browser = pkgs.firefox-esr-unwrapped;
libName = "firefox";
dotDir = ".mozilla/firefox";
desktop = "firefox.desktop";
};
defaultSettings = firefoxSettings;
# defaultSettings = librewolfSettings;
package = pkgs.wrapFirefox cfg.browser {
# inherit the default librewolf.cfg
# it can be further customized via ~/.librewolf/librewolf.overrides.cfg
inherit (pkgs.librewolf-unwrapped) extraPrefsFiles;
inherit (cfg) libName;
extraNativeMessagingHosts = [ pkgs.browserpass ];
# extraNativeMessagingHosts = [ pkgs.gopass-native-messaging-host ];
nixExtensions = let
addon = name: extid: hash: pkgs.fetchFirefoxAddon {
inherit name hash;
url = "https://addons.mozilla.org/firefox/downloads/latest/${name}/latest.xpi";
fixedExtid = extid;
};
localAddon = pkg: pkgs.fetchFirefoxAddon {
inherit (pkg) name;
src = "${pkg}/share/mozilla/extensions/\\{ec8030f7-c20a-464f-9b0e-13a3a9e97384\\}/${pkg.extid}.xpi";
fixedExtid = pkg.extid;
};
in [
(addon "ublock-origin" "uBlock0@raymondhill.net" "sha256-C+VQyaJ8BA0ErXGVTdnppJZ6J9SP+izf6RFxdS4VJoU=")
(addon "sponsorblock" "sponsorBlocker@ajay.app" "sha256-au5GGn22n4i6VrdOKqNMOrWdMoVCcpLdjO2wwRvyx7E=")
(addon "bypass-paywalls-clean" "{d133e097-46d9-4ecc-9903-fa6a722a6e0e}" "sha256-m14onUlnpLDPHezA/soKygcc76tF1fLG52tM/LkbAXQ=")
(addon "sidebery" "{3c078156-979c-498b-8990-85f7987dd929}" "sha256-YONfK/rIjlsrTgRHIt3km07Q7KnpIW89Z9r92ZSCc6w=")
(addon "ether-metamask" "webextension@metamask.io" "sha256-dnpwKpNF0KgHMAlz5btkkZySjMsnrXECS35ClkD2XHc=")
# (addon "browserpass-ce" "browserpass@maximbaz.com" "sha256-sXgUBbRvMnRpeIW1MTkmTcoqtW/8RDXAkxAq1evFkpc=")
(localAddon pkgs.browserpass-extension)
];
extraPolicies = {
NoDefaultBookmarks = true;
SearchEngines = {
Default = "DuckDuckGo";
};
AppUpdateURL = "https://localhost";
DisableAppUpdate = true;
OverrideFirstRunPage = "";
OverridePostUpdatePage = "";
DisableSystemAddonUpdate = true;
DisableFirefoxStudies = true;
DisableTelemetry = true;
DisableFeedbackCommands = true;
DisablePocket = true;
DisableSetDesktopBackground = false;
# remove many default search providers
# XXX this seems to prevent the `nixExtensions` from taking effect
# Extensions.Uninstall = [
# "google@search.mozilla.org"
# "bing@search.mozilla.org"
# "amazondotcom@search.mozilla.org"
# "ebay@search.mozilla.org"
# "twitter@search.mozilla.org"
# ];
# XXX doesn't seem to have any effect...
# docs: https://github.com/mozilla/policy-templates#homepage
# Homepage = {
# HomepageURL = "https://uninsane.org/";
# StartPage = "homepage";
# };
# NewTabPage = true;
};
};
in
{
options = {
sane.web-browser = mkOption {
default = defaultSettings;
type = types.attrs;
};
};
config = lib.mkIf config.sane.home-manager.enable {
# XXX: although home-manager calls this option `firefox`, we can use other browsers and it still mostly works.
home-manager.users.colin = lib.mkIf (config.sane.gui.enable) {
programs.firefox = {
enable = true;
inherit package;
};
# uBlock filter list configuration.
# specifically, enable the GDPR cookie prompt blocker.
# data.toOverwrite.filterLists is additive (i.e. it supplements the default filters)
# this configuration method is documented here:
# - <https://github.com/gorhill/uBlock/issues/2986#issuecomment-364035002>
# the specific attribute path is found via scraping ublock code here:
# - <https://github.com/gorhill/uBlock/blob/master/src/js/storage.js>
# - <https://github.com/gorhill/uBlock/blob/master/assets/assets.json>
home.file."${cfg.dotDir}/managed-storage/uBlock0@raymondhill.net.json".text = ''
{
"name": "uBlock0@raymondhill.net",
"description": "ignored",
"type": "storage",
"data": {
"toOverwrite": "{\"filterLists\": [\"fanboy-cookiemonster\"]}"
}
}
'';
home.file."${cfg.dotDir}/${cfg.libName}.overrides.cfg".text = ''
// if we can't query the revocation status of a SSL cert because the issuer is offline,
// treat it as unrevoked.
// see: <https://librewolf.net/docs/faq/#im-getting-sec_error_ocsp_server_error-what-can-i-do>
defaultPref("security.OCSP.require", false);
'';
};
};
}

View File

@@ -1,20 +0,0 @@
{ config, lib, pkgs, ... }:
lib.mkIf config.sane.home-manager.enable
{
home-manager.users.colin.programs.git = {
enable = true;
userName = "colin";
userEmail = "colin@uninsane.org";
aliases = { co = "checkout"; };
extraConfig = {
# difftastic docs:
# - <https://difftastic.wilfred.me.uk/git.html>
diff.tool = "difftastic";
difftool.prompt = false;
"difftool \"difftastic\"".cmd = ''${pkgs.difftastic}/bin/difft "$LOCAL" "$REMOTE"'';
# now run `git difftool` to use difftastic git
};
};
}

View File

@@ -1,71 +0,0 @@
{ config, lib, ... }:
lib.mkIf config.sane.home-manager.enable
{
home-manager.users.colin.programs.kitty = {
enable = true;
# docs: https://sw.kovidgoyal.net/kitty/conf/
settings = {
# disable terminal bell (when e.g. you backspace too many times)
enable_audio_bell = false;
};
keybindings = {
"ctrl+n" = "new_os_window_with_cwd";
};
# docs: https://github.com/kovidgoyal/kitty-themes
# theme = "1984 Light"; # dislike: awful, harsh blues/teals
# theme = "Adventure Time"; # dislike: harsh (dark)
# theme = "Atom One Light"; # GOOD: light theme. all color combos readable. not a huge fan of the blue.
# theme = "Belafonte Day"; # dislike: too low contrast for text colors
# theme = "Belafonte Night"; # better: dark theme that's easy on the eyes. all combos readable. low contrast.
# theme = "Catppuccin"; # dislike: a bit pale/low-contrast (dark)
# theme = "Desert"; # mediocre: colors are harsh
# theme = "Earthsong"; # BEST: dark theme. readable, good contrast. unique, but decent colors.
# theme = "Espresso Libre"; # better: dark theme. readable, but meh colors
# theme = "Forest Night"; # decent: very pastel. it's workable, but unconventional and muted/flat.
# theme = "Gruvbox Material Light Hard"; # mediocre light theme.
# theme = "kanagawabones"; # better: dark theme. colors are too background-y
# theme = "Kaolin Dark"; # dislike: too dark
# theme = "Kaolin Breeze"; # mediocre: not-too-harsh light theme, but some parts are poor contrast
# theme = "Later This Evening"; # mediocre: not-too-harsh dark theme, but cursor is poor contrast
# theme = "Material"; # decent: light theme, few colors.
# theme = "Mayukai"; # decent: not-too-harsh dark theme. the teal is a bit straining
# theme = "Nord"; # mediocre: pale background, low contrast
# theme = "One Half Light"; # better: not-too-harsh light theme. contrast could be better
theme = "PaperColor Dark"; # BEST: dark theme, very readable still the colors are background-y
# theme = "Parasio Dark"; # dislike: too low contrast
# theme = "Pencil Light"; # better: not-too-harsh light theme. decent contrast.
# theme = "Pnevma"; # dislike: too low contrast
# theme = "Piatto Light"; # better: readable light theme. pleasing colors. powerline prompt is hard to read.
# theme = "Rosé Pine Dawn"; # GOOD: light theme. all color combinations are readable. it is very mild -- may need to manually tweak contrast. tasteful colors
# theme = "Rosé Pine Moon"; # GOOD: dark theme. tasteful colors. but background is a bit intense
# theme = "Sea Shells"; # mediocre. not all color combos are readable
# theme = "Solarized Light"; # mediocre: not-too-harsh light theme; GREAT background; but some colors are low contrast
# theme = "Solarized Dark Higher Contrast"; # better: dark theme, decent colors
# theme = "Sourcerer"; # mediocre: ugly colors
# theme = "Space Gray"; # mediocre: too muted
# theme = "Space Gray Eighties"; # better: all readable, decent colors
# theme = "Spacemacs"; # mediocre: too muted
# theme = "Spring"; # mediocre: readable light theme, but the teal is ugly.
# theme = "Srcery"; # better: highly readable. colors are ehhh
# theme = "Substrata"; # decent: nice colors, but a bit flat.
# theme = "Sundried"; # mediocre: the solar text makes me squint
# theme = "Symfonic"; # mediocre: the dark purple has low contrast to the black bg.
# theme = "Tango Light"; # dislike: teal is too grating
# theme = "Tokyo Night Day"; # medicore: too muted
# theme = "Tokyo Night"; # better: tasteful. a bit flat
# theme = "Tomorrow"; # GOOD: all color combinations are readable. contrast is slightly better than Rose. on the blander side
# theme = "Treehouse"; # dislike: the orange is harsh on my eyes.
# theme = "Urple"; # dislike: weird palette
# theme = "Warm Neon"; # decent: not-too-harsh dark theme. the green is a bit unattractive
# theme = "Wild Cherry"; # GOOD: dark theme: nice colors. a bit flat
# theme = "Xcodedark"; # dislike: bad palette
# theme = "citylights"; # decent: dark theme. some parts have just a bit low contrast
# theme = "neobones_light"; # better light theme. the background is maybe too muted
# theme = "vimbones";
# theme = "zenbones_dark"; # mediocre: readable, but meh colors
# theme = "zenbones_light"; # decent: light theme. all colors are readable. contrast is passable but not excellent. highlight color is BAD
# theme = "zenwritten_dark"; # mediocre: looks same as zenbones_dark
# extraConfig = "";
};
}

View File

@@ -1,13 +0,0 @@
{ config, lib, ... }:
lib.mkIf config.sane.home-manager.enable
{
home-manager.users.colin.programs.mpv = {
enable = true;
config = {
save-position-on-quit = true;
keep-open = "yes";
};
};
}

View File

@@ -1,27 +0,0 @@
# nb is a CLI-drive Personal Knowledge Manager
# - <https://xwmx.github.io/nb/>
#
# it's pretty opinionated:
# - autocommits (to git) excessively (disable-able)
# - inserts its own index files to give deterministic names to files
#
# it offers a primitive web-server
# and it offers some CLI query tools
{ config, lib, pkgs, ... }:
# lib.mkIf config.sane.home-manager.enable
lib.mkIf false # XXX disabled!
{
sane.packages.extraUserPkgs = [ pkgs.nb ];
home-manager.users.colin = { config, ... }: {
# nb markdown/personal knowledge manager
home.file.".nb/knowledge".source = config.lib.file.mkOutOfStoreSymlink "/home/colin/dev/knowledge";
home.file.".nb/.current".text = "knowledge";
home.file.".nbrc".text = ''
# manage with `nb settings`
export NB_AUTO_SYNC=0
'';
};
}

View File

@@ -1,117 +0,0 @@
{ config, lib, pkgs, ... }:
lib.mkIf config.sane.home-manager.enable
{
sane.impermanence.home-dirs = [ ".cache/vim-swap" ];
home-manager.users.colin.programs.neovim = {
# neovim: https://github.com/neovim/neovim
enable = true;
viAlias = true;
vimAlias = true;
plugins = with pkgs.vimPlugins; [
# docs: surround-nvim: https://github.com/ur4ltz/surround.nvim/
# docs: vim-surround: https://github.com/tpope/vim-surround
vim-surround
# docs: fzf-vim (fuzzy finder): https://github.com/junegunn/fzf.vim
fzf-vim
# docs: https://github.com/KeitaNakamura/tex-conceal.vim/
({
plugin = tex-conceal-vim;
type = "viml";
config = ''
" present prettier fractions
let g:tex_conceal_frac=1
'';
})
({
plugin = vim-SyntaxRange;
type = "viml";
config = ''
" enable markdown-style codeblock highlighting for tex code
autocmd BufEnter * call SyntaxRange#Include('```tex', '```', 'tex', 'NonText')
" autocmd Syntax tex set conceallevel=2
'';
})
# nabla renders inline math in any document, but it's buggy.
# https://github.com/jbyuki/nabla.nvim
# ({
# plugin = pkgs.nabla;
# type = "lua";
# config = ''
# require'nabla'.enable_virt()
# '';
# })
# treesitter syntax highlighting: https://nixos.wiki/wiki/Tree_sitters
# docs: https://github.com/nvim-treesitter/nvim-treesitter
# config taken from: https://github.com/i077/system/blob/master/modules/home/neovim/default.nix
# this is required for tree-sitter to even highlight
({
plugin = nvim-treesitter.withAllGrammars;
type = "lua";
config = ''
require'nvim-treesitter.configs'.setup {
highlight = {
enable = true,
-- disable treesitter on Rust so that we can use SyntaxRange
-- and leverage TeX rendering in rust projects
disable = { "rust", "tex", "latex" },
-- disable = { "tex", "latex" },
-- true to also use builtin vim syntax highlighting when treesitter fails
additional_vim_regex_highlighting = false
},
incremental_selection = {
enable = true,
keymaps = {
init_selection = "gnn",
node_incremental = "grn",
mcope_incremental = "grc",
node_decremental = "grm"
}
},
indent = {
enable = true,
disable = {}
}
}
vim.o.foldmethod = 'expr'
vim.o.foldexpr = 'nvim_treesitter#foldexpr()'
'';
})
];
extraConfig = ''
" let the terminal handle mouse events, that way i get OS-level ctrl+shift+c/etc
" this used to be default, until <https://github.com/neovim/neovim/pull/19290>
set mouse=
" copy/paste to system clipboard
set clipboard=unnamedplus
" screw tabs; always expand them into spaces
set expandtab
" at least don't open files with sections folded by default
set nofoldenable
" allow text substitutions for certain glyphs.
" higher number = more aggressive substitution (0, 1, 2, 3)
" i only make use of this for tex, but it's unclear how to
" apply that *just* to tex and retain the SyntaxRange stuff.
set conceallevel=2
" horizontal rule under the active line
" set cursorline
" highlight trailing space & related syntax errors (doesn't seem to work??)
" let c_space_errors=1
" let python_space_errors=1
" enable highlighting of leading/trailing spaces,
" and especially tabs
" source: https://www.reddit.com/r/neovim/comments/chlmfk/highlight_trailing_whitespaces_in_neovim/
set list
set listchars=tab:\·,trail:·,extends:,precedes:,nbsp:
'';
};
}

View File

@@ -1,20 +0,0 @@
{ config, lib, pkgs, ... }:
lib.mkIf config.sane.home-manager.enable
{
home-manager.users.colin = let
host = config.networking.hostName;
user_pubkey = (import ../pubkeys.nix).users."${host}";
known_hosts_text = builtins.concatStringsSep
"\n"
(builtins.attrValues (import ../pubkeys.nix).hosts);
in { config, ...}: {
# ssh key is stored in private storage
home.file.".ssh/id_ed25519".source = config.lib.file.mkOutOfStoreSymlink "/home/colin/private/.ssh/id_ed25519";
home.file.".ssh/id_ed25519.pub".text = user_pubkey;
programs.ssh.enable = true;
# this optionally accepts multiple known_hosts paths, separated by space.
programs.ssh.userKnownHostsFile = builtins.toString (pkgs.writeText "known_hosts" known_hosts_text);
};
}

View File

@@ -1,16 +0,0 @@
{ config, lib, ... }:
lib.mkIf config.sane.home-manager.enable
{
# TODO: this should only be shipped on gui platforms
sops.secrets."sublime_music_config" = {
owner = config.users.users.colin.name;
sopsFile = ../../secrets/universal/sublime_music_config.json.bin;
format = "binary";
};
home-manager.users.colin = let sysconfig = config; in { config, ... }: {
# sublime music player
xdg.configFile."sublime-music/config.json".source =
config.lib.file.mkOutOfStoreSymlink sysconfig.sops.secrets.sublime_music_config.path;
};
}

View File

@@ -1,19 +0,0 @@
{ config, lib, ... }:
lib.mkIf config.sane.home-manager.enable
{
home-manager.users.colin.xdg.configFile."vlc/vlcrc".text =
let
feeds = import ./feeds.nix { inherit lib; };
podcastUrls = lib.strings.concatStringsSep "|" (
builtins.map (feed: feed.url) feeds.podcasts
);
in ''
[podcast]
podcast-urls=${podcastUrls}
[core]
metadata-network-access=0
[qt]
qt-privacy-ask=0
'';
}

View File

@@ -1,63 +0,0 @@
{ config, lib, ... }:
lib.mkIf config.sane.home-manager.enable
{
# we don't need to full zsh dir -- just the history file --
# but zsh will sometimes backup the history file and we get fewer errors if we do proper mounts instead of symlinks.
sane.impermanence.home-dirs = [ ".local/share/zsh" ];
home-manager.users.colin.programs.zsh = {
enable = true;
enableSyntaxHighlighting = true;
enableVteIntegration = true;
history.ignorePatterns = [ "rm *" ];
dotDir = ".config/zsh";
history.path = "/home/colin/.local/share/zsh/history";
initExtraBeforeCompInit = ''
# p10k instant prompt
# run p10k configure to configure, but it can't write out its file :-(
POWERLEVEL9K_DISABLE_CONFIGURATION_WIZARD=true
'';
initExtra = ''
# zmv is a way to do rich moves/renames, with pattern matching/substitution.
# see for an example: <https://filipe.kiss.ink/zmv-zsh-rename/>
autoload -Uz zmv
# disable `rm *` confirmations
setopt rmstarsilent
function nd() {
mkdir -p "$1";
pushd "$1";
}
'';
# prezto = oh-my-zsh fork; controls prompt, auto-completion, etc.
# see: https://github.com/sorin-ionescu/prezto
prezto = {
enable = true;
pmodules = [
"environment"
"terminal"
"editor"
"history"
"directory"
"spectrum"
"utility"
"completion"
"prompt"
"git"
];
prompt.theme = "powerlevel10k";
utility.safeOps = false; # disable `mv` confirmation (and supposedly `rm`, too)
};
};
home-manager.users.colin.home.shellAliases = {
":q" = "exit";
# common typos
"cd.." = "cd ..";
"cd../" = "cd ../";
};
}

View File

@@ -6,11 +6,6 @@ let
in in
{ {
options = { options = {
sane.image.enable = mkOption {
default = true;
type = types.bool;
description = "whether to enable image targets. this doesn't mean they'll be built unless you specifically reference the target.";
};
# packages whose contents should be copied directly into the /boot partition. # packages whose contents should be copied directly into the /boot partition.
# e.g. EFI loaders, u-boot bootloader, etc. # e.g. EFI loaders, u-boot bootloader, etc.
sane.image.extraBootFiles = mkOption { sane.image.extraBootFiles = mkOption {

View File

@@ -7,8 +7,6 @@
with lib; with lib;
let let
cfg = config.sane.impermanence; cfg = config.sane.impermanence;
# taken from sops-nix code: checks if any secrets are needed to create /etc/shadow
secretsForUsers = (lib.filterAttrs (_: v: v.neededForUsers) config.sops.secrets) != {};
in in
{ {
options = { options = {
@@ -16,6 +14,10 @@ in
default = false; default = false;
type = types.bool; type = types.bool;
}; };
sane.impermanence.home-files = mkOption {
default = [];
type = types.listOf types.str;
};
sane.impermanence.home-dirs = mkOption { sane.impermanence.home-dirs = mkOption {
default = []; default = [];
type = types.listOf (types.either types.str (types.attrsOf types.str)); type = types.listOf (types.either types.str (types.attrsOf types.str));
@@ -36,17 +38,38 @@ in
map-home-dirs = map-dirs { user = "colin"; group = "users"; mode = "0755"; directory = "/home/colin/"; }; map-home-dirs = map-dirs { user = "colin"; group = "users"; mode = "0755"; directory = "/home/colin/"; };
map-sys-dirs = map-dirs { user = "root"; group = "root"; mode = "0755"; directory = ""; }; map-sys-dirs = map-dirs { user = "root"; group = "root"; mode = "0755"; directory = ""; };
map-service-dirs = map-dirs { user = "root"; group = "root"; mode = "0755"; directory = ""; };
map-home-files = files: builtins.map (f: {
parentDirectory = {
user = "colin";
group = "users";
mode = "0755";
};
file = "/home/colin/${f}";
}) files;
in mkIf cfg.enable { in mkIf cfg.enable {
sane.image.extraDirectories = [ "/nix/persist/var/log" ]; sane.image.extraDirectories = [ "/nix/persist/var/log" ];
environment.persistence."/nix/persist" = { environment.persistence."/nix/persist" = {
directories = (map-home-dirs cfg.home-dirs) ++ (map-sys-dirs [ directories = (map-home-dirs ([
# NB: this `0700` here clobbers the perms for /persist/etc, breaking boot on freshly-deployed devices # cache is probably too big to fit on the tmpfs
# TODO: we could bind-mount it to something which gets cleared per boot, though.
".cache"
".cargo"
".rustup"
".ssh"
".local/share/keyrings"
# intentionally omitted:
# ".config" # managed by home-manager
# ".local" # nothing useful in here
] ++ cfg.home-dirs)) ++ (map-sys-dirs [
# TODO: this `0700` here clobbers the perms for /persist/etc, breaking boot on freshly-deployed devices
# { mode = "0700"; directory = "/etc/NetworkManager/system-connections"; } # { mode = "0700"; directory = "/etc/NetworkManager/system-connections"; }
# "/etc/nixos" # "/etc/nixos"
# "/etc/ssh" # persist only the specific files we want, instead # "/etc/ssh" # persist only the specific files we want, instead
"/var/log" "/var/log"
"/var/backup" # for e.g. postgres dumps "/var/backup" # for e.g. postgres dumps
]) ++ (map-service-dirs ([
# "/var/lib/AccountsService" # not sure what this is, but it's empty # "/var/lib/AccountsService" # not sure what this is, but it's empty
"/var/lib/alsa" # preserve output levels, default devices "/var/lib/alsa" # preserve output levels, default devices
# "/var/lib/blueman" # files aren't human readable # "/var/lib/blueman" # files aren't human readable
@@ -70,25 +93,37 @@ in
# "/var/lib/upower" # historic charge data. unnecessary, but maybe used somewhere? # "/var/lib/upower" # historic charge data. unnecessary, but maybe used somewhere?
# #
# servo additions: # servo additions:
] ++ cfg.service-dirs); # "/var/lib/dhparams" # https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/security/dhparams.nix
# /etc/machine-id is a globally unique identifier used for: # "/var/lib/dovecot"
# - systemd-networkd: DHCP lease renewal (instead of keying by the MAC address) # "/var/lib/duplicity"
# - systemd-journald: to filter logs by host ] ++ cfg.service-dirs));
# - chromium (potentially to track re-installations) files = [
# - gdbus; system services that might upgrade to AF_LOCAL if both services can confirm they're on the same machine "/etc/machine-id"
# of these, systemd-networkd is the only legitimate case to persist the machine-id. "/etc/ssh/ssh_host_ed25519_key"
# depersisting it should be "safe"; edge-cases like systemd-networkd can be directed to use some other ID if necessary. "/etc/ssh/ssh_host_ed25519_key.pub"
# nixos-impermanence shows binding the host ssh priv key to this; i could probably hash the host key into /etc/machine-id if necessary. "/etc/ssh/ssh_host_rsa_key"
# files = [ "/etc/machine-id" ]; "/etc/ssh/ssh_host_rsa_key.pub"
"/home/colin/.zsh_history"
# # XXX these only need persistence because i have mutableUsers = true, i think
# "/etc/group"
# "/etc/passwd"
# "/etc/shadow"
] ++ map-home-files cfg.home-files;
}; };
# secret decoding depends on /etc/ssh keys, which may be persisted systemd.services.sane-sops = {
system.activationScripts.setupSecrets.deps = [ "persist-ssh-host-keys" ]; # TODO: it would be better if we could inject the right dependency into setupSecrets instead of patching like this.
system.activationScripts.setupSecretsForUsers = lib.mkIf secretsForUsers { # /run/current-system/activate contains the precise ordering logic.
deps = [ "persist-ssh-host-keys" ]; # it's largely unaware of systemd.
# maybe we could insert some activation script which simply waits for /etc/ssh to appear?
description = "sops relies on /etc/ssh being available, so re-run its activation AFTER fs-local";
script = ''
${config.system.activationScripts.setupSecrets.text}
${config.system.activationScripts.linkIwdKeys.text}
'';
after = [ "fs-local.target" ];
wantedBy = [ "multi-user.target" ];
}; };
# populated by ssh.nix, which persists /etc/ssh/host_keys
system.activationScripts.persist-ssh-host-keys.text = lib.mkDefault "";
}; };
} }

View File

@@ -1,13 +1,3 @@
# speed up builds from e.g. moby or lappy by having them query desko and servo first.
# if one of these hosts is offline, instead manually specify just cachix:
# - `nixos-rebuild --option substituters https://cache.nixos.org/`
#
# future improvements:
# - apply for community arm build box:
# - <https://github.com/nix-community/aarch64-build-box>
# - don't require all substituters to be online:
# - <https://github.com/NixOS/nix/pull/7188>
{ lib, config, ... }: { lib, config, ... }:
with lib; with lib;
@@ -20,28 +10,22 @@ in
default = false; default = false;
type = types.bool; type = types.bool;
}; };
sane.nixcache.enable-trusted-keys = mkOption {
default = config.sane.nixcache.enable;
type = types.bool;
};
}; };
config = { config = mkIf cfg.enable {
# use our own binary cache # use our own binary cache
# to explicitly build from a specific cache (in case others are down): nix.settings = {
# - `nixos-rebuild ... --option substituters https://cache.nixos.org` substituters = [
# - `nix build ... --substituters http://desko:5000`
nix.settings.substituters = mkIf cfg.enable [
"https://nixcache.uninsane.org" "https://nixcache.uninsane.org"
"http://desko:5000" "http://desko:5000"
"https://nix-community.cachix.org" "https://nix-community.cachix.org"
"https://cache.nixos.org/" "https://cache.nixos.org/"
]; ];
# always trust our keys (so one can explicitly use a substituter even if it's not the default trusted-public-keys = [
nix.settings.trusted-public-keys = mkIf cfg.enable-trusted-keys [
"nixcache.uninsane.org:r3WILM6+QrkmsLgqVQcEdibFD7Q/4gyzD9dGT33GP70=" "nixcache.uninsane.org:r3WILM6+QrkmsLgqVQcEdibFD7Q/4gyzD9dGT33GP70="
"desko:Q7mjjqoBMgNQ5P0e63sLur65A+D4f3Sv4QiycDIKxiI=" "desko:Q7mjjqoBMgNQ5P0e63sLur65A+D4f3Sv4QiycDIKxiI="
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
]; ];
}; };
};
} }

View File

@@ -1,34 +0,0 @@
# create ssh key by running:
# - `ssh-keygen -t ed25519`
let
withHost = host: key: "${host} ${key}";
withUser = user: key: "${key} ${user}";
keys = rec {
lappy = {
host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILSJnqmVl9/SYQ0btvGb0REwwWY8wkdkGXQZfn/1geEc";
users.colin = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDpmFdNSVPRol5hkbbCivRhyeENzb9HVyf9KutGLP2Zu";
};
desko = {
host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFw9NoRaYrM6LbDd3aFBc4yyBlxGQn8HjeHd/dZ3CfHk";
users.colin = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPU5GlsSfbaarMvDA20bxpSZGWviEzXGD8gtrIowc1pX";
};
servo = {
host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOfdSmFkrVT6DhpgvFeQKm3Fh9VKZ9DbLYOPOJWYQ0E8";
users.colin = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPS1qFzKurAdB9blkWomq8gI1g0T3sTs9LsmFOj5VtqX";
};
moby = {
host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO1N/IT3nQYUD+dBlU1sTEEVMxfOyMkrrDeyHcYgnJvw";
users.colin = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICrR+gePnl0nV/vy7I5BzrGeyVL+9eOuXHU1yNE3uCwU";
};
"uninsane.org" = servo;
"git.uninsane.org" = servo;
};
in {
# map hostname -> something suitable for known_keys
hosts = builtins.mapAttrs (host: keys: withHost host keys.host) keys;
# map hostname -> something suitable for authorized_keys to allow access to colin@<hostname>
users = builtins.mapAttrs (host: keys: withUser "colin@${host}" keys.users.colin) keys;
}

View File

@@ -1,7 +0,0 @@
{ ... }:
{
imports = [
./duplicity.nix
./nixserve.nix
];
}

View File

@@ -1,5 +1,5 @@
# docs: https://search.nixos.org/options?channel=21.11&query=duplicity # docs: https://search.nixos.org/options?channel=21.11&query=duplicity
{ config, lib, pkgs, ... }: { config, lib, ... }:
with lib; with lib;
let let
@@ -18,7 +18,8 @@ in
sane.impermanence.service-dirs = [ "/var/lib/duplicity" ]; sane.impermanence.service-dirs = [ "/var/lib/duplicity" ];
services.duplicity.enable = true; services.duplicity.enable = true;
services.duplicity.targetUrl = "$DUPLICITY_URL"; services.duplicity.targetUrl = ''"$DUPLICITY_URL"'';
services.duplicity.escapeUrl = false;
# format: PASSPHRASE=<cleartext> \n DUPLICITY_URL=b2://... # format: PASSPHRASE=<cleartext> \n DUPLICITY_URL=b2://...
# two sisters # two sisters
# PASSPHRASE: remote backups will be encrypted using this passphrase (using gpg) # PASSPHRASE: remote backups will be encrypted using this passphrase (using gpg)
@@ -31,28 +32,29 @@ in
services.duplicity.secretFile = config.sops.secrets.duplicity_passphrase.path; services.duplicity.secretFile = config.sops.secrets.duplicity_passphrase.path;
# NB: manually trigger with `systemctl start duplicity` # NB: manually trigger with `systemctl start duplicity`
services.duplicity.frequency = "daily"; services.duplicity.frequency = "daily";
# TODO: this needs updating to handle impermanence changes
services.duplicity.exclude = [
# impermanent/inconsequential data:
"/dev"
"/proc"
"/run"
"/sys"
"/tmp"
# bind mounted (dupes):
"/var/lib"
# other mounts
"/mnt"
# data that's not worth the cost to backup:
"/nix/persist/var/lib/uninsane/media"
"/nix/persist/home/colin/tmp"
"/nix/persist/home/colin/Videos"
"/home/colin/tmp"
"/home/colin/Videos"
];
services.duplicity.extraFlags = [ services.duplicity.extraFlags = [
# without --allow-source-mismatch, duplicity will abort if you change the hostname between backups # without --allow-source-mismatch, duplicity will abort if you change the hostname between backups
"--allow-source-mismatch" "--allow-source-mismatch"
# includes/exclude ordering matters, so we explicitly control it here.
# the first match decides a file's treatment. so here:
# - /nix/persist/home/colin/tmp is excluded
# - *other* /nix/persist/ files are included by default
# - anything else under `/` are excluded by default
"--exclude" "/nix/persist/home/colin/dev/home-logic/coremem/out" # this can reach > 1 TB
"--exclude" "/nix/persist/home/colin/use/iso" # might want to re-enable... but not critical
"--exclude" "/nix/persist/home/colin/.local/share/sublime-music" # music cache. better to just keep the HQ sources
"--exclude" "/nix/persist/home/colin/.local/share/Steam" # can just re-download games
"--exclude" "/nix/persist/home/colin/.bitmonero/lmdb" # monero blockchain
"--exclude" "/nix/persist/home/colin/.rustup"
"--exclude" "/nix/persist/home/colin/ref" # publicly available data: no point in duplicating it
"--exclude" "/nix/persist/home/colin/tmp"
"--exclude" "/nix/persist/home/colin/Videos"
"--exclude" "/nix/persist/var/lib/duplicity" # don't back up our own backup state!
"--include" "/nix/persist"
"--exclude" "/"
]; ];
# set this for the FIRST backup, then remove it to enable incremental backups # set this for the FIRST backup, then remove it to enable incremental backups
@@ -68,26 +70,5 @@ in
"/dev/mmc0 5M" "/dev/mmc0 5M"
]; ];
}; };
# based on <nixpkgs:nixos/modules/services/backup/duplicity.nix> with changes:
# - remove the cleanup step: API key doesn't have delete perms
# - don't escape the targetUrl: it comes from an env var set in the secret file
systemd.services.duplicity.script = let
cfg = config.services.duplicity;
target = cfg.targetUrl;
extra = escapeShellArgs ([ "--archive-dir" "/var/lib/duplicity" ] ++ cfg.extraFlags);
dup = "${pkgs.duplicity}/bin/duplicity";
in lib.mkForce ''
set -x
# ${dup} cleanup ${target} --force ${extra}
# ${lib.optionalString (cfg.cleanup.maxAge != null) "${dup} remove-older-than ${lib.escapeShellArg cfg.cleanup.maxAge} ${target} --force ${extra}"}
# ${lib.optionalString (cfg.cleanup.maxFull != null) "${dup} remove-all-but-n-full ${builtins.toString cfg.cleanup.maxFull} ${target} --force ${extra}"}
# ${lib.optionalString (cfg.cleanup.maxIncr != null) "${dup} remove-all-inc-of-but-n-full ${toString cfg.cleanup.maxIncr} ${target} --force ${extra}"}
exec ${dup} ${if cfg.fullIfOlderThan == "always" then "full" else "incr"} ${lib.escapeShellArg cfg.root} ${target} ${lib.escapeShellArgs ([]
++ concatMap (p: [ "--include" p ]) cfg.include
++ concatMap (p: [ "--exclude" p ]) cfg.exclude
++ (lib.optionals (cfg.fullIfOlderThan != "never" && cfg.fullIfOlderThan != "always") [ "--full-if-older-than" cfg.fullIfOlderThan ])
)} ${extra}
'';
}; };
} }

View File

@@ -14,8 +14,8 @@ in
type = types.bool; type = types.bool;
}; };
sane.services.nixserve.sopsFile = mkOption { sane.services.nixserve.sopsFile = mkOption {
default = ../../secrets/servo.yaml;
type = types.path; type = types.path;
description = "path to file that contains the nix_serv_privkey secret (can be in VCS)";
}; };
}; };

View File

@@ -23,13 +23,10 @@ in
sane.allocations.greeter-uid = mkId 999; sane.allocations.greeter-uid = mkId 999;
sane.allocations.greeter-gid = mkId 999; sane.allocations.greeter-gid = mkId 999;
sane.allocations.freshrss-uid = mkId 2401;
sane.allocations.freshrss-gid = mkId 2401;
sane.allocations.colin-uid = mkId 1000; sane.allocations.colin-uid = mkId 1000;
sane.allocations.guest-uid = mkId 1100; sane.allocations.guest-uid = mkId 1100;
# found on all hosts # found on all machines
sane.allocations.sshd-uid = mkId 2001; # 997 sane.allocations.sshd-uid = mkId 2001; # 997
sane.allocations.sshd-gid = mkId 2001; # 997 sane.allocations.sshd-gid = mkId 2001; # 997
sane.allocations.polkituser-gid = mkId 2002; # 998 sane.allocations.polkituser-gid = mkId 2002; # 998
@@ -39,15 +36,15 @@ in
sane.allocations.systemd-oom-uid = mkId 2005; sane.allocations.systemd-oom-uid = mkId 2005;
sane.allocations.systemd-oom-gid = mkId 2005; sane.allocations.systemd-oom-gid = mkId 2005;
# found on graphical hosts # found on graphical machines
sane.allocations.nm-iodine-uid = mkId 2101; # desko/moby/lappy sane.allocations.nm-iodine-uid = mkId 2101; # desko/moby/lappy
# found on desko host # found on desko machine
sane.allocations.usbmux-uid = mkId 2204; sane.allocations.usbmux-uid = mkId 2204;
sane.allocations.usbmux-gid = mkId 2204; sane.allocations.usbmux-gid = mkId 2204;
# originally found on moby host # originally found on moby machine
sane.allocations.avahi-uid = mkId 2304; sane.allocations.avahi-uid = mkId 2304;
sane.allocations.avahi-gid = mkId 2304; sane.allocations.avahi-gid = mkId 2304;
sane.allocations.colord-uid = mkId 2305; sane.allocations.colord-uid = mkId 2305;

View File

@@ -0,0 +1,33 @@
{ pkgs, ... }:
{
imports = [
./allocations.nix
./env
./fs.nix
./net.nix
./secrets.nix
./users.nix
./vpn.nix
];
time.timeZone = "America/Los_Angeles";
fonts = {
enableDefaultFonts = true;
fonts = with pkgs; [ font-awesome twitter-color-emoji hack-font ];
fontconfig.enable = true;
fontconfig.defaultFonts = {
emoji = [ "Font Awesome 6 Free" "Twitter Color Emoji" ];
monospace = [ "Hack" ];
serif = [ "DejaVu Serif" ];
sansSerif = [ "DejaVu Sans" ];
};
};
# allow `nix flake ...` command
nix.extraOptions = ''
experimental-features = nix-command flakes
'';
}

24
modules/universal/env/default.nix vendored Normal file
View File

@@ -0,0 +1,24 @@
{ ... }:
{
imports = [
./feeds.nix
./home-manager.nix
./home-packages.nix
./system-packages.nix
];
# programs.vim.defaultEditor = true;
environment.variables = {
EDITOR = "vim";
# git claims it should use EDITOR, but it doesn't!
GIT_EDITOR = "vim";
# TODO: these should be moved to `home.sessionVariables` (home-manager)
# Electron apps should use native wayland backend:
# https://nixos.wiki/wiki/Slack#Wayland
# Discord under sway crashes with this.
# NIXOS_OZONE_WL = "1";
# LIBGL_ALWAYS_SOFTWARE = "1";
};
}

41
modules/universal/env/feeds.nix vendored Normal file
View File

@@ -0,0 +1,41 @@
{ lib, ... }:
with lib;
{
options = {
sane.feeds.podcastUrls = mkOption {
type = types.listOf types.str;
default = [
"https://lexfridman.com/feed/podcast/"
## Astral Codex Ten
"http://feeds.libsyn.com/108018/rss"
## Econ Talk
"https://feeds.simplecast.com/wgl4xEgL"
## Cory Doctorow
"https://feeds.feedburner.com/doctorow_podcast"
"https://congressionaldish.libsyn.com/rss"
## Civboot
"https://anchor.fm/s/34c7232c/podcast/rss"
"https://feeds.feedburner.com/80000HoursPodcast"
"https://allinchamathjason.libsyn.com/rss"
"https://acquired.libsyn.com/rss"
"https://rss.acast.com/deconstructed"
## The Daily
"https://feeds.simplecast.com/54nAGcIl"
"https://rss.acast.com/intercepted-with-jeremy-scahill"
"https://podcast.posttv.com/itunes/post-reports.xml"
## Eric Weinstein
"https://rss.art19.com/the-portal"
"https://feeds.megaphone.fm/darknetdiaries"
"http://feeds.wnyc.org/radiolab"
"https://wakingup.libsyn.com/rss"
## 99% Invisible
"https://feeds.simplecast.com/BqbsxVfO"
"https://rss.acast.com/ft-tech-tonic"
"https://feeds.feedburner.com/dancarlin/history?format=xml"
## 60 minutes (NB: this features more than *just* audio?)
"https://www.cbsnews.com/latest/rss/60-minutes"
];
};
};
}

578
modules/universal/env/home-manager.nix vendored Normal file
View File

@@ -0,0 +1,578 @@
# docs:
# https://rycee.gitlab.io/home-manager/
# https://rycee.gitlab.io/home-manager/options.html
# man home-configuration.nix
#
{ lib, config, pkgs, ... }:
with lib;
let
cfg = config.sane.home-manager;
vim-swap-dir = ".cache/vim-swap";
# extract package from `extraPackages`
pkglist = pkgspec: builtins.map (e: e.pkg or e) pkgspec;
# extract `dir` from `extraPackages`
dirlist = pkgspec: builtins.concatLists (builtins.map (e: if e ? "dir" then [ e.dir ] else []) pkgspec);
# extract `persist-files` from `extraPackages`
persistfileslist = pkgspec: builtins.concatLists (builtins.map (e: if e ? "persist-files" then e.persist-files else []) pkgspec);
# TODO: dirlist and persistfileslist should be folded
in
{
options = {
sane.home-manager.enable = mkOption {
default = false;
type = types.bool;
};
# packages to deploy to the user's home
sane.home-manager.extraPackages = mkOption {
default = [ ];
# each entry can be either a package, or attrs:
# { pkg = package; dir = optional string;
type = types.listOf (types.either types.package types.attrs);
};
# attributes to copy directly to home-manager's `wayland.windowManager` option
sane.home-manager.windowManager = mkOption {
default = {};
type = types.attrs;
};
# extra attributes to include in home-manager's `programs` option
sane.home-manager.programs = mkOption {
default = {};
type = types.attrs;
};
};
config = lib.mkIf cfg.enable {
sops.secrets."aerc_accounts" = {
owner = config.users.users.colin.name;
sopsFile = ../../../secrets/universal/aerc_accounts.conf;
format = "binary";
};
sops.secrets."sublime_music_config" = {
owner = config.users.users.colin.name;
sopsFile = ../../../secrets/universal/sublime_music_config.json.bin;
format = "binary";
};
sane.impermanence.home-dirs = [
"archive"
"dev"
"records"
"ref"
"tmp"
"use"
"Music"
"Pictures"
"Videos"
vim-swap-dir
] ++ (dirlist cfg.extraPackages);
sane.impermanence.home-files = persistfileslist cfg.extraPackages;
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
# XXX this weird rename + closure is to get home-manager's `config.lib.file` to exist.
# see: https://github.com/nix-community/home-manager/issues/589#issuecomment-950474105
home-manager.users.colin = let sysconfig = config; in { config, ... }: {
# run `home-manager-help` to access manpages
# or `man home-configuration.nix`
manual.html.enable = true;
home.packages = pkglist cfg.extraPackages;
wayland.windowManager = cfg.windowManager;
home.stateVersion = "21.11";
home.username = "colin";
home.homeDirectory = "/home/colin";
home.activation = {
initKeyring = {
after = ["writeBoundary"];
before = [];
data = "${../../../scripts/init-keyring}";
};
};
# XDG defines things like ~/Desktop, ~/Downloads, etc.
# these clutter the home, so i mostly don't use them.
xdg.userDirs = {
enable = true;
createDirectories = false; # on headless systems, most xdg dirs are noise
desktop = "$HOME/.xdg/Desktop";
documents = "$HOME/dev";
download = "$HOME/tmp";
music = "$HOME/Music";
pictures = "$HOME/Pictures";
publicShare = "$HOME/.xdg/Public";
templates = "$HOME/.xdg/Templates";
videos = "$HOME/Videos";
};
# the xdg mime type for a file can be found with:
# - `xdg-mime query filetype path/to/thing.ext`
xdg.mimeApps.enable = true;
xdg.mimeApps.defaultApplications = {
# HTML
"text/html" = [ "librewolf.desktop" ];
"x-scheme-handler/http" = [ "librewolf.desktop" ];
"x-scheme-handler/https" = [ "librewolf.desktop" ];
"x-scheme-handler/about" = [ "librewolf.desktop" ];
"x-scheme-handler/unknown" = [ "librewolf.desktop" ];
# RICH-TEXT DOCUMENTS
"application/pdf" = [ "org.gnome.Evince.desktop" ];
"text/markdown" = [ "obsidian.desktop" ];
# IMAGES
"image/heif" = [ "org.gnome.gThumb.desktop" ]; # apple codec
"image/png" = [ "org.gnome.gThumb.desktop" ];
"image/jpeg" = [ "org.gnome.gThumb.desktop" ];
# VIDEO
"video/mp4" = [ "vlc.desktop" ];
"video/quicktime" = [ "vlc.desktop" ];
"video/x-matroska" = [ "vlc.desktop" ];
# AUDIO
"audio/flag" = [ "vlc.desktop" ];
"audio/mpeg" = [ "vlc.desktop" ];
"audio/x-vorbis+ogg" = [ "vlc.desktop" ];
};
# convenience
home.file."knowledge".source = config.lib.file.mkOutOfStoreSymlink "/home/colin/dev/knowledge";
home.file."nixos".source = config.lib.file.mkOutOfStoreSymlink "/home/colin/dev/nixos";
home.file."Videos/servo".source = config.lib.file.mkOutOfStoreSymlink "/mnt/servo-media/Videos";
home.file."Videos/servo-incomplete".source = config.lib.file.mkOutOfStoreSymlink "/mnt/servo-media/incomplete";
home.file."Music/servo".source = config.lib.file.mkOutOfStoreSymlink "/mnt/servo-media/Music";
# nb markdown/personal knowledge manager
home.file.".nb/knowledge".source = config.lib.file.mkOutOfStoreSymlink "/home/colin/dev/knowledge";
home.file.".nb/.current".text = "knowledge";
home.file.".nbrc".text = ''
# manage with `nb settings`
export NB_AUTO_SYNC=0
'';
# uBlock filter list configuration.
# specifically, enable the GDPR cookie prompt blocker.
# data.toOverwrite.filterLists is additive (i.e. it supplements the default filters)
# this configuration method is documented here:
# - <https://github.com/gorhill/uBlock/issues/2986#issuecomment-364035002>
# the specific attribute path is found via scraping ublock code here:
# - <https://github.com/gorhill/uBlock/blob/master/src/js/storage.js>
# - <https://github.com/gorhill/uBlock/blob/master/assets/assets.json>
home.file.".librewolf/managed-storage/uBlock0@raymondhill.net.json".text = ''
{
"name": "uBlock0@raymondhill.net",
"description": "ignored",
"type": "storage",
"data": {
"toOverwrite": "{\"filterLists\": [\"fanboy-cookiemonster\"]}"
}
}
'';
home.file.".librewolf/librewolf.overrides.cfg".text = ''
// if we can't query the revocation status of a SSL cert because the issuer is offline,
// treat it as unrevoked.
// see: <https://librewolf.net/docs/faq/#im-getting-sec_error_ocsp_server_error-what-can-i-do>
defaultPref("security.OCSP.require", false);
'';
# aerc TUI mail client
xdg.configFile."aerc/accounts.conf".source =
config.lib.file.mkOutOfStoreSymlink sysconfig.sops.secrets.aerc_accounts.path;
# make Discord usable even when client is "outdated"
xdg.configFile."discord/settings.json".text = ''
{
"SKIP_HOST_UPDATE": true
}
'';
# sublime music player
xdg.configFile."sublime-music/config.json".source =
config.lib.file.mkOutOfStoreSymlink sysconfig.sops.secrets.sublime_music_config.path;
xdg.configFile."vlc/vlcrc".text =
let
podcastUrls = lib.strings.concatStringsSep "|" sysconfig.sane.feeds.podcastUrls;
in ''
[podcast]
podcast-urls=${podcastUrls}
[core]
metadata-network-access=0
[qt]
qt-privacy-ask=0
'';
xdg.configFile."gpodderFeeds.opml".text =
let
entries = builtins.toString (builtins.map
(url: ''\n <outline xmlUrl="${url}" type="rss"/>'')
sysconfig.sane.feeds.podcastUrls
);
in ''
<?xml version="1.0" encoding="utf-8"?>
<opml version="2.0">
<body>${entries}
</body>
</opml>
'';
# gnome feeds RSS viewer
xdg.configFile."org.gabmus.gfeeds.json".text = builtins.toJSON {
feeds = {
# AGGREGATORS (> 1 post/day)
"https://www.lesswrong.com/feed.xml" = { tags = [ "hourly" "rat" ]; };
"http://www.econlib.org/index.xml" = { tags = [ "hourly" "pol" ]; };
# AGGREGATORS (< 1 post/day)
"https://palladiummag.com/feed" = { tags = [ "weekly" "uncat" ]; };
"https://profectusmag.com/feed" = { tags = [ "weekly" "uncat" ]; };
"https://semiaccurate.com/feed" = { tags = [ "weekly" "tech" ]; };
"https://linuxphoneapps.org/blog/atom.xml" = { tags = [ "infrequent" "tech" ]; };
"https://spectrum.ieee.org/rss" = { tags = [ "weekly" "tech" ]; };
## No Moods, Ads or Cutesy Fucking Icons
"https://www.rifters.com/crawl/?feed=rss2" = { tags = [ "weekly" "uncat" ]; };
# DEVELOPERS
"https://mg.lol/blog/rss/" = { tags = [ "infrequent" "tech" ]; };
## Ken Shirriff
"https://www.righto.com/feeds/posts/default" = { tags = [ "infrequent" "tech" ]; };
## Vitalik Buterin
"https://vitalik.ca/feed.xml" = { tags = [ "infrequent" "tech" ]; };
## ian (Sanctuary)
"https://sagacioussuricata.com/feed.xml" = { tags = [ "infrequent" "tech" ]; };
## Bunnie Juang
"https://www.bunniestudios.com/blog/?feed=rss2" = { tags = [ "infrequent" "tech" ]; };
"https://blog.danieljanus.pl/atom.xml" = { tags = [ "infrequent" "tech" ]; };
"https://ianthehenry.com/feed.xml" = { tags = [ "infrequent" "tech" ]; };
"https://bitbashing.io/feed.xml" = { tags = [ "infrequent" "tech" ]; };
"https://idiomdrottning.org/feed.xml" = { tags = [ "daily" "uncat" ]; };
# (TECH; POL) COMMENTATORS
"http://benjaminrosshoffman.com/feed" = { tags = [ "weekly" "pol" ]; };
## Ben Thompson
"https://www.stratechery.com/rss" = { tags = [ "weekly" "pol" ]; };
## Balaji
"https://balajis.com/rss" = { tags = [ "weekly" "pol" ]; };
"https://www.ben-evans.com/benedictevans/rss.xml" = { tags = [ "weekly" "pol" ]; };
"https://www.lynalden.com/feed" = { tags = [ "infrequent" "pol" ]; };
"https://austinvernon.site/rss.xml" = { tags = [ "infrequent" "tech" ]; };
"https://oversharing.substack.com/feed" = { tags = [ "daily" "pol" ]; };
"https://doomberg.substack.com/feed" = { tags = [ "weekly" "tech" ]; };
## David Rosenthal
"https://blog.dshr.org/rss.xml" = { tags = [ "weekly" "pol" ]; };
## Matt Levine
"https://www.bloomberg.com/opinion/authors/ARbTQlRLRjE/matthew-s-levine.rss" = { tags = [ "weekly" "pol" ]; };
# RATIONALITY/PHILOSOPHY/ETC
"https://samkriss.substack.com/feed" = { tags = [ "infrequent" "uncat" ]; }; # ... satire? phil?
"https://unintendedconsequenc.es/feed" = { tags = [ "infrequent" "rat" ]; };
"https://applieddivinitystudies.com/atom.xml" = { tags = [ "weekly" "rat" ]; };
"https://slimemoldtimemold.com/feed.xml" = { tags = [ "weekly" "rat" ]; };
"https://www.richardcarrier.info/feed" = { tags = [ "weekly" "rat" ]; };
"https://www.gwern.net/feed.xml" = { tags = [ "infrequent" "uncat" ]; };
## Jason Crawford
"https://rootsofprogress.org/feed.xml" = { tags = [ "weekly" "rat" ]; };
## Robin Hanson
"https://www.overcomingbias.com/feed" = { tags = [ "daily" "rat" ]; };
## Scott Alexander
"https://astralcodexten.substack.com/feed.xml" = { tags = [ "daily" "rat" ]; };
## Paul Christiano
"https://sideways-view.com/feed" = { tags = [ "infrequent" "rat" ]; };
## Sean Carroll
"https://www.preposterousuniverse.com/rss" = { tags = [ "infrequent" "rat" ]; };
# COMICS
"https://www.smbc-comics.com/comic/rss" = { tags = [ "daily" "visual" ]; };
"https://xkcd.com/atom.xml" = { tags = [ "daily" "visual" ]; };
"http://dilbert.com/feed" = { tags = ["daily" "visual" ]; };
# ART
"https://miniature-calendar.com/feed" = { tags = [ "daily" "visual" ]; };
# CODE
"https://github.com/Kaiteki-Fedi/Kaiteki/commits/master.atom" = { tags = [ "infrequent" "tech" ]; };
};
dark_reader = false;
new_first = true;
# windowsize = {
# width = 350;
# height = 650;
# };
max_article_age_days = 90;
enable_js = false;
max_refresh_threads = 3;
# saved_items = {};
# read_items = [];
show_read_items = true;
full_article_title = true;
# views: "webview", "reader", "rsscont"
default_view = "rsscont";
open_links_externally = true;
full_feed_name = false;
refresh_on_startup = true;
tags = [
# hourly => aggregator
# daily => prolifiq writer
# weekly => i can keep up with most -- but maybe not all -- of their content
# infrequent => i can read everything in this category
"hourly" "daily" "weekly" "infrequent"
# rat[ionality] gets used interchangably with philosophy, here.
# pol[itical] gets used for social commentary and economics as well.
# visual gets used for comics/art
"uncat" "rat" "tech" "pol" "visual"
];
open_youtube_externally = false;
media_player = "vlc"; # default: mpv
};
programs = {
home-manager.enable = true; # this lets home-manager manage dot-files in user dirs, i think
zsh = {
enable = true;
enableSyntaxHighlighting = true;
enableVteIntegration = true;
dotDir = ".config/zsh";
initExtraBeforeCompInit = ''
# p10k instant prompt
# run p10k configure to configure, but it can't write out its file :-(
POWERLEVEL9K_DISABLE_CONFIGURATION_WIZARD=true
'';
initExtra = ''
# zmv is a way to do rich moves/renames, with pattern matching/substitution.
# see for an example: <https://filipe.kiss.ink/zmv-zsh-rename/>
autoload -Uz zmv
'';
# prezto = oh-my-zsh fork; controls prompt, auto-completion, etc.
# see: https://github.com/sorin-ionescu/prezto
prezto = {
enable = true;
pmodules = [
"environment"
"terminal"
"editor"
"history"
"directory"
"spectrum"
"utility"
"completion"
"prompt"
"git"
];
prompt = {
theme = "powerlevel10k";
};
};
};
kitty = {
enable = true;
# docs: https://sw.kovidgoyal.net/kitty/conf/
settings = {
# disable terminal bell (when e.g. you backspace too many times)
enable_audio_bell = false;
};
keybindings = {
"ctrl+n" = "new_os_window_with_cwd";
};
# docs: https://github.com/kovidgoyal/kitty-themes
# theme = "1984 Light"; # dislike: awful, harsh blues/teals
# theme = "Adventure Time"; # dislike: harsh (dark)
# theme = "Atom One Light"; # GOOD: light theme. all color combos readable. not a huge fan of the blue.
# theme = "Belafonte Day"; # dislike: too low contrast for text colors
# theme = "Belafonte Night"; # better: dark theme that's easy on the eyes. all combos readable. low contrast.
# theme = "Catppuccin"; # dislike: a bit pale/low-contrast (dark)
# theme = "Desert"; # mediocre: colors are harsh
# theme = "Earthsong"; # BEST: dark theme. readable, good contrast. unique, but decent colors.
# theme = "Espresso Libre"; # better: dark theme. readable, but meh colors
# theme = "Forest Night"; # decent: very pastel. it's workable, but unconventional and muted/flat.
# theme = "Gruvbox Material Light Hard"; # mediocre light theme.
# theme = "kanagawabones"; # better: dark theme. colors are too background-y
# theme = "Kaolin Dark"; # dislike: too dark
# theme = "Kaolin Breeze"; # mediocre: not-too-harsh light theme, but some parts are poor contrast
# theme = "Later This Evening"; # mediocre: not-too-harsh dark theme, but cursor is poor contrast
# theme = "Material"; # decent: light theme, few colors.
# theme = "Mayukai"; # decent: not-too-harsh dark theme. the teal is a bit straining
# theme = "Nord"; # mediocre: pale background, low contrast
# theme = "One Half Light"; # better: not-too-harsh light theme. contrast could be better
theme = "PaperColor Dark"; # BEST: dark theme, very readable still the colors are background-y
# theme = "Parasio Dark"; # dislike: too low contrast
# theme = "Pencil Light"; # better: not-too-harsh light theme. decent contrast.
# theme = "Pnevma"; # dislike: too low contrast
# theme = "Piatto Light"; # better: readable light theme. pleasing colors. powerline prompt is hard to read.
# theme = "Rosé Pine Dawn"; # GOOD: light theme. all color combinations are readable. it is very mild -- may need to manually tweak contrast. tasteful colors
# theme = "Rosé Pine Moon"; # GOOD: dark theme. tasteful colors. but background is a bit intense
# theme = "Sea Shells"; # mediocre. not all color combos are readable
# theme = "Solarized Light"; # mediocre: not-too-harsh light theme; GREAT background; but some colors are low contrast
# theme = "Solarized Dark Higher Contrast"; # better: dark theme, decent colors
# theme = "Sourcerer"; # mediocre: ugly colors
# theme = "Space Gray"; # mediocre: too muted
# theme = "Space Gray Eighties"; # better: all readable, decent colors
# theme = "Spacemacs"; # mediocre: too muted
# theme = "Spring"; # mediocre: readable light theme, but the teal is ugly.
# theme = "Srcery"; # better: highly readable. colors are ehhh
# theme = "Substrata"; # decent: nice colors, but a bit flat.
# theme = "Sundried"; # mediocre: the solar text makes me squint
# theme = "Symfonic"; # mediocre: the dark purple has low contrast to the black bg.
# theme = "Tango Light"; # dislike: teal is too grating
# theme = "Tokyo Night Day"; # medicore: too muted
# theme = "Tokyo Night"; # better: tasteful. a bit flat
# theme = "Tomorrow"; # GOOD: all color combinations are readable. contrast is slightly better than Rose. on the blander side
# theme = "Treehouse"; # dislike: the orange is harsh on my eyes.
# theme = "Urple"; # dislike: weird palette
# theme = "Warm Neon"; # decent: not-too-harsh dark theme. the green is a bit unattractive
# theme = "Wild Cherry"; # GOOD: dark theme: nice colors. a bit flat
# theme = "Xcodedark"; # dislike: bad palette
# theme = "citylights"; # decent: dark theme. some parts have just a bit low contrast
# theme = "neobones_light"; # better light theme. the background is maybe too muted
# theme = "vimbones";
# theme = "zenbones_dark"; # mediocre: readable, but meh colors
# theme = "zenbones_light"; # decent: light theme. all colors are readable. contrast is passable but not excellent. highlight color is BAD
# theme = "zenwritten_dark"; # mediocre: looks same as zenbones_dark
# extraConfig = "";
};
git = {
enable = true;
userName = "colin";
userEmail = "colin@uninsane.org";
};
neovim = {
# neovim: https://github.com/neovim/neovim
enable = true;
viAlias = true;
vimAlias = true;
plugins = with pkgs.vimPlugins; [
# docs: surround-nvim: https://github.com/ur4ltz/surround.nvim/
# docs: vim-surround: https://github.com/tpope/vim-surround
vim-surround
# docs: fzf-vim (fuzzy finder): https://github.com/junegunn/fzf.vim
fzf-vim
# docs: https://github.com/KeitaNakamura/tex-conceal.vim/
({
plugin = tex-conceal-vim;
type = "viml";
config = ''
" present prettier fractions
let g:tex_conceal_frac=1
'';
})
({
plugin = vim-SyntaxRange;
type = "viml";
config = ''
" enable markdown-style codeblock highlighting for tex code
autocmd BufEnter * call SyntaxRange#Include('```tex', '```', 'tex', 'NonText')
" autocmd Syntax tex set conceallevel=2
'';
})
# nabla renders inline math in any document, but it's buggy.
# https://github.com/jbyuki/nabla.nvim
# ({
# plugin = pkgs.nabla;
# type = "lua";
# config = ''
# require'nabla'.enable_virt()
# '';
# })
# treesitter syntax highlighting: https://nixos.wiki/wiki/Tree_sitters
# docs: https://github.com/nvim-treesitter/nvim-treesitter
# config taken from: https://github.com/i077/system/blob/master/modules/home/neovim/default.nix
# this is required for tree-sitter to even highlight
({
plugin = (nvim-treesitter.withPlugins (_: pkgs.tree-sitter.allGrammars));
type = "lua";
config = ''
require'nvim-treesitter.configs'.setup {
highlight = {
enable = true,
-- disable treesitter on Rust so that we can use SyntaxRange
-- and leverage TeX rendering in rust projects
disable = { "rust", "tex", "latex" },
-- disable = { "tex", "latex" },
-- true to also use builtin vim syntax highlighting when treesitter fails
additional_vim_regex_highlighting = false
},
incremental_selection = {
enable = true,
keymaps = {
init_selection = "gnn",
node_incremental = "grn",
mcope_incremental = "grc",
node_decremental = "grm"
}
},
indent = {
enable = true,
disable = {}
}
}
vim.o.foldmethod = 'expr'
vim.o.foldexpr = 'nvim_treesitter#foldexpr()'
'';
})
];
extraConfig = ''
" let the terminal handle mouse events, that way i get OS-level ctrl+shift+c/etc
" this used to be default, until <https://github.com/neovim/neovim/pull/19290>
set mouse=
" copy/paste to system clipboard
set clipboard=unnamedplus
" screw tabs; always expand them into spaces
set expandtab
" at least don't open files with sections folded by default
set nofoldenable
" allow text substitutions for certain glyphs.
" higher number = more aggressive substitution (0, 1, 2, 3)
" i only make use of this for tex, but it's unclear how to
" apply that *just* to tex and retain the SyntaxRange stuff.
set conceallevel=2
" horizontal rule under the active line
" set cursorline
" highlight trailing space & related syntax errors (doesn't seem to work??)
" let c_space_errors=1
" let python_space_errors=1
" enable highlighting of leading/trailing spaces,
" and especially tabs
" source: https://www.reddit.com/r/neovim/comments/chlmfk/highlight_trailing_whitespaces_in_neovim/
set list
set listchars=tab:\·,trail:·,extends:,precedes:,nbsp:
'';
};
# XXX: although home-manager calls this option `firefox`, we can use other browsers and it still mostly works.
firefox = lib.mkIf (sysconfig.sane.gui.enable) {
enable = true;
package = import ./web-browser.nix pkgs;
};
# "command not found" will cause the command to be searched in nixpkgs
nix-index.enable = true;
} // cfg.programs;
home.shellAliases = {
":q" = "exit";
# common typos
"cd.." = "cd ..";
"cd../" = "cd ../";
};
};
};
}

View File

@@ -3,19 +3,11 @@
with lib; with lib;
with pkgs; with pkgs;
let let
cfg = config.sane.packages; cfg = config.sane.home-packages;
consolePkgs = [ universalPkgs = [
backblaze-b2 backblaze-b2
cdrtools
dmidecode
duplicity duplicity
efivar
flashrom
fwupd
gnupg gnupg
gocryptfs
gopass
gopass-jsonapi
ifuse ifuse
ipfs ipfs
libimobiledevice libimobiledevice
@@ -23,7 +15,7 @@ let
lm_sensors # for sensors-detect lm_sensors # for sensors-detect
lshw lshw
ffmpeg ffmpeg
memtester nb
networkmanager networkmanager
nixpkgs-review nixpkgs-review
# nixos-generators # nixos-generators
@@ -33,8 +25,8 @@ let
# ponymix # ponymix
pulsemixer pulsemixer
python3 python3
rsync
# python3Packages.eyeD3 # music tagging # python3Packages.eyeD3 # music tagging
rmlint
sane-scripts sane-scripts
sequoia sequoia
snapper snapper
@@ -56,18 +48,14 @@ let
# GUI only # GUI only
aerc # email client aerc # email client
audacity audacity
celluloid # mpv frontend
chromium chromium
clinfo clinfo
{ pkg = dino; private = ".local/share/dino"; }
electrum electrum
# creds/session keys, etc # creds/session keys, etc
{ pkg = element-desktop; private = ".config/Element"; } { pkg = element-desktop; dir = ".config/Element"; }
# `emote` will show a first-run dialog based on what's in this directory.
# mostly, it just keeps a LRU of previously-used emotes to optimize display order. emote # TODO: package [smile](https://github.com/mijorus/smile) for probably a better mobile experience.
# TODO: package [smile](https://github.com/mijorus/smile) for probably a better mobile experience.
{ pkg = emote; dir = ".local/share/Emote"; }
evince # works on phosh evince # works on phosh
# { pkg = fluffychat-moby; dir = ".local/share/chat.fluffy.fluffychat"; } # TODO: ship normal fluffychat on non-moby? # { pkg = fluffychat-moby; dir = ".local/share/chat.fluffy.fluffychat"; } # TODO: ship normal fluffychat on non-moby?
@@ -78,7 +66,7 @@ let
# XXX by default fractal stores its state in ~/.local/share/<UUID>. # XXX by default fractal stores its state in ~/.local/share/<UUID>.
# after logging in, manually change ~/.local/share/keyrings/... to point it to some predictable subdir. # after logging in, manually change ~/.local/share/keyrings/... to point it to some predictable subdir.
# then reboot (so that libsecret daemon re-loads the keyring...?) # then reboot (so that libsecret daemon re-loads the keyring...?)
{ pkg = fractal-next; private = ".local/share/fractal"; } { pkg = fractal-next; dir = ".local/share/fractal"; }
gimp # broken on phosh gimp # broken on phosh
gnome.cheese gnome.cheese
@@ -88,7 +76,7 @@ let
gnome.gnome-disk-utility gnome.gnome-disk-utility
gnome.gnome-maps # works on phosh gnome.gnome-maps # works on phosh
gnome.nautilus gnome.nautilus
# gnome-podcasts gnome-podcasts
gnome.gnome-system-monitor gnome.gnome-system-monitor
gnome.gnome-terminal # works on phosh gnome.gnome-terminal # works on phosh
gnome.gnome-weather gnome.gnome-weather
@@ -96,32 +84,24 @@ let
{ pkg = gpodder-configured; dir = "gPodder/Downloads"; } { pkg = gpodder-configured; dir = "gPodder/Downloads"; }
gthumb gthumb
handbrake
inkscape inkscape
kdenlive kaiteki # Pleroma client
gnome.zenity # for kaiteki (it will use qarma, kdialog, or zenity)
kid3 # audio tagging kid3 # audio tagging
krita krita
libreoffice-fresh # XXX colin: maybe don't want this on mobile libreoffice-fresh # XXX colin: maybe don't want this on mobile
lollypop lollypop
mesa-demos mesa-demos
{ pkg = mpv; dir = ".config/mpv/watch_later"; }
networkmanagerapplet networkmanagerapplet
# not strictly necessary, but allows caching articles; offline use, etc.
{ pkg = newsflash; dir = ".local/share/news-flash"; }
# settings (electron app). TODO: can i manage these settings with home-manager? # settings (electron app). TODO: can i manage these settings with home-manager?
{ pkg = obsidian; dir = ".config/obsidian"; } { pkg = obsidian; dir = ".config/obsidian"; }
pavucontrol pavucontrol
# picard # music tagging picard # music tagging
playerctl playerctl
libsForQt5.plasmatube # Youtube player
soundconverter soundconverter
# sublime music persists any downloaded albums here. # sublime music persists any downloaded albums here.
# it doesn't obey a conventional ~/Music/{Artist}/{Album}/{Track} notation, so no symlinking # it doesn't obey a conventional ~/Music/{Artist}/{Album}/{Track} notation, so no symlinking
@@ -130,10 +110,8 @@ let
{ pkg = sublime-music; dir = ".local/share/sublime-music"; } { pkg = sublime-music; dir = ".local/share/sublime-music"; }
tdesktop # broken on phosh tdesktop # broken on phosh
{ pkg = tokodon; dir = ".cache/KDE/tokodon"; }
# vlc remembers play position in ~/.config/vlc/vlc-qt-interface.conf # vlc remembers play position in ~/.config/vlc/vlc-qt-interface.conf
{ pkg = vlc; dir = ".config/vlc"; } { pkg = vlc; persist-files = [ ".config/vlc/vlc-qt-interface.conf" ]; }
whalebird # pleroma client. input is broken on phosh whalebird # pleroma client. input is broken on phosh
xdg-utils # for xdg-open xdg-utils # for xdg-open
@@ -150,9 +128,6 @@ let
nss = pkgs.nss_latest; nss = pkgs.nss_latest;
}); in { pkg = discord; dir = ".config/discord"; }) }); in { pkg = discord; dir = ".config/discord"; })
# kaiteki # Pleroma client
# gnome.zenity # for kaiteki (it will use qarma, kdialog, or zenity)
logseq logseq
losslesscut-bin losslesscut-bin
makemkv makemkv
@@ -170,103 +145,30 @@ let
(tor-browser-bundle-bin.override { useHardenedMalloc = false; }) (tor-browser-bundle-bin.override { useHardenedMalloc = false; })
# zcash coins. safe to delete, just slow to regenerate (10-60 minutes) # zcash coins. safe to delete, just slow to regenerate (10-60 minutes)
{ pkg = zecwallet-lite; private = ".zcash"; } { pkg = zecwallet-lite; dir = ".zcash"; }
] else []); ] else []);
# general-purpose utilities that we want any user to be able to access
# (specifically: root, in case of rescue)
systemPkgs = [
btrfs-progs
cryptsetup
dig
efibootmgr
fatresize
fd
file
gptfdisk
hdparm
htop
iftop
inetutils # for telnet
iotop
iptables
jq
killall
lsof
netcat
nethogs
nmap
openssl
parted
pciutils
powertop
ripgrep
screen
smartmontools
socat
usbutils
wget
];
# useful devtools: # useful devtools:
devPkgs = [ # bison
bison # dtc
dtc # flex
flex # gcc
gcc
gdb
# gcc-arm-embedded # gcc-arm-embedded
# gcc_multi # gcc_multi
gnumake # gnumake
mercurial # mix2nix
mix2nix # rustup
rustup # swig
swig
];
in in
{ {
options = { options = {
# packages to deploy to the user's home sane.home-packages.enableGuiPkgs = mkOption {
sane.packages.extraUserPkgs = mkOption {
default = [ ];
# each entry can be either a package, or attrs:
# { pkg = package; dir = optional string; private = optional string };
type = types.listOf (types.either types.package types.attrs);
};
sane.packages.enableConsolePkgs = mkOption {
default = false; default = false;
type = types.bool; type = types.bool;
}; };
sane.packages.enableGuiPkgs = mkOption {
default = false;
type = types.bool;
}; };
sane.packages.enableDevPkgs = mkOption {
description = ''
enable packages that are useful for building other software by hand.
you should prefer to keep this disabled except when prototyping, e.g. packaging new software.
'';
default = false;
type = types.bool;
};
sane.packages.enableSystemPkgs = mkOption {
default = false;
type = types.bool;
description = "enable system-wide packages";
};
sane.packages.enabledUserPkgs = mkOption {
default = cfg.extraUserPkgs
++ (if cfg.enableConsolePkgs then consolePkgs else [])
++ (if cfg.enableGuiPkgs then guiPkgs else [])
++ (if cfg.enableDevPkgs then devPkgs else [])
;
type = types.listOf (types.either types.package types.attrs);
description = "generated from other config options";
};
};
config = { config = {
environment.systemPackages = mkIf cfg.enableSystemPkgs systemPkgs; sane.home-manager.extraPackages = universalPkgs
++ (if cfg.enableGuiPkgs then guiPkgs else []);
}; };
} }

View File

@@ -0,0 +1,38 @@
{ pkgs, ... }:
{
# general-purpose utilities that we want any user to be able to access
# (specifically: root, in case of rescue)
environment.systemPackages = with pkgs; [
btrfs-progs
cryptsetup
dig
efibootmgr
fatresize
fd
file
gptfdisk
hdparm
htop
iftop
inetutils # for telnet
iotop
iptables
jq
killall
lsof
netcat
nethogs
nmap
openssl
parted
pciutils
powertop
ripgrep
screen
smartmontools
socat
usbutils
wget
];
}

55
modules/universal/env/web-browser.nix vendored Normal file
View File

@@ -0,0 +1,55 @@
pkgs:
# common settings to toggle (at runtime, in about:config):
# > security.ssl.require_safe_negotiation
# librewolf is a forked firefox which patches firefox to allow more things
# (like default search engines) to be configurable at runtime.
# many of the settings below won't have effect without those patches.
# see: https://gitlab.com/librewolf-community/settings/-/blob/master/distribution/policies.json
pkgs.wrapFirefox pkgs.librewolf-unwrapped {
# inherit the default librewolf.cfg
# it can be further customized via ~/.librewolf/librewolf.overrides.cfg
inherit (pkgs.librewolf-unwrapped) extraPrefsFiles;
libName = "librewolf";
extraPolicies = {
NoDefaultBookmarks = true;
SearchEngines = {
Default = "DuckDuckGo";
};
AppUpdateURL = "https://localhost";
DisableAppUpdate = true;
OverrideFirstRunPage = "";
OverridePostUpdatePage = "";
DisableSystemAddonUpdate = true;
DisableFirefoxStudies = true;
DisableTelemetry = true;
DisableFeedbackCommands = true;
DisablePocket = true;
DisableSetDesktopBackground = false;
Extensions = {
Install = [
"https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi"
"https://addons.mozilla.org/firefox/downloads/latest/sponsorblock/latest.xpi"
"https://addons.mozilla.org/firefox/downloads/latest/bypass-paywalls-clean/latest.xpi"
"https://addons.mozilla.org/firefox/downloads/latest/sidebery/latest.xpi"
"https://addons.mozilla.org/firefox/downloads/latest/ether-metamask/latest.xpi"
];
# remove many default search providers
Uninstall = [
"google@search.mozilla.org"
"bing@search.mozilla.org"
"amazondotcom@search.mozilla.org"
"ebay@search.mozilla.org"
"twitter@search.mozilla.org"
];
};
# XXX doesn't seem to have any effect...
# docs: https://github.com/mozilla/policy-templates#homepage
# Homepage = {
# HomepageURL = "https://uninsane.org/";
# StartPage = "homepage";
# };
# NewTabPage = true;
};
}

View File

@@ -19,17 +19,11 @@ let sshOpts = rec {
optionsRoot = optionsBase ++ [ optionsRoot = optionsBase ++ [
# we don't transform_symlinks because that breaks the validity of remote /nix stores # we don't transform_symlinks because that breaks the validity of remote /nix stores
"sftp_server=/run/wrappers/bin/sudo\\040/run/current-system/sw/libexec/sftp-server" "sftp_server=/run/wrappers/bin/sudo\\040${pkgs.openssh}/libexec/sftp-server"
]; ];
}; };
in in
{ {
environment.pathsToLink = [
# needed to achieve superuser access for user-mounted filesystems (see optionsRoot above)
# we can only link whole directories here, even though we're only interested in pkgs.openssh
"/libexec"
];
fileSystems."/mnt/servo-media-wan" = { fileSystems."/mnt/servo-media-wan" = {
device = "colin@uninsane.org:/var/lib/uninsane/media"; device = "colin@uninsane.org:/var/lib/uninsane/media";
inherit (sshOpts) fsType; inherit (sshOpts) fsType;

View File

@@ -18,20 +18,10 @@
# docs: # docs:
# - <https://nixos.wiki/wiki/Iwd> # - <https://nixos.wiki/wiki/Iwd>
# - <https://iwd.wiki.kernel.org/networkmanager> # - <https://iwd.wiki.kernel.org/networkmanager>
# - `man iwd.config` for global config
# - `man iwd.network` for per-SSID config
# use `iwctl` to control # use `iwctl` to control
networking.networkmanager.wifi.backend = "iwd";
networking.wireless.iwd.enable = true; networking.wireless.iwd.enable = true;
networking.wireless.iwd.settings = { networking.networkmanager.wifi.backend = "iwd";
# auto-connect to a stronger network if signal drops below this value
# bedroom -> bedroom connection is -35 to -40 dBm
# bedroom -> living room connection is -60 dBm
General.RoamThreshold = "-52"; # default -70
General.RoamThreshold5G = "-52"; # default -76
};
# TODO: don't need to depend on binsh if we were to use a nix-style shebang
system.activationScripts.linkIwdKeys = let system.activationScripts.linkIwdKeys = let
unwrapped = ../../scripts/install-iwd; unwrapped = ../../scripts/install-iwd;
install-iwd = pkgs.writeShellApplication { install-iwd = pkgs.writeShellApplication {
@@ -40,7 +30,7 @@
text = ''${unwrapped} "$@"''; text = ''${unwrapped} "$@"'';
}; };
in (lib.stringAfter in (lib.stringAfter
[ "setupSecrets" "binsh" ] [ "setupSecrets" ]
'' ''
mkdir -p /var/lib/iwd mkdir -p /var/lib/iwd
${install-iwd}/bin/install-iwd /run/secrets/iwd /var/lib/iwd ${install-iwd}/bin/install-iwd /run/secrets/iwd /var/lib/iwd

View File

@@ -16,7 +16,7 @@
# add the result to .sops.yaml # add the result to .sops.yaml
# since we specify ssh pubkeys in the nix config, you can just grep for `ssh-ed25519` here and use those instead # since we specify ssh pubkeys in the nix config, you can just grep for `ssh-ed25519` here and use those instead
# #
# for each host you want to decrypt secrets: # for each machine you want to decrypt secrets:
# $ cat /etc/ssh/ssh_host_ed25519_key.pub | ssh-to-age # $ cat /etc/ssh/ssh_host_ed25519_key.pub | ssh-to-age
# add the result to .sops.yaml # add the result to .sops.yaml
# $ sops updatekeys secrets/example.yaml # $ sops updatekeys secrets/example.yaml
@@ -32,12 +32,12 @@
# This will add secrets.yaml to the nix store # This will add secrets.yaml to the nix store
# You can avoid this by adding a string to the full path instead, i.e. # You can avoid this by adding a string to the full path instead, i.e.
# sops.defaultSopsFile = "/root/.sops/secrets/example.yaml"; # sops.defaultSopsFile = "/root/.sops/secrets/example.yaml";
sops.defaultSopsFile = ../../secrets/universal.yaml; sops.defaultSopsFile = ./../../secrets/universal.yaml;
# This will automatically import SSH keys as age keys # This will automatically import SSH keys as age keys
sops.age.sshKeyPaths = [ sops.age.sshKeyPaths = [
"/etc/ssh/host_keys/ssh_host_ed25519_key" "/etc/ssh/ssh_host_ed25519_key"
# "/home/colin/.ssh/id_ed25519_dec"
]; ];
sops.gnupg.sshKeyPaths = []; # disable RSA key import
# This is using an age key that is expected to already be in the filesystem # This is using an age key that is expected to already be in the filesystem
# sops.age.keyFile = "/home/colin/.ssh/age.pub"; # sops.age.keyFile = "/home/colin/.ssh/age.pub";
# sops.age.keyFile = "/var/lib/sops-nix/key.txt"; # sops.age.keyFile = "/var/lib/sops-nix/key.txt";

View File

@@ -43,35 +43,19 @@ in
"feedbackd" "feedbackd"
"dialout" # required for modem access "dialout" # required for modem access
]; ];
# initial password is empty, in case anything goes wrong.
# if `colin-passwd` (a password hash) is successfully found/decrypted, that becomes the password at boot.
initialPassword = lib.mkDefault ""; initialPassword = lib.mkDefault "";
passwordFile = lib.mkIf (config.sops.secrets ? "colin-passwd") config.sops.secrets.colin-passwd.path;
shell = pkgs.zsh; shell = pkgs.zsh;
openssh.authorizedKeys.keys = builtins.attrValues (import ../../modules/pubkeys.nix).users; # shell = pkgs.bashInteractive;
# XXX colin: create ssh key for THIS user by logging in and running:
pamMount = { # ssh-keygen -t ed25519
# mount encrypted stuff at login openssh.authorizedKeys.keys = [
# requires that login password == fs encryption password "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDpmFdNSVPRol5hkbbCivRhyeENzb9HVyf9KutGLP2Zu colin@lappy"
# fstype = "fuse"; "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPU5GlsSfbaarMvDA20bxpSZGWviEzXGD8gtrIowc1pX colin@desko"
# path = "${pkgs.gocryptfs}/bin/gocryptfs#/nix/persist/home/colin/private"; "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPS1qFzKurAdB9blkWomq8gI1g0T3sTs9LsmFOj5VtqX colin@servo"
fstype = "fuse.gocryptfs"; # moby doesn't need to login to any other devices yet
path = "/nix/persist/home/colin/private"; # "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICrR+gePnl0nV/vy7I5BzrGeyVL+9eOuXHU1yNE3uCwU colin@moby"
mountpoint = "/home/colin/private";
options="nodev,nosuid,quiet,allow_other";
};
};
sane.impermanence.home-dirs = [
# cache is probably too big to fit on the tmpfs
# TODO: we could bind-mount it to something which gets cleared per boot, though.
".cache"
".cargo"
".rustup"
".local/share/keyrings"
]; ];
};
sane.impermanence.service-dirs = mkIf cfg.guest.enable [ sane.impermanence.service-dirs = mkIf cfg.guest.enable [
{ user = "guest"; group = "users"; directory = "/home/guest"; } { user = "guest"; group = "users"; directory = "/home/guest"; }

View File

@@ -0,0 +1,302 @@
diff --git a/pkgs/development/compilers/flutter/default.nix b/pkgs/development/compilers/flutter/default.nix
index 9eba6773448..f51aeb8b624 100644
--- a/pkgs/development/compilers/flutter/default.nix
+++ b/pkgs/development/compilers/flutter/default.nix
@@ -4,20 +4,20 @@ let
getPatches = dir:
let files = builtins.attrNames (builtins.readDir dir);
in map (f: dir + ("/" + f)) files;
- version = "2.10.1";
+ version = "3.0.0";
channel = "stable";
filename = "flutter_linux_${version}-${channel}.tar.xz";
# Decouples flutter derivation from dart derivation,
# use specific dart version to not need to bump dart derivation when bumping flutter.
- dartVersion = "2.16.1";
+ dartVersion = "2.17.0";
dartSourceBase = "https://storage.googleapis.com/dart-archive/channels";
dartForFlutter = dart.override {
version = dartVersion;
sources = {
"${dartVersion}-x86_64-linux" = fetchurl {
url = "${dartSourceBase}/stable/release/${dartVersion}/sdk/dartsdk-linux-x64-release.zip";
- sha256 = "sha256-PMY6DCFQC8XrlnFzOEPcwgBAs5/cAvNd78969Z+I1Fk=";
+ sha256 = "57b8fd964e47c81d467aeb95b099a670ab7e8f54a1cd74d45bcd1fdc77913d86";
};
};
};
@@ -29,7 +29,7 @@ in {
pname = "flutter";
src = fetchurl {
url = "https://storage.googleapis.com/flutter_infra_release/releases/${channel}/linux/${filename}";
- sha256 = "sha256-rSfwcglDV2rvJl10j7FByAWmghd2FYxrlkgYnvRO54Y=";
+ sha256 = "e96d75ec8e7dc2a46bc8dad5a9e01c391ab9310ad01c4e3940c963dd263788a0";
};
patches = getPatches ./patches;
};
diff --git a/pkgs/development/compilers/flutter/flutter.nix b/pkgs/development/compilers/flutter/flutter.nix
index 43538ede339..ece25c14b55 100644
--- a/pkgs/development/compilers/flutter/flutter.nix
+++ b/pkgs/development/compilers/flutter/flutter.nix
@@ -56,12 +56,15 @@ let
export STAMP_PATH="$FLUTTER_ROOT/bin/cache/flutter_tools.stamp"
export DART_SDK_PATH="${dart}"
+ export DART="${dart}/bin/dart"
HOME=../.. # required for pub upgrade --offline, ~/.pub-cache
# path is relative otherwise it's replaced by /build/flutter
+ # mkdir -p "$HOME/.cache"
+ # ln -sf "$FLUTTER_ROOT" "$HOME/.cache/flutter"
pushd "$FLUTTER_TOOLS_DIR"
- ${dart}/bin/pub get --offline
+ ${dart}/bin/dart pub get --offline
popd
local revision="$(cd "$FLUTTER_ROOT"; git rev-parse HEAD)"
diff --git a/pkgs/development/compilers/flutter/patches/git-dir.patch b/pkgs/development/compilers/flutter/patches/git-dir.patch
new file mode 100644
index 00000000000..0c736f945ea
--- /dev/null
+++ b/pkgs/development/compilers/flutter/patches/git-dir.patch
@@ -0,0 +1,102 @@
+diff --git a/dev/bots/prepare_package.dart b/dev/bots/prepare_package.dart
+index 468a91a954..5def6897ce 100644
+--- a/dev/bots/prepare_package.dart
++++ b/dev/bots/prepare_package.dart
+@@ -525,7 +525,7 @@ class ArchiveCreator {
+
+ Future<String> _runGit(List<String> args, {Directory? workingDirectory}) {
+ return _processRunner.runProcess(
+- <String>['git', ...args],
++ <String>['git', '--git-dir', '.git', ...args],
+ workingDirectory: workingDirectory ?? flutterRoot,
+ );
+ }
+diff --git a/packages/flutter_tools/lib/src/commands/downgrade.dart b/packages/flutter_tools/lib/src/commands/downgrade.dart
+index bb0eb428a9..4a2a48bb5e 100644
+--- a/packages/flutter_tools/lib/src/commands/downgrade.dart
++++ b/packages/flutter_tools/lib/src/commands/downgrade.dart
+@@ -118,7 +118,7 @@ class DowngradeCommand extends FlutterCommand {
+ // Detect unknown versions.
+ final ProcessUtils processUtils = _processUtils!;
+ final RunResult parseResult = await processUtils.run(<String>[
+- 'git', 'describe', '--tags', lastFlutterVersion,
++ 'git', '--git-dir', '.git', 'describe', '--tags', lastFlutterVersion,
+ ], workingDirectory: workingDirectory);
+ if (parseResult.exitCode != 0) {
+ throwToolExit('Failed to parse version for downgrade:\n${parseResult.stderr}');
+@@ -191,7 +191,7 @@ class DowngradeCommand extends FlutterCommand {
+ continue;
+ }
+ final RunResult parseResult = await _processUtils!.run(<String>[
+- 'git', 'describe', '--tags', sha,
++ 'git', '--git-dir', '.git', 'describe', '--tags', sha,
+ ], workingDirectory: workingDirectory);
+ if (parseResult.exitCode == 0) {
+ buffer.writeln('Channel "${getNameForChannel(channel)}" was previously on: ${parseResult.stdout}.');
+diff --git a/packages/flutter_tools/lib/src/version.dart b/packages/flutter_tools/lib/src/version.dart
+index f2068a6ca2..99b161689e 100644
+--- a/packages/flutter_tools/lib/src/version.dart
++++ b/packages/flutter_tools/lib/src/version.dart
+@@ -106,7 +106,7 @@ class FlutterVersion {
+ String? channel = _channel;
+ if (channel == null) {
+ final String gitChannel = _runGit(
+- 'git rev-parse --abbrev-ref --symbolic @{u}',
++ 'git --git-dir .git rev-parse --abbrev-ref --symbolic @{u}',
+ globals.processUtils,
+ _workingDirectory,
+ );
+@@ -114,7 +114,7 @@ class FlutterVersion {
+ if (slash != -1) {
+ final String remote = gitChannel.substring(0, slash);
+ _repositoryUrl = _runGit(
+- 'git ls-remote --get-url $remote',
++ 'git --git-dir .git ls-remote --get-url $remote',
+ globals.processUtils,
+ _workingDirectory,
+ );
+@@ -326,7 +326,7 @@ class FlutterVersion {
+ /// the branch name will be returned as `'[user-branch]'`.
+ String getBranchName({ bool redactUnknownBranches = false }) {
+ _branch ??= () {
+- final String branch = _runGit('git rev-parse --abbrev-ref HEAD', globals.processUtils);
++ final String branch = _runGit('git --git-dir .git rev-parse --abbrev-ref HEAD', globals.processUtils);
+ return branch == 'HEAD' ? channel : branch;
+ }();
+ if (redactUnknownBranches || _branch!.isEmpty) {
+@@ -359,7 +359,7 @@ class FlutterVersion {
+ /// wrapper that does that.
+ @visibleForTesting
+ static List<String> gitLog(List<String> args) {
+- return <String>['git', '-c', 'log.showSignature=false', 'log'] + args;
++ return <String>['git', '-c', 'log.showSignature=false', '--git-dir', '.git', 'log'] + args;
+ }
+
+ /// Gets the release date of the latest available Flutter version.
+@@ -730,7 +730,7 @@ class GitTagVersion {
+
+ static GitTagVersion determine(ProcessUtils processUtils, {String? workingDirectory, bool fetchTags = false, String gitRef = 'HEAD'}) {
+ if (fetchTags) {
+- final String channel = _runGit('git rev-parse --abbrev-ref HEAD', processUtils, workingDirectory);
++ final String channel = _runGit('git --git-dir .git rev-parse --abbrev-ref HEAD', processUtils, workingDirectory);
+ if (channel == 'dev' || channel == 'beta' || channel == 'stable') {
+ globals.printTrace('Skipping request to fetchTags - on well known channel $channel.');
+ } else {
+@@ -739,7 +739,7 @@ class GitTagVersion {
+ }
+ // find all tags attached to the given [gitRef]
+ final List<String> tags = _runGit(
+- 'git tag --points-at $gitRef', processUtils, workingDirectory).trim().split('\n');
++ 'git --git-dir .git tag --points-at $gitRef', processUtils, workingDirectory).trim().split('\n');
+
+ // Check first for a stable tag
+ final RegExp stableTagPattern = RegExp(r'^\d+\.\d+\.\d+$');
+@@ -760,7 +760,7 @@ class GitTagVersion {
+ // recent tag and number of commits past.
+ return parse(
+ _runGit(
+- 'git describe --match *.*.* --long --tags $gitRef',
++ 'git --git-dir .git describe --match *.*.* --long --tags $gitRef',
+ processUtils,
+ workingDirectory,
+ )
diff --git a/pkgs/development/compilers/flutter/patches/revert-frontend_server_cache.patch b/pkgs/development/compilers/flutter/patches/revert-frontend_server_cache.patch
new file mode 100644
index 00000000000..f68029eb7a1
--- /dev/null
+++ b/pkgs/development/compilers/flutter/patches/revert-frontend_server_cache.patch
@@ -0,0 +1,130 @@
+diff --git a/packages/flutter_tools/lib/src/artifacts.dart b/packages/flutter_tools/lib/src/artifacts.dart
+index 2aac9686e8..32c4b98b88 100644
+--- a/packages/flutter_tools/lib/src/artifacts.dart
++++ b/packages/flutter_tools/lib/src/artifacts.dart
+@@ -346,10 +346,10 @@ class CachedArtifacts implements Artifacts {
+ ) {
+ switch (artifact) {
+ case HostArtifact.engineDartSdkPath:
+- final String path = _dartSdkPath(_cache);
++ final String path = _dartSdkPath(_fileSystem);
+ return _fileSystem.directory(path);
+ case HostArtifact.engineDartBinary:
+- final String path = _fileSystem.path.join(_dartSdkPath(_cache), 'bin', _hostArtifactToFileName(artifact, _platform.isWindows));
++ final String path = _fileSystem.path.join(_dartSdkPath(_fileSystem), 'bin', _hostArtifactToFileName(artifact, _platform.isWindows));
+ return _fileSystem.file(path);
+ case HostArtifact.flutterWebSdk:
+ final String path = _getFlutterWebSdkPath();
+@@ -398,7 +398,7 @@ class CachedArtifacts implements Artifacts {
+ case HostArtifact.dart2jsSnapshot:
+ case HostArtifact.dartdevcSnapshot:
+ case HostArtifact.kernelWorkerSnapshot:
+- final String path = _fileSystem.path.join(_dartSdkPath(_cache), 'bin', 'snapshots', _hostArtifactToFileName(artifact, _platform.isWindows));
++ final String path = _fileSystem.path.join(_dartSdkPath(_fileSystem), 'bin', 'snapshots', _hostArtifactToFileName(artifact, _platform.isWindows));
+ return _fileSystem.file(path);
+ case HostArtifact.iosDeploy:
+ final String artifactFileName = _hostArtifactToFileName(artifact, _platform.isWindows);
+@@ -461,11 +461,13 @@ class CachedArtifacts implements Artifacts {
+ String _getAndroidArtifactPath(Artifact artifact, TargetPlatform platform, BuildMode mode) {
+ final String engineDir = _getEngineArtifactsPath(platform, mode)!;
+ switch (artifact) {
++ case Artifact.frontendServerSnapshotForEngineDartSdk:
++ assert(mode != BuildMode.debug, 'Artifact $artifact only available in non-debug mode.');
++ return _fileSystem.path.join(engineDir, _artifactToFileName(artifact));
+ case Artifact.genSnapshot:
+ assert(mode != BuildMode.debug, 'Artifact $artifact only available in non-debug mode.');
+ final String hostPlatform = getNameForHostPlatform(getCurrentHostPlatform());
+ return _fileSystem.path.join(engineDir, hostPlatform, _artifactToFileName(artifact));
+- case Artifact.frontendServerSnapshotForEngineDartSdk:
+ case Artifact.constFinder:
+ case Artifact.flutterFramework:
+ case Artifact.flutterMacOSFramework:
+@@ -497,13 +499,13 @@ class CachedArtifacts implements Artifacts {
+ switch (artifact) {
+ case Artifact.genSnapshot:
+ case Artifact.flutterXcframework:
++ case Artifact.frontendServerSnapshotForEngineDartSdk:
+ final String artifactFileName = _artifactToFileName(artifact)!;
+ final String engineDir = _getEngineArtifactsPath(platform, mode)!;
+ return _fileSystem.path.join(engineDir, artifactFileName);
+ case Artifact.flutterFramework:
+ final String engineDir = _getEngineArtifactsPath(platform, mode)!;
+ return _getIosEngineArtifactPath(engineDir, environmentType, _fileSystem);
+- case Artifact.frontendServerSnapshotForEngineDartSdk:
+ case Artifact.constFinder:
+ case Artifact.flutterMacOSFramework:
+ case Artifact.flutterMacOSPodspec:
+@@ -594,14 +596,10 @@ class CachedArtifacts implements Artifacts {
+ // For script snapshots any gen_snapshot binary will do. Returning gen_snapshot for
+ // android_arm in profile mode because it is available on all supported host platforms.
+ return _getAndroidArtifactPath(artifact, TargetPlatform.android_arm, BuildMode.profile);
+- case Artifact.frontendServerSnapshotForEngineDartSdk:
+- return _fileSystem.path.join(
+- _dartSdkPath(_cache), 'bin', 'snapshots',
+- _artifactToFileName(artifact),
+- );
+ case Artifact.flutterTester:
+ case Artifact.vmSnapshotData:
+ case Artifact.isolateSnapshotData:
++ case Artifact.frontendServerSnapshotForEngineDartSdk:
+ case Artifact.icuData:
+ final String engineArtifactsPath = _cache.getArtifactDirectory('engine').path;
+ final String platformDirName = _enginePlatformDirectoryName(platform);
+@@ -797,7 +795,7 @@ class CachedLocalEngineArtifacts implements LocalEngineArtifacts {
+ final String path = _fileSystem.path.join(_hostEngineOutPath, 'dart-sdk', 'bin', 'snapshots', _hostArtifactToFileName(artifact, _platform.isWindows));
+ return _fileSystem.file(path);
+ case HostArtifact.dartdevcSnapshot:
+- final String path = _fileSystem.path.join(_dartSdkPath(_cache), 'bin', 'snapshots', _hostArtifactToFileName(artifact, _platform.isWindows));
++ final String path = _fileSystem.path.join(_dartSdkPath(_fileSystem), 'bin', 'snapshots', _hostArtifactToFileName(artifact, _platform.isWindows));
+ return _fileSystem.file(path);
+ case HostArtifact.kernelWorkerSnapshot:
+ final String path = _fileSystem.path.join(_hostEngineOutPath, 'dart-sdk', 'bin', 'snapshots', _hostArtifactToFileName(artifact, _platform.isWindows));
+@@ -922,9 +920,7 @@ class CachedLocalEngineArtifacts implements LocalEngineArtifacts {
+ case Artifact.windowsUwpCppClientWrapper:
+ return _fileSystem.path.join(_hostEngineOutPath, artifactFileName);
+ case Artifact.frontendServerSnapshotForEngineDartSdk:
+- return _fileSystem.path.join(
+- _hostEngineOutPath, 'dart-sdk', 'bin', 'snapshots', artifactFileName,
+- );
++ return _fileSystem.path.join(_hostEngineOutPath, 'gen', artifactFileName);
+ case Artifact.uwptool:
+ return _fileSystem.path.join(_hostEngineOutPath, artifactFileName);
+ }
+@@ -1034,8 +1030,8 @@ class OverrideArtifacts implements Artifacts {
+ }
+
+ /// Locate the Dart SDK.
+-String _dartSdkPath(Cache cache) {
+- return cache.getRoot().childDirectory('dart-sdk').path;
++String _dartSdkPath(FileSystem fileSystem) {
++ return fileSystem.path.join(Cache.flutterRoot!, 'bin', 'cache', 'dart-sdk');
+ }
+
+ class _TestArtifacts implements Artifacts {
+diff --git a/packages/flutter_tools/test/general.shard/artifacts_test.dart b/packages/flutter_tools/test/general.shard/artifacts_test.dart
+index d906511a15..adfdd4bb42 100644
+--- a/packages/flutter_tools/test/general.shard/artifacts_test.dart
++++ b/packages/flutter_tools/test/general.shard/artifacts_test.dart
+@@ -153,10 +153,6 @@ void main() {
+ artifacts.getArtifactPath(Artifact.windowsUwpDesktopPath, platform: TargetPlatform.windows_uwp_x64, mode: BuildMode.release),
+ fileSystem.path.join('root', 'bin', 'cache', 'artifacts', 'engine', 'windows-uwp-x64-release'),
+ );
+- expect(
+- artifacts.getArtifactPath(Artifact.frontendServerSnapshotForEngineDartSdk),
+- fileSystem.path.join('root', 'bin', 'cache', 'dart-sdk', 'bin', 'snapshots', 'frontend_server.dart.snapshot')
+- );
+ });
+
+ testWithoutContext('precompiled web artifact paths are correct', () {
+@@ -322,11 +318,6 @@ void main() {
+ artifacts.getHostArtifact(HostArtifact.engineDartSdkPath).path,
+ fileSystem.path.join('/out', 'host_debug_unopt', 'dart-sdk'),
+ );
+- expect(
+- artifacts.getArtifactPath(Artifact.frontendServerSnapshotForEngineDartSdk),
+- fileSystem.path.join('/out', 'host_debug_unopt', 'dart-sdk', 'bin',
+- 'snapshots', 'frontend_server.dart.snapshot')
+- );
+ });
+
+ testWithoutContext('getEngineType', () {

View File

@@ -0,0 +1,646 @@
diff --git a/pkgs/applications/networking/instant-messengers/fluffychat/default.nix b/pkgs/applications/networking/instant-messengers/fluffychat/default.nix
index d50e7118cc1..22bbeb212f0 100644
--- a/pkgs/applications/networking/instant-messengers/fluffychat/default.nix
+++ b/pkgs/applications/networking/instant-messengers/fluffychat/default.nix
@@ -1,16 +1,16 @@
{ lib
, fetchFromGitLab
-, flutter
+, flutter2
, olm
, imagemagick
, makeDesktopItem
}:
-flutter.mkFlutterApp rec {
+flutter2.mkFlutterApp rec {
pname = "fluffychat";
version = "1.2.0";
- vendorHash = "sha256-co+bnsVIyg42JpM9FimfGEjrd6A99GlBeow1Dgv7NBI=";
+ vendorHash = "sha256-1PDX023WXRmRe/b1L+6Du91BvGwYNp3YATqYSQdPrRY=";
src = fetchFromGitLab {
owner = "famedly";
diff --git a/pkgs/development/compilers/flutter/default.nix b/pkgs/development/compilers/flutter/default.nix
index 4529d2adc1a..02188335129 100644
--- a/pkgs/development/compilers/flutter/default.nix
+++ b/pkgs/development/compilers/flutter/default.nix
@@ -4,34 +4,40 @@ let
getPatches = dir:
let files = builtins.attrNames (builtins.readDir dir);
in map (f: dir + ("/" + f)) files;
- version = "3.0.4";
- channel = "stable";
- filename = "flutter_linux_${version}-${channel}.tar.xz";
-
- # Decouples flutter derivation from dart derivation,
- # use specific dart version to not need to bump dart derivation when bumping flutter.
- dartVersion = "2.17.5";
- dartSourceBase = "https://storage.googleapis.com/dart-archive/channels";
- dartForFlutter = dart.override {
- version = dartVersion;
- sources = {
- "${dartVersion}-x86_64-linux" = fetchurl {
- url = "${dartSourceBase}/stable/release/${dartVersion}/sdk/dartsdk-linux-x64-release.zip";
- sha256 = "sha256-AFJGeiPsjUZSO+DykmOIFETg2jIohg62tp3ghZrKJFk=";
+ flutterDrv = { version, pname, dartVersion, hash, dartHash, patches }: mkFlutter {
+ inherit version pname patches;
+ dart = dart.override {
+ version = dartVersion;
+ sources = {
+ "${dartVersion}-x86_64-linux" = fetchurl {
+ url = "https://storage.googleapis.com/dart-archive/channels/stable/release/${dartVersion}/sdk/dartsdk-linux-x64-release.zip";
+ sha256 = dartHash;
+ };
};
};
+ src = fetchurl {
+ url = "https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_${version}-stable.tar.xz";
+ sha256 = hash;
+ };
};
in
{
inherit mkFlutter;
- stable = mkFlutter rec {
- inherit version;
- dart = dartForFlutter;
+ stable = flutterDrv {
pname = "flutter";
- src = fetchurl {
- url = "https://storage.googleapis.com/flutter_infra_release/releases/${channel}/linux/${filename}";
- sha256 = "sha256-vh3QjLGFBN321DUET9XhYqSkILjEj+ZqAALu/mxY+go=";
- };
- patches = getPatches ./patches;
+ version = "3.3.3";
+ dartVersion = "2.18.2";
+ hash = "sha256-MTZeWQUp4/TcPzYIT6eqIKSPUPvn2Mp/thOQzNgpTXg=";
+ dartHash = "sha256-C3+YjecXLvSmJrLwi9H7TgD9Np0AArRWx3EdBrfQpTU";
+ patches = getPatches ./patches/flutter3;
+ };
+
+ v2 = flutterDrv {
+ pname = "flutter";
+ version = "2.10.5";
+ dartVersion = "2.16.2";
+ hash = "sha256-DTZwxlMUYk8NS1SaWUJolXjD+JnRW73Ps5CdRHDGnt0=";
+ dartHash = "sha256-egrYd7B4XhkBiHPIFE2zopxKtQ58GqlogAKA/UeiXnI=";
+ patches = getPatches ./patches/flutter2;
};
}
diff --git a/pkgs/development/compilers/flutter/flutter.nix b/pkgs/development/compilers/flutter/flutter.nix
index 28a78c3e306..f2c861356ab 100644
--- a/pkgs/development/compilers/flutter/flutter.nix
+++ b/pkgs/development/compilers/flutter/flutter.nix
@@ -65,7 +65,7 @@ let
popd
local revision="$(cd "$FLUTTER_ROOT"; git rev-parse HEAD)"
- ${dart}/bin/dart --snapshot="$SNAPSHOT_PATH" --packages="$FLUTTER_TOOLS_DIR/.packages" "$SCRIPT_PATH"
+ ${dart}/bin/dart --snapshot="$SNAPSHOT_PATH" --packages="$FLUTTER_TOOLS_DIR/.dart_tool/package_config.json" "$SCRIPT_PATH"
echo "$revision" > "$STAMP_PATH"
echo -n "${version}" > version
diff --git a/pkgs/development/compilers/flutter/patches/disable-auto-update.patch b/pkgs/development/compilers/flutter/patches/flutter2/disable-auto-update.patch
similarity index 100%
rename from pkgs/development/compilers/flutter/patches/disable-auto-update.patch
rename to pkgs/development/compilers/flutter/patches/flutter2/disable-auto-update.patch
diff --git a/pkgs/development/compilers/flutter/patches/flutter2/git-dir.patch b/pkgs/development/compilers/flutter/patches/flutter2/git-dir.patch
new file mode 100644
index 00000000000..0136ef93106
--- /dev/null
+++ b/pkgs/development/compilers/flutter/patches/flutter2/git-dir.patch
@@ -0,0 +1,80 @@
+diff --git a/dev/bots/prepare_package.dart b/dev/bots/prepare_package.dart
+index 468a91a954..5def6897ce 100644
+--- a/dev/bots/prepare_package.dart
++++ b/dev/bots/prepare_package.dart
+@@ -525,7 +525,7 @@ class ArchiveCreator {
+
+ Future<String> _runGit(List<String> args, {Directory? workingDirectory}) {
+ return _processRunner.runProcess(
+- <String>['git', ...args],
++ <String>['git', '--git-dir', '.git', ...args],
+ workingDirectory: workingDirectory ?? flutterRoot,
+ );
+ }
+diff --git a/packages/flutter_tools/lib/src/version.dart b/packages/flutter_tools/lib/src/version.dart
+index f2068a6ca2..99b161689e 100644
+--- a/packages/flutter_tools/lib/src/version.dart
++++ b/packages/flutter_tools/lib/src/version.dart
+@@ -106,7 +106,7 @@ class FlutterVersion {
+ String? channel = _channel;
+ if (channel == null) {
+ final String gitChannel = _runGit(
+- 'git rev-parse --abbrev-ref --symbolic @{u}',
++ 'git --git-dir .git rev-parse --abbrev-ref --symbolic @{u}',
+ globals.processUtils,
+ _workingDirectory,
+ );
+@@ -114,7 +114,7 @@ class FlutterVersion {
+ if (slash != -1) {
+ final String remote = gitChannel.substring(0, slash);
+ _repositoryUrl = _runGit(
+- 'git ls-remote --get-url $remote',
++ 'git --git-dir .git ls-remote --get-url $remote',
+ globals.processUtils,
+ _workingDirectory,
+ );
+@@ -326,7 +326,7 @@ class FlutterVersion {
+ /// the branch name will be returned as `'[user-branch]'`.
+ String getBranchName({ bool redactUnknownBranches = false }) {
+ _branch ??= () {
+- final String branch = _runGit('git rev-parse --abbrev-ref HEAD', globals.processUtils);
++ final String branch = _runGit('git --git-dir .git rev-parse --abbrev-ref HEAD', globals.processUtils);
+ return branch == 'HEAD' ? channel : branch;
+ }();
+ if (redactUnknownBranches || _branch!.isEmpty) {
+@@ -359,7 +359,7 @@ class FlutterVersion {
+ /// wrapper that does that.
+ @visibleForTesting
+ static List<String> gitLog(List<String> args) {
+- return <String>['git', '-c', 'log.showSignature=false', 'log'] + args;
++ return <String>['git', '-c', 'log.showSignature=false', '--git-dir', '.git', 'log'] + args;
+ }
+
+ /// Gets the release date of the latest available Flutter version.
+@@ -730,7 +730,7 @@ class GitTagVersion {
+
+ static GitTagVersion determine(ProcessUtils processUtils, {String? workingDirectory, bool fetchTags = false, String gitRef = 'HEAD'}) {
+ if (fetchTags) {
+- final String channel = _runGit('git rev-parse --abbrev-ref HEAD', processUtils, workingDirectory);
++ final String channel = _runGit('git --git-dir .git rev-parse --abbrev-ref HEAD', processUtils, workingDirectory);
+ if (channel == 'dev' || channel == 'beta' || channel == 'stable') {
+ globals.printTrace('Skipping request to fetchTags - on well known channel $channel.');
+ } else {
+@@ -739,7 +739,7 @@ class GitTagVersion {
+ }
+ // find all tags attached to the given [gitRef]
+ final List<String> tags = _runGit(
+- 'git tag --points-at $gitRef', processUtils, workingDirectory).trim().split('\n');
++ 'git --git-dir .git tag --points-at $gitRef', processUtils, workingDirectory).trim().split('\n');
+
+ // Check first for a stable tag
+ final RegExp stableTagPattern = RegExp(r'^\d+\.\d+\.\d+$');
+@@ -760,7 +760,7 @@ class GitTagVersion {
+ // recent tag and number of commits past.
+ return parse(
+ _runGit(
+- 'git describe --match *.*.* --long --tags $gitRef',
++ 'git --git-dir .git describe --match *.*.* --long --tags $gitRef',
+ processUtils,
+ workingDirectory,
+ )
diff --git a/pkgs/development/compilers/flutter/patches/flutter2/move-cache.patch b/pkgs/development/compilers/flutter/patches/flutter2/move-cache.patch
new file mode 100644
index 00000000000..a81d2def242
--- /dev/null
+++ b/pkgs/development/compilers/flutter/patches/flutter2/move-cache.patch
@@ -0,0 +1,72 @@
+diff --git a/packages/flutter_tools/lib/src/asset.dart b/packages/flutter_tools/lib/src/asset.dart
+index ed42baea29..12941f733a 100644
+--- a/packages/flutter_tools/lib/src/asset.dart
++++ b/packages/flutter_tools/lib/src/asset.dart
+@@ -11,11 +11,11 @@ import 'base/file_system.dart';
+ import 'base/logger.dart';
+ import 'base/platform.dart';
+ import 'build_info.dart';
+-import 'cache.dart';
+ import 'convert.dart';
+ import 'dart/package_map.dart';
+ import 'devfs.dart';
+ import 'flutter_manifest.dart';
++import 'globals.dart' as globals;
+ import 'license_collector.dart';
+ import 'project.dart';
+
+@@ -504,7 +504,7 @@ class ManifestAssetBundle implements AssetBundle {
+ }
+ final Uri entryUri = _fileSystem.path.toUri(asset);
+ result.add(_Asset(
+- baseDir: _fileSystem.path.join(Cache.flutterRoot!, 'bin', 'cache', 'artifacts', 'material_fonts'),
++ baseDir: _fileSystem.path.join(globals.fsUtils.homeDirPath!, '.cache', 'flutter', 'artifacts', 'material_fonts'),
+ relativeUri: Uri(path: entryUri.pathSegments.last),
+ entryUri: entryUri,
+ package: null,
+diff --git a/packages/flutter_tools/lib/src/cache.dart b/packages/flutter_tools/lib/src/cache.dart
+index defc86cc20..7fdf14d112 100644
+--- a/packages/flutter_tools/lib/src/cache.dart
++++ b/packages/flutter_tools/lib/src/cache.dart
+@@ -22,6 +22,7 @@ import 'base/user_messages.dart';
+ import 'build_info.dart';
+ import 'convert.dart';
+ import 'features.dart';
++import 'globals.dart' as globals;
+
+ const String kFlutterRootEnvironmentVariableName = 'FLUTTER_ROOT'; // should point to //flutter/ (root of flutter/flutter repo)
+ const String kFlutterEngineEnvironmentVariableName = 'FLUTTER_ENGINE'; // should point to //engine/src/ (root of flutter/engine repo)
+@@ -322,8 +323,13 @@ class Cache {
+ return;
+ }
+ assert(_lock == null);
++ final Directory dir = _fileSystem.directory(_fileSystem.path.join(globals.fsUtils.homeDirPath!, '.cache', 'flutter'));
++ if (!dir.existsSync()) {
++ dir.createSync(recursive: true);
++ globals.os.chmod(dir, '755');
++ }
+ final File lockFile =
+- _fileSystem.file(_fileSystem.path.join(flutterRoot!, 'bin', 'cache', 'lockfile'));
++ _fileSystem.file(_fileSystem.path.join(globals.fsUtils.homeDirPath!, '.cache', 'flutter', 'lockfile'));
+ try {
+ _lock = lockFile.openSync(mode: FileMode.write);
+ } on FileSystemException catch (e) {
+@@ -382,8 +388,7 @@ class Cache {
+
+ String get devToolsVersion {
+ if (_devToolsVersion == null) {
+- const String devToolsDirPath = 'dart-sdk/bin/resources/devtools';
+- final Directory devToolsDir = getCacheDir(devToolsDirPath, shouldCreate: false);
++ final Directory devToolsDir = _fileSystem.directory(_fileSystem.path.join(flutterRoot!, 'bin/cache/dart-sdk/bin/resources/devtools'));
+ if (!devToolsDir.existsSync()) {
+ throw Exception('Could not find directory at ${devToolsDir.path}');
+ }
+@@ -536,7 +541,7 @@ class Cache {
+ if (_rootOverride != null) {
+ return _fileSystem.directory(_fileSystem.path.join(_rootOverride!.path, 'bin', 'cache'));
+ } else {
+- return _fileSystem.directory(_fileSystem.path.join(flutterRoot!, 'bin', 'cache'));
++ return _fileSystem.directory(_fileSystem.path.join(globals.fsUtils.homeDirPath!, '.cache', 'flutter'));
+ }
+ }
+
diff --git a/pkgs/development/compilers/flutter/patches/flutter3/disable-auto-update.patch b/pkgs/development/compilers/flutter/patches/flutter3/disable-auto-update.patch
new file mode 100644
index 00000000000..21b676a2af3
--- /dev/null
+++ b/pkgs/development/compilers/flutter/patches/flutter3/disable-auto-update.patch
@@ -0,0 +1,36 @@
+diff --git a/bin/internal/shared.sh b/bin/internal/shared.sh
+index ab746724e9..1087983c87 100644
+--- a/bin/internal/shared.sh
++++ b/bin/internal/shared.sh
+@@ -215,8 +215,6 @@ function shared::execute() {
+ exit 1
+ fi
+
+- upgrade_flutter 7< "$PROG_NAME"
+-
+ BIN_NAME="$(basename "$PROG_NAME")"
+ case "$BIN_NAME" in
+ flutter*)
+diff --git a/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart b/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart
+index 738fef987d..03a152e64f 100644
+--- a/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart
++++ b/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart
+@@ -241,7 +241,6 @@ class FlutterCommandRunner extends CommandRunner<void> {
+ globals.flutterUsage.suppressAnalytics = true;
+ }
+
+- globals.flutterVersion.ensureVersionFile();
+ final bool machineFlag = topLevelResults['machine'] as bool? ?? false;
+ final bool ci = await globals.botDetector.isRunningOnBot;
+ final bool redirectedCompletion = !globals.stdio.hasTerminal &&
+@@ -250,10 +249,6 @@ class FlutterCommandRunner extends CommandRunner<void> {
+ final bool versionCheckFlag = topLevelResults['version-check'] as bool? ?? false;
+ final bool explicitVersionCheckPassed = topLevelResults.wasParsed('version-check') && versionCheckFlag;
+
+- if (topLevelResults.command?.name != 'upgrade' &&
+- (explicitVersionCheckPassed || (versionCheckFlag && !isMachine))) {
+- await globals.flutterVersion.checkFlutterVersionFreshness();
+- }
+
+ // See if the user specified a specific device.
+ globals.deviceManager?.specifiedDeviceId = topLevelResults['device-id'] as String?;
diff --git a/pkgs/development/compilers/flutter/patches/git-dir.patch b/pkgs/development/compilers/flutter/patches/flutter3/git-dir.patch
similarity index 86%
rename from pkgs/development/compilers/flutter/patches/git-dir.patch
rename to pkgs/development/compilers/flutter/patches/flutter3/git-dir.patch
index 0c736f945ea..42ad756f8ea 100644
--- a/pkgs/development/compilers/flutter/patches/git-dir.patch
+++ b/pkgs/development/compilers/flutter/patches/flutter3/git-dir.patch
@@ -1,8 +1,8 @@
diff --git a/dev/bots/prepare_package.dart b/dev/bots/prepare_package.dart
-index 468a91a954..5def6897ce 100644
+index 8e4cb81340..2c20940423 100644
--- a/dev/bots/prepare_package.dart
+++ b/dev/bots/prepare_package.dart
-@@ -525,7 +525,7 @@ class ArchiveCreator {
+@@ -526,7 +526,7 @@ class ArchiveCreator {
Future<String> _runGit(List<String> args, {Directory? workingDirectory}) {
return _processRunner.runProcess(
@@ -12,7 +12,7 @@ index 468a91a954..5def6897ce 100644
);
}
diff --git a/packages/flutter_tools/lib/src/commands/downgrade.dart b/packages/flutter_tools/lib/src/commands/downgrade.dart
-index bb0eb428a9..4a2a48bb5e 100644
+index 666c190067..b6c3761f6f 100644
--- a/packages/flutter_tools/lib/src/commands/downgrade.dart
+++ b/packages/flutter_tools/lib/src/commands/downgrade.dart
@@ -118,7 +118,7 @@ class DowngradeCommand extends FlutterCommand {
@@ -34,19 +34,19 @@ index bb0eb428a9..4a2a48bb5e 100644
if (parseResult.exitCode == 0) {
buffer.writeln('Channel "${getNameForChannel(channel)}" was previously on: ${parseResult.stdout}.');
diff --git a/packages/flutter_tools/lib/src/version.dart b/packages/flutter_tools/lib/src/version.dart
-index f2068a6ca2..99b161689e 100644
+index dc47f17057..8068e2d1f5 100644
--- a/packages/flutter_tools/lib/src/version.dart
+++ b/packages/flutter_tools/lib/src/version.dart
-@@ -106,7 +106,7 @@ class FlutterVersion {
+@@ -111,7 +111,7 @@ class FlutterVersion {
String? channel = _channel;
if (channel == null) {
final String gitChannel = _runGit(
-- 'git rev-parse --abbrev-ref --symbolic @{u}',
-+ 'git --git-dir .git rev-parse --abbrev-ref --symbolic @{u}',
+- 'git rev-parse --abbrev-ref --symbolic $kGitTrackingUpstream',
++ 'git --git-dir .git rev-parse --abbrev-ref --symbolic $kGitTrackingUpstream',
globals.processUtils,
_workingDirectory,
);
-@@ -114,7 +114,7 @@ class FlutterVersion {
+@@ -119,7 +119,7 @@ class FlutterVersion {
if (slash != -1) {
final String remote = gitChannel.substring(0, slash);
_repositoryUrl = _runGit(
@@ -55,7 +55,7 @@ index f2068a6ca2..99b161689e 100644
globals.processUtils,
_workingDirectory,
);
-@@ -326,7 +326,7 @@ class FlutterVersion {
+@@ -298,7 +298,7 @@ class FlutterVersion {
/// the branch name will be returned as `'[user-branch]'`.
String getBranchName({ bool redactUnknownBranches = false }) {
_branch ??= () {
@@ -64,7 +64,7 @@ index f2068a6ca2..99b161689e 100644
return branch == 'HEAD' ? channel : branch;
}();
if (redactUnknownBranches || _branch!.isEmpty) {
-@@ -359,7 +359,7 @@ class FlutterVersion {
+@@ -331,7 +331,7 @@ class FlutterVersion {
/// wrapper that does that.
@visibleForTesting
static List<String> gitLog(List<String> args) {
@@ -73,16 +73,16 @@ index f2068a6ca2..99b161689e 100644
}
/// Gets the release date of the latest available Flutter version.
-@@ -730,7 +730,7 @@ class GitTagVersion {
-
- static GitTagVersion determine(ProcessUtils processUtils, {String? workingDirectory, bool fetchTags = false, String gitRef = 'HEAD'}) {
+@@ -708,7 +708,7 @@ class GitTagVersion {
+ String gitRef = 'HEAD'
+ }) {
if (fetchTags) {
- final String channel = _runGit('git rev-parse --abbrev-ref HEAD', processUtils, workingDirectory);
+ final String channel = _runGit('git --git-dir .git rev-parse --abbrev-ref HEAD', processUtils, workingDirectory);
if (channel == 'dev' || channel == 'beta' || channel == 'stable') {
globals.printTrace('Skipping request to fetchTags - on well known channel $channel.');
} else {
-@@ -739,7 +739,7 @@ class GitTagVersion {
+@@ -718,7 +718,7 @@ class GitTagVersion {
}
// find all tags attached to the given [gitRef]
final List<String> tags = _runGit(
@@ -91,7 +91,7 @@ index f2068a6ca2..99b161689e 100644
// Check first for a stable tag
final RegExp stableTagPattern = RegExp(r'^\d+\.\d+\.\d+$');
-@@ -760,7 +760,7 @@ class GitTagVersion {
+@@ -739,7 +739,7 @@ class GitTagVersion {
// recent tag and number of commits past.
return parse(
_runGit(
diff --git a/pkgs/development/compilers/flutter/patches/move-cache.patch b/pkgs/development/compilers/flutter/patches/flutter3/move-cache.patch
similarity index 83%
rename from pkgs/development/compilers/flutter/patches/move-cache.patch
rename to pkgs/development/compilers/flutter/patches/flutter3/move-cache.patch
index 5cb7c71e9bd..008c5959e5b 100644
--- a/pkgs/development/compilers/flutter/patches/move-cache.patch
+++ b/pkgs/development/compilers/flutter/patches/flutter3/move-cache.patch
@@ -1,13 +1,9 @@
+diff --git a/packages/flutter_tools/lib/src/artifacts.dart b/packages/flutter_tools/lib/src/artifacts.dart
diff --git a/packages/flutter_tools/lib/src/asset.dart b/packages/flutter_tools/lib/src/asset.dart
-index ed42baea29..12941f733a 100644
+index 9dd7272fbe..642c8e48e4 100644
--- a/packages/flutter_tools/lib/src/asset.dart
+++ b/packages/flutter_tools/lib/src/asset.dart
-@@ -11,11 +11,11 @@ import 'base/file_system.dart';
- import 'base/logger.dart';
- import 'base/platform.dart';
- import 'build_info.dart';
--import 'cache.dart';
- import 'convert.dart';
+@@ -16,6 +16,7 @@ import 'convert.dart';
import 'dart/package_map.dart';
import 'devfs.dart';
import 'flutter_manifest.dart';
@@ -15,17 +11,18 @@ index ed42baea29..12941f733a 100644
import 'license_collector.dart';
import 'project.dart';
-@@ -504,7 +504,7 @@ class ManifestAssetBundle implements AssetBundle {
- }
+@@ -530,8 +531,7 @@ class ManifestAssetBundle implements AssetBundle {
final Uri entryUri = _fileSystem.path.toUri(asset);
result.add(_Asset(
-- baseDir: _fileSystem.path.join(Cache.flutterRoot!, 'bin', 'cache', 'artifacts', 'material_fonts'),
-+ baseDir: _fileSystem.path.join(globals.fsUtils.homeDirPath!, '.cache', 'flutter', 'artifacts', 'material_fonts'),
+ baseDir: _fileSystem.path.join(
+- Cache.flutterRoot!,
+- 'bin', 'cache', 'artifacts', 'material_fonts',
++ globals.fsUtils.homeDirPath!, '.cache', 'flutter', 'artifacts', 'material_fonts',
+ ),
relativeUri: Uri(path: entryUri.pathSegments.last),
entryUri: entryUri,
- package: null,
diff --git a/packages/flutter_tools/lib/src/cache.dart b/packages/flutter_tools/lib/src/cache.dart
-index defc86cc20..7fdf14d112 100644
+index dd80b1e46e..8e54517765 100644
--- a/packages/flutter_tools/lib/src/cache.dart
+++ b/packages/flutter_tools/lib/src/cache.dart
@@ -22,6 +22,7 @@ import 'base/user_messages.dart';
@@ -36,7 +33,7 @@ index defc86cc20..7fdf14d112 100644
const String kFlutterRootEnvironmentVariableName = 'FLUTTER_ROOT'; // should point to //flutter/ (root of flutter/flutter repo)
const String kFlutterEngineEnvironmentVariableName = 'FLUTTER_ENGINE'; // should point to //engine/src/ (root of flutter/engine repo)
-@@ -322,8 +323,13 @@ class Cache {
+@@ -318,8 +319,13 @@ class Cache {
return;
}
assert(_lock == null);
@@ -51,7 +48,7 @@ index defc86cc20..7fdf14d112 100644
try {
_lock = lockFile.openSync(mode: FileMode.write);
} on FileSystemException catch (e) {
-@@ -382,8 +388,7 @@ class Cache {
+@@ -378,8 +384,7 @@ class Cache {
String get devToolsVersion {
if (_devToolsVersion == null) {
@@ -61,7 +58,7 @@ index defc86cc20..7fdf14d112 100644
if (!devToolsDir.existsSync()) {
throw Exception('Could not find directory at ${devToolsDir.path}');
}
-@@ -536,7 +541,7 @@ class Cache {
+@@ -532,7 +537,7 @@ class Cache {
if (_rootOverride != null) {
return _fileSystem.directory(_fileSystem.path.join(_rootOverride!.path, 'bin', 'cache'));
} else {
@@ -70,8 +67,7 @@ index defc86cc20..7fdf14d112 100644
}
}
-diff --git a/packages/flutter_tools/lib/src/artifacts.dart b/packages/flutter_tools/lib/src/artifacts.dart
-index 2aac9686e8..32c4b98b88 100644
+index c539d67156..4e0a64f7a9 100644
--- a/packages/flutter_tools/lib/src/artifacts.dart
+++ b/packages/flutter_tools/lib/src/artifacts.dart
@@ -346,10 +346,10 @@ class CachedArtifacts implements Artifacts {
@@ -82,8 +78,8 @@ index 2aac9686e8..32c4b98b88 100644
+ final String path = _dartSdkPath(_fileSystem);
return _fileSystem.directory(path);
case HostArtifact.engineDartBinary:
-- final String path = _fileSystem.path.join(_dartSdkPath(_cache), 'bin', _hostArtifactToFileName(artifact, _platform.isWindows));
-+ final String path = _fileSystem.path.join(_dartSdkPath(_fileSystem), 'bin', _hostArtifactToFileName(artifact, _platform.isWindows));
+- final String path = _fileSystem.path.join(_dartSdkPath(_cache), 'bin', _hostArtifactToFileName(artifact, _platform));
++ final String path = _fileSystem.path.join(_dartSdkPath(_fileSystem), 'bin', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.flutterWebSdk:
final String path = _getFlutterWebSdkPath();
@@ -91,12 +87,12 @@ index 2aac9686e8..32c4b98b88 100644
case HostArtifact.dart2jsSnapshot:
case HostArtifact.dartdevcSnapshot:
case HostArtifact.kernelWorkerSnapshot:
-- final String path = _fileSystem.path.join(_dartSdkPath(_cache), 'bin', 'snapshots', _hostArtifactToFileName(artifact, _platform.isWindows));
-+ final String path = _fileSystem.path.join(_dartSdkPath(_fileSystem), 'bin', 'snapshots', _hostArtifactToFileName(artifact, _platform.isWindows));
+- final String path = _fileSystem.path.join(_dartSdkPath(_cache), 'bin', 'snapshots', _hostArtifactToFileName(artifact, _platform));
++ final String path = _fileSystem.path.join(_dartSdkPath(_fileSystem), 'bin', 'snapshots', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.iosDeploy:
- final String artifactFileName = _hostArtifactToFileName(artifact, _platform.isWindows);
-@@ -461,11 +461,13 @@ class CachedArtifacts implements Artifacts {
+ final String artifactFileName = _hostArtifactToFileName(artifact, _platform);
+@@ -465,11 +465,13 @@ class CachedArtifacts implements Artifacts {
String _getAndroidArtifactPath(Artifact artifact, TargetPlatform platform, BuildMode mode) {
final String engineDir = _getEngineArtifactsPath(platform, mode)!;
switch (artifact) {
@@ -125,8 +121,8 @@ index 2aac9686e8..32c4b98b88 100644
- case Artifact.frontendServerSnapshotForEngineDartSdk:
case Artifact.constFinder:
case Artifact.flutterMacOSFramework:
- case Artifact.flutterMacOSPodspec:
-@@ -594,14 +596,10 @@ class CachedArtifacts implements Artifacts {
+ case Artifact.flutterPatchedSdkPath:
+@@ -586,14 +588,10 @@ class CachedArtifacts implements Artifacts {
// For script snapshots any gen_snapshot binary will do. Returning gen_snapshot for
// android_arm in profile mode because it is available on all supported host platforms.
return _getAndroidArtifactPath(artifact, TargetPlatform.android_arm, BuildMode.profile);
@@ -142,27 +138,27 @@ index 2aac9686e8..32c4b98b88 100644
case Artifact.icuData:
final String engineArtifactsPath = _cache.getArtifactDirectory('engine').path;
final String platformDirName = _enginePlatformDirectoryName(platform);
-@@ -797,7 +795,7 @@ class CachedLocalEngineArtifacts implements LocalEngineArtifacts {
- final String path = _fileSystem.path.join(_hostEngineOutPath, 'dart-sdk', 'bin', 'snapshots', _hostArtifactToFileName(artifact, _platform.isWindows));
+@@ -776,7 +774,7 @@ class CachedLocalEngineArtifacts implements LocalEngineArtifacts {
+ final String path = _fileSystem.path.join(_hostEngineOutPath, 'dart-sdk', 'bin', 'snapshots', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.dartdevcSnapshot:
-- final String path = _fileSystem.path.join(_dartSdkPath(_cache), 'bin', 'snapshots', _hostArtifactToFileName(artifact, _platform.isWindows));
-+ final String path = _fileSystem.path.join(_dartSdkPath(_fileSystem), 'bin', 'snapshots', _hostArtifactToFileName(artifact, _platform.isWindows));
+- final String path = _fileSystem.path.join(_dartSdkPath(_cache), 'bin', 'snapshots', _hostArtifactToFileName(artifact, _platform));
++ final String path = _fileSystem.path.join(_dartSdkPath(_fileSystem), 'bin', 'snapshots', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.kernelWorkerSnapshot:
- final String path = _fileSystem.path.join(_hostEngineOutPath, 'dart-sdk', 'bin', 'snapshots', _hostArtifactToFileName(artifact, _platform.isWindows));
-@@ -922,9 +920,7 @@ class CachedLocalEngineArtifacts implements LocalEngineArtifacts {
- case Artifact.windowsUwpCppClientWrapper:
+ final String path = _fileSystem.path.join(_hostEngineOutPath, 'dart-sdk', 'bin', 'snapshots', _hostArtifactToFileName(artifact, _platform));
+@@ -901,9 +899,7 @@ class CachedLocalEngineArtifacts implements LocalEngineArtifacts {
+ case Artifact.windowsCppClientWrapper:
return _fileSystem.path.join(_hostEngineOutPath, artifactFileName);
case Artifact.frontendServerSnapshotForEngineDartSdk:
- return _fileSystem.path.join(
- _hostEngineOutPath, 'dart-sdk', 'bin', 'snapshots', artifactFileName,
- );
+ return _fileSystem.path.join(_hostEngineOutPath, 'gen', artifactFileName);
- case Artifact.uwptool:
- return _fileSystem.path.join(_hostEngineOutPath, artifactFileName);
}
-@@ -1034,8 +1030,8 @@ class OverrideArtifacts implements Artifacts {
+ }
+
+@@ -1011,8 +1007,8 @@ class OverrideArtifacts implements Artifacts {
}
/// Locate the Dart SDK.
@@ -174,12 +170,12 @@ index 2aac9686e8..32c4b98b88 100644
class _TestArtifacts implements Artifacts {
diff --git a/packages/flutter_tools/test/general.shard/artifacts_test.dart b/packages/flutter_tools/test/general.shard/artifacts_test.dart
-index d906511a15..adfdd4bb42 100644
+index aed3eb9285..81b8362648 100644
--- a/packages/flutter_tools/test/general.shard/artifacts_test.dart
+++ b/packages/flutter_tools/test/general.shard/artifacts_test.dart
-@@ -153,10 +153,6 @@ void main() {
- artifacts.getArtifactPath(Artifact.windowsUwpDesktopPath, platform: TargetPlatform.windows_uwp_x64, mode: BuildMode.release),
- fileSystem.path.join('root', 'bin', 'cache', 'artifacts', 'engine', 'windows-uwp-x64-release'),
+@@ -141,10 +141,6 @@ void main() {
+ artifacts.getArtifactPath(Artifact.flutterTester, platform: TargetPlatform.linux_arm64),
+ fileSystem.path.join('root', 'bin', 'cache', 'artifacts', 'engine', 'linux-arm64', 'flutter_tester'),
);
- expect(
- artifacts.getArtifactPath(Artifact.frontendServerSnapshotForEngineDartSdk),
@@ -188,7 +184,7 @@ index d906511a15..adfdd4bb42 100644
});
testWithoutContext('precompiled web artifact paths are correct', () {
-@@ -322,11 +318,6 @@ void main() {
+@@ -310,11 +306,6 @@ void main() {
artifacts.getHostArtifact(HostArtifact.engineDartSdkPath).path,
fileSystem.path.join('/out', 'host_debug_unopt', 'dart-sdk'),
);
@@ -197,6 +193,6 @@ index d906511a15..adfdd4bb42 100644
- fileSystem.path.join('/out', 'host_debug_unopt', 'dart-sdk', 'bin',
- 'snapshots', 'frontend_server.dart.snapshot')
- );
- });
-
- testWithoutContext('getEngineType', () {
+ expect(
+ artifacts.getHostArtifact(HostArtifact.impellerc).path,
+ fileSystem.path.join('/out', 'host_debug_unopt', 'impellerc'),
diff --git a/pkgs/os-specific/linux/firmware/firmware-updater/default.nix b/pkgs/os-specific/linux/firmware/firmware-updater/default.nix
index fb9d3a9a36c..cc906b763e8 100644
--- a/pkgs/os-specific/linux/firmware/firmware-updater/default.nix
+++ b/pkgs/os-specific/linux/firmware/firmware-updater/default.nix
@@ -1,13 +1,13 @@
{ lib
-, flutter
+, flutter2
, fetchFromGitHub
}:
-flutter.mkFlutterApp {
+flutter2.mkFlutterApp {
pname = "firmware-updater";
version = "unstable";
- vendorHash = "sha256-3wVA9BLCnMijC0gOmskz+Hv7NQIGu/jhBDbWjmoq1Tc=";
+ vendorHash = "sha256-7uOiebGBcX61oUyNCi1h9KldTRTrCfYaHUQSH4J5OoQ=";
src = fetchFromGitHub {
owner = "canonical";
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index 4f25d9b20d8..c282471c464 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -13448,6 +13448,7 @@ with pkgs;
flutterPackages =
recurseIntoAttrs (callPackage ../development/compilers/flutter { });
flutter = flutterPackages.stable;
+ flutter2 = flutterPackages.v2;
fnm = callPackage ../development/tools/fnm {
inherit (darwin.apple_sdk.frameworks) DiskArbitration Foundation Security;

View File

@@ -0,0 +1,66 @@
diff --git a/pkgs/applications/networking/instant-messengers/fluffychat/default.nix b/pkgs/applications/networking/instant-messengers/fluffychat/default.nix
index 22bbeb212f0..c07bd8e9fd4 100644
--- a/pkgs/applications/networking/instant-messengers/fluffychat/default.nix
+++ b/pkgs/applications/networking/instant-messengers/fluffychat/default.nix
@@ -4,13 +4,19 @@
, olm
, imagemagick
, makeDesktopItem
+, stdenv
}:
+let vendorHashes = {
+ x86_64-linux = "sha256-Gi0mfxaMtPI/TxrxnvzQvH9M8CtLADKJfYO2JnzAz+Y=";
+ aarch64-linux = "sha256-iq8bMSJoYbDNtR82QunrpQdPUv0nceUKXRqAwDvxCpE=";
+};
+in
flutter2.mkFlutterApp rec {
pname = "fluffychat";
version = "1.2.0";
- vendorHash = "sha256-1PDX023WXRmRe/b1L+6Du91BvGwYNp3YATqYSQdPrRY=";
+ vendorHash = vendorHashes."${stdenv.hostPlatform.system}" or (throw "unsupported system: ${stdenv.hostPlatform.system}");
src = fetchFromGitLab {
owner = "famedly";
diff --git a/pkgs/development/compilers/flutter/default.nix b/pkgs/development/compilers/flutter/default.nix
index 02188335129..c264565e50a 100644
--- a/pkgs/development/compilers/flutter/default.nix
+++ b/pkgs/development/compilers/flutter/default.nix
@@ -11,7 +11,11 @@ let
sources = {
"${dartVersion}-x86_64-linux" = fetchurl {
url = "https://storage.googleapis.com/dart-archive/channels/stable/release/${dartVersion}/sdk/dartsdk-linux-x64-release.zip";
- sha256 = dartHash;
+ sha256 = dartHash.x86_64-linux;
+ };
+ "${dartVersion}-aarch64-linux" = fetchurl {
+ url = "https://storage.googleapis.com/dart-archive/channels/stable/release/${dartVersion}/sdk/dartsdk-linux-arm64-release.zip";
+ sha256 = dartHash.aarch64-linux;
};
};
};
@@ -28,7 +32,10 @@ in
version = "3.3.3";
dartVersion = "2.18.2";
hash = "sha256-MTZeWQUp4/TcPzYIT6eqIKSPUPvn2Mp/thOQzNgpTXg=";
- dartHash = "sha256-C3+YjecXLvSmJrLwi9H7TgD9Np0AArRWx3EdBrfQpTU";
+ dartHash = {
+ x86_64-linux = "sha256-C3+YjecXLvSmJrLwi9H7TgD9Np0AArRWx3EdBrfQpTU";
+ aarch64-linux = "sha256-zyIK1i5/9P2C+sjzdArhFwpVO4P+It+/X50l+n9gekI=";
+ };
patches = getPatches ./patches/flutter3;
};
@@ -37,7 +44,10 @@ in
version = "2.10.5";
dartVersion = "2.16.2";
hash = "sha256-DTZwxlMUYk8NS1SaWUJolXjD+JnRW73Ps5CdRHDGnt0=";
- dartHash = "sha256-egrYd7B4XhkBiHPIFE2zopxKtQ58GqlogAKA/UeiXnI=";
+ dartHash = {
+ x86_64-linux = "sha256-egrYd7B4XhkBiHPIFE2zopxKtQ58GqlogAKA/UeiXnI=";
+ aarch64-linux = "sha256-vmerjXkUAUnI8FjK+62qLqgETmA+BLPEZXFxwYpI+KY=";
+ };
patches = getPatches ./patches/flutter2;
};
}

View File

@@ -1,34 +1,31 @@
fetchpatch: [ fetchpatch: [
# phosh: 0.21.1 -> 0.22.0 # Flutter: 3.0.4 -> 3.3.3, flutter.dart: 2.17.5 -> 2.18.2
(fetchpatch { # merged 2022/10/07
url = "https://github.com/NixOS/nixpkgs/pull/201881.diff"; # (fetchpatch {
sha256 = "sha256-7tV7F1gKTfMwNJ0evweD7p6RXOvOHQXXtuuBqnRGyCc="; # url = "https://github.com/NixOS/nixpkgs/pull/189338.diff";
}) # sha256 = "sha256-HRkOIBcOnSXyTKkYxnMgZou8MHU/5eNhxxARdUq9UWg=";
# # url = "https://git.uninsane.org/colin/nixpkgs/commit/889c3a8cbc91c0d10b34ab7825fa1f6d1d31668a.diff";
# # sha256 = "sha256-qVWLpNoW3HVSWRtXS1BcSusKOq0CAMfY0BVU9MxPm98=";
# })
#
# XXX this is a cherry-pick of all the commits in PR 189338 (as appears in tree).
# the diff yielded by Github is apparently not the same somehow (maybe because the branches being merged had diverged too much?)
./11-flutter-3.3.3-189338.patch
# phosh-mobile-settings: init at 0.21.1 # phosh-mobile-settings: init at 0.21.1
(fetchpatch { (fetchpatch {
# url = "https://git.uninsane.org/colin/nixpkgs/commit/0c1a7e8504291eb0076bbee3f8ebf693f4641112.diff"; url = "http://git.uninsane.org/colin/nixpkgs/commit/0c1a7e8504291eb0076bbee3f8ebf693f4641112.diff";
# sha256 = "sha256-OczjlQcG7sTM/V9Y9VL/qdwaWPKfjAJsh3czqqhRQig="; # url = "https://github.com/NixOS/nixpkgs/pull/193845.diff";
url = "https://github.com/NixOS/nixpkgs/pull/193845.diff"; sha256 = "sha256-OczjlQcG7sTM/V9Y9VL/qdwaWPKfjAJsh3czqqhRQig=";
sha256 = "sha256-/9c8hUF7DO54f8/6oSRzxLOwMdts5UPa4pfXsdBa2pM=";
}) })
# librewolf: build with `MOZ_REQUIRE_SIGNING=false` # kaiteki: init at 2022-09-03
(fetchpatch { (fetchpatch {
url = "https://github.com/NixOS/nixpkgs/pull/199134.diff"; url = "https://git.uninsane.org/colin/nixpkgs/commit/e2c7f5f4870fcb0e5405e9001b39a64c516852d4.diff";
# url = "https://git.uninsane.org/colin/nixpkgs/commit/99b82e07fee4d194520d6e8d51bc45c80a4d3c7e.diff"; # url = "https://github.com/NixOS/nixpkgs/pull/193169.diff";
sha256 = "sha256-Ne4hyHQDwBHUlWo8Z3QyRdmEv1rYGOjFGxSfOAcLUvQ="; sha256 = "sha256-UWnfS+stVpUZ3Sfaym9XtVBlwvHWJVMaW7cYIcf3M5Q=";
}) })
# # kaiteki: init at 2022-09-03
# vendorHash changes too frequently (might not be reproducible).
# using local package defn until stabilized
# (fetchpatch {
# url = "https://git.uninsane.org/colin/nixpkgs/commit/e2c7f5f4870fcb0e5405e9001b39a64c516852d4.diff";
# # url = "https://github.com/NixOS/nixpkgs/pull/193169.diff";
# sha256 = "sha256-UWnfS+stVpUZ3Sfaym9XtVBlwvHWJVMaW7cYIcf3M5Q=";
# })
# Fix mk flutter app # Fix mk flutter app
# closed (not merged). updates fluffychat 1.2.0 -> 1.6.1, but unstable hashing # closed (not merged). updates fluffychat 1.2.0 -> 1.6.1, but unstable hashing
# (fetchpatch { # (fetchpatch {
@@ -41,8 +38,10 @@ fetchpatch: [
# (it's a dupe of https://github.com/NixOS/nixpkgs/pull/112677 ) # (it's a dupe of https://github.com/NixOS/nixpkgs/pull/112677 )
./02-rpi4-uboot.patch ./02-rpi4-uboot.patch
# ./07-duplicity-rich-url.patch # TODO: upstream
./07-duplicity-rich-url.patch
# enable aarch64 support for flutter's dart package # enable aarch64 support for flutter's dart package
# ./10-flutter-arm64.patch # ./10-flutter-arm64.patch
./12-flutter-arm64-2.patch
] ]

View File

@@ -1,67 +0,0 @@
{ stdenv
, fetchFromGitHub
, fetchFromGitea
, gnused
, jq
, mkYarnModules
, zip
}:
let
pname = "browserpass-extension";
version = "3.7.2-20221121";
# src = fetchFromGitHub {
# owner = "browserpass";
# repo = "browserpass-extension";
# # rev = version;
# rev = "21f3431d09e1d7ffd33e0b9fc5d2965b7bd93a1a";
# sha256 = "sha256-XIgbaQSAXx7L1e/9rzN7oBQy9U3HWJHOX2auuvgdvbc=";
# };
src = fetchFromGitea {
domain = "git.uninsane.org";
owner = "colin";
repo = "browserpass-extension";
# hack in sops support
rev = "e3bf558ff63d002d3c15f2ce966071f04fada306";
sha256 = "sha256-dSRZ2ToEOPhzHNvlG8qdewa7689gT8cNB7nXkN3/Avo=";
};
browserpass-extension-yarn-modules = mkYarnModules {
inherit pname version;
packageJSON = "${src}/src/package.json";
yarnLock = "${src}/src/yarn.lock";
};
extid = "browserpass@maximbaz.com";
in stdenv.mkDerivation {
inherit pname version src;
patchPhase = ''
# dependencies are built separately: skip the yarn install
${gnused}/bin/sed -i /yarn\ install/d src/Makefile
'';
preBuild = ''
ln -s ${browserpass-extension-yarn-modules}/node_modules src/node_modules
'';
installPhase = ''
BASE=$out/share/mozilla/extensions/\{ec8030f7-c20a-464f-9b0e-13a3a9e97384\}
mkdir -p $BASE
pushd firefox
# firefox requires addons to have an id field when sideloading:
# - <https://extensionworkshop.com/documentation/publish/distribute-sideloading/>
cat manifest.json \
| ${jq}/bin/jq '. + { applications: {gecko: {id: "${extid}" }}, browser_specific_settings: {gecko: {id: "${extid}"}} }' \
> manifest.patched.json
mv manifest{.patched,}.json
${zip}/bin/zip -r $BASE/browserpass@maximbaz.com.xpi ./*
popd
'';
passthru = {
inherit extid;
};
}

View File

@@ -1,48 +0,0 @@
{ pkgs
, bash
, fetchFromGitea
, gnused
, lib
, sane-scripts
, sops
, stdenv
, substituteAll
}:
let
sane-browserpass-gpg = stdenv.mkDerivation {
pname = "sane-browserpass-gpg";
version = "0.1.0";
src = ./.;
inherit bash gnused sops;
sane_scripts = sane-scripts;
installPhase = ''
mkdir -p $out/bin
substituteAll ${./sops-gpg-adapter} $out/bin/gpg
chmod +x $out/bin/gpg
ln -s $out/bin/gpg $out/bin/gpg2
'';
};
in
(pkgs.browserpass.overrideAttrs (upstream: {
src = fetchFromGitea {
domain = "git.uninsane.org";
owner = "colin";
repo = "browserpass-native";
# don't forcibly append '.gpg'
rev = "85bdb08379c03297c1236f66e8764160c922d397";
hash = "sha256-SEfihU+GreWhYfLVr7tTnMCo6Iq20a78F8iVbycOQUQ=";
};
installPhase = ''
make install
wrapProgram $out/bin/browserpass \
--prefix PATH : ${lib.makeBinPath [ sane-browserpass-gpg ]}
# This path is used by our firefox wrapper for finding native messaging hosts
mkdir -p $out/lib/mozilla/native-messaging-hosts
ln -s $out/lib/browserpass/hosts/firefox/*.json $out/lib/mozilla/native-messaging-hosts
'';
}))

View File

@@ -1,19 +0,0 @@
#! @bash@/bin/sh
# browserpass "validates" the gpg binary by invoking it with --version
if [ "$1" = "--version" ]
then
echo "sane-browserpass-gpg @version@";
exit 0
fi
# ensure the secret store is unlocked
@sane_scripts@/bin/sane-secrets-unlock
# using exec here forwards our stdin
# browserpass parses the response in
# <browserpass-extension/src/background.js#parseFields>
# it cares about `key:value`, and ignores whatever doesn't fit that (or has an unknown key)
# browserpass understands the `totp` field to hold either secret tokens, or full URLs.
# i use totp-b32 for the base-32-encoded secrets. renaming that field works OOTB.
exec @sops@/bin/sops --input-type yaml -d --output-type yaml --config /dev/null /dev/stdin | @gnused@/bin/sed s/\^totp-b32:/totp:/

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