Compare commits

..

1 Commits

Author SHA1 Message Date
c9d08c72e7 WIP: matrix: add signal bridge 2023-01-16 06:20:17 +00:00
247 changed files with 4524 additions and 7695 deletions

126
flake.lock generated
View File

@@ -2,11 +2,11 @@
"nodes": {
"flake-utils": {
"locked": {
"lastModified": 1678901627,
"narHash": "sha256-U02riOqrKKzwjsxc/400XnElV+UtPUQWpANPlyazjH0=",
"lastModified": 1659877975,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "93a2b84fc4b70d9e089d029deacc3583435c2ed6",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
"type": "github"
},
"original": {
@@ -15,14 +15,35 @@
"type": "github"
}
},
"home-manager": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1667907331,
"narHash": "sha256-bHkAwkYlBjkupPUFcQjimNS8gxWSWjOTevEuwdnp5m0=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "6639e3a837fc5deb6f99554072789724997bc8e5",
"type": "github"
},
"original": {
"owner": "nix-community",
"ref": "release-22.05",
"repo": "home-manager",
"type": "github"
}
},
"mobile-nixos": {
"flake": false,
"locked": {
"lastModified": 1679516998,
"narHash": "sha256-w4baQlS84X8Lf0E5RN0nGkx03luDuV1X0+jWMAXm6fs=",
"lastModified": 1670131242,
"narHash": "sha256-T/o1/3gffr010fsqgNshs1NJJjsnUYvQnUZgm6hilsY=",
"owner": "nixos",
"repo": "mobile-nixos",
"rev": "7a6e97e3af73c4cca87e12c83abcb4913dac7dbc",
"rev": "5ee45cc1f8e43f4af14ee17ccef9156b0db8cd77",
"type": "github"
},
"original": {
@@ -31,46 +52,47 @@
"type": "github"
}
},
"nix-serve": {
"inputs": {
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1678202930,
"narHash": "sha256-SF82/tTnagdazlETJLzXD9kjZ6lyk38agdLbmMx1UZE=",
"owner": "edolstra",
"repo": "nix-serve",
"rev": "3b6d30016d910a43e0e16f94170440a3e0b8fa8d",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "nix-serve",
"type": "github"
}
},
"nixpkgs": {
"inputs": {
"nixpkgs": [
"nixpkgs-unpatched"
],
"patches": []
},
"locked": {
"lastModified": 1606086654,
"narHash": "sha256-VFl+3eGIMqNp7cyOMJ6TjM/+UcsLKtodKoYexrlTJMI=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "19db3e5ea2777daa874563b5986288151f502e27",
"type": "github"
"lastModified": 1,
"narHash": "sha256-d3XSehPFkNwvwlOYy7gch0NLxOgdXuV7j5r/Qsn7kHc=",
"path": "/nix/store/wq6rmmnd7yhw9w44k54w4x5v63ah1psr-source/nixpatches",
"type": "path"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-20.09",
"type": "indirect"
"path": "/nix/store/wq6rmmnd7yhw9w44k54w4x5v63ah1psr-source/nixpatches",
"type": "path"
}
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1680390120,
"narHash": "sha256-RyDJcG/7mfimadlo8vO0QjW22mvYH1+cCqMuigUntr8=",
"lastModified": 1673704454,
"narHash": "sha256-5Wdj1MgdOgn3+dMFIBtg+IAYZApjF8JzwLWDPieg0C4=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "a83ed85c14fcf242653df6f4b0974b7e1c73c6c6",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-22.11",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-stable_2": {
"locked": {
"lastModified": 1673740915,
"narHash": "sha256-MMH8zONfqahgHly3K8/A++X34800rajA/XgZ2DzNL/M=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "c1e2efaca8d8a3db6a36f652765d6c6ba7bb8fae",
"rev": "7c65528c3f8462b902e09d1ccca23bb9034665c2",
"type": "github"
},
"original": {
@@ -82,24 +104,26 @@
},
"nixpkgs-unpatched": {
"locked": {
"lastModified": 1680415272,
"narHash": "sha256-S2J9n+sSeAAdXWHrz/s9pyS5fhbQilfNqYrs6RCUyN8=",
"lastModified": 1673631141,
"narHash": "sha256-AprpYQ5JvLS4wQG/ghm2UriZ9QZXvAwh1HlgA/6ZEVQ=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "66f60deb8aa348ca81d60d0639ae420c667ff92a",
"rev": "befc83905c965adfd33e5cae49acb0351f6e0404",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "staging-next",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"home-manager": "home-manager",
"mobile-nixos": "mobile-nixos",
"nix-serve": "nix-serve",
"nixpkgs": "nixpkgs",
"nixpkgs-stable": "nixpkgs-stable",
"nixpkgs-unpatched": "nixpkgs-unpatched",
"sops-nix": "sops-nix",
"uninsane-dot-org": "uninsane-dot-org"
@@ -108,16 +132,16 @@
"sops-nix": {
"inputs": {
"nixpkgs": [
"nixpkgs-unpatched"
"nixpkgs"
],
"nixpkgs-stable": "nixpkgs-stable"
"nixpkgs-stable": "nixpkgs-stable_2"
},
"locked": {
"lastModified": 1680404136,
"narHash": "sha256-06D8HJmRv4DdpEQGblMhx2Vm81SBWM61XBBIx7QQfo0=",
"lastModified": 1673752321,
"narHash": "sha256-EFfXY1ZHJq4FNaNQA9x0djtu/jiOhBbT0Xi+BT06cJw=",
"owner": "Mic92",
"repo": "sops-nix",
"rev": "b93eb910f768f9788737bfed596a598557e5625d",
"rev": "e18eefd2b133a58309475298052c341c08470717",
"type": "github"
},
"original": {
@@ -130,15 +154,15 @@
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": [
"nixpkgs-unpatched"
"nixpkgs"
]
},
"locked": {
"lastModified": 1680086409,
"narHash": "sha256-Q2QcVgKvTj/LLuZX9dP8ImySWD5sTn8DDI5+EggRn2c=",
"lastModified": 1666870107,
"narHash": "sha256-b9eXZxSwhzdJI5uQgfrMhu4SY2POrPkinUg7F5gQVYo=",
"ref": "refs/heads/master",
"rev": "068f176a64f0e26dc8c1f0eccf28cbd05be4909b",
"revCount": 182,
"rev": "80c6ec95bd430e29d231cf745f19279bb76fb382",
"revCount": 164,
"type": "git",
"url": "https://git.uninsane.org/colin/uninsane"
},

199
flake.nix
View File

@@ -12,11 +12,6 @@
# - Flake RFC: <https://github.com/tweag/rfcs/blob/flakes/rfcs/0049-flakes.md>
# - Discussion: <https://github.com/NixOS/rfcs/pull/49>
# - <https://serokell.io/blog/practical-nix-flakes>
#
#
# COMMON OPERATIONS:
# - update a specific flake input:
# - `nix flake lock --update-input nixpkgs`
{
# XXX: use the `github:` scheme instead of the more readable git+https: because it's *way* more efficient
@@ -24,62 +19,48 @@
# but `inputs` is required to be a strict attrset: not an expression.
inputs = {
# <https://github.com/nixos/nixpkgs/tree/nixos-22.11>
# nixpkgs-stable.url = "github:nixos/nixpkgs?ref=nixos-22.11";
nixpkgs-stable.url = "github:nixos/nixpkgs?ref=nixos-22.11";
# <https://github.com/nixos/nixpkgs/tree/nixos-unstable>
# nixpkgs-unpatched.url = "github:nixos/nixpkgs?ref=nixos-unstable";
nixpkgs-unpatched.url = "github:nixos/nixpkgs?ref=staging-next";
# nixpkgs = {
# url = "./nixpatches";
# inputs.nixpkgs.follows = "nixpkgs-unpatched";
# };
nixpkgs-unpatched.url = "github:nixos/nixpkgs?ref=nixos-unstable";
nixpkgs = {
url = "./nixpatches";
inputs.nixpkgs.follows = "nixpkgs-unpatched";
# TODO: remove this dependency injection: it's from when we used url = path:...
inputs.patches.follows = "";
};
mobile-nixos = {
# <https://github.com/nixos/mobile-nixos>
url = "github:nixos/mobile-nixos";
flake = false;
};
home-manager = {
# <https://github.com/nix-community/home-manager/tree/release-22.05>
url = "github:nix-community/home-manager?ref=release-22.05";
inputs.nixpkgs.follows = "nixpkgs";
};
sops-nix = {
# <https://github.com/Mic92/sops-nix>
url = "github:Mic92/sops-nix";
# inputs.nixpkgs.follows = "nixpkgs";
inputs.nixpkgs.follows = "nixpkgs-unpatched";
inputs.nixpkgs.follows = "nixpkgs";
};
uninsane-dot-org = {
url = "git+https://git.uninsane.org/colin/uninsane";
# inputs.nixpkgs.follows = "nixpkgs";
inputs.nixpkgs.follows = "nixpkgs-unpatched";
};
nix-serve = {
# <https://github.com/edolstra/nix-serve>
url = "github:edolstra/nix-serve";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = {
self,
nixpkgs,
nixpkgs-stable,
nixpkgs-unpatched,
mobile-nixos,
home-manager,
sops-nix,
uninsane-dot-org,
nix-serve,
...
}@inputs:
uninsane-dot-org
}:
let
inherit (builtins) attrNames elem listToAttrs map mapAttrs;
mapAttrs' = f: set:
listToAttrs (map (attr: f attr set.${attr}) (attrNames set));
# mapAttrs but without the `name` argument
mapAttrValues = f: mapAttrs (_: f);
# rather than apply our nixpkgs patches as a flake input, do that here instead.
# this (temporarily?) resolves the bad UX wherein a subflake residing in the same git
# repo as the main flake causes the main flake to have an unstable hash.
nixpkgs = (import ./nixpatches/flake.nix).outputs {
self = nixpkgs;
nixpkgs = nixpkgs-unpatched;
};
nixpkgsCompiledBy = local: nixpkgs.legacyPackages."${local}";
evalHost = { name, local, target }:
@@ -92,58 +73,35 @@
nixosSystem = import ((nixpkgsCompiledBy target).path + "/nixos/lib/eval-config.nix");
in
(nixosSystem {
# we use pkgs built for and *by* the target, i.e. emulation, by default.
# cross compilation only happens on explicit access to `pkgs.cross`
system = target;
modules = [
(import ./hosts/instantiate.nix { localSystem = local; hostName = name; })
self.nixosModules.default
self.nixosModules.passthru
{
nixpkgs.overlays = [
self.overlays.disable-flakey-tests
self.overlays.default
self.overlays.passthru
self.overlays.pins
self.overlays.pkgs
# self.overlays.optimizations
];
nixpkgs.hostPlatform = target;
# nixpkgs.buildPlatform = local; # set by instantiate.nix instead
# nixpkgs.config.replaceStdenv = { pkgs }: pkgs.ccacheStdenv;
}
];
});
in {
nixosConfigurations =
let
hosts = {
servo = { name = "servo"; local = "x86_64-linux"; target = "x86_64-linux"; };
desko = { name = "desko"; local = "x86_64-linux"; target = "x86_64-linux"; };
lappy = { name = "lappy"; local = "x86_64-linux"; target = "x86_64-linux"; };
moby = { name = "moby"; local = "x86_64-linux"; target = "aarch64-linux"; };
rescue = { name = "rescue"; local = "x86_64-linux"; target = "x86_64-linux"; };
};
# cross-compiled builds: instead of emulating the host, build using a cross-compiler.
# - these are faster to *build* than the emulated variants (useful when tweaking packages),
# - but fewer of their packages can be found in upstream caches.
cross = mapAttrValues evalHost hosts;
emulated = mapAttrValues
({name, local, target}: evalHost {
inherit name target;
local = null;
})
hosts;
prefixAttrs = prefix: attrs: mapAttrs'
(name: value: {
name = prefix + name;
inherit value;
})
attrs;
in
(prefixAttrs "cross-" cross) //
(prefixAttrs "emulated-" emulated) // {
# prefer native builds for these machines:
inherit (emulated) servo desko lappy rescue;
# prefer cross-compiled builds for these machines:
inherit (cross) moby;
};
nixosConfigurations = {
servo = evalHost { name = "servo"; local = "x86_64-linux"; target = "x86_64-linux"; };
desko = evalHost { name = "desko"; local = "x86_64-linux"; target = "x86_64-linux"; };
lappy = evalHost { name = "lappy"; local = "x86_64-linux"; target = "x86_64-linux"; };
moby = evalHost { name = "moby"; local = "aarch64-linux"; target = "aarch64-linux"; };
# 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
# v.s. emulate differ.
# so deploying foo-cross and then foo incurs some rebuilding.
moby-cross = evalHost { name = "moby"; local = "x86_64-linux"; target = "aarch64-linux"; };
rescue = evalHost { name = "rescue"; local = "x86_64-linux"; target = "x86_64-linux"; };
};
# unofficial output
# this produces a EFI-bootable .img file (GPT with a /boot partition and a system (/ or /nix) partition).
@@ -159,42 +117,22 @@
# - if fs wasn't resized automatically, then `sudo btrfs filesystem resize max /`
# - checkout this flake into /etc/nixos AND UPDATE THE FS UUIDS.
# - `nixos-rebuild --flake './#<host>' switch`
imgs = mapAttrValues (host: host.config.system.build.img) self.nixosConfigurations;
imgs = builtins.mapAttrs (_: host-dfn: host-dfn.config.system.build.img) self.nixosConfigurations;
# unofficial output
host-pkgs = mapAttrValues (host: host.config.system.build.pkgs) self.nixosConfigurations;
overlays = {
# N.B.: `nix flake check` requires every overlay to take `final: prev:` at defn site,
# hence the weird redundancy.
default = final: prev: self.overlays.pkgs final prev;
disable-flakey-tests = final: prev: import ./overlays/disable-flakey-tests.nix final prev;
pkgs = final: prev: import ./overlays/pkgs.nix final prev;
pins = final: prev: import ./overlays/pins.nix final prev;
optimizations = final: prev: import ./overlays/optimizations.nix final prev;
passthru = final: prev:
overlays = rec {
default = pkgs;
pkgs = import ./overlays/pkgs.nix;
pins = import ./overlays/pins.nix; # TODO: move to `nixpatches/` input
passthru =
let
stable =
if inputs ? "nixpkgs-stable" then (
final': prev': {
stable = inputs.nixpkgs-stable.legacyPackages."${prev'.stdenv.hostPlatform.system}";
}
) else (final': prev': {});
stable = next: prev: {
stable = nixpkgs-stable.legacyPackages."${prev.stdenv.hostPlatform.system}";
};
mobile = (import "${mobile-nixos}/overlay/overlay.nix");
uninsane = uninsane-dot-org.overlay;
# nix-serve' = nix-serve.overlay;
nix-serve' = next: prev: {
# XXX(2023/03/02): upstream isn't compatible with modern `nix`. probably the perl bindings.
# - we use the package built against `nixpkgs` specified in its flake rather than use its overlay,
# to get around this.
inherit (nix-serve.packages."${next.system}") nix-serve;
};
in
(stable final prev)
// (mobile final prev)
// (uninsane final prev)
// (nix-serve' final prev)
;
next: prev:
(stable next prev) // (mobile next prev) // (uninsane next prev);
};
nixosModules = rec {
@@ -202,6 +140,7 @@
sane = import ./modules;
passthru = { ... }: {
imports = [
home-manager.nixosModule
sops-nix.nixosModules.sops
];
};
@@ -218,33 +157,14 @@
aarch64-linux = allPkgsFor "aarch64-linux";
};
# extract only our own packages from the full set.
# because of `nix flake check`, we flatten the package set and only surface x86_64-linux packages.
packages = mapAttrs
(system: allPkgs:
allPkgs.lib.filterAttrs (name: pkg:
# keep only packages which will pass `nix flake check`, i.e. keep only:
# - derivations (not package sets)
# - packages that build for the given platform
(! elem name [ "feeds" "pythonPackagesExtensions" ])
&& (allPkgs.lib.meta.availableOn allPkgs.stdenv.hostPlatform pkg)
)
(allPkgs.sane // {
inherit (allPkgs) uninsane-dot-org;
})
)
# self.legacyPackages;
{ inherit (self.legacyPackages) x86_64-linux; }
;
# extract only our own packages from the full set
packages = builtins.mapAttrs
(_: full: full.sane // { inherit (full) sane uninsane-dot-org; })
self.legacyPackages;
apps."x86_64-linux" =
let
pkgs = self.legacyPackages."x86_64-linux";
deployScript = action: pkgs.writeShellScript "deploy-moby" ''
nixos-rebuild --flake '.#cross-moby' build
sudo nix sign-paths -r -k /run/secrets/nix_serve_privkey $(readlink ./result)
nixos-rebuild --flake '.#cross-moby' ${action} --target-host colin@moby --use-remote-sudo
'';
in {
update-feeds = {
type = "app";
@@ -252,21 +172,9 @@
};
init-feed = {
# use like `nix run '.#init-feed' uninsane.org`
type = "app";
program = "${pkgs.feeds.passthru.initFeedScript}";
};
deploy-moby-test = {
# `nix run '.#deploy-moby-test'`
type = "app";
program = ''${deployScript "test"}'';
};
deploy-moby-switch = {
# `nix run '.#deploy-moby-switch'`
type = "app";
program = ''${deployScript "switch"}'';
};
};
templates = {
@@ -279,6 +187,9 @@
description = "python environment for data processing";
};
};
# unofficial output; used by inputs.nixpatches
nixpatches = import ./nixpatches/list.nix;
};
}

View File

@@ -1,42 +0,0 @@
{ ... }:
{
sops.secrets."ddns_afraid" = {
sopsFile = ../../../secrets/servo.yaml;
};
sops.secrets."ddns_he" = {
sopsFile = ../../../secrets/servo.yaml;
};
sops.secrets."dovecot_passwd" = {
sopsFile = ../../../secrets/servo.yaml;
};
sops.secrets."duplicity_passphrase" = {
sopsFile = ../../../secrets/servo.yaml;
};
sops.secrets."freshrss_passwd" = {
sopsFile = ../../../secrets/servo.yaml;
};
sops.secrets."matrix_synapse_secrets" = {
sopsFile = ../../../secrets/servo.yaml;
};
sops.secrets."mautrix_signal_env" = {
sopsFile = ../../../secrets/servo/mautrix_signal_env.bin;
format = "binary";
};
sops.secrets."mediawiki_pw" = {
sopsFile = ../../../secrets/servo.yaml;
};
sops.secrets."pleroma_secrets" = {
sopsFile = ../../../secrets/servo.yaml;
};
sops.secrets."wg_ovpns_privkey" = {
sopsFile = ../../../secrets/servo.yaml;
};
}

View File

@@ -1,114 +0,0 @@
# configuration options (today i don't store my config in nix):
#
# - jellyfin-web can be statically configured (result/share/jellyfin-web/config.json)
# - <https://jellyfin.org/docs/general/clients/web-config>
# - configure server list, plugins, "menuLinks", colors
#
# - jellfyin server is configured in /var/lib/jellfin/
# - root/default/<LibraryType>/
# - <LibraryName>.mblink: contains the directory name where this library lives
# - options.xml: contains preferences which were defined in the web UI during import
# - e.g. `EnablePhotos`, `EnableChapterImageExtraction`, etc.
# - config/encoding.xml: transcoder settings
# - config/system.xml: misc preferences like log file duration, audiobook resume settings, etc.
# - data/jellyfin.db: maybe account definitions? internal state?
{ config, lib, ... }:
{
# identical to:
# services.jellyfin.openFirewall = true;
networking.firewall.allowedUDPPorts = [
# https://jellyfin.org/docs/general/networking/index.html
1900 # UPnP service discovery
7359 # Jellyfin-specific (?) client discovery
];
networking.firewall.allowedTCPPorts = [
8096 # HTTP (for the LAN)
8920 # HTTPS (for the LAN)
];
sane.persist.sys.plaintext = [
{ user = "jellyfin"; group = "jellyfin"; mode = "0700"; directory = "/var/lib/jellyfin"; }
];
sane.fs."/var/lib/jellyfin/config/logging.json" = {
# "Emby.Dlna" logging: <https://jellyfin.org/docs/general/networking/dlna>
symlink.text = ''
{
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Warning",
"Emby.Dlna": "Debug",
"Emby.Dlna.Eventing": "Debug"
}
},
"WriteTo": [
{
"Name": "Console",
"Args": {
"outputTemplate": "[{Timestamp:HH:mm:ss}] [{Level:u3}] [{ThreadId}] {SourceContext}: {Message:lj}{NewLine}{Exception}"
}
}
],
"Enrich": [ "FromLogContext", "WithThreadId" ]
}
}
'';
wantedBeforeBy = [ "jellyfin.service" ];
};
# Jellyfin multimedia server
# this is mostly taken from the official jellfin.org docs
services.nginx.virtualHosts."jelly.uninsane.org" = {
addSSL = true;
enableACME = true;
# inherit kTLS;
locations."/" = {
proxyPass = "http://127.0.0.1:8096";
extraConfig = ''
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Forwarded-Host $http_host;
# Disable buffering when the nginx proxy gets very resource heavy upon streaming
proxy_buffering off;
'';
};
# locations."/web/" = {
# proxyPass = "http://127.0.0.1:8096/web/index.html";
# extraConfig = ''
# proxy_set_header Host $host;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header X-Forwarded-Proto $scheme;
# proxy_set_header X-Forwarded-Protocol $scheme;
# proxy_set_header X-Forwarded-Host $http_host;
# '';
# };
locations."/socket" = {
proxyPass = "http://127.0.0.1:8096";
extraConfig = ''
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Forwarded-Host $http_host;
'';
};
};
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."jelly" = "native";
services.jellyfin.enable = true;
}

