Skip to content

[Update] Nextcloud tutorial: Improved encryption architecture with key separation#1347

Merged
svenja11 merged 2 commits into
hetzneronline:masterfrom
JMoVS:master
Feb 6, 2026
Merged

[Update] Nextcloud tutorial: Improved encryption architecture with key separation#1347
svenja11 merged 2 commits into
hetzneronline:masterfrom
JMoVS:master

Conversation

@JMoVS

@JMoVS JMoVS commented Dec 24, 2025

Copy link
Copy Markdown
Contributor

Summary

This PR updates the Nextcloud tutorial with a significantly improved security architecture that separates encryption keys from encrypted data.

Problem with the previous approach

The original guide stored the entire Nextcloud data directory on the Storage Box, including the files_encryption folder containing encryption keys. This meant anyone with access to the Storage Box had both the encrypted files AND the keys to decrypt them.

New architecture

  • Encryption keys stay on the local LUKS-encrypted VPS disk
  • Encrypted files are stored on the Storage Box via per-user bind mounts
  • If the Storage Box is compromised, attackers get only encrypted blobs with no way to decrypt them

Changes in this PR

Security improvements

  • NEXTCLOUD_DATADIR now points to local Docker volume
  • Per-user bind mounts for files/, files_trashbin/, files_versions/, uploads/
  • Per-user files_encryption/ and cache/ folders remain local

Bug fixes

  • Fixed systemd mount unit: added DefaultDependencies=no to prevent ordering cycles
  • Added mount verification service to prevent Docker starting with unmounted directories

Updates

  • Debian 12 Bookworm → Debian 13 Trixie
  • Standardized on ext4 filesystem (simpler, VPS snapshots make btrfs redundant)

New sections

  • Architecture Overview explaining the security model
  • Step 10: Setting up per-user storage offloading
  • Step 11: Adding the mounts verification service
  • Migration guide for users of the previous version

Migration path

Existing users can follow the new "Migration from Previous Guide" section to move their encryption keys to the local disk while keeping their files on the Storage Box.

Testing

This architecture has been running in production with 120,000+ files across multiple users, surviving multiple reboots. But it should be tested again whether new setup and whether migration fully works. I have migrated mine and am happily running it like this for now

I have read and understood the Contributor's Certificate of Origin available at the end of
https://raw.githubusercontent.com/hetzneronline/community-content/master/tutorial-template.md
and I hereby certify that I meet the contribution criteria described in it.
Signed-off-by: Justin Scholz git@justinscholz.de

…d files

This update introduces a more secure architecture where Nextcloud encryption
keys remain on the local LUKS-encrypted disk while encrypted file content
is stored on the Storage Box via per-user bind mounts.

Changes:
- NEXTCLOUD_DATADIR now points to local Docker volume instead of SMB mount
- Per-user bind mounts offload only files/, files_trashbin/, files_versions/,
  and uploads/ to Storage Box
- Added systemd mount verification service to prevent startup with unmounted dirs
- Fixed systemd mount unit (added DefaultDependencies=no to prevent cycles)
- Updated from Debian 12 Bookworm to Debian 13 Trixie
- Standardized on ext4 filesystem
- Added migration guide for users of previous version

Security improvement: Storage Box compromise no longer exposes encryption keys.
@svenja11 svenja11 added Existing tutorial Changes on an existing tutorial review wanted Request a review labels Jan 12, 2026
@svenja11

Copy link
Copy Markdown
Collaborator

This is a very important security update you did there, thank you for that @JMoVS! 🚀

@svenja11 svenja11 added ready and removed review wanted Request a review labels Jan 16, 2026
@svenja11

Copy link
Copy Markdown
Collaborator

Can you please add the following comment in this pull request:

(Please replace YOUR NAME YOUR@EMAILPROVIDER.TLD with your actual information)

I have read and understood the Contributor's Certificate of Origin available at the end of
https://raw.githubusercontent.com/hetzneronline/community-content/master/tutorial-template.md
and I hereby certify that I meet the contribution criteria described in it.
Signed-off-by: YOUR NAME YOUR@EMAILPROVIDER.TLD

