- new host `devbox`
- `flake-parts` module to manage agenix secrets
- Searx -> Google again 😩 (it was too slow)
- WIP `git-workspace` module for `home-manager`
- `cgit` module
- `spotify-adblocked` packaged
This commit is contained in:
Andrea Ciceri 2023-03-26 11:35:42 +02:00
parent 29bea282e7
commit 52298435cd
No known key found for this signature in database
23 changed files with 947 additions and 67 deletions

13
flake.lock generated
View file

@ -641,16 +641,17 @@
"kernel-src": { "kernel-src": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1678442395, "lastModified": 1676631659,
"narHash": "sha256-5q9ZqD+TQmLjKQI/sQetHHOgFRmwoNustb1I0M0f3ok=", "narHash": "sha256-TjAF7BPSDy5iHSk8byp+vsKop0V+rqrmr+TXLqXLB2M=",
"owner": "radxa", "owner": "radxa",
"repo": "kernel", "repo": "kernel",
"rev": "75f35d0549b7588cc561ed63b4246130c38a9c69", "rev": "a9583fb47e9b96c552f458a376207141602c0025",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "radxa", "owner": "radxa",
"repo": "kernel", "repo": "kernel",
"rev": "a9583fb47e9b96c552f458a376207141602c0025",
"type": "github" "type": "github"
} }
}, },
@ -1124,11 +1125,11 @@
"treefmt-nix": "treefmt-nix" "treefmt-nix": "treefmt-nix"
}, },
"locked": { "locked": {
"lastModified": 1678619682, "lastModified": 1679242046,
"narHash": "sha256-Om3Pe5Rss96jVh8Ncq72eFyu/ev8UO3iZZC8R0n2iAs=", "narHash": "sha256-CeGpTKnPQ++m11CV7Iisppwx+8fNwJSW8Q1ML6NxSJY=",
"owner": "aciceri", "owner": "aciceri",
"repo": "rock5b-nixos", "repo": "rock5b-nixos",
"rev": "ba79eb513a6db741b9c9d3b717ea5f7a36ff4812", "rev": "e1099dd4a6be8018a5cc489fb2ee1d50e4e285a0",
"type": "github" "type": "github"
}, },
"original": { "original": {

View file

@ -28,7 +28,7 @@
# fx_cast # TODO make PR to rycee NUR repo # fx_cast # TODO make PR to rycee NUR repo
]; ];
settings = { settings = {
"browser.startup.homepage" = "https://searx.be"; "browser.startup.homepage" = "https://google.com";
"browser.search.region" = "IT"; "browser.search.region" = "IT";
"browser.search.isUS" = false; "browser.search.isUS" = false;
"distribution.searchplugins.defaultLocale" = "it-IT"; "distribution.searchplugins.defaultLocale" = "it-IT";
@ -39,7 +39,7 @@
"browser.shell.checkDefaultBrowser" = false; "browser.shell.checkDefaultBrowser" = false;
}; };
search.force = true; search.force = true;
search.default = "Searx"; search.default = "Google";
search.engines = { search.engines = {
"Searx" = { "Searx" = {
urls = [ urls = [

View file

@ -0,0 +1,45 @@
{age, ...}: {
imports = [
./git-workspace-program.nix
./git-workspace-service.nix
];
programs.git-workspace.enable = true;
services.git-workspace = {
enable = true;
frequency = "04:00:00";
environmentFile = age.secrets.git-workspace-tokens.path;
workspaces = {
aciceri = {
provider = [
{
provider = "github";
name = "aciceri";
path = "/home/ccr/projects";
skips_forks = false;
}
];
};
mlabs = {
provider = [
{
provider = "github";
name = "mlabs-haskell";
path = "/home/ccr/projects";
skip_forks = false;
}
];
};
ethereansos = {
provider = [
{
provider = "github";
name = "EthereansOS";
path = "/home/ccr/projects";
skip_forks = false;
}
];
};
};
};
}

View file

@ -0,0 +1,20 @@
{
config,
lib,
pkgs,
...
}: let
cfg = config.programs.git-workspace;
in {
options.programs.git-workspace = {
enable = lib.mkEnableOption "git-workspace";
package = lib.mkOption {
type = lib.types.package;
default = pkgs.git-workspace;
description = "The git-workspace to use";
};
};
config = lib.mkIf cfg.enable {
home.packages = [pkgs.git-workspace];
};
}

View file

@ -0,0 +1,96 @@
{
config,
lib,
pkgs,
...
}: let
cfg = config.services.git-workspace;
tomlFormat = pkgs.formats.toml {};
in {
options.services.git-workspace = {
enable = lib.mkEnableOption "git-workspace systemd timer";
package = lib.mkOption {
type = lib.types.package;
default =
if config.programs.git-workspace.enable
then config.programs.git-workspace.package
else pkgs.git-workspace;
description = "The git-workspace to use";
};
frequency = lib.mkOption {
type = lib.types.str;
default = "";
description = "";
};
environmentFile = lib.mkOption {
type = lib.types.path;
default = "";
description = "";
example = "";
};
workspaces = lib.mkOption {
type = lib.types.attrsOf tomlFormat.type;
default = {};
description = "Workspaces verbatims";
# example = {
# workspace-foo = {
# provider = [
# {
# provider = "github";
# name = "";
# path = "...";
# skip_forks = false;
# }
# ];
# };
# };
};
};
config = lib.mkIf cfg.enable {
xdg.configFile =
lib.mapAttrs' (workspaceName: workspace: {
name = "git-workspace/${workspaceName}/workspace.toml";
value.source =
(tomlFormat.generate "${workspaceName}-workspace.toml" workspace).outPath;
})
cfg.workspaces;
systemd.user.services =
lib.mapAttrs' (workspaceName: workspace: rec {
name = "git-workspace-${workspaceName}-update";
value = {
Unit.Description = "Runs `git-workspace update` for ${workspaceName}";
Service = {
EnvironmentFile = cfg.environmentFile;
ExecStart = let
script = pkgs.writeShellApplication {
name = "${name}-launcher";
text = ''
${cfg.package}/bin/git-workspace \
--workspace ${config.xdg.configHome}/git-workspace/${workspaceName} \
update
'';
runtimeInputs = with pkgs; [busybox openssh git];
};
in "${script}/bin/${name}-launcher";
};
};
})
cfg.workspaces;
systemd.user.timers =
lib.mapAttrs' (workspaceName: workspace: {
name = "git-workspace-${workspaceName}-update";
value = {
Unit = {
Description = "Automatically runs `git-workspace update` for ${workspaceName}";
};
Timer = {
Unit = "git-workspace-${workspaceName}-update.unit";
OnCalendar = cfg.frequency;
Persistent = true;
};
Install.WantedBy = ["timers.target"];
};
})
cfg.workspaces;
};
}

