Upgraded. pkg upgrade zoneminder
made for a long night but in the end, I got it fixed.
If you've read the last post about ZoneMinder on FreeBSD, you've seen all the details on how to set up the entire suite. Here I'll go over what needs to be updated to support the newly polished ZoneMinder 1.32.3 on FreeBSD 11.
Start by kicking off an upgrade of the ZM package with pkg upgrade zoneminder
. This will upgrade your PHP from 5.6 to 7.2. If you have any #
in your php.ini
file, php will fail to start. Make sure you only comment out lines using ;
.
Next, stop the zoneminder serivce with service zoneminder stop
. Once it's stopped you'll need to run the zmupdate.pl
command to upgrade the database. This was the first snag. The upgrade was successful all the way up to the end where it errored out.
- First, I had to modify the database user's permissions:
GRANT SUPER ON *.* TO <zmuser>@"<zmIPaddress>";
- Second, I reran the
zmupdate.pl
command, this time successfully completing the upgrade. - Third, I removed the permissions:
REVOKE SUPER ON *.* FROM <zmuser>@"<zmIPaddress>";
- Finally, I restarted the zm service:
service zoneminder restart
ZoneMinder's code
If you have a reverse proxy in front of yours like I do, you'll have to make some changes to the way ZM identifies the proxy protocol and port. If you don't have a reverse proxy, you can skip this part as the ZoneMinder code will correctly identify your port and protocol.
Note: These changes were found in the ZoneMinder forums and on their GitHub page. This is a resurfaced bug from a few years ago.
All modifications are made in the includes/Server.php
file:
- About 65 lines down, replace this
with thisreturn (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? 'https' : 'http';
return ( ( isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ) or ( isset($_SERVER['HTTP_X_FORWARDED_PROTO']) and ( $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' ) ) ) ? 'https' : 'http';
- At the ~81 line mark of the same
includes/Settings.php
file, add the following abovereturn $_SERVER['SERVER_PORT'];
:if ( isset($_SERVER['HTTP_X_FORWARDED_PORT']) ) { return $_SERVER['HTTP_X_FORWARDED_PORT']; }
I noticed errors in the ZM logs complaining that it could not find /usr/local/bin/pear
. That was resolved with a simple pkg install php72-pear
.
Nginx updates
Above, you may have noticed we introduced two new headers into ZM's code:
- HTTP_X_FORWARDED_PROTO
- HTTP_X_FORWARDED_PORT
Here's my new proxy config defining these headers:
server {
server_name zm.example.net;
include enforce_https; # Redirects to HTTPS
}
server {
include ssl; # External SSL config
server_name zm.example.net;
access_log /var/log/nginx/access.zm.log main
error_log /var/log/nginx/error.http.zm.log;
location / {
proxy_pass http://<zoneminder_backend_ip>;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port 443;
}
}
For the downstream Nginx configuration (the one in the ZM jail), I had to add two distinct rewrites. One for the cache
and one for the api
.
After some searching and reading of the ZoneMinder forums, a few posters were gracious enough to suggest using nginx's rewrites
to mimic Apache's config. I wanted to link to the comments directly and give credit where it's due, but I honestly can't find that post again. I'll dig through my history later, and if I come across it, I'll update this post.
Below is my new config with these rewrite statements:
user www;
worker_processes 1;
error_log /var/log/nginx/error.log;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
gzip on;
server_tokens off;
server {
listen 80;
server_name __;
root /usr/local/www/zoneminder;
try_files $uri $uri/ /index.php$is_args$args;
index index.php;
location /cache {
alias "/var/cache/zoneminder";
}
location /zm {
rewrite ^/zm/(.+)$ /$1 last;
}
location / {
location = /cgi-bin/nph-zms {
gzip off;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/var/run/fcgiwrap/fcgiwrap.sock;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/var/run/php-fpm.socket;
}
location /api {
rewrite ^/api/(.+)$ /api/app/webroot/index.php?p=$1 last;
}
}
}
}
And that's it! a quick service restart _____
for each service and I was back up and running!
Other changes
I made a few other changes that might have added to the performance of ZoneMinder, but are not crucial to its operation:
- Updated
/etc/rc.conf.local
Changefcgiwrap_flags="-c 4"
tofcgiwrap_flags="-c 10"
- Updated
/usr/local/etc/php.ini
Changememory_limit = 128M
tomemory_limit = 512M
Oh, yeah, SET YOUR TIMEZONE! I'm embarrassed to say how long I spent working on an issue where the images wouldn't load in the browser. All it took was a simple tzsetup
and images loaded!