As the proud owner of a Swann NVR-7090 4 security camera system, I’ve always had a passionate distaste for the SwannView Plus app. Not only is the app itself terribly made with a non-standard and unintuitive tooltip-free UI, but it’s also not even mentioned on the official Swann website outside of some random support threads. There is a Windows version that hasn’t been updated in years, and an OSX version that is 32-bit only and doesn’t work on modern versions of OSX. This set of cameras does not work in any of the other SwannView apps (Why are there so many of them? They all do the same job!). Argh! The one light at the end of the tunnel is that this system supports being streamed over the RTSP protocol allowing us access with more modern apps such as VLC. There’s a few things you’ll need to go do get everything working and I’ve done my best to describe every step in detail below.
Create Certificate for Localhost Domains on macOS
Step 1: Create a self-signed root certificate
First, let’s create a self-signed root certificate:
1 2 | openssl req -x509 -nodes -new -sha256 -days 390 -newkey rsa:2048 -keyout "RootCA.key" -out "RootCA.pem" -subj "/C=de/CN=localhost.local" openssl x509 -outform pem -in "RootCA.pem" -out "RootCA.crt" |
The parameter
-days 390
sets the number of days, this certificate is valid. Starting on September 1st (2020), SSL/TLS certificates cannot be issued for longer than 13 months (397 days).
If this time is too long, you will receive an NET::ERR_CERT_VALIDITY_TOO_LONG
error. In the command above, this value was set to 390 days, which works for me.
Step 2: Define domains and subdomains that should be included in the certificate
For this, just create a text file named vhosts_domains.ext
and insert the following contents:
1 2 3 4 5 6 7 8 | authorityKeyIdentifier=keyid,issuer basicConstraints=CA:FALSE keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment subjectAltName = @alt_names [alt_names] DNS.1 = localhost DNS.2 = *.mixable.blog.local DNS.3 = mixable.blog.local |
This example includes subdomains for a local development environment for the domain mixable.blog.local and all subdomains like www.mixable.blog.local or apps.mixable.blog.local.
If you plan to use a more general certificate e.g. to include all subdomains under ..blog.local, this will not work. The definition only supports ‘first level’ subdomains. It would be great, because this saves a lot of additional setup, but unfortunately this is note supported.
Step 3: Create the certificate
Now let’s create the certificate:
1 2 | openssl req -new -nodes -newkey rsa:2048 -keyout localhost.key -out localhost.csr -subj "/C=de/ST=State/L=City/O=Organization/CN=localhost.local" openssl x509 -req -sha256 -days 1024 -in localhost.csr -CA RootCA.pem -CAkey RootCA.key -CAcreateserial -extfile vhosts_domains.ext -out localhost.crt |
Calling the two commands above will create the localhost certificate that includes all the provided domains and subdomains. Your file listing should look like this:

Step 4: Make the certificate available for Apache
Depending on your system, copy all those files into the the configuration folder of the Apache installation. In my case, the installation was done with the help of brew, so the local path is:
1 | <code>/usr/local/etc/httpd/cert/</code> |
At the end, it’s not important where those files are located, because we no add this path to the vhost definitions. For this, open your vhosts file and link the crt and the key file as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | # mixable.blog.local <VirtualHost *:80> ServerAdmin webmaster@example.com DocumentRoot "/Users/mathias/Sites/mixable.blog.local" ServerName mixable.blog.local ServerAlias mixable.blog.local ErrorLog "/usr/local/var/log/httpd/localhost-error.log" CustomLog "/usr/local/var/log/httpd/localhost-access.log" common </VirtualHost> <VirtualHost *:443> DocumentRoot "/Users/mathias/Sites/mixable.blog.local" ServerName mixable.blog.local SSLEngine on SSLCertificateFile "/usr/local/etc/httpd/cert/localhost.crt" SSLCertificateKeyFile "/usr/local/etc/httpd/cert/localhost.key" </VirtualHost> |
If you have additional vhost definitions, you can add the part to every server name entry and use the correct paths to SSLCertificateFile and SSLCertificateKeyFile.
After changing the vhost settings, it is required to restart your Apache server!
Step 5: Add the certificates to macOS
When opening a local website, the certificate should be used but you might see a NET::ERR_CERT_INVALID
error. This is the case, because modern browsers/systems do not trust self-signed certificates by default. to overcome this issue, we have to add the created certificates to the macOS Keychain Access. For this, open the *.crt
files in Keychain Access:

So that they are know by macOS:

And finally, update the trust settings of each certificate to “Always trust”:

You should now be able to use a secure connection between your browser and your local server:

