Formatted
This commit is contained in:
@@ -1,128 +0,0 @@
|
|||||||
# Contributor Covenant Code of Conduct
|
|
||||||
|
|
||||||
## Our Pledge
|
|
||||||
|
|
||||||
We as members, contributors, and leaders pledge to make participation in our
|
|
||||||
community a harassment-free experience for everyone, regardless of age, body
|
|
||||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
|
||||||
identity and expression, level of experience, education, socio-economic status,
|
|
||||||
nationality, personal appearance, race, religion, or sexual identity
|
|
||||||
and orientation.
|
|
||||||
|
|
||||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
|
||||||
diverse, inclusive, and healthy community.
|
|
||||||
|
|
||||||
## Our Standards
|
|
||||||
|
|
||||||
Examples of behavior that contributes to a positive environment for our
|
|
||||||
community include:
|
|
||||||
|
|
||||||
* Demonstrating empathy and kindness toward other people
|
|
||||||
* Being respectful of differing opinions, viewpoints, and experiences
|
|
||||||
* Giving and gracefully accepting constructive feedback
|
|
||||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
|
||||||
and learning from the experience
|
|
||||||
* Focusing on what is best not just for us as individuals, but for the
|
|
||||||
overall community
|
|
||||||
|
|
||||||
Examples of unacceptable behavior include:
|
|
||||||
|
|
||||||
* The use of sexualized language or imagery, and sexual attention or
|
|
||||||
advances of any kind
|
|
||||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
|
||||||
* Public or private harassment
|
|
||||||
* Publishing others' private information, such as a physical or email
|
|
||||||
address, without their explicit permission
|
|
||||||
* Other conduct which could reasonably be considered inappropriate in a
|
|
||||||
professional setting
|
|
||||||
|
|
||||||
## Enforcement Responsibilities
|
|
||||||
|
|
||||||
Community leaders are responsible for clarifying and enforcing our standards of
|
|
||||||
acceptable behavior and will take appropriate and fair corrective action in
|
|
||||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
|
||||||
or harmful.
|
|
||||||
|
|
||||||
Community leaders have the right and responsibility to remove, edit, or reject
|
|
||||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
|
||||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
|
||||||
decisions when appropriate.
|
|
||||||
|
|
||||||
## Scope
|
|
||||||
|
|
||||||
This Code of Conduct applies within all community spaces, and also applies when
|
|
||||||
an individual is officially representing the community in public spaces.
|
|
||||||
Examples of representing our community include using an official e-mail address,
|
|
||||||
posting via an official social media account, or acting as an appointed
|
|
||||||
representative at an online or offline event.
|
|
||||||
|
|
||||||
## Enforcement
|
|
||||||
|
|
||||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
||||||
reported to the community leaders responsible for enforcement at
|
|
||||||
mail@rasmuskirk.com.
|
|
||||||
All complaints will be reviewed and investigated promptly and fairly.
|
|
||||||
|
|
||||||
All community leaders are obligated to respect the privacy and security of the
|
|
||||||
reporter of any incident.
|
|
||||||
|
|
||||||
## Enforcement Guidelines
|
|
||||||
|
|
||||||
Community leaders will follow these Community Impact Guidelines in determining
|
|
||||||
the consequences for any action they deem in violation of this Code of Conduct:
|
|
||||||
|
|
||||||
### 1. Correction
|
|
||||||
|
|
||||||
**Community Impact**: Use of inappropriate language or other behavior deemed
|
|
||||||
unprofessional or unwelcome in the community.
|
|
||||||
|
|
||||||
**Consequence**: A private, written warning from community leaders, providing
|
|
||||||
clarity around the nature of the violation and an explanation of why the
|
|
||||||
behavior was inappropriate. A public apology may be requested.
|
|
||||||
|
|
||||||
### 2. Warning
|
|
||||||
|
|
||||||
**Community Impact**: A violation through a single incident or series
|
|
||||||
of actions.
|
|
||||||
|
|
||||||
**Consequence**: A warning with consequences for continued behavior. No
|
|
||||||
interaction with the people involved, including unsolicited interaction with
|
|
||||||
those enforcing the Code of Conduct, for a specified period of time. This
|
|
||||||
includes avoiding interactions in community spaces as well as external channels
|
|
||||||
like social media. Violating these terms may lead to a temporary or
|
|
||||||
permanent ban.
|
|
||||||
|
|
||||||
### 3. Temporary Ban
|
|
||||||
|
|
||||||
**Community Impact**: A serious violation of community standards, including
|
|
||||||
sustained inappropriate behavior.
|
|
||||||
|
|
||||||
**Consequence**: A temporary ban from any sort of interaction or public
|
|
||||||
communication with the community for a specified period of time. No public or
|
|
||||||
private interaction with the people involved, including unsolicited interaction
|
|
||||||
with those enforcing the Code of Conduct, is allowed during this period.
|
|
||||||
Violating these terms may lead to a permanent ban.
|
|
||||||
|
|
||||||
### 4. Permanent Ban
|
|
||||||
|
|
||||||
**Community Impact**: Demonstrating a pattern of violation of community
|
|
||||||
standards, including sustained inappropriate behavior, harassment of an
|
|
||||||
individual, or aggression toward or disparagement of classes of individuals.
|
|
||||||
|
|
||||||
**Consequence**: A permanent ban from any sort of public interaction within
|
|
||||||
the community.
|
|
||||||
|
|
||||||
## Attribution
|
|
||||||
|
|
||||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
|
||||||
version 2.0, available at
|
|
||||||
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
|
||||||
|
|
||||||
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
|
||||||
enforcement ladder](https://github.com/mozilla/diversity).
|
|
||||||
|
|
||||||
[homepage]: https://www.contributor-covenant.org
|
|
||||||
|
|
||||||
For answers to common questions about this code of conduct, see the FAQ at
|
|
||||||
https://www.contributor-covenant.org/faq. Translations are available at
|
|
||||||
https://www.contributor-covenant.org/translations.
|
|
||||||
@@ -29,7 +29,11 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = inputs @ {flake-parts, vpnconfinement, nixpkgs, ...}:
|
outputs = inputs @ {
|
||||||
|
flake-parts,
|
||||||
|
vpnconfinement,
|
||||||
|
...
|
||||||
|
}:
|
||||||
flake-parts.lib.mkFlake {
|
flake-parts.lib.mkFlake {
|
||||||
inherit inputs;
|
inherit inputs;
|
||||||
} {
|
} {
|
||||||
@@ -44,7 +48,7 @@
|
|||||||
|
|
||||||
flake = {
|
flake = {
|
||||||
nixosModules = rec {
|
nixosModules = rec {
|
||||||
nixarr = (import ./nixarr vpnconfinement);
|
nixarr = import ./nixarr vpnconfinement;
|
||||||
default = nixarr;
|
default = nixarr;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -52,7 +56,6 @@
|
|||||||
perSystem = {
|
perSystem = {
|
||||||
config,
|
config,
|
||||||
pkgs,
|
pkgs,
|
||||||
lib,
|
|
||||||
...
|
...
|
||||||
}: {
|
}: {
|
||||||
treefmt.config = {
|
treefmt.config = {
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
{ config, pkgs, lib, ... }:
|
|
||||||
|
|
||||||
with lib;
|
|
||||||
|
|
||||||
let
|
|
||||||
cfg = config.util-nixarr.services.bazarr;
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib; let
|
||||||
|
cfg = config.util-nixarr.services.bazarr;
|
||||||
|
in {
|
||||||
options = {
|
options = {
|
||||||
util-nixarr.services.bazarr = {
|
util-nixarr.services.bazarr = {
|
||||||
enable = mkEnableOption ("bazarr, a subtitle manager for Sonarr and Radarr");
|
enable = mkEnableOption "bazarr, a subtitle manager for Sonarr and Radarr";
|
||||||
|
|
||||||
openFirewall = mkOption {
|
openFirewall = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
@@ -49,8 +50,8 @@ in
|
|||||||
|
|
||||||
systemd.services.bazarr = {
|
systemd.services.bazarr = {
|
||||||
description = "bazarr";
|
description = "bazarr";
|
||||||
after = [ "network.target" ];
|
after = ["network.target"];
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = ["multi-user.target"];
|
||||||
|
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Type = "simple";
|
Type = "simple";
|
||||||
@@ -68,7 +69,7 @@ in
|
|||||||
};
|
};
|
||||||
|
|
||||||
networking.firewall = mkIf cfg.openFirewall {
|
networking.firewall = mkIf cfg.openFirewall {
|
||||||
allowedTCPPorts = [ cfg.listenPort ];
|
allowedTCPPorts = [cfg.listenPort];
|
||||||
};
|
};
|
||||||
|
|
||||||
users.users = mkIf (cfg.user == "bazarr") {
|
users.users = mkIf (cfg.user == "bazarr") {
|
||||||
|
|||||||
@@ -81,7 +81,12 @@ in {
|
|||||||
# Port mappings
|
# Port mappings
|
||||||
# TODO: openports
|
# TODO: openports
|
||||||
vpnnamespaces.wg = mkIf cfg.vpn.enable {
|
vpnnamespaces.wg = mkIf cfg.vpn.enable {
|
||||||
portMappings = [{ from = config.bazarr.listenPort; to = config.bazarr.listenPort; }];
|
portMappings = [
|
||||||
|
{
|
||||||
|
from = config.bazarr.listenPort;
|
||||||
|
to = config.bazarr.listenPort;
|
||||||
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
services.nginx = mkIf cfg.vpn.enable {
|
services.nginx = mkIf cfg.vpn.enable {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ with lib; let
|
|||||||
ddns-njalla = pkgs.writeShellApplication {
|
ddns-njalla = pkgs.writeShellApplication {
|
||||||
name = "ddns-njalla";
|
name = "ddns-njalla";
|
||||||
|
|
||||||
runtimeInputs = with pkgs; [ curl jq ];
|
runtimeInputs = with pkgs; [curl jq];
|
||||||
|
|
||||||
# Thanks chatgpt...
|
# Thanks chatgpt...
|
||||||
text = ''
|
text = ''
|
||||||
@@ -118,9 +118,12 @@ in {
|
|||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
assertion = cfg.njalla.vpn.enable -> (
|
assertion =
|
||||||
cfg.njalla.vpn.keysFile != null &&
|
cfg.njalla.vpn.enable
|
||||||
config.nixarr.vpn.enable
|
-> (
|
||||||
|
cfg.njalla.vpn.keysFile
|
||||||
|
!= null
|
||||||
|
&& config.nixarr.vpn.enable
|
||||||
);
|
);
|
||||||
message = ''
|
message = ''
|
||||||
The nixarr.ddns.njalla.enable option requires the
|
The nixarr.ddns.njalla.enable option requires the
|
||||||
|
|||||||
+1
-3
@@ -1,6 +1,4 @@
|
|||||||
vpnconfinement:
|
vpnconfinement: {...}: {
|
||||||
{ ... }:
|
|
||||||
{
|
|
||||||
imports = [
|
imports = [
|
||||||
vpnconfinement.nixosModules.default
|
vpnconfinement.nixosModules.default
|
||||||
./nixarr.nix
|
./nixarr.nix
|
||||||
|
|||||||
+21
-12
@@ -2,12 +2,12 @@
|
|||||||
config,
|
config,
|
||||||
lib,
|
lib,
|
||||||
...
|
...
|
||||||
}:
|
}: let
|
||||||
let
|
|
||||||
cfg = config.nixarr.jellyfin;
|
cfg = config.nixarr.jellyfin;
|
||||||
defaultPort = 8096;
|
defaultPort = 8096;
|
||||||
nixarr = config.nixarr;
|
nixarr = config.nixarr;
|
||||||
in with lib; {
|
in
|
||||||
|
with lib; {
|
||||||
options.nixarr.jellyfin = {
|
options.nixarr.jellyfin = {
|
||||||
enable = mkEnableOption "the Jellyfin service.";
|
enable = mkEnableOption "the Jellyfin service.";
|
||||||
|
|
||||||
@@ -150,9 +150,11 @@ in with lib; {
|
|||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
assertion = cfg.expose.https.enable -> (
|
assertion =
|
||||||
(cfg.expose.https.domainName != null) &&
|
cfg.expose.https.enable
|
||||||
(cfg.expose.https.acmeMail != null)
|
-> (
|
||||||
|
(cfg.expose.https.domainName != null)
|
||||||
|
&& (cfg.expose.https.acmeMail != null)
|
||||||
);
|
);
|
||||||
message = ''
|
message = ''
|
||||||
The nixarr.jellyfin.expose.https.enable option requires the
|
The nixarr.jellyfin.expose.https.enable option requires the
|
||||||
@@ -163,10 +165,12 @@ in with lib; {
|
|||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
assertion = cfg.expose.vpn.enable -> (
|
assertion =
|
||||||
cfg.vpn.enable &&
|
cfg.expose.vpn.enable
|
||||||
(cfg.expose.vpn.port != null) &&
|
-> (
|
||||||
(cfg.expose.vpn.accessibleFrom != null)
|
cfg.vpn.enable
|
||||||
|
&& (cfg.expose.vpn.port != null)
|
||||||
|
&& (cfg.expose.vpn.accessibleFrom != null)
|
||||||
);
|
);
|
||||||
message = ''
|
message = ''
|
||||||
The nixarr.jellyfin.expose.vpn.enable option requires the
|
The nixarr.jellyfin.expose.vpn.enable option requires the
|
||||||
@@ -264,11 +268,16 @@ in with lib; {
|
|||||||
# Port mappings
|
# Port mappings
|
||||||
# TODO: openports if expose.vpn
|
# TODO: openports if expose.vpn
|
||||||
vpnnamespaces.wg = mkIf cfg.vpn.enable {
|
vpnnamespaces.wg = mkIf cfg.vpn.enable {
|
||||||
portMappings = [{ from = defaultPort; to = defaultPort; }];
|
portMappings = [
|
||||||
|
{
|
||||||
|
from = defaultPort;
|
||||||
|
to = defaultPort;
|
||||||
|
}
|
||||||
|
];
|
||||||
openVPNPorts = optional cfg.expose.vpn.enable {
|
openVPNPorts = optional cfg.expose.vpn.enable {
|
||||||
port = cfg.expose.vpn.port;
|
port = cfg.expose.vpn.port;
|
||||||
protocol = "tcp";
|
protocol = "tcp";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,7 +78,12 @@ in {
|
|||||||
# Port mappings
|
# Port mappings
|
||||||
# TODO: openports
|
# TODO: openports
|
||||||
vpnnamespaces.wg = mkIf cfg.vpn.enable {
|
vpnnamespaces.wg = mkIf cfg.vpn.enable {
|
||||||
portMappings = [{ from = defaultPort; to = defaultPort; }];
|
portMappings = [
|
||||||
|
{
|
||||||
|
from = defaultPort;
|
||||||
|
to = defaultPort;
|
||||||
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
services.nginx = mkIf cfg.vpn.enable {
|
services.nginx = mkIf cfg.vpn.enable {
|
||||||
|
|||||||
+10
-5
@@ -13,7 +13,6 @@ with lib; let
|
|||||||
find "$1" -type f -links 1 -exec du -h {} + | sort -h
|
find "$1" -type f -links 1 -exec du -h {} + | sort -h
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
in {
|
in {
|
||||||
imports = [
|
imports = [
|
||||||
./jellyfin
|
./jellyfin
|
||||||
@@ -69,7 +68,7 @@ in {
|
|||||||
mediaUsers = mkOption {
|
mediaUsers = mkOption {
|
||||||
type = with types; listOf str;
|
type = with types; listOf str;
|
||||||
default = [];
|
default = [];
|
||||||
example = [ "user" ];
|
example = ["user"];
|
||||||
description = ''
|
description = ''
|
||||||
Extra users to add to the media group.
|
Extra users to add to the media group.
|
||||||
'';
|
'';
|
||||||
@@ -251,7 +250,8 @@ in {
|
|||||||
|
|
||||||
runtimeInputs = with pkgs; [util-linux unixtools.ping coreutils curl bash libressl netcat-gnu openresolv dig];
|
runtimeInputs = with pkgs; [util-linux unixtools.ping coreutils curl bash libressl netcat-gnu openresolv dig];
|
||||||
|
|
||||||
text = ''
|
text =
|
||||||
|
''
|
||||||
cd "$(mktemp -d)"
|
cd "$(mktemp -d)"
|
||||||
|
|
||||||
# Print resolv.conf
|
# Print resolv.conf
|
||||||
@@ -271,10 +271,15 @@ in {
|
|||||||
curl -s https://raw.githubusercontent.com/macvk/dnsleaktest/b03ab54d574adbe322ca48cbcb0523be720ad38d/dnsleaktest.sh -o dnsleaktest.sh
|
curl -s https://raw.githubusercontent.com/macvk/dnsleaktest/b03ab54d574adbe322ca48cbcb0523be720ad38d/dnsleaktest.sh -o dnsleaktest.sh
|
||||||
chmod +x dnsleaktest.sh
|
chmod +x dnsleaktest.sh
|
||||||
./dnsleaktest.sh
|
./dnsleaktest.sh
|
||||||
'' + (if cfg.vpn.vpnTestService.port != null then ''
|
''
|
||||||
|
+ (
|
||||||
|
if cfg.vpn.vpnTestService.port != null
|
||||||
|
then ''
|
||||||
echo "starting netcat on port ${builtins.toString cfg.vpn.vpnTestService.port}:"
|
echo "starting netcat on port ${builtins.toString cfg.vpn.vpnTestService.port}:"
|
||||||
nc -vnlp ${builtins.toString cfg.vpn.vpnTestService.port}
|
nc -vnlp ${builtins.toString cfg.vpn.vpnTestService.port}
|
||||||
'' else "");
|
''
|
||||||
|
else ""
|
||||||
|
);
|
||||||
};
|
};
|
||||||
in "${vpn-test}/bin/vpn-test";
|
in "${vpn-test}/bin/vpn-test";
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,9 @@ in {
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
warnings = if config.services.openssh.enable then [
|
warnings =
|
||||||
|
if config.services.openssh.enable
|
||||||
|
then [
|
||||||
''
|
''
|
||||||
nixarr.openssh.expose.vpn.enable is set, but openssh is not enabled
|
nixarr.openssh.expose.vpn.enable is set, but openssh is not enabled
|
||||||
on your system, so the openssh server is not running. This is probably
|
on your system, so the openssh server is not running. This is probably
|
||||||
@@ -74,7 +76,8 @@ in {
|
|||||||
to a ssh public key file from the machine that you want to have
|
to a ssh public key file from the machine that you want to have
|
||||||
access. Don't use password authentication as it is insecure!
|
access. Don't use password authentication as it is insecure!
|
||||||
''
|
''
|
||||||
] else [];
|
]
|
||||||
|
else [];
|
||||||
|
|
||||||
# Enable and specify VPN namespace to confine service in.
|
# Enable and specify VPN namespace to confine service in.
|
||||||
systemd.services.openssh.vpnconfinement = {
|
systemd.services.openssh.vpnconfinement = {
|
||||||
@@ -84,8 +87,18 @@ in {
|
|||||||
|
|
||||||
# Port mappings
|
# Port mappings
|
||||||
vpnnamespaces.wg = {
|
vpnnamespaces.wg = {
|
||||||
portMappings = [{ From = defaultPort; To = defaultPort; }];
|
portMappings = [
|
||||||
openVPNPorts = map (x: { port = x; protocol = "both"; }) services.openssh.ports;
|
{
|
||||||
|
From = defaultPort;
|
||||||
|
To = defaultPort;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
openVPNPorts =
|
||||||
|
map (x: {
|
||||||
|
port = x;
|
||||||
|
protocol = "both";
|
||||||
|
})
|
||||||
|
services.openssh.ports;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,7 +80,12 @@ in {
|
|||||||
|
|
||||||
# Port mappings
|
# Port mappings
|
||||||
vpnnamespaces.wg = mkIf cfg.vpn.enable {
|
vpnnamespaces.wg = mkIf cfg.vpn.enable {
|
||||||
portMappings = [{ from = defaultPort; to = defaultPort; }];
|
portMappings = [
|
||||||
|
{
|
||||||
|
from = defaultPort;
|
||||||
|
to = defaultPort;
|
||||||
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
services.nginx = mkIf cfg.vpn.enable {
|
services.nginx = mkIf cfg.vpn.enable {
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ in {
|
|||||||
};
|
};
|
||||||
|
|
||||||
users.groups = mkIf (cfg.group == "prowlarr") {
|
users.groups = mkIf (cfg.group == "prowlarr") {
|
||||||
prowlarr = { };
|
prowlarr = {};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,7 +78,12 @@ in {
|
|||||||
|
|
||||||
# Port mappings
|
# Port mappings
|
||||||
vpnnamespaces.wg = mkIf cfg.vpn.enable {
|
vpnnamespaces.wg = mkIf cfg.vpn.enable {
|
||||||
portMappings = [{ from = defaultPort; to = defaultPort; }];
|
portMappings = [
|
||||||
|
{
|
||||||
|
from = defaultPort;
|
||||||
|
to = defaultPort;
|
||||||
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
services.nginx = mkIf cfg.vpn.enable {
|
services.nginx = mkIf cfg.vpn.enable {
|
||||||
|
|||||||
@@ -76,7 +76,12 @@ in {
|
|||||||
|
|
||||||
# Port mappings
|
# Port mappings
|
||||||
vpnnamespaces.wg = mkIf cfg.vpn.enable {
|
vpnnamespaces.wg = mkIf cfg.vpn.enable {
|
||||||
portMappings = [{ from = defaultPort; to = defaultPort; }];
|
portMappings = [
|
||||||
|
{
|
||||||
|
from = defaultPort;
|
||||||
|
to = defaultPort;
|
||||||
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
services.nginx = mkIf cfg.vpn.enable {
|
services.nginx = mkIf cfg.vpn.enable {
|
||||||
|
|||||||
@@ -82,7 +82,12 @@ in {
|
|||||||
|
|
||||||
# Port mappings
|
# Port mappings
|
||||||
vpnnamespaces.wg = mkIf cfg.vpn.enable {
|
vpnnamespaces.wg = mkIf cfg.vpn.enable {
|
||||||
portMappings = [{ from = defaultPort; to = defaultPort; }];
|
portMappings = [
|
||||||
|
{
|
||||||
|
from = defaultPort;
|
||||||
|
to = defaultPort;
|
||||||
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
services.nginx = mkIf cfg.vpn.enable {
|
services.nginx = mkIf cfg.vpn.enable {
|
||||||
|
|||||||
@@ -91,12 +91,14 @@ in {
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
systemd.tmpfiles.rules = [
|
systemd.tmpfiles.rules =
|
||||||
|
[
|
||||||
"L+ '${cfg.dataDir}'/config.js - - - - ${configJs}"
|
"L+ '${cfg.dataDir}'/config.js - - - - ${configJs}"
|
||||||
"d '${cfg.dataDir}' 0700 ${cfg.user} ${cfg.group} - -"
|
"d '${cfg.dataDir}' 0700 ${cfg.user} ${cfg.group} - -"
|
||||||
] ++ (
|
]
|
||||||
if cfg.settings.outputDir != null then
|
++ (
|
||||||
[ "d '${cfg.settings.outputDir}' 0755 ${cfg.user} ${cfg.group} - -" ]
|
if cfg.settings.outputDir != null
|
||||||
|
then ["d '${cfg.settings.outputDir}' 0755 ${cfg.user} ${cfg.group} - -"]
|
||||||
else []
|
else []
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -109,11 +111,15 @@ in {
|
|||||||
|
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
# Run as root in case that the cfg.credentialsFile is not readable by cross-seed
|
# Run as root in case that the cfg.credentialsFile is not readable by cross-seed
|
||||||
ExecStartPre = [("+" + pkgs.writeShellScript "transmission-prestart" ''
|
ExecStartPre = [
|
||||||
|
(
|
||||||
|
"+"
|
||||||
|
+ pkgs.writeShellScript "transmission-prestart" ''
|
||||||
${pkgs.jq}/bin/jq --slurp add ${settingsFile} '${cfg.credentialsFile}' |
|
${pkgs.jq}/bin/jq --slurp add ${settingsFile} '${cfg.credentialsFile}' |
|
||||||
install -D -m 600 -o '${cfg.user}' /dev/stdin '${cfg.dataDir}/config.json'
|
install -D -m 600 -o '${cfg.user}' /dev/stdin '${cfg.dataDir}/config.json'
|
||||||
''
|
''
|
||||||
)];
|
)
|
||||||
|
];
|
||||||
Type = "simple";
|
Type = "simple";
|
||||||
User = cfg.user;
|
User = cfg.user;
|
||||||
Group = cfg.group;
|
Group = cfg.group;
|
||||||
@@ -130,7 +136,7 @@ in {
|
|||||||
};
|
};
|
||||||
|
|
||||||
users.groups = mkIf (cfg.group == "cross-seed") {
|
users.groups = mkIf (cfg.group == "cross-seed") {
|
||||||
cross-seed = { };
|
cross-seed = {};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,20 +9,22 @@ with lib; let
|
|||||||
nixarr = config.nixarr;
|
nixarr = config.nixarr;
|
||||||
cfg-cross-seed = config.nixarr.transmission.privateTrackers.cross-seed;
|
cfg-cross-seed = config.nixarr.transmission.privateTrackers.cross-seed;
|
||||||
downloadDir = "${nixarr.mediaDir}/torrents";
|
downloadDir = "${nixarr.mediaDir}/torrents";
|
||||||
transmissionCrossSeedScript = with builtins; pkgs.writeShellApplication {
|
transmissionCrossSeedScript = with builtins;
|
||||||
|
pkgs.writeShellApplication {
|
||||||
name = "transmission-cross-seed-script";
|
name = "transmission-cross-seed-script";
|
||||||
|
|
||||||
runtimeInputs = with pkgs; [ curl ];
|
runtimeInputs = with pkgs; [curl];
|
||||||
|
|
||||||
text = ''
|
text = ''
|
||||||
PROWLARR_API_KEY=$(cat prowlarr-api-key)
|
PROWLARR_API_KEY=$(cat prowlarr-api-key)
|
||||||
curl -XPOST http://localhost:2468/api/webhook?apikey="$PROWLARR_API_KEY" --data-urlencode "infoHash=$TR_TORRENT_HASH"
|
curl -XPOST http://localhost:2468/api/webhook?apikey="$PROWLARR_API_KEY" --data-urlencode "infoHash=$TR_TORRENT_HASH"
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
importProwlarrApi = with builtins; pkgs.writeShellApplication {
|
importProwlarrApi = with builtins;
|
||||||
|
pkgs.writeShellApplication {
|
||||||
name = "import-prowlarr-api";
|
name = "import-prowlarr-api";
|
||||||
|
|
||||||
runtimeInputs = with pkgs; [ yq ];
|
runtimeInputs = with pkgs; [yq];
|
||||||
|
|
||||||
text = ''
|
text = ''
|
||||||
touch ${cfg.stateDir}/prowlarr-api-key
|
touch ${cfg.stateDir}/prowlarr-api-key
|
||||||
@@ -31,10 +33,11 @@ with lib; let
|
|||||||
xq -r '.Config.ApiKey' "${nixarr.prowlarr.stateDir}/config.xml" > "${cfg.stateDir}/prowlarr-api-key"
|
xq -r '.Config.ApiKey' "${nixarr.prowlarr.stateDir}/config.xml" > "${cfg.stateDir}/prowlarr-api-key"
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
mkCrossSeedCredentials = with builtins; pkgs.writeShellApplication {
|
mkCrossSeedCredentials = with builtins;
|
||||||
|
pkgs.writeShellApplication {
|
||||||
name = "mk-cross-seed-credentials";
|
name = "mk-cross-seed-credentials";
|
||||||
|
|
||||||
runtimeInputs = with pkgs; [ jq yq ];
|
runtimeInputs = with pkgs; [jq yq];
|
||||||
|
|
||||||
text =
|
text =
|
||||||
"INDEX_LINKS=("
|
"INDEX_LINKS=("
|
||||||
@@ -154,7 +157,7 @@ in {
|
|||||||
indexIds = mkOption {
|
indexIds = mkOption {
|
||||||
type = with types; listOf int;
|
type = with types; listOf int;
|
||||||
default = [];
|
default = [];
|
||||||
example = [ 1 3 7 ];
|
example = [1 3 7];
|
||||||
description = ''
|
description = ''
|
||||||
List of indexer-ids, from prowlarr. These are from the RSS links
|
List of indexer-ids, from prowlarr. These are from the RSS links
|
||||||
for the indexers, located by the "radio" or "RSS" logo on the
|
for the indexers, located by the "radio" or "RSS" logo on the
|
||||||
@@ -259,7 +262,8 @@ in {
|
|||||||
enable = true;
|
enable = true;
|
||||||
dataDir = cfg-cross-seed.stateDir;
|
dataDir = cfg-cross-seed.stateDir;
|
||||||
group = "torrenter";
|
group = "torrenter";
|
||||||
settings = {
|
settings =
|
||||||
|
{
|
||||||
torrentDir = "${nixarr.mediaDir}/torrents";
|
torrentDir = "${nixarr.mediaDir}/torrents";
|
||||||
outputDir = "${nixarr.mediaDir}/torrents/.cross-seed";
|
outputDir = "${nixarr.mediaDir}/torrents/.cross-seed";
|
||||||
transmissionRpcUrl = "http://localhost:${builtins.toString cfg.uiPort}/transmission/rpc";
|
transmissionRpcUrl = "http://localhost:${builtins.toString cfg.uiPort}/transmission/rpc";
|
||||||
@@ -271,19 +275,24 @@ in {
|
|||||||
searchCadence = "1 week";
|
searchCadence = "1 week";
|
||||||
excludeRecentSearch = "1 year";
|
excludeRecentSearch = "1 year";
|
||||||
excludeOlder = "1 year";
|
excludeOlder = "1 year";
|
||||||
} // cfg-cross-seed.extraSettings;
|
}
|
||||||
|
// cfg-cross-seed.extraSettings;
|
||||||
};
|
};
|
||||||
# Run as root in case that the cfg.credentialsFile is not readable by cross-seed
|
# Run as root in case that the cfg.credentialsFile is not readable by cross-seed
|
||||||
systemd.services.cross-seed.serviceConfig = mkIf cfg-cross-seed.enable {
|
systemd.services.cross-seed.serviceConfig = mkIf cfg-cross-seed.enable {
|
||||||
ExecStartPre = mkBefore [(
|
ExecStartPre = mkBefore [
|
||||||
|
(
|
||||||
"+" + "${mkCrossSeedCredentials}/bin/mk-cross-seed-credentials"
|
"+" + "${mkCrossSeedCredentials}/bin/mk-cross-seed-credentials"
|
||||||
)];
|
)
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.services.transmission.serviceConfig = mkIf cfg-cross-seed.enable {
|
systemd.services.transmission.serviceConfig = mkIf cfg-cross-seed.enable {
|
||||||
ExecStartPre = mkBefore [(
|
ExecStartPre = mkBefore [
|
||||||
|
(
|
||||||
"+" + "${importProwlarrApi}/bin/import-prowlarr-api"
|
"+" + "${importProwlarrApi}/bin/import-prowlarr-api"
|
||||||
)];
|
)
|
||||||
|
];
|
||||||
};
|
};
|
||||||
services.transmission = {
|
services.transmission = {
|
||||||
enable = true;
|
enable = true;
|
||||||
@@ -305,7 +314,10 @@ in {
|
|||||||
watch-dir-enabled = true;
|
watch-dir-enabled = true;
|
||||||
watch-dir = "${downloadDir}/.watch";
|
watch-dir = "${downloadDir}/.watch";
|
||||||
|
|
||||||
rpc-bind-address = if cfg.vpn.enable then "192.168.15.1" else "127.0.0.1";
|
rpc-bind-address =
|
||||||
|
if cfg.vpn.enable
|
||||||
|
then "192.168.15.1"
|
||||||
|
else "127.0.0.1";
|
||||||
rpc-port = cfg.uiPort;
|
rpc-port = cfg.uiPort;
|
||||||
# TODO: fix this for ssh tunneling...
|
# TODO: fix this for ssh tunneling...
|
||||||
rpc-whitelist-enabled = true;
|
rpc-whitelist-enabled = true;
|
||||||
@@ -326,8 +338,9 @@ in {
|
|||||||
anti-brute-force-threshold = 10;
|
anti-brute-force-threshold = 10;
|
||||||
|
|
||||||
script-torrent-done-enabled = cfg-cross-seed.enable;
|
script-torrent-done-enabled = cfg-cross-seed.enable;
|
||||||
script-torrent-done-filename = if cfg-cross-seed.enable then
|
script-torrent-done-filename =
|
||||||
"${transmissionCrossSeedScript}/bin/transmission-cross-seed-script"
|
if cfg-cross-seed.enable
|
||||||
|
then "${transmissionCrossSeedScript}/bin/transmission-cross-seed-script"
|
||||||
else null;
|
else null;
|
||||||
|
|
||||||
message-level =
|
message-level =
|
||||||
@@ -358,9 +371,17 @@ in {
|
|||||||
|
|
||||||
# Port mappings
|
# Port mappings
|
||||||
vpnnamespaces.wg = mkIf cfg.vpn.enable {
|
vpnnamespaces.wg = mkIf cfg.vpn.enable {
|
||||||
portMappings = [{ from = cfg.uiPort; to = cfg.uiPort; }];
|
portMappings = [
|
||||||
|
{
|
||||||
|
from = cfg.uiPort;
|
||||||
|
to = cfg.uiPort;
|
||||||
|
}
|
||||||
|
];
|
||||||
openVPNPorts = [
|
openVPNPorts = [
|
||||||
{ port = cfg.peerPort; protocol = "both"; }
|
{
|
||||||
|
port = cfg.peerPort;
|
||||||
|
protocol = "both";
|
||||||
|
}
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
{ lib, buildNpmPackage, fetchFromGitHub }:
|
{
|
||||||
|
lib,
|
||||||
|
buildNpmPackage,
|
||||||
|
fetchFromGitHub,
|
||||||
|
}:
|
||||||
buildNpmPackage rec {
|
buildNpmPackage rec {
|
||||||
pname = "cross-seed";
|
pname = "cross-seed";
|
||||||
version = "5.9.2";
|
version = "5.9.2";
|
||||||
@@ -17,6 +20,5 @@ buildNpmPackage rec {
|
|||||||
description = "cross-seed is an app designed to help you download torrents that you can cross seed based on your existing torrents";
|
description = "cross-seed is an app designed to help you download torrents that you can cross seed based on your existing torrents";
|
||||||
homepage = "https://www.cross-seed.org";
|
homepage = "https://www.cross-seed.org";
|
||||||
license = licenses.asl20;
|
license = licenses.asl20;
|
||||||
maintainers = with maintainers; [ rasmus-kirk ];
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user