<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Bookmarks – Serverküche</title><link>https://serverkueche.de/en/tags/bookmarks/</link><description>Bookmarks – Neueste Beiträge von Serverküche</description><generator>Hugo</generator><language>en-US</language><managingEditor>feedback@serverkueche.de (Serverküche)</managingEditor><webMaster>feedback@serverkueche.de (Serverküche)</webMaster><copyright>2026 Serverküche</copyright><lastBuildDate>Sat, 19 Sep 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://serverkueche.de/en/tags/bookmarks/index.xml" rel="self" type="application/rss+xml"/><item><title>linkding: Self-Host Your Bookmarks</title><link>https://serverkueche.de/en/tutorials/linkding-bookmarks/</link><pubDate>Sat, 19 Sep 2026 00:00:00 +0000</pubDate><author>feedback@serverkueche.de (Serverküche)</author><guid>https://serverkueche.de/en/tutorials/linkding-bookmarks/</guid><description>All your bookmarks in one place, across devices and without browser lock-in: linkding as a lean bookmark manager behind Traefik – with tags and API.</description><content:encoded><![CDATA[<p>Browser bookmarks are tied to one device, chaotically organized and gone the moment the profile breaks. linkding collects your links centrally on your own server: via the browser, an extension, the API – searchable, tagged and cross-device.</p>
<h2 id="what-are-we-building">What are we building?</h2>
<p>A lean, self-hosted bookmark manager with <strong>linkding</strong> (v1.45.0) behind <a href="/en/tutorials/traefik-reverse-proxy/">Traefik</a>. By the end you save links in one click, tag them, find them again via full-text search – and linkding fetches title and description from the linked page automatically. linkding is deliberately minimalist and extremely frugal (SQLite, barely any RAM).</p>
<h2 id="prerequisites">Prerequisites</h2>
<ul>
<li>A server with <a href="/en/tutorials/traefik-reverse-proxy/">Traefik</a> running and <a href="/en/tutorials/docker-compose-basics/">Docker Compose</a></li>
<li>A <a href="/en/tutorials/connect-domain-to-server/">subdomain pointing at the server</a> – <code>YOUR_DOMAIN</code> below</li>
</ul>
<div class="not-prose my-6 overflow-hidden rounded-xl border border-paprika-200 bg-paprika-50 dark:border-paprika-800 dark:bg-paprika-900/20"
     data-track-content data-content-name="Affiliate-Box · /en/tutorials/linkding-bookmarks/" data-content-piece="VPS 1000 G12.5">
  <div class="flex items-center justify-between border-b border-paprika-200 bg-paprika-100 px-4 py-1.5 text-xs font-semibold uppercase tracking-wide text-paprika-700 dark:border-paprika-800 dark:bg-paprika-900/40 dark:text-paprika-300">
    <span>🍳 Recommendation</span>
    <span title="Links marked with * are affiliate links.">Ad</span>
  </div>
  <div class="flex flex-col gap-4 p-4 sm:flex-row sm:items-center sm:justify-between">
    <div>
      <p class="text-lg font-bold text-slate-900 dark:text-white">VPS 1000 G12.5</p>
      <p class="mt-1 text-sm text-slate-600 dark:text-slate-300">4 vCores · 8 GB RAM · 128 GB SSD</p>
      <p class="mt-1 text-sm font-semibold text-paprika-700 dark:text-paprika-400">from €14.50/month</p>
      <p class="mt-2 text-sm text-slate-600 dark:text-slate-400">linkding is tiny – even the smallest VPS is bored by it.</p>
    </div>
    <a href="https://www.netcup.com/en/server/vps/vps-1000-g12.5-iv-24m-eu?ref=44083#vps-1000-g12.5-iv-12m-eu" rel="sponsored noopener" target="_blank"
   data-track-event="Affiliate|netcup: Affiliate-Box|VPS 1000 G12.5 · {page}"
   class="inline-flex shrink-0 items-center justify-center rounded-lg bg-paprika-600 px-5 py-2.5 font-semibold text-white transition-colors hover:bg-paprika-700">
  Go to netcup →
</a>

  </div><div class="px-4 pb-4"><div class="not-prose my-3 rounded-lg border border-herb-500/40 bg-herb-50 px-3 py-2 text-sm text-slate-700 dark:bg-herb-900/20 dark:text-slate-200">
  <p class="flex flex-wrap items-center gap-x-2 gap-y-1">
    <span>💶 <strong>€5 voucher</strong> for new netcup customers:</span>
    <button type="button" data-voucher-code data-track-voucher="36nc17844976032"
            title="Click to copy" class="cursor-pointer rounded bg-white px-2 py-0.5 font-mono text-sm font-semibold text-herb-800 hover:ring-2 hover:ring-herb-500/40 dark:bg-slate-800 dark:text-herb-400">36nc17844976032</button>
    <span class="text-xs text-slate-500 dark:text-slate-400">(not for domains or VPS Lite)</span>
  </p>
  <p class="mt-1 text-xs text-slate-500 dark:text-slate-400">
    <a href="https://www.netcup.com/en/checkout/cart?ref=44083" rel="sponsored noopener" target="_blank"
       data-track-event="Affiliate|netcup: Gutschein einlösen|€5 · {page}"
       class="font-medium text-herb-800 underline underline-offset-2 hover:text-herb-900 dark:text-herb-400">Redeem in the cart →</a>
  </p>
