Compare commits

..

No commits in common. "7032ddef37fcb244d95894c493cc3586b9c9ceb1" and "11fbbd62eba3f7524e2f73ec27fd4ce8cd21ff6a" have entirely different histories.

20 changed files with 261 additions and 386 deletions

View file

@ -1,27 +0,0 @@
{ lib, ... }:
let
inherit (lib) filter foldl';
in
{
# Count the number of appararitions of each value in a list.
#
# countValues ::
# [ any ] -> ({ any = int; })
countValues =
let
addToCount = acc: x:
let
v = toString x;
in
acc // { ${v} = (acc.${v} or 0) + 1; };
in
foldl' addToCount { };
# Filter a list using a predicate function after applying a map.
#
# mapFilter ::
# (value -> bool)
# (any -> value)
# [ any ]
mapFilter = pred: f: attrs: filter pred (map f attrs);
}

View file

@ -4,12 +4,28 @@ let
cfg = config.my.services.blog;
domain = config.networking.domain;
makeHostInfo = subdomain: {
inherit subdomain;
root = "/var/www/${subdomain}";
makeHostInfo = name: {
name = "${name}.${domain}";
value = "/var/www/${name}";
};
hostsInfo = map makeHostInfo [ "cv" "dev" "key" ];
hostsInfo = [
{
name = domain;
value = "/var/www/blog";
}
] ++ builtins.map makeHostInfo [ "cv" "dev" "key" ];
hosts = builtins.listToAttrs hostsInfo;
makeVirtualHost = with lib.attrsets;
name: root: nameValuePair "${name}" {
forceSSL = true;
useACMEHost = domain;
inherit root;
# Make my blog the default landing site
default = (name == domain);
};
in
{
options.my.services.blog = {
@ -17,17 +33,7 @@ in
};
config = lib.mkIf cfg.enable {
services.nginx.virtualHosts = {
# This is not a subdomain, cannot use my nginx wrapper module
${domain} = {
forceSSL = true;
useACMEHost = domain;
root = "/var/www/blog";
default = true; # Redirect to my blog
};
};
# Those are all subdomains, no problem
my.services.nginx.virtualHosts = hostsInfo;
services.nginx.virtualHosts = with lib.attrsets;
mapAttrs' makeVirtualHost hosts;
};
}

View file

@ -1,6 +1,8 @@
{ config, lib, ... }:
let
cfg = config.my.services.calibre-web;
domain = config.networking.domain;
calibreDomain = "library.${domain}";
in
{
options.my.services.calibre-web = with lib; {
@ -37,12 +39,12 @@ in
};
};
my.services.nginx.virtualHosts = [
{
subdomain = "library";
inherit (cfg) port;
}
];
services.nginx.virtualHosts."${calibreDomain}" = {
forceSSL = true;
useACMEHost = domain;
locations."/".proxyPass = "http://127.0.0.1:${toString cfg.port}/";
};
my.services.backup = {
paths = [

View file

@ -6,6 +6,9 @@
let
cfg = config.my.services.drone;
domain = config.networking.domain;
droneDomain = "drone.${domain}";
hasRunner = (name: builtins.elem name cfg.runners);
execPkg = pkgs.drone-runner-exec;
@ -56,7 +59,7 @@ in
];
Environment = [
"DRONE_DATABASE_DATASOURCE=postgres:///drone?host=/run/postgresql"
"DRONE_SERVER_HOST=drone.${config.networking.domain}"
"DRONE_SERVER_HOST=${droneDomain}"
"DRONE_SERVER_PROTO=https"
"DRONE_DATABASE_DRIVER=postgres"
"DRONE_SERVER_PORT=:${toString cfg.port}"
@ -88,12 +91,12 @@ in
}];
};
my.services.nginx.virtualHosts = [
{
subdomain = "drone";
inherit (cfg) port;
}
];
services.nginx.virtualHosts."${droneDomain}" = {
forceSSL = true;
useACMEHost = domain;
locations."/".proxyPass = "http://127.0.0.1:${toString cfg.port}";
};
# Docker runner
systemd.services.drone-runner-docker = lib.mkIf (hasRunner "docker") {
@ -104,7 +107,7 @@ in
confinement.enable = true;
serviceConfig = {
Environment = [
"DRONE_SERVER_HOST=drone.${config.networking.domain}"
"DRONE_SERVER_HOST=${droneDomain}"
"DRONE_SERVER_PROTO=https"
"DRONE_RUNNER_CAPACITY=10"
"CLIENT_DRONE_RPC_HOST=127.0.0.1:${toString cfg.port}"
@ -153,7 +156,7 @@ in
];
serviceConfig = {
Environment = [
"DRONE_SERVER_HOST=drone.${config.networking.domain}"
"DRONE_SERVER_HOST=${droneDomain}"
"DRONE_SERVER_PROTO=https"
"DRONE_RUNNER_CAPACITY=10"
"CLIENT_DRONE_RPC_HOST=127.0.0.1:${toString cfg.port}"

View file

@ -2,6 +2,9 @@
{ config, lib, pkgs, ... }:
let
cfg = config.my.services.flood;
domain = config.networking.domain;
webuiDomain = "flood.${domain}";
in
{
options.my.services.flood = with lib; {
@ -40,11 +43,11 @@ in
};
};
my.services.nginx.virtualHosts = [
{
subdomain = "flood";
inherit (cfg) port;
}
];
services.nginx.virtualHosts."${webuiDomain}" = {
forceSSL = true;
useACMEHost = domain;
locations."/".proxyPass = "http://127.0.0.1:${toString cfg.port}";
};
};
}

View file

@ -2,6 +2,8 @@
{ config, lib, ... }:
let
cfg = config.my.services.gitea;
domain = config.networking.domain;
giteaDomain = "gitea.${config.networking.domain}";
in
{
options.my.services.gitea = with lib; {
@ -15,38 +17,34 @@ in
};
config = lib.mkIf cfg.enable {
services.gitea =
let
giteaDomain = "gitea.${config.networking.domain}";
in
{
enable = true;
services.gitea = {
enable = true;
appName = "Ambroisie's forge";
httpPort = cfg.port;
domain = giteaDomain;
rootUrl = "https://${giteaDomain}";
appName = "Ambroisie's forge";
httpPort = cfg.port;
domain = giteaDomain;
rootUrl = "https://${giteaDomain}";
user = "git";
lfs.enable = true;
user = "git";
lfs.enable = true;
useWizard = false;
disableRegistration = true;
useWizard = false;
disableRegistration = true;
# only send cookies via HTTPS
cookieSecure = true;
# only send cookies via HTTPS
cookieSecure = true;
database = {
type = "postgres"; # Automatic setup
user = "git"; # User needs to be the same as gitea user
};
# NixOS module uses `gitea dump` to backup repositories and the database,
# but it produces a single .zip file that's not very backup friendly.
# I configure my backup system manually below.
dump.enable = false;
database = {
type = "postgres"; # Automatic setup
user = "git"; # User needs to be the same as gitea user
};
# NixOS module uses `gitea dump` to backup repositories and the database,
# but it produces a single .zip file that's not very backup friendly.
# I configure my backup system manually below.
dump.enable = false;
};
users.users.git = {
description = "Gitea Service";
home = config.services.gitea.stateDir;
@ -62,12 +60,12 @@ in
users.groups.git = { };
# Proxy to Gitea
my.services.nginx.virtualHosts = [
{
subdomain = "gitea";
inherit (cfg) port;
}
];
services.nginx.virtualHosts."${giteaDomain}" = {
forceSSL = true;
useACMEHost = domain;
locations."/".proxyPass = "http://127.0.0.1:${toString cfg.port}/";
};
my.services.backup = {
paths = [

View file

@ -3,6 +3,10 @@
let
cfg = config.my.services.indexers;
domain = config.networking.domain;
jackettDomain = "jackett.${config.networking.domain}";
nzbhydraDomain = "nzbhydra.${config.networking.domain}";
jackettPort = 9117;
nzbhydraPort = 5076;
in
@ -25,19 +29,25 @@ in
};
};
services.nginx.virtualHosts."${jackettDomain}" =
lib.mkIf cfg.jackett.enable {
forceSSL = true;
useACMEHost = domain;
locations."/".proxyPass = "http://127.0.0.1:${toString jackettPort}/";
};
services.nzbhydra2 = lib.mkIf cfg.nzbhydra.enable {
enable = true;
};
my.services.nginx.virtualHosts = [
{
subdomain = "jackett";
port = jackettPort;
}
{
subdomain = "nzbhydra";
port = nzbhydraPort;
}
];
services.nginx.virtualHosts."${nzbhydraDomain}" =
lib.mkIf cfg.nzbhydra.enable {
forceSSL = true;
useACMEHost = domain;
locations."/".proxyPass = "http://127.0.0.1:${toString nzbhydraPort}/";
};
};
}

View file

@ -2,6 +2,8 @@
{ config, lib, ... }:
let
cfg = config.my.services.jellyfin;
domain = config.networking.domain;
jellyfinDomain = "jellyfin.${config.networking.domain}";
in
{
options.my.services.jellyfin = {
@ -14,23 +16,22 @@ in
group = "media";
};
my.services.nginx.virtualHosts = [
{
subdomain = "jellyfin";
port = 8096;
extraConfig = {
locations."/" = {
extraConfig = ''
proxy_buffering off;
'';
};
# Too bad for the repetition...
locations."/socket" = {
proxyPass = "http://127.0.0.1:8096/";
proxyWebsockets = true;
};
};
}
];
# Proxy to Jellyfin
services.nginx.virtualHosts."${jellyfinDomain}" = {
forceSSL = true;
useACMEHost = domain;
locations."/" = {
proxyPass = "http://127.0.0.1:8096/";
extraConfig = ''
proxy_buffering off;
'';
};
locations."/socket" = {
proxyPass = "http://127.0.0.1:8096/";
proxyWebsockets = true;
};
};
};
}

View file

@ -4,6 +4,9 @@ let
cfg = config.my.services.lohr;
settingsFormat = pkgs.formats.yaml { };
domain = config.networking.domain;
lohrDomain = "lohr.${config.networking.domain}";
lohrPkg = pkgs.ambroisie.lohr;
in
{
@ -72,11 +75,13 @@ in
};
users.groups.lohr = { };
my.services.nginx.virtualHosts = [
{
subdomain = "lohr";
inherit (cfg) port;
}
];
services.nginx.virtualHosts."${lohrDomain}" = {
forceSSL = true;
useACMEHost = domain;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString cfg.port}/";
};
};
};
}