View File

@@ -1,37 +0,0 @@
# config options:
# - <https://github.com/mautrix/signal/blob/master/mautrix_signal/example-config.yaml>
{ config, pkgs, ... }:
{
sane.persist.sys.plaintext = [
{ user = "mautrix-signal"; group = "mautrix-signal"; directory = "/var/lib/mautrix-signal"; }
{ user = "signald"; group = "signald"; directory = "/var/lib/signald"; }
];
# allow synapse to read the registration file
users.users.matrix-synapse.extraGroups = [ "mautrix-signal" ];
services.signald.enable = true;
services.mautrix-signal.enable = true;
services.mautrix-signal.environmentFile =
config.sops.secrets.mautrix_signal_env.path;
services.mautrix-signal.settings.signal.socket_path = "/run/signald/signald.sock";
services.mautrix-signal.settings.homeserver.domain = "uninsane.org";
services.mautrix-signal.settings.bridge.permissions."@colin:uninsane.org" = "admin";
services.matrix-synapse.settings.app_service_config_files = [
# auto-created by mautrix-signal service
"/var/lib/mautrix-signal/signal-registration.yaml"
];
systemd.services.mautrix-signal.serviceConfig = {
# allow communication to signald
SupplementaryGroups = [ "signald" ];
ReadWritePaths = [ "/run/signald" ];
};
sops.secrets."mautrix_signal_env" = {
mode = "0440";
owner = config.users.users.mautrix-signal.name;
group = config.users.users.matrix-synapse.name;
};
}

View File

@@ -0,0 +1,16 @@
{ lib, pkgs, ... }:
{
# persist external pairings by default
sane.persist.sys.plaintext = [ "/var/lib/bluetooth" ];
sane.fs."/var/lib/bluetooth".generated.acl.mode = "0700";
sane.fs."/var/lib/bluetooth/.secrets.stamp" = {
wantedBeforeBy = [ "bluetooth.service" ];
# XXX: install-bluetooth uses sed, but that's part of the default systemd unit path, it seems
generated.script.script = builtins.readFile ../../scripts/install-bluetooth + ''
touch "/var/lib/bluetooth/.secrets.stamp"
'';
generated.script.scriptArgs = [ "/run/secrets/bt" ];
};
}

22
hosts/common/cross.nix Normal file
View File

@@ -0,0 +1,22 @@
{ config, ... }:
let
mkCrossFrom = localSystem: pkgs: import pkgs.path {
inherit localSystem;
crossSystem = pkgs.stdenv.hostPlatform.system;
inherit (config.nixpkgs) config overlays;
};
in
{
# the configuration of which specific package set `pkgs.cross` refers to happens elsewhere;
# here we just define them all.
nixpkgs.overlays = [
(next: prev: {
# non-emulated packages build *from* local *for* target.
# for large packages like the linux kernel which are expensive to build under emulation,
# the config can explicitly pull such packages from `pkgs.cross` to do more efficient cross-compilation.
crossFrom."x86_64-linux" = mkCrossFrom "x86_64-linux" next;
crossFrom."aarch64-linux" = mkCrossFrom "aarch64-linux" next;
})
];
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,22 +0,0 @@
diff --git a/setup.py b/setup.py
index 2b9d240e..770bc5e7 100755
--- a/setup.py
+++ b/setup.py
@@ -1092,11 +1092,12 @@ def c(base_path: str, **kw: object) -> None:
def create_linux_bundle_gunk(ddir: str, libdir_name: str) -> None:
- if not os.path.exists('docs/_build/html'):
- make = 'gmake' if is_freebsd else 'make'
- run_tool([make, 'docs'])
- copy_man_pages(ddir)
- copy_html_docs(ddir)
+ if not os.getenv('KITTY_NO_DOCS'):
+ if not os.path.exists('docs/_build/html'):
+ make = 'gmake' if is_freebsd else 'make'
+ run_tool([make, 'docs'])
+ copy_man_pages(ddir)
+ copy_html_docs(ddir)
for (icdir, ext) in {'256x256': 'png', 'scalable': 'svg'}.items():
icdir = os.path.join(ddir, 'share', 'icons', 'hicolor', icdir, 'apps')
safe_makedirs(icdir)

View File

@@ -1,31 +1,34 @@
{ lib, pkgs, ... }:
{ pkgs, ... }:
{
imports = [
./cross
./bluetooth.nix
./cross.nix
./feeds.nix
./fs.nix
./hardware.nix
./home
./hardware
./i2p.nix
./ids.nix
./machine-id.nix
./net.nix
./persist.nix
./programs.nix
./secrets.nix
./ssh.nix
./users.nix
./vpn.nix
];
sane.home-manager.enable = true;
sane.nixcache.enable-trusted-keys = true;
sane.nixcache.enable = lib.mkDefault true;
sane.persist.enable = lib.mkDefault true;
sane.programs.sysadminUtils.enableFor.system = lib.mkDefault true;
sane.programs.consoleUtils.enableFor.user.colin = lib.mkDefault true;
sane.packages.enableConsolePkgs = true;
sane.packages.enableSystemPkgs = true;
# some services which use private directories error if the parent (/var/lib/private) isn't 700.
sane.fs."/var/lib/private".dir.acl.mode = "0700";
sane.persist.sys.plaintext = [
"/var/log"
"/var/backup" # for e.g. postgres dumps
# TODO: move elsewhere
"/var/lib/alsa" # preserve output levels, default devices
"/var/lib/colord" # preserve color calibrations (?)
"/var/lib/machines" # maybe not needed, but would be painful to add a VM and forget.
];
nixpkgs.config.allowUnfree = true;
@@ -33,7 +36,6 @@
time.timeZone = "Etc/UTC"; # DST is too confusing for me => use a stable timezone
# allow `nix flake ...` command
# TODO: is this still required?
nix.extraOptions = ''
experimental-features = nix-command flakes
'';
@@ -42,37 +44,20 @@
"nixpkgs=${pkgs.path}"
"nixpkgs-overlays=${../..}/overlays"
];
# hardlinks identical files in the nix store to save 25-35% disk space.
# unclear _when_ this occurs. it's not a service.
# does the daemon continually scan the nix store?
# does the builder use some content-addressed db to efficiently dedupe?
nix.settings.auto-optimise-store = true;
# TODO: move this into home-manager?
fonts = {
enableDefaultFonts = true;
fonts = with pkgs; [ font-awesome noto-fonts-emoji hack-font ];
fonts = with pkgs; [ font-awesome twitter-color-emoji hack-font ];
fontconfig.enable = true;
fontconfig.defaultFonts = {
emoji = [ "Font Awesome 6 Free" "Noto Color Emoji" ];
emoji = [ "Font Awesome 6 Free" "Twitter Color Emoji" ];
monospace = [ "Hack" ];
serif = [ "DejaVu Serif" ];
sansSerif = [ "DejaVu Sans" ];
};
};
# XXX: twitter-color-emoji doesn't cross-compile; but not-fonts-emoji does
# 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 = [];
@@ -88,20 +73,8 @@
# NIXOS_OZONE_WL = "1";
# LIBGL_ALWAYS_SOFTWARE = "1";
};
# dconf docs: <https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/desktop_migration_and_administration_guide/profiles>
# find keys/values with `dconf dump /`
programs.dconf.enable = true;
programs.dconf.packages = [
(pkgs.writeTextFile {
name = "dconf-user-profile";
destination = "/etc/dconf/profile/user";
text = ''
user-db:user
system-db:site
'';
})
];
# enable zsh completions
environment.pathsToLink = [ "/share/zsh" ];
# link debug symbols into /run/current-system/sw/lib/debug
# hopefully picked up by gdb automatically?

View File

