DEV Community

Jojo
Jojo Subscriber

Posted on

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 .db file. Back it up with cp. Move it with scp. 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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:

  1. Navigate to Settings > Integrations and copy your API token.
  2. Install the linkding extension for Chrome or Firefox.
  3. 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
Enter fullscreen mode Exit fullscreen mode

That is it. No pg_dump, no replication, no managed database service.

Here is a quick walkthrough of linkding in practice:

https://www.youtube.com/watch?v=I7uNk62Z_pM&pp=ygU5U2VsZi1Ib3N0IFlvdXIgV2ViIEJvb2ttYXJrcyBXaXRoIFNRTGl0ZSBhbmQgRnVsbCBQcml2YWN5

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Open chrome://extensions → enable Developer modeLoad 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>"
Enter fullscreen mode Exit fullscreen mode

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 in your own account) is wired in the repo but treat a clean-account deploy as the intended path until you verify it yourself. For most readers, local SQLite + the private extension is the setup to start with.

Putting linkding Behind a Reverse Proxy With HTTPS

Running on port 9090 over plain HTTP is fine on a home network, but if you want to reach your bookmarks from anywhere, you need HTTPS and a domain. The most common setups use Nginx Proxy Manager or Caddy as the reverse proxy, with a free TLS certificate from Let's Encrypt.

Caddy example - add this to your Caddyfile:

bookmarks.yourdomain.com {
    reverse_proxy localhost:9090
}
Enter fullscreen mode Exit fullscreen mode

Caddy automatically obtains and renews the Let's Encrypt certificate. No certbot cronjob needed.

Cloudflare Tunnel is an increasingly popular alternative for self-hosters who do not want to open firewall ports at all. You install the cloudflared daemon on your server, create a tunnel in the Cloudflare dashboard, and Cloudflare routes traffic to your linkding instance through an encrypted outbound-only connection. Your home IP never appears in DNS.

cloudflared tunnel --url http://localhost:9090
Enter fullscreen mode Exit fullscreen mode

The trade-off: Cloudflare sees your traffic metadata, even though content is encrypted in transit. If your threat model requires hiding the existence of your bookmark server from all third parties, use a self-hosted WireGuard VPN instead and access linkding only over the tunnel.

Using linkding's REST API for Automation

One of linkding's underrated strengths is its REST API. Every operation you can do in the UI is available over HTTP, which means you can build automation pipelines without any scraping.

Common API patterns:

Bulk import from browser exports. Linkding accepts the standard Netscape bookmark HTML format, so you can import years of browser bookmarks in seconds via the UI or the /api/bookmarks/ endpoint.

Save from the command line. A one-liner to save the current page you are reading in a terminal session:

curl -X POST https://bookmarks.yourdomain.com/api/bookmarks/ \
  -H "Authorization: Token YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com","tag_names":["reading","dev"]}'
Enter fullscreen mode Exit fullscreen mode

MCP server for AI assistants. The Model Context Protocol (MCP), introduced by Anthropic in 2024, lets AI assistants like Claude query tools and data sources on your behalf. Several community projects expose linkding's API as an MCP server, so you can ask Claude "what did I bookmark last week about Rust async?" and get a direct answer from your private database - without sending your bookmark list to any cloud AI service for indexing.

To set up an MCP bookmark server with linkding, run a lightweight MCP adapter that speaks the MCP protocol on one side and calls the linkding REST API on the other. The adapter runs locally, so your bookmarks never leave your machine.

Security Hardening for Your Self-Hosted Bookmark Server

Running a public-facing web service introduces real risks. Here is a practical security checklist:

  • [ ] Change the default admin password immediately after first login - never leave changeme in production.
  • [ ] Enable HTTPS before exposing the service to the internet. Linkding over plain HTTP leaks your API token to any network observer.
  • [ ] Restrict registration. Set LD_DISABLE_BACKGROUND_TASKS=False and leave user registration closed unless you are running a shared instance.
  • [ ] Keep the Docker image updated. Run docker compose pull && docker compose up -d monthly to pick up security patches.
  • [ ] Use fail2ban or Crowdsec to block brute-force login attempts on your reverse proxy.
  • [ ] Store backups off-site. A single-location backup is not a backup. Use rclone to sync your SQLite file to an encrypted S3-compatible bucket (Backblaze B2 costs roughly $0.006 per GB/month).
  • [ ] Audit your Cloudflare Tunnel or firewall rules to ensure only the bookmark port is exposed, not Docker's management API or other internal services.

For a deeper look at home lab security practices, this video from Techno Tim covers the full picture:

https://www.youtube.com/watch?v=Cs8yOmTJNYQ&pp=ygU5U2VsZi1Ib3N0IFlvdXIgV2ViIEJvb2ttYXJrcyBXaXRoIFNRTGl0ZSBhbmQgRnVsbCBQcml2YWN5