View file

@ -118,35 +118,6 @@ in
'';
};
my.services.nginx.virtualHosts = [
# Element Web app deployment
{
subdomain = "chat";
root = pkgs.element-web.override {
conf = {
default_server_config = {
"m.homeserver" = {
"base_url" = "https://matrix.${domain}";
"server_name" = domain;
};
"m.identity_server" = {
"base_url" = "https://vector.im";
};
};
showLabsSettings = true;
defaultCountryCode = "FR"; # cocorico
roomDirectory = {
"servers" = [
"matrix.org"
"mozilla.org"
];
};
};
};
}
];
# Those are too complicated to use my wrapper...
services.nginx.virtualHosts = {
"matrix.${domain}" = {
onlySSL = true;
@ -221,6 +192,34 @@ in
return 200 '${builtins.toJSON client}';
'';
};
# Element Web app deployment
"chat.${domain}" = {
useACMEHost = domain;
forceSSL = true;
root = pkgs.element-web.override {
conf = {
default_server_config = {
"m.homeserver" = {
"base_url" = "https://matrix.${domain}";
"server_name" = domain;
};
"m.identity_server" = {
"base_url" = "https://vector.im";
};
};
showLabsSettings = true;
defaultCountryCode = "FR"; # cocorico
roomDirectory = {
"servers" = [
"matrix.org"
"mozilla.org"
];
};
};
};
};
};
# For administration tools.

