Self-hosted service
sissbruecker/linkding avatar
sissbruecker/linkding

linkding: a self-hosted bookmark manager you run with Docker

Self-hosted bookmark manager that is designed be to be minimal, fast, and easy to set up using Docker.

11,231 stars624 forksPythonMIT

At a glance

What is it?
linkding is a Django bookmark manager built around tags, a REST API and a single Docker container. It is small, opinionated, and a poor fit if you want full-text archiving or a hosted service.
Who is it for?
Adopt linkding if you want a tag-based bookmark store you own, reachable over a REST API, and you are comfortable running one Docker container with SQLite behind it. Do not adopt it if you need full-text search across page contents, a native mobile client maintained by the project, or a hosted service with a support contract; the README points to community projects for mobile apps and to managed hosting options instead.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 12 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 25, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What linkding actually stores, and who it is for

linkding is a bookmark manager you host yourself. The README describes it as "minimal, fast, and easy to set up using Docker", and the name is a compound of link and the German word Ding, which the README explains as "something for managing your links". The unit of storage is a bookmark with a URL, a title, a description, tags and an optional Markdown note. Everything else in the feature list hangs off that: bulk editing, a read-it-later flag, sharing with other users or guests, and automatic fetching of titles, descriptions and icons from the bookmarked site.

The audience is narrow on purpose. This is for someone who already runs a server, wants their bookmarks in a database file they control, and does not want a subscription. The README also points at a demo instance and at browser extensions for Firefox and Chrome plus a bookmarklet, so the intended daily loop is: click the extension, the bookmark lands in your instance. If you want a bookmark service that works without you administering anything, this is the wrong shape of project, and the README says so implicitly by linking to managed hosting options rather than offering one itself.

Django, Huey and a uWSGI process inside one container

The stack is visible in pyproject.toml. The project is a Django application (django>=6.0.7) with Django REST Framework for the API, served by uWSGI, with supervisor as the process manager. Background work runs through Huey, which is the queue that handles the parts you do not want in the request cycle: fetching a site's title and description, and archiving a page either as a local HTML file or to the Internet Archive through waybackpy. The repository ships supervisord-all.conf and supervisord-tasks.conf, which is how the web process and the task worker are kept running side by side in the image.

On the frontend the project does not use a single-page framework. package.json shows esbuild bundling bookmarks/frontend/index.js into bookmarks/static/bundle.js, with Lit for components and Turbo for navigation, plus two separately built CSS themes. That is a deliberate trade-off: server-rendered pages with small islands of JavaScript, which keeps the page weight low and the Django templates in charge, at the cost of not having a rich client-side application model. Storage defaults to SQLite. Postgres is supported, and pyproject.toml keeps it in a separate dependency group because the psycopg driver builds from source in production, which the file notes requires libpq on the build machine.

Installing linkding with Docker Compose

The repository ships a docker-compose.yml and a .env.sample, and the compose file is short enough to read in one pass. It defines a single service named linkding using the image sissbruecker/linkding:latest, publishes port 9090, mounts a data directory at /etc/linkding/data, and reads environment from a .env file next to it. Copy the sample to .env and set the host port and data directory first.

bash
cp .env.sample .env

Then edit .env. The three keys that matter for a first run are LD_HOST_PORT, LD_HOST_DATA_DIR and the initial superuser. LD_HOST_PORT defaults to 9090 in the sample, and LD_HOST_DATA_DIR defaults to ./data, which is where the SQLite database and any archived files live.

bash
LD_HOST_PORT=9090
LD_HOST_DATA_DIR=./data
LD_SUPERUSER_NAME=joe
LD_SUPERUSER_PASSWORD=change-me

Bring it up and open the published port. The README's development instructions use http://localhost:8000 for the Django dev server; the container publishes 9090, so with the sample settings the instance answers on http://localhost:9090.

bash
docker compose up -d

Log in with the superuser you set, then add your first bookmark through the web form or the browser extension. Two sample keys are worth knowing before you expose the instance: LD_CSRF_TRUSTED_ORIGINS is the list of origins from which POST requests are accepted, and LD_CONTEXT_PATH lets you run linkding under a subpath such as linkding/ (the sample notes it must end with a slash). If you already have bookmarks elsewhere, the README lists import and export in Netscape HTML format, which is the format most browsers still export.

Where linkding stops short

There is no full-text search over page contents in the feature overview. Search and organisation are tag-based, and the automatic archiving either writes a local HTML file or hands the URL to the Internet Archive. If your use case is "find that sentence I read six months ago", linkding is not that tool, and the README does not claim it is. The same gap applies to the mobile story: the README links to community projects for mobile apps and extensions, which means those clients are maintained outside the project and by other people.

The background worker is another boundary. Because title fetching and archiving run through Huey, they depend on the task process being alive, and the sample environment file includes LD_DISABLE_BACKGROUND_TASKS to turn that work off entirely. Running with tasks disabled is a legitimate choice on a small box, but then bookmarks will not get their titles and icons filled in automatically. LD_DISABLE_URL_VALIDATION is the matching escape hatch for environments where outbound checks are unwanted. Finally, the contributing section is explicit that the maintainer may ignore pull requests for features that do not align with the project's goals, so treat the feature set as the author's, not as a backlog you can steer.

linkding compared with linkwarden and karakeep

The two comparisons people search for are linkding vs linkwarden and linkding vs karakeep, and the difference is mostly about what gets stored. linkding keeps the bookmark record, its metadata and an optional archive, and it stays inside a Django application with tags as the primary organising tool. linkwarden and karakeep are aimed at capturing and preserving page content, which puts them in a different weight class: more moving parts to run, and a different answer to "what do I get back when the original page dies". If your requirement is a durable, searchable copy of the page text, linkding's local HTML archive or Internet Archive handoff is a thinner answer than a tool built around capture.

The other axis is how much you want to own. linkding's REST API and admin panel are documented as ways to build third-party apps and reach raw data, and the README points to a community page of mobile apps, extensions and libraries. That is an integration-friendly posture, but the extensions and clients are not all first-party. A self-hosted alternative that ships its own clients will feel more finished on day one; linkding will feel smaller and easier to reason about, which is the trade the author made.

Maintenance, licence and upgrade cost

The repository is not archived, and the last push was on 2026-08-18, which is within the last month. The release history shows v1.46.0, v1.46.1 and v1.46.2 all landing in August 2026, so the project is being released, not just pushed to. pyproject.toml declares version 1.47.0, which is ahead of the newest listed release, so the version file and the release tags are not always in step; check the CHANGELOG.md in the repository rather than the version string when you want to know what changed.

Upgrades are the usual container image pull plus migrations, and the compose file uses sissbruecker/linkding:latest with restart: unless-stopped, so pinning a tag is a choice you have to make yourself if you want reproducible deploys. Back up LD_HOST_DATA_DIR before an upgrade: with the default SQLite setup, that directory is the database. The licence is MIT, which is permissive and places few obligations on how you run or redistribute it; it is not a legal opinion, and if you plan to redistribute a modified image, read LICENSE.txt yourself. The dependency list is ordinary Django-era Python (Django 6, DRF, Huey, uWSGI, requests, bleach, beautifulsoup4), so the upgrade treadmill is the one you already know if you run Django services.

Editorial conclusion

Adopt linkding if you want a tag-based bookmark store you own, reachable over a REST API, and you are comfortable running one Docker container with SQLite behind it. Do not adopt it if you need full-text search across page contents, a native mobile client maintained by the project, or a hosted service with a support contract; the README points to community projects for mobile apps and to managed hosting options instead. Verify first that your reverse proxy setup matches the LD_CONTEXT_PATH and LD_CSRF_TRUSTED_ORIGINS options in .env.sample, and confirm whether you want SQLite or the Postgres path before you import an existing bookmark file.

Frequently asked questions

Is there a self-hosted bookmark manager available?

Yes. linkding is a self-hosted bookmark manager that the README describes as minimal, fast and easy to set up using Docker, installed from the sissbruecker/linkding image with the included docker-compose.yml.

How does linkding compare with linkwarden?

linkding stores bookmarks with tags, notes and metadata, and archives pages either as a local HTML file or through the Internet Archive. linkwarden is aimed at capturing and preserving page content, which means more components to run and a different answer to what you keep when the original page disappears.

How does linkding compare with karakeep?

linkding is a Django application with tag-based organisation, a REST API and an optional archive step. karakeep sits in the content-capture category, so the comparison is mostly about whether you need a searchable copy of the page text or just a well-organised link record.

Official sources

  1. Official documentation
  2. Official README
  3. Project repository
  4. Release notes
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/sissbruecker-linkding.svg)](https://hysenlabs.com/projects/sissbruecker-linkding)