UniFi Controller – Self Hosted Docker

One of the wifi access point brands that we’ve always recommend to family, friends, and others is Unifi. Usually, we end up having to do maintenance of their equipment. A solution is to setup an Unifi Docker container for a L3 management over the internet. Sure, we could set it up to phone home to UniFi cloud management, but what would be the fun of that?

We would like to note that we are not Docker experts or work with Docker on a daily basis and it’s something we would like to study more into when we have the chance. We are sure there is a more automated way to maintain the Docker image.

Step 1: On a Linux host, add a service account for Docker. Doesn’t need to be the same name. After adding the user, get the UID of the user, this will be referenced later.
sudo adduser docker_unifi

Step 2: Install Docker
curl -fsSL get.docker.com -o get-docker.sh
sh get-docker.sh

Step 3: Setup persistent storage.
sudo mkdir -p /var/docker_storage/unifi
sudo chown docker_unifi:docker_unifi /var/docker_storage/unifi

Step 4: Pull and create Docker Container

I’ll be using Jacob Albery’s container for Unifi. Use a container that you trust, at this time of this post, there was no official Unifi container.
docker pull jacobalberty/unifi:stable

To create the container, we will need the UID and GID of the non root user you’ve created in Step 1.
id -u docker_unifi
id -g docker_unifi

In this case, the UID and GID of docker_unifi is 1001.

The below command will create the Docker container and allow it to automatically restart if it ever crash and will not run as root. In this case, we are using L2 discovery to setup and firmware upgrade the APs on the local network. Otherwise, we would use network port forwarding.
docker run -d --restart=always --net=host --name=unifi -e RUNAS_UID0=false -e UNIFI_UID=1001 -e UNIFI_GID=1001 -v /var/docker_storage/unifi:/unifi jacobalberty/unifi:stable

To update this container in the future, use the following commands. Just be sure to remember what you used for creating the Docker container.

docker pull jacobalberty/unifi:stable
docker stop unifi
docker rename unifi unifi.old
docker run -d --restart=always --net=host --name=unifi -e RUNAS_UID0=false -e UNIFI_UID=1001 -e UNIFI_GID=1001 -v /var/docker_storage/unifi:/unifi jacobalberty/unifi:stable

If the upgrade was successful, remove the old container by using command:
docker rm unifi.old

Next is setting up external DNS.

External DNS – Setup

Since normal consumer external IP addresses usually change every so often and we needed to allow the firewall to only allow certain IP addresses as a source. An A or AAAA record will be needed to be updated dynamically by a client at the client’s location.

Luckily, we are able to setup the DDNS settings at these locations, each with their own unique API key following a naming convention and under a different domain name than the primary one utilized. If the client has a public domain name already, see if you can get them to setup DDNS on public DNS instead. We are using Cloudflare DNS nameservers and protections; this will be different depending on what you use.

We suggest making a subdomain that you only know and add sub-records to that.

For example:

  • A record for 1 client site
    • Host Name: c1.u.i
    • Proxy status: DNS only (do not use proxied, your firewall will block these)
  • A record for another client site
    • Host Name: c2.u.i
    • Proxy status: DNS only

If DDNS is configured correctly, the DNS records update with the correct IP addresses. Next we configure the firewall to only allow these certain FQDN.

Firewall – Setup

We use pfSense firewall here and the easiest way to setup the firewall settings and not having multiple repeating rules is to setup an Firewall Alias for both the Ports and Hosts allowed. Below is an example of the Hosts alias.

In the firewall rules, we set the Hosts Alias as the source, the destination, and the Port Alias for the allowed custom Ports. This would prevent usual internet background scans and malicious users/bots from seeing the ports are open.

As always, secure this environment with firewalls and within a DMZ network zone that is separate from your normal network and always keep this host and the Docker image updated. We allowed the following ports through the firewall defined here: https://help.ubnt.com/hc/en-us/articles/218506997-UniFi-Ports-Used#2

UniFi Controller – Setup

Be sure to set the Controller hostname to the FQDN and check the box to Override inform host with Controller Hostname/IP. Also, update this public DNS record to point to the Controller WAN IP address.

To remove/migrate a external client

  1. Migrate their Unifi Management 1st. Note: Site Export works wonders.
  2. Notify the DDNS record is no longer required (unless they set it up and want to keep it)
  3. If any, remove their public DNS entries & their DNS API access to your domain management
  4. Remove the FQDN name from the firewall host alias.

MikroTik Switch – Setup VLANs

