Matter, Energy, and Life of Michael A. Castello.

FreeNAS: Reverse Proxy, NextCloud, and Joplin

This is a mega-project that has existed as various schemes scrawled in my notebook for quite some time, likely approaching the order of years. I have long wanted to put my storage to use replacing Dropbox as my source of between-device file syncing, and I’ve been cautious of note-taking apps ever since being forsaken first by Google Notebook and subsequently by Evernote.

There is a well-maintained script that will do everything but the Joplin part of this project correctly in one fell swoop. I made things harder for myself because I wanted to learn what was actually going on underneath and I didn’t want to use Caddy as my reverse proxy.

A lot of people on the FreeNAS forums prefer using Caddy, but the 1.04 version available on FreeBSD is about to be end-of-lifed, including the documentation, in favor of a completely rewritten application. The “caddyfiles” will not be backwards-compatible, and right now, getting the Caddy 2.0 on FreeBSD involves compiling it from source. While not nearly as simple to use, I went with nginx.

Things Needed

  • Domain name to point at Nextcloud.
  • Dynamic DNS (DDNS) so that the domain can still find the home server if the residential IP address changes.
  • Reverse proxy to accept secure connections from outside the house and route them appropriately to Nextcloud.

Dynamic DNS

Many routers, including my own, support some form of this (especially if using third-party firmware setups). Unfortunately the router I bought this time isn’t very hackable and the built-in DDNS would not allow me to use my own custom domain name.

DDNS with your own domain name is ideally supported by the domain name registrar. I dislike using Google for this purpose but went with Google Domains anyway due to them having a lot of cheap domains. I also erroneously thought Google Domains supported Certbot for setting up my SSL connections, but it turned out that is Google Cloud DNS, part of a separate suite of subscription services.

FreeNAS has a built-in module that can handle the DDNS updates to many services. Google is one of the built-in providers. CheckIP is just:


And the URL is:

The other stuff is generated for you on the Google page under settings for that domain.

Thanks to the Certbot discovery I set up my domain with CloudFlare instead, and may transfer the registration to them from Google if things are still working out in 60 days. CloudFlare isn’t built in to FreeNAS so I set up DNS-O-Matic as an intermediary.

In the FreeNAS DDNS module, I specified the checkip server and path per this forum thread. Note that the path is simply a slash character.

Checkip-path: / 

I found a support post that helped me get the rest of the settings working which I have reproduced here.

DNS-O-MATIC settings

  • Service: Cloudflare
  • Email: (email address registered with Cloudflare)
  • API Token: (global API Token from Cloudflare, not the specific ones)
  • Hostname: dynamic
  • Domain:

Cloudflare settings

