Cloudy With a Chance of Awesome

When we built our house a few years ago, I took the opportunity to level-up our network infrastructure and configuration. I had Cat 6 run to many rooms and conduit installed from attic to basement to simplify future wiring projects. I picked up a sweet little rack, patch panel, switch, router, firewall, and UPS. I set up wireless access points on each floor. I carved up separate SSIDs and VLANs for grown-ups and kids. To police and protect the latter part of my user community, I implemented a transparent proxy with squid, squidguard, and dansguardian that logged to Splunk. I set up alerts for content blocks and wrote a little web app à la Splunk SDK that displayed images being viewed in near real-time for improved Shenanigan Awareness.

You might be thinking, “Jay, that sounds totes amazeballs, please allow me to bask in the radiance of your technological splendor!” Before you reach for your sunblock…

The Shame

Amid technical text banter with a friend and colleague (we’ll call him “John”) a few weeks back, the topic of home network infrastructure surfaced. We volleyed different aspects of our respective setups. Everything was great until he shared a bit about his storage configuration. It was epic. Well thought-out and engineered – maybe even nerd chic. My eyes were immediately opened to my technical sin. I was confronted by the cold and brutal reality that my storage configuration was, technically speaking, weak sauce. Like a plumber with clogged toilets or a barber with a bad haircut, I was the engineer with crummy tech. The shame!

Prior to that momentous text exchange, the vast majority of our data lived on a couple elderly, consumer-grade NAS devices: a Synology Disk Station (c. 2015) and a Western Digital MyCloud Mirror (c. 2014). The little double-drive RAID 1 boxes worked. That is to say, they achieved non-failure. But stacked up against John’s infrastructure, it was embarrassing – like parking your perrywinkle Prius next to an octane red Challenger Hellcat.

With my lackluster configuration, if our home ever went This Is Us Crock-Pot Inferno we’d lose pretty much everything (much like the loss of manliness I just experienced by indicating I’ve seen greater than zero episodes of This Is Us). There would undoubtedly be weeping and gnashing of teeth, after which, my wife would turn to me and say “At least we still have all of our family photos and important files… Right? Jay?!” At that very moment, I would have no other choice but to go into exile.

The Road to Redemption

Fueled by shame and my calendar quarantine-clear, I decided it was time to right these wrongs and avoid an untimely death.

The End-State

The logical diagram below shows where I ended up: a Nextcloud implementation in a DigitalOcean VPC with external storage in Wasabi.

I’ll discuss the notable parts of my configuration and also share some config snippets where I believe they will be helpful. IPs and hostnames have been changed to protect the innocent.

Please note: the installation and configuration of common or well-documented stuff is beyond the scope of this post.

Existing NAS

I plan to replace the Synology and WD NAS devices with something fast, sexy, and rack-mountable, but for now they remain. We still save our stuff there, however, said stuff is replicated to the Nextcloud instance with the Nextcloud desktop client on our machines.

RP Cloud Firewall

My love for DigitalOcean cannot be over-stated, but that’s a long and rambling post for another day. One of many reasons for my DO-love, is the ability to provision network-based, stateful firewall services for droplets at no additional cost. In my configuration, the cloud firewall is logically situated in front of the reverse proxy. It permits inbound SSH, HTTP, and HTTPS traffic originating from a very short list of IPs, including the public IP (NAT) of our home network.

RP Host-Based Firewall

I’m running a firewall on the reverse proxy that incorporates the same rules as the cloud firewall. This allows me to exercise some control over the traffic and offers some protection in the unlikely event of a cloud firewall failure or compromise.

Reverse Proxy

The RP provides connectivity to the Nextcloud drop in the VPC. It runs nginx with both public and private IP addresses.

I created a subdomain that points to the public IP of the RP. We’ll call it secret.squirrel.foo. I also used Let’s Encrypt for SSL goodness. The config that follows allows me to point my browser at https://secret.squirrel.foo and hit the Nextcloud interface.

server {
    server_name secret.squirrel.foo;
    listen 443 ssl;
    set $upstream ;
    location / { 
        add_header Front-End-Https on;
        add_header X-Content-Type-Options nosniff;
        add_header X-XSS-Protection "1; mode=block";
        add_header X-Robots-Tag none;
        add_header X-Download-Options noopen; 
        add_header X-Permitted-Cross-Domain-Policies none;
        add_header Referrer-Policy no-referrer;
        proxy_pass_header Authorization;
        proxy_pass http://$upstream;
        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_http_version 1.1;
        proxy_set_header Connection “”;
        proxy_buffering off;
        client_max_body_size 0;
        proxy_read_timeout 36000s; 
        proxy_redirect off;
    }
    ssl_certificate /etc/letsencrypt/live/secret.squirrel.foo/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/secret.squirrel.foo/privkey.pem;   
}
server {
    if ($host = secret.squirrel.foo) {
        return 301 https://$host$request_uri;
    }   
    server_name secret.squirrel.foo;
    listen 80; 
    return 404;
}

NC Cloud Firewall

Drat! I just noticed a diagram error. I also have a cloud firewall that sits in front of the Nextcloud instance that permits traffic only from the reverse proxy. I refuse to modify the diagram. As much as I like OmniGraffle, it is a time-sucking vortex. So just imagine another cloud firewall there. Cool? Cool.

NC Host-Based Firewall

The firewall ruleset on the Nextcloud droplet is identical to the cloud firewall I omitted in the diagram. It only allows traffic from the private IP of the reverse proxy.

Nextcloud

(If you’re not familiar with Nextcloud, you should go read about it and then come back. Really, I’ll wait for you.)

The Nextcloud droplet is tucked away in a VPC. Without the reverse proxy discussed above, it would not be accessible from the Internet.

You can do a lot of things with Nextcloud. It’s a full collaboration/productivity suite and there’s an ecosystem of apps that can be integrated very easily. I’m only making use of the file management functionality but that might change down the road.

I’m using the Default Encryption Module to encrypt everything that gets written to the Wasabi buckets. This increases every file’s size by about a third. That does have an impact on the price tag when working with several terabytes of data, but it’s a necessary expense. I’m way too paranoid to store our personal stuff in the clear with a service provider, regardless of their safeguards, controls, and good intentions.

If you decide to make use of Nextcloud’s encryption, be sure to backup your keys or you run the risk of having a Very Bad Day down the road. Lose the keys and you will permanently lose access to your files.

The mobile app is also pretty slick. In theory, it gives you access to your files from wherever you may roam. In my setup, I’m intentionally limiting access to my home and any IP addresses or subnets I explicitly allow on my firewall instances. I plan to keep it locked down and only tweak the rulesets when I’m on travel (assuming travel becomes a thing we do again at some point in the future).

This was my first deployment of Nextcloud, and while my configuration does what I want it to, I’m not convinced it is complete or anywhere near best practice. I’ll refine it as a I get smarter on the platform and will share any significant config updates here.

Below are the parts of the configuration that were necessary for the reverse proxy configuration:

'trusted_domains' =>
    array (
        0 =>; 'secret.squirrel.foo',
        1 =>; 'localhost',
    ),
'overwrite.cli.url' => 'https://secret.squirrel.foo',
'trusted_proxies' =>
    array (
        0 => '',
    ),
'overwriteprotocol' => 'https',

Wasabi

DO has some nice options for smaller amounts of disk but none that were cost effective for multiple terabytes. AWS was an obvious candidate as well but it was also cost prohibitive. Wasabi checked all of the boxes for me in terms of feature set and price tag. Plus, since it’s AWS S3 compatible, the setup of Wasabi was dead-simple via the Nextcloud interface.

What’s next?

Clean-up and Transfer

We’ve transferred lots of data to Nextcloud but stll have a ways to go. I’m taking this opportunity to organize my stuff and eliminate files I don’t need. We also have some files in Dropbox, G Drive, and iCloud that we need to move.

iPhone Photos and Videos

I’m in the process of transferring all of the photos and videos on my phone using the Nextcloud mobile app’s Auto upload photos/videos option. If this works as expected, I should be able to disable iCloud photo storage.

VPN

I’m thinking about implementing a VPN to provide for more security of data in flight and also flexibility for Nextcloud access. With the latter, I could tweak the firewall rules to allow access from the VPN addresses and simply connect to VPN while mobile or traveling.

Comments

Please read the Comments Policy for guidelines and guardrails.