A server running, for example, Nextcloud and Immich on a single unencrypted locally mounted drive presents two problems: no redundancy and no encryption. Moving bulk storage to Hetzner StorageBox addresses both issues. This post examines how to do this and the technical tradeoffs of that migration.
Starting Configuration
The existing example server runs Ubuntu 24.04 LTS with the following storage layout:
/eph3: 8.2TB (bulk data, unencrypted, no redundancy)
/opt: 77GB (application data)
/temp: 39GB (temporary files)
/var: 43GB (system data)
/backups: 100GB (backups)The single 16TB drive, eph3, has no RAID protection. All data is unencrypted at rest. The risk here is that the drive is deemed faulty, removed and discarded without being wiped, then later retrieved from the trash and recovered. The drive might also be retained and repurposed with another customer, if, for example, the server subscription is discontinued.
Proposed Configuration
The migration plan uses an Intel i7-7700 or i7-8700 system with dual SSDs for local storage and Hetzner StorageBox for bulk data. Local NVMe retains /opt, /temp, metadata directories, and cache. StorageBox mounts provide encrypted storage for Nextcloud and Immich media files using gocryptfs.
Advantages of This Approach
StorageBox provides RAID-60 redundancy without managing hardware RAID locally. The service includes an NVMe cache layer. Single disk failures are handled by Hetzner without user intervention.
Keeping /opt, /temp, metadata, and cache on local NVMe maintains performance for random I/O and file locking operations. These access patterns perform poorly over network mounts. The Storagebox needs to be in the same region for maximal throughput.
Performance Considerations
gocryptfs runs in userspace through FUSE rather than kernel-native encryption like LUKS. This adds overhead compared to local encrypted storage. Running gocryptfs over a CIFS or SFTP mount adds network latency to the FUSE overhead.
For archival data with sequential access patterns, this combination works adequately. Its not fast, but it works and the cache can be tuned on the server to take some overhead..
File Locking Limitations
StorageBox does not provide reliable POSIX file locking semantics. Do not place SQLite databases or application state files expecting flock or fcntl operations on the remote mount. The proposed configuration correctly keeps metadata local. Avoid the temptation to symlink additional files into the mount when troubleshooting issues later.
Redundancy Is Not Backup
RAID-60 on Hetzner’s infrastructure protects against drive failures in their array. It does not protect against accidental deletion, ransomware, or corrupted gocryptfs keys. If the encrypted library on StorageBox is the only copy, hardware failure risk is addressed but user error risk remains.
Irreplaceable data such as Immich originals requires a separate backup destination. A second smaller StorageBox with Borg or rclone-crypt snapshots provides protection against both hardware failure and operational mistakes.
Encryption Key Management
If the gocryptfs key or password lives on the same local SSD being protected, the threat model is specifically network and provider-side visibility. This differs from a threat model addressing physical server theft. Clarify which threat the encryption defends against before deciding where to store the key material.
StorageBox Sizing and Costs
Hetzner StorageBox pricing uses fixed tiers rather than per-GB billing. Current pricing as of this configuration:
1TB: €3.20/month
5TB: €10.90/month
10TB: €20.80/month
...The existing bulk data totals approximately 8.2TB. Using two separate StorageBox instances means paying two base-tier minimums. Unless Nextcloud/Immich data and other data each independently approach a tier boundary, two boxes cost more than necessary.
One consolidated 10TB StorageBox with two separate gocryptfs-encrypted subdirectories provides the same isolation with separate mount points and separate keys. This avoids paying for unused capacity in two smaller boxes unless access control, credentials, or retention policies require true separation.
Implementation Recommendations
Use a single 10TB StorageBox unless specific requirements demand separation. Create two gocryptfs-encrypted directories within that box, one for Nextcloud/Immich and one for other data. Each gets its own mount point and encryption key.
Test Immich performance with a representative photo library subset before full migration. Monitor thumbnail generation time and upload speeds. Small-file workloads reveal performance issues that bulk transfers hide.
Keep all metadata, databases, cache directories, and lock files on local NVMe. Map out exactly which directories remain local before starting the migration.
Establish a backup routine separate from the StorageBox. Even a smaller second StorageBox with snapshot-based backups using Borg or rclone provides recovery options for user error and corruption.
Document where gocryptfs keys are stored and what threat model the encryption addresses. If keys live on the local system, the encryption protects data in transit and at rest on Hetzner infrastructure but not against physical server compromise.
Example Setup
For an example, the server is connecting to a Storagebox via CIFS, this part is as usual, the encryption happens in the filesystem itself, not the mount point. Here, a mountpoint /mnt/backups is created and connects to smb://storagebox/backups
The Storagebox details are given in the Hetzner Console:
Username: u648764-sub1
SMB/CIFS Share: \\u648764-sub1.your-storagebox.de\u648764-sub1A complex password is setup through the Hetzner Console, too. In this case, CIFS is being used, all other protocols are disabled.
Install the prerequisite packages:
sudo apt install -y cifs-utils gocryptfsAs usual, create a mountpoint plus a mountpoint for the encrypted content:
sudo mkdir -p /mnt/backups
sudo mkdir -p /mnt/backups_rawCreate a secure file for the gocryptfs key:
sudo mkdir -p /opt/storagebox
sudo touch /opt/storagebox/gocryptfs.key
sudo chmod 600 /opt/storagebox/gocryptfs.key
sudo nano /opt/storagebox/gocryptfs.keyThe file contains only the key or passphrase you will use to encrypt the folders. All on one line, no quotes, just the exact key.
root@server ~ # cat /opt/storagebox/gocryptfs.key
dfgkljsdfghkjsairhgjaerpCreate a secure file for the CIFS details:
sudo mkdir -p /opt/storagebox
sudo touch /opt/storagebox/backups.creds
sudo chmod 600 /opt/storagebox/backups.creds
sudo nano /opt/storagebox/backups.credsThis file contains the CIFS credentials to connect to the share:
root@server ~ # cat /opt/storagebox/backups.creds
username=u648764-sub1
password=thePasswordYouChoseWhenYoutSetupTheStorageboxThe fstab file needs to be updated, first, it needs to mount the cifs share:
//u648764-sub1.your-storagebox.de/u648764-sub1 /mnt/backups_raw cifs nofail,credentials=/opt/storagebox/backups.creds,vers=3.1.1,iocharset=utf8,rw,uid=0,gid=0,file_mode=0770,dir_mode=0770,nobrl,_netdev 0 0If there is already data there (or data is copied there in the future), it can be viewed in the encrypted format:
root@server ~ # ls -al /mnt/backups_raw
total 8
drwxrwx--- 2 root root 0 Aug 31 01:02 .
drwxr-xr-x 5 root root 4096 Sep 2 21:21 ..
drwxrwx--- 2 root root 0 Aug 6 13:44 H-JOCC1SJ78E_ycb1DrFeA
drwxrwx--- 2 root root 0 Aug 23 18:12 H9caa4a4S-jToOUKjUUq-Q
drwxrwx--- 2 root root 0 Jul 15 16:08 J1bMdyJJlOEJxTZBt7DcUQ
drwxrwx--- 2 root root 0 Aug 10 20:00 S7SHnQGFCP63rC6KZ5xl9Q
drwxrwx--- 2 root root 0 Aug 2 20:00 SlmRQEYUWYuaHiwuHEtGkg
drwxrwx--- 2 root root 0 Aug 23 18:12 bQoaz2138ml5qJoOBsS-rA
-r-xr-x--- 1 root root 385 Aug 11 09:50 gocryptfs.conf
-r-xr-x--- 1 root root 16 Aug 11 09:50 gocryptfs.dirivThe mount folder needs to opened with gocryptfs, add another line in the /etc/fstab file:
/mnt/backups_raw /mnt/backups fuse./usr/bin/gocryptfs nofail,passfile=/opt/storagebox/gocryptfs.key,x-systemd.requires-mounts-for=/mnt/backups_raw 0 0The decrypted folder is now available with 770 permissions (as specified in the fstab file):
root@server ~ # ls -al /mnt/backups
total 4
drwxrwx--- 2 root root 0 Aug 31 01:02 .
drwxr-xr-x 5 root root 4096 Sep 2 21:21 ..
drwxrwx--- 2 root root 0 Jul 15 16:08 29
drwxrwx--- 2 root root 0 Jul 22 09:06 30
...Any of the variables or locations above can be changed to suit the purpose. The backups folder should be in another region, but there is a performance hit, so maybe the backup needs to be staged or another method of managing bandwidth and throughput can be tested or developed.
Summary
Moving from a single unencrypted drive to StorageBox with gocryptfs trades raw compute cost for redundancy and encryption.
The primary risks are gocryptfs performance over the network for small-file workloads and lack of backup beyond redundancy. Testing Immich workload performance and establishing separate backup procedures address these risks. Using a single consolidated StorageBox with separate encrypted subdirectories reduces costs compared to multiple boxes.
AI assistance is used on this site for language, formatting, and turning research into a consistent template. It is not used to perform the underlying research or verify technical claims. Every command, configuration, and step in this post is tested by hand before publication.