Notyx logo

A self-hosted, zero-knowledge, secure PHP alternative to Obsidian.

Your notes, in your browser, on your server β€” every byte encrypted with AES-256 using a key only you know. No database, no cloud, no build step, no tracking.



What is Notyx?

Notyx is a single-folder PHP application that gives you an Obsidian-style Markdown notebook you fully own and host yourself. It looks and feels like Obsidian β€” a file tree, folders, a live-preview Markdown editor β€” but every note is stored on disk as an encrypted .md.enc file, and the encryption key is derived directly from your password and never stored anywhere.

If someone copies your data/ folder, they get nothing but ciphertext. Lose the password and even you can't recover the notes β€” that's the point.

TL;DR: Obsidian's writing experience + a zero-knowledge encrypted vault, running on plain PHP you can drop on any cheap shared host.


✨ Features

Writing

  • Obsidian-style Live Preview editor built on CodeMirror 6 β€” Markdown syntax characters (#, **, `, >, links…) are hidden and rendered inline, and revealed again only on the line your cursor is on.
  • GitHub-Flavored Markdown: tables, task lists, strikethrough.
  • Read mode with full Markdown rendering (via marked).
  • Graceful fallback β€” if the CDN that serves CodeMirror is unreachable, the editor degrades to a plain Markdown textarea and keeps working offline.
  • Autosave with a configurable debounce interval, plus Ctrl/Cmd + S to save on demand.

Organization

  • Nested folders and a collapsible file tree, just like a vault.
  • Note name = file name (Obsidian convention).
  • Full-text search across note titles.
  • Drag-and-drop import of existing .md / .markdown / .txt files (bulk import never overwrites β€” duplicates get a numeric suffix).
  • Right-click context menu: new note, new subfolder, rename, delete.

Security & privacy

  • Zero-knowledge AES-256 encryption. Notes are encrypted with AES-256-CBC using Encrypt-then-MAC (HMAC-SHA256) for tamper detection.
  • Your password is the key. It is run through PBKDF2-SHA256 (200,000 iterations) to derive the encryption + MAC keys. No password hash, no verification blob, and no per-file salt is ever written to disk.
  • Nothing to steal at rest. The data/ folder holds only opaque ciphertext.
  • Change password re-encrypts every note with the new key in a safe two-pass operation (decrypt all β†’ write all).
  • Hardened sessions: the derived key lives only in the PHP session for the session's lifetime (8 h by default); HttpOnly, SameSite=Strict, strict-mode cookies.
  • Defense in depth: .htaccess denies direct web access to data/, path-traversal is blocked server-side, and responses send X-Content-Type-Options: nosniff.

Self-hosting

  • No database. No Composer. No Node build. Just PHP files.
  • 5 built-in languages: English, Π£ΠΊΡ€Π°Ρ—Π½ΡΡŒΠΊΠ°, PortuguΓͺs, EspaΓ±ol, Deutsch.
  • Drops into any PHP 8.1+ web root and runs.

πŸš€ Installation

Requirements

  • PHP 8.1+ with the OpenSSL extension enabled (bundled in most builds).
  • A web server (Apache with .htaccess support, or nginx with an equivalent deny rule for data/).
  • A writable data/ directory.
  • (Optional) Outbound internet access on the client for the CodeMirror / marked CDN β€” without it the app falls back to the plain-textarea editor.

Steps

# 1. Clone into your web root
git clone https://github.com/<you>/notyx.git
cd notyx

# 2. Make sure PHP can write the data directory
chmod 700 data        # the app also creates it automatically

# 3. Point your web server at this folder, then open it in a browser

On first visit you'll be asked to create a vault password. That password becomes your encryption key β€” choose a strong one and don't lose it.

Local quick start (PHP built-in server)

php -S localhost:8000
# open http://localhost:8000

⚠️ The built-in server ignores .htaccess. Use it only for local testing; for anything exposed to a network, serve behind Apache/nginx so data/ is protected.


βš™οΈ Configuration

All settings live in config.php:

Constant Default Description
DATA_DIR ./data Where encrypted notes are stored.
CIPHER aes-256-cbc OpenSSL cipher.
PBKDF2_ITERATIONS 200000 Key-derivation cost.
KDF_SALT Notyx::static-kdf-salt::v1 In-code KDF salt β€” change this to a unique random string before creating your first note (see Security notes).
AUTOSAVE_SEC 0.8 Autosave debounce (seconds). Editable from the in-app Settings.
SESSION_LIFETIME 28800 (8 h) Session validity window.

The autosave interval can also be changed at runtime from βš™ Settings, which rewrites the value in config.php.


πŸ” Security model

Notyx is zero-knowledge by design:

  1. You type a password. It is stretched with PBKDF2-SHA256 (200k iterations) into 64 bytes of key material β€” 32 bytes for AES-256, 32 bytes for HMAC.
  2. Each note is stored as [IV (16B)][HMAC-SHA256 (32B)][ciphertext].
  3. On unlock, Notyx verifies the password by trial-decrypting the first note and checking the MAC. An empty vault accepts any password (it becomes the key for the notes you create).
  4. The key exists only in the server-side session while you're logged in. The password and key are never written to disk.

Notes & caveats (please read)

  • The KDF_SALT is a constant in config.php, not a secret stored per install. For best results, replace it with your own random value before creating any notes. Once notes exist, changing it would make them unreadable (use Change password to re-key instead).
  • Lose the password = lose the data. There is no recovery, by design.
  • No login rate-limiting is built in β€” use a strong password and/or put the app behind your server's auth / fail2ban if it's internet-facing.
  • The Markdown read view renders raw HTML in your notes. Since you author your own notes this is normally fine, but don't paste untrusted HTML and then open it in Read mode.
  • For anything public, serve over HTTPS so the password isn't sent in the clear.

πŸ—‚οΈ Project structure

notyx/
β”œβ”€β”€ index.php           # App shell: login screen + editor UI
β”œβ”€β”€ api.php             # JSON API (status, login, CRUD, change password, settings)
β”œβ”€β”€ config.php          # All configuration constants
β”œβ”€β”€ lib/
β”‚   β”œβ”€β”€ Auth.php        # Passwordβ†’key login, session, change-password re-encrypt
β”‚   β”œβ”€β”€ Crypto.php      # AES-256-CBC + Encrypt-then-MAC (HMAC-SHA256)
β”‚   β”œβ”€β”€ Notes.php       # Encrypted note/folder storage on the filesystem
β”‚   β”œβ”€β”€ Settings.php    # Persists autosave interval back into config.php
β”‚   └── I18n.php        # Tiny translation helper
β”œβ”€β”€ lang/               # en Β· uk Β· pt Β· es Β· de
β”œβ”€β”€ assets/
β”‚   β”œβ”€β”€ app.js          # Client logic (tree, tabs, autosave, API calls)
β”‚   β”œβ”€β”€ editor.js       # CodeMirror 6 Live Preview editor
β”‚   β”œβ”€β”€ style.css       # Obsidian-like dark theme
β”‚   └── favicon.svg     # Brand mark
└── data/               # Encrypted *.md.enc notes (web-access denied)

πŸ› οΈ Tech stack

  • Backend: plain PHP 8.1+ (no framework, no dependencies), OpenSSL.
  • Editor: CodeMirror 6 (loaded as ESM from a CDN) with a custom Live-Preview decoration layer; marked for read mode.
  • Storage: the filesystem β€” one encrypted file per note.
  • No database, no build pipeline.

πŸ“œ License

MIT license


Notyx β€” own your notes. Encrypt everything. Host it yourself.