diff --git a/src/system/machines/server/hardware.nix b/src/system/machines/server/hardware.nix index fb45e7f..8a9ebe5 100644 --- a/src/system/machines/server/hardware.nix +++ b/src/system/machines/server/hardware.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, modulesPath, ... }: +{ config, lib, modulesPath, ... }: { imports = [ @@ -17,14 +17,6 @@ hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; - # Enable VAAPI for hardware video acceleration - hardware.graphics = { - enable = true; - extraPackages = with pkgs; [ - intel-vaapi-driver # i965 driver for Haswell - ]; - }; - nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; powerManagement.cpuFreqGovernor = lib.mkDefault "ondemand"; } diff --git a/src/system/machines/server/system.nix b/src/system/machines/server/system.nix index c290f9d..5278443 100644 --- a/src/system/machines/server/system.nix +++ b/src/system/machines/server/system.nix @@ -7,13 +7,13 @@ modules.system = { nginx.enable = true; forgejo.enable = true; - frigate.enable = true; + frigate.enable = false; immich.enable = true; - # bitcoin = { - # enable = true; - # electrum.enable = true; - # clightning.enable = true; - # }; + bitcoin = { + enable = true; + electrum.enable = true; + clightning.enable = true; + }; backup = { enable = true; @@ -120,19 +120,6 @@ firewall = { enable = true; allowedTCPPorts = [ 22 ]; - allowedUDPPorts = [ 53 67 ]; # DNS + DHCP - extraCommands = '' - # Block specific camera MACs from forwarding (instant DROP, no timeouts) - # Add each camera MAC here as you set them up - iptables -A FORWARD -m mac --mac-source 00:1f:54:c2:d1:b1 -j DROP # parking_lot - iptables -A FORWARD -m mac --mac-source 00:1f:54:b2:9b:1d -j DROP # living_room/kitchen - iptables -A FORWARD -m mac --mac-source 00:1f:54:a9:81:d1 -j DROP # doorbell - ''; - extraStopCommands = '' - iptables -D FORWARD -m mac --mac-source 00:1f:54:c2:d1:b1 -j DROP || true - iptables -D FORWARD -m mac --mac-source 00:1f:54:b2:9b:1d -j DROP || true - iptables -D FORWARD -m mac --mac-source 00:1f:54:a9:81:d1 -j DROP || true - ''; }; }; @@ -156,16 +143,12 @@ interface = "enp2s0f1"; bind-interfaces = true; dhcp-range = "192.168.1.100,192.168.1.200,24h"; - - # Static DHCP reservations for cameras - dhcp-host = [ - "00:1f:54:c2:d1:b1,192.168.1.194,parking_lot" - "00:1f:54:b2:9b:1d,192.168.1.147,living_room_kitchen" - "00:1f:54:a9:81:d1,192.168.1.167,doorbell" - ]; + # No gateway option = cameras can't route to internet }; }; + networking.firewall.allowedUDPPorts = [ 53 ]; + services.fail2ban = { enable = true; maxretry = 5; diff --git a/src/system/modules/backup/default.nix b/src/system/modules/backup/default.nix index 511b332..07a3895 100644 --- a/src/system/modules/backup/default.nix +++ b/src/system/modules/backup/default.nix @@ -9,7 +9,6 @@ let # Convert absolute paths to relative for tar, preserving structure # e.g., /var/lib/forgejo -> var/lib/forgejo tarPaths = map (p: removePrefix "/" p) cfg.paths; - excludeArgs = concatMapStrings (e: "--exclude='${e}' ") cfg.exclude; backupScript = pkgs.writeShellScript "backup" '' set -euo pipefail @@ -23,7 +22,7 @@ let echo "Paths: ${concatStringsSep " " cfg.paths}" export PATH="${pkgs.age-plugin-yubikey}/bin:$PATH" - ${pkgs.gnutar}/bin/tar -C / ${excludeArgs}-cf - ${concatStringsSep " " tarPaths} | \ + ${pkgs.gnutar}/bin/tar -C / -cf - ${concatStringsSep " " tarPaths} | \ ${pkgs.age}/bin/age ${recipientArgs} -o "$TEMP_DIR/$BACKUP_NAME" ${pkgs.rclone}/bin/rclone --config /root/.config/rclone/rclone.conf copy "$TEMP_DIR/$BACKUP_NAME" "${cfg.destination}" @@ -50,12 +49,6 @@ in description = "Absolute paths to include in backup (structure preserved)"; }; - exclude = mkOption { - type = types.listOf types.str; - default = []; - description = "Patterns to exclude (passed to tar --exclude)"; - }; - recipients = mkOption { type = types.listOf types.str; default = []; diff --git a/src/system/modules/frigate/README.md b/src/system/modules/frigate/README.md deleted file mode 100644 index 0166264..0000000 --- a/src/system/modules/frigate/README.md +++ /dev/null @@ -1,119 +0,0 @@ -# Frigate Camera Setup - -## Camera Models - -| Camera | Model | MAC | IP | -|--------|-------|-----|-----| -| parking_lot | W461ASC | 00:1f:54:c2:d1:b1 | 192.168.1.194 | -| doorbell | B463AJ | 00:1f:54:a9:81:d1 | 192.168.1.167 | -| living_room | W463AQ (ch1) | 00:1f:54:b2:9b:1d | 192.168.1.147 | -| kitchen | W463AQ (ch2) | 00:1f:54:b2:9b:1d | 192.168.1.147 | -| porch | SL300 | | | | - -## Network Architecture - -- Camera network: 192.168.1.0/24 (isolated, no internet) -- Server NIC: enp2s0f1 @ 192.168.1.1 -- WiFi AP: TP-Link RE315 @ 192.168.1.254 -- DHCP range: 192.168.1.100-200 - -## RTSP URL Format - -``` -rtsp://admin:ocu?u3Su@/cam/realmonitor?channel=&subtype=0 -``` - -- channel=1 for single-camera devices -- channel=1,2 for dual-camera devices (W463AQ) -- subtype=0 for main stream, subtype=1 for sub stream - -## Camera Reset Procedures - -### W461ASC (parking_lot) -1. Keep camera powered on -2. Reset button is on the back of the camera -3. Press and hold reset button for 30-60 seconds until chime sounds - -### B463AJ (doorbell) -1. Remove doorbell from mount -2. Locate reset button on the back -3. Press and hold until you hear chime reset sound -4. Reconnect via Lorex app as new device - -### W463AQ (living_room/kitchen) -1. Keep camera powered on -2. Rotate the lens upwards to reveal hidden reset button -3. Press and hold reset button until you hear audio prompt -4. Flashing green Smart Security Lighting confirms reset -5. Solid green = not fully reset, repeat if needed - -### SL300 (porch) -1. Keep camera powered on -2. Tilt camera lens upwards to reveal reset/microSD card cover -3. Remove the cover -4. Press and hold reset button until audio prompt -5. Replace cover quickly -6. Wait for green LED flash + audio confirmation - -## Initial Setup - -1. Temporarily enable internet for camera network: - ```bash - sudo iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o enp2s0f0 -j MASQUERADE - sudo sysctl -w net.ipv4.ip_forward=1 - ``` - -2. Connect camera to "cams" WiFi network - -3. Use Lorex app to configure camera (requires cloud - CCP middleman) - -4. Get camera MAC from DHCP leases: - ```bash - cat /var/lib/dnsmasq/dnsmasq.leases - ``` - -5. Add DHCP reservation in `system.nix`: - ```nix - dhcp-host = [ - "aa:bb:cc:dd:ee:ff,192.168.1.XXX,camera_name" - ]; - ``` - -6. Add MAC to firewall block list in `system.nix`: - ```nix - iptables -A FORWARD -m mac --mac-source aa:bb:cc:dd:ee:ff -j DROP - ``` - -7. Update camera IP in `frigate/default.nix` and enable - -8. Deploy and disable internet: - ```bash - nixos-rebuild switch --flake .#server --target-host server - sudo iptables -t nat -D POSTROUTING -s 192.168.1.0/24 -o enp2s0f0 -j MASQUERADE - sudo sysctl -w net.ipv4.ip_forward=0 - ``` - -## Storage - -Frigate data is stored on /data to avoid filling root partition: - -| Path | Bind Mount | Contents | -|------|------------|----------| -| /var/lib/frigate | /data/frigate/lib | Database, recordings, clips | -| /var/cache/frigate | /data/frigate/cache | Temporary cache | -| /var/cache/nginx/frigate | /data/frigate/nginx-cache | API response cache | - -## Notes - -- Lorex cameras are cloud-only for configuration (no local web UI responds) -- RTSP works locally without internet -- Cameras phone home aggressively when internet is available - keep isolated -- Haswell CPU cannot hardware decode HEVC - using CPU decode -- Consider T400 GPU for hardware acceleration if scaling to more cameras - -## Port Scan Results (W461ASC) - -- 80/tcp - HTTP (non-responsive, proprietary) -- 554/tcp - RTSP (working) -- 8086/tcp - Proprietary -- 35000/tcp - Proprietary diff --git a/src/system/modules/frigate/default.nix b/src/system/modules/frigate/default.nix index 11c14d3..94e345c 100644 --- a/src/system/modules/frigate/default.nix +++ b/src/system/modules/frigate/default.nix @@ -16,46 +16,38 @@ in services.frigate = { enable = true; hostname = "frigate.${domain}"; - # vaapiDriver = "i965"; # Haswell only supports H.264, not HEVC settings = { mqtt.enabled = false; - # ffmpeg.hwaccel_args = "preset-vaapi"; # Disabled - camera uses HEVC which Haswell can't decode - record.enabled = true; cameras = { doorbell = { - enabled = true; detect.enabled = false; ffmpeg.inputs = [{ - path = "rtsp://admin:ocu?u3Su@192.168.1.167/cam/realmonitor?channel=1&subtype=0"; + path = "rtsp://admin:ocu?u3Su@192.168.0.134/cam/realmonitor?channel=1&subtype=0"; roles = [ "record" ]; }]; }; living_room = { - enabled = false; detect.enabled = false; ffmpeg.inputs = [{ - path = "rtsp://admin:ocu?u3Su@192.168.1.147/cam/realmonitor?channel=1&subtype=0"; + path = "rtsp://admin:ocu?u3Su@192.168.0.181/cam/realmonitor?channel=1&subtype=0"; roles = [ "record" ]; }]; }; kitchen = { - enabled = false; detect.enabled = false; ffmpeg.inputs = [{ - path = "rtsp://admin:ocu?u3Su@192.168.1.147/cam/realmonitor?channel=2&subtype=0"; + path = "rtsp://admin:ocu?u3Su@192.168.0.181/cam/realmonitor?channel=2&subtype=0"; roles = [ "record" ]; }]; }; parking_lot = { - enabled = true; detect.enabled = false; ffmpeg.inputs = [{ - path = "rtsp://admin:ocu?u3Su@192.168.1.194/cam/realmonitor?channel=1&subtype=0"; + path = "rtsp://admin:ocu?u3Su@192.168.0.59/cam/realmonitor?channel=1&subtype=0"; roles = [ "record" ]; }]; }; porch = { - enabled = false; detect.enabled = false; ffmpeg.inputs = [{ path = "rtsp://admin:ocu?u3Su@192.168.0.43/cam/realmonitor?channel=1&subtype=0"; @@ -72,27 +64,5 @@ in forceSSL = true; }; - # Bind mount caches into the 3TB frigate LVM volume - systemd.tmpfiles.rules = [ - "d /var/lib/frigate/cache 0750 frigate frigate -" - "d /var/lib/frigate/nginx-cache 0750 nginx nginx -" - ]; - - fileSystems."/var/cache/frigate" = { - device = "/var/lib/frigate/cache"; - options = [ "bind" ]; - }; - - fileSystems."/var/cache/nginx/frigate" = { - device = "/var/lib/frigate/nginx-cache"; - options = [ "bind" ]; - }; - - # Backup recordings/database, exclude caches - modules.system.backup = { - paths = [ "/var/lib/frigate" ]; - exclude = [ "*/cache" "*/nginx-cache" ]; - }; - }; }