</div></div>
</div>

<h2 id="step-by-step">Step by step</h2>
<h3 id="step-1-project-and-compose-file">Step 1: Project and Compose file</h3>
<p>linkding stores everything (database, settings) in a <code>data</code> folder. Create the project:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">mkdir -p /opt/linkding/data <span class="o">&amp;&amp;</span> <span class="nb">cd</span> /opt/linkding</span></span></code></pre></div>
</div>
<p>The <code>compose.yaml</code> – replace <code>YOUR_DOMAIN</code>. linkding creates the admin account on first start from the environment variables:</p>
<div class="sk-code">
  <span class="sk-code-head">YAML</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">services</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">linkding</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">sissbruecker/linkding:1.45.0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">restart</span><span class="p">:</span><span class="w"> </span><span class="l">unless-stopped</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">./data:/etc/linkding/data</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">environment</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">LD_SUPERUSER_NAME</span><span class="p">:</span><span class="w"> </span><span class="l">cook</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">LD_SUPERUSER_PASSWORD</span><span class="p">:</span><span class="w"> </span><span class="l">YOUR_STRONG_PASSWORD</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">LD_CSRF_TRUSTED_ORIGINS</span><span class="p">:</span><span class="w"> </span><span class="l">https://YOUR_DOMAIN</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">networks</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">proxy]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">labels</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.enable=true&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.http.routers.linkding.rule=Host(`YOUR_DOMAIN`)&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.http.routers.linkding.entrypoints=websecure&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.http.routers.linkding.tls.certresolver=le&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.http.services.linkding.loadbalancer.server.port=9090&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">networks</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">proxy</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">external</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span></span></span></code></pre></div>
</div>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-amber-400 bg-amber-50 dark:border-amber-700 dark:bg-amber-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">⚠️</span>Don&#39;t forget LD_CSRF_TRUSTED_ORIGINS
  </p>
  <div class="prose-kitchen text-sm">Like many Django applications behind a reverse proxy, linkding needs <code>LD_CSRF_TRUSTED_ORIGINS</code> set to your full HTTPS domain – otherwise the login form fails with a CSRF error. The login <em>page</em> loads, but submitting it is rejected.</div>