View file

@ -14,13 +14,21 @@ in {
pull.rebase = false; pull.rebase = false;
rebase.autostash = true; rebase.autostash = true;
github.user = "aciceri"; github.user = "aciceri";
user.signingKey = "/home/ccr/.ssh/id_rsa";
gpg.format = "ssh";
commit.gpgsign = true;
}; };
userName = config.name; userName = config.name;
userEmail = config.email; userEmail = config.email;
signing = { # signing = {
signByDefault = true; # signByDefault = true;
key = config.email; # key = config.email;
# };
extraConfig.url = {
"ssh://git@github.com/" = {insteadOf = "https://github.com/";};
}; };
delta = { delta = {

View file

@ -0,0 +1,13 @@
{
programs.kitty = {
enable = true;
font = {
name = "Fira Code";
size = 12;
};
settings = {
disable_ligatures = "cursor";
confirm_os_window_close = 0;
};
};
}

View file

@ -0,0 +1,27 @@
{pkgs, ...}: let
spotify-adblock = pkgs.rustPlatform.buildRustPackage {
pname = "spotify-adblock";
version = "1.0.2";
src = pkgs.fetchFromGitHub {
owner = "abba23";
repo = "spotify-adblock";
rev = "v1.0.2";
sha256 = "YGD3ymBZ2yT3vrcPRS9YXcljGNczJ1vCvAXz/k16r9Y=";
};
cargoSha256 = "bYqkCooBfGeHZHl2/9Om+0qbudyOCzpvwMhy8QCsPRE=";
};
spotify-adblocked = pkgs.callPackage ./spotify-adblocked.nix {
inherit spotify-adblock;
};
# spotify-adblocked = pkgs.spotify.overrideAttrs (_: {
# preInstallPhase = ''
# ln -s ${spotify-adblock}/lib/libspotifyadblock.so $out/lib/spotify/
# # wrapProgram $out/bin/spotify \
# # --set LD_PRELOAD ${spotify-adblock}/lib/libspotifyadblock.so
# '';
# });
in {
home.packages = [spotify-adblocked];
}

View file

@ -0,0 +1,212 @@
{
fetchurl,
lib,
stdenv,
squashfsTools,
xorg,
alsa-lib,
makeWrapper,
wrapGAppsHook,
openssl,
freetype,
glib,
pango,
cairo,
atk,
gdk-pixbuf,
gtk3,
cups,
nspr,
nss,
libpng,
libnotify,
libgcrypt,
systemd,
fontconfig,
dbus,
expat,
ffmpeg,
curlWithGnuTls,
zlib,
gnome,
at-spi2-atk,
at-spi2-core,
libpulseaudio,
libdrm,
mesa,
libxkbcommon,
# High-DPI support: Spotify's --force-device-scale-factor argument
# not added if `null`, otherwise, should be a number.
deviceScaleFactor ? null,
spotify-adblock,
}: let
# TO UPDATE: just execute the ./update.sh script (won't do anything if there is no update)
# "rev" decides what is actually being downloaded
# If an update breaks things, one of those might have valuable info:
# https://aur.archlinux.org/packages/spotify/
# https://community.spotify.com/t5/Desktop-Linux
version = "1.1.84.716.gc5f8b819";
# To get the latest stable revision:
# curl -H 'X-Ubuntu-Series: 16' 'https://api.snapcraft.io/api/v1/snaps/details/spotify?channel=stable' | jq '.download_url,.version,.last_updated'
# To get general information:
# curl -H 'Snap-Device-Series: 16' 'https://api.snapcraft.io/v2/snaps/info/spotify' | jq '.'
# More examples of api usage:
# https://github.com/canonical-websites/snapcraft.io/blob/master/webapp/publisher/snaps/views.py
rev = "60";
deps = [
alsa-lib
at-spi2-atk
at-spi2-core
atk
cairo
cups
curlWithGnuTls
dbus
expat
ffmpeg
fontconfig
freetype
gdk-pixbuf
glib
gtk3
libdrm
libgcrypt
libnotify
libpng
libpulseaudio
libxkbcommon
mesa
nss
pango
stdenv.cc.cc
systemd
xorg.libICE
xorg.libSM
xorg.libX11
xorg.libxcb
xorg.libXcomposite
xorg.libXcursor
xorg.libXdamage
xorg.libXext
xorg.libXfixes
xorg.libXi
xorg.libXrandr
xorg.libXrender
xorg.libXScrnSaver
xorg.libxshmfence
xorg.libXtst
zlib
];
in
stdenv.mkDerivation {
pname = "spotify";
inherit version;
# fetch from snapcraft instead of the debian repository most repos fetch from.
# That is a bit more cumbersome. But the debian repository only keeps the last
# two versions, while snapcraft should provide versions indefinately:
# https://forum.snapcraft.io/t/how-can-a-developer-remove-her-his-app-from-snap-store/512
# This is the next-best thing, since we're not allowed to re-distribute
# spotify ourselves:
# https://community.spotify.com/t5/Desktop-Linux/Redistribute-Spotify-on-Linux-Distributions/td-p/1695334
src = fetchurl {
url = "https://api.snapcraft.io/api/v1/snaps/download/pOBIoZ2LrCB3rDohMxoYGnbN14EHOgD7_${rev}.snap";
sha512 = "1209b956822d8bb661daa2c88616bed403ec26dc22c6b866cecff59235c56112284c2f99aa06352fc0df6fcd15225a6ad60afd3b4ff4d7b948ab83e70ab31a71";
};
nativeBuildInputs = [makeWrapper wrapGAppsHook squashfsTools];
dontStrip = true;
dontPatchELF = true;
unpackPhase = ''
runHook preUnpack
unsquashfs "$src" '/usr/share/spotify' '/usr/bin/spotify' '/meta/snap.yaml'
cd squashfs-root
if ! grep -q 'grade: stable' meta/snap.yaml; then
# Unfortunately this check is not reliable: At the moment (2018-07-26) the
# latest version in the "edge" channel is also marked as stable.
echo "The snap package is marked as unstable:"
grep 'grade: ' meta/snap.yaml
echo "You probably chose the wrong revision."
exit 1
fi
if ! grep -q '${version}' meta/snap.yaml; then
echo "Package version differs from version found in snap metadata:"
grep 'version: ' meta/snap.yaml
echo "While the nix package specifies: ${version}."
echo "You probably chose the wrong revision or forgot to update the nix version."
exit 1
fi
runHook postUnpack
'';
# Prevent double wrapping
dontWrapGApps = true;
installPhase = ''
runHook preInstall
libdir=$out/lib/spotify
mkdir -p $libdir
mv ./usr/* $out/
cp meta/snap.yaml $out
# Work around Spotify referring to a specific minor version of
# OpenSSL.
ln -s ${lib.getLib openssl}/lib/libssl.so $libdir/libssl.so.1.0.0
ln -s ${lib.getLib openssl}/lib/libcrypto.so $libdir/libcrypto.so.1.0.0
ln -s ${nspr.out}/lib/libnspr4.so $libdir/libnspr4.so
ln -s ${nspr.out}/lib/libplc4.so $libdir/libplc4.so
ln -s ${ffmpeg.lib}/lib/libavcodec.so* $libdir
ln -s ${ffmpeg.lib}/lib/libavformat.so* $libdir
ln -s ${spotify-adblock}/lib/libspotifyadblock.so $libdir
rpath="$out/share/spotify:$libdir"
patchelf \
--interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
--set-rpath $rpath $out/share/spotify/spotify
librarypath="${lib.makeLibraryPath deps}:$libdir"
wrapProgram $out/share/spotify/spotify \
''${gappsWrapperArgs[@]} \
${lib.optionalString (deviceScaleFactor != null) ''
--add-flags "--force-device-scale-factor=${toString deviceScaleFactor}" \
''} \
--prefix LD_LIBRARY_PATH : "$librarypath" \
--prefix PATH : "${gnome.zenity}/bin"
# fix Icon line in the desktop file (#48062)
sed -i "s:^Icon=.*:Icon=spotify-client:" "$out/share/spotify/spotify.desktop"
# Desktop file
mkdir -p "$out/share/applications/"
cp "$out/share/spotify/spotify.desktop" "$out/share/applications/"
# Icons
for i in 16 22 24 32 48 64 128 256 512; do
ixi="$i"x"$i"
mkdir -p "$out/share/icons/hicolor/$ixi/apps"
ln -s "$out/share/spotify/icons/spotify-linux-$i.png" \
"$out/share/icons/hicolor/$ixi/apps/spotify-client.png"
done
runHook postInstall
'';
meta = with lib; {
homepage = "https://www.spotify.com/";
description = "Play music from the Spotify music service";
sourceProvenance = with sourceTypes; [binaryNativeCode];
license = licenses.unfree;
maintainers = with maintainers; [eelco ftrvxmtrx sheenobu mudri timokau ma27];
platforms = ["x86_64-linux"];
};
}

View file

@ -10,6 +10,7 @@
./gammastep.nix ./gammastep.nix
../foot ../foot
../alacritty ../alacritty
../kitty
]; ];
config = { config = {
home.packages = with pkgs; [wl-clipboard]; home.packages = with pkgs; [wl-clipboard];

View file

@ -21,8 +21,23 @@
}; };
secrets = lib.mkOption { secrets = lib.mkOption {
description = "List of secrets names in the `secrets` folder"; description = "List of secrets names in the `secrets` folder";
type = lib.types.listOf lib.types.str; type = lib.types.attrsOf (lib.types.submodule ({name, ...}: {
default = []; options = {
owner = lib.mkOption {
type = lib.types.str;
default = "root";
};
group = lib.mkOption {
type = lib.types.str;
default = "root";
};
file = lib.mkOption {
type = lib.types.path;
default = "${self.outPath}/secrets/${name}.age";
};
};
}));
default = {};
}; };
enableHomeManager = lib.mkOption { enableHomeManager = lib.mkOption {
description = "Enable home-manager module"; description = "Enable home-manager module";
@ -80,20 +95,38 @@
] ]
++ (lib.optionals (config.secrets != []) [ ++ (lib.optionals (config.secrets != []) [
inputs.agenix.nixosModules.default inputs.agenix.nixosModules.default
({lib, ...}: { ({lib, ...}: let
age.secrets = allSecrets = lib.mapAttrs' (name: value: {
name = lib.removeSuffix ".age" name;
inherit value;
}) (import "${self.outPath}/secrets");
filteredSecrets =
lib.filterAttrs lib.filterAttrs
(name: _: builtins.elem name config.secrets) (name: _: builtins.hasAttr name config.secrets)
(lib.mapAttrs' (name: _: { allSecrets;
name = lib.removeSuffix ".age" (builtins.baseNameOf name); in {
value.file = "${self.outPath}/${name}"; age.secrets =
}) (import "${self.outPath}/secrets")); lib.mapAttrs' (name: _: {
name = builtins.baseNameOf name;
value = {
inherit (config.secrets.${name}) owner group file;
};
})
filteredSecrets;
}) })
]) ])
++ (lib.optionals config.enableHomeManager [ ++ (lib.optionals config.enableHomeManager (let
user = config.extraHmModulesUser;
extraHmModules = config.extraHmModules;
in [
inputs.homeManager.nixosModule inputs.homeManager.nixosModule
{home-manager.users."${config.extraHmModulesUser}".imports = config.extraHmModules;} ({config, ...}: {
]) home-manager.users."${user}" = {
imports = extraHmModules;
_module.args.age = config.age or {};
};
})
]))
++ config.extraModules; ++ config.extraModules;
specialArgs = { specialArgs = {
fleetModules = builtins.map (moduleName: "${self.outPath}/modules/${moduleName}"); fleetModules = builtins.map (moduleName: "${self.outPath}/modules/${moduleName}");
@ -117,7 +150,6 @@
extraHmModules = [ extraHmModules = [
inputs.ccrEmacs.hmModules.default inputs.ccrEmacs.hmModules.default
]; ];
secrets = ["cachix"];
}; };
rock5b = { rock5b = {
system = "aarch64-linux"; system = "aarch64-linux";
@ -134,6 +166,15 @@
]; ];
}; };
hs = {}; hs = {};
devbox = {
extraModules = [inputs.disko.nixosModules.disko];
extraHmModules = [
inputs.ccrEmacs.hmModules.default
];
secrets = {
"git-workspace-tokens".owner = "ccr";
};
};
}; };
flake.nixosConfigurations = flake.nixosConfigurations =

68
hosts/devbox/default.nix Normal file
View file

@ -0,0 +1,68 @@
{
modulesPath,
fleetModules,
lib,
pkgs,
...
}: {
imports =
[
(modulesPath + "/installer/scan/not-detected.nix")
(modulesPath + "/profiles/qemu-guest.nix")
]
++ fleetModules [
"common"
"ssh"
"ccr"
"nix"
];
ccr = {
enable = true;
autologin = true;
modules = [
"emacs"
"git"
"gpg"
"helix"
"password-store"
"shell"
"xdg"
"git-workspace"
];
packages = with pkgs; [
comma
];
extraGroups = [
"wheel"
"fuse"
"video"
"networkmanager"
];
};
fonts = {
fonts = with pkgs; [powerline-fonts dejavu_fonts fira-code fira-code-symbols emacs-all-the-icons-fonts nerdfonts joypixels etBook];
fontconfig.defaultFonts = {
monospace = ["DejaVu Sans Mono for Powerline"];
sansSerif = ["DejaVu Sans"];
serif = ["DejaVu Serif"];
};
};
nixpkgs.config.joypixels.acceptLicense = true;
environment.systemPackages = with pkgs; [waypipe firefox];
programs.mosh.enable = true;
disko.devices = import ./disko.nix {
inherit lib;
};
boot.loader.grub = {
devices = ["/dev/sda"];
efiSupport = true;
efiInstallAsRemovable = true;
};
}

79
hosts/devbox/disko.nix Normal file
View file

@ -0,0 +1,79 @@
# Example to create a bios compatible gpt partition
{
lib,
disks ? ["/dev/sda"],
...
}: {
disk = lib.genAttrs disks (dev: {
device = dev;
type = "disk";
content = {
type = "table";
format = "gpt";
partitions = [
{
name = "boot";
type = "partition";
start = "0";
end = "1M";
part-type = "primary";
flags = ["bios_grub"];
}
{
type = "partition";
name = "ESP";
start = "1MiB";
end = "100MiB";
bootable = true;
content = {
type = "mdraid";
name = "boot";
};
}
{
name = "root";
type = "partition";
start = "100MiB";
end = "100%";
part-type = "primary";
bootable = true;
content = {
type = "lvm_pv";
vg = "pool";
};
}
];
};
});
mdadm = {
boot = {
type = "mdadm";
level = 1;
metadata = "1.0";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
};
};
};
lvm_vg = {
pool = {
type = "lvm_vg";
lvs = {
root = {
type = "lvm_lv";
size = "100%FREE";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/";
mountOptions = [
"defaults"
];
};
};
};
};
};
}

View file

@ -14,17 +14,33 @@
"common" "common"
"ssh" "ssh"
"ccr" "ccr"
"cgit"
]); ]);
ccr.enable = true; ccr.enable = true;
# programs.sway.enable = true;
services.rock5b-fan-control.enable = true; services.rock5b-fan-control.enable = true;
# nixpkgs.config.permittedInsecurePackages = [ services.nginx.enable = true;
# "libav-11.12" services.nginx.virtualHosts."localhost" = {
# ]; cgit = {
enable = true;
virtual-root = "/";
include = [
(builtins.toFile "cgitrc-extra-1" ''
repo.url=test-repo.git
repo.path=/srv/git/test-repo.
repo.desc=the master foo repository
repo.owner=fooman@example.com
css=/custom.css
'')
(builtins.toFile "cgitrc-extra-2" ''
# Allow http transport git clone
enable-http-clone=1
'')
];
};
};
fileSystems."/mnt/film" = { fileSystems."/mnt/film" = {
device = "//ccr.ydns.eu/film"; device = "//ccr.ydns.eu/film";
@ -58,6 +74,18 @@
extraGroups = ["video" "input"]; extraGroups = ["video" "input"];
}; };
networking.firewall.allowedTCPPorts = [
8080 # kodi control
80
];
programs.bash.loginShellInit = ''
[[ "$(tty)" == '/dev/tty1' ]] && \
[[ "$(whoami)" == 'kodi' ]] && \
${pkgs.kodi-rock5b}/bin/kodi-standalone
'';
# Waiting for https://github.com/NixOS/nixpkgs/issues/140304 # Waiting for https://github.com/NixOS/nixpkgs/issues/140304
services.getty = let services.getty = let
script = pkgs.writeText "login-program.sh" '' script = pkgs.writeText "login-program.sh" ''

View file

@ -60,6 +60,7 @@
"zathura" "zathura"
"chrome" "chrome"
"obs-studio" "obs-studio"
"spotify"
]; ];
packages = with pkgs; [ packages = with pkgs; [
comma comma

86
modules/cgit/custom.css Normal file
View file

@ -0,0 +1,86 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
@import url("cgit.css");
* { line-height: 1.25em; }
div#cgit {
max-width: 117ch;
margin: auto;
font-family: monospace;
-moz-tab-size: 4;
tab-size: 4;
}
div#cgit table#header td.sub {
border-top: none;
}
div#cgit table#header td.sub.right {
padding-right: 1em;
}
div#cgit table.tabs {
border-bottom: none;
}
div#cgit div.content {
border-bottom: none;
}
div#cgit table.list th a {
color: inherit;
}
div#cgit table.list tr:nth-child(even) {
background: inherit;
}
div#cgit table.list tr:hover {
background: inherit;
}
div#cgit table.list tr.nohover-highlight:hover:nth-child(even) {
background: inherit;
}
div#cgit table.blob td.linenumbers a:target {
color: goldenrod;
text-decoration: underline;
outline: none;
}
div#cgit div#summary {
max-width: 80ch;
}
/* for hilex(1) */
div#cgit pre .Ke { color: dimgray; }
div#cgit pre .Ma { color: green; }
div#cgit pre .Co { color: navy; }
div#cgit pre .St { color: teal; }
div#cgit pre .Fo { color: teal; font-weight: bold; }
div#cgit pre .Su { color: olive; }
/* for htagml(1) */
div#cgit pre a.tag { color: inherit; text-decoration: underline; }
div#cgit pre a.tag:target { color: goldenrod; outline: none; }
/* for mandoc(1) */
table.head, table.foot { width: 100%; }
td.head-rtitle, td.foot-os { text-align: right; }
td.head-vol { text-align: center; }
div.Pp { margin: 1ex 0ex; }
div.Nd, div.Bf, div.Op { display: inline; }
span.Pa, span.Ad { font-style: italic; }
span.Ms { font-weight: bold; }
dl.Bl-diag > dt { font-weight: bold; }
code.Nm, code.Fl, code.Cm, code.Ic, code.In, code.Fd, code.Fn,
code.Cd { font-weight: bold; font-family: inherit; }
h1.Sh { font-size: 1.5em; }
table.Nm td:first-child { padding-right: 1ch; }
code.Fl { white-space: nowrap; }
span.RsT { font-style: italic; }
dl.Bl-tag:not(.Bl-compact) > dt { margin-top: 1em; }
ul.Bl-bullet:not(.Bl-compact) > li { margin-top: 1em; }
div.Bd-indent { margin-left: 4ch; }
table.Bl-column { width: 100%; }
table.foot { margin-top: 1em; }
div#cgit a.permalink { color: inherit; }

133
modules/cgit/default.nix Normal file
View file

@ -0,0 +1,133 @@
{
config,
lib,
pkgs,
...
}:
with lib; let
globalConfig = config;
settingsFormat = {
type = with lib.types; let
value =
oneOf [int str]
// {
description = "INI-like atom (int or string)";
};
values =
coercedTo value lib.singleton (listOf value)
// {
description = value.description + " or a list of them for duplicate keys";
};
in
attrsOf values;
generate = name: values:
pkgs.writeText name (lib.generators.toKeyValue {listsAsDuplicateKeys = true;} values);
};
in {
options.services.nginx.virtualHosts = mkOption {
type = types.attrsOf (types.submodule ({config, ...}: let
cfg = config.cgit;
# These are the global options for this submodule, but for nicer UX they
# are inlined into the freeform settings. Hence they MUST NOT INTERSECT
# with any settings from cgitrc!
options = {
enable = mkEnableOption "cgit";
location = mkOption {
default = "/";
type = types.str;
description = ''
Location to serve cgit on.
'';
};
};
# Remove the global options for serialization into cgitrc
settings = removeAttrs cfg (attrNames options);
in {
options.cgit = mkOption {
type = types.submodule {
freeformType = settingsFormat.type;
inherit options;
config = {
css = mkDefault "/cgit.css";
logo = mkDefault "/cgit.png";
favicon = mkDefault "/favicon.ico";
};
};
default = {};
example = literalExample ''
{
enable = true;
virtual-root = "/";
source-filter = "''${pkgs.cgit-pink}/lib/cgit/filters/syntax-highlighting.py";
about-filter = "''${pkgs.cgit-pink}/lib/cgit/filters/about-formatting.sh";
cache-size = 1000;
scan-path = "/srv/git";
include = [
(builtins.toFile "cgitrc-extra-1" '''
# Anything that has to be in a particular order
''')
(builtins.toFile "cgitrc-extra-2" '''
# Anything that has to be in a particular order
''')
];
}
'';
description = ''
Verbatim contents of the cgit runtime configuration file. Documentation
(with cgitrc example file) is available in "man cgitrc". Or online:
http://git.zx2c4.com/cgit/tree/cgitrc.5.txt
'';
};
config = let
location = removeSuffix "/" cfg.location;
in
mkIf cfg.enable {
locations."${location}/" = {
root = "${pkgs.cgit-pink}/cgit/";
tryFiles = "$uri @cgit";
};
locations."~ ^${location}/(cgit.(css|png)|favicon.ico|robots.txt)$" = {
alias = "${pkgs.cgit-pink}/cgit/$1";
};
locations."~ ^${location}/custom.css$" = {
alias = ./custom.css;
};
locations."@cgit" = {
extraConfig =
''
include ${pkgs.nginx}/conf/fastcgi_params;
fastcgi_param CGIT_CONFIG ${settingsFormat.generate "cgitrc" settings};
fastcgi_param SCRIPT_FILENAME ${pkgs.cgit-pink}/cgit/cgit.cgi;
fastcgi_param QUERY_STRING $args;
fastcgi_param HTTP_HOST $server_name;
fastcgi_pass unix:${globalConfig.services.fcgiwrap.socketAddress};
''
+ (
if cfg.location == "/"
then ''
fastcgi_param PATH_INFO $uri;
''
else ''
fastcgi_split_path_info ^(${location}/)(/?.+)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
''
);
};
};
}));
};
config = let
vhosts = config.services.nginx.virtualHosts;
in
mkIf (any (name: vhosts.${name}.cgit.enable) (attrNames vhosts)) {
# make the cgitrc manpage available
environment.systemPackages = [pkgs.cgit-pink];
services.fcgiwrap.enable = true;
};
}

View file

@ -1,19 +1,17 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-rsa QHr3/A -> ssh-rsa QHr3/A
htmJ7Ita9rp1TshaeTq14G7Z8vUmsHG8cvcbiT+X7acGx/W79zUjM0r1KiBwyD75 mkKvIOoT0dIym2TcQCRk+QALX+gUo2HqahYwMbuJbfbUAyoB3rG9ccgwoVr7R+Iu
SqLMhlLylaPCf7wjoL800UZ/nlQsXCCOgETKFbJH7jJIJhsYIzWOWwVScXjRNRqY KJazZredX8SBnA8X2V6J9GIT4xkShAM5JZ4g8BLclKFqPXmSXzNh26Kxli7upt15
xp1Y+TTnyao0gzTv2uFJy2w2cg2VM+f+UXOeoQ6gUGxFHvwsuRDorXu2n/JHXh/R h5hmGejDJ3jdPU7UTfxv0g8EnXbvEBdP5C0B4nKex11d0ZBceCZmsXDTj+c9Y6f6
kiNZGBi9tx93F3jAsHM6Sudq7j1HsJwQZO6vaHwuqxankHX5CpXXo8bHY1pE+smG gf7tveLqLk1bj0gyKA3KHpUz+yj2dN5AFyME55bcISqoNMmXIX9Iu1JygF9LG8CL
yO92qJ4cxSB/A9T2PXr20EDmj1Nr4pbk12Tn69GZasSKAlyUo0SDUW6BVFHwDf8E EC6/dcSGe5FPjTFeJmmvjq8+adJ1oGsmH1UUwkDSMbpAWVMGwqZbiwIjcvsfx95i
L3K6XKyGuUcZsd5Hh26deT7kAYwUbD5Edlyhgc8Rp9/rX2qEG5i196/tLL0ngI4G KGYlNOcuLXxh9eWpXqQBGt3u5dAN3tHq8xU3D0pDefRU/bnIImYOpW1p2P12O7L6
xoHwHhnVUC0IULOizzPbxtnat1cCIhcSbncKv6wnBnlXHDivJV8Vg0YGnzmYy0j8 ntmFhOehI5dj4awLV9agKEst7GsiqFkODFELV+rOA+4pJnkKwY/GEdyJF4SmpBPE
TbVN76OsNrU8zXXTGjLO6Gp+AEPIk5Z72Snpoq5Io4H+IoNuX0hYGbMrPQg0Urnn bFwOlPaw5DH4JWrEZBF0CCidPHME6eXXkPPfsRyjLq8cS2e+iVie+bokfC5VrMpV
gM2/EN2ivCKfMMNWI6sq0FJy4IsGNsVLM98VmAh9pfWXGFjz3So9cYMwYCqG0vbP 3g1PVYKi1dhZ+lFKaL8fcMx/AHXAfPsCFFJAO7idfhNqEh3RhOPTwQu6tbffA+gT
HQQKqsmxbdJljxGix7Z5SpIl6bDuS66hJpEA6wlvGcUmXzy+kFnlTNmmFwovfotX qTsK830hTkMDIkk3u6U/eBDLJ6QUsmsl7S/8lzpnC22XIIRckgPQPZo7Lj0TlCUf
wIPYTJZGtXh0WNsIuVnPYSZ6MahBswKzHcI+az48PvM RRCXX7bxvrv941wlgiLEvHzIJhy2IkyNx2fVrizj/8Q
-> u!n2o-grease -> 0\@ek*.D-grease Kr #fh S|97g@0K N?M2
+fY6SvlSCYFsB0/7dxDJtw7zKufZ9LZUZ7tqVaJkdjSl9y/2fDGVQHFKFXBGhHKu JzOV6h/q
wcIB --- u1h801vplfmXhMJ8qkpD+XTyI9TwY1XjQcGMJqTl6YU
--- hBiR9gBibjABVhE5I42l1zepYvWZq3qsqXk9Y8qlTno bô°-² •³Ùo±ž}1§³<C2A7>ÐåoÉÚBi%w Dwà&J
ýò蹿\Ѓ-
(>2ðA…½™ä^­ l[CPW@•Ï›¹¸µdj

Binary file not shown.

View file

@ -1,9 +1,11 @@
let let
keys = { users.ccr = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC5cEUx25pnZiH3eBrE2xNbJ92gJiKSznDUNRzcEL4ti6FlJm+75p4q0hgdqHwStR8+uCWBL6viVFCGutOVMFE5MX1Oc3A8fJdR6H9Rrwvk/1UQzqzc9tWxw1qPLKz+fnPDomjOvNofghCWQRwX3Xf1HnIqvRwELpNbR9i+/cHkDGzLJxkstbt4gol8ywMPkw02QdKk8s5MEd1vawxc+7Chs0JPW57RDqDYFErYys52JLeAViCBB9bofF+KT42LuRXKSjWlvCV9kR5TL49vUeBgzMQWMh++WQdN4m9lpqFqYyc75I49/E0HGf8LChDSS+hvRnb5MbtnVGjEA4WDHyldmJCvUNob5CUo4FjoSPRi+S/J3Ads8D4JVwaJOJEVqmMKEhiQ0Hzk4hwe3eV/VumlZj4U/QjaCrqqi4TW/iP0gNRfzcfiM+G/z5R7w1NMUpTX7oilyKjMQmGnXB857D3SSptS7dwh5OiKhVmrQMRCduooUsj236abqLU28K//RnxhOgh8kDGgoUHApnTiMZNKhgLiR42lKrubNcW1tAAqoNyFLMwwXeMLjh0iP1b5y8ntfNPNIcGb7vcwpS24z/aIjW7rQ4J7x5EBphHGhys6ne+irdhOM8c7kFr+c8+Q2oU0YAtFuMYztAFOHm1e20X00Zvys2nuee+hT9F1NungAQ==";
agenix = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC5cEUx25pnZiH3eBrE2xNbJ92gJiKSznDUNRzcEL4ti6FlJm+75p4q0hgdqHwStR8+uCWBL6viVFCGutOVMFE5MX1Oc3A8fJdR6H9Rrwvk/1UQzqzc9tWxw1qPLKz+fnPDomjOvNofghCWQRwX3Xf1HnIqvRwELpNbR9i+/cHkDGzLJxkstbt4gol8ywMPkw02QdKk8s5MEd1vawxc+7Chs0JPW57RDqDYFErYys52JLeAViCBB9bofF+KT42LuRXKSjWlvCV9kR5TL49vUeBgzMQWMh++WQdN4m9lpqFqYyc75I49/E0HGf8LChDSS+hvRnb5MbtnVGjEA4WDHyldmJCvUNob5CUo4FjoSPRi+S/J3Ads8D4JVwaJOJEVqmMKEhiQ0Hzk4hwe3eV/VumlZj4U/QjaCrqqi4TW/iP0gNRfzcfiM+G/z5R7w1NMUpTX7oilyKjMQmGnXB857D3SSptS7dwh5OiKhVmrQMRCduooUsj236abqLU28K//RnxhOgh8kDGgoUHApnTiMZNKhgLiR42lKrubNcW1tAAqoNyFLMwwXeMLjh0iP1b5y8ntfNPNIcGb7vcwpS24z/aIjW7rQ4J7x5EBphHGhys6ne+irdhOM8c7kFr+c8+Q2oU0YAtFuMYztAFOHm1e20X00Zvys2nuee+hT9F1NungAQ=="; hosts = {
test = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHc46mGCuaKLwNzK/abuedYQLw9h/Cp5MhVb7IHTGh0E root@test";
}; };
in { in {
"secrets/cachix.age".publicKeys = [keys.agenix]; "cachix.age".publicKeys = [users.ccr];
"secrets/autistici-password.age".publicKeys = [keys.agenix]; "autistici-password.age".publicKeys = [users.ccr];
"secrets/magit-forge-github-token.age".publicKeys = [keys.agenix]; "magit-forge-github-token.age".publicKeys = [users.ccr];
"git-workspace-tokens.age".publicKeys = [users.ccr hosts.test];
} }

View file

@ -0,0 +1,20 @@
age-encryption.org/v1
-> ssh-rsa QHr3/A
keGOWcWTGA2ddugZLX3ZXs4V7vsEMYv3SNSFlgvqjiJx0dzUQCCrp5FE2v+uXwjp
MQegxCuveBiHK4ea5eogCt9ZTAzkvbV8J3NAxYqyGs/sOjbArluqUkRzJ+mV1L5f
m9iu5s1eyViesiRT7mt9dI7JvZGfbxbroZcXBDDjxqcbrOyzqhnRhSH4FhYXMITa
63fIeqgXNpdy6XnwFS8q0nQoECboKdWHPRvRJlJ86ysBhI3QwZRwjG+v14XpsE4e
6meFszkX0A+gg//qOe02TTSoMNexupdVj4mSrola5HFkiOfLAJIS+51L+g3Rs7ZN
scvjnxlv7nF/4K/s0ksFs8gpDjWzY0VVdhbY3ZBJQCanF/LBtol/5WttCRHXS+/R
be+Ak/j8NpZJcHgCJkXinA9y0fsEKb2YngX4klnemGQ12an15cfV8B4V1GON1Brz
Bro7Z3cvxaHhXWI3VlsbFXlffJgEz+rF434z9u7mYlCjkt0wJAHMZkBqn/Ecu7wE
6b4qrmI3VdsDCNp4fMVLvgfdAyzl5kfzqDPJRKBhXYyO51dK6wKy3j4hT5v4ahyK
2TpRwVebmrmE2jIEU+X0QX4mw76f5oZ0AArUO1XZT2oiT7bW0MFWiqT526xok7sa
ZPZZTEMeuNNn7GQscknt3mTYfrwSPwCNH5YcTXUsINc
-> ssh-ed25519 zco92w YYlPbyyNNzbqwHrvB4K/S6pSXF19FgBMLa7YPwLURlA
1lAiYKEGBuPeNEpE75tcrsf6mzTj0UB+rH15L2LfeN8
-> s)xdR|-grease M
uVmULVxzGAPmPwQyi+DMLt9YXIhj5nLW6ox/cDQiJ0r9P1KecouXQPU
--- MU/ggSTGHLbNDds2mBqI99xf68ab3vI5C3r8wZFhNMM
¨˜]úF„Ò=w0£1˜ìÑäSS±7Šf®€ÎtÕR9_ùz»
K¾ÔŸaáÔWíãy¹üÙ?8a ¶F!¨<>âC(k&Ÿ™Þ'Q±<51>~áX

Binary file not shown.

View file

@ -1,18 +1,19 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-rsa QHr3/A -> ssh-rsa QHr3/A
minytBGD5mhGlZVBUiHlTCKgR/IQBa5CLqr49w39AM8fjjJtj19UryLyoA1Jouef qcb2b07+fqMtxbC9ij/OV7HeQqQ7NGTVx2qN6UPqkbcSx4FU9RoHVdRvyhj4gOcz
GKRU+uR16Lj9MjdqJhcGi7Ox7/L+Si/eh5M5y08G0M8bod6VTyezbjWjbKTeoY68 R1lC2li0gsoijTnSlpJNdJALk/BBFKMNtMDhI4zeEivVhRuPg2cXpf4q41eL+FK+
72Iz20s254jP75jhlyekL/rTQJR9aeQiDsVXBr02wu8ICC+eESfTiq8Srwwaq3Gr UIovBdx+xTOaSvWtz4QzWMaGaREUTLlg7IS+OjVh9p6LgXpn5I5L4vQ8P4n8JGRb
H/rfHO2/vqrA+NYSI9I+1fCYp+8YLSIAMmDI4jjrC/d3RQhDkiqhn2uvslV5UiqH cNsXIVKJ5KMOzoj+UZCJ4ltfd4kUPmETSXMCtu2qEIsV9hF6T1yeImGXZW2tgNHC
yBcfIEz7CSNdJp5KfF/Qw2BgepkMibYj+iKZ9zfYZJQyQy8FCEXfx+BwwjdEPadk WobMSm7Au0l5w2NQDwgEQnEE9BAFhsxZpM1nSC80vh5q9EHwvRkAOZT2l7MAp+7l
0lOmatm1UmR8BAl0LCof7VxwsEbTeQHuz/FX/kfadlxNSUYF0bkVBNWHsLG1YP6Y yKhbF4yN5dM7Xf4SqXY89YeSU2uZ52AwPam54+MRyeLfc2qS9zjGaFo1+7SFjA5W
JBzFiBA5Wy8qEUHIeKmVP70moVohURiTliV8mN1dL490ns+kgpBPjQm+ThJGXyCE dHbFBEXOjAJinVNgNGs9r4ot1CAZFym3nUhvbET8Cqirl9w71vObw6KqwWM04xTH
ibx6j8AmGxMXoykBIFYxi3HvSJm5CKhUahBCHLlTdcUoGqDMz6ZS0Ys6ojW6iMEu IXhUo2xbCObuPTkohoUg/P/EFyBrg6PBnUDW4lCx6Wi20SEoQo4KnimQHYZnSC7Q
VfI1ZeHScnFKmR7Y237i5ZRYl4wUD7tjBSHl+7T1UsHUyg6Vymop6tiR+TYp0Jwp UOk+Y/dwF+rRJcJ4BkbKJuieFlmHYIlNMbmpDz4ufsOSl9sL5Sop+28uLDee5llh
j+1V4irQ5PVbULWW5IYEDzyeggiUUarWXJQiIhZvR+w5IQGK0OpigWqlzZz/OJ9N zcNe+S7mpHdHVjqc5S9CXsReqVxzqnv6igaOcAm704W6WeytJx7u3kwu3vaoDTY4
8VyiKhr1/Q7Lbxvt3aF/gudZG9HeDVAnXTLSxF/HfWs 5m9Oag936EuBHdsyyR+f7X3OsCsF46/iP0OEDEePkdo
-> k04\pIXA-grease !~)DrR 8gGWs" % -> e<IGP-grease c~E86 U;yv[9P <P#!* ?/Biih
bWx1d5LHHOqqMjp9oLbsWfuSmojeftp2Cm9gfvf78lbLFfamqVRJDZiqwCOBF8Zx Pg1N0kZq3b89Y93q0RJ9R7hiM880fSgwu+Vc4zrgMZTTJhbB0iR5LCrogXdljD7u
haDVCJPzlTbXJ7dJ3A jJ8W2inmVPXz4Fby7Ns3lc7rtsfui1hg0b8ATmfVsttMOGUdGHEkUS4fbm0Fnk5V
--- Oj+guFcy4YP1C3mhTRK7WIogGKH1PH06Ppc+MqT6dV0 Fg
cp·±ÑÊ ÍƒlI†ÁFÀ<>êamT§äõèöµ 5¬¹õÿl½É“! ©`Ykg4p¹Ø5f¹p£RÕ0|<7C>] --- pDXiZDwMRH8NQ2xxSYf32kKX49fn1PuDDDU5SS7Xm9A
+JU”6[':zäñÙ™1£M•èS`îÝ=ܬuK3a×ÒqSÀM;ZõZ;NÀ}ö§zÈãsXdÁ° 6ã£,(œAÖ_?{á