{ fleetModules, pkgs, lib, config, ... }: { imports = [ ./hardware-configuration.nix ] ++ fleetModules [ "common" "ccr" "ssh" ]; ccr = { enable = true; modules = [ "shell" "git" ]; packages = []; extraGroups = [ "wheel" "fuse" "networkmanager" ]; }; systemd.services.standby-sdb = { description = "Set spindown time (sleep) for /dev/sdb "; wantedBy = ["multi-user.target"]; serviceConfig = { Type = "oneshot"; ExecStart = "${pkgs.hdparm}/bin/hdparm -B 127 -S 241 /dev/sdb"; }; }; systemd.services.standby-sdc = { description = "Set spindown time (sleep) for /dev/sdc "; wantedBy = ["multi-user.target"]; serviceConfig = { Type = "oneshot"; ExecStart = "${pkgs.hdparm}/bin/hdparm -B 127 -S 241 /dev/sdc"; }; }; systemd.services.amuled.serviceConfig.Restart = pkgs.lib.mkForce "always"; users.users.amule = { isNormalUser = false; isSystemUser = true; group = "amule"; }; users.groups."amule" = {}; services = { samba-wsdd = { enable = true; workgroup = "WORKGROUP"; hostname = "nas"; discovery = true; }; samba = { enable = true; securityType = "user"; extraConfig = '' workgroup = WORKGROUP server string = nas netbios name = nas security = user map to guest = bad user vfs objects = recycle recycle:repository = .recycle recycle:keeptree = yes recycle:versions = yes ''; shares = { archivio = { path = "/mnt/archivio/archivio"; comment = "archivio"; "force user" = "ccr"; browseable = "yes"; writeable = "yes"; "guest ok" = "yes"; "read only" = "no"; }; film = { path = "/mnt/film/film"; comment = "film"; "force user" = "ccr"; browseable = "yes"; writeable = "yes"; "guest ok" = "yes"; "read only" = "no"; }; transmission = { path = "/mnt/archivio/transmission"; comment = "transmission"; "force user" = "transmission"; browseable = "yes"; writeable = "yes"; "guest ok" = "yes"; "read only" = "no"; }; amule = { path = "/mnt/archivio/amule"; comment = "amule"; "force user" = "ccr"; browseable = "yes"; writeable = "yes"; "guest ok" = "yes"; "read only" = "no"; }; musica = { path = "/mnt/film/musica"; comment = "music"; "force user" = "ccr"; browseable = "yes"; writeable = "no"; "guest ok" = "yes"; "read only" = "no"; }; }; }; transmission = { enable = true; # following json is merged to this attrset, it must have `rpc-username` and `rpc-password` credentialsFile = "/mnt/archivio/transmission/credentials.json"; settings = { download-dir = "/mnt/archivio/transmission/"; incomplete-dir = "/mnt/archivio/transmission/.incomplete"; incomplete-dir-enabled = true; rpc-port = 9091; rpc-whitelist-enabled = false; rpc-host-whitelist-enabled = false; rpc-authentication-required = true; }; }; amule = { dataDir = "/mnt/archivio/amule"; enable = true; user = "amule"; }; calibre-web = { enable = true; listen = { ip = "0.0.0.0"; port = 9092; }; options.calibreLibrary = "/mnt/archivio/calibre/"; openFirewall = true; }; syncthing = { enable = true; guiAddress = "0.0.0.0:8384"; dataDir = "/mnt/archivio/syncthing"; user = "ccr"; overrideDevices = false; overrideFolders = false; folders = { "/mnt/archivio/syncthing/camera" = { id = "camera"; }; "/mnt/archivio/syncthing/orgzly" = { id = "orgzly"; }; "/mnt/archivio/syncthing/roam" = { id = "roam"; }; "/mnt/archivio/syncthing/whatsapp" = { id = "whatsapp"; }; "/mnt/archivio/syncthing/calls" = { id = "calls"; }; }; }; navidrome = { enable = false; settings = { Address = "0.0.0.0"; Port = 9093; MusicFolder = "/mnt/film/musica"; DataFolder = "/mnt/film/musica/.navidrome"; }; }; nginx = { enable = true; recommendedGzipSettings = true; recommendedOptimisation = true; recommendedProxySettings = true; recommendedTlsSettings = true; clientMaxBodySize = "10G"; # max file size for uploads commonHttpConfig = '' log_format upstream_time '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent"' 'rt=$request_time uct="$upstream_connect_time" uht="$upstream_header_time" urt="$upstream_response_time"'; ''; virtualHosts = { "torrent.ccr.ydns.eu" = { enableACME = true; forceSSL = true; locations."/" = { proxyPass = "http://localhost:9091"; }; }; "sync.ccr.ydns.eu" = { enableACME = true; addSSL = true; locations."/" = { proxyPass = "http://localhost:8384"; }; }; "books.ccr.ydns.eu" = { enableACME = true; addSSL = true; locations."/" = { proxyPass = "http://localhost:9092"; }; }; "music.ccr.ydns.eu" = { enableACME = true; addSSL = true; locations."/" = { proxyPass = "http://localhost:9093"; }; }; "gate.ccr.ydns.eu" = { enableACME = true; addSSL = true; locations."/" = { proxyPass = "http://192.168.1.71:80"; }; }; }; }; }; systemd.services.ydns = let ydnsUpdater = pkgs.writeScriptBin "ydnsUpdater" '' USER="andrea.ciceri@autistici.org" PASSWORD=$(cat /home/ccr/.ydns-password) DOMAIN="ccr.ydns.eu" for SUBDOMAIN in "books" "music" "sync" "torrent" "gate" do HOST="$SUBDOMAIN.$DOMAIN" ${pkgs.curl}/bin/curl --basic -u "$USER:$PASSWORD" --silent https://ydns.io/api/v1/update/?host=$HOST done ${pkgs.curl}/bin/curl --basic -u "$USER:$PASSWORD" --silent https://ydns.io/api/v1/update/?host=$DOMAIN ''; in { description = "YDNS IP updater"; wantedBy = ["multi-user.target"]; after = ["network.target"]; serviceConfig = { User = "root"; Type = "oneshot"; ExecStart = "${pkgs.bash}/bin/bash ${ydnsUpdater}/bin/ydnsUpdater"; }; }; # TODO It seems to not work systemd.timers.ydnsUpdater = { wantedBy = ["timers.target"]; partOf = ["ydnsUpdater.service"]; timerConfig = { OnCalendar = "*-*-* *:00:00"; # hourly Unit = "ydnsUpdater.service"; }; }; networking.firewall = { enable = true; allowPing = true; allowedTCPPorts = [ 80 # http 139 # samba 443 # https 445 # samba 4712 # amule 4711 # amule web gui 8384 # syncthing 53 # dns ]; allowedUDPPorts = [ 137 # samba 138 # samba 51820 # wireguard 53 # dns ]; }; networking.nat.enable = true; networking.nat.externalInterface = "enp0s10"; networking.nat.internalInterfaces = ["wg0"]; networking.wireguard.interfaces = { # "wg0" is the network interface name. You can name the interface arbitrarily. wg0 = { # Determines the IP address and subnet of the server's end of the tunnel interface. ips = ["10.100.0.1/24"]; # The port that WireGuard listens to. Must be accessible by the client. listenPort = 51820; # This allows the wireguard server to route your traffic to the internet and hence be like a VPN # For this to work you have to set the dnsserver IP of your router (or dnsserver of choice) in your clients postSetup = '' ${pkgs.iptables}/bin/iptables -t nat -A POSTROUTING -s 10.100.0.0/24 -o enp0s10 -j MASQUERADE ''; # This undoes the above command postShutdown = '' ${pkgs.iptables}/bin/iptables -t nat -D POSTROUTING -s 10.100.0.0/24 -o enp0s10 -j MASQUERADE ''; # Path to the private key file. # # Note: The private key can also be included inline via the privateKey option, # but this makes the private key world-readable; thus, using privateKeyFile is # recommended. privateKeyFile = "/home/ccr/wireguard-keys/private"; peers = [ # List of allowed peers. { # Feel free to give a meaning full name # Public key of the peer (not a file path). publicKey = "fCwjd75CefC9A7WqO7s3xfOk2nRcoTKfnAzDT6Lc5AA="; # List of IPs assigned to this peer within the tunnel subnet. Used to configure routing. allowedIPs = ["10.100.0.2/32"]; } ]; }; }; security.acme = { acceptTerms = true; defaults.email = "andrea.ciceri@autistici.org"; }; nix = { gc = { automatic = true; options = lib.mkForce "--delete-older-than 3d"; }; }; powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; # TODO move away networking.nameservers = [ # https://libreops.cc/radicaldns.html "88.198.92.222" "192.71.166.92" ]; #environment.etc."coredns/blocklist.hosts".source = ../blocklist.hosts; services.coredns = { enable = true; config = '' . { # RadicalDNS Forwarding forward . 88.198.92.222 192.71.166.92 cache } ccr.ydns.eu { template IN A { answer "{{ .Name }} 0 IN A 192.168.1.33" } } *.ccr.ydns.eu { template IN A { answer "{{ .Name }} 0 IN A 192.168.1.33" } } ''; }; }