I had purchased a MikroTik RB260GS (product link) to allow me to setup vlans for about $40 and later be able to setup a fiber run for a few remote devices.The MikroTik RB260GS is able to handle 802.1Q VLAN tags with 5 Gigabit Ethernet Ports and a single SPF cage. It can be powered by PoE (Power over Ethernet) on the 1st port and has a small form factor of 4 7/16 x 5 1/2 x 1 1/8 inches or 133 x 139 x 28 mm. There are larger and different models to choose from as well and should be considered depending on your needs.

From the beginning of trying to setup the VLANs, I had a hard time with this switch and a learning curve ahead of me for this solution. I hope this will assist those whom are having difficulties as well.

Port – Trunk

A trunk port is where multiple VLANs share the same physical connection and is used for the network backbone infrastructure up to the Access Level Switches.

Also, consider the amount of VLANs and traffic going through this port, it will be limited to 1 Gigabit and shared amongst all the VLANs going through it. Sometimes, it might be a better idea to have the SPF port be the trunk port with a 10 Gb fiber module. It would use less power, faster, lower latency, and electrically isolated from the other end of the trunk on this connection.

For this switch, it’s best for the trunk port to be port 1, especially if PoE is being delivered from another switch, or the SPF port. Below is how to configure the trunk port and can be any port on the switch.

  1. Navigate to VLAN tab
  2. Configure the port’s Ingress settings as listed:
    • VLAN Mode: Enabled
    • VLAN Recieve: Any
    • Default VLAN ID: 1
    • Force VLAN ID: Unchecked
  3. Configure the port’s Egress settings as listed:
    • VLAN Header: Add If Missing
  4. Navigate to VLANS tab , Add the VLAN numbers here.
  5. Make sure the Trunk port has all of the VLANs settings are set to Leave as is

Access Ports

These ports only have a single VLAN associated to them and is normally used at the Access Switch Level when end devices plug into.

  1. Navigate to VLAN tab
  2. Configure the port’s Ingress settings as listed:
    • VLAN Mode: Strict
    • VLAN Recieve: only untagged
    • Default VLAN ID: <Your VLAN ID here>
    • Force VLAN ID: Unchecked
  3. Configure the port’s Egress settings as listed:
    • VLAN Header: always strip
  4. Navigate to VLANS tab
  5. Make sure the Access port has all of the VLANs settings are set to Not a Member, except for the VLAN ID you’ve entered in step 2. It would be set to the value Always strip.

Multi-VLAN Ports

Sometimes there is a need where a port may need multiple VLANs going across it to a device, like a wireless access point. See below settings

  1. Navigate to VLAN tab
  2. Configure the port’s Ingress settings as listed:
    • VLAN Mode: Strict
    • VLAN Recieve: any
    • Default VLAN ID: <Your Default VLAN ID here, usually management VLAN ID>
    • Force VLAN ID: Unchecked
  3. Configure the port’s Egress settings as listed:
    • VLAN Header: always strip
  4. Navigate to VLANS tab
  5. Make sure this port has all of the VLANs settings are set to Leave as is except for the VLAN ID you’ve entered in step 2. This would be set to the value Always strip. The non-allowed VLANS on that port should be set to Not a Member

Testing your config

It’s best practice to test each port to see if the configuration is correct when doing this the 1st few times. Wireshark (link) will be your friend or even a simple checking of the IP range you receive will work for the most part. There are plenty of online tutorials with working with Wireshark and I will not cover them.

Ender 3 – MKS Gen L and BLTouch Upgrade

After breaking my Ender 3 board by acciendent, I decided to switch to a MKS Gen L board. Contained in this article are the steps that I’ve taken to swap boards. I am writing this after the fact, I do apologize if I miss any details.

WARNING: This deals with handling electronics and electricity. Follow at your own risk.

Required Equipment & Software

  • MKS Gen L Board
  • Computer
  • Arduino IDE
  • Screwdrivers (insulated one for adjusting stepper drivers)
  • Multi Meter

Step 1 – Print a Case & (Optional) BLTouch mount

Print a case for the MKS Gen L board and optionally the BLTouch mount beforehand. Following are the models I’ve used:

MKS Gen L Case by TeachingTech: https://www.thingiverse.com/thing:3311643

BLTouch Mount for Ender 3 created by registerdthing https://www.thingiverse.com/thing:3003725 .

Step 2 – Label current connections

IMPORTANT: Turn Power Off and Unplug Power Cord

After opening the case, label the current connections on the Ender 3. Below is an image describing what everything is.

Step 3 – Write down current Ender 3 Firmware settings

Write down/take photos of current Ender 3 Firmware Settings for acceleration, steps, etc.

Step 4 – Measure Stepper Drivers’s Voltage