Once that is added, I will merge your changes.

@svenja11

svenja11 commented Feb 4, 2026

Copy link
Copy Markdown
Collaborator

I'm not sure if you saw my comment above because I forgot to mention you in it.

@JMoVS Can you please add the following comment in this pull request:

(Please replace YOUR NAME YOUR@EMAILPROVIDER.TLD with your actual information)

I have read and understood the Contributor's Certificate of Origin available at the end of
https://raw.githubusercontent.com/hetzneronline/community-content/master/tutorial-template.md
and I hereby certify that I meet the contribution criteria described in it.
Signed-off-by: YOUR NAME YOUR@EMAILPROVIDER.TLD

Once that is added, I will merge your changes.

@JMoVS

JMoVS commented Feb 4, 2026

Copy link
Copy Markdown
Contributor Author

I'm not sure if you saw my comment above because I forgot to mention you in it.

@JMoVS Can you please add the following comment in this pull request:

(Please replace YOUR NAME YOUR@EMAILPROVIDER.TLD with your actual information)

I have read and understood the Contributor's Certificate of Origin available at the end of
https://raw.githubusercontent.com/hetzneronline/community-content/master/tutorial-template.md
and I hereby certify that I meet the contribution criteria described in it.
Signed-off-by: YOUR NAME YOUR@EMAILPROVIDER.TLD

Once that is added, I will merge your changes.

Hi @svenja11

I'm not sure I understand. You linked to the "tutorial-template" - why would you want me to sign the tutorial-template?

@svenja11

svenja11 commented Feb 5, 2026

Copy link
Copy Markdown
Collaborator

Hi @JMoVS

Sorry if my wording was a bit confusing. What I meant was not to sign the tutorial template itself, but to add the entire Contributor’s Certificate of Origin block to the description of this pull request (as a comment in the PR description).

So basically edit the description of this PR and add the Contributor’s Certificate of Origin block at the top (with your own name and email).

Contributor’s Certificate of Origin block:

I have read and understood the Contributor's Certificate of Origin available at the end of
https://raw.githubusercontent.com/hetzneronline/community-content/master/tutorial-template.md
and I hereby certify that I meet the contribution criteria described in it.
Signed-off-by: YOUR NAME [YOUR@EMAILPROVIDER.TLD](mailto:YOUR@EMAILPROVIDER.TLD)

@JMoVS

JMoVS commented Feb 6, 2026

Copy link
Copy Markdown
Contributor Author

Hi @JMoVS

Sorry if my wording was a bit confusing. What I meant was not to sign the tutorial template itself, but to add the entire Contributor’s Certificate of Origin block to the description of this pull request (as a comment in the PR description).

So basically edit the description of this PR and add the Contributor’s Certificate of Origin block at the top (with your own name and email).

Contributor’s Certificate of Origin block:

I have read and understood the Contributor's Certificate of Origin available at the end of
https://raw.githubusercontent.com/hetzneronline/community-content/master/tutorial-template.md
and I hereby certify that I meet the contribution criteria described in it.
Signed-off-by: YOUR NAME [YOUR@EMAILPROVIDER.TLD](mailto:YOUR@EMAILPROVIDER.TLD)

Hi @svenja11,

I updated the description now. Thanks for the clarification!

@svenja11

svenja11 commented Feb 6, 2026

Copy link
Copy Markdown
Collaborator

Perfect, thank you for the update 🙂

@svenja11 svenja11 merged commit c4c5cc9 into hetzneronline:master Feb 6, 2026
1 check passed
@JMoVS

JMoVS commented Feb 9, 2026

Copy link
Copy Markdown
Contributor Author

@svenja11 One other comment: The published date still shows August last year - is that something that should have been updated?

@svenja11

Copy link
Copy Markdown
Collaborator

Thank you for pointing this out. That's fine, I'll update it with the next PR on this tutorial🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Existing tutorial Changes on an existing tutorial ready

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants