cage (Client-side age Encryption) is a Nextcloud app that allows you to securely view and edit .age encrypted text files directly in the browser.
cage uses the standard age encryption format, so encrypted files remain portable and can be decrypted outside Nextcloud using the age CLI.
All encryption and decryption happens locally in the browser. The Nextcloud server only stores encrypted data and never sees plaintext.
cage is designed for text-based files such as notes, passwords, and configuration files. Support for Markdown editing is planned. Binary files are intentionally not supported.
- Client-side encryption/decryption using the age standard with the age-encryption npm package
- Passphrase-based encryption with scrypt key derivation
- No plaintext ever sent to the server
- Passphrase stored only in JavaScript runtime memory and cleared on lock
- Files remain compatible with the age CLI and other age tools
- Auto-generated mnemonic passphrases (EFF diceware)
- Custom passphrase support with strength estimation
- Auto-lock timer
.agetype integration in Nextcloud
- Multi-recipient encryption (X25519 keys)
- Markdown editor with rich text formatting
- FIDO2/WebAuthn support
- Nextcloud 31-32
- Modern browsers (Chrome, Firefox, Safari, Edge)
cage is designed with zero-trust principles:
- Client-side only: All encryption/decryption happens in client browser using the age-encryption
- No passphrase persistence: Passphrase is stored in a JavaScript variable only, cleared on page unload and auto-lock
- DOM cleanup: When the editor locks, decrypted content is removed from the DOM and in-memory state
- No telemetry: editor runs with no server extensions
(Coming soon)
-
Clone this repository into your Nextcloud
apps/directory:cd /path/to/nextcloud/apps git clone https://github.com/j-suchy/nextcloud-cage.git cage -
Install dependencies and build:
cd cage npm install npm run build -
Enable the app:
sudo -u www-data php occ app:enable cage
-
Configure settings in Settings → Administration → cage - Client-side age
- Click any
.agefile in Nextcloud Files - Enter your passphrase
- View/edit the decrypted content
- Save to re-encrypt and write back
- Click New → Encrypted file in the Files app
- Enter a filename (e.g., "passwords") -
.ageextension is added automatically - The file opens in cage and prompts for passphrase creation
- Choose to either:
- Generate a secure mnemonic passphrase (e.g.
carpet-bicycle-mountain-elephant-garden-violet) - Create your own custom passphrase
- Generate a secure mnemonic passphrase (e.g.
- Copy and save this passphrase securely (make sure you have your password secured)
- Confirm and the file is encrypted
- Start editing
Edit Mode:
- Click Edit button to enter edit mode
- Modify the plaintext content in the editor
- Click Save to re-encrypt and save changes
- Content is encrypted with your cached passphrase (in memory)
- Encrypted data is written back to the
.agefile - You remain in view mode after saving
Unsaved Changes Protection:
- If you try to close the editor with unsaved changes, you'll see a confirmation dialog
- If you try to lock with unsaved changes, you'll be warned that changes will be lost
- If you try to close/refresh the browser with unsaved changes, the browser will show a warning
Change Passphrase:
- Click Change Passphrase to re-encrypt the file with a new passphrase
- The file is automatically saved with the new encryption
- Your session continues with the new passphrase cached
- cage will automatically try to initialize any empty
.agefile with encryption when you first open it. - Saving always overwrites the encrypted file. Nextcloud file versioning may store previous encrypted versions.
After a configurable period of inactivity (default: 5 minutes):
- Passphrase is cleared from memory
- Decrypted content is removed from the DOM
- Lock screen appears
- Re-enter passphrase to continue
Configure these in Settings → Administration → Security → cage:
| Setting | Options | Default | Description |
|---|---|---|---|
| Auto-lock timeout | 1 / 5 / 15 / 30 / 0 (never) |
5 min |
Automatically lock after inactivity |
| Mnemonic word count | 6 / 7 / 8 |
6 |
Words in generated passphrases (6 words ≈ 77 bits) |
| Min passphrase strength | 0 / 30 / 50 / 70 bits |
50 |
Minimum entropy for custom passphrases |
- Backend: PHP (minimal — serves frontend, manages settings)
- Frontend: Vue
- Encryption: age-encryption (typage)
cage creates standard age-encrypted files compatible with the age CLI:
# Encrypt with age CLI
echo "secret" | age -p -o file.age
# Decrypt with age CLI
age -d file.age
# Open in cage (Nextcloud)
# Click file.age → enter same passphraseCage relies on age-encryption, no custom cryptography is implemented.
Trust in Nextcloud frontend: cage assumes the Nextcloud web interface has not been modified to include malicious JavaScript. If the Nextcloud instance is compromised or malicious apps inject scripts, decrypted data or passphrases could be exposed.
Because cage performs decryption in the browser:
- Malicious browser extensions may access decrypted content
- Even though cage clears sensitive data on lock, browser memory management is not fully controllable. In rare cases decrypted content may remain in memory until garbage collection occurs.
- Copying decrypted text to the clipboard may expose it to other applications or browser extensions.
- Compromised devices can capture passphrases
- Shared or public computers should not be used to decrypt sensitive files.
Always use a trusted browser environment.
- Use generated mnemonic passphrases
- Never "encrypt existing files" — if plaintext was on the server, it's in backups/versions/search index
- Only create new files through cage — start with encrypted files from the beginning
- Save passphrases securely — use a password manager or write them down offline
- Enable auto-lock — don't leave decrypted content in browser longer than needed
cage works only in a web browser. This is a limitation of Nextcloud mobile app, not cage itself.
Contributions are welcome!
Please do not open public issues for security vulnerabilities.
Clone the repository:
git clone https://github.com/j-suchy/nextcloud-cage.git cage
cd cage
npm installFor development:
npm run devFor production:
npm run buildThis project is licensed under the AGPL-3.0-or-later license. See LICENSE for details.
- age by Filippo Valsorda
- Typage (age-encryption npm package)
- EFF Diceware word list
This software is provided "as is" without warranty of any kind. Use at your own risk. Always back up your encrypted files and passphrases.
cage = Client-side Age Encryption