This article summarizes my descent into insanity and the following events that transpired on 30th July 2022. More formally, as I had mentioned in my previous blog post, I was looking to replace Google Drive and Photos with something self hosted and OSS. It was also the right time as I was bumping against the 15GB free limit on my Google Drive. I’ve been following Nextcloud for a while now, as I’ve heard it to be reliable and easy to set up.
My goals are,
- Cost Effectiveness
I’ve been using a Digital Ocean droplet (a Virtual Private Server) for the past 2 years to host Bitwarden password manager and some ad-hoc testing for ongoing projects.
Couple of things to note,
- TOR1 is a datacenter in Toronto, Canada. Toronto is quite far from Hyderabad in terms of network latency, which is not a concern for Bitwarden as the mobile app and extension cache the password vault frequently.
- Memory of 2GB - The absolute minimum required for installing Bitwarden.
- 50GB Disk - This was originally only 25GB because why would a password manager need more?
Okay, first problem to tackle.
I’ve recently migrated to a new PC, so I had to enable SSH login from this one. It was a very straight-forward process.
- Copy over public key from local to remote server’s /root/.ssh/authorized_keys
- Restart ssh daemon,
service sshd restart
- SSH into the server.
I had an A record configured on Bluehost to point “verylongname.saihemanth.com” to the static IP of my server. Purely for aesthetic reasons, I wanted to change it to “short.saihemanth.com” instead. Updating the DNS record barely took 10 mins.
Bitwarden turned out to be a pain in the ass while switching domain names. Specifically, it was the built-in certbot. It was supposed to be a single config change in
/opt/bitwarden/bwdata/config.yml and restart,
./bitwarden.sh restart. This worked, but the generated SSL certificates were still linked to the old domain.
I thought, “Okay, no problem. Let me just trigger the renew certificate command. It should pick up the new domain name from config. Right?” Wrong!
I deleted all certificate files used specifically by certbot in the hopes that it’ll try to pick up the correct domain name from config next time. That still didn’t work. I struggled with fixing this for over an hour!
With no other resort, I exported all my passwords using the Bitwarden Web UI and uninstalled bitwarden:
./bitwarden.sh uninstall. Reinstalling the entire setup and importing my exported passwords took less than 20 mins.
Not elegant, but problem solved!
I took a backup of the droplet to start with — in case I brick the server. DigitalOcean bills me for keeping backups too. Thanks, DO 👍
- Installing NextCloud itself was very simple. I just had to follow nextcloud all-in-one’s README. What does all-in-one mean? I didn’t know, I only needed the cloud storage functionality, and AIO was easy to set up.
1 2 3 4 5 6 7 8 9
sudo docker run -it \ --name nextcloud-aio-mastercontainer \ --restart always \ -p 80:80 \ -p 8080:8080 \ -p 8443:8443 \ --volume nextcloud_aio_mastercontainer:/mnt/docker-aio-config \ --volume /var/run/docker.sock:/var/run/docker.sock:ro \ nextcloud/all-in-one:latest
Next step, I opened the AIO (all-in-one) interface at
short.saihemanth.com:8443. This webpage gave me the default admin password and redirected me to an installation page. It asked for a valid domain name with port 443 open and a valid SSL to be used for NextCloud.
The domain was quickly verified and accepted by the tool! I started all the required nextcloud docker containers through the UI and waited for the containers to come up. They never did. The apache docker container logs gave me this error,
cURL error 35: OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to <domain>:443.
Took a while to figure out, but I realized it’s a memory issue. Bitwarden’s containers were struggling for resources alongside the newly bought up NextCloud containers. NextCloud’s Redis container was in particular failing, and the Apache container was waiting for the database to be up. So, no NextCloud for me.
I resized the droplet to 2vCPUS, 4GB memory, and 50GB Disk and followed from step 1 again. It all worked flawlessly now!
- I quickly set up 2FA for the admin account, and created a different personal user account for daily use.
After 4 hours, I finally have a working NextCloud instance running! (Not Really)
NextCloud AIO doesn’t seem to have support for automated backups. Admin needs to explicitly generate backups by clicking a button in settings, upon which an encrypted backup is created and stored. I would’ve liked something automated, but I wasn’t too eager to explore more.
- Upon generating backups through the UI, they land as encrypted files in “/root/nextcloud_backup” directory. This works for now.
- I need to sync these backups from the DO droplet to my local backup disk. What better tool than rsync? I rsynced with archiving and compressing enabled to hopefully make it faster.
rsync -avzh email@example.com:/root/nextcloud_backup /backup-disk/remote_backup/nextcloud_backup
The files were downloading at 25KBps! It will take forever to download 15GB backups. This speed was abysmal and barely viable as a solution. I forboded to one of the reasons before. This server is all the way in Canada, and this trans-continental data transfer was poor. However, I partially felt it also had to do with DigitalOcean itself.
There were a couple of reasons why I wanted to dabble with AWS,
- Cheaper Servers - AWS VPSs are about 5\$ cheaper compared to a similar configuration in DO. The exact setup is 20\$ on AWS Lightsail, while DO was 24\$ per month.
- Better Integrations - AWS is known for its wide variety of services and integrations, and I believed they could aid me later.
- Curiosity - I probably could do something similar on DigitalOcean, but I wanted to play with AWS and see what AWS is all about.
Everything after this was smooth,
- Started a lightsail instance in Mumbai datacenter with 2GB RAM and 1vCPU. This config’s free for 3 months.
- Setup the network config,
- Open ports 443, 8080, and 8443 on both TCP and UDP.
- Create a static IP and attach it to the instance.
- Add DNS mapping for this static IP on Bluehost.
- Follow all steps from Problem #2 to install and set up NextCloud AIO.
Once again, I finally have a working NextCloud instance running!
8 hours in.
I downloaded 600MB worth of pictures from Google Photos and tried uploading them to NextCloud. The app promptly became unresponsive and crashed. I couldn’t SSH into the server either. Nice 👌.
It was clear that 1vCPU was insufficient for this instance, so I bumped it up to 2vCPUs and 4GB RAM. Unlike DigitalOcean, AWS had no option to resize the existing server itself. I had to create a new larger lightsail instance using a backup of the previous one.
One other observation I had was that NextCloud does not send previews for gallery views by default. It instead sends over the entire image! One way to circumvent this is to use the previewgenerator NextCloud app. This requires a cron job to continuously generate previews for any recently uploaded media.
1 */10 * * * * docker exec -it <docker-process-id> ./occ preview:pre-generate
I tried out rsync of backups similar to before, and this time it downloads at 8MBps!
Okay, I finally finally have a working NextCloud instance! For real.
Comparing my final setup against the goals I set initially.
I’m not happy with storing my files in the instance’s disk. It seems fragile and bound to fail at some point. Increasing storage also requires me to bump up the instance’s config, which is far from ideal. For e.g., the current lightsail instance comes with 80GB disk. If I need more space, I’ll have to increase the VPS’s specs including vCPUs.
If the server dies, I have mechanisms to recover the setup using a backup. Creating and syncing backups is a low effort task. However, I might lose the recent uploads that aren’t backed up. There’s scope for improvement here.
I don’t see any obvious security flaws here. Running NextCloud Scan gives an A rating. There’s SSL in place. Only required ports are open. There’s probably more I can do here, but they only yield diminishing returns.
After I moved to AWS Lightsail, the website and Android app are blazing fast. The uploads happen at upwards of 8MBps, and the experience is super smooth.
The entire setup is just one Lightsail instance. The lightsail instance (2vCPUs/4GB/80GB Disk) costs \$20 per month. In contrast, Google One subscription costs Rs.135 in India, \$1.7.
I cannot justify having a feasible replacement if it costs 11 times more!
Stay tuned for Part 2 of this series! Follow me on Twitter for more :)