View file

@ -2,6 +2,9 @@
{ config, lib, ... }:
let
cfg = config.my.services.miniflux;
domain = config.networking.domain;
minifluxDomain = "reader.${config.networking.domain}";
in
{
options.my.services.miniflux = with lib; {
@ -20,7 +23,7 @@ in
description = "Password of the admin user";
};
port = mkOption {
privatePort = mkOption {
type = types.port;
default = 9876;
example = 8080;
@ -42,8 +45,8 @@ in
config = {
# Virtual hosts settings
BASE_URL = "https://reader.${config.networking.domain}";
LISTEN_ADDR = "localhost:${toString cfg.port}";
BASE_URL = "https://${minifluxDomain}";
LISTEN_ADDR = "localhost:${toString cfg.privatePort}";
# I want fast updates
POLLING_FREQUENCY = "30";
BATCH_SIZE = "50";
@ -53,11 +56,12 @@ in
};
};
my.services.nginx.virtualHosts = [
{
subdomain = "reader";
inherit (cfg) port;
}
];
# Proxy to Jellyfin
services.nginx.virtualHosts."${minifluxDomain}" = {
forceSSL = true;
useACMEHost = domain;
locations."/".proxyPass = "http://127.0.0.1:${toString cfg.privatePort}/";
};
};
}

