Compiling Q2Admin r872 for i386 and x64

q2admin-r872 running

Note: As I already have all of these dependencies installed, it can be hard for me to sometimes determine exactly what you might need to apt-install. Let me know if anything goes awry in the comments and I’ll update the guide!

Edit: I’ll try and get this wrapped into a script you can just run that will do all the work and prep/compile the build.

The most-excellent PacketFlinger has kept a version of Quake 2’s former cheat detection mod q2admin still running after all these years. His version works very well for me on both older i386 mods, and modern mods on x64. And I’m going to show you how you can compile it for your own server, on Ubuntu Linux.

First, we need to install the required dependencies. If you plan to build the i386 version for older mods, then run this to install the i386 version of libc:

sudo dpkg --add-architecture i386
sudo apt update
sudo apt install libc6:i386

You will also need some standard packages if you don’t have them installed already for some reason:

sudo apt install git build-essential gcc-multilib g++-multilib pkg-config make perl wget curl ca-certificates tar xz-utils file binutils

Next, we need to clone the q2admin git repository. Make sure you’re in the folder where you want to download it to. The git clone command will automatically create a subfolder named q2admin:

git clone https://github.com/packetflinger/q2admin
cd q2admin

For i386 builds, we need to modify the Makefile slightly. If you’re not compiling for i386 mods, skip down to make — and yes, I should really learn how to commit changes to a git repository one of these days… maybe I’ll try that after this guide, so I can commit this Makefile change to the q2admin repository. Edit Makefile with your editor of choice, for me, that’s nano. I have, since forever, ran nano with -w to prevent line wrapping:

nano -w Makefile

Add the lines in bold below to your Makefile. The change should begin around line 77 or so. You can press CTRL-W, CTRL-T, 77, [Enter] to jump to that line. Others may prefer CTRL-/, 77, [Enter], nano is versatile!

else
    CFLAGS += -fPIC -ffast-math -w -DLINUX
endif

ifeq ($(CPU),i386)
    CFLAGS += -m32
    LDFLAGS += -m32
endif

CFLAGS += -DQ2A_COMMIT='"$(VER)"' -DQ2A_REVISION=$(REV) -DCPU='"$(CPU)"'

CTRL-X, Y, [Enter] to save your changes. Others may prefer CTRL-O, [Enter], CTRL-X which will do the same thing.

We can immediately compile the x86_64 version by simply typing make:

make

This should produce a gamex86_64-q2admin-r###.so file, which is your freshly compiled q2admin for 64-bit!

However, for i386, we are again going to have to do a few things, namely we need to recompile the dependencies to avoid a linker warning after compiling. You’ll also have the most up to date version of q2admin possible for i386, including its libraries. You must determine the full path to your q2admin/deps/ folder, so if you ran git clone in your home directory, this will be ~/q2admin/deps/. From a shell, first set a variable the next script will use. Modify the path in the below if necessary. Do not put a trailing / at the end. Do not put quotes () around it either!

Q2ADEPS=~/q2admin/deps

The above command will set a variable, $Q2ADEPS, that we use in the below snippet. In that same shell, run the following, which will download and compile zlib, curl, and openssl i386 dependencies.

cd /tmp; rm -rf zlib-1.3.2 openssl-3.0.16 curl-8.8.0
wget -nc https://zlib.net/zlib-1.3.2.tar.gz https://www.openssl.org/source/openssl-3.0.16.tar.gz https://curl.se/download/curl-8.8.0.tar.gz
tar xf zlib-1.3.2.tar.gz -C /tmp; cd /tmp/zlib-1.3.2; CFLAGS="-m32 -fPIC -O3" ./configure --static --prefix="$Q2ADEPS/i386/zlib"; make clean; make -j"$(nproc)"; make install
tar xf /tmp/openssl-3.0.16.tar.gz -C /tmp; cd /tmp/openssl-3.0.16; ./Configure linux-x86 no-shared no-tests no-module enable-pic --prefix="$Q2ADEPS/i386/openssl" CFLAGS="-m32 -fPIC"; make clean; make -j"$(nproc)"; make install_sw
tar xf /tmp/curl-8.8.0.tar.gz -C /tmp; cd /tmp/curl-8.8.0; PKG_CONFIG_PATH="$Q2ADEPS/i386/openssl/lib/pkgconfig:$Q2ADEPS/i386/zlib/lib/pkgconfig" CFLAGS="-m32 -fPIC -O3" LDFLAGS="-m32" ./configure --host=i686-pc-linux-gnu --prefix="$Q2ADEPS/i386/curl" --disable-shared --enable-static --with-openssl="$Q2ADEPS/i386/openssl" --with-zlib="$Q2ADEPS/i386/zlib" --disable-ldap --disable-ldaps --without-brotli --without-zstd --without-nghttp2 --without-libpsl; make clean; make -j"$(nproc)"; make install
cd "$Q2ADEPS/.."

