feat: add Git-annex module
This commit is contained in:
@@ -169,9 +169,9 @@ A bit on the nose for a transfemme into computers, but my chosen name is also Ma
|
||||
|
||||
Used as a server admin account with little configuration.
|
||||
|
||||
** escort
|
||||
** public
|
||||
|
||||
Another low-config user for "escorting" people to system services that require a user, e.g. logging in for file-sharing.
|
||||
Another low-config, low-permission user for access to public resources.
|
||||
|
||||
* ~sydnix-cli~
|
||||
|
||||
@@ -535,3 +535,4 @@ Following is a subset of the many places I've learnt from.
|
||||
- [[https://prelude.emacsredux.com/en/stable/][Emacs Prelude]]
|
||||
- [[https://github.com/doomemacs/doomemacs][Doom Emacs]]
|
||||
- [[https://cce.whatthefuck.computer/cce][Ryan Rix's Complete Computing Environment]]
|
||||
- [cite:@wünsch2024setting]
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
users.users = [
|
||||
"lain"
|
||||
"escort"
|
||||
"public"
|
||||
];
|
||||
|
||||
impermanence = {
|
||||
@@ -37,15 +37,29 @@
|
||||
keyFile = "/persist/vault/root/deertopia-key";
|
||||
};
|
||||
|
||||
git-annex = {
|
||||
enable = true;
|
||||
user.name = "annex";
|
||||
user.email = "annex@deertopia.net";
|
||||
keyFiles = [ ../../public-keys/crumb-at-guix-rebound.pub ];
|
||||
repos = {
|
||||
"/persist/deertopia.net/dav/org" = {
|
||||
managed = true;
|
||||
remotes = {
|
||||
"guix-rebound" = "crumb@guix-rebound:/tmp/org";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
deertopia = {
|
||||
nginx.enable = true;
|
||||
git-annex.enable = true;
|
||||
webdav.enable = true;
|
||||
|
||||
# A simple default webpage. This should probably live somewhere else.
|
||||
nginx.vhosts."www" = {
|
||||
vhostName = "deertopia.net";
|
||||
vhost = {
|
||||
# addSSL = true;
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.sydnix.deertopia.git-annex;
|
||||
in
|
||||
{
|
||||
options.sydnix.deertopia.git-annex = {
|
||||
enable = lib.mkEnableOption "Git-annex";
|
||||
};
|
||||
|
||||
config = {
|
||||
environment.systemPackages = with pkgs; [
|
||||
git-annex
|
||||
# git
|
||||
# rsync
|
||||
];
|
||||
|
||||
# # Our files managed by git-annex actually live on a WebDAV server that is
|
||||
# # declared by the following section. This is mainly because it's the most
|
||||
# # convenient way to share files with my iPhone. Apple hates developers!
|
||||
# services.nginx = {
|
||||
# # Nginx's WebDAV support is in a separate module we must import.
|
||||
# additionalModules = [ pkgs.nginxModules.dav ];
|
||||
|
||||
# virtualHosts."dav.deertopia.net" = {
|
||||
# addSSL = true;
|
||||
# enableACME = true;
|
||||
# locations."/".extraConfig = ''
|
||||
# alias /persist/web/webdav;
|
||||
# client_body_temp_path /tmp/nginx/webdav;
|
||||
# dav_methods PUT DELETE MKCOL COPY MOVE;
|
||||
# dav_ext_methods PROPFIND OPTIONS;
|
||||
# create_full_put_path on
|
||||
|
||||
# auth_basic "Restricted Access";
|
||||
# auth_basic_user_file /etc/nginx/webdav.passwd;
|
||||
|
||||
# # Deny all access unless authenticated
|
||||
# satisfy all;
|
||||
# allow all; # This allows all authenticated users
|
||||
# deny all; # This denies all other users
|
||||
# '';
|
||||
# };
|
||||
# };
|
||||
};
|
||||
}
|
||||
@@ -41,6 +41,16 @@ in
|
||||
type = lib.types.str;
|
||||
default = "${cfg.root}/${name}";
|
||||
};
|
||||
user = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
description = "The owning user of the host's root directory.";
|
||||
default = cfg.user;
|
||||
};
|
||||
group = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
description = "The owning group of the host's root directory.";
|
||||
default = cfg.group;
|
||||
};
|
||||
vhostName = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "${name}.deertopia.net";
|
||||
@@ -98,22 +108,22 @@ in
|
||||
# };
|
||||
# };
|
||||
|
||||
system.activationScripts.initialiseDeertopiaRoot.text =
|
||||
let
|
||||
directories =
|
||||
builtins.catAttrs "directory" (builtins.attrValues cfg.vhosts);
|
||||
inherit (cfg) root group user;
|
||||
in ''
|
||||
mkdir -p "${root}"
|
||||
chown -R "${user}:${group}" "${root}"
|
||||
chmod -R 775 "${root}"
|
||||
# system.activationScripts.initialiseDeertopiaRoot.text =
|
||||
# let
|
||||
# # FIXME: Use `lib.strings.toShellVar`.
|
||||
# inherit (cfg) root group user;
|
||||
# in ''
|
||||
# mkdir -p "${root}"
|
||||
# chown -R "${user}:${group}" "${root}"
|
||||
# chmod -R 775 "${root}"
|
||||
|
||||
dirs=(${builtins.concatStringsSep " " (map (x: "'${x}'") directories)})
|
||||
for i in "''${dirs[@]}"; do
|
||||
mkdir -p "$i"
|
||||
chown -R "${user}:${group}" "$i"
|
||||
chmod -R 775 "$i"
|
||||
done
|
||||
'';
|
||||
# ${lib.toShellVar "dirs"
|
||||
# (builtins.catAttrs "directory" (builtins.attrValues cfg.vhosts))}
|
||||
# for i in "''${dirs[@]}"; do
|
||||
# mkdir -p "$i"
|
||||
# chown -R "${user}:${group}" "$i"
|
||||
# chmod -R 775 "$i"
|
||||
# done
|
||||
# '';
|
||||
};
|
||||
}
|
||||
|
||||
63
modules/nixos/deertopia/webdav.nix
Normal file
63
modules/nixos/deertopia/webdav.nix
Normal file
@@ -0,0 +1,63 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let cfg = config.sydnix.deertopia.webdav;
|
||||
in {
|
||||
options = {
|
||||
sydnix.deertopia.webdav = {
|
||||
enable = mkEnableOption "Deertopia's WebDAV server";
|
||||
|
||||
port = lib.mkOption {
|
||||
default = 22016;
|
||||
type = lib.types.port;
|
||||
description = ''
|
||||
The internal WebDAV port. The actual server will be hosted at
|
||||
https://dav.deertopia.net:80/.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
systemd.services.deertopia-webdav-server =
|
||||
let htpasswdFile = "/persist/deertopia.net/htpasswd";
|
||||
directory = "/persist/deertopia.net/dav";
|
||||
in {
|
||||
description = "Deertopia's WebDAV server";
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
script = ''
|
||||
${pkgs.rclone}/bin/rclone serve webdav \
|
||||
--addr ":${builtins.toString cfg.port}" \
|
||||
--htpasswd "${htpasswdFile}" "${directory}"
|
||||
'';
|
||||
serviceConfig.Restart = "always";
|
||||
};
|
||||
|
||||
# Without this, Nginx will attempt redirections to https://localhost, which
|
||||
# is not okay, as localhost does not have any associated certs!
|
||||
# See: https://forum.seafile.com/t/seafdav-move-command-causing-502/11582/26
|
||||
services.nginx.appendHttpConfig = ''
|
||||
map $http_destination $http_destination_webdav {
|
||||
~*https://(.+) http://$1;
|
||||
default $http_destination;
|
||||
}
|
||||
'';
|
||||
|
||||
sydnix.deertopia.nginx.vhosts."dav".vhost = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
locations."/" = {
|
||||
extraConfig = ''
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
# See previous note regarding the HTTPS -> HTTP redirection.
|
||||
proxy_set_header Destination $http_destination_webdav;
|
||||
|
||||
proxy_pass "http://localhost:${builtins.toString cfg.port}";
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
149
modules/nixos/git-annex.nix
Normal file
149
modules/nixos/git-annex.nix
Normal file
@@ -0,0 +1,149 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let cfg = config.sydnix.git-annex;
|
||||
in {
|
||||
options = {
|
||||
sydnix.git-annex = {
|
||||
enable = lib.mkEnableOption "git-annex";
|
||||
|
||||
user = {
|
||||
name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
email = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
};
|
||||
|
||||
keyFiles = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.path;
|
||||
default = [];
|
||||
};
|
||||
|
||||
repos = lib.mkOption {
|
||||
type = lib.types.attrsOf (lib.types.submodule ({ name, ... }: {
|
||||
options = {
|
||||
enable = lib.mkOption {
|
||||
description = ''
|
||||
Git-annex repo ${name};
|
||||
'';
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
};
|
||||
|
||||
path = lib.mkOption {
|
||||
description = ''
|
||||
Path to the repo.
|
||||
'';
|
||||
type = lib.types.str;
|
||||
default = name;
|
||||
};
|
||||
|
||||
remotes = lib.mkOption {
|
||||
type = lib.types.attrsOf lib.types.str;
|
||||
default = {};
|
||||
};
|
||||
|
||||
user = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "annex";
|
||||
};
|
||||
|
||||
group = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "annex";
|
||||
};
|
||||
|
||||
managed = lib.mkOption {
|
||||
description = ''
|
||||
If true, the repo will be automatically managed by Nix.
|
||||
'Management' includes creating and initialising the repo and
|
||||
setting permissions.
|
||||
'';
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
};
|
||||
};
|
||||
}));
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
# Git-annex assistant requires remotes to have git-annex on the PATH.
|
||||
environment.systemPackages = [
|
||||
pkgs.git-annex
|
||||
];
|
||||
|
||||
# The user that users log in as to access managed repos.
|
||||
users.groups.annex = {};
|
||||
users.users.annex = {
|
||||
isSystemUser = true;
|
||||
group = "annex";
|
||||
home = "/var/sydnix/annex";
|
||||
createHome = true;
|
||||
openssh.authorizedKeys.keyFiles = cfg.keyFiles;
|
||||
};
|
||||
|
||||
system.activationScripts.initialiseUserAnnex =
|
||||
let gitconfig-file = pkgs.writeText "gitconfig" ''
|
||||
[user]
|
||||
email = ${cfg.user.email}
|
||||
name = ${cfg.user.name}
|
||||
[init]
|
||||
defaultBranch = main
|
||||
'';
|
||||
in ''
|
||||
ln -sf "${gitconfig-file}" ~/.gitconfig
|
||||
'';
|
||||
|
||||
systemd.services =
|
||||
let
|
||||
init-if-necessary = repo:
|
||||
pkgs.writeScript "git-annex-init-if-necessary" ''
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
[ -e .git ] || git init
|
||||
[ -e .git/annex ] || git annex init
|
||||
|
||||
${lib.strings.toShellVar "remotes" repo.remotes}
|
||||
for remoteName in ''${!remotes[@]}; do
|
||||
git remote get-url "$remoteName"
|
||||
if [ $? -eq 0 ]; then
|
||||
git remote set-url "$remoteName" "''${remotes["$remoteName"]}"
|
||||
else
|
||||
git remote add "$remoteName" "''${remotes["$remoteName"]}"
|
||||
fi
|
||||
done
|
||||
'';
|
||||
|
||||
mkAssistantService = repo: {
|
||||
description = "git-annex assistant (${repo.path})";
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig.User = repo.user;
|
||||
serviceConfig.WorkingDirectory = repo.path;
|
||||
path = [ pkgs.git pkgs.git-annex pkgs.openssh ];
|
||||
# Set the default file mode for new files created by this process to
|
||||
# 775. Oddly, `UMask = x` will set the mode to `0777 & x`, so 002
|
||||
# gets us the desired figure of 775. We want 775 because Nginx,
|
||||
# running under user `nginx` needs to be able to read/write these
|
||||
# files to server them over WebDAV.
|
||||
serviceConfig.UMask = "002";
|
||||
serviceConfig.ExecStartPre =
|
||||
lib.optionalString
|
||||
repo.managed
|
||||
"${pkgs.bash}/bin/bash ${init-if-necessary repo}";
|
||||
serviceConfig.ExecStart = ''
|
||||
${pkgs.git-annex}/bin/git-annex assistant --foreground
|
||||
'';
|
||||
};
|
||||
in builtins.listToAttrs
|
||||
(builtins.map
|
||||
(repo: {
|
||||
name = "annex-${lib.strings.sanitizeDerivationName repo.path}";
|
||||
value = mkAssistantService repo;
|
||||
})
|
||||
(builtins.attrValues cfg.repos));
|
||||
};
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
isNormalUser = true;
|
||||
# TODO: Don't hard-code `persist`. Use
|
||||
# config.sydnix.impermanence.persistGroupName.
|
||||
extraGroups = [ "wheel" "persist" "nginx" ];
|
||||
extraGroups = [ "wheel" "persist" "nginx" "annex" ];
|
||||
initialHashedPassword =
|
||||
"$y$j9T$aEFDDwdTZbAc6VQRXrkBJ0$K8wxTGTWDihyX1wxJ.ZMH//wmQFfrGGUkLkxIU0Lyq8";
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
{
|
||||
systemConfiguration = { config, ... }: {
|
||||
isNormalUser = true;
|
||||
# TODO: Don't hard-code `persist`. Use
|
||||
# config.sydnix.impermanence.persistGroupName.
|
||||
extraGroups = [ ];
|
||||
initialHashedPassword =
|
||||
"$y$j9T$uU64mjI.5Y1JICkKAaIgl0$kkO089hyDp3akSj7ReIKqFthA4T/d1w/nF40a5Tujt1";
|
||||
openssh.authorizedKeys.keyFiles = [
|
||||
../../public-keys/crumb-at-guix-rebound.pub
|
||||
];
|
||||
};
|
||||
|
||||
homeConfiguration = { config, lib, pkgs, ... }: {
|
||||
Reference in New Issue
Block a user