</div>
<h3 id="step-2-start-and-log-in">Step 2: Start and log in</h3>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker compose up -d</span></span></code></pre></div>
</div>
<p>The image ships a health check; Traefik only routes once linkding is <code>healthy</code> (about 30 seconds). Then open <code>https://YOUR_DOMAIN/</code>:</p>
<p><figure class="my-6"><img src="/en/tutorials/linkding-bookmarks/ld-login_hu_79919b2d44682b79.webp" srcset="/en/tutorials/linkding-bookmarks/ld-login_hu_d077e8827c1bce63.webp 480w, /en/tutorials/linkding-bookmarks/ld-login_hu_79919b2d44682b79.webp 768w, /en/tutorials/linkding-bookmarks/ld-login_hu_444f43acce17ec79.webp 1200w, /en/tutorials/linkding-bookmarks/ld-login_hu_af8a018e463ec8e4.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/en/tutorials/linkding-bookmarks/ld-login_hu_63401009cb83b200.webp"
    alt="The linkding login page under your own HTTPS domain" title="The linkding login – the credentials come from the Compose file"
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">The linkding login – the credentials come from the Compose file</figcaption></figure></p>
<p>Log in with the account set in the Compose file.</p>
<h3 id="step-3-save-your-first-bookmark">Step 3: Save your first bookmark</h3>
<p>Click <strong>Add bookmark</strong> at the top and paste a URL. The clever part: linkding fetches the page and <strong>fills in title and description automatically</strong> – you only add tags (separated by spaces, without <code>#</code>):</p>
<p><figure class="my-6"><img src="/en/tutorials/linkding-bookmarks/ld-add_hu_d095319ce7e648d1.webp" srcset="/en/tutorials/linkding-bookmarks/ld-add_hu_3fc76596871ed221.webp 480w, /en/tutorials/linkding-bookmarks/ld-add_hu_d095319ce7e648d1.webp 768w, /en/tutorials/linkding-bookmarks/ld-add_hu_18c0109475f059cb.webp 1200w, /en/tutorials/linkding-bookmarks/ld-add_hu_187db8e433aa47e6.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/en/tutorials/linkding-bookmarks/ld-add_hu_b15a5bceb87c08f.webp"
    alt="The form for creating a bookmark with automatically filled title and description" title="\&#34;Add bookmark\&#34;: linkding fetches title and description from the page itself; you add tags"
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">\&#34;Add bookmark\&#34;: linkding fetches title and description from the page itself; you add tags</figcaption></figure></p>
<p>Optionally you can mark a bookmark as <strong>unread</strong> (&ldquo;Mark as unread&rdquo;) – handy as a read-later list.</p>
<h3 id="step-4-search-and-filter-the-collection">Step 4: Search and filter the collection</h3>
<p>The overview shows your bookmarks chronologically, with a clickable tag cloud on the right. The search finds links by words or <code>#tags</code>:</p>
<p><figure class="my-6"><img src="/en/tutorials/linkding-bookmarks/ld-list_hu_5dde5f65a7e63c9d.webp" srcset="/en/tutorials/linkding-bookmarks/ld-list_hu_a71d2b0c0ed716b4.webp 480w, /en/tutorials/linkding-bookmarks/ld-list_hu_5dde5f65a7e63c9d.webp 768w, /en/tutorials/linkding-bookmarks/ld-list_hu_4efd6c66402162cf.webp 1200w, /en/tutorials/linkding-bookmarks/ld-list_hu_5dc87daac13b997f.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/en/tutorials/linkding-bookmarks/ld-list_hu_c12a886c6d6001dd.webp"
    alt="The linkding overview with several bookmarks, tags and a search box" title="The bookmark list: title, tags and auto description, with tag navigation on the right"
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">The bookmark list: title, tags and auto description, with tag navigation on the right</figcaption></figure></p>
<p>Clicking a tag filters instantly; multiple tags combine the filters. That keeps even a large collection tidy – without any folder hierarchy.</p>
<h3 id="step-5-save-quickly-from-the-browser">Step 5: Save quickly from the browser</h3>
<p>For everyday use you don&rsquo;t want to open the web interface every time. linkding offers two convenient ways:</p>
<ul>
<li><strong>Browser extension:</strong> there&rsquo;s an official linkding extension for Firefox and Chrome. In its settings you enter <code>https://YOUR_DOMAIN</code> and an <strong>API token</strong> (found in linkding under <strong>Settings → Integrations → REST API</strong>). After that you save the current page with one click.</li>
<li><strong>Bookmarklet:</strong> alternatively linkding offers a bookmarklet under Settings – a bookmark in your browser bar that sends the current page straight to linkding. Works without an extension, on mobile too.</li>
</ul>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-herb-400 bg-herb-50 dark:border-herb-700 dark:bg-herb-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">🧑‍🍳</span>Import existing bookmarks
  </p>
  <div class="prose-kitchen text-sm">Switching from a browser or another service? Export your bookmarks there as an <strong>HTML file</strong> (the standard format of all browsers) and import them under <strong>Settings → Import</strong>. All your links move over at once – including the folder structure, which linkding turns into tags.</div>
</div>
<h2 id="when-things-go-wrong">When things go wrong</h2>
<div class="troubleshoot not-prose">
<p><strong>Login fails with a CSRF error.</strong> <code>LD_CSRF_TRUSTED_ORIGINS: https://YOUR_DOMAIN</code> is missing or wrong (must be given with <code>https://</code> and no path). Add it and <code>docker compose up -d</code> (see the warning in step 1).</p>
<p><strong>The page doesn&rsquo;t load (Traefik 404) even though the container is running.</strong> The health check isn&rsquo;t <code>healthy</code> yet – Traefik deliberately doesn&rsquo;t route then. Wait about 30 seconds after start; check the status with <code>docker inspect -f '{{.State.Health.Status}}' linkding-linkding-1</code>.</p>
<p><strong>Title/description aren&rsquo;t fetched automatically.</strong> The target page blocks automated access or responds too slowly. You can then simply enter title and description by hand – the fields are in the same form.</p>
<p><strong>The admin account wasn&rsquo;t created.</strong> <code>LD_SUPERUSER_NAME</code>/<code>LD_SUPERUSER_PASSWORD</code> only take effect on the <strong>first</strong> start with an empty database. If the <code>data</code> database already exists, a later change does nothing. Create the account afterwards: <code>docker compose exec linkding python manage.py createsuperuser</code>.</p>
<p><strong>The extension won&rsquo;t connect.</strong> Almost always the API token or the URL. Regenerate the token under Settings → Integrations and enter exactly <code>https://YOUR_DOMAIN</code> as the server.</p>

</div>

<h2 id="maintenance--backups">Maintenance &amp; backups</h2>
<ul>
<li><strong>Updates.</strong> Occasionally bump the image tag (<code>sissbruecker/linkding:1.45.0</code>) to the current version and <code>docker compose up -d</code>; the database migrates automatically at start. The rest runs through your normal <a href="/en/tutorials/keep-docker-stack-updated/">update process</a>.</li>
<li><strong>The backup is tiny.</strong> The entire state lives in the <code>data</code> folder (SQLite database). Add it to your <a href="/en/tutorials/restic-backups/">Restic backup</a> – then all bookmarks, tags and settings are safe. Additionally an occasional <strong>HTML export</strong> (Settings → Export) makes a browser-readable, service-independent backup.</li>
<li><strong>Near-zero effort.</strong> linkding is a &ldquo;set it up and forget it&rdquo; service. The only recurring activity is saving new links – and you&rsquo;ll do that via the extension or bookmarklet in a second from now on.</li>
</ul>
]]></content:encoded></item></channel></rss>