{ config, pkgs, lib, ... }: { # For nautilius and iOS services.gvfs.enable = true; # iOS services.usbmuxd.enable = true; environment.systemPackages = with pkgs; [libimobiledevice idevicerestore]; # https://unix.stackexchange.com/questions/592775/how-can-i-enable-apple-ios-fast-charge-support services.udev.extraRules = '' SUBSYSTEM=="usb", ACTION=="add", DRIVER=="apple-mfi-fastcharge", RUN+="/bin/sh -c 'echo Fast > /sys/class/power_supply/apple_mfi_fastcharge/charge_type'" ''; users.users.root.openssh.authorizedKeys.keys = let ids = import ../../../identities.nix; in builtins.concatMap builtins.attrValues (builtins.attrValues ids); networking = { networkmanager.enable = lib.mkForce false; firewall.allowedTCPPorts = [ 8080 # For 'localsend' # https://github.com/localsend/localsend?tab=readme-ov-file#setup 53317 ]; # To enable roaming https://wiki.archlinux.org/title/Wpa_supplicant#Roaming wireless = { enable = true; userControlled.enable = true; secretsFile = config.age.secrets.wpa_password.path; scanOnLowSignal = false; networks = let # wpa_supplicant uses `strchr` to seek to the first `=`, so the only forbidden character is `=`. escapePwdKey = lib.replaceStrings ["="] ["_"]; privatePriority = 10; limitedPriority = -10; fromList = ns: let go = networkArgs @ { ssid, # Custom fields wrapping nixpkgs module options hasPassword ? false, scanOnLowSignal ? false, randomizeMac ? false, ... }: { ${ssid} = lib.mkMerge [ (builtins.removeAttrs networkArgs ["ssid" "hasPassword" "scanOnLowSignal" "randomizeMac"]) (lib.optionalAttrs hasPassword { pskRaw = "ext:${escapePwdKey ssid}"; }) (lib.optionalAttrs scanOnLowSignal { extraConfig = '' bgscan="simple:30:-70:3600" ''; }) (lib.optionalAttrs randomizeMac { extraConfig = '' mac_addr=1 ''; }) ]; }; in lib.mkMerge (map go ns); in fromList [ { ssid = "~"; priority = privatePriority; hasPassword = true; } { ssid = "Pei’s Wifi"; priority = privatePriority; hasPassword = true; } { ssid = "girlypop-net"; priority = privatePriority; hasPassword = true; } { ssid = "annapurna"; priority = privatePriority; hasPassword = true; scanOnLowSignal = true; } { ssid = "5526-1"; # TODO: set bssid preference ? priority = privatePriority; hasPassword = true; scanOnLowSignal = true; } { ssid = "eduroam"; priority = privatePriority; scanOnLowSignal = true; authProtocols = ["WPA-EAP"]; auth = '' pairwise=CCMP group=CCMP TKIP eap=PEAP ca_cert="${./certs/universite_de_rennes.pem}" identity="ychiang@etudiant.univ-rennes.fr" altsubject_match="DNS:radius.univ-rennes1.fr;DNS:radius1.univ-rennes1.fr;DNS:radius2.univ-rennes1.fr;DNS:vmradius-psf1.univ-rennes1.fr;DNS:vmradius-psf2.univ-rennes1.fr" phase2="auth=MSCHAPV2" password=ext:EDUROAM anonymous_identity="anonymous@univ-rennes.fr" ''; } { ssid = "A-WAY"; priority = privatePriority; hasPassword = true; randomizeMac = true; } { ssid = "CAT.jpgcafe"; priority = privatePriority; hasPassword = true; randomizeMac = true; } { ssid = "LOUISA"; # 區公所 priority = privatePriority; hasPassword = true; randomizeMac = true; } { ssid = "LouisaCoffee"; # 七張 priority = privatePriority; hasPassword = true; randomizeMac = true; } { ssid = "MetroTaipei x Louisa"; # 大安 priority = privatePriority; hasPassword = true; randomizeMac = true; } {ssid = "_SNCF_WIFI_INOUI";} {ssid = "_WIFI_LYRIA";} {ssid = "EurostarTrainsWiFi";} {ssid = "SBB-FREE";} {ssid = "AOT Airport Free Wi-Fi by NT";} {ssid = "NewTaipei";} {ssid = "Fami-WiFi";} { ssid = "iPhone de Léana 江"; priority = limitedPriority; hasPassword = true; } ]; }; }; services.mullvad-vpn.enable = true; hardware.bluetooth.enable = true; # # Secure DNS # # https://nixos.wiki/wiki/Encrypted_DNS networking = { nameservers = ["127.0.0.1" "::1"]; dhcpcd.extraConfig = "nohook resolv.conf"; # networkmanager.dns = "none"; }; services.resolved.enable = false; services.dnscrypt-proxy2 = { enable = true; # Settings reference: # https://github.com/DNSCrypt/dnscrypt-proxy/blob/master/dnscrypt-proxy/example-dnscrypt-proxy.toml settings = { listen_addresses = ["127.0.0.1:53"]; ipv4_servers = true; require_dnssec = true; require_nolog = true; require_nofilter = true; lb_strategy = "p2"; lb_estimator = true; # Prevent building up reliance on chatbots # Gotta preserve that thinking ability of my smoof bwain blocked_names = { blocked_names_file = let ai-blocklist = pkgs.fetchFromGitHub { owner = "laylavish"; repo = "uBlockOrigin-HUGE-AI-Blocklist"; rev = "f63645250fbd982b8a6ebc9b384e7dbbc37d174c"; hash = "sha256-nuZnU+CJYdN8dR7yC8Zq13C8MgBYwZZdyQEFeSMUQkA="; } + "/noai_hosts.txt"; # Blocklists are made of one pattern per line. # https://github.com/DNSCrypt/dnscrypt-proxy/blob/fa59f990431a49b6485f63f96601bc7e64017bf8/dnscrypt-proxy/example-dnscrypt-proxy.toml#L583C4-L583C75 blocked_names = lib.pipe (builtins.readFile ai-blocklist) [ (lib.replaceStrings ["\r\n"] ["\n"]) # convert to unix ending just in case (lib.splitString "\n") (builtins.filter (x: ! (x == "" || lib.hasPrefix "#" x))) (builtins.map (x: builtins.elemAt (lib.splitString " " x) 1)) # remove 0.0.0.0 ]; in pkgs.writeText "no-ai-blocklist" (builtins.concatStringsSep "\n" blocked_names); }; # Add this to test if dnscrypt-proxy is actually used to resolve DNS requests # query_log.file = "/var/log/dnscrypt-proxy/query.log"; sources.public-resolvers = { urls = [ "https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v3/public-resolvers.md" "https://download.dnscrypt.info/resolvers-list/v3/public-resolvers.md" ]; cache_file = "/var/cache/dnscrypt-proxy/public-resolvers.md"; minisign_key = "RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3"; }; }; }; }