View file

@ -2,6 +2,9 @@
{ config, lib, pkgs, ... }:
let
cfg = config.my.services.monitoring;
domain = config.networking.domain;
grafanaDomain = "monitoring.${config.networking.domain}";
in
{
options.my.services.monitoring = with lib; {
@ -49,7 +52,7 @@ in
config = lib.mkIf cfg.enable {
services.grafana = {
enable = true;
domain = "monitoring.${config.networking.domain}";
domain = grafanaDomain;
port = cfg.grafana.port;
addr = "127.0.0.1"; # Proxied through Nginx
@ -112,11 +115,16 @@ in
];
};
my.services.nginx.virtualHosts = [
{
subdomain = "monitoring";
inherit (cfg.grafana) port;
}
];
services.nginx = {
virtualHosts.${grafanaDomain} = {
forceSSL = true;
useACMEHost = domain;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString cfg.grafana.port}";
proxyWebsockets = true;
};
};
};
};
}

View file

@ -2,6 +2,8 @@
{ config, lib, pkgs, ... }:
let
cfg = config.my.services.navidrome;
domain = config.networking.domain;
navidromeDomain = "music.${config.networking.domain}";
in
{
options.my.services.navidrome = with lib; {
@ -21,7 +23,7 @@ in
'';
};
port = mkOption {
privatePort = mkOption {
type = types.port;
default = 4533;
example = 8080;
@ -40,18 +42,21 @@ in
enable = true;
settings = cfg.settings // {
Port = cfg.port;
Port = cfg.privatePort;
Address = "127.0.0.1"; # Behind reverse proxy, so only loopback
MusicFolder = cfg.musicFolder;
LogLevel = "info";
};
};
my.services.nginx.virtualHosts = [
{
subdomain = "music";
inherit (cfg) port;
}
];
services.nginx.virtualHosts."${navidromeDomain}" = {
forceSSL = true;
useACMEHost = domain;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString cfg.privatePort}/";
proxyWebsockets = true;
};
};
};
}

View file