Step 6: Additional fixes
The steps above might already work for Chrome and Safari. If you have problems with Firefox, just open settings and go to Privacy & Security. Then you have to import the root certificate file RootCA.crt
, so that Firefox knows about your certificate.
This post was copied pretty much verbatim from Mathias Lipowski’s Create certificate for localhost domains on macOS.
Automatically Back up Elden Ring Saves on Windows
With Elden Ring saving every step you take and stories of hackers destroying save files with various exploits it’s important to keep a healthy backup schedule. For that reason I’ve whipped up an improved version of my Subnautica backup script for Elden Ring.
This script will check if Elden Ring is running, and if so, will zip the save folder to whatever folder the script is located.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | @echo off :loop rem Determine if Elden Ring is running tasklist /fi "ImageName eq eldenring.exe" /fo csv 2>NUL | find /I "eldenring.exe">NUL rem Save the current datetime to a var https://stackoverflow.com/a/203116 For /f "tokens=2-4 delims=/ " %%a in ('date /t') do (set mydate=%%c_%%a_%%b) For /f "tokens=1-2 delims=/:" %%a in ("%TIME%") do (set mytime=%%a_%%b) set mydatetime="%mydate%__%mytime%" rem If Elden Ring is running... if "%ERRORLEVEL%"=="1" ( rem Set up a folder name for our new backup SET stamp=backup-%mydatetime%.zip rem Back up with Windows 10 'tar.exe' https://superuser.com/a/1473257 tar.exe -a -cf "%stamp%" "%USERPROFILE%\AppData\Roaming\EldenRing" 2> NUL echo [%TIME%] Backed up to %stamp% ) else ( echo [%TIME%] Not running... ) rem sleep for 30 minutes https://serverfault.com/a/432323 timeout /t 1800 /nobreak goto loop |
The latest version of this code is available over on my GitHub page. It requires no external tools to run, just Windows 10 or newer.
To run the script simply save the above code into a file with a filename like backup.bat and double click it. Run it whenever you’re playing and close it when you’re done.
Automatically Back up Subnautica 2 Saves on Windows
After an unfortunate incident involving a crash and a lost save file, I decided to write a batch script to automatically back up my Subnautica 2 saves every x number of minutes. You’ll need 7-Zip and PowerShell installed.
This script will check if Subnautica 2 is running, and if so, will zip the Subnautica save folder to whatever folder the script is located.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | @echo off :loop rem Get HH:MM:SS for log prefix FOR /F "tokens=* USEBACKQ" %%F IN (`powershell get-date -format ^"{HH:mm:ss}^"`) DO ( SET logtime=%%F ) rem Determine if subnautica is running tasklist /fi "ImageName eq SubnauticaZero.exe" /fo csv 2>NUL | find /I "SubnauticaZero.exe">NUL rem If subnautica is running... if "%ERRORLEVEL%"=="0" ( rem Get current datetime https://stackoverflow.com/a/2854857 FOR /F "tokens=* USEBACKQ" %%F IN (`powershell get-date -format ^"{yyyy_MM_dd_HH_mm_ss}^"`) DO ( SET mydatetime=%%F ) rem Set up a folder name for our new backup SET stamp=slot0000-%mydatetime%.zip rem Back up with 7zip "C:\Program Files\7-Zip\7z.exe" a -tzip "%stamp%" "%USERPROFILE%\AppData\LocalLow\Unknown Worlds\Subnautica Below Zero\SubnauticaZero\SavedGames\slot0000" > NUL echo [%logtime%] Backed up to %stamp% ) else ( echo [%logtime%] Not running... ) rem sleep for 30 minutes https://stackoverflow.com/a/16803409 powershell -command "Start-Sleep -s 1800" goto loop |
To run the script simply save the above code into a file with a filename like backup.bat and double click it. Run it whenever you’re playing and close it when you’re done.
How to Replace React with Preact in WordPress Frontity
While playing around with Frontity (a react framework for WordPress) I noticed the compiled bundle size for the default Mars theme was pretty huge clocking in at an unacceptable 390KB of JavaScript. That’s a lot to download before my site will appear. Below I detail how I knocked over 100KB off that size with no discernible difference in functionality simply by swapping out React with its lightweight drop in replacement Preact.
Extending WebPack
To replace React we need to modify Frontity’s webpack configuration. At the time of writing it’s not documented how to do that however a forum post by SantosGuillamot contains a link to a CodeSandbox showing how to do it.
In your root folder’s package.json add the following dependencies:
1 2 3 4 5 6 | "dependencies": { ... "change-config": "./packages/change-config", "preact": "^10.5.14", "preact-render-to-string": "^5.1.19" } |
Create the following files:
- /packages/change-config/package.json
- /packages/change-config/frontity.config.js
Here’s the contents of package.json:
1 2 3 4 5 6 7 8 9 10 11 | { "name": "change-config", "version": "1.0.0", "description": "Frontity package created using the Frontity CLI.", "keywords": [ "frontity", "frontity-theme" ], "license": "Apache-2.0", "dependencies": {} } |
And here is frontity.config.js:
1 2 3 4 5 6 | export const webpack = ({ config, mode }) => { config.resolve.alias["react"] = "preact/compat"; config.resolve.alias["react-dom/test-utils"] = "preact/test-utils"; config.resolve.alias["react-dom"] = "preact/compat"; config.resolve.alias["react/jsx-runtime"] = "preact/jsx-runtime"; }; |
Now back in your root folder open frontity.settings.js and set the following at the end of the packages section:
1 2 3 4 5 6 7 8 | const settings = { ... "packages": [ ..., "@frontity/tiny-router", "@frontity/html2react", "change-config" ] |
That should be it. Run
1 2 | npx frontity build npx frontity serve |
Here are the before and after filesizes:
Before:
After:
A saving of 110KB! Not too shabby.
Importing a Model from VRoid Studio into Unreal Engine
For something that should be simple, importing a model from VRoid Studio into Unreal Engine 4 as of the time of writing is extremely convoluted and time consuming – even with the great tools that have been created to speed up the process.
Below I’ll attempt to walk through every step I took to get things looking and working correctly as well as documenting my struggles along the way. Our basic workflow will be VRoid -> Blender -> Unreal.
I should note that as of the time of writing, the latest version of each of the pieces of software I’ll be using are as follows:
Add WordPress Gutenberg Components Anywhere in DOM with createPortal

Gutenberg may be the shiny new toy available for WordPress admin but it still feels very limiting at times – especially when trying to do things the developers don’t anticipate. I wanted to add an extra button at the top of the post edit page next to the Publish button before finding out there is no SlotFill for this but once again, React has us covered with a handy little helper createPortal. createPortal allows you to place a component anywhere in the DOM of your choosing – perfect for what I wanted to do here.
The Component
Without further adieu, component code below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | /** * WordPress dependencies */ import { Button } from '@wordpress/components'; import { compose } from '@wordpress/compose'; import { createPortal, useEffect, useState } from '@wordpress/element'; import { withSelect } from '@wordpress/data'; const TopBtn = ( { postPreviewButton } ) => { // Empty div element our button will be placed into // This div will be inserted before the Publish button with useEffect() const [ container ] = useState( document.createElement( 'div' ) ); // The button submit handler const onSubmit = () => { console.log( 'Button pressed!' ); }; // Do the actual placing/removing of the button in the DOM useEffect( () => { // Ensure we have a Preview button to place next to if ( ! postPreviewButton ) { return; } // Insert our button immediately after the post preview button. postPreviewButton.parentNode.insertBefore( container, postPreviewButton.nextSibling ); // Remove our button on component unload return () => { postPreviewButton.parentNode.removeChild( container ); }; }, [ postPreviewButton ] ); // Use createPortal to place our component into the <div/> container return createPortal( <> <Button isSecondary showTooltip={ true } label="My Custom Button" onClick={ onSubmit } > My Btn </Button> <span> </span> </>, container ); }; export default compose( [ withSelect( () => { return { // Provide the Post preview button element so we'll know where to // place our component postPreviewButton: document.querySelector( '.editor-post-preview' ), }; } ), ] )( TopBtn ); |
This setup is quite flexible allowing you to add components pretty much anywhere on the page you like. I’ve commented the component as best I could. If you have any questions feel free to ask in the comments section below.
Renewing SSL Certificates Behind CloudFlare
For the longest time now I’ve been having issues with certbot not being able to create a certificate for my domain, returning the error
Attempting to renew cert (mydomain.com) from /home/ubuntu/.certbot/config/renewal/mydomain.com.conf produced an unexpected error: Failed authorization procedure. mydomain.com (http-01): urn:ietf:params:acme:error:unauthorized :: The client lacks sufficient authorization :: Invalid response from https://mydomain.com/.well-known/acme-challenge/-jYlHtpK6x6LZ8B4KjHeY7RgchNFPoouXADS_XQtowc [2606:4700:3035::681c:1e6e]: “<!DOCTYPE html>\n<!–[if lt IE 7]> <html class=\”no-js ie6 oldie\” lang=\”en-US\”> <html class=\”no-js “. Skipping.
I think the reason for this is because I’m using Full (Strict) encryption mode in CloudFlare dashboard which requires a valid SSL certificate be present when communicating between my web server and CloudFlare.

The solution for this is instead of using certbot’s default authentication method, we instead make use of the certbot-dns-cloudflare plugin that will handle the Lets Encrypt challenge through DNS. This works by automatically creating and deleting our CloudFlare DNS TXT record for us during the certbot renew. Let’s set this up now.
Fixing MariaDB ‘Too many open files’ Error on OSX
While trying to import a database dump on the homebrew version of MariaDB on OSX, I was getting the error
SQL ERROR [mysql4] Out of resources when opening file `./mydatabase/table.MYD´ (Errcode: 24 – Too many open files)
This is caused by the open_files_limit setting being too low. To check your open_files_limit in MariaDB run
1 | SHOW GLOBAL VARIABLES LIKE 'open_files_limit'; |
For me this value was 256 – it should be much higher. Increasing the value isn’t as simple as it would seem, however, as the limit is actually coming from OSX’s maxfiles value. You can see this value by running
1 | launchctl limit |
1 2 3 4 5 6 7 8 9 | cpu unlimited unlimited
filesize unlimited unlimited
data unlimited unlimited
stack 8388608 67104768
core 0 unlimited
rss unlimited unlimited
memlock unlimited unlimited
maxproc 2784 4176
maxfiles 256 unlimited |
Thankfully increasing maxfiles is relatively simple:
Adjusting Open File Limits in Yosemite
To adjust open files limits on a system-wide basis in Mac OS X Yosemite, you must create two configuration files. The first is a property list (aka plist) file in /Library/LaunchDaemons/limit.maxfiles.plist that contains the following XML configuration:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>limit.maxfiles</string> <key>ProgramArguments</key> <array> <string>launchctl</string> <string>limit</string> <string>maxfiles</string> <string>200000</string> <string>200000</string> </array> <key>RunAtLoad</key> <true/> <key>ServiceIPC</key> <false/> </dict> |
This will set the open files limit to 200000. The second plist configuration file should be stored in /Library/LaunchDaemons/limit.maxproc.plist with the following contents:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple/DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>limit.maxproc</string> <key>ProgramArguments</key> <array> <string>launchctl</string> <string>limit</string> <string>maxproc</string> <string>2048</string> <string>2048</string> </array> <key>RunAtLoad</key> <true /> <key>ServiceIPC</key> <false /> </dict> </plist> |
Both plist files must be owned by root:wheel and have permissions -rw-r–r–. This permissions should be in place by default, but you can ensure that they are in place by running sudo chmod 644 . While the steps explained above will cause system-wide open file limits to be correctly set upon restart, you can apply them manually by running launchctl limit.
In addition to setting these limits at the system level, we recommend setting the at the session level as well by appending the following lines to your bashrc, bashprofile, or analogous file:
1 2 | ulimit -n 200000 ulimit -u 2048 |
At this point, you can restart your computer and enter ulimit -n into your terminal. If your system is configured correctly, you should see that maxfiles has been set to 200000.
How to Serve Static Assets in WordPress Admin From W3TC CDN
With the rise of Gutenberg and it’s million tiny JavaScript files loaded every time you go to write a post, it’s become more important than ever to utilise a CDN for static assets loaded through the WordPress admin.
W3 Total Cache is a great plugin for speeding up your site and it’s CDN feature is top notch. One seemingly missing feature however is serving static assets from the configured CDN when browsing around your sites admin. By default no CDN rewriting at all is done on your sites backend and if you have a lot of logged in users writing posts, this can cause a bunch of unnecessary load on your server as they each download all the files.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | // Automatically rewrite assets to CDN URLs in the backend if (class_exists('W3TC\Dispatcher')) { add_action('admin_init', function () { $config = new W3TC\Config(); if ($config->get('cdn.enabled')) { // CDN domain with trailing slash $cdn_domain = W3TC\Dispatcher::component('Cdn_Core')->get_cdn()->format_url(''); /** * Filters the HTML link tag of an enqueued style. * * @since 2.6.0 * @since 4.3.0 Introduced the `$href` parameter. * @since 4.5.0 Introduced the `$media` parameter. * * @param string $html The link tag for the enqueued style. * @param string $handle The style's registered handle. * @param string $href The stylesheet's source URL. * @param string $media The stylesheet's media attribute. */ add_filter('style_loader_tag', function ($tag, $handle, $href, $media) use ($cdn_domain) { return str_replace(site_url('/'), $cdn_domain, $tag); }, 10, 4); /** * Filters the HTML script tag of an enqueued script. * * @since 4.1.0 * * @param string $tag The script tag for the enqueued script. * @param string $handle The script's registered handle. * @param string $src The script's source URL. */ add_filter('script_loader_tag', function ($tag, $handle, $src) use ($cdn_domain) { return str_replace(site_url('/'), $cdn_domain, $tag); }, 10, 3); } }); } |
I’d only recommend using this code with an Origin Pull CDN, as it doesn’t handle pushing any of these assets to the CDN – only serving from what’s already in there (which if using an Origin Pull CDN will be everything).