VYLKDocs
Install and use Vylk.
VYLK is a single-user Markdown editor. Run it on your computer and open it in a browser.
First run
Install VYLK, then start it with your chosen password. Open localhost:8080 and sign in.
Markdown notes default to ./notes and the SQLite database to ./vylk.db, relative to VYLK's startup directory. Keep VYLK running while using the app.
Install VYLK
Ubuntu or Debian
Add the shared Toxdes repository once:
sudo apt update && sudo apt install -y ca-certificates curl gnupg && curl -fsSL https://packages.toxdes.com/apt/pubkey.gpg | sudo gpg --dearmor --yes -o /usr/share/keyrings/toxdes-archive-keyring.gpg && echo "deb [signed-by=/usr/share/keyrings/toxdes-archive-keyring.gpg] https://packages.toxdes.com/apt stable main" | sudo tee /etc/apt/sources.list.d/toxdes.list && sudo apt updatesudo apt install vylkVYLK_PASSWORD='replace-with-your-password' vylkUpdate: run sudo apt update && sudo apt upgrade vylk, then restart VYLK.
Fedora
Add the shared Toxdes repository once:
printf '%s\n' '[toxdes]' 'name=Toxdes' 'baseurl=https://packages.toxdes.com/rpm' 'enabled=1' 'gpgcheck=1' 'repo_gpgcheck=1' 'gpgkey=https://packages.toxdes.com/rpm/pubkey.gpg' | sudo tee /etc/yum.repos.d/toxdes.reposudo dnf install vylkVYLK_PASSWORD='replace-with-your-password' vylkUpdate: run sudo dnf upgrade vylk, then restart VYLK.
Arch Linux (AUR)
yay -S vylk-binVYLK_PASSWORD='replace-with-your-password' vylkFor current source: yay -S vylk-git.
Update: run yay -Syu vylk-bin, then restart VYLK.
Standalone binary
Download your processor’s archive and put the binary on your PATH.
Download v3.1.1 - AMD64Download v3.1.1 - ARM64
curl -fsSL https://packages.toxdes.com/releases/vylk_3.1.1_amd64.tar.gz | sudo tar xzC /VYLK_PASSWORD='replace-with-your-password' vylkUpdate: download the newer archive, replace the binary, and restart VYLK. Your notes and database stay where they are.
Docker
Linux AMD64 and ARM64. Notes and database are stored in vylk-data.
docker run -d --name vylk -p 127.0.0.1:8080:8080 -e VYLK_PASSWORD='replace-with-your-password' -v vylk-data:/data toxdes/vylk:{version}Open localhost:8080 after the container starts.
Update: pull the new image, remove the container, then run the same command again with the volume unchanged.
Build from source
Requires Git and the Go version declared in the application's go.mod.
git clone https://github.com/toxdes/vylk.git && cd vylkgo build -trimpath -ldflags="-s -w -X vylk/internal/server.version=$(cat VERSION)" -o vylk ./cmd/vylkVYLK_PASSWORD='replace-with-your-password' ./vylkUpdate: pull the latest source, rebuild the binary, and restart the process.
Windows binary
Download the executable and open PowerShell in its folder.
Download v3.1.1 - Windows AMD64
$env:VYLK_PASSWORD="replace-with-your-password".\vylk_windows_amd64_{version}.exeUpdate: download the newer executable, replace the file in the same folder, and start it again. Keep the notes folder and vylk.db file.
Docker
Notes and database are stored in vylk-data.
docker run -d --name vylk -p 127.0.0.1:8080:8080 -e VYLK_PASSWORD='replace-with-your-password' -v vylk-data:/data toxdes/vylk:{version}Update: pull the new image, remove the container, and run the same command again with vylk-data unchanged.
Homebrew
brew install toxdes/tap/vylkUpdate: run brew update && brew upgrade vylk.
macOS binary
Download and extract the ZIP, then start VYLK from Terminal.
Download v3.1.1 - IntelDownload v3.1.1 - Apple Silicon
VYLK_PASSWORD='replace-with-your-password' ./vylkUpdate: download the newer ZIP, replace the binary, and restart VYLK. Keep your notes folder and database.
Docker
Notes and database are stored in vylk-data.
docker run -d --name vylk -p 127.0.0.1:8080:8080 -e VYLK_PASSWORD='replace-with-your-password' -v vylk-data:/data toxdes/vylk:{version}Update: pull the new image, remove the container, and run the same command again with vylk-data unchanged.
Build from source
Requires Git and the Go version in go.mod.
git clone https://github.com/toxdes/vylk.git && cd vylkgo build -trimpath -ldflags="-s -w -X vylk/internal/server.version=$(cat VERSION)" -o vylk ./cmd/vylkVYLK_PASSWORD='replace-with-your-password' ./vylkUpdate: pull the latest source, rebuild the binary, and restart it.
Write and customize
Markdown and live preview
Write Markdown or use the toolbar. Live preview shows the result beside your text; cursor-position highlighting connects the two.
Zen writing
Zen renders completed bold, italic, strikethrough, inline code, and Markdown links as you type. Unfinished syntax stays as typed. Select text for the compact toolbar; notes remain Markdown.
Click a rendered link and choose Edit link to change its URL. Apply an empty URL to remove the link but keep its label; click away to cancel. Switch to Write or Split to inspect the source.
Writing and reading views
Choose editor-only, preview-only, resizable Split, or distraction-free Zen. Switching views focuses the visible pane. Cursor-following and selection scrolling stay gradual; Preferences sections switch instantly, and dialogs follow your motion setting.
Interactive preview
In the preview, check tasks, edit Markdown blocks, or drag them into order. On mobile, selected blocks show a fixed action tray.
Preferences
Set themes, fonts, page width, autosave, toolbar and Save button visibility, and your starting view. Appearance → Reduce motion can follow your system, always reduce motion, or never reduce it.
Keyboard shortcuts
In the editor: Ctrl+1 opens Write, Ctrl+2 Preview, Ctrl+3 Split, and Ctrl+4 Zen. On macOS, use Command. Customize keys in Preferences → Shortcuts; sequences default to the Ctrl+E prefix.
Encryption: setup and recovery.
First-run defaults
New accounts start in Write, with interactive preview, toolbar, and autosave on; manual Save button hidden. Zen: Inter at 125%, with title, word count, and view switcher visible. Upgrades keep saved preferences.
Offline use and sync
Sign in online once per device. Install VYLK as a PWA if supported. The installed app caches its shell and notes; offline edits and deletions wait in browser IndexedDB and sync when you reconnect.
Connection details
While open, an authenticated event stream watches for changes. A 25-second heartbeat updates Online/Offline status; 70 seconds without one means offline. On reconnect, VYLK reconciles the full cache before replaying local work.
When two devices edit one note, VYLK attempts a three-way merge. Separate line edits and one-sided title or tag changes merge automatically. Ambiguous overlaps open a conflict resolver that keeps both versions and lets you edit the result.
Sign-out retains cached notes and pending edits for your next sign-in. Without encryption, browser storage stays plaintext; signing out does not erase it. With encryption, notes and queued edits stay encrypted and the remembered key is forgotten. Offline Sign out locks this browser but cannot revoke its server session.
- Saving: waiting for server acknowledgement.
- Saved: changes reached the server.
- Offline: edits remain on this device until reconnection.
Do not clear browser storage with pending work.
If the server database changes
Sync pauses. Choose:
- Keep changes preserves local work. Restore the previous matching database and notes directory, then reload.
- Switch permanently discards this browser’s cached notes and pending edits, loads the replacement, and requires sign-in.
An older backup of the same database keeps its identity; this check cannot detect rollback.
End-to-end encryption
Encryption is optional. Your browser encrypts titles, tags, bodies, and pending offline edits before sending or storing them. The server holds ciphertext and wrapped keys, never your passphrase or recovery words.
HTTPS first
Use HTTPS or http://localhost:8080 on the host. Browser cryptography requires a secure context. Plain HTTP on a LAN IP does not qualify, even on a trusted network.
If login says encryption requires HTTPS, use the HTTPS address with a trusted certificate, or localhost on the host. Already signed-in insecure pages return to login with this notice; bypassing it cannot enable browser cryptography.
Enable encryption
- Back up
VYLK_DBandVYLK_DIRtogether. Sign in with the server password; open Preferences → Encryption. - Choose a passphrase. Download or write down the numbered 24-word recovery key; store it safely, separate from the server.
- With the original list hidden, confirm all 24 words individually and acknowledge the access-loss warning. Bulk paste is disabled to encourage a separate recovery copy.
- Keep setup open while VYLK encrypts and verifies notes, converts local offline edits, and switches server storage. Note writes pause during conversion.
- Restart the server to release plaintext from the old process's memory. Update and unlock other devices to convert their local caches.
To resume an interrupted conversion, reopen setup with the original server password, vault passphrase, and recovery key. Unopened devices may still hold plaintext caches.
Passphrase and recovery key
After conversion, sign in and unlock with your passphrase or recovery key; VYLK_PASSWORD no longer unlocks notes. Recovery downloads use vylk-recovery-key-YYYYMMDDHHMM.txt. Anyone with the key can unlock your vault: protect it like a password.
In Preferences → Encryption, verify your current passphrase or recovery key to change either. Passphrase changes offer Sign out other devices, on by default. Replacing the recovery key revokes other sessions. This browser signs in again automatically.
If you lose both the passphrase and recovery key, VYLK cannot recover your notes—even from a backup. Retaining VYLK_PASSWORD permits a destructive reset to an empty vault. Old ciphertext is archived for 30 days on the server; unlocking it still requires the original secret.
Remembered browsers and devices
Sign-in remembers a non-extractable browser key across tabs, refreshes, updates, and later visits while server access stays valid. Anyone using that browser profile can read cached notes. Sign out on shared devices: this forgets the key but keeps encrypted pending edits for your next unlock.
Preferences → Account → Devices treats each browser profile, including its tabs, as one device. Signing it out revokes its server sessions; offline devices learn this when reconnecting. Revocation cannot erase their cached notes or existing keys.
What encryption does and does not cover
Argon2id derives a passphrase wrapping key; a random vault key encrypts notes with AES-256-GCM. The server still sees IDs, revisions, timestamps, pins, preferences, and sync activity. Search, tag filtering, and conflict resolution run on unlocked devices.
Use HTTPS and a trusted deployment. A compromised server can replace the app to steal secrets at unlock or use a remembered key on your next visit. Encryption cannot detect replayed older valid ciphertext. Changing a passphrase or recovery key rewraps the same vault key; it does not revoke a key or old wrapped-key copy already stolen.
Backups and safety
Without encryption, notes are Markdown files; SQLite holds their metadata. With encryption, the server stores encrypted note bodies, titles, and tags. Stop VYLK and copy VYLK_DB and VYLK_DIR together, or use a consistent backup method that captures both. Neither alone is a complete backup. Keep encrypted notes’ passphrase or recovery key separately. Restart with matching data and valid credentials to resume the instance.
Enabling encryption removes active plaintext storage and the temporary conversion backup. It cannot erase old external backups, SQLite migration snapshots, unopened browser caches, filesystem snapshots, or freed disk blocks. Review those copies under your backup policy.
Upgrading from server-side file encryption
Legacy server-side encryption and its settings have been removed. Before upgrading, export those notes as plaintext with the previous VYLK version; then optionally enable E2EE in the app. Removed settings or recognized encrypted files stop startup safely. The oldest ciphertext has no identifying header: removing settings does not decrypt it.
Migration backups
Before a pending database migration, VYLK saves a consistent SQLite snapshot beside the database. It retains the three newest *.pre-migration-*.db snapshots. Allow roughly one extra database-sized block of free space.
Connect another device
Use a desktop or mobile browser, or install the PWA.
VYLK listens on port 8080 by default. For an unencrypted instance, open the host's local IP address on a trusted network and allow the connection through its firewall. Plain HTTP exposes passwords and notes in transit.
Encrypted notes require HTTPS, even on a local network. A LAN address such as http://192.168.1.10:8080 is not a secure browser context and cannot unlock notes. HTTP on localhost or loopback works on the host. Encryption requirements.
Use an HTTPS reverse proxy with a certificate trusted by every device. VYLK neither serves HTTPS nor issues certificates. Service workers and PWA installation require HTTPS; localhost is exempt. The Docker examples bind to localhost: use your proxy to reach them from other devices.
Sign in online once per device before relying on offline access. Keep password protection enabled. Set VYLK_TRUST_PROXY=1 only when a trusted proxy supplies forwarding headers.
Configuration
Set environment variables before starting VYLK. For Docker or secret managers, VYLK_PASSWORD_FILE=/run/secrets/vylk_password reads the server password from a file. Enable encryption in the app; its passphrase and recovery key are not server settings.
| Variable | Default | Purpose |
|---|---|---|
| VYLK_PASSWORD | none | Required before encryption. Afterward, sign in with the vault passphrase or recovery key. Retaining this password permits a destructive reset to an empty vault; it cannot recover old notes. |
| VYLK_PASSWORD_FILE | unset | Read the initial server password from a secret file instead of an environment variable. |
| PORT | 8080 | HTTP listen port. |
| VYLK_DIR | ./notes | Directory for Markdown notes or encrypted note files. |
| VYLK_DB | ./vylk.db | SQLite database: metadata, sync state, and wrapped vault keys. Back up with the notes directory. |
| VYLK_APP_NAME | VYLK | App and PWA name for this server. Restart to apply. |
| VYLK_TRUST_PROXY | unset | Set to 1 only behind a trusted TLS-terminating proxy. |
| VYLK_REQUIRE_STRONG_PASSWORDS | false | Use true or 1 to require strong server passwords and have browsers enforce strong vault passphrases. |
| VYLK_DISABLE_VAULT_CHANGES | false | Use true or 1 for shared demos: block encryption setup, passphrase/recovery-key changes, vault reset, and device revocation at the API. Notes, sign-in, and existing encryption still work. |
| VYLK_NO_BROWSER | unset | Use 1 or --no-browser to skip the startup browser-opening attempt. |
| ARTIFICIAL_RTT_DELAY_MS | 0 | Request delay for development only; keep disabled in production. |
With VYLK_DISABLE_VAULT_CHANGES=true, encryption settings remain viewable. Startup refuses this setting during an unfinished encryption migration.
Local setup example
VYLK_PASSWORD=change-this PORT=8080 VYLK_DIR=./notes VYLK_DB=./vylk.db ./vylkBuild and test
Local binary, with version from VERSION:
go build -trimpath -ldflags="-s -w -X vylk/internal/server.version=$(cat VERSION)" -o vylk ./cmd/vylkAll supported binaries and platform archives:
./build.pyLinux packages and archives (Yesb):
./yesb/build_all.pyTests require the Go version in go.mod and Bun. Browser tests require Chrome or CHROME_PATH pointing to a compatible browser. Install dependencies and run:
bun cigo test ./...go tool staticcheck ./...bun run test:frontendbun run test:browser