* Updated localDomain config
* Added generic static site config * Added stub admin page
This commit is contained in:
parent
06e0f0fc0a
commit
306c15c890
48 changed files with 324 additions and 341 deletions
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -3,5 +3,7 @@ result
|
|||
*.qcow2
|
||||
homefree-image
|
||||
lan-client-image
|
||||
site/node_modules
|
||||
site/public
|
||||
site/default-landing-page/node_modules
|
||||
site/default-landing-page/public
|
||||
site/admin/node_modules
|
||||
site/admin/public
|
||||
|
|
|
@ -6,17 +6,17 @@
|
|||
../../profiles/config-editor.nix
|
||||
../../profiles/git.nix
|
||||
../../profiles/hardware-configuration.nix
|
||||
../../profiles/hosting.nix
|
||||
../../profiles/nixvim.nix
|
||||
../../profiles/podman.nix
|
||||
../../profiles/router.nix
|
||||
# ../../profiles/traffic-shaping.nix
|
||||
../../profiles/traffic-control.nix
|
||||
|
||||
../../services/adguardhome.nix
|
||||
../../services/admin.nix
|
||||
../../services/authentik.nix
|
||||
../../services/backup.nix
|
||||
../../services/baikal.nix
|
||||
../../services/caddy.nix
|
||||
../../services/cryptpad.nix
|
||||
../../services/ddclient.nix
|
||||
../../services/dnsmasq.nix
|
||||
|
@ -27,6 +27,7 @@
|
|||
../../services/headscale-ui.nix
|
||||
../../services/immich.nix
|
||||
../../services/jellyfin.nix
|
||||
../../services/landing-page.nix
|
||||
../../services/linkwarden.nix
|
||||
../../services/matrix.nix
|
||||
../../services/mqtt.nix
|
||||
|
|
63
module.nix
63
module.nix
|
@ -52,8 +52,20 @@
|
|||
localDomain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
## @TODO: Should this be "local"?
|
||||
default = "localdomain";
|
||||
description = "local lan domain";
|
||||
default = "lan";
|
||||
description = ''
|
||||
local lan domain for internal devices and services.
|
||||
|
||||
Default is "lan". Don't choose "local", as this can conflict with Multicast DNS (mDNS) services,
|
||||
such as Apple's Bonjour/Zeroconf. "local" is also a reserved TLD and some tools and browsers
|
||||
might trigger cert warnings.
|
||||
|
||||
Other common localdomains you can use:
|
||||
"localdomain"
|
||||
"home"
|
||||
"private"
|
||||
"internal"
|
||||
'';
|
||||
};
|
||||
|
||||
domain = lib.mkOption {
|
||||
|
@ -396,7 +408,7 @@
|
|||
|
||||
public = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
default = true;
|
||||
description = "Open to public on WAN port";
|
||||
};
|
||||
|
||||
|
@ -616,6 +628,12 @@
|
|||
description = "description of proxy config";
|
||||
};
|
||||
|
||||
rootDomain = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Maps to root domain, i.e. no subdomain. Only one service can set this to true.";
|
||||
};
|
||||
|
||||
subdomains = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [];
|
||||
|
@ -635,16 +653,23 @@
|
|||
};
|
||||
|
||||
host = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "10.0.0.1";
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
description = "host name or address of service to proxy";
|
||||
};
|
||||
|
||||
port = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
type = lib.types.nullOr lib.types.int;
|
||||
default = null;
|
||||
description = "port of service on lan network";
|
||||
};
|
||||
|
||||
static-path = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = null;
|
||||
description = "path to static files to serve. Do not set host or port if using this.";
|
||||
};
|
||||
|
||||
subdir = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
description = "subdir at which service is served";
|
||||
|
@ -674,6 +699,12 @@
|
|||
default = false;
|
||||
description = "Whether to enable basic auth headers";
|
||||
};
|
||||
|
||||
extraCaddyConfig = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
description = "custom caddy config";
|
||||
};
|
||||
};
|
||||
|
||||
backup = {
|
||||
|
@ -693,6 +724,14 @@
|
|||
});
|
||||
};
|
||||
|
||||
admin-page = {
|
||||
public = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Open to public on WAN port (not recommended)";
|
||||
};
|
||||
};
|
||||
|
||||
landing-page = {
|
||||
path = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
|
@ -812,6 +851,10 @@
|
|||
map getDuplicateOriginal duplicateLowerLabels;
|
||||
|
||||
duplicateLabels = findDuplicateLabels config.homefree.service-config;
|
||||
badServiceConfigs = builtins.filter (entry: (entry.reverse-proxy.host != null || entry.reverse-proxy.port != null) && entry.reverse-proxy.static-path != null) config.homefree.service-config;
|
||||
badServiceConfigLabels = builtins.map (entry: entry.label) badServiceConfigs;
|
||||
rootDomainConfigs = builtins.filter (entry: (entry.reverse-proxy.rootDomain == true)) config.homefree.service-config;
|
||||
rootDomainConfigLabels = builtins.map (entry: entry.label) rootDomainConfigs;
|
||||
in
|
||||
[
|
||||
{
|
||||
|
@ -819,6 +862,14 @@
|
|||
assertion = lib.length duplicateLabels == 0;
|
||||
message = "Multiple homefree.service-config entries with the same label: ${lib.concatStringsSep ", " duplicateLabels}";
|
||||
}
|
||||
{
|
||||
assertion = lib.length badServiceConfigs == 0;
|
||||
message = "homefree.service-config contains entries with both a host/port and static-path config; can only specify one: ${lib.concatStringsSep ", " badServiceConfigLabels}";
|
||||
}
|
||||
{
|
||||
assertion = lib.length rootDomainConfigs <= 1;
|
||||
message = "homefree.service-config contains more than one service with rootDomain = true: ${lib.concatStringsSep ", " rootDomainConfigLabels}";
|
||||
}
|
||||
];
|
||||
|
||||
warnings =
|
||||
|
|
|
@ -195,7 +195,7 @@
|
|||
# Networking
|
||||
# --------------------------------------------------------------------------------------
|
||||
|
||||
networking.search = [ "localdomain" ];
|
||||
networking.search = [ config.homefree.system.localDomain ];
|
||||
|
||||
# --------------------------------------------------------------------------------------
|
||||
# Base Packages
|
||||
|
|
|
@ -1,170 +0,0 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
## @TODO: Convert to work with nftables
|
||||
## @TODO: Test with ethernet cable using the following: https://www.waveform.com/tools/bufferbloat
|
||||
|
||||
let
|
||||
wan-interface = config.homefree.network.wan-interface;
|
||||
wan-bitrate-mbps-down = config.homefree.network.wan-bitrate-mbps-down;
|
||||
wan-bitrate-mbps-down-95-percent = builtins.floor (builtins.mul wan-bitrate-mbps-down 0.95);
|
||||
wan-bitrate-mbps-down-20-percent = builtins.floor (builtins.mul wan-bitrate-mbps-down 0.20);
|
||||
in
|
||||
{
|
||||
## OPNSense Config
|
||||
## ---------------
|
||||
## Pipe
|
||||
## Name: Downstream Pipe
|
||||
## Bandwidth: 950 Mbit/s
|
||||
## Scheduler: FlowQueue-CoDel
|
||||
## CoDel enabled
|
||||
## Pipe
|
||||
## Name: Upstream Pipe
|
||||
## Bandwidth: 950 Mbit/s
|
||||
## Scheduler: FlowQueue-CoDel
|
||||
## CoDel enabled
|
||||
## Queue
|
||||
## Name: Upstream Queue
|
||||
## Pipe: Upstream Pipe
|
||||
## Weight: 1
|
||||
## Queue
|
||||
## Name: Downstream Queue
|
||||
## Pipe: Downstream Pipe
|
||||
## Weight: 1
|
||||
## Queue
|
||||
## Name: High Priority Queue
|
||||
## Pipe: Upstream Pipe
|
||||
## Weight: 10
|
||||
## Rule
|
||||
## Name: DNS High Priority
|
||||
## Sequence: 11
|
||||
## Interface: WAN
|
||||
## Protocol: UDP
|
||||
## Source: 10.0.0.1 (lan gateway)
|
||||
## Src-port: any
|
||||
## Destination: any
|
||||
## Dst-port: 53
|
||||
## Target: High Priority Queue
|
||||
## Rule
|
||||
## Name: Upstream traffic
|
||||
## Sequence: 12
|
||||
## Interface: WAN
|
||||
## Protocol: IP
|
||||
## Source: 10.0.0.0/24 (lan)
|
||||
## Src-port: any
|
||||
## Destination: any
|
||||
## Dst-port: any
|
||||
## Target: Upstream queue
|
||||
## Rule
|
||||
## Name: ACK High Priority
|
||||
## Sequence: 13
|
||||
## Interface: WAN
|
||||
## Protocol: tcp (ACK packets only)
|
||||
## Source: 10.0.0.0/24 (lan)
|
||||
## Src-port: any
|
||||
## Destination: any
|
||||
## Dst-port: any
|
||||
## Target: High Priority Queue
|
||||
## Rule
|
||||
## Name: Downstream traffic
|
||||
## Sequence: 14
|
||||
## Interface: WAN
|
||||
## Protocol: ip
|
||||
## Source: any
|
||||
## Src-port: any
|
||||
## Destination: 10.0.0.0/24 (lan)
|
||||
## Dst-port: any
|
||||
## Target: Downstream queue
|
||||
|
||||
## Disable TCP offload engine, which bypasses traffic shaper to save on CPU
|
||||
systemd.services.disable-transmit-segment-offload = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
enable = true;
|
||||
serviceConfig = {
|
||||
User = "root";
|
||||
Group = "root";
|
||||
};
|
||||
# script = builtins.readFile ../scripts/tune_router_performance.sh;
|
||||
script = ''
|
||||
ETHTOOL=${pkgs.ethtool}/bin/ethtool
|
||||
|
||||
$ETHTOOL -K ${wan-interface} tso off
|
||||
$ETHTOOL -K ${wan-interface} gso off
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.services.traffic-shaper = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
enable = true;
|
||||
serviceConfig = {
|
||||
User = "root";
|
||||
Group = "root";
|
||||
};
|
||||
# script = builtins.readFile ../scripts/tune_router_performance.sh;
|
||||
script = ''
|
||||
TC=${pkgs.iproute2}/bin/tc
|
||||
IPTABLES=${pkgs.iptables}/bin/iptables
|
||||
|
||||
# CoDel Active Queue Management (AQM) algorithm
|
||||
# https://www.bufferbloat.net/projects/codel/wiki/
|
||||
|
||||
# fq_codel only supported by certain network drivers
|
||||
# https://www.bufferbloat.net/projects/bloat/wiki/BQL_enabled_drivers/
|
||||
|
||||
# Reference for rules below
|
||||
# https://wiki.archlinux.org/title/Advanced_traffic_control
|
||||
# https://www.linuxquestions.org/questions/linux-networking-3/traffic-shaping-with-tc-on-a-server-4175690429-print/
|
||||
|
||||
# Remove existing queues
|
||||
# redirect errors to /dev/null in case the qdisc doesn't exist
|
||||
$TC qdisc del dev ${wan-interface} ingress 2>/dev/null || true
|
||||
$TC qdisc del dev ${wan-interface} root 2>/dev/null || true
|
||||
|
||||
# 1) Add/Replace root qdisc of eth0 with an HTB instance,
|
||||
# specify handle so it can be referred to by other rules,
|
||||
# set default class for all unclassified traffic
|
||||
|
||||
$TC qdisc replace dev ${wan-interface} root handle 1: htb default 30
|
||||
|
||||
# 2) Create single top level class with handle 1:1 which limits
|
||||
# total traffic to slightly less than the path max
|
||||
# Limit to 95% of maximum bandwidth
|
||||
|
||||
$TC class add dev ${wan-interface} parent 1: classid 1:1 htb rate ${toString wan-bitrate-mbps-down-95-percent}mbit
|
||||
|
||||
# 3) Create child classes for different uses:
|
||||
# Class 1:10 is our outgoing highest priority path, outgoing SSH/SFTP in this example
|
||||
# Class 1:20 is our next highest priority path, web admin traffic for example
|
||||
# Class 1:30 is default and has lowest priority but highest total bandwidth - bulk web traffic for example
|
||||
|
||||
$TC class add dev ${wan-interface} parent 1:1 classid 1:10 htb rate 1mbit ceil ${toString wan-bitrate-mbps-down-20-percent}mbit prio 1
|
||||
$TC class add dev ${wan-interface} parent 1:1 classid 1:20 htb rate 1mbit ceil ${toString wan-bitrate-mbps-down-20-percent}mbit prio 2
|
||||
$TC class add dev ${wan-interface} parent 1:1 classid 1:30 htb rate 1mbit ceil ${toString wan-bitrate-mbps-down-95-percent}mbit prio 3
|
||||
|
||||
# 4) Attach a leaf qdisc to each child class
|
||||
# HTB by default attaches pfifo as leaf so this is optional.
|
||||
# fq_codel is said to be worth the effort.
|
||||
|
||||
$TC qdisc add dev ${wan-interface} parent 1:10 fq_codel
|
||||
$TC qdisc add dev ${wan-interface} parent 1:20 fq_codel
|
||||
$TC qdisc add dev ${wan-interface} parent 1:30 fq_codel
|
||||
|
||||
# 5) Add filters for priority traffic
|
||||
$TC filter add dev ${wan-interface} parent 1: handle 100 fw classid 1:10
|
||||
$TC filter add dev ${wan-interface} parent 1: handle 200 fw classid 1:20
|
||||
|
||||
# Shape traffic
|
||||
## -t mangle mangle table, used for modifying packet headers
|
||||
## -A OUTPUT Append to OUTPUT chain (OUTPUT being packets leaving the system)
|
||||
## -p tcp TCP protocol
|
||||
## --match multiport Match multiple ports
|
||||
## --dports 53 Match destination port of 53 (DNS)
|
||||
## -j MARK What to do on match. Jump to MARK (to set the netfilter mark value associated with the packet. It is only valid in the mangle table)
|
||||
## --set-mark 200 Set connection mark of 200, which matches the tc filter above
|
||||
|
||||
## DNS High Priority
|
||||
$IPTABLES -t mangle -A OUTPUT -p tcp --match multiport --dports 53 -j MARK --set-mark 100
|
||||
## ACK High Priority
|
||||
$IPTABLES -t mangle -A OUTPUT -p tcp --match tcp --tcp-flags ACK ACK -j MARK --set-mark 100
|
||||
'';
|
||||
};
|
||||
}
|
|
@ -173,8 +173,9 @@
|
|||
reverse-proxy = {
|
||||
enable = true;
|
||||
subdomains = [ "adguard" ];
|
||||
http-domains = [ "homefree.${config.homefree.system.localDomain}" ];
|
||||
http-domains = [ "homefree.lan" config.homefree.system.localDomain ];
|
||||
https-domains = [ config.homefree.system.domain ];
|
||||
host = "10.0.0.1";
|
||||
port = 3000;
|
||||
public = config.homefree.services.adguard.public;
|
||||
};
|
||||
|
|
26
services/admin.nix
Normal file
26
services/admin.nix
Normal file
|
@ -0,0 +1,26 @@
|
|||
{ config, pkgs, ... }:
|
||||
let
|
||||
homefree-admin = pkgs.callPackage ../site/admin { };
|
||||
in
|
||||
{
|
||||
## add homefree admin page as a package
|
||||
nixpkgs.overlays = [
|
||||
(final: prev: {
|
||||
homefree-admin = homefree-admin;
|
||||
})
|
||||
];
|
||||
|
||||
homefree.service-config = [
|
||||
{
|
||||
label = "admin";
|
||||
reverse-proxy = {
|
||||
enable = true;
|
||||
subdomains = [ "admin" ];
|
||||
http-domains = [ "homefree.lan" config.homefree.system.localDomain ];
|
||||
https-domains = [ config.homefree.system.domain ];
|
||||
static-path = "${pkgs.homefree-admin}/lib/node_modules/homefree-admin";
|
||||
public = config.homefree.admin-page.public;
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
|
@ -40,8 +40,9 @@
|
|||
reverse-proxy = {
|
||||
enable = true;
|
||||
subdomains = [ "authentik" "auth" ];
|
||||
http-domains = [ "homefree.${config.homefree.system.localDomain}" ];
|
||||
http-domains = [ "homefree.lan" config.homefree.system.localDomain ];
|
||||
https-domains = [ config.homefree.system.domain ];
|
||||
host = "10.0.0.1";
|
||||
port = 9000;
|
||||
public = config.homefree.services.authentik.public;
|
||||
};
|
||||
|
|
|
@ -45,8 +45,9 @@ in
|
|||
reverse-proxy = {
|
||||
enable = true;
|
||||
subdomains = [ "baikal" ];
|
||||
http-domains = [ "homefree.${config.homefree.system.localDomain}" ];
|
||||
http-domains = [ "homefree.lan" config.homefree.system.localDomain ];
|
||||
https-domains = [ config.homefree.system.domain ];
|
||||
host = "10.0.0.1";
|
||||
port = 3007;
|
||||
public = config.homefree.services.baikal.public;
|
||||
};
|
||||
|
|
|
@ -1,21 +1,9 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
hostConfig = ''
|
||||
respond "Hello, world! I am being accessed from {scheme}."
|
||||
'';
|
||||
proxiedHostConfig = lib.filter (service-config: service-config.reverse-proxy.enable == true) config.homefree.service-config;
|
||||
homefree-site = pkgs.callPackage ../site { };
|
||||
headscale-ui-config = lib.elemAt (lib.filter (service-config: service-config.label == "headscale-ui") config.homefree.service-config) 0;
|
||||
trimTrailingSlash = s: lib.head (lib.match "(.*[^/])[/]*" s);
|
||||
in
|
||||
{
|
||||
## add homefree default site as a package
|
||||
nixpkgs.overlays = [
|
||||
(final: prev: {
|
||||
homefree-site = homefree-site;
|
||||
})
|
||||
];
|
||||
|
||||
systemd.services.caddy = {
|
||||
after = [ "network.target" "network-online.target" "unbound.service" ];
|
||||
requires = [ "network-online.target" "unbound.service" ];
|
||||
|
@ -36,7 +24,9 @@ in
|
|||
reverse-proxy-config = service-config.reverse-proxy;
|
||||
http-urls = lib.flatten (lib.map (subdomain: (lib.map (domain: "http://${subdomain}.${domain}") reverse-proxy-config.http-domains)) reverse-proxy-config.subdomains);
|
||||
https-urls = lib.flatten (lib.map (subdomain: (lib.map (domain: "https://${subdomain}.${domain}") reverse-proxy-config.https-domains)) reverse-proxy-config.subdomains);
|
||||
urls = http-urls ++ https-urls;
|
||||
http-urls-root-domain = if reverse-proxy-config.rootDomain == true then (lib.map (domain: "http://${domain}") reverse-proxy-config.http-domains) else [];
|
||||
https-urls-root-domain = if reverse-proxy-config.rootDomain == true then (lib.map (domain: "https://${domain}") reverse-proxy-config.https-domains) else [];
|
||||
urls = http-urls ++ https-urls ++ http-urls-root-domain ++ https-urls-root-domain;
|
||||
host-string = lib.concatStringsSep ", " urls;
|
||||
in {
|
||||
name = host-string;
|
||||
|
@ -68,106 +58,13 @@ in
|
|||
rewrite / ${trimTrailingSlash reverse-proxy-config.subdir}{uri}
|
||||
'' else "")
|
||||
## @TODO: throw an error if more than one host is using the same port
|
||||
+ ''
|
||||
reverse_proxy ${if reverse-proxy-config.ssl == true then "https" else "http"}://${reverse-proxy-config.host}:${toString reverse-proxy-config.port} {
|
||||
''
|
||||
+ (if reverse-proxy-config.ssl == true && reverse-proxy-config.ssl-no-verify then ''
|
||||
transport http {
|
||||
tls
|
||||
tls_insecure_skip_verify
|
||||
}
|
||||
'' else "")
|
||||
+ (if reverse-proxy-config.basic-auth == true then ''
|
||||
header_up X-remote-user {http.auth.user.id}
|
||||
'' else "")
|
||||
+
|
||||
''
|
||||
}
|
||||
'';
|
||||
};
|
||||
}
|
||||
) proxiedHostConfig))
|
||||
{
|
||||
## Needed so as to host ui and headscale enpoint on separate domains
|
||||
"http://headscale.${config.homefree.system.domain}, https://headscale.${config.homefree.system.domain}" = {
|
||||
logFormat = ''
|
||||
output file ${config.services.caddy.logDir}/access-headscale.log
|
||||
'';
|
||||
extraConfig = ''
|
||||
header {
|
||||
# Add general security headers
|
||||
Strict-Transport-Security "max-age=31536000; includeSubdomains"
|
||||
X-Content-Type-Options "nosniff"
|
||||
X-Frame-Options "SAMEORIGIN"
|
||||
Referrer-Policy "strict-origin-when-cross-origin"
|
||||
X-XSS-Protection "1; mode=block"
|
||||
}
|
||||
|
||||
reverse_proxy /web* http://10.0.0.1:3009
|
||||
reverse_proxy * http://10.0.0.1:8087
|
||||
bind 10.0.0.1 ${config.homefree.system.domain}
|
||||
'';
|
||||
};
|
||||
}
|
||||
# {
|
||||
# ## Needed so as to host ui and headscale enpoint on separate domains
|
||||
# "https://headscale.${config.homefree.system.domain}" = {
|
||||
# logFormat = ''
|
||||
# output file ${config.services.caddy.logDir}/access-headscale.log
|
||||
# '';
|
||||
# extraConfig = ''
|
||||
# @headscale-options {
|
||||
# host headscale.${config.homefree.system.domain}
|
||||
# method OPTIONS
|
||||
# }
|
||||
# @headscale-other {
|
||||
# host headscale.${config.homefree.system.domain}
|
||||
# }
|
||||
# handle @headscale-options {
|
||||
# header {
|
||||
# Access-Control-Allow-Origin https://headscale-ui.${config.homefree.system.domain}
|
||||
# Access-Control-Allow-Headers *
|
||||
# Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE"
|
||||
# }
|
||||
# respond 204
|
||||
# }
|
||||
# handle @headscale-other {
|
||||
# reverse_proxy http://10.0.0.1:8087 {
|
||||
# header_down Access-Control-Allow-Origin https://headscale-ui.${config.homefree.system.domain}
|
||||
# header_down Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE"
|
||||
# header_down Access-Control-Allow-Headers *
|
||||
# }
|
||||
# ''
|
||||
# + (if headscale-ui-config.public == false then ''
|
||||
# bind 10.0.0.1
|
||||
# '' else ''
|
||||
# bind 10.0.0.1 ${config.homefree.system.domain}
|
||||
# '')
|
||||
# + ''
|
||||
# }
|
||||
# '';
|
||||
# };
|
||||
# }
|
||||
|
||||
## Static root site
|
||||
{
|
||||
"http://localhost, https://localhost, https://${config.homefree.system.domain}, https://www.${config.homefree.system.domain}" = {
|
||||
logFormat = ''
|
||||
output file ${config.services.caddy.logDir}/access-landing-page.log
|
||||
'';
|
||||
extraConfig = ''
|
||||
bind 10.0.0.1 ${config.homefree.system.domain}
|
||||
root * ${config.homefree.landing-page.path}
|
||||
+ (if reverse-proxy-config.static-path != null then ''
|
||||
root * ${reverse-proxy-config.static-path}
|
||||
file_server
|
||||
|
||||
# Enable Gzip compression
|
||||
encode gzip
|
||||
|
||||
# Matrix Synapse settings
|
||||
respond /.well-known/matrix/server `{"m.server": "matrix.${config.homefree.system.domain}:443"}`
|
||||
# respond /.well-known/matrix/client `{"m.homeserver":{"base_url":"https://matrix.${config.homefree.system.domain}"},"m.identity_server":{"base_url":"https://identity.${config.homefree.system.domain}"}}`
|
||||
respond /.well-known/matrix/client `{"m.homeserver":{"base_url":"https://matrix.${config.homefree.system.domain}"}}`
|
||||
|
||||
# HTML files - No caching to ensure fresh content
|
||||
@html {
|
||||
file
|
||||
|
@ -222,20 +119,26 @@ in
|
|||
Referrer-Policy "strict-origin-when-cross-origin"
|
||||
X-XSS-Protection "1; mode=block"
|
||||
}
|
||||
'';
|
||||
'' else (''
|
||||
reverse_proxy ${if reverse-proxy-config.ssl == true then "https" else "http"}://${reverse-proxy-config.host}:${toString reverse-proxy-config.port} {
|
||||
''
|
||||
+ (if reverse-proxy-config.ssl == true && reverse-proxy-config.ssl-no-verify then ''
|
||||
transport http {
|
||||
tls
|
||||
tls_insecure_skip_verify
|
||||
}
|
||||
'' else "")
|
||||
+ (if reverse-proxy-config.basic-auth == true then ''
|
||||
header_up X-remote-user {http.auth.user.id}
|
||||
'' else "")
|
||||
+
|
||||
''
|
||||
}
|
||||
''))
|
||||
+ (if reverse-proxy-config.extraCaddyConfig != null then reverse-proxy-config.extraCaddyConfig else "");
|
||||
};
|
||||
}
|
||||
) proxiedHostConfig))
|
||||
];
|
||||
|
||||
## With both http and https set, caddy won't redirect http to https
|
||||
## REMOVE THIS IN PROD
|
||||
# virtualHosts."http://localhost, https://localhost, https://${config.homefree.system.domain}, https://www.${config.homefree.system.domain}" = {
|
||||
# # Nix config mangles the log name, so set it manually
|
||||
# logFormat = ''
|
||||
# output file ${config.services.caddy.logDir}/access-localhost.log
|
||||
# '';
|
||||
# extraConfig = hostConfig;
|
||||
# };
|
||||
|
||||
};
|
||||
}
|
|
@ -20,9 +20,10 @@
|
|||
label = "cryptpad";
|
||||
reverse-proxy = {
|
||||
enable = true;
|
||||
subdomains = [ "cryptpad" "cryptpad-sandbox" "cryptpad-ui" ];
|
||||
http-domains = [ "homefree.${config.homefree.system.localDomain}" ];
|
||||
subdomains = [ "docs" "cryptpad" "cryptpad-sandbox" "cryptpad-ui" ];
|
||||
http-domains = [ "homefree.lan" config.homefree.system.localDomain ];
|
||||
https-domains = [ config.homefree.system.domain ];
|
||||
host = "10.0.0.1";
|
||||
port = 3004;
|
||||
public = config.homefree.services.cryptpad.public;
|
||||
};
|
||||
|
|
|
@ -204,8 +204,9 @@ in
|
|||
reverse-proxy = {
|
||||
enable = true;
|
||||
subdomains = [ "frigate" ];
|
||||
http-domains = [ "homefree.${config.homefree.system.localDomain}" ];
|
||||
http-domains = [ "homefree.lan" config.homefree.system.localDomain ];
|
||||
https-domains = [ config.homefree.system.domain ];
|
||||
host = "10.0.0.1";
|
||||
port = 8971;
|
||||
ssl = true;
|
||||
ssl-no-verify = true;
|
||||
|
|
|
@ -30,8 +30,9 @@
|
|||
reverse-proxy = {
|
||||
enable = true;
|
||||
subdomains = [ "git" ];
|
||||
http-domains = [ "homefree.${config.homefree.system.localDomain}" ];
|
||||
http-domains = [ "homefree.lan" config.homefree.system.localDomain ];
|
||||
https-domains = [ config.homefree.system.domain ];
|
||||
host = "10.0.0.1";
|
||||
port = 3001;
|
||||
public = config.homefree.services.gitea.public;
|
||||
};
|
||||
|
|
|
@ -26,12 +26,57 @@
|
|||
# reverse-proxy = {
|
||||
# enable = true;
|
||||
# subdomains = [ "headscale-ui" ];
|
||||
# http-domains = [ "homefree.${config.homefree.system.localDomain}" ];
|
||||
# http-domains = [ "homefree.lan" config.homefree.system.localDomain ];
|
||||
# https-domains = [ config.homefree.system.domain ];
|
||||
# host = "10.0.0.1";
|
||||
# port = 3009;
|
||||
# public = config.homefree.services.headscale-ui.public;
|
||||
# };
|
||||
# }
|
||||
# ] else [];
|
||||
|
||||
## Reference of what caddy config might look like:
|
||||
# let
|
||||
# headscale-ui-config = lib.elemAt (lib.filter (service-config: service-config.label == "headscale-ui") config.homefree.service-config) 0;
|
||||
# in
|
||||
# {
|
||||
# ## Needed so as to host ui and headscale enpoint on separate domains
|
||||
# "https://headscale.${config.homefree.system.domain}" = {
|
||||
# logFormat = ''
|
||||
# output file ${config.services.caddy.logDir}/access-headscale.log
|
||||
# '';
|
||||
# extraConfig = ''
|
||||
# @headscale-options {
|
||||
# host headscale.${config.homefree.system.domain}
|
||||
# method OPTIONS
|
||||
# }
|
||||
# @headscale-other {
|
||||
# host headscale.${config.homefree.system.domain}
|
||||
# }
|
||||
# handle @headscale-options {
|
||||
# header {
|
||||
# Access-Control-Allow-Origin https://headscale-ui.${config.homefree.system.domain}
|
||||
# Access-Control-Allow-Headers *
|
||||
# Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE"
|
||||
# }
|
||||
# respond 204
|
||||
# }
|
||||
# handle @headscale-other {
|
||||
# reverse_proxy http://10.0.0.1:8087 {
|
||||
# header_down Access-Control-Allow-Origin https://headscale-ui.${config.homefree.system.domain}
|
||||
# header_down Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE"
|
||||
# header_down Access-Control-Allow-Headers *
|
||||
# }
|
||||
# ''
|
||||
# + (if headscale-ui-config.public == false then ''
|
||||
# bind 10.0.0.1
|
||||
# '' else ''
|
||||
# bind 10.0.0.1 ${config.homefree.system.domain}
|
||||
# '')
|
||||
# + ''
|
||||
# }
|
||||
# '';
|
||||
# };
|
||||
# }
|
||||
}
|
||||
|
||||
|
|
|
@ -69,17 +69,21 @@ in
|
|||
];
|
||||
};
|
||||
|
||||
# homefree.service-config = if config.homefree.services.headscale.enable == true then [
|
||||
# {
|
||||
# label = "headscale";
|
||||
# reverse-proxy = {
|
||||
# enable = true;
|
||||
# subdomains = [ "headscale" ];
|
||||
# http-domains = [ "homefree.${config.homefree.system.localDomain}" ];
|
||||
# https-domains = [ config.homefree.system.domain ];
|
||||
# port = 8087;
|
||||
# public = config.homefree.services.headscale.public;
|
||||
# };
|
||||
# }
|
||||
# ] else [];
|
||||
homefree.service-config = if config.homefree.services.headscale.enable == true then [
|
||||
{
|
||||
label = "headscale";
|
||||
reverse-proxy = {
|
||||
enable = true;
|
||||
subdomains = [ "headscale" ];
|
||||
http-domains = [ "homefree.lan" config.homefree.system.localDomain ];
|
||||
https-domains = [ config.homefree.system.domain ];
|
||||
host = "10.0.0.1";
|
||||
port = 8087;
|
||||
public = config.homefree.services.headscale.public;
|
||||
extraCaddyConfig = ''
|
||||
reverse_proxy /web* http://10.0.0.1:3009
|
||||
'';
|
||||
};
|
||||
}
|
||||
] else [];
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ config, inputs, pkgs, ... }:
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
let
|
||||
# automations = import ./automations.nix;
|
||||
|
@ -145,19 +145,19 @@ in
|
|||
switch = {
|
||||
name = "msi_desktop";
|
||||
unique_id = "msi-desktop";
|
||||
command_state = "ping -c 2 -i 1 msi-desktop.localdomain";
|
||||
command_state = "ping -c 2 -i 1 msi-desktop.${config.homefree.system.localDomain}";
|
||||
## Hibernate
|
||||
# command_off = "ssh -i /run/agenix/msi-desktop-id_rsa -o 'StrictHostKeyChecking=no' erahhal@msi-desktop rundll32.exe powrprof.dll, SetSuspendState Sleep";
|
||||
command_on = "wakeonlan 2c:f0:5d:72:ac:ab";
|
||||
## Suspend
|
||||
command_off = "ssh -i /config/certs/msi_desktop-id_rsa -o ConnectTimeout=30 -o 'StrictHostKeyChecking=no' erahhal@msi-desktop.localdomain 'cd \"/mnt/c/Program Files/PSTools\"; ./psshutdown.exe -accepteula -d -t 0'";
|
||||
command_off = "ssh -i /config/certs/msi_desktop-id_rsa -o ConnectTimeout=30 -o 'StrictHostKeyChecking=no' erahhal@msi-desktop.${config.homefree.system.localDomain} 'cd \"/mnt/c/Program Files/PSTools\"; ./psshutdown.exe -accepteula -d -t 0'";
|
||||
};
|
||||
}
|
||||
{
|
||||
switch = {
|
||||
name = "stream_vr";
|
||||
unique_id = "steam-vr";
|
||||
command_on = "ssh -i /config/certs/msi_desktop-id_rsa -o ConnectTimeout=30 -o 'StrictHostKeyChecking=no' erahhal@msi-desktop.localdomain 'cd \"/mnt/c/Program Files (x86)/Steam/steamapps/common/SteamVR/bin/win64\"; ./vrstartup.exe'";
|
||||
command_on = "ssh -i /config/certs/msi_desktop-id_rsa -o ConnectTimeout=30 -o 'StrictHostKeyChecking=no' erahhal@msi-desktop.${config.homefree.system.localDomain} 'cd \"/mnt/c/Program Files (x86)/Steam/steamapps/common/SteamVR/bin/win64\"; ./vrstartup.exe'";
|
||||
};
|
||||
}
|
||||
];
|
||||
|
@ -417,7 +417,7 @@ in
|
|||
reverse-proxy = {
|
||||
enable = true;
|
||||
subdomains = [ "homeassistant" "ha" ];
|
||||
http-domains = [ "homefree.${config.homefree.system.localDomain}" ];
|
||||
http-domains = [ "homefree.lan" config.homefree.system.localDomain ];
|
||||
https-domains = [ config.homefree.system.domain ];
|
||||
port = 8123;
|
||||
public = config.homefree.services.homeassistant.public;
|
||||
|
|
|
@ -23,8 +23,9 @@
|
|||
reverse-proxy = {
|
||||
enable = true;
|
||||
subdomains = [ "photos" "immich" ];
|
||||
http-domains = [ "homefree.${config.homefree.system.localDomain}" ];
|
||||
http-domains = [ "homefree.lan" config.homefree.system.localDomain ];
|
||||
https-domains = [ config.homefree.system.domain ];
|
||||
host = "10.0.0.1";
|
||||
port = config.services.immich.port;
|
||||
public = config.homefree.services.immich.public;
|
||||
};
|
||||
|
|
|
@ -39,9 +39,10 @@
|
|||
label = "jellyfin";
|
||||
reverse-proxy = {
|
||||
enable = true;
|
||||
subdomains = [ "jellyfin" ];
|
||||
http-domains = [ "homefree.${config.homefree.system.localDomain}" ];
|
||||
subdomains = [ "jellyfin" "video" ];
|
||||
http-domains = [ "homefree.lan" config.homefree.system.localDomain ];
|
||||
https-domains = [ config.homefree.system.domain ];
|
||||
host = "10.0.0.1";
|
||||
port = 8096;
|
||||
public = config.homefree.services.jellyfin.public;
|
||||
};
|
||||
|
|
33
services/landing-page.nix
Normal file
33
services/landing-page.nix
Normal file
|
@ -0,0 +1,33 @@
|
|||
{ config, pkgs, ... }:
|
||||
let
|
||||
homefree-site = pkgs.callPackage ../site/default-landing-page { };
|
||||
in
|
||||
{
|
||||
## add homefree default site as a package
|
||||
nixpkgs.overlays = [
|
||||
(final: prev: {
|
||||
homefree-site = homefree-site;
|
||||
})
|
||||
];
|
||||
|
||||
homefree.service-config = [
|
||||
{
|
||||
label = "landing-page";
|
||||
reverse-proxy = {
|
||||
enable = true;
|
||||
rootDomain = true;
|
||||
subdomains = [ "www" "homefree" ];
|
||||
http-domains = [ config.homefree.system.localDomain ];
|
||||
https-domains = [ config.homefree.system.domain ];
|
||||
static-path = config.homefree.landing-page.path;
|
||||
public = true;
|
||||
extraCaddyConfig = ''
|
||||
# Matrix Synapse settings
|
||||
respond /.well-known/matrix/server `{"m.server": "matrix.${config.homefree.system.domain}:443"}`
|
||||
# respond /.well-known/matrix/client `{"m.homeserver":{"base_url":"https://matrix.${config.homefree.system.domain}"},"m.identity_server":{"base_url":"https://identity.${config.homefree.system.domain}"}}`
|
||||
respond /.well-known/matrix/client `{"m.homeserver":{"base_url":"https://matrix.${config.homefree.system.domain}"}}`
|
||||
'';
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
|
@ -26,9 +26,10 @@ in
|
|||
label = "linkwarden";
|
||||
reverse-proxy = {
|
||||
enable = true;
|
||||
subdomains = [ "linkwarden" ];
|
||||
http-domains = [ "homefree.${config.homefree.system.localDomain}" ];
|
||||
subdomains = [ "linkwarden" "links" ];
|
||||
http-domains = [ "homefree.lan" config.homefree.system.localDomain ];
|
||||
https-domains = [ config.homefree.system.domain ];
|
||||
host = "10.0.0.1";
|
||||
port = 3005;
|
||||
public = config.homefree.services.linkwarden.public;
|
||||
};
|
||||
|
|
|
@ -203,8 +203,9 @@
|
|||
reverse-proxy = {
|
||||
enable = true;
|
||||
subdomains = [ "matrix" ];
|
||||
http-domains = [ "homefree.${config.homefree.system.localDomain}" ];
|
||||
http-domains = [ "homefree.lan" config.homefree.system.localDomain ];
|
||||
https-domains = [ config.homefree.system.domain ];
|
||||
host = "10.0.0.1";
|
||||
port = 8008;
|
||||
public = config.homefree.services.matrix.public;
|
||||
# basic-auth = true;
|
||||
|
|
|
@ -146,8 +146,9 @@ in
|
|||
reverse-proxy = {
|
||||
enable = true;
|
||||
subdomains = [ "nextcloud" ];
|
||||
http-domains = [ "homefree.${config.homefree.system.localDomain}" ];
|
||||
http-domains = [ "homefree.lan" config.homefree.system.localDomain ];
|
||||
https-domains = [ config.homefree.system.domain ];
|
||||
host = "10.0.0.1";
|
||||
port = 3010;
|
||||
subdir = "/nextcloud/";
|
||||
public = config.homefree.services.nextcloud.public;
|
||||
|
|
|
@ -24,8 +24,9 @@
|
|||
reverse-proxy = {
|
||||
enable = true;
|
||||
subdomains = [ "radicale" "dav" "webdav" "caldav" "carddav" ];
|
||||
http-domains = [ "homefree.${config.homefree.system.localDomain}" ];
|
||||
http-domains = [ "homefree.lan" config.homefree.system.localDomain ];
|
||||
https-domains = [ config.homefree.system.domain ];
|
||||
host = "10.0.0.1";
|
||||
port = 5232;
|
||||
public = config.homefree.services.radicale.public;
|
||||
# basic-auth = true;
|
||||
|
|
|
@ -215,7 +215,7 @@ in
|
|||
# range-lan = {
|
||||
# start = "10.0.0.200";
|
||||
# end = "10.0.0.254";
|
||||
# domain = "localdomain";
|
||||
# domain = config.homefree.system.localDomain;
|
||||
# };
|
||||
|
||||
forward-zone = [
|
||||
|
|
|
@ -15,8 +15,9 @@
|
|||
reverse-proxy = {
|
||||
enable = true;
|
||||
subdomains = [ "unifi" ];
|
||||
http-domains = [ "homefree.${config.homefree.system.localDomain}" ];
|
||||
http-domains = [ "homefree.lan" config.homefree.system.localDomain ];
|
||||
https-domains = [ config.homefree.system.domain ];
|
||||
host = "10.0.0.1";
|
||||
port = 8443;
|
||||
ssl = true;
|
||||
ssl-no-verify = true;
|
||||
|
|
|
@ -20,8 +20,9 @@ in
|
|||
reverse-proxy = {
|
||||
enable = true;
|
||||
subdomains = [ "vaultwarden" ];
|
||||
http-domains = [ "homefree.${config.homefree.system.localDomain}" ];
|
||||
http-domains = [ "homefree.lan" config.homefree.system.localDomain ];
|
||||
https-domains = [ config.homefree.system.domain ];
|
||||
host = "10.0.0.1";
|
||||
port = 8222;
|
||||
public = config.homefree.services.vaultwarden.public;
|
||||
};
|
||||
|
|
18
site/admin/default.nix
Normal file
18
site/admin/default.nix
Normal file
|
@ -0,0 +1,18 @@
|
|||
{ pkgs, buildNpmPackage, ... }:
|
||||
|
||||
buildNpmPackage {
|
||||
name = "admin";
|
||||
src = ./.;
|
||||
# npmDepsHash = lib.fakeHash;
|
||||
npmDepsHash = "sha256-C7dFRyWooP920Ei4JeK10fL93zJN5XQu85+Tz6oU0fA=";
|
||||
|
||||
# The prepack script runs the build script, which we'd rather do in the build phase.
|
||||
npmPackFlags = [
|
||||
"--legacy-peer-deps"
|
||||
"--loglevel=verbose"
|
||||
];
|
||||
|
||||
makeCacheWritable = true;
|
||||
|
||||
nodejs = pkgs.nodejs_22;
|
||||
}
|
11
site/admin/index.html
Normal file
11
site/admin/index.html
Normal file
|
@ -0,0 +1,11 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>HomeFree Admin</title>
|
||||
<script type="module" src="./index.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<homefree-admin></homefree-admin>
|
||||
</body>
|
||||
</html>
|
9
site/admin/index.js
Normal file
9
site/admin/index.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
import XElement from '/node_modules/@netflix/x-element/x-element.js';
|
||||
|
||||
class HomeFreeAdmin extends XElement {
|
||||
static template(html) {
|
||||
return () => html`<span>HomeFree Admin</span>`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('homefree-admin', HomeFreeAdmin);
|
24
site/admin/package-lock.json
generated
Normal file
24
site/admin/package-lock.json
generated
Normal file
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"name": "homefree-admin",
|
||||
"version": "0.0.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "homefree-admin",
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"@netflix/x-element": "github:netflix/x-element"
|
||||
}
|
||||
},
|
||||
"node_modules/@netflix/x-element": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "git+ssh://git@github.com/netflix/x-element.git#aaefbba9b9b754c52ef292234ef751705908b888",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": "22.11.0",
|
||||
"npm": "10.9.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
12
site/admin/package.json
Normal file
12
site/admin/package.json
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"name": "homefree-admin",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@netflix/x-element": "github:netflix/x-element"
|
||||
},
|
||||
"scripts": {
|
||||
"build": ""
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
{ buildNpmPackage, lib, ... }:
|
||||
{ buildNpmPackage, ... }:
|
||||
|
||||
buildNpmPackage {
|
||||
name = "site";
|
||||
name = "default-landing-page";
|
||||
src = ./.;
|
||||
# npmDepsHash = lib.fakeHash;
|
||||
npmDepsHash = "sha256-uOLu/MrHS+Et9yUyZO66ANRCzG15hki+7oSTqw4eyT0=";
|
Loading…
Add table
Reference in a new issue