Measure the stepper drivers’ voltage when it’s powered on. Only connect your multi-meter negative lead to the main negative terminal and positive lead to each stepper driver potentiometer and record the voltage value. These will be used for future reference in tuning the external stepper drivers.

Step 7 – Install Stepper Drivers

Install stepper drivers onto the MKS Gen L board. Keep track of which stepper model you use, they may be needed for preparing the firmware.

Step 5 – Prepare MKS Gen L Firmware

Next we will be preparing Marlin 1.1.9 Firmware to be flashed onto the MKS Gen L board. Obviously, we will be including the configuration for the BLTouch and we are keeping the original Ender 3 display. Note: Since we are keeping our original display, we are going to lose the SD card functionality. To get this functionality back, replacing the Ender 3 original display with one that has a SD card.

  1. Download Marlin 1.1.9 release firmware from github.com. Direct link: https://github.com/MarlinFirmware/Marlin/releases/tag/1.1.9
  2. Extract files from the zip or tar.gz archive
  3. Copy files from Marlin Example Configurations/Creality/Ender-3 to Marlin Folder. Overwrite files that already exist.
  4. Within Configuration.h change the following:
    1. #define MOTHERBOARD BOARD_MELZI_CREALITY to #define MOTHERBOARD BOARD_MKS_GEN_L
    2. #define INVERT_X_DIR true to #define INVERT_X_DIR false
    3. #define INVERT_Y_DIR true to #define INVERT_Y_DIR false
    4. #define INVERT_Z_DIR false to #define INVERT_Z_DIR true
    5. #define INVERT_E0_DIR true to #define INVERT_E0_DIR false
    6. #define E0_AUTO_FAN_PIN -1 to #define E0_AUTO_FAN_PIN 7
  5. (Optional) BLTouch Configuration.h changes:
    1. //#define BLTOUCH to #define BLTOUCH
    2. //#define BLTOUCH_DELAY 375 to #define BLTOUCH_DELAY 375
    3. #define X_PROBE_OFFSET_FROM_EXTRUDER 10 to #define X_Probe_OFFSET_FROM_EXTRUDER -42
    4. #define Y_PROBE_OFFSET_FROM_EXTRUDER 10 to #define Y_PROBE_OFFSET_FROM_EXTRUDER -5
    5. //#define AUTO_BED_LEVELING_BILINEAR to #define AUTO_BED_LEVELING_BILINEAR
    6. //#define Z_SAFE_HOMING to #define Z_SAFE_HOMING
  6. Install U8glib package under Sketch -> Libraries -> Manage Libraries
  7. Configure the stepper driver settings under Configuration.h. Search #define X_DRIVER_TYPE and change the options to match the same models used. A4988 is automatically assumed the stepper driver for all stepper locations.
  8. Try click on the check mark on the top left, this will compile the project and ensure no errors shows up on the bottom status window.

Step 6 – Flash Firmware

Connect the MKS Gen L board to the computer with Arduino IDE installed. Ensure under Tools -> Board is set to Mega 2560, Tools -> Processor is Mega 2560, and you’ve selected the proper port. Then click the button on the top left with an arrow pointing right.

Step 8 – Swap cases & boards

Warning: Turn off power and unplug power.

Unplug and unscrew everything from the Ender 3 board, by now each should be labeled to where they go. They should correspond with the labeling on the MKS Gen L board.

Note for the Ender 3 sensors, you may need to trim off the bottom left notch as shown above.

Step 10 – (Optional) Install BLTouch

I installed the BLTouch Mount for Ender 3 created by registerdthing https://www.thingiverse.com/thing:3003725 .

For plugging in the BLTouch, the 2 pin connector goes into the z min sensor with black to the middle pin and white to the S(signal) pin. The 3 pin one (brown, red, & orange pins) plugs into the last 3 pin socket as shown in this picture.

Step 9 – Adjust Stepper Drivers

Turn on the power and adjust the stepper driver potentiometers with an insulated screw driver and measure with a multimeter to get as close as you can get to the values you’ve written down under step 4. Essentially, the same as measuring in step 4.

Step 11 – Calibrate

With BLTouch, include G29 after G28 command in all GCODEs and adjust the bed corners to be within 0.1 mm or better of each other. Also, adjust the Z offset when Z axis is at 0 after G28 and G29 commands using https://nate15329.com/3d-printer-calibration/.

Ender 3 – Upgrade Failure

While attempting to upgrade my Ender 3 printer to have both a BLTouch and a filament run out sensor, I had damaged my Ender 3 board. Had the decision of either getting a new Ender 3 replacement board or MKS Gen L board.