Note: The above links are bound to become outdated, I will try to keep them updated. You may have to get updated links if you’re reading this in 2030…

Finally, with ALL THAT out of the way, you can now type:

make CPU=i386

And that should give you a gamei386-q2admin-r###.so file!

Using and configuring q2admin is out of the scope of this guide, and worthy of a whole post or four in itself, so you’ll have to do some research on getting things configured for your server(s).

The README.md will be your absolute best starting point. And all of the stock configs are in your ~/q2admin/runtime-config/ folder.

HUGE shout out to PacketFlinger for keeping this alive! Thank you!!

pfSense WAN 5GbE to AT&T Modem

There’s a few ways to do this, I think the simplest, if you have the PCIE slot room would be to buy an ethernet card that supports 10/5/2.5/1GbE network speed negotiation.

But since I only have one real usable slot in my pfSense machine, and I need 10G for LAN, I opted for a dual-port Mellanox ConnectX-3 SFP card that I purchased off of eBay for $21 USD. An incredible buy. I would definitely recommend putting a fan on the heatsink if you have room, or blowing across the card is even better to help cool the SFP modules themselves. Especially when using ethernet modules, they run hotter than fiber modules.

For the SFP module, I chose a H!Fiber branded module: https://www.amazon.com/dp/B06XQBFHNL