Cloudflare needs several records to be set in order to work correctly. The final piece is setting up CNAME records at Cloudflare (DNS provider) that point any subdomains that will be used for Nextcloud or other reverse proxy services back to the main domain. Free Cloudflare won’t wildcard it for you.

  • Type: A | Name: dynamic | Value: (DNS-O-Matic will update this when it runs)
  • Type: CNAME | Name: ( | Value:
  • Type: CNAME | Name: www | Value:
  • Type: CNAME | Name: nextcloud | Value:
  • Type: CNAME | Name: jellyfin | Value:

Reverse Proxy

This is needed to get requests from the outside to the inside of the network over SSL, and setting things up this way creates a central place for managing and renewing the SSL certificates. In lieu of Caddy, I went with nginx following an excellent guide by Samuel Dowling.

Certbot and certificates

Again, the Certbot instructions for Google are for Google Cloud something or other, not Google Domains. The guide provides instructions for Amazon Route53, but I was able to follow the Cloudflare Certbot documentation without incident.

SSL configuration

When performing the SSL configuration, I used Mozilla’s boilerplate as recommended by the guide. I wanted to try using the “modern” configuration but I ended up having to use intermediate. Delete everything before the SSL timeout line. Also delete the line with “path to certificates,” because one of the snippet files you created includes that stuff. “Resolver” is the IP address of your router unless you have a more complicated configuration.

I did have an issue with getting a “too many redirects” error, but fixed it by changing the SSL setting from flexible to full in Cloudflare as recommended by a comment:

I managed to solve the problem. I changed my SSL setting from flexible to full in Cloudflare and now the redirects have stopped and nextcloud is up and running.

Helpful internet commenter

Jellyfin-specific settings

The “default” proxy-params from the guide need to be tweaked a little to work with Jellyfin. In my conf file for, I removed the call to the proxy-params file and combined my default settings with the Jellyfin project’s recommendations:

server {
        listen 443 ssl http2;

        access_log /var/log/nginx/media.access.log;
        error_log /var/log/nginx/media.error.log;

        include snippets/;
        include snippets/ssl-params.conf;

        index index.html;

        location / {
            try_files $uri $uri/ =404;
            return 302 $scheme://$host/jellyfin/;

        # Jellyfin
        location /jellyfin {
            return 302 $scheme://$host/jellyfin/;

        # Jellyfin
        location /jellyfin {
            return 302 $scheme://$host/jellyfin/;

        location /jellyfin/ {
            # Proxy main Jellyfin traffic
            # The / at the end is significant.


            proxy_pass_request_headers on;
            proxy_set_header Host $host;

            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header X-Forwarded_host $http_host;

            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $http_connection;

            proxy_buffering off;

I would be happy to hear any suggestions or corrections of mistakes I made above.


Nextcloud is an open source file synchronization application that allows individuals or organizations to use and control their own storage setup. I again based my installation on another fantastic guide written by our friend Samuel Dowling.

My changes from the guide include using the latest MariaDB version in the package manager at the time of writing, and the PHP 7.3 version of Nextcloud. I skipped over the SSL part as mentioned in the guide itself, since I had previously set up the reverse proxy.

I found information for configuring the reverse proxy information from the comment section of the guide, which ended up being very similar to the easy ones above.

server {
        listen 443 ssl http2;

        access_log /var/log/nginx/cloud.access.log;
        error_log /var/log/nginx/cloud.error.log;

        proxy_hide_header Strict-Transport-Security;
        include snippets/;
        include snippets/ssl-params.conf;

        location / {
                include snippets/proxy-params.conf;

During the redis portion of the guide I changed ownership of the configuration file.

chown redis:wheel /usr/local/etc/redis.conf

Finally, I ran into a weird issue where I was unable to log in without first refreshing the page. I would go to the site, log in, and the page would perpetually load without completing and showing the files. If I simply refreshed the browser, the files page would load correctly. In the Android Nextcloud app, you can’t “refresh the browser,” so the app would display the loading screen without going anywhere. Scouring the log files pointed at the reverse proxy as the culprit, and the solution turned out to be in a single self-answered post on the Nextcloud help forums.

To make Nextcloud work correctly with a reverse proxy, add the following to Nextcloud’s config.php:

'trusted_proxies' => 
array (
  0 => 'reverse_proxy_IP_address',

On first run, Nextcloud will prompt for creation of an admin user. Once in there, tweak basic settings and create the user account you will actually use on devices.


Joplin is an open-source note-taking app that can sync to a number of targets, including Dropbox and Nextcloud. Making it work with Nextcloud was fairly easy, and starts on the Nextcloud side.

Log in as your regular Nextcloud user (not the admin) and create a folder called “Joplin.” That’s all you need to do on the Nextcloud side. There is a Nextcloud Joplin plugin but it is still in testing and not necessary for syncing, so I did not install it.

Each Joplin instance will need to be configured to use Nextcloud individually. Luckily it’s the same process in all the apps I’ve used so far (Android, Mac OS, Windows). For “sync target,” change it from Dropbox to Nextcloud. For Nextcloud WebDAV URL, use the direct link to the Joplin folder previously created:

Input your Nextcloud login information, and Joplin should be ready to sync.

Final Thoughts

We will see what happens now that everything is working and I start actually using the apps. So far I am pleased with the enhanced Markdown support of Joplin and the flexibility of its web clipper browser extension. I haven’t installed any of the Nextcloud plugins, and I may need to make adjustments to the virtual machine running Jellyfin to be able to handle practical usage without embarrassment: In the first real field test, Rachel has reported lag at least once.

You may also enjoy…

Want more? Keep up with the hottest content.