I decided to go with the MKS Gen L board. It has more memory for Marlin firmware functions and ability to add more physical features/accessories in the future, including servos, BLTouch, filament run out sensor, dual extrusion, any stepper drivers, etc.

A later blog post will contain swapping a Ender 3 board with a MKS Gen L board, since it involves multiple steps, especially in the firmware config. At this moment, the printer is being calibrated with a BLTouch sensor.

DDR4 RAM Latency

As a system builder, enthusiast, and gamer, one of the items we usually purchase in a new build is RAM (Random Access Memory). This RAM is used for fast temporary storage for your CPU (Central Processing Unit). Persistence storage such as HDDs and SDDs are very slow to process data directly plus they have a limited lifespan for reads and writes. Hence RAM is used between the CPU and the persistence storage, bringing faster application performance. We’ll take a look at finding the lowest RAM latency, which would be the faster response RAM and estimated cost per GB.

RAM is sold in terms of how fast the RAM is and CAS Latency. RAM speed is the built in clock cycles that refreshes the memory and is usually in terms of MHz or MT/s. CAS Latency is the delay time between memory controller asks for data and data is available on the RAMs output pins and is usually in nanoseconds.

Since usually RAM is sold with different speed and CAS Latency, the following formula will assist you on figuring out the relatively faster RAM as the 2 values do determine the performance of the RAM.

Latency (ns) = Clock Cycle Time (ns) x CAS Latency (CL)

Latency (ns) = (1/Module Speed(MT/s) x 2) x CAS Latency (CL)

To find the higher performance RAM, look at the least CAS Latency and higher speeds to minimize the latency as much as possible as shown below in the table. We’ve excluded some results due to not existing on the market or only found very few results to provide an good average price per GB.

Module SpeedCAS LatencyLatency (ns)Est Price $/GB (6/2019)
4400177.7320.937
4400188.1819.749
3600158.3316.281
4000178.515.745
4400198.6418.041
3200148.7511.149
3600168.8912.292
400018911.619
3000149.338.923
3200159.389.895
3600179.4410.635
4000199.515.706
2666139.7511.697
300015108.61
320016108.932
3600181010.754
36001910.566.484
30001610.677.868
24001310.836.906
26661511.257.023
30001711.335.577
24001411.676.454
266616126.582
21331312.196.242
24001512.57.432
21331413.139.76
24001613.335.82
21331514.067.466
24001714.177.164

The difference between the lowest and highest latency times are 7 nanoseconds apart. These differences might be noticeable, but very slightly.

As for our gamer audience, it is wiser to spend extra money on the GPU than on faster RAM. usually for gaming an individual computer only need s8 to 16 GB depending on the game and near 10 ns in latency before getting higher prices.

Officially, DDR4 memory limitation is set by JEDEC (https://www.jedec.org/) and the upper limit is at 3200 (MT/s) before needing to turn on XMP (Intel Extreme Memory Profile) in your motherboard settings to get the higher speeds on XMP Ready/Certified RAM.

3D Printer Calibration

Here’s what I use to calibrate our 3D printers. There are many guides out there for most of the methods and didn’t see the need to go into heavy details.

Calibration Tools used:

  • Pro-Grade Electronic Digital Caliper 82806
    • Know your accuracy tolerances, ours was +- .02 mm for lengths below 100mm with a resolution of .01 mm
  • Thin Wall Calibration https://www.thingiverse.com/thing:342198
  • Single sheet of paper

1.Initial Extruding Calibration

First thing we will need to calibrate on a new 3D printer is the filament extrude rate. It is very important to get this as accurate as possible, minor tweaking can be done with extrusion multipliers.

To figure this out by telling the printer to send 30 mm of filament through with the hot end disconnected and measuring with a caliper to see if the amount is accurate. Then update the stored value of Esteps/mm under Marlin Motion options by following this formula: Current Esteps/mm * 30mm / Actual amount of filament pushed

For example:

  • Current Esteps/mm: 93
  • Tell printer to extrude this amount of filament: 30mm
  • After measuring the amount of filament extruded: 29.33 mm
  • New Esteps/mm value = 93 * 30/29.33 = 95.124

2. Bed Leveling

Bed leveling is crucial for it will either allow your print complete properly or outright fail later on besides filament run-out or the disastrous thermal runaway. There are numerous ways of getting this done usually by sliding a piece of paper between the heated nozzle and heated bed, or something similar to a BLTouch or a conductive sensor.

The methods that are used often:

  1. 1st is done with piece of paper between heated nozzle and heated bed at normal printing temperatures for the printer. Since I print mainly in PLA, the temps would be at 200 C and bed at 70 C. Then manually level the middle, then the 4 corners where the paper is slightly catching between extruder and the bed
  2. Next, print Bed Leveling squares that looks like the 5 dot side on dice, 1 mm height and slightly adjust our leveling while it prints and wait a few lines are printed after adjusting and see if its flat and clean looking and doesn’t come off of the bed easily. An example of these squares on Thingiverse: https://www.thingiverse.com/thing:2789086

For Auto Bed leveling, a great bed visual is from OctoPrint with the plugin Bed Visualizer. It will highlight which corners need to be readjusted much better and readjust the dark red and blue slightly. Just keep an eye on the visual scale as it will re-adjust.

3. Wall thickness

Next up to calibrate our Wall thickness, please note that this will affect your bed leveling, extrusion multiplier, and/or Esteps/mm. Essentially with .2 mm nozzle, print a hollow cube with .2 mm thick walls with a layer height of 0.16 mm (80% the size of the nozzle), then measuring with a caliber. A good resource to use are the Thin Wall calibration files created by MEH4d at https://www.thingiverse.com/thing:342198

Once the .2 mm thick walls have been printed, measure the wall thickness with the caliber but exclude the bottom of the walls. The bottom will usually be a tad off due to 1st layer height/bed leveling is a tad off. If the thickness is off try adjusting the multiplier between .9 and 1.1, but keep in mind of your calibers limits. For example, if the measured result was .19, you could be very will be accurate.

If you had to adjust your multiplier to get best results outside of this range, place the multiplier back to 1 and adjust your ESteps/mm. Lower if the walls were too thick and the opposite if the walls were thin. After readjusting, you may need to readjust the bed level and layer heights.

Usually, a good max layer height for each of the nozzle sizes are at 80% as shown below:

  • 0.2 mm nozzle = 0.16 mm layer height
  • 0.3 mm nozzle = 0.24 mm layer height
  • 0.4 mm nozzle = 0.32 mm layer height
  • 0.5 mm nozzle = 0.40 mm layer height
  • 0.6 mm nozzle = 0.48 mm layer height

4. XYZ Calibration Cube

At this point, print a calibration cube and measure with the caliber. Usually, it’ll be within measured dimensions that are to be expected. Check how the cube looks by actually looking for infill, speed, and other issues and try to correct them in our slicer program. Slowing down the speed improves many issues at this point.

5. Stress Test

Now its time to stress test your printer. Good set of models to use are by ctrlV on Thingiverse especially https://www.thingiverse.com/thing:704409 and then part fitting a M4 nut in the slot. Also, look at how well the filament retraction works and increase or decrease the retraction length.

MRRF 2019

1st time going to MRRF (Midwest RepRap Festival), We had enjoyed going to it. I had meet and talked briefly with few well known content creators.

  • Barnacules Nerdgasm
  • 3D Printing Nerd
  • Nerys
  • Ben Heck

I had gotten a few sample filaments to try and will be making the Sample Spool by Nerys (https://www.thingiverse.com/thing:2942019) relatively soon

  • Filament PM: MARRBLEJet
    • Figured this would be a good one for Statue Art pieces
  • Carbon Fiber Extreme from Atomic Filament
  • Glass Fiber Nylon from FiberForce Italy
  • Filament PM: RUBBERJet 88Blue
  • Filament PM: GLOWJet

I was always curious on how the fiber and rubber based filaments quality would work with my printers. Proto-Pasta metal infused filaments are another type to try out sometime this year. Since I don’t have any harden heads for these abrasive filaments, we’ll just sacrifice my brass ones and get them replaced after tinkering.

3D Gloop and their latest project Glooped! was interesting. 3D gloop is basically a stronger superglue for PLA and ABS prints. Meanwhile Glooped! is a primer layer to be applied on top of any print to smooth layer lines and chemically bonded to the plastic. I had picked up a small tube of 3D Gloop to try it out on a few prints. Glooped! as far as we know isn’t available yet.

The following things that I think could make MRRF better:

  • Larger area
    • The walking paths were often narrow and crowded which made it hard to move between booths
  • Map layout and defining table areas
    • Reduce the need to bring cards and a quick reference for all of us of where certain booths are

New 3D Printer – Ender 3

Due to having problems with my version of HyperCube 3D printer, I’ve decided to acquire a Ender 3.

I like having the latest printer firmware installed, mostly for safety concerns. I’ve upgraded the Marlin Firmware to the latest and using the sample Ender 3 config by using a USBtinvisp v2.0 board.

Currently, I’ve upgraded the Ender 3 with the following addons: