Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
This PR introduces optional, compile-time support for Encryption at Rest for SQLite databases by integrating SQLCipher. This provides a robust security enhancement for self-hosted instances, protecting data from unauthorized filesystem access.
This feature is opt-in and must be enabled at build time using the
memos_sqlcipherbuild tag.Documentation, including enabling encryption and migrating existing data has been added to the README. More documentation is written at the end of this PR description. I'm still a bit unsure about the doc site.
Note that:
Relevant Issues:
Motivation
Currently, Memos' SQLite database is stored as a plaintext db file on disk. If a server's filesystem is compromised or the database file is inadvertently exposed (like a backup leak or cloud providers), all user data is at risk. By implementing full-database encryption, we can mitigate this risk, ensuring that the data remains secure even if the database file is stolen.
Implementation Details
modernc.org/sqlitedriver with the CGo-basedgit.colasdn.top/mattn/go-sqlite3to enable linking against the SQLCipher C library.memos_sqlcipherbuild tag. Users who don't need encryption can continue to build Memos without CGo dependencies.Dockerfilehas been updated to support building an encryption-ready image. It correctly handles build-time (sqlcipher-dev) and runtime (sqlcipher-libs) dependencies.--sqlite-encryption-keycommand-line flag or theMEMOS_SQLITE_ENCRYPTION_KEYenvironment variable.How to Use (Docker Example)
Build the Image:
Run the Container:
Migrating an Existing Database
Users can encrypt an existing SQLite database without installing additional tools on the host by leveraging the SQLCipher-enabled Docker image.
Migration Steps:
memos_prod.db(and any-wal/-shmfiles).memos-sqlcipher).mv memos_prod.db memos_prod.db.plaintext && mv memos_encrypted.db memos_prod.db && rm -f memos_prod.db-wal memos_prod.db-shm).MEMOS_SQLITE_ENCRYPTION_KEY(or the CLI flag).Important Notes
Notes for Reviewers
modernc.org/sqlite). CGO is only required when consumers compile with-tags memos_sqlcipher. Reviewer should verify this does not affect existing release pipelines.libsqlcipher/libsqlite3. Docker packaging now installs these libraries and symlinks them appropriately; downstream packagers will need similar tooling if they ship their own binaries.go-sqlite3inclusion:github.com/mattn/go-sqlite3is now ingo.mod. Although only pulled in under the SQLCipher tag, this increases the module graph; ensure this is acceptable for distribution.More Documentation
Database Encryption with SQLCipher
Memos now supports transparent, full-database encryption for SQLite using the integrated SQLCipher library. This feature provides robust Encryption at Rest for your data.
What It Is and What It Protects
Encryption at Rest means your database file (e.g.,
memos_prod.db) is fully encrypted on the disk. Without the correct key, its contents are unreadable.This protects you from:
How to Enable Encryption
Enabling encryption is a two-step process: building Memos with the correct build tag and providing the encryption key at runtime.
Step 1: Build Memos with SQLCipher Support
You must compile a version of Memos that includes SQLCipher support using the
memos_sqlcipherbuild tag.Using Docker (Recommended)
This is the simplest and recommended method. From the project root, build a SQLCipher-enabled Docker image:
Building from Source
sqlcipher-devorlibsqlcipher-devel.CGO_ENABLED=1 go build -tags="memos_sqlcipher libsqlite3 sqlite_omit_load_extension" -o memos ./bin/memos/main.goStep 2: Provide the Encryption Key at Runtime
You must provide your encryption key when starting the Memos server.
Using Docker
Pass the key as an environment variable in your
docker runcommand:Using the Binary
Pass the key as a command-line flag or as an environment variable:
Key Management and Security
Migrating an Existing Database
To encrypt an existing, unencrypted Memos database, you must use the
sqlciphercommand-line tool.Stop your Memos service.
Back up your original database file! This is critical.
Install the
sqlciphercommand-line tool.# On Debian/Ubuntu sudo apt-get install -y sqlcipherPerform the encryption process:
Replace the old database file with the new encrypted one:
You can now start your Memos service with the encryption key, and it will read the newly encrypted database.
FAQ
Can I change the encryption key?
Yes. Open your encrypted database with the
sqlciphercommand-line tool and runPRAGMA rekey = 'new-secret-key';.What is the performance impact?
SQLCipher is highly optimized. The performance impact is generally minimal and should be negligible for most operations. The main overhead occurs when the database connection is first opened and during heavy write operations.