Posted Monday, 12 October 2020 by Jeremy Cook

Attributes Toggle Tag Helper

Example CSHTML:

@var somethingBoolean = true;
<div sk-bool-data-template="@somethingBoolean" sk-bool-other="false">...</div>

Resulting HTML:

<div data-template>...</div>

The Code:

using Microsoft.AspNetCore.Razor.TagHelpers;
using System;
using System.Collections.Generic;

namespace SiteKit.AspNetCore.TagHelpers
    [HtmlTargetElement(Attributes = BoolPrefix + "*")]
    public class SkBoolAttributeTagHelper : TagHelper
        private const string BoolPrefix = "sk-bool-";

        private IDictionary<string, bool>? _boolValues;

        [HtmlAttributeName(DictionaryAttributePrefix = BoolPrefix)]
        public IDictionary<string, bool> BoolValues
                if (_boolValues == null)
                    _boolValues = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);

                return _boolValues;
                _boolValues = value;
        public override void Process(TagHelperContext context, TagHelperOutput output)
            if (_boolValues != null)
                foreach (var item in _boolValues)
                    if (item.Value)
                        output.Attributes.Add(item.Key, null);
Read More

Posted Friday, 20 March 2020 by Jeremy Cook

Using NGINX with nginx-rtmp-module to broadcast from OBS Studio

This article is the combination of a post to the OBS Project's forum by a dodgepong:

And a fantastic Howtoforge article by Blago Eres:

1. Build and Configure NGINX

Find the latest releases here and here:

cd ~

# You'll need these
sudo apt-get install build-essential libpcre3 libpcre3-dev libssl-dev

# From your home directory, download the latest nginx source code:
tar -zxvf nginx-1.15.7.tar.gz

tar -zxvf v1.2.1.tar.gz

cd nginx-1.15.7 

# Configure using common paths and of course the nginx-rtmp-module ♠
./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --pid-path=/var/run/ --lock-path=/var/run/nginx.lock --user=nginx --group=nginx --with-debug --with-http_ssl_module --add-module=../nginx-rtmp-module-1.2.1

♠ This is a minimal configuration. If you need more features consult the Howtoforge article or NGINX docs.

Some important output that let's you know where folders and files will exist.

Configuration summary
  + using system PCRE library
  + using system OpenSSL library
  + using system zlib library

  nginx path prefix: "/etc/nginx"
  nginx binary file: "/usr/sbin/nginx"
  nginx modules path: "/usr/lib/nginx/modules"
  nginx configuration prefix: "/etc/nginx"
  nginx configuration file: "/etc/nginx/nginx.conf"
  nginx pid file: "/var/run/"
  nginx error log file: "/var/log/nginx/error.log"
  nginx http access log file: "/etc/nginx/logs/access.log"
  nginx http client request body temporary files: "client_body_temp"
  nginx http proxy temporary files: "proxy_temp"
  nginx http fastcgi temporary files: "fastcgi_temp"
  nginx http uwsgi temporary files: "uwsgi_temp"
  nginx http scgi temporary files: "scgi_temp"
sudo make install
cd ~
# Symbolic link
sudo ln -s /usr/lib/nginx/modules /etc/nginx/modules
# Check the nginx can be ran from anywhere and its version
sudo nginx -V
# Add the nginx user and group
sudo adduser --system --home /nonexistent --shell /bin/false --no-create-home --disabled-login --disabled-password --gecos "nginx user" --group nginx
# Check nginx config
sudo nginx -t

