{ config, inputs, pkgs, ... }: let inherit (config.virtualisation.quadlet) volumes; inboundInterface = "wlo1"; inboundGateway = "192.168.1.1"; inboundRangeStart = "192.168.1.2"; inboundRangeStop = "192.168.1.254"; inboundRangeMask = "255.255.255.0"; inboundRangePrefix = 24; outboundInterface = "enp2s0"; in { boot.kernel.sysctl."net.ipv4.ip_forward" = 1; networking = { firewall = { interfaces.${inboundInterface} = { allowedUDPPorts = [ 53 67 ]; allowedTCPPorts = [ 53 8080 ]; }; extraCommands = '' iptables -t nat -A POSTROUTING -o ${outboundInterface} -j MASQUERADE iptables -A FORWARD -i ${outboundInterface} -o ${inboundInterface} -m state --state RELATED,ESTABLISHED -j ACCEPT iptables -A FORWARD -i ${inboundInterface} -o ${outboundInterface} -j ACCEPT iptables -t nat -A PREROUTING -i ${inboundInterface} -p udp --dport 53 -j DNAT --to-destination ${inboundGateway}:53 ''; extraStopCommands = '' iptables -t nat -D POSTROUTING -o ${outboundInterface} -j MASQUERADE || true iptables -D FORWARD -i ${outboundInterface} -o ${inboundInterface} -m state --state RELATED,ESTABLISHED -j ACCEPT || true iptables -D FORWARD -i ${inboundInterface} -o ${outboundInterface} -j ACCEPT || true iptables -t nat -D PREROUTING -i ${inboundInterface} -p udp --dport 53 -j DNAT --to-destination ${inboundGateway}:53 || true ''; }; networkmanager.unmanaged = [ "interface-name:${inboundInterface}" ]; interfaces.${inboundInterface}.ipv4 = { addresses = [ { address = inboundGateway; prefixLength = inboundRangePrefix; } ]; }; }; sops = { secrets = { "tv/network/password".sopsFile = "${inputs.secrets}/hosts/jupiter/secrets.yaml"; "tv/adguard/admin".sopsFile = "${inputs.secrets}/hosts/jupiter/secrets.yaml"; }; templates.adguard-env.content = '' ADGUARD_ADMIN_PASSWORD=${config.sops.placeholder."tv/adguard/admin"} ''; }; services.hostapd = { enable = true; radios.${inboundInterface} = { band = "2g"; channel = 2; countryCode = "GB"; networks.${inboundInterface} = { ssid = "jupiter-tv"; authentication.saePasswords = [ { passwordFile = config.sops.secrets."tv/network/password".path; } ]; }; }; }; virtualisation.quadlet = { volumes.tv-adguard = { }; containers.tv-adguard = { containerConfig = { image = "docker-archive:${pkgs.dockerImages.adguardhome}"; volumes = let config = (pkgs.formats.yaml { }).generate "config.yaml.default" { http.address = "${inboundGateway}:8080"; dns = { bind_hosts = [ inboundGateway ]; port = 53; ratelimit = 0; }; dhcp = { enabled = true; interface_name = inboundInterface; local_domain_name = "local"; dhcpv4 = { gateway_ip = inboundGateway; subnet_mask = inboundRangeMask; range_start = inboundRangeStart; range_end = inboundRangeStop; }; }; filters = [ ]; whitelist_filters = [ ]; filtering.rewrites = [ { domain = "beta.media.karaolidis.com"; answer = inboundGateway; } ]; user_rules = let domains = [ # Personal "beta.media.karaolidis.com" # Connectivity Check "clients3.google.com" "clients.l.google.com" "connectivitycheck.gstatic.com" "connectivitycheck.android.com" # NTP "pool.ntp.org" "time.android.com" "time.akamai.com" # Plex "plex.tv" "plex.direct" # YouTube "youtube.com" "yt.be" "ytimg.com" "googlevideo.com" # YouTube Extensions "returnyoutubedislikeapi.com" "sponsor.ajay.app" # Google Misc "accounts.google.com" "www.gstatic.com" "content-autofill.googleapis.com" # Google Play "play.google.com" "android.googleapis.com" "androidtvsetupwraithfe-pa.googleapis.com" "play-fe.googleapis.com" "play-lh.googleusercontent.com" "play.googleapis.com" "android.apis.google.com" "playatoms-pa.googleapis.com" "gvt1.com" # Spotify "spotify.com" "spotify.dev" "scdn.co" "tospotify.com" "spotifycdn.com" # Twitch "twitch.tv" "ttvnw.net" "static-cdn.jtvnw.net" # Cosmote TV "account.cosmote.gr" "cosmotetvott.gr" "msvdn.net" "theplatform.eu" "theplatform.com" # Releases "github.com" "release-assets.githubusercontent.com" ]; in [ "||*^" ] ++ (map (domain: "@@||${domain}^$important") domains); schema_version = 29; }; in [ "${config}:/etc/adguard/config.yaml.default" "${volumes.tv-adguard.ref}:/var/lib/adguard" ]; networks = [ "host" ]; addCapabilities = [ "NET_RAW" "NET_ADMIN" ]; environmentFiles = [ config.sops.templates.adguard-env.path ]; }; unitConfig.After = [ "sops-nix.service" ]; }; }; }