mirror of
https://github.com/itme-brain/nixos.git
synced 2026-03-23 16:29:42 -04:00
Compare commits
No commits in common. "ac95d1c23d75dd095083e4b914562279b67bf140" and "887dcaf16ffc7350d8261bd211405f1e02e3b009" have entirely different histories.
ac95d1c23d
...
887dcaf16f
5 changed files with 15 additions and 196 deletions
|
|
@ -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";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,15 +143,11 @@
|
|||
interface = "enp2s0f1";
|
||||
bind-interfaces = true;
|
||||
dhcp-range = "192.168.1.100,192.168.1.200,24h";
|
||||
# No gateway option = cameras can't route to internet
|
||||
};
|
||||
};
|
||||
|
||||
# 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"
|
||||
];
|
||||
};
|
||||
};
|
||||
networking.firewall.allowedUDPPorts = [ 53 ];
|
||||
|
||||
services.fail2ban = {
|
||||
enable = true;
|
||||
|
|
|
|||
|
|
@ -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 = [];
|
||||
|
|
|
|||
|
|
@ -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@<IP>/cam/realmonitor?channel=<CH>&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
|
||||
|
|
@ -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" ];
|
||||
};
|
||||
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue