Certificates for Unifi on Docker in Synology

I have my Unifi Controller running within Docker on a Synology NAS. It is simple to set up, for example by following the instructions here. Getting certificates for https with the Synology UI is straightforward. Functionality to obtain (for example) LetsEncrypt certificates is readily available in the Control Panel under Security/Certificates. But how can one transfer those certificates to the UniFi Controller running in Docker? Here is how it worked for me:

  1. Download the certificates from the NAS by using the “Export” function in DSM. This will download a zip file called archive.zip containing three files: cert.pem, chain.pem and privkey.pem.

  2. Unzip the archive and concatenate the cert.pem and chain.pem files:

    cat cert.pem chain.pem >fullchain.pem

    Upload fullchain.pem and privkey.pem to the unifi directory on the NAS.

  3. Start a bash session within the UniFi Controller docker container. Run the following commands to convert and install the certs (see also here):

    openssl pkcs12 -export -inkey privkey.pem -in fullchain.pem -out cert.p12 -name unifi -password pass:temppass
    keytool -importkeystore -deststorepass aircontrolenterprise -destkeypass aircontrolenterprise -destkeystore /var/lib/unifi/keystore -srckeystore cert.p12 -srcstoretype PKCS12 -srcstorepass temppass -alias unifi -noprompt
  4. Restart the Controller. Easiest way to do that is restarting the Docker container.

  5. Don’t forget to delete all the certificate files.

Link Aggregation with Unifi Switches

Most workstations and NAS come with multiple Ethernet ports nowadays, so one would assume that port bonding with 802.3ad is a popular and easy to configure option. Port bonding can double the bandwidth while maintaining a single IP address, at least if you have multiple connection active at the same time. Of course, it is not so simple in practice. The main issue is how the devices split the data across the two links.

This hash policy needs to be configured on each source device (and every switch in between) individually. The simple policies (layer2 or layer2+3) base the routing decision on MAC or IP addresses, so all connections between two hosts (e.g. workstation to NAS) always go over the same link. In order to get the actual benefit of port bonding for multiple connections between two hosts one would need to use the layer3+4 policy, which also takes port numbers into account.

This was easy to configure for my workstation and my NAS, and it was also easy to enable Link Aggreagtion on my Unifi switch by following the instructions here. However, it turns out the UniFi switch does not yet have a configuration option for setting the hash policy. One can change the policy manually to layer3+4 by opening a session in the switch’s debug terminal and then typing:

telnet localhost
port-channel load-balance 6 all

The setting is lost when you restart the switch, but that is hopefully not very common.

Some people are concerned that the layer3+4 hash is not strictly 802.3ad compliant, but as far as I can tell that is rarely an issue in practice. It seems the main problem would be slower speeds for some specific services in some specific configurations, see e.g. here.


MandelVR is a small toy project I have been working on over the last few months. It is a simple VR app which lets you move around a Mandelbrot set visualization. It is implemented as a Windows app running on SteamVR with (GPU-accelerated) Direct3D 12. One can use the VR controller’s pad to fly around and the A and B buttons to zoom in and out. It is quite a bit of fun to discover the Mandelbrot set in VR already, but it turns out there are a few things that could benefit from some more work to get them right:

  • MandelVR computes the height of the points on a regular grid. That is problematic because there a plenty of cliffs and ridges which do not align well with the grid. In those areas the 3D Mandelbrot mesh resembles a rocky up-and-down zig-zag landscape rather than the clean edge one usually can see in 2D visualizations. It is probably not too hard to fix this by having MandelVR compute the mesh on the peak points rather than strictly on the grid, but it would take a bit to get that right.
  • Direct3D and (and GPUs designed for 3D acceleration) use 32-bit floats as that is accurate enough for most realistic 3D sceneries. Of course the main thing one would want to do with a Mandelbrot set is to zoom in, so float32 arithemtic becomes too inaccuracte quickly. MandelVR uploads the whole mesh to the GPU’s VRAM in float32 accuracy, so the rendered visualization becomes wobbly and blurry at larger zoom levels. It is easy to avoid this problem by computing the original mesh with 64-bit floats, but one would need to put a bit of thought in how to dynamically update the float32 mesh for the GPU.
  • Finding the right level of detail is challenging as the number of vertices that need to be rendered differs quite a bit from location to location. Ideally, one would want to have something that adapts dynamically so one can achieve stable frame rates. That is again not too difficult to implement but one would probably need to test on a variety of GPUs to be sure it works well.

Anyways, I am planning to work on some of those issues over the next few months. The source code is available here. If you are interested in contributing or adding stuff, feel free to open an issue or drop me a line.

Hello World!

Haha, 8too is online. Let’s hope this little blog will turn out to be interesting or maybe even useful.