feat: Jellyfin media server
This commit is contained in:
@@ -219,6 +219,8 @@ CLOSED: [2025-02-02 Sun 14:06]
|
||||
|
||||
**** TODO [[https://github.com/promethial/paxedit][Paxedit]]
|
||||
|
||||
Seems old and broken?
|
||||
|
||||
**** TODO Evil stuff
|
||||
|
||||
**** TODO Text objects
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
users.users = [
|
||||
"lain"
|
||||
"besties"
|
||||
];
|
||||
|
||||
impermanence = {
|
||||
@@ -46,17 +47,32 @@
|
||||
../../public-keys/lain-at-deertopia.pub
|
||||
];
|
||||
repos = {
|
||||
"/persist/vault/jellyfin/Documents" = {
|
||||
managed = true;
|
||||
symlinkToAnnexHome = "documents";
|
||||
remotes = {
|
||||
"guix-rebound" = "crumb@guix-rebound:Documents";
|
||||
};
|
||||
};
|
||||
"/persist/vault/jellyfin/Music" = {
|
||||
managed = true;
|
||||
symlinkToAnnexHome = "music";
|
||||
remotes = {
|
||||
"guix-rebound" = "crumb@guix-rebound:Music";
|
||||
};
|
||||
};
|
||||
"/persist/deertopia.net/dav/org" = {
|
||||
managed = true;
|
||||
symlinkToAnnexHome = "org";
|
||||
remotes = {
|
||||
"guix-rebound" = "crumb@guix-rebound:org";
|
||||
# "fruitbook" = "crumble@fruitbook:org";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
deertopia = {
|
||||
jellyfin.enable = true;
|
||||
nginx.enable = true;
|
||||
webdav.enable = true;
|
||||
bepasty.enable = true;
|
||||
|
||||
39
modules/nixos/deertopia/jellyfin.nix
Normal file
39
modules/nixos/deertopia/jellyfin.nix
Normal file
@@ -0,0 +1,39 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let cfg = config.sydnix.deertopia.jellyfin;
|
||||
in {
|
||||
options = {
|
||||
sydnix.deertopia.jellyfin = {
|
||||
enable = mkEnableOption "Deertopia's Jellyfin media server";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
sydnix.impermanence =
|
||||
let jcfg = config.services.jellyfin;
|
||||
in {
|
||||
directories = [
|
||||
jcfg.dataDir
|
||||
jcfg.configDir
|
||||
];
|
||||
cache.directories = [
|
||||
jcfg.cacheDir
|
||||
];
|
||||
};
|
||||
|
||||
services.jellyfin = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
};
|
||||
|
||||
sydnix.deertopia.nginx.vhosts."watch".vhost = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://localhost:8096"; # Uses default port.
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -31,6 +31,11 @@ in {
|
||||
default = true;
|
||||
};
|
||||
|
||||
symlinkToAnnexHome = lib.mkOption {
|
||||
default = null;
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
};
|
||||
|
||||
path = lib.mkOption {
|
||||
description = ''
|
||||
Path to the repo.
|
||||
@@ -47,6 +52,9 @@ in {
|
||||
user = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "annex";
|
||||
description = ''
|
||||
The user that the Git-annex assistant will be run as.
|
||||
'';
|
||||
};
|
||||
|
||||
group = lib.mkOption {
|
||||
@@ -81,11 +89,21 @@ in {
|
||||
# Necessary to enable cloning over SSH.
|
||||
isNormalUser = true;
|
||||
group = "annex";
|
||||
# TODO: Don't hardcode extra groups!
|
||||
extraGroups = [ "jellyfin" ];
|
||||
home = "/var/sydnix/annex";
|
||||
homeMode = "770";
|
||||
createHome = true;
|
||||
openssh.authorizedKeys.keyFiles = cfg.keyFiles;
|
||||
};
|
||||
|
||||
# HACK: Some Jellyfin libraries are served by Git-annex. Give Jellyfin
|
||||
# permission to symlink some of those libraries into the annex user's home
|
||||
# dir.
|
||||
users.users.${config.services.jellyfin.user}.extraGroups =
|
||||
lib.mkIf config.sydnix.deertopia.jellyfin.enable
|
||||
[ "annex" ];
|
||||
|
||||
system.activationScripts.initialiseUserAnnex =
|
||||
let gitconfig-file = pkgs.writeText "gitconfig" ''
|
||||
[user]
|
||||
@@ -95,23 +113,16 @@ in {
|
||||
defaultBranch = main
|
||||
[core]
|
||||
symlinks = true
|
||||
[safe]
|
||||
${lib.strings.concatMapStrings
|
||||
(repo: "\tdirectory = ${repo.path}\n")
|
||||
(builtins.attrValues cfg.repos)}
|
||||
'';
|
||||
in ''
|
||||
set -e
|
||||
|
||||
annexHome="${config.users.users.annex.home}"
|
||||
ln -sf "${gitconfig-file}" "$annexHome/.gitconfig"
|
||||
|
||||
# Symlink repos into annex's home for easy access. This is particularly nice for cloning:
|
||||
# git clone annex@deertopia.net:org
|
||||
# instead of
|
||||
# git clone annex@deertopia.net:/persist/deertopia.net/org
|
||||
# Less assumptions about the host's file system!
|
||||
${lib.strings.toShellVar "repos" (builtins.attrNames cfg.repos)}
|
||||
for repoPath in ''${!repos[@]}; do
|
||||
target="$annexHome/$(basename "$repoPath")"
|
||||
ln -sf "$repoPath" "$target"
|
||||
done
|
||||
'';
|
||||
|
||||
systemd.services =
|
||||
@@ -124,8 +135,18 @@ in {
|
||||
[ -e .git ] || git init
|
||||
[ -e .git/annex ] || git annex init
|
||||
|
||||
# Symlink repo into user `annex` for easy access.
|
||||
ln -sf "$(pwd)" "$HOME/"
|
||||
# git config set user.name "${cfg.user.name}"
|
||||
# git config set user.email "${cfg.user.email}"
|
||||
|
||||
# Symlink repos into annex's home for easy access. This is
|
||||
# particularly nice for cloning:
|
||||
# git clone annex@deertopia.net:org
|
||||
# instead of
|
||||
# git clone annex@deertopia.net:/persist/deertopia.net/dav/org
|
||||
# Less assumptions about the host's file system!
|
||||
annexHome="${config.users.users.annex.home}"
|
||||
${lib.optionalString (repo.symlinkToAnnexHome != null)
|
||||
''ln -sf "$PWD" "$annexHome/${repo.symlinkToAnnexHome}"''}
|
||||
|
||||
${lib.strings.toShellVar "remotes" repo.remotes}
|
||||
for remoteName in ''${!remotes[@]}; do
|
||||
|
||||
@@ -38,6 +38,28 @@ in {
|
||||
Name of the group whose members have access to the persist directory.
|
||||
'';
|
||||
};
|
||||
|
||||
cache = {
|
||||
directories = mkOption {
|
||||
description = ''
|
||||
While functionally identical to `directories` (at the moment),
|
||||
`cache.directories` carries additional semantics: these directories
|
||||
/can/ be erased, but typically /shouldn't/ be.
|
||||
'';
|
||||
default = [];
|
||||
type = types.listOf types.anything;
|
||||
};
|
||||
|
||||
files = mkOption {
|
||||
description = ''
|
||||
While functionally identical to `files` (at the moment),
|
||||
`cache.files` carries additional semantics: these files /can/ be
|
||||
erased, but typically /shouldn't/ be.
|
||||
'';
|
||||
default = [];
|
||||
type = types.listOf types.anything;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -72,8 +94,8 @@ in {
|
||||
programs.fuse.userAllowOther = true;
|
||||
|
||||
environment.persistence."${cfg.persistDirectory}/root" = {
|
||||
directories = cfg.directories;
|
||||
files = cfg.files;
|
||||
directories = cfg.directories ++ cfg.cache.directories;
|
||||
files = cfg.files ++ cfg.cache.files;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,7 +3,18 @@
|
||||
isNormalUser = true;
|
||||
# TODO: Don't hard-code `persist`. Use
|
||||
# config.sydnix.impermanence.persistGroupName.
|
||||
extraGroups = [ "wheel" "persist" "nginx" "annex" ];
|
||||
extraGroups = [
|
||||
# Admin account.
|
||||
"wheel"
|
||||
# Default permissions to modify /persist.
|
||||
"persist"
|
||||
# Can modify the files served by Nginx.
|
||||
"nginx"
|
||||
# Can modify Deertopia's git-annex repos.
|
||||
"annex"
|
||||
# Can modify Deertopia's Jellyfin libraries.
|
||||
"jellyfin"
|
||||
];
|
||||
initialHashedPassword =
|
||||
"$y$j9T$aEFDDwdTZbAc6VQRXrkBJ0$K8wxTGTWDihyX1wxJ.ZMH//wmQFfrGGUkLkxIU0Lyq8";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user