Per the previous guide, I updated my /conf/dhcp6_att.conf to replace interface re0 with interface mlxen1 (by process of elimination or checking ifconfig to determine which slot is which. What the bracket of the card calls port 0 actually was my mlxen1 interface, in this case.

In pfSense, you will see it negotiate as 10Gbase-CX4. The speed of the port does not matter, assuming it supports your standard 1G/10G SFP+ port speeds. The module is what matters. The modules SFP end will interface with the port at 10Gbase-CX4, and the ethernet side of the module will interface with your modem at 5Gbase-T. You’ll have to login to your AT&T modem to confirm the speed of the client (under Device > Device List). Make sure you’re connected to the 5G port on the back of your AT&T BGW320!

As I only pay for the 1G plan, I am at least now able to pull the full speed.

Insanity.

pfSense, AT&T Fiber (BGW320), IPv6 Prefix Delegation

I’ve spent the last few days making this work properly across multiple VLANs, because AT&T does NOT even REMOTELY conform to any kind of industry standard for dishing out IPv6 blocks or addresses.

Normally your WAN would receive a /56 block from an ISP, giving you 00-FF in blocks to assign off of that. And everything you read online says AT&T gives out a /60, which is true. But it’s misleading if you’re expecting to be able to USE that /60. You cannot. You cannot give your WAN adapter a /60 prefix, it does not work that way. It will always be a /64. (we’re not talking about a custom ONT SFP module here or what-not, obviously some people have made it work that way).

So, assuming you just want to use the AT&T BGW320 as-is, and you want multiple IPv6 prefixes, here’s my quick little guide on that.

On the BGW320:

Turn all 3 settings to On under Home Network > IPv6

Under Firewall > Packet Filter, click to Disable Packet Filters (Note: This is not required for this guide, but you should just let pfSense handle packets if that’s your router)

Under Firewall > IP Passthrough
– Allocation Mode: Passthrough
– Passthrough Mode: DHCPS-fixed
– Passthrough Fixed MAC Address: pfSense WAN adapter MAC address

Under Firewall > Firewall Advanced: I would recommend Reflexive ACL, ESP ALG, SIP ALG be turned Off.

pfSense Configuration

Under Interfaces > WAN
– IPv6 Configuration Type: DHCP6

Note: If you only ever want 1 prefix to use for your LAN, and don’t plan to use any other /64 blocks, you do not have to use a custom configuration and could essentially stop here. Set DHCPv6 Prefix Delegation Size to 64 and that’s it, leave the rest of the boxes unchecked. Your WAN will get the passthrough address from the BGW320, and then you’ll have one prefix delegated to use which you can assign statically on your LAN adapter.

If you want multiple /64 prefixes to use, you will need to SSH into your pfSense machine. As that is kind of out of the scope of this guide, but basically use PuTTY or ssh from a linux machine to your pfSense LAN IP, and login with your admin credentials. The menu should say to enter option 8 for a shell I believe.

At the shell, type ls /var/etc/dhcp6*.conf to list your dhcp6 configuration file. It should either be dhcp6c.conf or dhcp6c_wan.conf in some cases I have read. Mine was dhcp6c.conf. We need to copy this file to a new location so we can modify it and use it as our custom WAN interface configuration file. So type cp /var/etc/dhcp6c.conf /conf/dhcp6c_att.conf

cp /var/etc/dhcp6c.conf /conf/dhcp6c_att.conf
nano -w /conf/dhcp6c_att.conf

Edit the file to include extra send ia-pd # lines. The stuff in bold is likely what will not already be in the file. But ultimately you need to start with send ia-pd 0, then 1, then 2, and so on. This is literally my current running configuration, so I hope it works for you. Do not blindly copy and paste this, make sure your interface name matches YOUR firewall, not mine! And yes, I plan to stop using a RealTek adapter soon. I also don’t think the prefix ::/64 infinity; lines are necessary but I added them just in case. The real important part is the send ia-pd lines.

interface re0 {
        send ia-na 0;
        send ia-pd 0;   # THIS WILL BE YOUR 'f' PREFIX and will probably already be in the file
        send ia-pd 1;   # ADD THIS to get the next prefix after f (e)
        send ia-pd 2;   # ..and so on, up to send ia-pd 7 if needed, for a total of 8 usable /64 blocks
        request domain-name-servers;
        request domain-name;
        script "/var/etc/dhcp6c_wan_script.sh";
};
id-assoc na 0 { };
id-assoc pd 0 {
        prefix ::/64 infinity;
};

id-assoc pd 1 {
        prefix ::/64 infinity;
};

id-assoc pd 2 {
        prefix ::/64 infinity;
};

To save your edited file, press CTRL-X, press Y to save, and then press Enter to overwrite the existing file. Alternatively, you can press CTRL-O and then Enter to write the changes out, and then CTRL-X to just exit.

You’ll notice that the blocks actually start at the end of the /60 from the BGW320. So if the BGW320 gives your WAN 2600:1700:a123:b340::, then your first usable /64 will be :b34F, the second is :b34E, the third would be :b34D and so on, C, B, A, 9, 8. 0-7 are reserved by the BGW320 for internal stuff apparently. Personally I’m only using 3 prefixes, and haven’t tested the limits.

Back in pfSense, under Interfaces > WAN, scroll down to DHCP6 Client Configuration, and enable the checkbox for Configuration Override. Type into Configuration File Override the following (or whatever you named your config): /conf/dhcp6c_att.conf

Save and apply your WAN changes. If all goes well, back on your BGW320 under Home Network > Status, you should see under the IPv6 section near the middle your IPv6 Delegated Prefix Subnet section, and it should list as many prefixes as you put send ia-pd’s into your dhcp6c_att.conf file.

Back in pfSense, under the lan/vlan/tunnel interface(s) you want to assign an IPv6 network to, set their IPv6 type to Static, and, e.g. with our example above, if you have 2600:1700:a123:b34f::/64 as one of your delegated prefixes, set your interface static to 2600:1700:a123:b34f::1 on a /64 subnet size. And then that interface will hold the ::1 ipv6 address on that prefix.

GOOD LUCK!

tzdata fails to upgrade on Ubuntu 23.10

If you’re getting a dpkg error about tzdata prematurely exiting, you need to get this file:
Ubuntu – Package Download Selection — tzdata_2024a-0ubuntu0.23.10_all.deb

Afterwards, install with dpkg -i tzdata_2024a-0ubuntu0.23.10_all.deb

Afterwards, you can do apt upgrade to upgrade to the latest one in the apt repo that was failing.

Hope this helps someone!

dpkg: error processing package tzdata (–configure):
installed tzdata package post-installation script subprocess returned error exit status 10
Errors were encountered while processing:
tzdata
needrestart is being skipped since dpkg has failed

Docker Compose with an external LAN / VLAN IP!

I just figured this out, and it’s too cool not to share. I have business grade switches at my house, so I have various VLANs setup already. You’ll need that in place to make this work, and have your port tagging in place already, etc.

This requires no additional configuration on the host. In the below, I’ve included two examples — default_lan and vlan5. So if you just want to give a container an IP on your local LAN, you can use default_lan for that. And if you’re looking to create a service on a vlan IP, you can use vlan5 as an example for that.

EDIT: YOU MAY NEED TO modprobe 8021q (and/or add it to /etc/modules)

You do not need to include default_lan in order to use a vlan. This also of course works great in Portainer.

networks:
  default_lan: # the name you'll reference in the service configuration
    driver: ipvlan
    driver_opts:
      parent: enp1s0d1 # the interface on your docker host that it will tunnel through
    ipam:
      config:
        - subnet: 10.1.1.0/24 # your networks subnet
          gateway: 10.1.1.1 # your networks gateway

  vlan5:
    driver: ipvlan
    driver_opts:
      parent: enp1s0d1.5 # I've added '.5' for vlan 5
    ipam:
      config:
        - subnet: 10.1.5.0/24 # the vlans subnet
          gateway: 10.1.5.1 # the vlans gateway

services:
  service_on_lan:
    networks:
      default_lan:
        ipv4_address: 10.1.1.51

  service_on_vlan:
    networks:
      vlan5:
        ipv4_address: 10.1.5.55

I have not tested, but I believe you can also just add another two subnet and gateway lines for ipv6 routing as well, and then specify your ipv6_address in the service.

You can also use macvlan instead, which will give the container a unique MAC address that you can see on your network. I have found the best way to do this is individually per-IP, at least for my needs. Otherwise you can easily run into duplicate IP problems.

networks:
  macvlan5_5: # the name you'll reference in the service configuration, and I give _5 as the IP
    driver: macvlan
    driver_opts:
      parent: enp1s0d1.5 # the interface on your docker host and .# for the vlan #
    ipam:
      config:
        - subnet: 10.1.5.0/24 # your networks subnet
          gateway: 10.1.5.1 # your networks gateway
          ip_range: 10.1.5.5/32 # the static ip you want to assign to this networks container

And then just assign the network in your container:

services:
  service_on_macvlan5:
    networks:
      - macvlan5_5

Unfortunately, the container does not seem to try to register with the defined hostname so my firewall just sees a new ‘unknown’ host on the random MAC address in the arp tables.

Check out the complete Docker Network Drivers Overview page for more examples and usage.

Frigate Docker Compose / Portainer

You will need to have Mosquitto MQTT setup before using Frigate — fortunately, I have a guide for that already!

https://itbacon.com/2023/08/01/installing-mosquitto-mqtt-in-portainer/

Once you have confirmed Mosquitto is up and running, we can deploy a Frigate stack. This particular stack has a device mapping for a Google Coral A+E key device, as well as using /dev/dri/renderD128 for onboard graphics (Intel, in this case). You’ll want to adjust some things, such as whatever MQTT username and password you created during MQTT setup/install (see the guide for help!), as well as your camera admin username and password. If you use different usernames and passwords for all your cameras, you can specify them individually in your Frigate configuration file after the stack is deployed.

Also in this stack is a configuration for using a Samba/Windows based NAS as a volume for /media/frigate, which is where recordings and snapshots will be saved to. Basically, what I’m saying is, you’ll need to make some changes to the below code after pasting it, in order to have it suit your needs.

The majority of my configuration file was taken from the Full Reference Configuration File which is an excellent reference with comments about the various options in the configuration file.

I had also initially planned to include my nvidia setup/configuration sections, but the machine I just moved Frigate into can only take one full length card, I have used it for something else.

services:
  frigate:
    container_name: "frigate"
    image: "ghcr.io/blakeblackshear/frigate:stable"
    hostname: "frigate"
    shm_size: 1024mb # increase if getting bus errors
    privileged: true
    restart: unless-stopped
    cap_add:
      - CAP_PERFMON
    devices:
      - /dev/dri/renderD128:/dev/dri/renderD128:ro # onboard video
      - /dev/apex_0:/dev/apex_0:ro # coral
    environment:
      - "TZ=EST5EDT" # your timezone
      - "FRIGATE_RTSP_USERNAME=admin" # camera admin username
      - "FRIGATE_RTSP_PASSWORD=password" # camera admin password
      - "FRIGATE_MQTT_USERNAME=frigate" # mqtt server username
      - "FRIGATE_MQTT_PASSWORD=password" # mqtt server password
    network_mode: host
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - data:/config
      # if you're not using a NAS, change NAS to the path you're using
      # e.g. /mnt/frigate:/media/frigate or /any/path:/media/frigate
      - NAS:/media/frigate
      - type: tmpfs
        target: /tmp/cache
        tmpfs:
          size: 1G

volumes:
  data:
  mqtt_data:
  NAS:
    driver_opts:
      type: cifs
      o: "addr=IP.OF.NAS,username=SAMBA_USERNAME,password=SAMBA_PASSWORD,iocharset=utf8,file_mode=0600,dir_mode=0700"
      device: "//IP.OF.NAS/SharedFolder"

networks:
  frigate:

Here is my Frigate configuration file. It will be in /var/lib/docker/volumes/frigate_data/_data/config.yml

I know it’s kind of a mess, and there’s probably some redundant things in here, but I just felt bad about not having anything up still after so long. So there’s definitely some useful examples in here I imagine, for Amcrest, Reolink, Hikvision cameras. Examples of how to use separate streams for recording and detection, etc. Unfortunately at the time of writing all of this up tonight, I am extremely tired and must just get it out as is at this point.

Now, admittedly, full on support and assistance with configuring your Frigate NVR is vastly out of the scope of this guide. There is plenty of great documentation already available on the Official Frigate Website. Good luck!

mqtt:
  enabled: true
  host: 10.1.1.5 # the IP of the computer running MQTT, or localhost
  port: 1883
  topic_prefix: frigate
  client_id: frigate
  user: '{FRIGATE_MQTT_USERNAME}'
  password: '{FRIGATE_MQTT_PASSWORD}'
  stats_interval: 30

detectors:
  coral:
    type: edgetpu
    device: pci
  #cuda:
  #  type: tensorrt
  #  device: 0
  #openvino:
  #  type: openvino
  #  device: AUTO
  #cpu:
  #  type: cpu
  #  num_threads: 2

database:
  path: /config/frigate.db

logger:
  # Optional: Default log verbosity
  default: warning
  #default: warning
  # Optional: Component specific logger overrides
  #logs:
  #  frigate.nginx: error
  #  frigate.event: error

birdseye:
  enabled: true
  restream: true
  width: 1280
  height: 720
  quality: 7
  # motion (if motion was detected), objects (if it detected an object), or continuous (always on)
  mode: continuous

ffmpeg:
  global_args: -hide_banner -loglevel warning -threads 2
  #hwaccel_args: preset-vaapi
  hwaccel_args: preset-intel-qsv-h264
  #hwaccel_args: preset-nvidia-h264

  #input_args: preset-rtsp-generic
  input_args: preset-rtsp-restream
  output_args:
    record: preset-record-generic-audio-copy

# default detect settings for all cameras
detect:
  enabled: true
  width: 704
  height: 480

  fps: 10
  max_disappeared: 50
  stationary:
    interval: 10
    threshold: 50

# default object tracking for all cameras
objects:
  track:
  - person
  #filters:
  #  person:
  #    min_area: 100
  #    max_area: 75000

motion:
  threshold: 25
  contour_area: 25
  delta_alpha: 0.2
  frame_alpha: 0.2
  frame_height: 75
  improve_contrast: false
  mqtt_off_delay: 30

# default record settings for all cameras
record:
  enabled: true
  expire_interval: 60
  retain:
    days: 15
    mode: all
  events:
    pre_capture: 5
    post_capture: 5
    objects:
    - person
    retain:
      default: 15
      mode: all

snapshots:
  enabled: true
  clean_copy: true
  timestamp: false
  bounding_box: true
  crop: false
  retain:
    default: 15

# configure your cameras here
go2rtc:
  streams:
    # reolink poe doorbell
    doorbell:
    - ffmpeg:rtsp://{FRIGATE_RTSP_USERNAME}:{FRIGATE_RTSP_PASSWORD}@10.1.5.108:554/h264Preview_01_main#video=copy#audio=copy#audio=opus
    doorbell_sub:
    - ffmpeg:rtsp://{FRIGATE_RTSP_USERNAME}:{FRIGATE_RTSP_PASSWORD}@10.1.5.108:554/h264Preview_01_sub#video=copy
    # amcrest
    front:
    - rtsp://{FRIGATE_RTSP_USERNAME}:{FRIGATE_RTSP_PASSWORD}@10.1.5.114:554/cam/realmonitor?channel=1&subtype=0
    - ffmpeg:back#audio=opus
    front_sub:
    - rtsp://{FRIGATE_RTSP_USERNAME}:{FRIGATE_RTSP_PASSWORD}@10.1.5.114:554/cam/realmonitor?channel=1&subtype=1
    # amcrest
    back:
    - rtsp://{FRIGATE_RTSP_USERNAME}:{FRIGATE_RTSP_PASSWORD}@10.1.5.107:554/cam/realmonitor?channel=1&subtype=0
    - ffmpeg:back#audio=opus
    back_sub:
    - rtsp://{FRIGATE_RTSP_USERNAME}:{FRIGATE_RTSP_PASSWORD}@10.1.5.107:554/cam/realmonitor?channel=1&subtype=1
    # amcrest
    porch:
    - rtsp://{FRIGATE_RTSP_USERNAME}:{FRIGATE_RTSP_PASSWORD}@10.1.5.106:554/cam/realmonitor?channel=1&subtype=0
    - ffmpeg:porch#audio=opus
    porch_sub:
    - rtsp://{FRIGATE_RTSP_USERNAME}:{FRIGATE_RTSP_PASSWORD}@10.1.5.106:554/cam/realmonitor?channel=1&subtype=1
    # amcrest wifi camera
    livingroom:
    - rtsp://{FRIGATE_RTSP_USERNAME}:{FRIGATE_RTSP_PASSWORD}@10.1.5.112:554/cam/realmonitor?channel=1&subtype=0&authbasic=64
    - ffmpeg:livingroom#audio=opus
    livingroom_sub:
    - rtsp://{FRIGATE_RTSP_USERNAME}:{FRIGATE_RTSP_PASSWORD}@10.1.5.112:554/cam/realmonitor?channel=1&subtype=1&authbasic=64
    # hikvision
    basement:
    - rtsp://{FRIGATE_RTSP_USERNAME}:{FRIGATE_RTSP_PASSWORD}@10.1.5.104:554/Streaming/Channels/101
    - ffmpeg:basement#video=copy
    #basement_sub:
    #- rtsp://{FRIGATE_RTSP_USERNAME}:{FRIGATE_RTSP_PASSWORD}@10.1.5.104:554/Streaming/Channels/102
    #- ffmpeg:basement#video=copy

# we use localhost because go2rtc is restreaming them locally based on the names we gave them above
cameras:
  doorbell:
    enabled: true
    ffmpeg:
      inputs:
      - path: rtsp://localhost:8554/doorbell
        roles:
        - record
      - path: rtsp://localhost:8554/doorbell_sub
        roles:
        - detect
    detect:
      enabled: true
      width: 640
      height: 480
    objects:
      track:
      - person
    mqtt:
      enabled: true
      timestamp: true
      bounding_box: true
      crop: true
      height: 720
      quality: 92
    live:
      height: 720
      quality: 7
    ui:
      order: 1
    #motion:
    #  mask:
    #  - 640,0,640,309,605,335,482,368,252,366,0,311,0,0
  front:
    enabled: true
    ffmpeg:
      inputs:
      - path: rtsp://localhost:8554/front
        roles:
        - record
    detect:
      enabled: true
    record:
      events:
        #required_zones:
        #- FrontYard
        retain:
          default: 15
    objects:
      track:
      - person
      - cat
    mqtt:
      enabled: true
      timestamp: true
      bounding_box: true
      crop: true
      height: 720
      quality: 92
    live:
      height: 720
      quality: 7
    ui:
      order: 2
    #motion:
    #  mask:
    #  - 704,0,704,202,0,150,0,0
    #zones:
    #  FrontYard:
    #    coordinates: 650,196,82,136,0,228,0,480,704,480
  back:
    enabled: true
    ffmpeg:
      inputs:
      - path: rtsp://localhost:8554/back
        roles:
        - record
      - path: rtsp://localhost:8554/back_sub
        roles:
        - detect
    record:
      events:
        #required_zones:
        #- BackYard
        retain:
          default: 15
    objects:
      track:
      - person
      - cat
    mqtt:
      enabled: true
      timestamp: true
      bounding_box: true
      crop: true
      height: 720
      quality: 92
    live:
      height: 720
      quality: 7
    ui:
      order: 3
    #motion:
    #  mask:
    #  - 291,0,288,41,0,39,0,0
    #zones:
    #  BackYard:
    #    coordinates: 374,0,600,480,0,480,0,0
  porch:
    enabled: true
    ffmpeg:
      inputs:
      - path: rtsp://localhost:8554/porch
        roles:
        - record
      - path: rtsp://localhost:8554/porch_sub
        roles:
        - detect
    record:
      events:
        retain:
          default: 15
    objects:
      track:
      - person
      - cat
    mqtt:
      enabled: true
      timestamp: true
      bounding_box: true
      crop: true
      height: 720
      quality: 92
    live:
      height: 720
      quality: 7
    ui:
      order: 4
    #motion:
    #  mask:
    #  - 261,0,270,104,323,223,367,333,480,348,534,76,640,51,640,480,0,480,0,0
  livingroom:
    enabled: true
    ffmpeg:
      inputs:
      - path: rtsp://localhost:8554/livingroom
        roles:
        - record
      - path: rtsp://localhost:8554/livingroom_sub
        roles:
        - detect
    detect:
      enabled: true
    record:
      events:
        objects:
        - cat
        retain:
          default: 15
    objects:
      track:
      - cat
    mqtt:
      enabled: true
      timestamp: true
      bounding_box: true
      crop: true
      height: 720
      quality: 92
    live:
      height: 720
      quality: 7
    ui:
      order: 5

  basement:
    enabled: true
    ffmpeg:
      inputs:
      - path: rtsp://localhost:8554/basement
        roles:
        - record
        - detect
    record:
      events:
        #required_zones:
        #- BasementStairs
        objects:
        - cat
        retain:
          default: 15
    detect:
      enabled: true
      width: 1280
      height: 720
      fps: 10
    objects:
      track:
      - cat
    mqtt:
      enabled: true
      timestamp: true
      bounding_box: true
      crop: true
      height: 720
      quality: 92
    live:
      height: 720
      quality: 7
    ui:
      order: 6

timestamp_style:
  position: tl
  format: '%m/%d/%Y %H:%M:%S'
  color:
    red: 255
    green: 255
    blue: 255
  thickness: 1
  effect: solid

ui:
  live_mode: webrtc
  timezone: EST5EDT
  use_experimental: false
  time_format: 12hour
  date_style: short
  time_style: medium
  strftime_fmt: '%Y/%m/%d %H:%M'

telemetry:
  version_check: true

Installing Google Coral on Ubuntu 23.10 / 24.04

MAY THE 4TH BE WITH YOU!… and also this guide.

I have not tested it in Ubuntu 24.04 but it may work. Let me know in the comments if you try! Update: Myself and others in the comments are running this successfully on 24.04!

This brief guide has been revised from:
https://coral.ai/docs/m2/get-started#2-install-the-pcie-driver-and-edge-tpu-runtime

This will essentially be the first part of a few parts coming for Frigate and Home Assistant. (must. find. motivation!)

First, we need to setup the apt repository, and install the required packages:

echo "deb https://packages.cloud.google.com/apt coral-edgetpu-stable main" | sudo tee /etc/apt/sources.list.d/coral-edgetpu.list

curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/google-coral-edgetpu.gpg

sudo apt update
sudo apt install gasket-dkms libedgetpu1-std

If gasket-dkms fails (it probably will — if it doesn’t, skip down to the udev rule section):

sudo apt purge gasket-dkms
git clone https://github.com/KyleGospo/gasket-dkms
apt install dkms debhelper libfuse2 dh-dkms devscripts
cd gasket-dkms; debuild -us -uc -tc -b

You’ll have a .deb file one folder up (e.g. gasket-dkms_1.0-18_all.deb):

cd ..
ls *.deb
dpkg -i gasket-dkms*.deb

We need to add a udev rule for permission to the hardware device:

sudo sh -c "echo 'SUBSYSTEM==\"apex\", MODE=\"0660\", GROUP=\"docker\"' >> /etc/udev/rules.d/65-apex.rules"

If you don’t want to use the docker group, replace docker in the udev command string:

sudo groupadd apex
sudo usermod -a -G apex your_linux_username
sudo sh -c "echo 'SUBSYSTEM==\"apex\", MODE=\"0660\", GROUP=\"apex\"' >> /etc/udev/rules.d/65-apex.rules"

REBOOT!

Verify the device is detected and available:

ls -alh /dev/apex*
crw-rw---- 1 root docker 120, 0 May 4 20:34 /dev/apex_0

Server Service Shuffle

Over the next week or two as I find time and motivation (Helldivers 2 has been winning both of them lately), I’ll be moving some services to a new server, namely Docker/Portainer, Frigate and Home Assistant. I’ll be doing my best to keep notes from beginning to end and get something posted, finally, to help anyone else trying to get the two of them working.

I do use a coral, and have also used an nVidia card for graphics offloading. With 5-6 cameras I can’t say I noticed a huge impact offloading the graphics, but I will try to cover that part as well since I plan to move the card over anyway. For reference, it’s just a lowly GTX 1050ti that I’m using for the task. I figure if I ever bother to buy a Plex license, I can use it for that as well.

I’ll be using Ubuntu Server 23.10.

Portainer as Docker Compose file

Updating portainer becomes:
docker compose down
docker pull portainer/portainer-ce:latest
docker compose up -d

version: '3.0'
services:
  portainer:
    container_name: portainer
    hostname: portainer
    command: --sslcert /certs/lan.fullchain --sslkey /certs/lan.key
    image: portainer/portainer-ce:latest
    restart: unless-stopped
    network_mode: bridge
    environment:
      - "TZ=EST5EDT"
    ports:
      - 9443:9443
    volumes:
      - data:/data
      - /certs:/certs:ro
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock

volumes:
  data:

Paste the above into a docker-compose.yml file, I placed mine in a ‘portainer’ folder inside my home directory. Then just run docker compose up -d

Once it’s up and running, you have 10 or 15 minutes to browse to the login page (http://ip.address:9443 or equivalent), or you’ll have to restart it. The first visit to Portainer will have you create your admin credentials.

I use a folder on my system, /certs, which I map to /certs inside the container. You will have to modify your certificate locations in the volumes section, and the command line towards the top of the compose file. If you are not using SSL, then simply comment out or remove the command line at the top of the compose file and remove the volume mapping.

Plex Media Server – Convert CRT to Plex SSL Compatible Certificate

If you’re like me and you use Let’s Encrypt, then it seems sometime semi-recently Plex changed the way their SSL certificates work. I used to just generate a simple .p12 certificate to use with Plex, but it seems that wasn’t good enough anymore.

After some research, it appears the encryption algorithms needed to be updated on the certificate I was generating.

Simply adding the following to my openssl command solved the problem:
-certpbe AES-256-CBC -keypbe AES-256-CBC -macalg SHA256

So the full command becomes something like this:
openssl pkcs12 -certpbe AES-256-CBC -keypbe AES-256-CBC -macalg SHA256 -export -out plex.p12 -inkey your.com.key -in your.com.crt -certfile your.com.ca

I just hit the enter key when it asks for a password since I am only using this certificate locally. You could add -passout ‘pass:’ to do that automatically. Which works wonderfully as I just scp my certs out of pfSense from /cf/conf/acme. I’ve still been experimenting with that and in some cases, e.g. unifi, I’ve found it better to use the fullchain file and not the all file. In other cases I use the all.pem file.

In Plex > Network settings, set the path to this certificate and leave the key field blank.