@@ -1,9 +1,3 @@
# candidates:
# - The Nonlinear Library (podcast): <https://forum.effectivealtruism.org/posts/JTZTBienqWEAjGDRv/listen-to-more-ea-content-with-the-nonlinear-library>
# - has ~10 posts per day, text-to-speech; i would need better tagging before adding this
# - <https://www.metaculus.com/questions/11102/introducing-the-metaculus-journal-podcast/>
# - dead since 2022/10 - 2023/03
{ lib, sane-data, ... }:
let
hourly = { freq = "hourly"; };
@@ -19,7 +13,6 @@ let
uncat = { cat = "uncat"; };
text = { format = "text"; };
img = { format = "image"; };
mkRss = format: url: { inherit url format; } // uncat // infrequent;
# format-specific helpers
@@ -36,16 +29,16 @@ let
in {
url = raw.url;
# not sure the exact mapping with velocity here: entries per day?
freq = lib.mkIf (raw.velocity or 0 != 0) (lib.mkDefault (
if raw.velocity > 2 then
freq = lib.mkDefault (
if raw.velocity or 0 > 2 then
"hourly"
else if raw.velocity > 0.5 then
else if raw.velocity or 0 > 0.5 then
"daily"
else if raw.velocity > 0.1 then
else if raw.velocity or 0 > 0.1 then
"weekly"
else
"infrequent"
));
);
} // lib.optionalAttrs (raw.is_podcast or false) {
format = "podcast";
} // lib.optionalAttrs (raw.title or "" != "") {
@@ -54,31 +47,19 @@ let
podcasts = [
(fromDb "lexfridman.com/podcast" // rat)
# (mkPod "https://lexfridman.com/feed/podcast/" // rat // weekly)
## Astral Codex Ten
(fromDb "sscpodcast.libsyn.com" // rat)
## Less Wrong Curated
(fromDb "feeds.libsyn.com/421877" // rat)
## Econ Talk
(fromDb "feeds.simplecast.com/wgl4xEgL" // rat)
## Cory Doctorow -- both podcast & text entries
(fromDb "craphound.com" // pol)
## Maggie Killjoy -- referenced by Cory Doctorow
(fromDb "omny.fm/shows/cool-people-who-did-cool-stuff" // pol)
(fromDb "congressionaldish.libsyn.com" // pol)
(mkPod "https://podcasts.la.utexas.edu/this-is-democracy/feed/podcast/" // pol // weekly)
(mkPod "https://congressionaldish.libsyn.com/rss" // pol // infrequent)
## Civboot -- https://anchor.fm/civboot
(fromDb "anchor.fm/s/34c7232c/podcast/rss" // tech)
## Emerge: making sense of what's next -- <https://www.whatisemerging.com/emergepodcast>
(mkPod "https://anchor.fm/s/21bc734/podcast/rss" // pol // infrequent)
(fromDb "feeds.feedburner.com/80000HoursPodcast" // rat)
## Daniel Huberman on sleep
(fromDb "feeds.megaphone.fm/hubermanlab" // uncat)
## Multidisciplinary Association for Psychedelic Studies
(fromDb "mapspodcast.libsyn.com" // uncat)
(fromDb "allinchamathjason.libsyn.com" // pol)
(fromDb "acquired.libsyn.com" // tech)
## ACQ2 - more "Acquired" episodes
(fromDb "acquiredlpbonussecretsecret.libsyn.com" // tech)
# The Intercept - Deconstructed; also available: <rss.acast.com/deconstructed>
(fromDb "rss.prod.firstlook.media/deconstructed/podcast.rss" // pol)
## The Daily
@@ -104,122 +85,93 @@ let
(fromDb "feed.podbean.com/matrixlive/feed.xml" // tech)
## Michael Malice - Your Welcome -- also available here: <https://origin.podcastone.com/podcast?categoryID2=2232>
(fromDb "rss.art19.com/your-welcome" // pol)
(fromDb "seattlenice.buzzsprout.com" // pol)
## Sci-Fi? has Peter Watts; author of No Moods, Ads or Cutesy Fucking Icons (rifters.com)
(fromDb "talesfromthebridge.buzzsprout.com" // tech)
## UnNamed Reverse Engineering Podcast
(fromDb "reverseengineering.libsyn.com/rss" // tech)
];
texts = [
# AGGREGATORS (> 1 post/day)
(fromDb "lwn.net" // tech)
(fromDb "lesswrong.com" // rat)
(fromDb "econlib.org" // pol)
# AGGREGATORS (< 1 post/day)
(fromDb "palladiummag.com" // uncat)
(fromDb "profectusmag.com" // uncat)
(fromDb "semiaccurate.com" // tech)
(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)
(fromDb "spectrum.ieee.org" // tech)
(fromDb "thisweek.gnome.org" // tech)
# more nixos stuff here, but unclear how to subscribe: <https://nixos.org/blog/categories.html>
(mkText "https://nixos.org/blog/announcements-rss.xml" // tech // infrequent)
(mkText "https://nixos.org/blog/stories-rss.xml" // tech // weekly)
## n.b.: quality RSS list here: <https://forum.merveilles.town/thread/57/share-your-rss-feeds%21-6/>
(mkText "https://forum.merveilles.town/rss.xml" // pol // infrequent)
(mkText "https://spectrum.ieee.org/rss" // tech // weekly)
## No Moods, Ads or Cutesy Fucking Icons
(fromDb "rifters.com/crawl" // uncat)
(mkText "https://www.rifters.com/crawl/?feed=rss2" // uncat // weekly)
# DEVELOPERS
(fromDb "uninsane.org" // tech)
(fromDb "ascii.textfiles.com" // tech) # Jason Scott
(fromDb "xn--gckvb8fzb.com" // tech)
(fromDb "mg.lol" // tech)
(fromDb "drewdevault.com" // tech)
## Ken Shirriff
(fromDb "righto.com" // tech)
## shared blog by a few NixOS devs, notably onny
(fromDb "project-insanity.org" // tech)
## Vitalik Buterin
(fromDb "vitalik.ca" // tech)
(mkText "https://vitalik.ca/feed.xml" // tech // infrequent)
## ian (Sanctuary)
(fromDb "sagacioussuricata.com" // tech)
(mkText "https://sagacioussuricata.com/feed.xml" // tech // infrequent)
## Bunnie Juang
(fromDb "bunniestudios.com" // tech)
(fromDb "blog.danieljanus.pl" // tech)
(fromDb "ianthehenry.com" // tech)
(fromDb "bitbashing.io" // tech)
(fromDb "idiomdrottning.org" // uncat)
(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)
(fromDb "jefftk.com" // tech)
(fromDb "pomeroyb.com" // tech)
(mkText "https://til.simonwillison.net/tils/feed.atom" // tech // weekly)
# TECH PROJECTS
(fromDb "blog.rust-lang.org" // tech)
(mkText "https://www.jefftk.com/news.rss" // tech // daily)
(mkText "https://pomeroyb.com/feed.xml" // tech // infrequent)
# (TECH; POL) COMMENTATORS
## Matt Webb -- engineering-ish, but dreamy
(fromDb "interconnected.org/home/feed" // rat)
(fromDb "edwardsnowden.substack.com" // pol // text)
## Julia Evans
(mkText "https://jvns.ca/atom.xml" // tech // weekly)
(mkText "http://benjaminrosshoffman.com/feed" // pol // weekly)
## Ben Thompson
(mkText "https://www.stratechery.com/rss" // pol // weekly)
## Balaji
(fromDb "balajis.com" // pol)
(fromDb "ben-evans.com/benedictevans" // pol)
(fromDb "lynalden.com" // pol)
(fromDb "austinvernon.site" // tech)
(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 "byrnehobart" // pol // infrequent)
# (mkSubstack "doomberg" // tech // weekly) # articles are all pay-walled
(mkSubstack "doomberg" // tech // weekly)
## David Rosenthal
(fromDb "blog.dshr.org" // pol)
(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)
(fromDb "stpeter.im/atom.xml" // pol)
## Peter Saint-Andre -- side project of stpeter.im
(fromDb "philosopher.coach" // rat)
(mkText "https://stpeter.im/atom.xml" // pol // weekly)
# RATIONALITY/PHILOSOPHY/ETC
(mkSubstack "samkriss" // humor // infrequent)
(fromDb "unintendedconsequenc.es" // rat)
(fromDb "applieddivinitystudies.com" // rat)
(fromDb "slimemoldtimemold.com" // rat)
(fromDb "richardcarrier.info" // rat)
(fromDb "gwern.net" // rat)
(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
(fromDb "rootsofprogress.org" // rat)
(mkText "https://rootsofprogress.org/feed.xml" // rat // weekly)
## Robin Hanson
(fromDb "overcomingbias.com" // rat)
(mkText "https://www.overcomingbias.com/feed" // rat // daily)
## Scott Alexander
(mkSubstack "astralcodexten" // rat // daily)
## Paul Christiano
(fromDb "sideways-view.com" // rat)
(mkText "https://sideways-view.com/feed" // rat // infrequent)
## Sean Carroll
(fromDb "preposterousuniverse.com" // rat)
(mkText "https://www.preposterousuniverse.com/rss" // rat // infrequent)
## mostly dating topics. not advice, or humor, but looking through a social lens
(fromDb "putanumonit.com" // rat)
(mkText "https://putanumonit.com/feed" // rat // infrequent)
# CODE
# (mkText "https://github.com/Kaiteki-Fedi/Kaiteki/commits/master.atom" // tech // infrequent)
];
images = [
(fromDb "smbc-comics.com" // img // humor)
(fromDb "xkcd.com" // img // humor)
(fromDb "pbfcomics.com" // img // humor)
(mkImg "https://www.smbc-comics.com/comic/rss" // humor // daily)
(mkImg "https://xkcd.com/atom.xml" // humor // daily)
(mkImg "https://pbfcomics.com/feed" // humor // infrequent)
# (mkImg "http://dilbert.com/feed" // humor // daily)
(fromDb "poorlydrawnlines.com/feed" // img // humor)
# ART
(fromDb "miniature-calendar.com" // img // art // daily)
(mkImg "https://miniature-calendar.com/feed" // art // daily)
];
in
{

View File

@@ -2,6 +2,7 @@
{
imports = [
./all.nix
./x86_64.nix
];
}

View File

@@ -1,7 +1,8 @@
{ lib, pkgs, ... }:
with lib;
{
config = lib.mkIf (pkgs.system == "x86_64-linux") {
config = mkIf (pkgs.system == "x86_64-linux") {
boot.initrd.availableKernelModules = [
"xhci_pci" "ahci" "sd_mod" "sdhci_pci" # nixos-generate-config defaults
"usb_storage" # rpi needed this to boot from usb storage, i think.
@@ -9,6 +10,11 @@
# efi_pstore evivars
];
# enable cross compilation
boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
# nixpkgs.config.allowUnsupportedSystem = true;
# nixpkgs.crossSystem.system = "aarch64-linux";
powerManagement.cpuFreqGovernor = "powersave";
hardware.cpu.amd.updateMicrocode = true; # desktop
hardware.cpu.intel.updateMicrocode = true; # laptop

View File

@@ -1,11 +0,0 @@
# Terminal UI mail client
{ config, sane-lib, ... }:
{
sops.secrets."aerc_accounts" = {
owner = config.users.users.colin.name;
sopsFile = ../../../secrets/universal/aerc_accounts.conf;
format = "binary";
};
sane.user.fs.".config/aerc/accounts.conf" = sane-lib.fs.wantedSymlinkTo config.sops.secrets.aerc_accounts.path;
}

View File

@@ -1,25 +0,0 @@
{ ... }:
{
imports = [
./aerc.nix
./firefox.nix
./gfeeds.nix
./git.nix
./gpodder.nix
./keyring.nix
./kitty
./libreoffice.nix
./mime.nix
./mpv.nix
./neovim.nix
./newsflash.nix
./offlineimap.nix
./ripgrep.nix
./splatmoji.nix
./ssh.nix
./sublime-music.nix
./vlc.nix
./xdg-dirs.nix
./zsh
];
}

View File

@@ -1,18 +0,0 @@
{ lib, pkgs, sane-lib, ... }:
let
mkCfg = lib.generators.toINI { };
in
{
sane.user.fs.".config/git/config" = sane-lib.fs.wantedText (mkCfg {
user.name = "Colin";
user.email = "colin@uninsane.org";
alias.co = "checkout";
# 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,11 +0,0 @@
{ config, sane-lib, ... }:
{
sane.user.persist.private = [ ".local/share/keyrings" ];
sane.user.fs."private/.local/share/keyrings/default" = {
generated.script.script = builtins.readFile ../../../scripts/init-keyring;
# TODO: is this `wantedBy` needed? can we inherit it?
wantedBy = [ config.sane.fs."/home/colin/private".unit ];
};
}

View File

@@ -1,47 +0,0 @@
# vim:ft=kitty
## name: PaperColor Dark
## author: Nikyle Nguyen
## license: MIT
## blurb: Dark color scheme inspired by Google's Material Design
# special
foreground #d0d0d0
background #1c1c1c
cursor #d0d0d0
cursor_text_color background
# black
color0 #1c1c1c
color8 #585858
# red
color1 #af005f
color9 #5faf5f
# green
# "color2" is the green color used by ls to indicate executability
# both as text color
# or as bg color when the text is blue (color4)
color2 #246a28
color10 #2df200
# yellow
color3 #d7af5f
color11 #af87d7
# blue
color4 #78c6ef
color12 #ffaf00
# magenta
color5 #808080
color13 #ff5faf
# cyan
color6 #d7875f
color14 #00afaf
# white
color7 #d0d0d0
color15 #5f8787

View File

@@ -1,70 +0,0 @@
{ pkgs, sane-lib, ... }:
{
sane.user.fs.".config/kitty/kitty.conf" = sane-lib.fs.wantedText ''
# docs: https://sw.kovidgoyal.net/kitty/conf/
# disable terminal bell (when e.g. you backspace too many times)
enable_audio_bell no
map ctrl+n new_os_window_with_cwd
include ${./PaperColor_dark.conf}
'';
# include ${pkgs.kitty-themes}/themes/PaperColor_dark.conf
# THEME CHOICES:
# 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
}

View File

@@ -1,14 +0,0 @@
{ sane-lib, ... }:
{
# libreoffice: disable first-run stuff
sane.user.fs.".config/libreoffice/4/user/registrymodifications.xcu" = sane-lib.fs.wantedText ''
<?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>
}

View File

@@ -1,42 +0,0 @@
{ config, sane-lib, ...}:
let
www = config.sane.web-browser.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
{
# the xdg mime type for a file can be found with:
# - `xdg-mime query filetype path/to/thing.ext`
# we can have single associations or a list of associations.
# there's also options to *remove* [non-default] associations from specific apps
xdg.mime.enable = true;
xdg.mime.defaultApplications = {
# AUDIO
"audio/flac" = audio;
"audio/mpeg" = audio;
"audio/x-vorbis+ogg" = audio;
# IMAGES
"image/heif" = thumb; # apple codec
"image/png" = thumb;
"image/jpeg" = thumb;
# VIDEO
"video/mp4" = video;
"video/quicktime" = video;
"video/x-matroska" = video;
# 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;
};
}

View File

@@ -1,10 +0,0 @@
{ sane-lib, ... }:
{
# format is <key>=%<length>%<value>
sane.user.fs.".config/mpv/mpv.conf" = sane-lib.fs.wantedText ''
save-position-on-quit=%3%yes
keep-open=%3%yes
'';
}

View File

@@ -1,129 +0,0 @@
{ lib, pkgs, ... }:
let
inherit (builtins) map;
inherit (lib) concatMapStrings optionalString;
# this structure roughly mirrors home-manager's `programs.neovim.plugins` option
plugins = with pkgs.vimPlugins; [
# docs: surround-nvim: https://github.com/ur4ltz/surround.nvim/
# docs: vim-surround: https://github.com/tpope/vim-surround
{ plugin = vim-surround; }
# docs: fzf-vim (fuzzy finder): https://github.com/junegunn/fzf.vim
{ plugin = fzf-vim; }
({
# docs: tex-conceal-vim: 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
'';
})
({
# 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()'
'';
})
];
plugin-packages = map (p: p.plugin) plugins;
plugin-config-tex = concatMapStrings (p: optionalString (p.type or "" == "viml") p.config) plugins;
plugin-config-lua = concatMapStrings (p: optionalString (p.type or "" == "lua") p.config) plugins;
in
{
# private because there could be sensitive things in the swap
sane.user.persist.private = [ ".cache/vim-swap" ];
programs.neovim = {
# neovim: https://github.com/neovim/neovim
enable = true;
viAlias = true;
vimAlias = true;
configure = {
packages.myVimPackage = {
start = plugin-packages;
};
customRC = ''
" 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:
""""" PLUGIN CONFIG (tex)
${plugin-config-tex}
""""" PLUGIN CONFIG (lua)
lua <<EOF
${plugin-config-lua}
EOF
'';
};
};
}

View File

@@ -1,17 +0,0 @@
# mail archiving/synchronization tool.
#
# manually download all emails for an account with
# - `offlineimap -a <accountname>`
#
# view account names inside the secrets file, listed below.
{ config, sane-lib, ... }:
{
sops.secrets."offlineimaprc" = {
owner = config.users.users.colin.name;
sopsFile = ../../../secrets/universal/offlineimaprc.bin;
format = "binary";
};
sane.user.fs.".config/offlineimap/config" = sane-lib.fs.wantedSymlinkTo config.sops.secrets.offlineimaprc.path;
}

View File

@@ -1,9 +0,0 @@
{ sane-lib, ... }:
{
# .ignore file is read by ripgrep (rg), silver searcher (ag), maybe others.
# ignore translation files by default when searching, as they tend to have
# a LOT of duplicate text.
sane.user.fs.".ignore" = sane-lib.fs.wantedText ''
po/
'';
}

View File

@@ -1,11 +0,0 @@
{ config, sane-lib, ... }:
{
# 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";
};
sane.user.fs.".config/sublime-music/config.json" = sane-lib.fs.wantedSymlinkTo config.sops.secrets.sublime_music_config.path;
}

View File

@@ -1,20 +0,0 @@
{ lib, sane-lib, ...}:
{
# XDG defines things like ~/Desktop, ~/Downloads, etc.
# these clutter the home, so i mostly don't use them.
sane.user.fs.".config/user-dirs.dirs" = sane-lib.fs.wantedText ''
XDG_DESKTOP_DIR="$HOME/.xdg/Desktop"
XDG_DOCUMENTS_DIR="$HOME/dev"
XDG_DOWNLOAD_DIR="$HOME/tmp"
XDG_MUSIC_DIR="$HOME/Music"
XDG_PICTURES_DIR="$HOME/Pictures"
XDG_PUBLICSHARE_DIR="$HOME/.xdg/Public"
XDG_TEMPLATES_DIR="$HOME/.xdg/Templates"
XDG_VIDEOS_DIR="$HOME/Videos"
'';
# prevent `xdg-user-dirs-update` from overriding/updating our config
# see <https://manpages.ubuntu.com/manpages/bionic/man5/user-dirs.conf.5.html>
sane.user.fs.".config/user-dirs.conf" = sane-lib.fs.wantedText "enabled=False";
}

View File

@@ -1,161 +0,0 @@
{ config, lib, pkgs, sane-lib, ... }:
let
inherit (lib) mkOption types;
cfg = config.sane.zsh;
# powerlevel10k prompt config
# p10k.zsh is the auto-generated config, and i overwrite those defaults here, below.
p10k-overrides = ''
# powerlevel10k launches a gitstatusd daemon to accelerate git prompt queries.
# this keeps open file handles for any git repo i touch for 60 minutes (by default).
# that prevents unmounting whatever device the git repo is on -- particularly problematic for ~/private.
# i can disable gitstatusd and get slower fallback git queries:
# - either universally
# - or selectively by path
# see: <https://github.com/romkatv/powerlevel10k/issues/246>
typeset -g POWERLEVEL9K_VCS_DISABLED_DIR_PATTERN='(/home/colin/private/*|/home/colin/knowledge/*)'
# typeset -g POWERLEVEL9K_DISABLE_GITSTATUS=true
# show user@host also when logged into the current machine.
# default behavior is to show it only over ssh.
typeset -g POWERLEVEL9K_CONTEXT_{DEFAULT,SUDO}_CONTENT_EXPANSION='$P9K_CONTENT'
'';
prezto-init = ''
source ${pkgs.zsh-autosuggestions}/share/zsh-autosuggestions/zsh-autosuggestions.zsh
source ${pkgs.zsh-syntax-highlighting}/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
source ${pkgs.zsh-prezto}/share/zsh-prezto/init.zsh
'';
in
{
options = {
sane.zsh = {
showDeadlines = mkOption {
type = types.bool;
default = true;
description = "show upcoming deadlines (frommy PKM) upon shell init";
};
};
};
config = {
sane.user.persist.plaintext = [
# 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.
# TODO: should be private?
".local/share/zsh"
# cache gitstatus otherwise p10k fetched it from the net EVERY BOOT
".cache/gitstatus"
];
# zsh/prezto complains if zshrc doesn't exist; but it does allow an "empty" file.
sane.user.fs.".config/zsh/.zshrc" = sane-lib.fs.wantedText "# ";
# enable zsh completions
environment.pathsToLink = [ "/share/zsh" ];
programs.zsh = {
enable = true;
histFile = "$HOME/.local/share/zsh/history";
shellAliases = {
":q" = "exit";
# common typos
"cd.." = "cd ..";
"cd../" = "cd ../";
};
setOptions = [
# defaults:
"HIST_IGNORE_DUPS"
"SHARE_HISTORY"
"HIST_FCNTL_LOCK"
# disable `rm *` confirmations
"rmstarsilent"
];
# .zshenv config:
shellInit = ''
ZDOTDIR=$HOME/.config/zsh
'';
# .zshrc config:
interactiveShellInit =
(builtins.readFile ./p10k.zsh)
+ p10k-overrides
+ prezto-init
+ ''
# 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
HISTORY_IGNORE='(sane-shutdown *|sane-reboot *|rm *|nixos-rebuild.* switch)'
# extra aliases
# TODO: move to `shellAliases` config?
function nd() {
mkdir -p "$1";
pushd "$1";
}
''
+ lib.optionalString cfg.showDeadlines ''
${pkgs.sane-scripts}/bin/sane-deadlines
''
+ ''
# auto-cd into any of these dirs by typing them and pressing 'enter':
hash -d 3rd="/home/colin/dev/3rd"
hash -d dev="/home/colin/dev"
hash -d knowledge="/home/colin/knowledge"
hash -d nixos="/home/colin/nixos"
hash -d nixpkgs="/home/colin/dev/3rd/nixpkgs"
hash -d ref="/home/colin/ref"
hash -d secrets="/home/colin/knowledge/secrets"
hash -d tmp="/home/colin/tmp"
hash -d uninsane="/home/colin/dev/uninsane"
hash -d Videos="/home/colin/Videos"
'';
syntaxHighlighting.enable = true;
vteIntegration = true;
};
# enable a command-not-found hook to show nix packages that might provide the binary typed.
programs.nix-index.enable = true;
programs.command-not-found.enable = false; #< mutually exclusive with nix-index
# prezto = oh-my-zsh fork; controls prompt, auto-completion, etc.
# see: https://github.com/sorin-ionescu/prezto
# i believe this file is auto-sourced by the prezto init.zsh script.
sane.user.fs.".config/zsh/.zpreztorc" = sane-lib.fs.wantedText ''
zstyle ':prezto:*:*' color 'yes'
# modules (they ship with prezto):
# ENVIRONMENT: configures jobs to persist after shell exit; other basic niceties
# TERMINAL: auto-titles terminal (e.g. based on cwd)
# EDITOR: configures shortcuts like Ctrl+U=undo, Ctrl+L=clear
# HISTORY: `history-stat` alias, setopts for good history defaults
# DIRECTORY: sets AUTO_CD, adds `d` alias to list directory stack, and `1`-`9` to cd that far back the stack
# SPECTRUM: helpers for term colors and styling. used by prompts? might be unnecessary
# UTILITY: configures aliases like `ll`, `la`, disables globbing for things like rsync
# adds aliases like `get` to fetch a file. also adds `http-serve` alias??
# COMPLETION: tab completion. requires `utility` module prior to loading
# TODO: enable AUTO_PARAM_SLASH
zstyle ':prezto:load' pmodule \
'environment' \
'terminal' \
'editor' \
'history' \
'directory' \
'spectrum' \
'utility' \
'completion' \
'prompt'
# default keymap. try also `vicmd` (vim normal mode, AKA "cmd mode") or `vi`.
zstyle ':prezto:module:editor' key-bindings 'emacs'
zstyle ':prezto:module:prompt' theme 'powerlevel10k'
# disable `mv` confirmation (and `rm`, too, unfortunately)
zstyle ':prezto:module:utility' safe-ops 'no'
'';
};
}

View File

@@ -1,6 +1,3 @@
# TODO: migrate to nixpkgs `config.ids.uids`
# - note that nixpkgs' `config.ids.uids` is strictly a database: it doesn't set anything by default
# whereas our impl sets the gid/uid of the user/group specified if they exist.
{ ... }:
{
@@ -24,12 +21,6 @@
sane.ids.freshrss.uid = 2401;
sane.ids.freshrss.gid = 2401;
sane.ids.mediawiki.uid = 2402;
sane.ids.signald.uid = 2403;
sane.ids.signald.gid = 2403;
sane.ids.mautrix-signal.uid = 2404;
sane.ids.mautrix-signal.gid = 2404;
sane.ids.navidrome.uid = 2405;
sane.ids.navidrome.gid = 2405;
sane.ids.colin.uid = 1000;
sane.ids.guest.uid = 1100;
@@ -38,7 +29,7 @@
sane.ids.sshd.uid = 2001; # 997
sane.ids.sshd.gid = 2001; # 997
sane.ids.polkituser.gid = 2002; # 998
sane.ids.systemd-coredump.gid = 2003; # 996 # 2023/02/12-2023/02/28: upstream temporarily specified this as 151
sane.ids.systemd-coredump.gid = 2003; # 996
sane.ids.nscd.uid = 2004;
sane.ids.nscd.gid = 2004;
sane.ids.systemd-oom.uid = 2005;

View File

@@ -1,6 +1,16 @@
{ config, lib, pkgs, ... }:
{
# if using router's DNS, these mappings will already exist.
# if using a different DNS provider (which servo does), then we need to explicity provide them.
# ugly hack. would be better to get servo to somehow use the router's DNS
networking.hosts = {
"192.168.0.5" = [ "servo" ];
"192.168.0.20" = [ "lappy" ];
"192.168.0.22" = [ "desko" ];
"192.168.0.48" = [ "moby" ];
};
# the default backend is "wpa_supplicant".
# wpa_supplicant reliably picks weak APs to connect to.
# see: <https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/474>
@@ -20,4 +30,14 @@
General.RoamThreshold = "-52"; # default -70
General.RoamThreshold5G = "-52"; # default -76
};
sane.fs."/var/lib/iwd/.secrets.psk.stamp" = {
wantedBeforeBy = [ "iwd.service" ];
generated.acl.mode = "0600";
# XXX: install-iwd uses sed, but that's part of the default systemd unit path, it seems
generated.script.script = builtins.readFile ../../scripts/install-iwd + ''
touch "/var/lib/iwd/.secrets.psk.stamp"
'';
generated.script.scriptArgs = [ "/run/secrets/iwd" "/var/lib/iwd" ];
};
}

View File

@@ -1,18 +0,0 @@
{ ... }:
{
sane.persist.stores.private.origin = "/home/colin/private";
# store /home/colin/a/b in /home/private/a/b instead of /home/private/home/colin/a/b
sane.persist.stores.private.prefix = "/home/colin";
sane.persist.sys.plaintext = [
"/var/log"
"/var/backup" # for e.g. postgres dumps
# TODO: move elsewhere
"/var/lib/alsa" # preserve output levels, default devices
"/var/lib/colord" # preserve color calibrations (?)
"/var/lib/machines" # maybe not needed, but would be painful to add a VM and forget.
"/var/lib/systemd/backlight" # backlight brightness
"/var/lib/systemd/coredump"
];
}

View File

@@ -1,384 +0,0 @@
{ lib, pkgs, ... }:
let
inherit (builtins) attrNames concatLists;
inherit (lib) mapAttrs mapAttrsToList mkDefault mkMerge optional;
flattenedPkgs = pkgs // (with pkgs; {
# XXX can't `inherit` a nested attr, so we move them to the toplevel
"cacert.unbundled" = pkgs.cacert.unbundled;
"gnome.cheese" = gnome.cheese;
"gnome.dconf-editor" = gnome.dconf-editor;
"gnome.file-roller" = gnome.file-roller;
"gnome.gnome-disk-utility" = gnome.gnome-disk-utility;
"gnome.gnome-maps" = gnome.gnome-maps;
"gnome.nautilus" = gnome.nautilus;
"gnome.gnome-system-monitor" = gnome.gnome-system-monitor;
"gnome.gnome-terminal" = gnome.gnome-terminal;
"gnome.gnome-weather" = gnome.gnome-weather;
"gnome.totem" = gnome.totem;
"libsForQt5.plasmatube" = libsForQt5.plasmatube;
});
sysadminPkgs = {
inherit (flattenedPkgs)
btrfs-progs
"cacert.unbundled" # some services require unbundled /etc/ssl/certs
cryptsetup
dig
efibootmgr
fatresize
fd
file
gawk
git
gptfdisk
hdparm
htop
iftop
inetutils # for telnet
iotop
iptables
jq
killall
lsof
nano
netcat
nethogs
nmap
openssl
parted
pciutils
powertop
pstree
ripgrep
screen
smartmontools
socat
strace
subversion
tcpdump
tree
usbutils
wget
;
};
sysadminExtraPkgs = {
# application-specific packages
inherit (pkgs)
backblaze-b2
duplicity
sqlite # to debug sqlite3 databases
;
};
iphonePkgs = {
inherit (pkgs)
ifuse
ipfs
libimobiledevice
;
};
tuiPkgs = {
inherit (pkgs)
aerc # email client
offlineimap # email mailox sync
visidata # TUI spreadsheet viewer/editor
w3m
;
};
# TODO: split these into smaller groups.
# - transcoders (ffmpeg, imagemagick) only wanted on desko/lappy ("powerutils"?)
consolePkgs = {
inherit (pkgs)
cdrtools
dmidecode
efivar
flashrom
fwupd
ghostscript # TODO: imagemagick wrapper should add gs to PATH
gnupg
gocryptfs
gopass
gopass-jsonapi
imagemagick
kitty # TODO: move to GUI, but `ssh servo` from kitty sets `TERM=xterm-kitty` in the remove and breaks things
libsecret # for managing user keyrings
lm_sensors # for sensors-detect
lshw
ffmpeg
memtester
# networkmanager
nixpkgs-review
# nixos-generators
# nettools
nmon
oathToolkit # for oathtool
# ponymix
pulsemixer
python3
rsync
# python3Packages.eyeD3 # music tagging
sane-scripts
sequoia
snapper
sops
sox
speedtest-cli
ssh-to-age
sudo
# tageditor # music tagging
unar
wireguard-tools
xdg-utils # for xdg-open
# youtube-dl
yt-dlp
;
};
guiPkgs = {
inherit (flattenedPkgs)
celluloid # mpv frontend
clinfo
emote
evince # works on phosh
# { pkg = fluffychat-moby; dir = [ ".local/share/chat.fluffy.fluffychat" ]; } # TODO: ship normal fluffychat on non-moby?
# foliate # e-book reader
# 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.
# then reboot (so that libsecret daemon re-loads the keyring...?)
# { pkg = fractal-latest; private = [ ".local/share/fractal" ]; }
# { pkg = fractal-next; private = [ ".local/share/fractal" ]; }
# "gnome.cheese"
"gnome.dconf-editor"
gnome-feeds # RSS reader (with claimed mobile support)
"gnome.file-roller"
# "gnome.gnome-maps" # works on phosh
"gnome.nautilus"
# gnome-podcasts
"gnome.gnome-system-monitor"
# "gnome.gnome-terminal" # works on phosh
"gnome.gnome-weather"
gpodder-configured
gthumb
# lollypop
mpv
networkmanagerapplet
# newsflash
nheko
pavucontrol
# picard # music tagging
playerctl
# "libsForQt5.plasmatube" # Youtube player
soundconverter
# sublime music persists any downloaded albums here.
# it doesn't obey a conventional ~/Music/{Artist}/{Album}/{Track} notation, so no symlinking
# config (e.g. server connection details) is persisted in ~/.config/sublime-music/config.json
# possible to pass config as a CLI arg (sublime-music -c config.json)
# { pkg = sublime-music; dir = [ ".local/share/sublime-music" ]; }
sublime-music-mobile
# tdesktop # broken on phosh
# tokodon
vlc
# pleroma client (Electron). input is broken on phosh. TODO(2023/02/02): fix electron19 input (insecure)
# whalebird
xterm # broken on phosh
;
};
desktopGuiPkgs = {
inherit (flattenedPkgs)
audacity
brave # for the integrated wallet -- as a backup
chromium
dino
electrum
element-desktop
font-manager
gajim # XMPP client
gimp # broken on phosh
"gnome.gnome-disk-utility"
# "gnome.totem" # video player, supposedly supports UPnP
handbrake
hase
inkscape
jellyfin-media-player # TODO: try on moby!
kdenlive
kid3 # audio tagging
krita
libreoffice-fresh # XXX colin: maybe don't want this on mobile
mumble
obsidian
;
};
x86GuiPkgs = {
inherit (pkgs)
discord
# kaiteki # Pleroma client
# gnome.zenity # for kaiteki (it will use qarma, kdialog, or zenity)
# gpt2tc # XXX: unreliable mirror
logseq
losslesscut-bin
makemkv
monero-gui
signal-desktop
spotify
tor-browser-bundle-bin
zecwallet-lite
;
};
# packages not part of any package set
otherPkgs = {
inherit (pkgs)
stepmania
;
};
# define -- but don't enable -- the packages in some attrset.
# use `mkDefault` for the package here so we can customize some of them further down this file
declarePkgs = pkgsAsAttrs: mapAttrs (_n: p: {
package = mkDefault p;
}) pkgsAsAttrs;
in
{
config = {
sane.programs = mkMerge [
(declarePkgs consolePkgs)
(declarePkgs desktopGuiPkgs)
(declarePkgs guiPkgs)
(declarePkgs iphonePkgs)
(declarePkgs sysadminPkgs)
(declarePkgs sysadminExtraPkgs)
(declarePkgs tuiPkgs)
(declarePkgs x86GuiPkgs)
(declarePkgs otherPkgs)
{
# link the various package sets into their own meta packages
consoleUtils = {
package = null;
suggestedPrograms = attrNames consolePkgs;
};
desktopGuiApps = {
package = null;
suggestedPrograms = attrNames desktopGuiPkgs;
};
guiApps = {
package = null;
suggestedPrograms = (attrNames guiPkgs)
++ [ "tuiApps" ]
++ optional (pkgs.system == "x86_64-linux") "x86GuiApps";
};
iphoneUtils = {
package = null;
suggestedPrograms = attrNames iphonePkgs;
};
sysadminUtils = {
package = null;
suggestedPrograms = attrNames sysadminPkgs;
};
sysadminExtraUtils = {
package = null;
suggestedPrograms = attrNames sysadminExtraPkgs;
};
tuiApps = {
package = null;
suggestedPrograms = attrNames tuiPkgs;
};
x86GuiApps = {
package = null;
suggestedPrograms = attrNames x86GuiPkgs;
};
}
{
# nontrivial package definitions
imagemagick.package = pkgs.imagemagick.override {
ghostscriptSupport = true;
};
dino.private = [ ".local/share/dino" ];
# creds, but also 200 MB of node modules, etc
discord.private = [ ".config/discord" ];
# creds/session keys, etc
element-desktop.private = [ ".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.
# TODO: package [smile](https://github.com/mijorus/smile) for probably a better mobile experience.
emote.dir = [ ".local/share/Emote" ];
# XXX: we preserve the whole thing because if we only preserve gPodder/Downloads
# then startup is SLOW during feed import, and we might end up with zombie eps in the dl dir.
gpodder-configured.dir = [ "gPodder" ];
# jellyfin stores things in a bunch of directories: this one persists auth info.
# it *might* be possible to populate this externally (it's Qt stuff), but likely to
# be fragile and take an hour+ to figure out.
jellyfin-media-player.dir = [ ".local/share/Jellyfin Media Player" ];
# actual monero blockchain (not wallet/etc; safe to delete, just slow to regenerate)
# XXX: is it really safe to persist this? it doesn't have info that could de-anonymize if captured?
monero-gui.dir = [ ".bitmonero" ];
mpv.dir = [ ".config/mpv/watch_later" ];
mumble.private = [ ".local/share/Mumble" ];
# not strictly necessary, but allows caching articles; offline use, etc.
newsflash.dir = [ ".local/share/news-flash" ];
nheko.private = [
".config/nheko" # config file (including client token)
".cache/nheko" # media cache
".local/share/nheko" # per-account state database
];
# settings (electron app)
obsidian.dir = [ ".config/obsidian" ];
# creds, media
signal-desktop.private = [ ".config/Signal" ];
# creds, widevine .so download. TODO: could easily manage these statically.
spotify.dir = [ ".config/spotify" ];
# sublime music persists any downloaded albums here.
# it doesn't obey a conventional ~/Music/{Artist}/{Album}/{Track} notation, so no symlinking
# config (e.g. server connection details) is persisted in ~/.config/sublime-music/config.json
# possible to pass config as a CLI arg (sublime-music -c config.json)
# { pkg = sublime-music; dir = [ ".local/share/sublime-music" ]; }
sublime-music-mobile.dir = [ ".local/share/sublime-music" ];
tdesktop.private = [ ".local/share/TelegramDesktop" ];
tokodon.private = [ ".cache/KDE/tokodon" ];
# hardenedMalloc solves a crash at startup
# TODO 2023/02/02: is this safe to remove yet?
tor-browser-bundle-bin.package = pkgs.tor-browser-bundle-bin.override {
useHardenedMalloc = false;
};
# vlc remembers play position in ~/.config/vlc/vlc-qt-interface.conf
vlc.dir = [ ".config/vlc" ];
whalebird.private = [ ".config/Whalebird" ];
# zcash coins. safe to delete, just slow to regenerate (10-60 minutes)
zecwallet-lite.private = [ ".zcash" ];
}
];
# XXX: this might not be necessary. try removing this and cacert.unbundled (servo)?
environment.etc."ssl/certs".source = "${pkgs.cacert.unbundled}/etc/ssl/certs/*";
};
}

View File

@@ -55,9 +55,6 @@
sops.secrets."router_passwd" = {
sopsFile = ../../secrets/universal.yaml;
};
sops.secrets."transmission_passwd" = {
sopsFile = ../../secrets/universal.yaml;
};
sops.secrets."wg_ovpnd_us_privkey" = {
sopsFile = ../../secrets/universal.yaml;
};
@@ -102,26 +99,18 @@
sopsFile = ../../secrets/universal/net/friend-rationalist-empathist.psk.bin;
format = "binary";
};
sops.secrets."iwd/home-bedroom.psk" = {
sopsFile = ../../secrets/universal/net/home-bedroom.psk.bin;
format = "binary";
};
sops.secrets."iwd/home-shared-24G.psk" = {
sopsFile = ../../secrets/universal/net/home-shared-24G.psk.bin;
format = "binary";
};
sops.secrets."iwd/home-shared.psk" = {
sopsFile = ../../secrets/universal/net/home-shared.psk.bin;
format = "binary";
};
sops.secrets."iwd/makespace-south.psk" = {
sopsFile = ../../secrets/universal/net/makespace-south.psk.bin;
format = "binary";
};
sops.secrets."iwd/archive-2023-02-home-bedroom.psk" = {
sopsFile = ../../secrets/universal/net/archive/2023-02-home-bedroom.psk.bin;
format = "binary";
};
sops.secrets."iwd/archive-2023-02-home-shared-24G.psk" = {
sopsFile = ../../secrets/universal/net/archive/2023-02-home-shared-24G.psk.bin;
format = "binary";
};
sops.secrets."iwd/archive-2023-02-home-shared.psk" = {
sopsFile = ../../secrets/universal/net/archive/2023-02-home-shared.psk.bin;
format = "binary";
};
sops.secrets."iwd/iphone" = {
sopsFile = ../../secrets/universal/net/iphone.psk.bin;
format = "binary";

View File

@@ -1,33 +1,24 @@
{ config, lib, sane-data, sane-lib, ... }:
let
inherit (builtins) head map mapAttrs tail;
inherit (lib) concatStringsSep mkMerge reverseList;
in
{
sane.ssh.pubkeys =
let
# path is a DNS-style path like [ "org" "uninsane" "root" ]
keyNameForPath = path:
let
rev = reverseList path;
name = head rev;
host = concatStringsSep "." (tail rev);
rev = lib.reverseList path;
name = builtins.head rev;
host = lib.concatStringsSep "." (builtins.tail rev);
in
"${name}@${host}";
# [{ path :: [String], value :: String }] for the keys we want to install
globalKeys = sane-lib.flattenAttrs sane-data.keys;
domainKeys = sane-lib.flattenAttrs (
mapAttrs (host: cfg: {
colin = cfg.ssh.user_pubkey;
root = cfg.ssh.host_pubkey;
}) config.sane.hosts.by-name
);
in mkMerge (map
localKeys = sane-lib.flattenAttrs sane-data.keys.org.uninsane.local;
in lib.mkMerge (builtins.map
({ path, value }: {
"${keyNameForPath path}" = lib.mkIf (value != null) value;
"${keyNameForPath path}" = value;
})
(globalKeys ++ domainKeys)
(globalKeys ++ localKeys)
);
}

View File

@@ -3,12 +3,12 @@
# installer docs: https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/profiles/installation-device.nix
with lib;
let
cfg = config.sane.guest;
cfg = config.sane.users;
fs = sane-lib.fs;
in
{
options = {
sane.guest.enable = mkOption {
sane.users.guest.enable = mkOption {
default = false;
type = types.bool;
};
@@ -66,7 +66,6 @@ in
security.pam.mount.enable = true;
sane.users.colin.default = true;
# ensure ~ perms are known to sane.fs module.
# TODO: this is generic enough to be lifted up into sane.fs itself.
sane.fs."/home/colin".dir.acl = {
@@ -75,7 +74,7 @@ in
mode = config.users.users.colin.homeMode;
};
sane.user.persist.plaintext = [
sane.persist.home.plaintext = [
"archive"
"dev"
# TODO: records should be private
@@ -88,28 +87,25 @@ in
"Videos"
".cache/nix"
".cache/nix-index"
# ".cargo"
# ".rustup"
".cargo"
".rustup"
];
# convenience
sane.user.fs."knowledge" = fs.wantedSymlinkTo "private/knowledge";
sane.user.fs."nixos" = fs.wantedSymlinkTo "dev/nixos";
sane.user.fs."Books/servo" = fs.wantedSymlinkTo "/mnt/servo-media/Books";
sane.user.fs."Videos/servo" = fs.wantedSymlinkTo "/mnt/servo-media/Videos";
sane.user.fs."Videos/servo-incomplete" = fs.wantedSymlinkTo "/mnt/servo-media/incomplete";
sane.user.fs."Music/servo" = fs.wantedSymlinkTo "/mnt/servo-media/Music";
sane.fs."/home/colin/knowledge" = fs.wantedSymlinkTo "/home/colin/private/knowledge";
sane.fs."/home/colin/nixos" = fs.wantedSymlinkTo "/home/colin/dev/nixos";
sane.fs."/home/colin/Videos/servo" = fs.wantedSymlinkTo "/mnt/servo-media/Videos";
sane.fs."/home/colin/Videos/servo-incomplete" = fs.wantedSymlinkTo "/mnt/servo-media/incomplete";
sane.fs."/home/colin/Music/servo" = fs.wantedSymlinkTo "/mnt/servo-media/Music";
# used by password managers, e.g. unix `pass`
sane.user.fs.".password-store" = fs.wantedSymlinkTo "knowledge/secrets/accounts";
sane.fs."/home/colin/.password-store" = fs.wantedSymlinkTo "/home/colin/knowledge/secrets/accounts";
sane.persist.sys.plaintext = mkIf cfg.enable [
sane.persist.sys.plaintext = mkIf cfg.guest.enable [
# intentionally allow other users to write to the guest folder
{ directory = "/home/guest"; user = "guest"; group = "users"; mode = "0775"; }
];
users.users.guest = mkIf cfg.enable {
users.users.guest = mkIf cfg.guest.enable {
isNormalUser = true;
home = "/home/guest";
subUidRanges = [
@@ -130,8 +126,8 @@ in
services.openssh = {
enable = true;
settings.PermitRootLogin = "no";
settings.PasswordAuthentication = false;
permitRootLogin = "no";
passwordAuthentication = false;
};
};
}

View File

@@ -4,17 +4,13 @@
./fs.nix
];
sane.roles.build-machine.enable = true;
sane.roles.client = true;
sane.services.wg-home.enable = true;
sane.services.wg-home.ip = config.sane.hosts.by-name."desko".wg-home.ip;
sane.services.duplicity.enable = true;
sane.services.nixserve.sopsFile = ../../../secrets/desko.yaml;
# sane.packages.enableDevPkgs = true;
sane.gui.sway.enable = true;
sane.programs.iphoneUtils.enableFor.user.colin = true;
sane.programs.guiApps.suggestedPrograms = [ "desktopGuiApps" ];
sane.services.duplicity.enable = true;
sane.services.nixserve.enable = true;
sane.services.nixserve.sopsFile = ../../secrets/desko.yaml;
sane.persist.enable = true;
boot.loader.efi.canTouchEfiVariables = false;
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
@@ -23,7 +19,7 @@
services.usbmuxd.enable = true;
sops.secrets.colin-passwd = {
sopsFile = ../../../secrets/desko.yaml;
sopsFile = ../../secrets/desko.yaml;
neededForUsers = true;
};
@@ -45,7 +41,7 @@
};
sops.secrets.duplicity_passphrase = {
sopsFile = ../../../secrets/desko.yaml;
sopsFile = ../../secrets/desko.yaml;
};
programs.steam = {
@@ -54,7 +50,7 @@
remotePlay.openFirewall = true; # Open ports in the firewall for Steam Remote Play
dedicatedServer.openFirewall = true; # Open ports in the firewall for Source Dedicated Server
};
sane.user.persist.plaintext = [
sane.persist.home.plaintext = [
".steam"
".local/share/Steam"
];

View File

@@ -1,29 +1,23 @@
# trampoline from flake.nix into the specific host definition, while doing a tiny bit of common setup
# args from flake-level `import`
{ hostName, localSystem }:
# module args
{ config, lib, ... }:
{ ... }:
{
imports = [
./by-name/${hostName}
./${hostName}
./common
./modules
];
networking.hostName = hostName;
nixpkgs.buildPlatform = lib.mkIf (localSystem != null) localSystem;
sane.cross.enablePatches = localSystem != null;
# nixpkgs.overlays = [
# (next: prev: {
# # for local != target we by default just emulate the target while building.
# # provide a `pkgs.cross.<pkg>` alias that consumers can use instead of `pkgs.<foo>`
# # to explicitly opt into non-emulated cross compilation for any specific package.
# # this is most beneficial for large packages with few pre-requisites -- like Linux.
# cross = prev.crossFrom."${localSystem}";
# })
# ];
nixpkgs.overlays = [
(next: prev: {
# for local != target we by default just emulate the target while building.
# provide a `pkgs.cross.<pkg>` alias that consumers can use instead of `pkgs.<foo>`
# to explicitly opt into non-emulated cross compilation for any specific package.
# this is most beneficial for large packages with few pre-requisites -- like Linux.
cross = next.crossFrom."${localSystem}";
})
];
}

View File

@@ -1,27 +1,20 @@
{ config, pkgs, ... }:
{ pkgs, ... }:
{
imports = [
./fs.nix
];
sane.yggdrasil.enable = true;
# sane.packages.enableDevPkgs = true;
sane.roles.client = true;
sane.services.wg-home.enable = true;
sane.services.wg-home.ip = config.sane.hosts.by-name."lappy".wg-home.ip;
# sane.guest.enable = true;
# sane.users.guest.enable = true;
sane.gui.sway.enable = true;
sane.persist.enable = true;
sane.nixcache.enable = true;
boot.loader.efi.canTouchEfiVariables = false;
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
sane.programs.guiApps.suggestedPrograms = [
"desktopGuiApps"
"stepmania"
];
sops.secrets.colin-passwd = {
sopsFile = ../../../secrets/lappy.yaml;
sopsFile = ../../secrets/lappy.yaml;
neededForUsers = true;
};

View File

@@ -6,9 +6,12 @@
./kernel.nix
];
sane.roles.client = true;
sane.services.wg-home.enable = true;
sane.services.wg-home.ip = config.sane.hosts.by-name."moby".wg-home.ip;
# cross-compiled documentation is *slow*.
# no obvious way to natively compile docs (2022/09/29).
# entrypoint is nixos/modules/misc/documentation.nix
# doc building happens in nixos/doc/manual/default.nix
# TODO: we could *maybe* inject pkgs.buildPackages.xyz = cross.buildPackages.xyz?
documentation.nixos.enable = false;
# XXX colin: phosh doesn't work well with passwordless login,
# so set this more reliable default password should anything go wrong
@@ -16,29 +19,25 @@
services.getty.autologinUser = "root"; # allows for emergency maintenance?
sops.secrets.colin-passwd = {
sopsFile = ../../../secrets/moby.yaml;
sopsFile = ../../secrets/moby.yaml;
neededForUsers = true;
};
sane.web-browser = {
# compromise impermanence for the sake of usability
persistCache = "private";
persistData = "private";
# i don't do crypto stuff on moby
addons.ether-metamask.enable = false;
# addons.sideberry.enable = false;
};
sane.user.persist.plaintext = [
# usability compromises
sane.web-browser.persistCache = "private";
sane.web-browser.persistData = "private";
sane.persist.home.plaintext = [
".config/pulse" # persist pulseaudio volume
];
# sane.packages.enableGuiPkgs = false; # XXX faster builds/imaging for debugging
sane.packages.extraUserPkgs = [
pkgs.plasma5Packages.konsole # terminal
];
sane.nixcache.enable = true;
sane.persist.enable = true;
sane.gui.phosh.enable = true;
# sane.programs.consoleUtils.enableFor.user.colin = false;
# sane.programs.guiApps.enableFor.user.colin = false;
sane.programs.sequoia.enableFor.user.colin = false;
sane.programs.tuiApps.enableFor.user.colin = false; # visidata, others, don't compile well
boot.loader.efi.canTouchEfiVariables = false;
# /boot space is at a premium. default was 20.
@@ -55,10 +54,9 @@
# without this some GUI apps fail: `DRM_IOCTL_MODE_CREATE_DUMB failed: Cannot allocate memory`
# this is because they can't allocate enough video ram.
# the default CMA seems to be 32M.
# i was running fine with 256MB from 2022/07-ish through 2022/12-ish, but then the phone quit reliably coming back from sleep: maybe a memory leak?
# the default CMA seems to be 32M. we could probably get by with as little as 64M, and safely with 128M.
# `cat /proc/meminfo` to see CmaTotal/CmaFree if interested in tuning this.
boot.kernelParams = [ "cma=512M" ];
boot.kernelParams = [ "cma=256M" ];
# mobile-nixos' /lib/firmware includes:
# rtl_bt (bluetooth)

View File

@@ -114,7 +114,7 @@ in
# - phone rotation sensor is off by 90 degrees
# - ambient light sensor causes screen brightness to be shakey
# - phosh greeter may not appear after wake from sleep
boot.kernelPackages = pkgs.linuxPackagesFor pkgs.linux-megous;
boot.kernelPackages = pkgs.cross.linuxPackagesFor pkgs.cross.linux-megous;
boot.kernelPatches = [
(patchDefconfig (kernelConfig //

View File

@@ -1,16 +0,0 @@
{ ... }:
{
imports = [
./derived-secrets.nix
./gui
./hardware
./hostnames.nix
./hosts.nix
./nixcache.nix
./roles
./services
./wg-home.nix
./yggdrasil.nix
];
}

View File

@@ -1,47 +0,0 @@
{ config, lib, ... }:
let
inherit (builtins) toString;
inherit (lib) mapAttrs mkOption types;
cfg = config.sane.derived-secrets;
secret = types.submodule {
options = {
len = mkOption {
type = types.int;
};
encoding = mkOption {
type = types.enum [ "base64" ];
};
};
};
in
{
options = {
sane.derived-secrets = mkOption {
type = types.attrsOf secret;
default = {};
description = ''
fs path => secret options.
for each entry, we create an item at the given path whose value is deterministic,
but also pseudo-random and not predictable by anyone without root access to the machine.
as PRNG source we use the host ssh key, and derived secrets are salted based on the destination path.
'';
};
};
config = {
sane.fs = mapAttrs (path: c: {
generated.script.script = ''
echo "$1" | cat /dev/stdin /etc/ssh/host_keys/ssh_host_ed25519_key \
| sha512sum \
| cut -c 1-${toString (c.len * 2)} \
| tr a-z A-Z \
| basenc -d --base16 \
| basenc --${c.encoding} \
> "$1"
'';
generated.script.scriptArgs = [ path ];
generated.acl.mode = "0600";
}) cfg;
};
}

View File

@@ -1,15 +0,0 @@
{ lib, config, ... }:
let
inherit (lib) mkDefault mkIf mkOption types;
cfg = config.sane.gui;
in
{
imports = [
./gnome.nix
./phosh.nix
./plasma.nix
./plasma-mobile.nix
./sway.nix
];
}

View File

@@ -1,665 +0,0 @@
{ config, lib, pkgs, sane-lib, ... }:
# docs: https://nixos.wiki/wiki/Sway
with lib;
let
cfg = config.sane.gui.sway;
# docs: https://github.com/Alexays/Waybar/wiki/Configuration
# format specifiers: https://fmt.dev/latest/syntax.html#syntax
waybar-config = [
{ # TOP BAR
layer = "top";
height = 40;
modules-left = ["sway/workspaces" "sway/mode"];
modules-center = ["sway/window"];
modules-right = ["custom/mediaplayer" "clock" "battery" "cpu" "network"];
"sway/window" = {
max-length = 50;
};
# include song artist/title. source: https://www.reddit.com/r/swaywm/comments/ni0vso/waybar_spotify_tracktitle/
"custom/mediaplayer" = {
exec = pkgs.writeShellScript "waybar-mediaplayer" ''
player_status=$(${pkgs.playerctl}/bin/playerctl status 2> /dev/null)
if [ "$player_status" = "Playing" ]; then
echo "$(${pkgs.playerctl}/bin/playerctl metadata artist) - $(${pkgs.playerctl}/bin/playerctl metadata title)"
elif [ "$player_status" = "Paused" ]; then
echo " $(${pkgs.playerctl}/bin/playerctl metadata artist) - $(${pkgs.playerctl}/bin/playerctl metadata title)"
fi
'';
interval = 2;
format = "{} ";
# return-type = "json";
on-click = "${pkgs.playerctl}/bin/playerctl play-pause";
on-scroll-up = "${pkgs.playerctl}/bin/playerctl next";
on-scroll-down = "${pkgs.playerctl}/bin/playerctl previous";
};
network = {
# docs: https://github.com/Alexays/Waybar/blob/master/man/waybar-network.5.scd
interval = 2;
max-length = 40;
# custom :> format specifier explained here: https://github.com/Alexays/Waybar/pull/472
format-ethernet = " {bandwidthUpBits:>} {bandwidthDownBits:>}";
tooltip-format-ethernet = "{ifname} {bandwidthUpBits:>} {bandwidthDownBits:>}";
format-wifi = "{ifname} ({signalStrength}%) {bandwidthUpBits:>} {bandwidthDownBits:>}";
tooltip-format-wifi = "{essid} ({signalStrength}%) {bandwidthUpBits:>} {bandwidthDownBits:>}";
format-disconnected = "";
};
cpu = {
format = " {usage:2}%";
tooltip = false;
};
battery = {
states = {
good = 95;
warning = 30;
critical = 10;
};
format = "{icon} {capacity}%";
format-icons = [
""
""
""
""
""
];
};
clock = {
format-alt = "{:%a, %d. %b %H:%M}";
};
}
];
# waybar-config-text = lib.generators.toJSON {} waybar-config;
waybar-config-text = (pkgs.formats.json {}).generate "waybar-config.json" waybar-config;
# bare sway launcher
sway-launcher = pkgs.writeShellScriptBin "sway-launcher" ''
${pkgs.sway}/bin/sway --debug > /tmp/sway.log 2>&1
'';
# start sway and have it construct the gtkgreeter
sway-as-greeter = pkgs.writeShellScriptBin "sway-as-greeter" ''
${pkgs.sway}/bin/sway --debug --config ${sway-config-into-gtkgreet} > /tmp/sway-as-greeter.log 2>&1
'';
# (config file for the above)
sway-config-into-gtkgreet = pkgs.writeText "greetd-sway-config" ''
exec "${gtkgreet-launcher}"
'';
# gtkgreet which launches a layered sway instance
gtkgreet-launcher = pkgs.writeShellScript "gtkgreet-launcher" ''
# NB: the "command" field here is run in the user's shell.
# so that command must exist on the specific user's path who is logging in. it doesn't need to exist system-wide.
${pkgs.greetd.gtkgreet}/bin/gtkgreet --layer-shell --command sway-launcher
'';
greeter-session = {
# greeter session config
command = "${sway-as-greeter}/bin/sway-as-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";`
};
greeterless-session = {
# no greeter
command = "${sway-launcher}/bin/sway-launcher";
user = "colin";
};
in
{
options = {
sane.gui.sway.enable = mkOption {
default = false;
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 = mkMerge [
{
sane.programs.swayApps = {
package = null;
suggestedPrograms = [
"guiApps"
"swaylock"
"swayidle"
"wl-clipboard"
"mako" # notification daemon
# # "pavucontrol"
"gnome.gnome-bluetooth"
"gnome.gnome-control-center"
"sway-contrib.grimshot"
];
};
}
{
sane.programs = {
inherit (pkgs // {
"gnome.gnome-bluetooth" = pkgs.gnome.gnome-bluetooth;
"gnome.gnome-control-center" = pkgs.gnome.gnome-control-center;
"sway-contrib.grimshot" = pkgs.sway-contrib.grimshot;
})
swaylock
swayidle
wl-clipboard
mako
"gnome.gnome-bluetooth"
"gnome.gnome-control-center"
"sway-contrib.grimshot"
;
};
}
(mkIf cfg.enable {
sane.programs.swayApps.enableFor.user.colin = true;
# swap in these lines to use SDDM instead of `services.greetd`.
# services.xserver.displayManager.sddm.enable = true;
# services.xserver.enable = true;
services.greetd = {
# greetd source/docs:
# - <https://git.sr.ht/~kennylevinsen/greetd>
enable = true;
settings = {
default_session = if cfg.useGreeter then greeter-session else greeterless-session;
};
};
# we need the greeter's command to be on our PATH
users.users.colin.packages = [ sway-launcher ];
# some programs (e.g. fractal) **require** a "Secret Service Provider"
services.gnome.gnome-keyring.enable = true;
# unlike other DEs, sway configures no audio stack
# administer with pw-cli, pw-mon, pw-top commands
services.pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true; # ??
pulse.enable = true;
};
networking.useDHCP = false;
networking.networkmanager.enable = true;
networking.wireless.enable = lib.mkForce false;
hardware.bluetooth.enable = true;
services.blueman.enable = true;
# gsd provides Rfkill, which is required for the bluetooth pane in gnome-control-center to work
services.gnome.gnome-settings-daemon.enable = true;
# start the components of gsd we need at login
systemd.user.targets."org.gnome.SettingsDaemon.Rfkill".wantedBy = [ "graphical-session.target" ];
# go ahead and `systemctl --user cat gnome-session-initialized.target`. i dare you.
# the only way i can figure out how to get Rfkill to actually load is to just disable all the shit it depends on.
# it doesn't actually seem to need ANY of them in the first place T_T
systemd.user.targets."gnome-session-initialized".enable = false;
# bluez can't connect to audio devices unless pipewire is running.
# a system service can't depend on a user service, so just launch it at graphical-session
systemd.user.services."pipewire".wantedBy = [ "graphical-session.target" ];
programs.sway = {
enable = true;
wrapperFeatures.gtk = true;
};
sane.user.fs.".config/sway/config" =
let
fuzzel = "${pkgs.fuzzel}/bin/fuzzel";
sed = "${pkgs.gnused}/bin/sed";
wtype = "${pkgs.wtype}/bin/wtype";
kitty = "${pkgs.kitty}/bin/kitty";
launcher-cmd = fuzzel;
terminal-cmd = kitty;
lock-cmd = "${pkgs.swaylock}/bin/swaylock --indicator-idle-visible --indicator-radius 100 --indicator-thickness 30";
vol-up-cmd = "${pkgs.pulsemixer}/bin/pulsemixer --change-volume +5";
vol-down-cmd = "${pkgs.pulsemixer}/bin/pulsemixer --change-volume -5";
mute-cmd = "${pkgs.pulsemixer}/bin/pulsemixer --toggle-mute";
brightness-up-cmd = "${pkgs.brightnessctl}/bin/brightnessctl set +2%";
brightness-down-cmd = "${pkgs.brightnessctl}/bin/brightnessctl set 2%-";
screenshot-cmd = "${pkgs.sway-contrib.grimshot}/bin/grimshot copy area";
# "bookmarking"/snippets inspired by Luke Smith:
# - <https://www.youtube.com/watch?v=d_11QaTlf1I>
snip-file = ./snippets.txt;
# TODO: querying sops here breaks encapsulation
list-snips = "cat ${snip-file} ${config.sops.secrets.snippets.path}";
strip-comments = "${sed} 's/ #.*$//'";
snip-cmd = "${wtype} $(${list-snips} | ${fuzzel} -d -i -w 60 | ${strip-comments})";
# TODO: next splatmoji release should allow `-s none` to disable skin tones
emoji-cmd = "${pkgs.splatmoji}/bin/splatmoji -s medium-light type";
in sane-lib.fs.wantedText ''
### default font
font pango:monospace 8
### pixel boundary between windows
default_border pixel 3
default_floating_border pixel 2
hide_edge_borders smart
### defaults
focus_wrapping no
focus_follows_mouse yes
focus_on_window_activation smart
mouse_warping output
workspace_layout default
workspace_auto_back_and_forth no
### default colors (#border #background #text #indicator #childBorder)
client.focused #4c7899 #285577 #ffffff #2e9ef4 #285577
client.focused_inactive #333333 #5f676a #ffffff #484e50 #5f676a
client.unfocused #333333 #222222 #888888 #292d2e #222222
client.urgent #2f343a #900000 #ffffff #900000 #900000
client.placeholder #000000 #0c0c0c #ffffff #000000 #0c0c0c
client.background #ffffff
### key bindings
floating_modifier Mod1
## media keys
bindsym XF86AudioRaiseVolume exec ${vol-up-cmd}
bindsym XF86AudioLowerVolume exec ${vol-down-cmd}
bindsym Mod1+Page_Up exec ${vol-up-cmd}
bindsym Mod1+Page_Down exec ${vol-down-cmd}
bindsym XF86AudioMute exec ${mute-cmd}
bindsym XF86MonBrightnessUp exec ${brightness-up-cmd}
bindsym XF86MonBrightnessDown exec ${brightness-down-cmd}
## special functions
bindsym Mod1+Print exec ${screenshot-cmd}
bindsym Mod1+l exec ${lock-cmd}
bindsym Mod1+s exec ${snip-cmd}
bindsym Mod1+slash exec ${emoji-cmd}
bindsym Mod1+d exec ${launcher-cmd}
bindsym Mod1+Return exec ${terminal-cmd}
bindsym Mod1+Shift+q kill
bindsym Mod1+Shift+e exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit'
bindsym Mod1+Shift+c reload
## layout
bindsym Mod1+b splith
bindsym Mod1+v splitv
bindsym Mod1+f fullscreen toggle
bindsym Mod1+a focus parent
bindsym Mod1+w layout tabbed
bindsym Mod1+e layout toggle split
bindsym Mod1+Shift+space floating toggle
bindsym Mod1+space focus mode_toggle
bindsym Mod1+r mode resize
## movement
bindsym Mod1+Up focus up
bindsym Mod1+Down focus down
bindsym Mod1+Left focus left
bindsym Mod1+Right focus right
bindsym Mod1+Shift+Up move up
bindsym Mod1+Shift+Down move down
bindsym Mod1+Shift+Left move left
bindsym Mod1+Shift+Right move right
## workspaces
bindsym Mod1+1 workspace number 1
bindsym Mod1+2 workspace number 2
bindsym Mod1+3 workspace number 3
bindsym Mod1+4 workspace number 4
bindsym Mod1+5 workspace number 5
bindsym Mod1+6 workspace number 6
bindsym Mod1+7 workspace number 7
bindsym Mod1+8 workspace number 8
bindsym Mod1+9 workspace number 9
bindsym Mod1+Shift+1 move container to workspace number 1
bindsym Mod1+Shift+2 move container to workspace number 2
bindsym Mod1+Shift+3 move container to workspace number 3
bindsym Mod1+Shift+4 move container to workspace number 4
bindsym Mod1+Shift+5 move container to workspace number 5
bindsym Mod1+Shift+6 move container to workspace number 6
bindsym Mod1+Shift+7 move container to workspace number 7
bindsym Mod1+Shift+8 move container to workspace number 8
bindsym Mod1+Shift+9 move container to workspace number 9
## "scratchpad" = ??
bindsym Mod1+Shift+minus move scratchpad
bindsym Mod1+minus scratchpad show
### defaults
mode "resize" {
bindsym Down resize grow height 10 px
bindsym Escape mode default
bindsym Left resize shrink width 10 px
bindsym Return mode default
bindsym Right resize grow width 10 px
bindsym Up resize shrink height 10 px
bindsym h resize shrink width 10 px
bindsym j resize grow height 10 px
bindsym k resize shrink height 10 px
bindsym l resize grow width 10 px
}
### lightly modified bars
bar {
# TODO: fonts was:
# config.fonts.fontconfig.defaultFonts; (monospace ++ emoji)
font pango:Hack, Font Awesome 6 Free, Twitter Color Emoji 24.000000
mode dock
hidden_state hide
position top
status_command ${pkgs.i3status}/bin/i3status
swaybar_command ${pkgs.waybar}/bin/waybar
workspace_buttons yes
strip_workspace_numbers no
tray_output primary
colors {
background #000000
statusline #ffffff
separator #666666
# #border #background #text
focused_workspace #4c7899 #285577 #ffffff
active_workspace #333333 #5f676a #ffffff
inactive_workspace #333333 #222222 #888888
urgent_workspace #2f343a #900000 #ffffff
binding_mode #2f343a #900000 #ffffff
}
}
### displays
## DESKTOP
output "Samsung Electric Company S22C300 0x00007F35" {
pos 0,0
res 1920x1080
}
output "Goldstar Company Ltd LG ULTRAWIDE 0x00004E94" {
pos 1920,0
res 3440x1440
}
## LAPTOP
# sh/en TV
output "Pioneer Electronic Corporation VSX-524 0x00000101" {
pos 0,0
res 1920x1080
}
# internal display
output "Unknown 0x0637 0x00000000" {
pos 1920,0
res 1920x1080
}
'';
sane.user.fs.".config/waybar/config" = sane-lib.fs.wantedSymlinkTo waybar-config-text;
# style docs: https://github.com/Alexays/Waybar/wiki/Styling
sane.user.fs.".config/waybar/style.css" = sane-lib.fs.wantedText ''
* {
font-family: monospace;
}
/* defaults below: https://github.com/Alexays/Waybar/blob/master/resources/style.css */
window#waybar {
background-color: rgba(43, 48, 59, 0.5);
border-bottom: 3px solid rgba(100, 114, 125, 0.5);
color: #ffffff;
transition-property: background-color;
transition-duration: .5s;
}
window#waybar.hidden {
opacity: 0.2;
}
/*
window#waybar.empty {
background-color: transparent;
}
window#waybar.solo {
background-color: #FFFFFF;
}
*/
window#waybar.termite {
background-color: #3F3F3F;
}
window#waybar.chromium {
background-color: #000000;
border: none;
}
#workspaces button {
padding: 0 5px;
background-color: transparent;
color: #ffffff;
/* Use box-shadow instead of border so the text isn't offset */
box-shadow: inset 0 -3px transparent;
/* Avoid rounded borders under each workspace name */
border: none;
border-radius: 0;
}
/* https://github.com/Alexays/Waybar/wiki/FAQ#the-workspace-buttons-have-a-strange-hover-effect */
#workspaces button:hover {
background: rgba(0, 0, 0, 0.2);
box-shadow: inset 0 -3px #ffffff;
}
#workspaces button.focused {
background-color: #64727D;
box-shadow: inset 0 -3px #ffffff;
}
#workspaces button.urgent {
background-color: #eb4d4b;
}
#mode {
background-color: #64727D;
border-bottom: 3px solid #ffffff;
}
#clock,
#battery,
#cpu,
#memory,
#disk,
#temperature,
#backlight,
#network,
#pulseaudio,
#custom-media,
#tray,
#mode,
#idle_inhibitor,
#mpd {
padding: 0 10px;
color: #ffffff;
}
#window,
#workspaces {
margin: 0 4px;
}
/* If workspaces is the leftmost module, omit left margin */
.modules-left > widget:first-child > #workspaces {
margin-left: 0;
}
/* If workspaces is the rightmost module, omit right margin */
.modules-right > widget:last-child > #workspaces {
margin-right: 0;
}
#clock {
background-color: #64727D;
}
#battery {
background-color: #ffffff;
color: #000000;
}
#battery.charging, #battery.plugged {
color: #ffffff;
background-color: #26A65B;
}
@keyframes blink {
to {
background-color: #ffffff;
color: #000000;
}
}
#battery.critical:not(.charging) {
background-color: #f53c3c;
color: #ffffff;
animation-name: blink;
animation-duration: 0.5s;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-direction: alternate;
}
label:focus {
background-color: #000000;
}
#cpu {
background-color: #2ecc71;
color: #000000;
}
#memory {
background-color: #9b59b6;
}
#disk {
background-color: #964B00;
}
#backlight {
background-color: #90b1b1;
}
#network {
background-color: #2980b9;
}
#network.disconnected {
background-color: #f53c3c;
}
#pulseaudio {
background-color: #f1c40f;
color: #000000;
}
#pulseaudio.muted {
background-color: #90b1b1;
color: #2a5c45;
}
#custom-media {
background-color: #66cc99;
color: #2a5c45;
min-width: 100px;
}
#custom-media.custom-spotify {
background-color: #66cc99;
}
#custom-media.custom-vlc {
background-color: #ffa000;
}
#temperature {
background-color: #f0932b;
}
#temperature.critical {
background-color: #eb4d4b;
}
#tray {
background-color: #2980b9;
}
#tray > .passive {
-gtk-icon-effect: dim;
}
#tray > .needs-attention {
-gtk-icon-effect: highlight;
background-color: #eb4d4b;
}
#idle_inhibitor {
background-color: #2d3436;
}
#idle_inhibitor.activated {
background-color: #ecf0f1;
color: #2d3436;
}
#mpd {
background-color: #66cc99;
color: #2a5c45;
}
#mpd.disconnected {
background-color: #f53c3c;
}
#mpd.stopped {
background-color: #90b1b1;
}
#mpd.paused {
background-color: #51a37a;
}
#language {
background: #00b093;
color: #740864;
padding: 0 5px;
margin: 0 5px;
min-width: 16px;
}
#keyboard-state {
background: #97e1ad;
color: #000000;
padding: 0 0px;
margin: 0 5px;
min-width: 16px;
}
#keyboard-state > label {
padding: 0 5px;
}
#keyboard-state > label.locked {
background: rgba(0, 0, 0, 0.2);
}
'';
# style = ''
# * {
# border: none;
# border-radius: 0;
# font-family: Source Code Pro;
# }
# window#waybar {
# background: #16191C;
# color: #AAB2BF;
# }
# #workspaces button {
# padding: 0 5px;
# }
# .custom-spotify {
# padding: 0 10px;
# margin: 0 4px;
# background-color: #1DB954;
# color: black;
# }
# '';
})
];
}

View File

@@ -1,21 +0,0 @@
{ config, lib, ... }:
{
# give each host a shortname that all the other hosts know, to allow easy comms.
networking.hosts = lib.mkMerge [
(lib.mapAttrs' (host: cfg: {
# bare-name for LAN addresses
# if using router's DNS, these mappings will already exist.
# if using a different DNS provider (which servo does), then we need to explicity provide them.
# ugly hack. would be better to get servo to somehow use the router's DNS
name = cfg.lan-ip;
value = [ host ];
}) config.sane.hosts.by-name)
(lib.mapAttrs' (host: cfg: {
# -hn suffixed name for communication over my wg-home VPN.
# hn = "home network"
name = cfg.wg-home.ip;
value = [ "${host}-hn" ];
}) config.sane.hosts.by-name)
];
}

View File

@@ -1,100 +0,0 @@
{ config, lib, ... }:
let
inherit (lib) attrValues filterAttrs mkMerge mkOption types;
cfg = config.sane.hosts;
host = types.submodule ({ config, ... }: {
options = {
ssh.user_pubkey = mkOption {
type = types.str;
description = ''
ssh pubkey that the primary user of this machine will use when connecting to other machines.
e.g. "ssh-ed25519 AAAA<base64>".
'';
};
ssh.host_pubkey = mkOption {
type = types.str;
description = ''
ssh pubkey which this host will present to connections initiated against it.
e.g. "ssh-ed25519 AAAA<base64>".
'';
};
wg-home.pubkey = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
wireguard public key for the wg-home VPN.
e.g. "pWtnKW7f7sNIZQ2M83uJ7cHg3IL1tebE3IoVkCgjkXM=".
'';
};
wg-home.ip = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
IP address to use on the wg-home VPN.
e.g. "10.0.10.5";
'';
};
wg-home.endpoint = mkOption {
type = types.nullOr types.str;
default = null;
};
lan-ip = mkOption {
type = types.str;
description = ''
ip address when on the lan.
e.g. "192.168.0.5";
'';
};
};
});
in
{
options = {
sane.hosts.by-name = mkOption {
type = types.attrsOf host;
default = {};
description = ''
map of hostname => attrset of information specific to that host,
like its ssh pubkey, etc.
'';
};
};
config = {
# TODO: this should be populated per-host
sane.hosts.by-name."desko" = {
ssh.user_pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPU5GlsSfbaarMvDA20bxpSZGWviEzXGD8gtrIowc1pX";
ssh.host_pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFw9NoRaYrM6LbDd3aFBc4yyBlxGQn8HjeHd/dZ3CfHk";
wg-home.pubkey = "17PMZssYi0D4t2d0vbmhjBKe1sGsE8kT8/dod0Q2CXc=";
wg-home.ip = "10.0.10.22";
lan-ip = "192.168.15.25";
};
sane.hosts.by-name."lappy" = {
ssh.user_pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDpmFdNSVPRol5hkbbCivRhyeENzb9HVyf9KutGLP2Zu";
ssh.host_pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILSJnqmVl9/SYQ0btvGb0REwwWY8wkdkGXQZfn/1geEc";
wg-home.pubkey = "FTUWGw2p4/cEcrrIE86PWVnqctbv8OYpw8Gt3+dC/lk=";
wg-home.ip = "10.0.10.20";
lan-ip = "192.168.15.13";
};
sane.hosts.by-name."moby" = {
ssh.user_pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICrR+gePnl0nV/vy7I5BzrGeyVL+9eOuXHU1yNE3uCwU";
ssh.host_pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO1N/IT3nQYUD+dBlU1sTEEVMxfOyMkrrDeyHcYgnJvw";
wg-home.pubkey = "I7XIR1hm8bIzAtcAvbhWOwIAabGkuEvbWH/3kyIB1yA=";
wg-home.ip = "10.0.10.48";
lan-ip = "192.168.15.28";
};
sane.hosts.by-name."servo" = {
ssh.user_pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPS1qFzKurAdB9blkWomq8gI1g0T3sTs9LsmFOj5VtqX";
ssh.host_pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOfdSmFkrVT6DhpgvFeQKm3Fh9VKZ9DbLYOPOJWYQ0E8";
wg-home.pubkey = "roAw+IUFVtdpCcqa4khB385Qcv9l5JAB//730tyK4Wk=";
wg-home.ip = "10.0.10.5";
wg-home.endpoint = "uninsane.org:51820";
lan-ip = "192.168.15.24";
};
};
}

View File

@@ -1,82 +0,0 @@
{ config, lib, pkgs, sane-lib, ... }:
let
inherit (lib) mkIf mkMerge mkOption types;
inherit (config.programs.ccache) cacheDir;
cfg = config.sane.roles.build-machine;
in
{
options.sane.roles.build-machine = {
enable = mkOption {
type = types.bool;
default = false;
};
emulation = mkOption {
type = types.bool;
default = true;
};
ccache = mkOption {
type = types.bool;
default = true;
};
};
config = mkMerge [
({
sane.programs.qemu = pkgs.qemu;
})
(mkIf cfg.enable {
# enable opt-in emulation of any package at runtime.
# i.e. `nix build '.#host-pkgs.moby.bash' ; qemu-aarch64 ./result/bin/bash`.
sane.programs.qemu.enableFor.user.colin = true;
# serve packages to other machines that ask for them
sane.services.nixserve.enable = true;
# enable cross compilation
# TODO: do this via stdenv injection, linking into /run/binfmt the stuff in <nixpkgs:nixos/modules/system/boot/binfmt.nix>
boot.binfmt.emulatedSystems = lib.optionals cfg.emulation [
"aarch64-linux"
# "aarch64-darwin" # not supported
# "x86_64-darwin" # not supported
];
# corresponds to env var: NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM=1
# nixpkgs.config.allowUnsupportedSystem = true;
})
(mkIf (cfg.enable && cfg.ccache) {
# programs.ccache.cacheDir = "/var/cache/ccache"; # nixos default
# programs.ccache.cacheDir = "/homeless-shelter/.ccache"; # ccache default (~/.ccache)
# if the cache doesn't reside at ~/.ccache, then CCACHE_DIR has to be set.
# we can do that manually as commented out below, or let nixos do it for us by telling it to use ccache on a dummy package:
programs.ccache.packageNames = [ "dummy-pkg-to-force-ccache-config" ];
# nixpkgs.overlays = [
# (self: super: {
# # XXX: if the cache resides not at ~/.ccache (i.e. /homeless-shelter/.ccache)
# # then we need to explicitly tell ccache where that is.
# ccacheWrapper = super.ccacheWrapper.override {
# extraConfig = ''
# export CCACHE_DIR="${cacheDir}"
# '';
# };
# })
# ];
# granular compilation cache
# docs: <https://nixos.wiki/wiki/CCache>
# investigate the cache with:
# - `nix-ccache --show-stats`
# - `build '.#ccache'
# - `sudo CCACHE_DIR=/var/cache/ccache ./result/bin/ccache --show-stats -v`
# TODO: whitelist `--verbose` in <nixpkgs:nixos/modules/programs/ccache.nix>
# TODO: configure without compression (leverage fs-level compression), and enable file-clone (i.e. hardlinks)
programs.ccache.enable = true;
nix.settings.extra-sandbox-paths = [ cacheDir ];
sane.persist.sys.plaintext = [
{ group = "nixbld"; mode = "0775"; directory = config.programs.ccache.cacheDir; }
];
sane.fs."${cacheDir}/ccache.conf" = sane-lib.fs.wantedText ''
max_size = 50G
'';
})
];
}

View File

@@ -1,18 +0,0 @@
{ config, lib, pkgs, ... }:
{
config = lib.mkIf config.sane.roles.client {
# persist external pairings by default
sane.persist.sys.plaintext = [ "/var/lib/bluetooth" ];
sane.fs."/var/lib/bluetooth".generated.acl.mode = "0700";
sane.fs."/var/lib/bluetooth/.secrets.stamp" = {
wantedBeforeBy = [ "bluetooth.service" ];
# XXX: install-bluetooth uses sed, but that's part of the default systemd unit path, it seems
generated.script.script = builtins.readFile ../../../../scripts/install-bluetooth + ''
touch "/var/lib/bluetooth/.secrets.stamp"
'';
generated.script.scriptArgs = [ "/run/secrets/bt" ];
};
};
}

View File

@@ -1,17 +0,0 @@
{ config, lib, ... }:
let
inherit (lib) mkIf mkOption types;
in
{
imports = [
./bluetooth-pairings.nix
./wifi-pairings.nix
];
# option is consumed by the other imports in this dir
options.sane.roles.client = mkOption {
type = types.bool;
default = false;
};
}

View File

@@ -1,15 +0,0 @@
{ config, lib, pkgs, ... }:
{
config = lib.mkIf config.sane.roles.client {
sane.fs."/var/lib/iwd/.secrets.psk.stamp" = {
wantedBeforeBy = [ "iwd.service" ];
generated.acl.mode = "0600";
# XXX: install-iwd uses sed, but that's part of the default systemd unit path, it seems
generated.script.script = builtins.readFile ../../../../scripts/install-iwd + ''
touch "/var/lib/iwd/.secrets.psk.stamp"
'';
generated.script.scriptArgs = [ "/run/secrets/iwd" "/var/lib/iwd" ];
};
};
}

View File

@@ -1,7 +0,0 @@
{ ... }:
{
imports = [
./build-machine.nix
./client
];
}

View File

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

View File

@@ -1,80 +0,0 @@
{ config, lib, pkgs, ... }:
let
inherit (builtins) filter map;
inherit (lib) concatMap mapAttrsToList mkIf mkMerge mkOption optionalAttrs types;
cfg = config.sane.services.wg-home;
server-cfg = config.sane.hosts.by-name."servo".wg-home;
mkPeer = { ips, pubkey, endpoint }: {
publicKey = pubkey;
allowedIPs = map (k: "${k}/32") ips;
} // (optionalAttrs (endpoint != null) {
inherit endpoint;
# send keepalives every 25 seconds to keep NAT routes live.
# only need to do this from client -> server though, i think.
persistentKeepalive = 25;
# allows wireguard to notice DNS/hostname changes, with this much effective TTL.
dynamicEndpointRefreshSeconds = 600;
});
# make separate peers to route each given host
mkClientPeers = hosts: map (p: mkPeer {
inherit (p) pubkey endpoint;
ips = [ p.ip ];
}) hosts;
# make a single peer which routes all the given hosts
mkServerPeer = hosts: mkPeer {
inherit (server-cfg) pubkey endpoint;
ips = map (h: h.ip) hosts;
};
in
{
options = {
sane.services.wg-home.enable = mkOption {
type = types.bool;
default = false;
};
sane.services.wg-home.ip = mkOption {
type = types.str;
};
};
config = mkIf cfg.enable {
# generate a (deterministic) wireguard private key
sane.derived-secrets."/run/wg-home.priv" = {
len = 32;
encoding = "base64";
};
# wireguard VPN which allows everything on my domain to speak to each other even when
# not behind a shared LAN.
# this config defines both the endpoint (server) and client configs
# for convenience, have both the server and client use the same port for their wireguard connections.
networking.firewall.allowedUDPPorts = [ 51820 ];
networking.wireguard.interfaces.wg-home = {
listenPort = 51820;
privateKeyFile = "/run/wg-home.priv";
preSetup =
let
gen-key = config.sane.fs."/run/wg-home.priv".unit;
in
"${pkgs.systemd}/bin/systemctl start '${gen-key}'";
ips = [
"${cfg.ip}/24"
];
peers =
let
all-peers = mapAttrsToList (_: hostcfg: hostcfg.wg-home) config.sane.hosts.by-name;
peer-list = filter (p: p.ip != null && p.ip != cfg.ip && p.pubkey != null) all-peers;
in
if cfg.ip == server-cfg.ip then
# if we're the server, then we maintain the entire client list
mkClientPeers peer-list
else
# but if we're a client, we maintain a single peer -- the server -- which does the actual routing
[ (mkServerPeer peer-list) ];
};
};
}

View File

@@ -1,30 +0,0 @@
# docs: <nixpkgs:nixos/modules/services/networking/yggdrasil.md>
# - or message CW/0x00
{ config, lib, ... }:
let
inherit (lib) mkIf mkOption types;
cfg = config.sane.yggdrasil;
in
{
options.sane.yggdrasil = {
enable = mkOption {
type = types.bool;
default = false;
};
};
config = mkIf cfg.enable {
services.yggdrasil = {
enable = true;
persistentKeys = true;
config = {
IFName = "ygg0";
Peers = [
"tls://longseason.1200bps.xyz:13122"
];
};
};
};
}

View File

@@ -1,4 +1,4 @@
{ pkgs, ... }:
{ config, pkgs, ... }:
{
imports = [
./fs.nix
@@ -7,8 +7,6 @@
boot.loader.generic-extlinux-compatible.enable = true;
boot.loader.efi.canTouchEfiVariables = false;
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
# sane.persist.enable = false; # TODO: disable (but run `nix flake check` to ensure it works!)
sane.nixcache.enable = false; # don't want to be calling out to dead machines that we're *trying* to rescue
# docs: https://nixos.org/manual/nixos/stable/options.html#opt-system.stateVersion
system.stateVersion = "21.05";

View File

@@ -1,35 +1,29 @@
{ config, pkgs, ... }:
{ pkgs, ... }:
{
imports = [
./fs.nix
./net.nix
./secrets.nix
./users.nix
./services
];
sane.programs = {
sane.packages.extraUserPkgs = [
# for administering services
freshrss.enableFor.user.colin = true;
matrix-synapse.enableFor.user.colin = true;
signaldctl.enableFor.user.colin = true;
};
sane.roles.build-machine.enable = true;
sane.roles.build-machine.emulation = false;
sane.zsh.showDeadlines = false; # ~/knowledge doesn't always exist
pkgs.matrix-synapse
pkgs.freshrss
];
sane.persist.enable = true;
sane.services.dyn-dns.enable = true;
sane.services.wg-home.enable = true;
sane.services.wg-home.ip = config.sane.hosts.by-name."servo".wg-home.ip;
# sane.services.duplicity.enable = true; # TODO: re-enable after HW upgrade
# automatically log in at the virtual consoles.
# using root here makes sure we always have an escape hatch
services.getty.autologinUser = "root";
boot.loader.efi.canTouchEfiVariables = false;
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
sops.secrets.duplicity_passphrase = {
sopsFile = ../../secrets/servo.yaml;
};
# both transmission and ipfs try to set different net defaults.
# we just use the most aggressive of the two here:
boot.kernel.sysctl = {

View File

@@ -52,18 +52,18 @@
# services.resolved.extraConfig = ''
# # docs: `man resolved.conf`
# # DNS servers to use via the `wg-ovpns` interface.
# # DNS servers to use via the `wg0` interface.
# # i hope that from the root ns, these aren't visible.
# DNS=46.227.67.134%wg-ovpns 192.165.9.158%wg-ovpns
# DNS=46.227.67.134%wg0 192.165.9.158%wg0
# FallbackDNS=1.1.1.1 9.9.9.9
# '';
# OVPN CONFIG (https://www.ovpn.com):
# DOCS: https://nixos.wiki/wiki/WireGuard
# if you `systemctl restart wireguard-wg-ovpns`, make sure to also restart any other services in `NetworkNamespacePath = .../ovpns`.
# if you `systemctl restart wireguard-wg0`, make sure to also restart any other services in `NetworkNamespacePath = .../ovpns`.
# TODO: why not create the namespace as a seperate operation (nix config for that?)
networking.wireguard.enable = true;
networking.wireguard.interfaces.wg-ovpns = let
networking.wireguard.interfaces.wg0 = let
ip = "${pkgs.iproute2}/bin/ip";
in-ns = "${ip} netns exec ovpns";
iptables = "${pkgs.iptables}/bin/iptables";
@@ -159,10 +159,13 @@
# create a new routing table that we can use to proxy traffic out of the root namespace
# through the ovpns namespace, and to the WAN via VPN.
networking.iproute2.rttablesExtraConfig = ''
5 ovpns
5 ovpns
'';
networking.iproute2.enable = true;
sops.secrets."wg_ovpns_privkey" = {
sopsFile = ../../secrets/servo.yaml;
};
# HURRICANE ELECTRIC CONFIG:
# networking.sits = {

View File

@@ -24,4 +24,8 @@ lib.mkIf false
OnUnitActiveSec = "10min";
};
};
sops.secrets."ddns_afraid" = {
sopsFile = ../../../secrets/servo.yaml;
};
}

View File

@@ -27,4 +27,8 @@ lib.mkIf false
OnUnitActiveSec = "10min";
};
};
sops.secrets."ddns_he" = {
sopsFile = ../../../secrets/servo.yaml;
};
}

View File

@@ -38,11 +38,11 @@
];
networking.firewall.allowedTCPPortRanges = [{
from = 49152; # TURN
to = 49408;
to = 65535;
}];
networking.firewall.allowedUDPPortRanges = [{
from = 49152; # TURN
to = 49408;
to = 65535;
}];
# provide access to certs

View File

@@ -11,7 +11,8 @@
{ config, lib, pkgs, sane-lib, ... }:
{
sops.secrets."freshrss_passwd" = {
sops.secrets.freshrss_passwd = {
sopsFile = ../../../secrets/servo.yaml;
owner = config.users.users.freshrss.name;
mode = "0400";
};
@@ -41,10 +42,7 @@
description = "import sane RSS feed list";
after = [ "freshrss-config.service" ];
script = ''
# easiest way to preserve feeds: delete the user, recreate it, import feeds
${pkgs.freshrss}/cli/delete-user.php --user colin || true
${pkgs.freshrss}/cli/create-user.php --user colin --password "$(cat ${config.services.freshrss.passwordFile})" || true
${pkgs.freshrss}/cli/import-for-user.php --user colin --filename ${opml}
${pkgs.freshrss}/cli/import-for-user.php --user admin --filename ${opml}
'';
};

View File

@@ -15,17 +15,6 @@
services.gitea.settings.session.COOKIE_SECURE = true;
# services.gitea.disableRegistration = true;
# gitea doesn't create the git user
users.users.git = {
description = "Gitea Service";
home = "/var/lib/gitea";
useDefaultShell = true;
group = "gitea";
isSystemUser = true;
# sendmail access (not 100% sure if this is necessary)
extraGroups = [ "postdrop" ];
};
services.gitea.settings = {
server = {
# options: "home", "explore", "organizations", "login" or URL fragment (or full URL)

View File

@@ -7,8 +7,8 @@
];
services.jackett.enable = true;
systemd.services.jackett.after = [ "wireguard-wg-ovpns.service" ];
systemd.services.jackett.partOf = [ "wireguard-wg-ovpns.service" ];
systemd.services.jackett.after = [ "wireguard-wg0.service" ];
systemd.services.jackett.partOf = [ "wireguard-wg0.service" ];
systemd.services.jackett.serviceConfig = {
# run this behind the OVPN static VPN
NetworkNamespacePath = "/run/netns/ovpns";

View File

@@ -0,0 +1,67 @@
{ config, lib, ... }:
# TODO: re-enable after migrating media dir to /var/lib/uninsane/media
# else it's too spammy
lib.mkIf false
{
networking.firewall.allowedUDPPorts = [
1900 7359 # DLNA: https://jellyfin.org/docs/general/networking/index.html
];
sane.persist.sys.plaintext = [
# TODO: mode? could be more granular
{ user = "jellyfin"; group = "jellyfin"; directory = "/var/lib/jellyfin"; }
];
# Jellyfin multimedia server
# this is mostly taken from the official jellfin.org docs
services.nginx.virtualHosts."jelly.uninsane.org" = {
addSSL = true;
enableACME = true;
# inherit kTLS;
locations."/" = {
proxyPass = "http://127.0.0.1:8096";
extraConfig = ''
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Forwarded-Host $http_host;
# Disable buffering when the nginx proxy gets very resource heavy upon streaming
proxy_buffering off;
'';
};
# locations."/web/" = {
# proxyPass = "http://127.0.0.1:8096/web/index.html";
# extraConfig = ''
# proxy_set_header Host $host;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header X-Forwarded-Proto $scheme;
# proxy_set_header X-Forwarded-Protocol $scheme;
# proxy_set_header X-Forwarded-Host $http_host;
# '';
# };
locations."/socket" = {
proxyPass = "http://127.0.0.1:8096";
extraConfig = ''
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Forwarded-Host $http_host;
'';
};
};
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."jelly" = "native";
services.jellyfin.enable = true;
}

View File

@@ -6,16 +6,20 @@
imports = [
./discord-puppet.nix
# ./irc.nix
# TODO(2023/03/10): disabled because it's not bridging and mautrix_signal is hogging CPU
# ./signal.nix
./signal.nix
];
services.matrix-appservices = {
# configure defaults. used by e.g. ./signal.nix
homeserverUrl = "http://127.0.0.1:8008";
homeserverDomain = "uninsane.org";
addRegistrationFiles = true;
};
sane.persist.sys.plaintext = [
{ user = "matrix-synapse"; group = "matrix-synapse"; directory = "/var/lib/matrix-synapse"; }
];
services.matrix-synapse.enable = true;
# this changes the default log level from INFO to WARN.
# maybe there's an easier way?
services.matrix-synapse.settings.log_config = ./synapse-log_level.yaml;
services.matrix-synapse.settings.server_name = "uninsane.org";
@@ -131,7 +135,8 @@
};
sops.secrets."matrix_synapse_secrets" = {
sops.secrets.matrix_synapse_secrets = {
sopsFile = ../../../../secrets/servo.yaml;
owner = config.users.users.matrix-synapse.name;
};
}

View File

@@ -43,7 +43,6 @@
};
};
# TODO: should use a dedicated user
systemd.services.mx-puppet-discord.serviceConfig = {
# fix up to not use /var/lib/private, but just /var/lib
DynamicUser = lib.mkForce false;

View File

@@ -0,0 +1,32 @@
{ ... }:
{
services.signald.enable = true;
# TODO: required?
# comes from <nix-matrix-appservices:examples/mautrix.nix>
systemd.services.matrix-as-signal = {
requires = [ "signald.service" ];
after = [ "signald.service" ];
unitConfig = {
JoinsNamespaceOf = "signald.service";
};
path = [
pkgs.ffmpeg # voice messages need `ffmpeg`
];
};
services.matrix-appservices.services.signal = {
port = 29184;
format = "mautrix-python";
package = pkgs.mautrix-signal;
serviceConfig = {
StateDirectory = [ "matrix-as-signal" "signald" ];
SupplementaryGroups = [ "signald" ];
};
settings.signal = {
socket_path = config.services.signald.socketPath;
outgoing_attachment_dir = "/var/lib/signald/tmp";
};
};
}

View File

@@ -1,8 +1,11 @@
{ lib, ... }:
{ ... }:
{
sane.persist.sys.plaintext = [
{ user = "navidrome"; group = "navidrome"; directory = "/var/lib/navidrome"; }
# TODO: we don't have a static user allocated for navidrome!
# the chown would happen too early for us to set static perms
"/var/lib/private/navidrome"
# { user = "navidrome"; group = "navidrome"; directory = "/var/lib/private/navidrome"; }
];
services.navidrome.enable = true;
services.navidrome.settings = {
@@ -15,20 +18,6 @@
ScanSchedule = "@every 1h";
};
systemd.services.navidrome.serviceConfig = {
# fix to use a normal user so we can configure perms correctly
DynamicUser = lib.mkForce false;
User = "navidrome";
Group = "navidrome";
};
users.groups.navidrome = {};
users.users.navidrome = {
group = "navidrome";
isSystemUser = true;
};
services.nginx.virtualHosts."music.uninsane.org" = {
forceSSL = true;
enableACME = true;

View File

@@ -17,5 +17,5 @@
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."nixcache" = "native";
sane.services.nixserve.enable = true;
sane.services.nixserve.sopsFile = ../../../../secrets/servo.yaml;
sane.services.nixserve.sopsFile = ../../../secrets/servo.yaml;
}

View File

@@ -111,7 +111,7 @@
''
];
systemd.services.pleroma.path = [
systemd.services.pleroma.path = [
# something inside pleroma invokes `sh` w/o specifying it by path, so this is needed to allow pleroma to start
pkgs.bash
# used by Pleroma to strip geo tags from uploads
@@ -135,11 +135,6 @@
# CapabilityBoundingSet = lib.mkForce "~";
# };
# this is required to allow pleroma to send email.
# raw `sendmail` works, but i think pleroma's passing it some funny flags or something, idk.
# hack to fix that.
users.users.pleroma.extraGroups = [ "postdrop" ];
# Pleroma server and web interface
# TODO: enable publog?
services.nginx.virtualHosts."fed.uninsane.org" = {
@@ -184,7 +179,8 @@
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."fed" = "native";
sops.secrets."pleroma_secrets" = {
sops.secrets.pleroma_secrets = {
sopsFile = ../../../secrets/servo.yaml;
owner = config.users.users.pleroma.name;
};
}

View File

@@ -1,6 +1,3 @@
# DOCS:
# - dovecot config: <https://doc.dovecot.org/configuration_manual/>
{ config, lib, ... }:
let
@@ -30,14 +27,11 @@ in
];
networking.firewall.allowedTCPPorts = [
# exposed over non-vpn imap.uninsane.org
143 # IMAP
993 # IMAPS
# exposed over vpn mx.uninsane.org
25 # SMTP
143 # IMAP
465 # SMTPS
587 # SMTPS/submission
993 # IMAPS
];
# exists only to manage certs for dovecot
@@ -65,7 +59,7 @@ in
# DKIM public key:
TXT."mx._domainkey" =
"v=DKIM1;k=rsa;p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCkSyMufc2KrRx3j17e/LyB+3eYSBRuEFT8PUka8EDX04QzCwDPdkwgnj3GNDvnB5Ktb05Cf2SJ/S1OLqNsINxJRWtkVfZd/C339KNh9wrukMKRKNELL9HLUw0bczOI4gKKFqyrRE9qm+4csCMAR79Te9FCjGV/jVnrkLdPT0GtFwIDAQAB"
"v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCkSyMufc2KrRx3j17e/LyB+3eYSBRuEFT8PUka8EDX04QzCwDPdkwgnj3GNDvnB5Ktb05Cf2SJ/S1OLqNsINxJRWtkVfZd/C339KNh9wrukMKRKNELL9HLUw0bczOI4gKKFqyrRE9qm+4csCMAR79Te9FCjGV/jVnrkLdPT0GtFwIDAQAB"
;
# DMARC fields <https://datatracker.ietf.org/doc/html/rfc7489>:
@@ -116,8 +110,8 @@ in
services.postfix.enableSubmissions = true;
services.postfix.submissionsOptions = submissionOptions;
systemd.services.postfix.after = [ "wireguard-wg-ovpns.service" ];
systemd.services.postfix.partOf = [ "wireguard-wg-ovpns.service" ];
systemd.services.postfix.after = [ "wireguard-wg0.service" ];
systemd.services.postfix.partOf = [ "wireguard-wg0.service" ];
systemd.services.postfix.serviceConfig = {
# run this behind the OVPN static VPN
NetworkNamespacePath = "/run/netns/ovpns";
@@ -138,8 +132,8 @@ in
# keeping this the same as the hostname seems simplest
services.opendkim.selector = "mx";
systemd.services.opendkim.after = [ "wireguard-wg-ovpns.service" ];
systemd.services.opendkim.partOf = [ "wireguard-wg-ovpns.service" ];
systemd.services.opendkim.after = [ "wireguard-wg0.service" ];
systemd.services.opendkim.partOf = [ "wireguard-wg0.service" ];
systemd.services.opendkim.serviceConfig = {
# run this behind the OVPN static VPN
NetworkNamespacePath = "/run/netns/ovpns";
@@ -149,25 +143,6 @@ in
# inspired by https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/
services.dovecot2.enable = true;
services.dovecot2.mailboxes = {
# special-purpose mailboxes: "All" "Archive" "Drafts" "Flagged" "Junk" "Sent" "Trash"
# RFC6154 describes these special mailboxes: https://www.ietf.org/rfc/rfc6154.html
# how these boxes are treated is 100% up to the client and server to decide.
# client behavior:
# iOS
# - Drafts: ?
# - Sent: works
# - Trash: works
# aerc
# - Drafts: works
# - Sent: works
# - Trash: no; deleted messages are actually deleted
# use `:move trash` instead
# Sent mailbox: all sent messages are copied to it. unclear if this happens server-side or client-side.
Drafts = { specialUse = "Drafts"; auto = "create"; };
Sent = { specialUse = "Sent"; auto = "create"; };
Trash = { specialUse = "Trash"; auto = "create"; };
};
services.dovecot2.sslServerCert = "/var/lib/acme/imap.uninsane.org/fullchain.pem";
services.dovecot2.sslServerKey = "/var/lib/acme/imap.uninsane.org/key.pem";
services.dovecot2.enablePAM = false;
@@ -222,7 +197,8 @@ in
# }
];
sops.secrets."dovecot_passwd" = {
sops.secrets.dovecot_passwd = {
sopsFile = ../../../secrets/servo.yaml;
owner = config.users.users.dovecot2.name;
# TODO: debug why mail can't be sent without this being world-readable
mode = "0444";

View File

@@ -40,8 +40,8 @@
# transmission will by default not allow the world to read its files.
services.transmission.downloadDirPermissions = "775";
systemd.services.transmission.after = [ "wireguard-wg-ovpns.service" ];
systemd.services.transmission.partOf = [ "wireguard-wg-ovpns.service" ];
systemd.services.transmission.after = [ "wireguard-wg0.service" ];
systemd.services.transmission.partOf = [ "wireguard-wg0.service" ];
systemd.services.transmission.serviceConfig = {
# run this behind the OVPN static VPN
NetworkNamespacePath = "/run/netns/ovpns";

View File

@@ -6,10 +6,9 @@
sane.services.trust-dns.listenAddrsIPv4 = [
# specify each address explicitly, instead of using "*".
# this ensures responses are sent from the address at which the request was received.
config.sane.hosts.by-name."servo".lan-ip
"192.168.0.5"
"10.0.1.5"
];
sane.services.trust-dns.quiet = true;
sane.services.trust-dns.zones."uninsane.org".TTL = 900;

View File

@@ -8,6 +8,7 @@ lib.mkIf false
{
sops.secrets."mediawiki_pw" = {
owner = config.users.users.mediawiki.name;
sopsFile = ../../../secrets/servo.yaml;
};
services.mediawiki.enable = true;

24
hosts/servo/users.nix Normal file
View File

@@ -0,0 +1,24 @@
{ config, ... }:
# installer docs: https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/profiles/installation-device.nix
{
# automatically log in at the virtual consoles.
# using root here makes sure we always have an escape hatch
services.getty.autologinUser = "root";
# gitea doesn't create the git user
users.users.git = {
description = "Gitea Service";
home = "/var/lib/gitea";
useDefaultShell = true;
group = "gitea";
isSystemUser = true;
# sendmail access (not 100% sure if this is necessary)
extraGroups = [ "postdrop" ];
};
# this is required to allow pleroma to send email.
# raw `sendmail` works, but i think pleroma's passing it some funny flags or something, idk.
# hack to fix that.
users.users.pleroma.extraGroups = [ "postdrop" ];
}

View File

@@ -1,21 +0,0 @@
{
"bozo": 0,
"content_length": 443732,
"content_type": "application/rss+xml; charset=utf-8",
"description": "Ben and David are joined by expert founders and investors \u2014 writing the next generation of great company stories in real-time.\n\nWe go behind the scenes on their journeys and bring back emerging insights and lessons that are useful for anyone in the tech and investing ecosystems.\n\nAcquired covers yesterday. ACQ2 covers tomorrow.",
"favicon": "",
"favicon_data_uri": "",
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 92,
"last_updated": "2023-03-02T17:03:15+00:00",
"score": 10,
"self_url": "https://acquiredlpbonussecretsecret.libsyn.com/",
"site_name": "ACQ2 by Acquired",
"site_url": "https://acquiredlpbonussecretsecret.libsyn.com",
"title": "ACQ2 by Acquired",
"url": "https://acquiredlpbonussecretsecret.libsyn.com",
"velocity": 0.057,
"version": "rss20"
}

View File

@@ -1,21 +0,0 @@
{
"bozo": 0,
"content_length": 208377,
"content_type": "application/xml; charset=utf-8",
"description": "applieddivinitystudies@gmail.com",
"favicon": "",
"favicon_data_uri": "",
"hubs": [],
"is_podcast": false,
"is_push": false,
"item_count": 20,
"last_updated": "2022-12-20T01:23:44.546000+00:00",
"score": 26,
"self_url": "https://applieddivinitystudies.com/atom.xml",
"site_name": "Applied Divinity Studies",
"site_url": "https://applieddivinitystudies.com",
"title": "Applied Divinity Studies",
"url": "https://applieddivinitystudies.com/atom.xml",
"velocity": 0.079,
"version": "atom10"
}

File diff suppressed because one or more lines are too long

View File

@@ -1,21 +0,0 @@
{
"bozo": 0,
"content_length": 19245,
"content_type": "text/xml; charset=utf-8",
"description": "Austin Vernon's Blog",
"favicon": "",
"favicon_data_uri": "",
"hubs": [],
"is_podcast": false,
"is_push": false,
"item_count": 42,
"last_updated": "2023-01-05T00:00:00+00:00",
"score": 24,
"self_url": "",
"site_name": "Austin Vernon - Austin Vernon's Blog",
"site_url": "https://austinvernon.site",
"title": "Austin Vernon",
"url": "https://austinvernon.site/rss.xml",
"velocity": 0.063,
"version": "rss20"
}

View File

@@ -1,21 +0,0 @@
{
"bozo": 0,
"content_length": 453506,
"content_type": "text/xml; charset=utf-8",
"description": "Balaji Srinivasan's personal blog. Formerly CTO of Coinbase and General Partner at a16z, @balajis is an investor and founder.",
"favicon": "",
"favicon_data_uri": "",
"hubs": [],
"is_podcast": false,
"is_push": false,
"item_count": 15,
"last_updated": "2022-04-28T18:22:11+00:00",
"score": 16,
"self_url": "https://balajis.com/rss/",
"site_name": "Balaji Srinivasan",
"site_url": "https://balajis.com",
"title": "Balaji Srinivasan",
"url": "https://balajis.com/rss/",
"velocity": 0.01,
"version": "rss20"
}

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