Self-Host Your Web Bookmarks With SQLite and Full Privacy
Self-hosting your bookmarks sounds like a weekend project for serious tinkerers, but it has become one of the most practical privacy decisions a developer or power user can make in 2026. Cloud bookmark services track what you save, when you save it, and what you read. Some sell that data. Others simply disappear - Delicious was sold multiple times before going dark for years. After Mozilla's 2024 layoffs, Pocket's future grew uncertain. When your reading list lives on someone else's server, you are always one acquisition away from losing it.
The good news: self-hosting a private bookmark manager is no longer painful. Tools like linkding, Shiori, Wallabag, Linkwarden, Karakeep, and Anansi give you a browser-friendly, searchable library of the references you care about - hosted locally or in infrastructure you control. No subscriptions. No tracking. No vendor lock-in.
This guide covers why self-hosted bookmark managers beat cloud alternatives on privacy, how SQLite makes them lightweight enough to run on a Raspberry Pi, and how to get linkding (the most popular choice in 2026) running in under ten minutes with Docker. I'll also compare the top open-source options so you can pick the one that fits your setup - including when Anansi's automatic multi-source capture (X + Reddit + GitHub + Web in one library) is the better fit than manual one-by-one saving.
Why Cloud Bookmarks Create a Privacy Problem
Most people don't think of their bookmark list as sensitive data. Stop and consider what it contains: every article you researched during a health scare, every job listing you quietly checked, every political long-read you saved before forming an opinion. That is a detailed portrait of your thoughts and intentions.
Cloud services profit from that portrait in several ways:
- Behavioural advertising. Services like the old Pocket share reading patterns with ad networks to build interest profiles linked to your browser fingerprint.
- Third-party analytics. Even "privacy-friendly" services often embed trackers from Google Analytics or Segment into their web apps.
- Data breach exposure. Centralised databases are high-value targets. A leaked bookmark list can reveal sensitive research habits.
- Account termination. Violate a vague terms-of-service clause and your entire archive vanishes overnight with no appeal.
The Electronic Frontier Foundation consistently recommends reducing reliance on cloud services for personal data. Self-hosting is the logical extension: if the server is in your home or on a VPS you control, there is no third party to subpoena, breach, or sell.
Why SQLite Powers the Best Self-Hosted Bookmark Managers
SQLite is not a toy database. It is the most widely deployed database engine in the world - embedded in every Android phone, every iOS device, every Firefox browser, and most desktop applications. The SQLite Consortium, whose members include Bloomberg, Mozilla, and the US Air Force, funds its long-term development and guarantees backward compatibility through at least 2050.
For a personal bookmark manager, SQLite wins for three practical reasons:
- Zero administration. The entire database is a single
.dbfile. Back it up withcp. Move it withscp. Inspect it with any SQLite GUI. No connection strings, no user accounts, no running daemon. - Low resource use. A linkding instance serving one user consumes roughly 50 MB of RAM - small enough to run alongside a dozen other services on a 2 GB VPS or a Raspberry Pi 4.
- Full-text search built in. SQLite's FTS5 extension powers instant search across titles, descriptions, and tags without any external search index.
The trade-off: SQLite handles one write at a time. For a personal or small-team bookmark manager with a handful of simultaneous users, this is never a bottleneck. If you are building a shared bookmark platform for hundreds of users, PostgreSQL is the better choice - but that is a different problem.
The Top Self-Hosted Bookmark Managers in 2026
Before committing to a setup, understand how the major open-source options compare:
| Tool | Backend DB | Docker | Browser Extension | Full-Text Search | Read-Later / Archive | Active in 2026 |
|---|---|---|---|---|---|---|
| linkding | SQLite | โ | โ Chrome, Firefox | โ FTS5 | โ (via SingleFile) | โ |
| Shiori | SQLite / PostgreSQL | โ | โ | โ | โ (page archiving) | โ |
| Wallabag | SQLite / MySQL / PostgreSQL | โ | โ | โ | โ (read-later focused) | โ |
| Linkwarden | PostgreSQL | โ | โ | โ | โ (screenshot + PDF) | โ |
| Karakeep | SQLite + Meilisearch | โ | โ | โ (AI tagging) | โ | โ |
| Anansi | SQLite / Cloudflare D1 | - (Bun local + Cloudflare Worker) | โ (Chrome/MV3) | โ (FTS5/BM25; optional semantic search) | - (aggregation focus, not archiver) | โ |
Linkding is my recommendation for anyone who wants the simplest possible setup. It is opinionated in the best way: one purpose, done well. The Docker image is under 100 MB, the interface loads in milliseconds, and the API is clean enough to automate.
Karakeep (rebranded from Hoarder in early 2025) is the right pick if you want AI-assisted tagging and a more visual interface. It uses Meilisearch as a search engine, which adds memory overhead but delivers relevance ranking that SQLite FTS5 alone cannot match.
Anansi is the right pick if your bookmarks are spread across social platforms and you want an AI coding agent to use them. That multi-source capture is its core advantage: linkding, Shiori, and Wallabag save one page at a time from the toolbar, while Anansi aggregates the saves you already make elsewhere into one searchable library you control. It is an open-source, local-first web memory for developers and agents. One Chrome/MV3 extension captures four shipped sources into the same SQLite library (FTS5/BM25 locally; D1 + R2 on the intended Cloudflare path, with optional semantic search and automatic tagging):
- X bookmarks - history import via page adapter + live saves as you bookmark.
- Reddit saves - history import + live saves via background session requests, without opening tabs.
- GitHub stars - full import + live star/unstar events. Extension-only: it reads the signed-in stars pages in your browser session, includes private repositories visible to that account, and needs no GitHub OAuth or personal access token.
- Web pages & Chrome bookmarks - toolbar, context-menu, and optional Chrome-bookmark mirroring, stored as Web items.
Imports are resumable with a persisted cursor, survive restarts and rate limits through queued capture and retry, and include a daily incremental catch-up for changes made while Chrome was closed. Anansi closes only tabs it created and asks for sign-in in the popup when a provider session is missing.
Privacy is bounded by design: no <all_urls>, no cookies permission, bearer-auth ingest. Its MCP server then exposes that unified library through eight read-focused tools for searching, retrieving, listing, and summarising saved references from clients such as Claude Code or Codex.
Anansi is not a replacement for Wallabag when you need a faithful offline copy of every article. Its strength is aggregation and retrieval: it brings scattered X / Reddit / GitHub / Web saves into one personal library and makes that library available to your development workflow.
TikTok capture is currently paused in the shipped extension while its authenticated path is being repaired, so it should not be chosen on the assumption that TikTok imports are active today.
Wallabag is the closest open-source equivalent to Pocket - built specifically for the read-later workflow, with article stripping, offline reading, and an e-reader-friendly interface. If your goal is reading, not just bookmarking, Wallabag wins.
Linkwarden targets teams. It supports collaborative collections, link health monitoring (checking whether saved URLs are still live), and PDF/screenshot archiving. It requires PostgreSQL, which adds operational complexity.
Shiori sits between linkding and Wallabag: it archives page content and supports multiple users, but it is lighter than Linkwarden and simpler to maintain than Wallabag's PHP stack.
For a developer building a personal knowledge base around saved technical content, I would choose Anansi when automatic multi-source capture and agent access matter more than full-page archiving - X bookmarks, Reddit saves, GitHub stars, and Web pages aggregated into one library with live capture plus resumable history imports, instead of saving each URL by hand. For a traditional, single-source bookmark server with a mature Docker workflow, linkding remains the simpler choice.
Setup: Pick Your Track
If you want single-source manual saving, follow Option A. If your saves are scattered across X, Reddit, GitHub, and the web and you want them aggregated automatically, skip to Option B.
Option A - Setting Up linkding With Docker in Under 10 Minutes
This is the fastest path to a working self-hosted bookmark manager. You need Docker and Docker Compose installed on your server or local machine.
Step 1 - Create the project directory and compose file
mkdir linkding && cd linkding
Create a file named docker-compose.yml:
version: "3"
services:
linkding:
image: sissbruecker/linkding:latest
container_name: linkding
ports:
- "9090:9090"
volumes:
- ./data:/etc/linkding/data
environment:
- LD_SUPERUSER_NAME=admin
- LD_SUPERUSER_PASSWORD=changeme
restart: unless-stopped
A few environment variables worth knowing:
| Variable | Purpose | Default |
|---|---|---|
LD_SUPERUSER_NAME |
Admin username created on first boot (none - required) | - |
LD_SUPERUSER_PASSWORD |
Admin password (none - required) | - |
LD_ENABLE_AUTH_PROXY |
Enable reverse-proxy auth (e.g. Authelia) | False |
LD_REQUEST_TIMEOUT |
HTTP request timeout in seconds | 60 |
LD_SERVER_PORT |
Internal port | 9090 |
Step 2 - Start the container
docker compose up -d
Linkding pulls its image (about 80 MB), creates the SQLite database at ./data/db.sqlite3, and starts serving on http://localhost:9090. First boot typically takes under 30 seconds.
Step 3 - Log in and install the browser extension
Open http://your-server-ip:9090 and log in with the credentials you set. Then:
- Navigate to Settings > Integrations and copy your API token.
- Install the linkding extension for Chrome or Firefox.
- Paste your server URL and API token into the extension settings.
You can now save any page with one click from your browser. Linkding fetches the page title, lets you add tags and a description, and stores everything locally in your SQLite file.
Step 4 - Back up your data
The entire state of your linkding instance lives in one file: ./data/db.sqlite3. Back it up daily with a cron job:
0 3 * * * cp /opt/linkding/data/db.sqlite3 /mnt/backup/linkding-$(date +\%Y\%m\%d).db
That is it. No pg_dump, no replication, no managed database service.
Here is a quick walkthrough of linkding in practice:
Option B - Setting Up Anansi for Multi-Source Capture
Use this when linkding's one-page-at-a-time saving is the bottleneck. Anansi does not replace manual saving with a nicer button - it removes it for the sources you already use: X bookmarks, Reddit saves, GitHub stars, and web pages land in one SQLite library automatically, then stay searchable for you and your AI agent.
Requirements: Bun 1.3+ and a Chromium-based browser. No Docker image, no Postgres.
Step 1 - Clone and start the local library
git clone https://github.com/jojomensah89/anansi.git
cd anansi
bun install
cp .env.example .env
Edit .env and set three independent secrets: LIBRARY_TOKEN, INGEST_TOKEN, MCP_TOKEN. Then mirror INGEST_TOKEN into ANANSI_EXTENSION_INGEST_TOKEN. Keep ANANSI_EXTENSION_ORIGIN=http://127.0.0.1:3001.
bun run dev:local
Open http://127.0.0.1:3001. First start creates data/anansi.db and prints the local library sign-in token. The library is at /, JSON endpoints under /api, MCP at /mcp. Back up that one .db file the same way you would linkding's - cp it daily.
Step 2 - Load the private extension
In a second terminal:
bun run --cwd apps/extension build
Open chrome://extensions โ enable Developer mode โ Load unpacked โ choose apps/extension/.output/chrome-mv3. The popup connects immediately; there is no server or token field to fill in. That build embeds your ingest credential. It is meant for your private load-unpacked use only - never upload it to a public extension store or share the folder.
Step 3 - Import what you already saved
Sign in to each provider in the same browser profile, then use the popup's Import button per source:
- X - history import via page adapter + live saves going forward.
- Reddit - history import + live saves via background session requests, no tabs opened.
- GitHub - full stars import + live star/unstar events. It reads your signed-in stars pages, includes private repos visible to that account, and needs no OAuth or PAT.
- Web - save via toolbar or context menu; optional Chrome-bookmark mirroring is stored as Web items.
Imports persist a cursor and resume after restarts or rate limits, plus a daily incremental catch-up covers changes made while Chrome was closed. Unstarring on GitHub hides from the current-stars view without deleting history; re-starring restores it.
Step 4 - Search it yourself, then let your agent search it
Keyword search (SQLite FTS5/BM25) works immediately across text, authors, sources, tags, and recency. Optional semantic search and automatic tagging are off by default - enable them in Settings when you want them (local Ollama or Cloudflare Workers AI + Vectorize on the hosted path).
The same library is exposed to agents through eight read-focused MCP tools (search_saved, get_saved, list_saved, list_recent_saves, list_author_saves, list_tags, library_stats, etc., filtered by x, reddit, github, web):
claude mcp add --transport http anansi http://127.0.0.1:3001/mcp --header "Authorization: Bearer <YOUR_MCP_TOKEN>"
Ask "what did I star last month about Rust async?" and the agent queries your private DB - nothing is sent to a cloud index for training.
The hosted Cloudflare path (Worker + D1 + R2
Comments
No comments yet. Start the discussion.