Migrating From Pocket, Raindrop, or Browser Bookmarks

Switching is easier than most people expect.

From Pocket: Go to getpocket.com/export and download your list as an HTML file. In linkding, go to Settings > Import and upload the file. Linkding parses the Netscape bookmark format that Pocket exports, and tags carry over automatically.

From Raindrop.io: Export as HTML (Netscape format) from Settings > Export. Upload to linkding's import page. Collection names become tags.

From browser bookmarks (Chrome, Firefox, Edge, Safari): All major browsers export bookmarks as Netscape HTML. Use the browser's built-in export (Bookmarks Manager > Export Bookmarks) and import the file directly into linkding. Folder names are converted to tags.

From Wallabag: Wallabag exports to JSON, CSV, or XML. Linkding does not natively import Wallabag's JSON format, so the cleanest path is to export from Wallabag as CSV and use a small Python script to POST each URL to linkding's API. The whole process takes about 15 minutes for a few thousand entries.

Local-First Bookmarks and Browser Sync Without the Cloud

A common concern with self-hosting is browser sync: if your bookmarks live on a home server, how do you save and access them from your phone or a work laptop?

The answer: the browser extension plus mobile access.

Linkding's browser extensions for Chrome and Firefox save bookmarks from any device where the extension is installed. The linkding web UI is mobile-responsive. Bookmark it as a PWA (Add to Home Screen) on iOS or Android for near-native access. Shiori's approach is slightly different: it caches full page content locally, so you can read archived articles offline from your phone even without an internet connection to your server.

If you want the browser's native bookmarks bar synced privately across devices without a self-hosted server, xBrowserSync is a strong local-first option that encrypts everything client-side before syncing.

Frequently Asked Questions

What is the easiest self-hosted bookmark manager to set up?

Linkding is the easiest self-hosted bookmark manager for most people. It ships as a single Docker image, uses SQLite with no configuration required, and is production-ready in under ten minutes. The browser extension works with Chrome and Firefox out of the box, and the API supports automation without any additional dependencies.

Can I self-host bookmarks on a Raspberry Pi?

Yes. Linkding and Shiori both run comfortably on a Raspberry Pi 4 with 2 GB of RAM. The Docker images have ARM64 builds. Karakeep works on a Pi 4 with 4 GB of RAM, but the Meilisearch component is memory-hungry, so expect to allocate at least 512 MB to it alone.

Is SQLite safe for storing thousands of bookmarks long-term?

Absolutely. SQLite databases remain performant well into the millions of rows for read-heavy workloads like bookmark search. The SQLite documentation describes it as suitable for databases up to roughly 1 TB. A typical bookmark database with 10,000 entries and cached page content rarely exceeds a few hundred megabytes.

What is a self-hosted alternative to Pocket?

Wallabag is the most direct self-hosted Pocket alternative. It focuses on the read-later workflow - stripping article formatting, storing the full text, and offering an e-reader-friendly reading mode. Linkding is better if you want a fast bookmark manager rather than a reading app. Karakeep covers both use cases with AI-assisted tagging.

Can I use my self-hosted bookmarks with an AI assistant?

Yes, through the Model Context Protocol. Anansi ships this natively: eight read-focused MCP tools (search, get, list, recent, by-author, tags, stats) expose your unified X / Reddit / GitHub / Web library to Claude Code, Codex, or OpenCode without sending the library to a cloud AI service for indexing.

Running a local MCP adapter that wraps linkding's REST API lets AI assistants query your bookmarks without any data leaving your server. This is a local-first AI workflow: the AI sees only the data you explicitly share through the MCP connection, and your bookmark list never gets uploaded to a training dataset.

How do I sync bookmarks between devices without a cloud service?

Install the linkding browser extension on every device and point it at your self-hosted instance over HTTPS. If your server is behind a Cloudflare Tunnel or a WireGuard VPN, you can reach it from anywhere. For fully offline-first sync, look at Shiori's offline archiving or xBrowserSync's encrypted peer-to-peer approach.

Does linkding support multi-user setups?

Yes. Linkding supports multiple user accounts, each with its own isolated bookmark database. An admin can create accounts via the UI or the Django management interface. Bookmarks are not shared between users by default. For team-oriented sharing and collaborative collections, Linkwarden is the better fit.

Sources

Top comments (1)

Collapse
 
raknaos profile image
Baptiste Le Bouquin

The acquisition-risk framing is the right one — Delicious is the canonical horror story, and Pocket's fate after the layoffs proved it wasn't just nostalgia for old failures.

I run most of my infra self-hosted on a small VPS and linkding was one of the easiest wins there: SQLite means backups are just a file copy, and the search is genuinely usable. One tip for anyone following the Docker guide: set up the SQLite backup on a cron from day one, not "later" — a bookmarks DB you've curated for two years hurts to lose.

Does Anansi's multi-source capture dedupe URLs across sources, or can you end up with the same page saved three times?