Encrypt pages at rest with a key per person
Pages are sealed with AES-256-GCM. Each person's key is derived (HKDF) from a master key in the settings file plus their Authentik issuer and subject. Plain files from earlier versions are read and re-saved encrypted. Mako refuses to open a notebook it cannot decrypt rather than overwrite it. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e3147597e8
commit
9f2fe4a416
11 files changed
+396
-33
No files matched your search
@@ -2,7 +2,7 @@
|
||||
|
||||
A private notebook in the spirit of Obsidian and Notion, for people who would rather run their own.
|
||||
Pages that nest inside each other, `[[links]]` between them with backlinks, a journal page for each
|
||||
day, tags, and quick search, all kept as plain markdown files. One small binary, no database, no
|
||||
day, tags, and quick search, all kept as encrypted markdown files. One small binary, no database, no
|
||||
dependencies. You sign in with **Authentik** and nothing else: there are no passwords in Mako.
|
||||
|
||||
Named for the mako shark, the fastest in the sea, because a notebook should keep up with you.
|
||||
@@ -116,23 +116,42 @@ written to it:
|
||||
| `oidc.client_id` | `MAKO_OIDC_CLIENT_ID` | |
|
||||
| `oidc.client_secret` | `MAKO_OIDC_CLIENT_SECRET` | |
|
||||
| `allowed` | `MAKO_ALLOWED` | optional; emails, usernames or Authentik ids, comma separated |
|
||||
| `key` | `MAKO_KEY` | encrypts your pages; made for you, see Encryption below |
|
||||
| `listen` | `MAKO_LISTEN` | default `127.0.0.1:8490` |
|
||||
| `data_dir` | `MAKO_DATA` | default `data` |
|
||||
|
||||
`mako.json` also holds a `secret` that signs session cookies. It is made on first run and written
|
||||
with mode `0600`. Changing it signs everyone out.
|
||||
|
||||
## Encryption
|
||||
|
||||
Every page is encrypted on disk with AES-256-GCM. Each person has a key of their own, made from the
|
||||
`key` in `mako.json` together with who they are in Authentik (the issuer and their subject id). So one
|
||||
person's files cannot be opened with another's key, and a file copied over another page's name stops
|
||||
opening. Pages are decrypted in the server's memory while it runs, and your downloads are plain
|
||||
markdown.
|
||||
|
||||
- **The key is made on first run** and written to `mako.json` (mode `0600`), or set `MAKO_KEY` (at least
|
||||
32 characters, for example `openssl rand -base64 32`) to keep it out of the file.
|
||||
- **Back the key up, apart from the notes.** Without it the pages cannot be read, and Mako refuses to
|
||||
start a notebook it cannot decrypt rather than overwrite it. Do not change it. Unlike `secret`,
|
||||
changing `key` does not just sign people out.
|
||||
- **What it protects:** a stolen disk or backup of `data/`, and anyone who can read the notes folder but
|
||||
not the settings. **What it does not:** someone who controls the running server, or who can read both
|
||||
`mako.json` and `data/`. Who you are in Authentik is not secret, so it cannot be the key by itself.
|
||||
- **Upgrading from 0.1.0:** existing plain files are read and saved again encrypted the first time
|
||||
that person signs in, and a `key` is added to your settings file.
|
||||
|
||||
## Where your notes are
|
||||
|
||||
```
|
||||
data/users/<hash of who you are>/
|
||||
owner.txt your name and email, so the folder can be matched to a person
|
||||
notes/20261031-143205-a1b2c3.md one file per page
|
||||
notes/daily-2026-10-31.md the journal page for a day
|
||||
notes/20261031-143205-a1b2c3 one encrypted file per page (named .md)
|
||||
notes/daily-2026-10-31 the journal page for a day
|
||||
trash/ deleted pages, until the trash is emptied
|
||||
```
|
||||
|
||||
A page file looks like this, so you can edit it with anything:
|
||||
Inside, a page is markdown with a small header (shown here decrypted, and what the zip export holds):
|
||||
|
||||
```
|
||||
---
|
||||
@@ -146,8 +165,8 @@ pinned: true
|
||||
Flights and hotels, see [[Packing list]] #travel
|
||||
```
|
||||
|
||||
A plain `.md` file dropped into `notes/` is picked up too, with its file time as its date (name it with
|
||||
lower-case letters, numbers and dashes). Restart Mako to see files added by hand.
|
||||
A plain `.md` file dropped into `notes/` is picked up when that person's notebook next opens, with its
|
||||
file time as its date, and is then encrypted (name it with lower-case letters, numbers and dashes).
|
||||
|
||||
## Security notes
|
||||
|
||||
@@ -161,7 +180,8 @@ lower-case letters, numbers and dashes). Restart Mako to see files added by hand
|
||||
person's requests can only ever reach their own folder.
|
||||
- Every change from the browser needs a header a page on another site can't send. The page has a strict
|
||||
Content-Security-Policy, and pages are never rendered as HTML.
|
||||
- Pages are **not encrypted** on disk. Anyone who can read the server's disk can read them.
|
||||
- Pages are encrypted on disk (see Encryption), with a key per person. The server itself, while it
|
||||
runs, can read them: this is not end-to-end encryption.
|
||||
|
||||
## Honest limits
|
||||
|
||||
|
||||
Reference in new issue
Block a user