@ -2,6 +2,8 @@
{ config, lib, pkgs, ... }:
let
cfg = config.my.services.nextcloud;
domain = config.networking.domain;
nextcloudDomain = "nextcloud.${config.networking.domain}";
in
{
options.my.services.nextcloud = with lib; {
@ -29,7 +31,7 @@ in
services.nextcloud = {
enable = true;
package = pkgs.nextcloud22;
hostName = "nextcloud.${config.networking.domain}";
hostName = nextcloudDomain;
home = "/var/lib/nextcloud";
maxUploadSize = cfg.maxSize;
config = {
@ -57,10 +59,11 @@ in
after = [ "postgresql.service" ];
};
# The service above configures the domain, no need for my wrapper
services.nginx.virtualHosts."nextcloud.${config.networking.domain}" = {
services.nginx.virtualHosts."${nextcloudDomain}" = {
forceSSL = true;
useACMEHost = config.networking.domain;
useACMEHost = domain;
locations."/".proxyPass = "http://127.0.0.1:3000/";
};
my.services.backup = {

View file

@ -1,147 +1,12 @@
# A simple abstraction layer for almost all of my services' needs
# Configuration shamelessly stolen from [1]
#
# [1]: https://github.com/delroth/infra.delroth.net/blob/master/common/nginx.nix
{ config, lib, pkgs, ... }:
let
cfg = config.my.services.nginx;
virtualHostOption = with lib; types.submodule {
options = {
subdomain = mkOption {
type = types.str;
example = "dev";
description = ''
Which subdomain, under config.networking.domain, to use
for this virtual host.
'';
};
port = mkOption {
type = with types; nullOr port;
default = null;
example = 8080;
description = ''
Which port to proxy to, through 127.0.0.1, for this virtual host.
This option is incompatible with `root`.
'';
};
root = mkOption {
type = with types; nullOr path;
default = null;
example = "/var/www/blog";
description = ''
The root folder for this virtual host. This option is incompatible
with `port`.
'';
};
extraConfig = mkOption {
type = types.attrs; # FIXME: forward type of virtualHosts
example = litteralExample ''
{
locations."/socket" = {
proxyPass = "http://127.0.0.1:8096/";
proxyWebsockets = true;
};
}
'';
default = { };
description = ''
Any extra configuration that should be applied to this virtual host.
'';
};
};
};
in
{
options.my.services.nginx = with lib; {
enable =
mkEnableOption "Nginx, activates when `virtualHosts` is not empty" // {
default = builtins.length cfg.virtualHosts != 0;
};
monitoring = {
enable = my.mkDisableOption "monitoring through grafana and prometheus";
};
virtualHosts = mkOption {
type = types.listOf virtualHostOption;
default = [ ];
example = litteralExample ''
[
{
subdomain = "gitea";
port = 8080;
}
{
subdomain = "dev";
root = "/var/www/dev";
}
{
subdomain = "jellyfin";
port = 8096;
extraConfig = {
locations."/socket" = {
proxyPass = "http://127.0.0.1:8096/";
proxyWebsockets = true;
};
};
}
]
'';
description = ''
List of virtual hosts to set-up using default settings.
'';
};
};
config = lib.mkIf cfg.enable {
assertions = [ ]
++ (lib.flip builtins.map cfg.virtualHosts ({ subdomain, ... } @ args:
let
conflicts = [ "port" "root" ];
optionsNotNull = builtins.map (v: args.${v} != null) conflicts;
optionsSet = lib.filter lib.id optionsNotNull;
in
{
assertion = builtins.length optionsSet == 1;
message = ''
Subdomain '${subdomain}' must have exactly one of ${
lib.concatStringsSep ", " (builtins.map (v: "'${v}'") conflicts)
} configured.
'';
}))
++ (
let
ports = lib.my.mapFilter
(v: v != null)
({ port, ... }: port)
cfg.virtualHosts;
portCounts = lib.my.countValues ports;
nonUniquesCounts = lib.filterAttrs (_: v: v != 1) portCounts;
nonUniques = builtins.attrNames nonUniquesCounts;
mkAssertion = port: {
assertion = false;
message = "Port ${port} cannot appear in multiple virtual hosts.";
};
in
map mkAssertion nonUniques
) ++ (
let
subs = map ({ subdomain, ... }: subdomain) cfg.virtualHosts;
subsCounts = lib.my.countValues subs;
nonUniquesCounts = lib.filterAttrs (_: v: v != 1) subsCounts;
nonUniques = builtins.attrNames nonUniquesCounts;
mkAssertion = v: {
assertion = false;
message = ''
Subdomain '${v}' cannot appear in multiple virtual hosts.
'';
};
in
map mkAssertion nonUniques
)
;
# Whenever something defines an nginx vhost, ensure that nginx defaults are
# properly set.
config = lib.mkIf ((builtins.attrNames config.services.nginx.virtualHosts) != [ ]) {
services.nginx = {
enable = true;
statusPage = true; # For monitoring scraping.
@ -150,33 +15,6 @@ in
recommendedOptimisation = true;
recommendedTlsSettings = true;
recommendedProxySettings = true;
virtualHosts =
let
domain = config.networking.domain;
mkVHost = ({ subdomain, ... } @ args: lib.nameValuePair
"${subdomain}.${domain}"
(builtins.foldl' lib.recursiveUpdate { } [
# Base configuration
{
forceSSL = true;
useACMEHost = domain;
}
# Proxy to port
(lib.optionalAttrs (args.port != null) {
locations."/".proxyPass =
"http://127.0.0.1:${toString args.port}";
})
# Serve filesystem content
(lib.optionalAttrs (args.root != null) {
inherit (args) root;
})
# VHost specific configuration
args.extraConfig
])
);
in
lib.my.genAttrs' cfg.virtualHosts mkVHost;
};
networking.firewall.allowedTCPPorts = [ 80 443 ];
@ -184,10 +22,10 @@ in
# Nginx needs to be able to read the certificates
users.users.nginx.extraGroups = [ "acme" ];
# Use DNS wildcard certificate
security.acme = {
email = "bruno.acme@belanyi.fr";
acceptTerms = true;
# Use DNS wildcard certificate
certs =
let
domain = config.networking.domain;
@ -202,8 +40,8 @@ in
};
};
};
services.grafana.provision.dashboards = lib.mkIf cfg.monitoring.enable [
# Setup monitoring
services.grafana.provision.dashboards = [
{
name = "NGINX";
options.path = pkgs.nur.repos.alarsyo.grafanaDashboards.nginx;
@ -211,7 +49,7 @@ in
}
];
services.prometheus = lib.mkIf cfg.monitoring.enable {
services.prometheus = {
exporters.nginx = {
enable = true;
listenAddress = "127.0.0.1";

View file

@ -5,6 +5,7 @@
{ config, lib, ... }:
let
cfg = config.my.services.pirate;
domain = config.networking.domain;
ports = {
sonarr = 8989;
@ -21,8 +22,15 @@ let
})
ports);
redirections = lib.flip lib.mapAttrsToList ports
(subdomain: port: { inherit subdomain port; });
redirections = with lib.attrsets;
(mapAttrs'
(service: port: nameValuePair "${service}.${domain}" {
forceSSL = true;
useACMEHost = domain;
locations."/".proxyPass = "http://127.0.0.1:${builtins.toString port}/";
})
ports);
in
{
options.my.services.pirate = {
@ -30,7 +38,6 @@ in
};
config = lib.mkIf cfg.enable {
services = managers;
my.services.nginx.virtualHosts = redirections;
services = managers // { nginx.virtualHosts = redirections; };
};
}

View file

@ -2,6 +2,9 @@
{ config, lib, pkgs, ... }:
let
cfg = config.my.services.podgrab;
domain = config.networking.domain;
podgrabDomain = "podgrab.${domain}";
in
{
options.my.services.podgrab = with lib; {
@ -31,11 +34,11 @@ in
inherit (cfg) passwordFile port;
};
my.services.nginx.virtualHosts = [
{
subdomain = "podgrab";
inherit (cfg) port;
}
];
services.nginx.virtualHosts."${podgrabDomain}" = {
forceSSL = true;
useACMEHost = domain;
locations."/".proxyPass = "http://127.0.0.1:${toString cfg.port}";
};
};
}

View file

@ -2,6 +2,8 @@
{ config, lib, ... }:
let
cfg = config.my.services.rss-bridge;
domain = config.networking.domain;
rss-bridgeDomain = "rss-bridge.${config.networking.domain}";
in
{
options.my.services.rss-bridge = {
@ -12,13 +14,12 @@ in
services.rss-bridge = {
enable = true;
whitelist = [ "*" ]; # Whitelist all
virtualHost = "rss-bridge.${config.networking.domain}";
virtualHost = rss-bridgeDomain; # Setup virtual host
};
# The service above configures the domain, no need for my wrapper
services.nginx.virtualHosts."rss-bridge.${config.networking.domain}" = {
services.nginx.virtualHosts."${rss-bridgeDomain}" = {
forceSSL = true;
useACMEHost = config.networking.domain;
useACMEHost = domain;
};
};
}

View file

@ -2,6 +2,9 @@
{ config, lib, ... }:
let
cfg = config.my.services.sabnzbd;
domain = config.networking.domain;
sabnzbdDomain = "sabnzbd.${domain}";
port = 9090; # NOTE: not declaratively set...
in
{
@ -15,11 +18,11 @@ in
group = "media";
};
my.services.nginx.virtualHosts = [
{
subdomain = "sabnzbd";
inherit port;
}
];
services.nginx.virtualHosts."${sabnzbdDomain}" = {
forceSSL = true;
useACMEHost = domain;
locations."/".proxyPass = "http://127.0.0.1:${toString port}";
};
};
}

View file

@ -6,6 +6,9 @@
{ config, lib, ... }:
let
cfg = config.my.services.transmission;
domain = config.networking.domain;
webuiDomain = "transmission.${domain}";
in
{
options.my.services.transmission = with lib; {
@ -31,7 +34,7 @@ in
description = "Download base directory";
};
port = mkOption {
privatePort = mkOption {
type = types.port;
default = 9091;
example = 8080;
@ -60,7 +63,7 @@ in
peer-port = cfg.peerPort;
rpc-enabled = true;
rpc-port = cfg.port;
rpc-port = cfg.privatePort;
rpc-authentication-required = true;
rpc-username = cfg.username;
@ -74,12 +77,12 @@ in
# Default transmission webui, I prefer combustion but its development
# seems to have stalled
my.services.nginx.virtualHosts = [
{
subdomain = "transmission";
inherit (cfg) port;
}
];
services.nginx.virtualHosts."${webuiDomain}" = {
forceSSL = true;
useACMEHost = domain;
locations."/".proxyPass = "http://127.0.0.1:${toString cfg.privatePort}";
};
networking.firewall = {
allowedTCPPorts = [ cfg.peerPort ];