Compare commits
No commits in common. "596081838e529f0cf4b0d47091b8b30874900d8d" and "a1f92323dd5301448de13707d1a2420e87970674" have entirely different histories.
596081838e
...
a1f92323dd
28
flake.lock
generated
28
flake.lock
generated
@ -8,11 +8,11 @@
|
|||||||
"systems": "systems"
|
"systems": "systems"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1754433428,
|
"lastModified": 1750173260,
|
||||||
"narHash": "sha256-NA/FT2hVhKDftbHSwVnoRTFhes62+7dxZbxj5Gxvghs=",
|
"narHash": "sha256-9P1FziAwl5+3edkfFcr5HeGtQUtrSdk/MksX39GieoA=",
|
||||||
"owner": "ryantm",
|
"owner": "ryantm",
|
||||||
"repo": "agenix",
|
"repo": "agenix",
|
||||||
"rev": "9edb1787864c4f59ae5074ad498b6272b3ec308d",
|
"rev": "531beac616433bac6f9e2a19feb8e99a22a66baf",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -152,27 +152,27 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1754028485,
|
"lastModified": 1745391562,
|
||||||
"narHash": "sha256-IiiXB3BDTi6UqzAZcf2S797hWEPCRZOwyNThJIYhUfk=",
|
"narHash": "sha256-sPwcCYuiEopaafePqlG826tBhctuJsLx/mhKKM5Fmjo=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "59e69648d345d6e8fef86158c555730fa12af9de",
|
"rev": "8a2f738d9d1f1d986b5a4cd2fd2061a7127237d7",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"ref": "nixos-25.05",
|
"ref": "nixos-unstable",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs-master": {
|
"nixpkgs-master": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1754468877,
|
"lastModified": 1753715863,
|
||||||
"narHash": "sha256-4f2CMXEM6PtLcfIC5Emo4pYaj+yLizWEQAekSwy4gzQ=",
|
"narHash": "sha256-wUsY8bZpLBa7rkJuqsVKLuzFSEvGRUcoCU5HGiDbM5o=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "5b7d804f77c2e9e89ddd527ed6a5e5bf77f0a826",
|
"rev": "6a7d91d53ac0fdf6dffac103b616a548938f84fc",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -200,17 +200,17 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs_3": {
|
"nixpkgs_3": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1754292888,
|
"lastModified": 1754028485,
|
||||||
"narHash": "sha256-1ziydHSiDuSnaiPzCQh1mRFBsM2d2yRX9I+5OPGEmIE=",
|
"narHash": "sha256-IiiXB3BDTi6UqzAZcf2S797hWEPCRZOwyNThJIYhUfk=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "ce01daebf8489ba97bd1609d185ea276efdeb121",
|
"rev": "59e69648d345d6e8fef86158c555730fa12af9de",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "ce01daebf8489ba97bd1609d185ea276efdeb121",
|
"rev": "59e69648d345d6e8fef86158c555730fa12af9de",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/ce01daebf8489ba97bd1609d185ea276efdeb121";
|
nixpkgs.url = "github:NixOS/nixpkgs/59e69648d345d6e8fef86158c555730fa12af9de";
|
||||||
nixos-unstable.url = "github:NixOS/nixpkgs/5b09dc45f24cf32316283e62aec81ffee3c3e376";
|
nixos-unstable.url = "github:NixOS/nixpkgs/5b09dc45f24cf32316283e62aec81ffee3c3e376";
|
||||||
nixpkgs-master.url = "github:NixOS/nixpkgs/master";
|
nixpkgs-master.url = "github:NixOS/nixpkgs/master";
|
||||||
local-unstable.url = "path:///home/giulio/dev/nixpkgs";
|
local-unstable.url = "path:///home/giulio/dev/nixpkgs";
|
||||||
|
39
hosts/architect/calibre.nix
Normal file
39
hosts/architect/calibre.nix
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
{ config, lib, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
domain = "books.giugl.io";
|
||||||
|
auth_block = (import ./openid.nix { inherit lib; }).openresty_oidc_block;
|
||||||
|
|
||||||
|
utilities = import ./utilities.nix { inherit lib config; };
|
||||||
|
inherit (utilities) architectInterfaceAddress;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
services = {
|
||||||
|
calibre-web = {
|
||||||
|
enable = true;
|
||||||
|
group = "media";
|
||||||
|
options = {
|
||||||
|
enableBookConversion = true;
|
||||||
|
enableBookUploading = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
nginx.virtualHosts.${domain} = {
|
||||||
|
forceSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
locations."/" = {
|
||||||
|
proxyPass = "http://127.0.0.1:8083";
|
||||||
|
extraConfig = ''
|
||||||
|
client_max_body_size 500M;
|
||||||
|
'' + auth_block { access_role = "calibre"; };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.extraHosts = ''
|
||||||
|
${architectInterfaceAddress "lan"} ${domain}
|
||||||
|
${architectInterfaceAddress "tailscale"} ${domain}
|
||||||
|
'';
|
||||||
|
|
||||||
|
users.groups.media.members = [ "calibre-web" ];
|
||||||
|
}
|
@ -19,6 +19,7 @@ in
|
|||||||
./tailscale.nix
|
./tailscale.nix
|
||||||
./sunshine.nix
|
./sunshine.nix
|
||||||
./postgres.nix
|
./postgres.nix
|
||||||
|
./netdata.nix
|
||||||
./searx.nix
|
./searx.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -139,21 +140,25 @@ in
|
|||||||
radarr = {
|
radarr = {
|
||||||
enable = true;
|
enable = true;
|
||||||
domain = "htrad.giugl.io";
|
domain = "htrad.giugl.io";
|
||||||
|
package = pkgs.unstablePkgs.radarr;
|
||||||
};
|
};
|
||||||
|
|
||||||
sonarr = {
|
sonarr = {
|
||||||
enable = true;
|
enable = true;
|
||||||
domain = "htson.giugl.io";
|
domain = "htson.giugl.io";
|
||||||
|
package = pkgs.unstablePkgs.sonarr;
|
||||||
};
|
};
|
||||||
|
|
||||||
bazarr = {
|
bazarr = {
|
||||||
enable = true;
|
enable = true;
|
||||||
domain = "htbaz.giugl.io";
|
domain = "htbaz.giugl.io";
|
||||||
|
package = pkgs.unstablePkgs.bazarr;
|
||||||
};
|
};
|
||||||
|
|
||||||
nzbget = {
|
nzbget = {
|
||||||
enable = true;
|
enable = true;
|
||||||
domain = "htnzb.giugl.io";
|
domain = "htnzb.giugl.io";
|
||||||
|
package = pkgs.unstablePkgs.nzbget;
|
||||||
};
|
};
|
||||||
|
|
||||||
jellyfin = {
|
jellyfin = {
|
||||||
@ -188,7 +193,7 @@ in
|
|||||||
|
|
||||||
llm = {
|
llm = {
|
||||||
enable = true;
|
enable = true;
|
||||||
package = pkgs.masterPkgs.ollama-cuda;
|
package = pkgs.unstablePkgs.ollama-cuda;
|
||||||
backendDomain = "ollama.giugl.io";
|
backendDomain = "ollama.giugl.io";
|
||||||
acceleration = "cuda";
|
acceleration = "cuda";
|
||||||
|
|
||||||
@ -225,6 +230,17 @@ in
|
|||||||
domain = "music.giugl.io";
|
domain = "music.giugl.io";
|
||||||
package = pkgs.unstablePkgs.navidrome;
|
package = pkgs.unstablePkgs.navidrome;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
languagetool = {
|
||||||
|
enable = true;
|
||||||
|
domain = "lang.giugl.io";
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
whisparr = {
|
||||||
|
enable = true;
|
||||||
|
domain = "whisparr.giugl.io";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
22
hosts/architect/invidious.nix
Normal file
22
hosts/architect/invidious.nix
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
domain = "tube.giugl.io";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
services.invidious = {
|
||||||
|
enable = true;
|
||||||
|
package = pkgs.unstablePkgs.invidious;
|
||||||
|
settings = {
|
||||||
|
hmac_key = "a2a91eca269d26de1221285e8981879834045bff";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
architect.vhost.${domain} = {
|
||||||
|
dnsInterfaces = [ "lan" "tailscale" ];
|
||||||
|
locations."/" = {
|
||||||
|
port = config.services.invidious.port;
|
||||||
|
allowWAN = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
82
hosts/architect/librephotos.nix
Normal file
82
hosts/architect/librephotos.nix
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
{ config, lib, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
domain = "photos.giugl.io";
|
||||||
|
backendPort = 8001;
|
||||||
|
frontendPort = 3000;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
architect.vhost.${domain} = {
|
||||||
|
dnsInterfaces = [ "tailscale" ];
|
||||||
|
|
||||||
|
locations."/" = {
|
||||||
|
host = "172.17.0.1";
|
||||||
|
port = frontendPort;
|
||||||
|
# allowLan = true;
|
||||||
|
# allow = [ config.architect.networks."tailscale".net ];
|
||||||
|
};
|
||||||
|
|
||||||
|
locations."~ ^/(api|media)/" = {
|
||||||
|
host = "172.17.0.1";
|
||||||
|
port = backendPort;
|
||||||
|
# allowLan = true;
|
||||||
|
# allow = [ config.architect.networks."tailscale".net ];
|
||||||
|
};
|
||||||
|
|
||||||
|
locations."/ws" = {
|
||||||
|
host = "172.17.0.1";
|
||||||
|
port = backendPort;
|
||||||
|
proxyWebsockets = true;
|
||||||
|
# allowLan = true;
|
||||||
|
# allow = [ config.architect.networks."tailscale".net ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services.redis.servers."librephotos" = {
|
||||||
|
enable = true;
|
||||||
|
port = 1233;
|
||||||
|
bind = "172.17.0.1";
|
||||||
|
extraParams = [ "--protected-mode no" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
virtualisation.oci-containers = {
|
||||||
|
containers = {
|
||||||
|
librephotos-front = {
|
||||||
|
image = "reallibrephotos/librephotos-frontend:latest";
|
||||||
|
autoStart = true;
|
||||||
|
ports = [
|
||||||
|
"172.17.0.1:${toString frontendPort}:${toString frontendPort}"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
librephotos-back = {
|
||||||
|
image = "reallibrephotos/librephotos:latest";
|
||||||
|
autoStart = true;
|
||||||
|
|
||||||
|
ports = [
|
||||||
|
"172.17.0.1:${toString backendPort}:${toString backendPort}"
|
||||||
|
];
|
||||||
|
|
||||||
|
environment = {
|
||||||
|
SECRET_KEY = "LOLOL";
|
||||||
|
BACKEND_HOST = domain;
|
||||||
|
ADMIN_EMAIL = "me@giugl.io";
|
||||||
|
ADMIN_USERNAME = "giulio";
|
||||||
|
ADMIN_PASSWORD = "giulio";
|
||||||
|
ALLOWED_HOSTS = domain;
|
||||||
|
DB_BACKEND = "mysql";
|
||||||
|
DB_NAME = "librephotos";
|
||||||
|
DB_USER = "librephotos";
|
||||||
|
DB_PASS = "librephotos";
|
||||||
|
DB_HOST = "172.17.0.1";
|
||||||
|
DB_PORT = toString config.services.mysql.settings.mysqld.port;
|
||||||
|
REDIS_HOST = "172.17.0.1";
|
||||||
|
REDIS_PORT = toString config.services.redis.servers."librephotos".port;
|
||||||
|
MAPBOX_API_KEY = "SOME_KEY";
|
||||||
|
WEB_CONCURRENCY = "24";
|
||||||
|
DEBUG = "0";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
25
hosts/architect/lidarr.nix
Normal file
25
hosts/architect/lidarr.nix
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{ config, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
domain = "htlid.giugl.io";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
services = {
|
||||||
|
lidarr = {
|
||||||
|
enable = true;
|
||||||
|
group = "media";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
architect.vhost.${domain} = {
|
||||||
|
dnsInterfaces = [ "lan" "tailscale" ];
|
||||||
|
locations."/" = {
|
||||||
|
port = 8686;
|
||||||
|
allowLan = true;
|
||||||
|
allowWAN = false;
|
||||||
|
allow = [ config.architect.networks."tailscale".net ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
users.groups.media.members = [ "lidarr" ];
|
||||||
|
}
|
26
hosts/architect/netdata.nix
Normal file
26
hosts/architect/netdata.nix
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{ config, pkgs, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
domain = "monitor.giugl.io";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
services.netdata = {
|
||||||
|
enable = true;
|
||||||
|
package = pkgs.unstablePkgs.netdata;
|
||||||
|
config = {
|
||||||
|
db.mode = "dbengine";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
architect.vhost.${domain} = with config.architect.networks; {
|
||||||
|
dnsInterfaces = [ "tailscale" "lan" ];
|
||||||
|
|
||||||
|
locations."/" = {
|
||||||
|
port = 19999;
|
||||||
|
allowLan = true;
|
||||||
|
allow = [
|
||||||
|
tailscale.net
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
24
hosts/architect/nzbget.nix
Normal file
24
hosts/architect/nzbget.nix
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{ config, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
domain = "htnzb.giugl.io";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
services.nzbget = {
|
||||||
|
enable = true;
|
||||||
|
group = "media";
|
||||||
|
};
|
||||||
|
|
||||||
|
architect.vhost.${domain} = with config.architect.networks; {
|
||||||
|
dnsInterfaces = [ "tailscale" "lan" ];
|
||||||
|
|
||||||
|
locations."/" = {
|
||||||
|
port = 6789;
|
||||||
|
allowLan = true;
|
||||||
|
|
||||||
|
allow = [ tailscale.net ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
users.groups.media.members = [ "nzbget" ];
|
||||||
|
}
|
50
hosts/architect/openid.nix
Normal file
50
hosts/architect/openid.nix
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
{ lib }:
|
||||||
|
|
||||||
|
{
|
||||||
|
openresty_oidc_block =
|
||||||
|
{ access_role ? "", whitelisted_ips ? [ ] }: ''
|
||||||
|
|
||||||
|
'';
|
||||||
|
# access_by_lua_block {
|
||||||
|
# local opts = {
|
||||||
|
# discovery = "https://auth.giugl.io/realms/master/.well-known/openid-configuration",
|
||||||
|
# client_id = "nginx",
|
||||||
|
# client_secret = "9C6BYxPhTbrRS4DIwd3Smk7e11ABmnt8",
|
||||||
|
# logout_path = "/logout",
|
||||||
|
# redirect_after_logout_uri = "/",
|
||||||
|
# redirect_uri = "/redirect_uri",
|
||||||
|
# keepalive = "yes",
|
||||||
|
# accept_none_alg = true,
|
||||||
|
# revoke_tokens_on_logout = true,
|
||||||
|
# -- access token valid for a day
|
||||||
|
# access_token_expires_in = 86400
|
||||||
|
# }
|
||||||
|
|
||||||
|
# ${lib.optionalString (whitelisted_ips != []) ''
|
||||||
|
# local whitelist = {${lib.strings.concatMapStringsSep "," (x: "\"${x}\"") whitelisted_ips}}
|
||||||
|
|
||||||
|
# if is_ip_whitelisted(ngx.var.remote_addr, whitelist) then
|
||||||
|
# return
|
||||||
|
# end
|
||||||
|
# ''}
|
||||||
|
|
||||||
|
# -- call introspect for OAuth 2.0 Bearer Access Token validation
|
||||||
|
# local res, err = require("resty.openidc").authenticate(opts)
|
||||||
|
|
||||||
|
# if err then
|
||||||
|
# ngx.status = 403
|
||||||
|
# ngx.say(err)
|
||||||
|
# ngx.exit(ngx.HTTP_FORBIDDEN)
|
||||||
|
# end
|
||||||
|
|
||||||
|
# ${lib.optionalString (access_role != "") ''
|
||||||
|
# if not check_role(res, "${access_role}") then
|
||||||
|
# ngx.status = 401
|
||||||
|
# ngx.header.content_type = 'text/html';
|
||||||
|
# ngx.say("You are not authorized to access this page. Please contact Er Pepotto.")
|
||||||
|
# ngx.exit(ngx.HTTP_UNAUTHORIZED)
|
||||||
|
# end
|
||||||
|
# ''}
|
||||||
|
# }
|
||||||
|
# '';
|
||||||
|
}
|
37
hosts/architect/photoprism.nix
Normal file
37
hosts/architect/photoprism.nix
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
{ config, pkgs, lib, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
domain = "photos.giugl.io";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
services.photoprism = {
|
||||||
|
enable = true;
|
||||||
|
package = pkgs.unstablePkgs.photoprism;
|
||||||
|
originalsPath = "/var/lib/private/photoprism/originals";
|
||||||
|
address = "0.0.0.0";
|
||||||
|
settings = {
|
||||||
|
PHOTOPRISM_DEFAULT_LOCALE = "en";
|
||||||
|
PHOTOPRISM_DATABASE_DRIVER = "mysql";
|
||||||
|
PHOTOPRISM_DATABASE_NAME = "photoprism";
|
||||||
|
PHOTOPRISM_DATABASE_SERVER = "/run/mysqld/mysqld.sock";
|
||||||
|
PHOTOPRISM_DATABASE_USER = "photoprism";
|
||||||
|
PHOTOPRISM_SITE_URL = "https://${domain}";
|
||||||
|
PHOTOPRISM_SITE_TITLE = "PePrism";
|
||||||
|
PHOTOPRISM_FFMPEG_ENCODER = "nvidia";
|
||||||
|
PHOTOPRISM_INIT = "tensorflow";
|
||||||
|
NVIDIA_VISIBLE_DEVICES = "all";
|
||||||
|
NVIDIA_DRIVER_CAPABILITIES = "compute,video,utility";
|
||||||
|
PHOTOPRISM_FFMPEG_BIN = "${pkgs.ffmpeg}/bin/ffmpeg";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
architect.vhost.${domain} = {
|
||||||
|
dnsInterfaces = [ "tailscale" "lan" ];
|
||||||
|
locations."/" = {
|
||||||
|
port = config.services.photoprism.port;
|
||||||
|
allowLan = true;
|
||||||
|
allow = [ config.architect.networks."tailscale".net ];
|
||||||
|
proxyWebsockets = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
79
hosts/architect/plex.nix
Normal file
79
hosts/architect/plex.nix
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
{ pkgs, config, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
domain = "media.giugl.io";
|
||||||
|
port = 32400;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
architect.firewall = {
|
||||||
|
openTCP = [ 32400 3005 8324 32469 ];
|
||||||
|
openUDP = [ 1900 5353 32410 32412 32413 32414 ];
|
||||||
|
};
|
||||||
|
|
||||||
|
services.plex = {
|
||||||
|
enable = true;
|
||||||
|
package = pkgs.unstablePkgs.plex;
|
||||||
|
dataDir = "/plex";
|
||||||
|
};
|
||||||
|
|
||||||
|
architect.vhost.${domain} = with config.architect.networks; {
|
||||||
|
dnsInterfaces = [ "lan" "tailscale" ];
|
||||||
|
locations = {
|
||||||
|
"/" = {
|
||||||
|
inherit port;
|
||||||
|
|
||||||
|
proxyWebsockets = true;
|
||||||
|
allowLan = true;
|
||||||
|
allow = [
|
||||||
|
tailscale.net
|
||||||
|
];
|
||||||
|
extraConfig = ''
|
||||||
|
#Some players don't reopen a socket and playback stops totally instead of resuming after an extended pause
|
||||||
|
send_timeout 100m;
|
||||||
|
|
||||||
|
# Forward real ip and host to Plex
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_set_header Host $server_addr;
|
||||||
|
proxy_set_header Referer $server_addr;
|
||||||
|
proxy_set_header Origin $server_addr;
|
||||||
|
|
||||||
|
# Plex has A LOT of javascript, xml and html. This helps a lot, but if it causes playback issues with devices turn it off.
|
||||||
|
gzip on;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_min_length 1000;
|
||||||
|
gzip_proxied any;
|
||||||
|
gzip_types text/plain text/css text/xml application/xml text/javascript application/x-javascript image/svg+xml;
|
||||||
|
gzip_disable "MSIE [1-6]\.";
|
||||||
|
|
||||||
|
# Nginx default client_max_body_size is 1MB, which breaks Camera Upload feature from the phones.
|
||||||
|
# Increasing the limit fixes the issue. Anyhow, if 4K videos are expected to be uploaded, the size might need to be increased even more
|
||||||
|
client_max_body_size 100M;
|
||||||
|
|
||||||
|
# Plex headers
|
||||||
|
proxy_set_header X-Plex-Client-Identifier $http_x_plex_client_identifier;
|
||||||
|
proxy_set_header X-Plex-Device $http_x_plex_device;
|
||||||
|
proxy_set_header X-Plex-Device-Name $http_x_plex_device_name;
|
||||||
|
proxy_set_header X-Plex-Platform $http_x_plex_platform;
|
||||||
|
proxy_set_header X-Plex-Platform-Version $http_x_plex_platform_version;
|
||||||
|
proxy_set_header X-Plex-Product $http_x_plex_product;
|
||||||
|
proxy_set_header X-Plex-Token $http_x_plex_token;
|
||||||
|
proxy_set_header X-Plex-Version $http_x_plex_version;
|
||||||
|
proxy_set_header X-Plex-Nocache $http_x_plex_nocache;
|
||||||
|
proxy_set_header X-Plex-Provides $http_x_plex_provides;
|
||||||
|
proxy_set_header X-Plex-Device-Vendor $http_x_plex_device_vendor;
|
||||||
|
proxy_set_header X-Plex-Model $http_x_plex_model;
|
||||||
|
|
||||||
|
# Buffering off send to the client as soon as the data is received from Plex.
|
||||||
|
proxy_redirect off;
|
||||||
|
proxy_buffering off;
|
||||||
|
|
||||||
|
add_header 'Content-Security-Policy' 'upgrade-insecure-requests';
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
users.groups.media.members = [ "plex" ];
|
||||||
|
}
|
55
hosts/architect/prosody.nix
Normal file
55
hosts/architect/prosody.nix
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
{ lib, config, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
domain = "xmpp.giugl.io";
|
||||||
|
conference_domain = "conference.${domain}";
|
||||||
|
upload_domain = "uploads.${domain}";
|
||||||
|
|
||||||
|
utilities = import ./utilities.nix { inherit lib config; };
|
||||||
|
inherit (utilities) architectInterfaceAddress;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
architect.firewall = {
|
||||||
|
openTCP = [ 5222 5269 ];
|
||||||
|
};
|
||||||
|
|
||||||
|
services = {
|
||||||
|
prosody = {
|
||||||
|
enable = true;
|
||||||
|
virtualHosts.${domain} = {
|
||||||
|
inherit domain;
|
||||||
|
|
||||||
|
enabled = true;
|
||||||
|
ssl.key = "${config.security.acme.certs.${domain}.directory}/key.pem";
|
||||||
|
ssl.cert =
|
||||||
|
"${config.security.acme.certs.${domain}.directory}/fullchain.pem";
|
||||||
|
};
|
||||||
|
|
||||||
|
muc = [{ domain = conference_domain; }];
|
||||||
|
uploadHttp = { domain = upload_domain; };
|
||||||
|
|
||||||
|
admins = [ "giulio@${domain}" ];
|
||||||
|
#httpInterfaces = [ "wg0" ];
|
||||||
|
#httpsInterfaces = [ "wg0" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
nginx.virtualHosts = {
|
||||||
|
"${domain}" = {
|
||||||
|
enableACME = true;
|
||||||
|
forceSSL = true;
|
||||||
|
};
|
||||||
|
# "${conference_domain}".enableACME = true;
|
||||||
|
# "${upload_domain}".enableACME = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.extraHosts = ''
|
||||||
|
${architectInterfaceAddress "lan"} ${domain}
|
||||||
|
${architectInterfaceAddress "tailscale"} ${domain}
|
||||||
|
'';
|
||||||
|
|
||||||
|
users.groups = {
|
||||||
|
acme.members = [ "prosody" ];
|
||||||
|
nginx.members = [ "prosody" ];
|
||||||
|
};
|
||||||
|
}
|
29
hosts/architect/redlib.nix
Normal file
29
hosts/architect/redlib.nix
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
{ config, pkgs, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
domain = "reddit.giugl.io";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
systemd.services.redlib.environment = {
|
||||||
|
REDLIB_ROBOTS_DISABLE_INDEXING = "on";
|
||||||
|
REDLIB_DEFAULT_THEME = "dracula";
|
||||||
|
REDLIB_DEFAULT_SHOW_NSFW = "on";
|
||||||
|
REDLIB_DEFAULT_BLUR_NSFW = "off";
|
||||||
|
REDLIB_DEFAULT_USE_HLS = "on";
|
||||||
|
REDLIB_DEFAULT_HIDE_HLS_NOTIFICATION = "on";
|
||||||
|
};
|
||||||
|
|
||||||
|
services.redlib = {
|
||||||
|
enable = true;
|
||||||
|
port = 9090;
|
||||||
|
package = pkgs.unstablePkgs.redlib;
|
||||||
|
};
|
||||||
|
|
||||||
|
architect.vhost.${domain} = {
|
||||||
|
dnsInterfaces = [ "lan" "tailscale" ];
|
||||||
|
locations."/" = {
|
||||||
|
port = config.services.redlib.port;
|
||||||
|
allowWAN = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
48
hosts/architect/runas.nix
Normal file
48
hosts/architect/runas.nix
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
{ config, pkgs, lib, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
domain = "runas.rocks";
|
||||||
|
runas_root = "/var/lib/runas.rocks/dist";
|
||||||
|
service_name = "runas.rocks-pull";
|
||||||
|
mkStartScript = name: pkgs.writeShellScript "${name}.sh" ''
|
||||||
|
set -euo pipefail
|
||||||
|
cd ${runas_root}
|
||||||
|
git pull origin main --rebase
|
||||||
|
'';
|
||||||
|
|
||||||
|
utilities = import ./utilities.nix { inherit lib config; };
|
||||||
|
inherit (utilities) architectInterfaceAddress;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
services.nginx.virtualHosts.${domain} = {
|
||||||
|
enableACME = true;
|
||||||
|
forceSSL = true;
|
||||||
|
|
||||||
|
locations."/".root = runas_root;
|
||||||
|
|
||||||
|
locations."/.git" = { return = "404"; };
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd = {
|
||||||
|
services.${service_name} = {
|
||||||
|
path = [ pkgs.git ];
|
||||||
|
enable = true;
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
ExecStart = mkStartScript "${service_name}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
timers.${service_name} = {
|
||||||
|
wantedBy = [ "timers.target" ];
|
||||||
|
timerConfig = {
|
||||||
|
OnCalendar = "hourly";
|
||||||
|
Unit = "${service_name}.service";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.extraHosts = ''
|
||||||
|
${architectInterfaceAddress "lan"} ${domain}
|
||||||
|
${architectInterfaceAddress "tailscale"} ${domain}
|
||||||
|
'';
|
||||||
|
}
|
64
hosts/architect/teslamate.nix
Normal file
64
hosts/architect/teslamate.nix
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
{ config, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
domain = "tesla.giugl.io";
|
||||||
|
teslamatePort = 11234;
|
||||||
|
grafanaPort = 11334;
|
||||||
|
allowLan = true;
|
||||||
|
allowWAN = false;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
age.secrets.teslamate = {
|
||||||
|
file = ../../secrets/teslamate.age;
|
||||||
|
owner = "teslamate";
|
||||||
|
};
|
||||||
|
|
||||||
|
architect.vhost.${domain} = with config.architect.networks; {
|
||||||
|
dnsInterfaces = [ "lan" "tailscale" ];
|
||||||
|
locations = {
|
||||||
|
"/" = {
|
||||||
|
inherit allowLan allowWAN;
|
||||||
|
port = teslamatePort;
|
||||||
|
proxyWebsockets = true;
|
||||||
|
allow = [
|
||||||
|
tailscale.net
|
||||||
|
];
|
||||||
|
};
|
||||||
|
"/live/websocket" = {
|
||||||
|
inherit allowLan allowWAN;
|
||||||
|
port = teslamatePort;
|
||||||
|
proxyWebsockets = true;
|
||||||
|
allow = [
|
||||||
|
tailscale.net
|
||||||
|
];
|
||||||
|
};
|
||||||
|
"/grafana" = {
|
||||||
|
inherit allowLan allowWAN;
|
||||||
|
port = grafanaPort;
|
||||||
|
proxyWebsockets = true;
|
||||||
|
allow = [
|
||||||
|
tailscale.net
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services.teslamate = {
|
||||||
|
enable = true;
|
||||||
|
port = teslamatePort;
|
||||||
|
|
||||||
|
listenAddress = "127.0.0.1";
|
||||||
|
secretsFile = config.age.secrets.teslamate.path;
|
||||||
|
virtualHost = domain;
|
||||||
|
postgres.enable_server = true;
|
||||||
|
grafana = {
|
||||||
|
enable = true;
|
||||||
|
port = grafanaPort;
|
||||||
|
listenAddress = "127.0.0.1";
|
||||||
|
urlPath = "/grafana";
|
||||||
|
};
|
||||||
|
mqtt = {
|
||||||
|
enable = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
@ -103,15 +103,6 @@ in
|
|||||||
proxyWebsockets = true;
|
proxyWebsockets = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
"${cfg.backend.domain}" = {
|
|
||||||
locations."/docling" = {
|
|
||||||
host = config.services.docling-serve.host;
|
|
||||||
port = config.services.docling-serve.port;
|
|
||||||
allowLAN = true;
|
|
||||||
allowVPN = true;
|
|
||||||
allowWAN = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user