# Create NGINX cache directories and set proper permissions
sudo mkdir -p /var/cache/nginx/client_temp /var/cache/nginx/fastcgi_temp /var/cache/nginx/proxy_temp /var/cache/nginx/scgi_temp /var/cache/nginx/uwsgi_temp
sudo chmod 700 /var/cache/nginx/*
sudo chown nginx:root /var/cache/nginx/*

# Re-check syntax and potential errors
sudo nginx -t

# Create a systemd service file with nano
sudo nano /etc/systemd/system/nginx.service

Paste this into the file editor:

Description=nginx - high performance web server

ExecStartPre=/usr/sbin/nginx -t -c /etc/nginx/nginx.conf
ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID


Exit nano, saving the file:

<ctl+x> <y> <enter>
# Enable NGINX to start on boot and start NGINX immediately
sudo systemctl enable nginx.service
sudo systemctl start nginx.service
# Is it enabled?
sudo systemctl is-enabled nginx.service
# Is it running?
sudo systemctl status nginx.service
# or
wget -qO- http://localhost
# Clean up backup .default files 
sudo rm /etc/nginx/*.default
# Create conf.d, snippets, sites-available and sites-enabled directories in /etc/nginx directory:
sudo mkdir /etc/nginx/{conf.d,snippets,sites-available,sites-enabled}
# Change permissions and group ownership of NGINX log files:
sudo chmod 640 /var/log/nginx/*
sudo nano /var/log/nginx/access.log
sudo chown nginx:adm /var/log/nginx/access.log /var/log/nginx/error.log

Populate the access.log file with the below text, then save and exit:

/var/log/nginx/*.log {
    rotate 52
    create 640 nginx adm
            if [ -f /var/run/ ]; then
                    kill -USR1 `cat /var/run/`
# You may want to switch to your home directory and clean up after yourself
cd ~
rm -rf <those-tar.gz> <files-you-downloaded>

2. Configure the nginx-rtmp-module

Now we're ready to use the nginx-rtmp-module.

sudo nano /etc/nginx/nginx.conf

Paste something like this at the very end.

rtmp {
        server {
                listen 1935;
                chunk_size 4096;

                application live {
                        live on;
                        record off;
# Test and reload the updated nginx config
sudo nginx -t
sudo systemctl reload nginx.service

Aside: Now might be a good time to add firewall rules using ufw. The Howtoforge article covers it. Just remember that you'll need to allow SSH if that's how you are accessing your device, 1935/tcp for RTMP traffic, and 80/tcp if you want to verify that nginx is responding to HTTP requests.

3. Stream from OBS Studio to the nginx and back to VLC media player

There and back again, an RTMP tail.

# Display your device's IP address
ifconfig | grep -F "inet "
# Outputs something like
        inet  netmask  broadcast
        inet  netmask

Open OBS Studio and configure your Stream Settings:

  1. Click the Settings button
  2. Click Stream
  3. Choose "Custom Streaming Server" for Stream Type
  4. Set URL to "rtmp://" where you change to your device's IP or domain, and live is what you named the application in the nginx configuration above
  5. Set Stream key to test
  6. Click OK to exit the Settings dialog
  7. Click the Start Streaming button

Now you are streaming to the device and it will restream to anything that connects to "rtmp://".

Open VLC media player to watch the video replayed from your device:

  1. Click the Media menu and Open Network Stream...
  2. Enter your "rtmp://" but with your device's IP address
  3. Click Play

And now you are done.

For extra credit you could push to YouTube, Twitch or something. That config looks something like this:

rtmp {
    server {
        listen 1935;
        chunk_size 4096;

        application live {
            live on;
            record off;
            push rtmp://[KEY];

My experience with a RaspberryPi 2 is very limited, but I found it wasn't fast enough to modify the video before pushing. So having OBS Studio push to your Pi exactly what you want to push on to YouTube works best. I also found YouTube's website terribly confusing for getting streaming running. I vaguely remember some obscure checkbox that must be checked for all things to work. JC.

Read More

Posted Sunday, 23 February 2020 by Jeremy Cook

SQL Server on Ubuntu 16.04

Install and configure mssql

Create and mount mssql volume

Create a Digital Ocean volume. In the following examples it appears as volume_sfo2_03 or ``volume-sfo2-03`.

sudo su -

mkdir -p /mnt/mssql
mount -o discard,defaults,noatime /dev/disk/by-id/scsi-0DO_Volume_volume-sfo2-03 /mnt/mssql
echo '/dev/disk/by-id/scsi-0DO_Volume_volume-sfo2-03 /mnt/mssql ext4 defaults,nofail,discard 0 0' | sudo tee -a /etc/fstab

Configure mssql default directories

sudo su -

# Backup to the mounted drive
mkdir -p /mnt/mssql/backup
chown -R mssql:mssql /mnt/mssql/backup
chmod 770 /mnt/mssql/backup
/opt/mssql/bin/mssql-conf set filelocation.defaultbackupdir /mnt/mssql/backup

# OPTIONALLY, store data in a mounted drive
mkdir -p /mnt/mssql/data
chown -R mssql:mssql /mnt/mssql/data
chmod 770 /mnt/mssql/data
/opt/mssql/bin/mssql-conf set filelocation.defaultdatadir /mnt/mssql/data

# OPTIONALLY, log to a mounted drive
mkdir -p /mnt/mssql/log
chown -R mssql:mssql /mnt/mssql/log
chmod 770 /mnt/mssql/log
/opt/mssql/bin/mssql-conf set filelocation.defaultlogdir /mnt/mssql/log

systemctl restart mssql-server.service

Use NGINX and certbot to generate certificates

sudo su -

# Install NGINX
apt update
apt install nginx

# Create NGINX stub site
nano /etc/nginx/sites-available/

Paste this into nano and save.

server {
    listen 80;
    listen [::]:80;

    return 404 'ignore mode';
sudo su -

# Enable the stub site
ln -s /etc/nginx/sites-available/ /etc/nginx/sites-enabled/
# Disable the default site
rm /etc/nginx/sites-enabled/default
# Test the config and restart NGINX to apply the changes
nginx -t
systemctl restart nginx.service

# Install Certbot -
apt-get update
apt-get install software-properties-common
add-apt-repository universe
add-apt-repository ppa:certbot/certbot
# press ENTER to agree
apt-get update

apt-get install certbot python-certbot-nginx

# Configure certbot and NGINX to work together
certbot --nginx

# Create a script that copies the Let's Encrypt certificates for MSSQL to use
nano /opt/flipforms-scripts/

Paste this into nano and save.

cp /etc/letsencrypt/live/ /etc/letsencrypt/live/ /var/opt/mssql/secrets/
chown mssql:mssql /var/opt/mssql/secrets/fullchain.pem /var/opt/mssql/secrets/privkey.pem
chmod 400 /var/opt/mssql/secrets/fullchain.pem /var/opt/mssql/secrets/privkey.pem
systemctl restart mssql-server
sudo su -

chmod 770 /opt/flipforms-scripts/
# Run it and make sure there are no errors

# Have root run it weekly
crontab -e
0 0 * * 1  /opt/flipforms-scripts/

# Update mssql TLS settings
cat /var/opt/mssql/mssql.conf
/opt/mssql/bin/mssql-conf set network.tlscert /var/opt/mssql/secrets/fullchain.pem
/opt/mssql/bin/mssql-conf set network.tlskey /var/opt/mssql/secrets/privkey.pem
/opt/mssql/bin/mssql-conf set network.tlsprotocols 1.2
/opt/mssql/bin/mssql-conf set network.forceencryption 1

systemctl restart mssql-server.service
Read More

Posted Sunday, 23 February 2020 by Jeremy Cook

Setup Ubuntu 18.04 Server on Digital Ocean

Create SSH Key

ssh-keygen -t rsa -b 4096 -C ""

Initial Server Setup with Ubuntu 18.04

Logged in as root:

timedatectl set-timezone America/Denver

adduser jeremy # and enter password
usermod -aG sudo jeremy
# May need to `apt install rsync`
rsync --archive --chown=jeremy:jeremy ~/.ssh /home/jeremy
Read More