Overview

I've been saving URLs in different places for a long time. Sometimes to share them, sometimes to aggregate ideas, sometimes to read later. Truth is, we collect more than we use and all these links end up in a cemetery before I can sort and process them. I needed an inbox I could automate.

There are several bookmark managers available and I spent some time looking at them. I wanted to self-host and automate some tasks like sharing bookmarks tagged X in a Matrix room, while avoiding duplicates.

A few months ago I discovered Karakeep, an open-source bookmark manager, with a Chrome extension and an iOS app. At the time it didn't have all features I needed. They are now available or under development, thanks to the active community.

So, I decided to give Karakeep and n8n a try on a weekend project.

Architecture

Before touching the infrastructure, we must understand the topology of the stack. Karakeep operates as a multi-tiered architecture that relies on headless browser isolation and search indexes.

Here is what we're gonna build:

Architecture diagram

Note: Karakeep relies on SQLite only but developers have approved Postgres and a PR is on its way.

Preparation

  • Create a DNS record for karakeep: karakeep.domain.tld.
  • Read the security considerations related to web crawling and multi-users.
  • Ensure your Matrix and n8n instance are ready and available over HTTPS.

Install Karakeep on Kubernetes

The Karakeep repository contains the sources and the Kustomize manifests. The team also maintains a Helm chart based on a template Chart.

The cluster I use runs with Traefik and Cert-Manager, so I picked the Kustomize approach because it is faster to add my own manifests.

Environment variables can be set using the .env.

Secrets must be generated beforehand:

  • APPLICATION_SECRET_KEY="<generate-key>"
  • MEILISEARCH_MASTER_KEY="<generate-key>"

The documentation comes with a troubleshooting page if needed.

Administration first steps

Note: Users cannot change their username or email, so double check the values before creating the user.

  1. Create an admin user by signing up first.
  2. Create a tenant by signing up second.
  3. Disable sign up: APPLICATION_DISABLE_SIGNUPS=true

Understanding the basics

Entries:

  • Karakeep separates text entries (Notes) and url entries (Bookmarks). A note is a multi-line entry with more than a URL, while a bookmark is just a link. That little detail is important to keep in mind when creating entries because the crawler won't run on a note. However, a bookmark can be edited to add a notes!
  • Open bookmark first instead of opening link: SettingsUser InfoBookmark Click ActionOpen Bookmark Details

Tags:

  • Adding tags comes after an entry is created. There is currently no way to add tags on creation.
  • When playing around with Rules, one cannot act on an "entry that has no tag".

Lists:

  • Entries can belong to one list only.
  • Collaborations are possible on lists by inviting other users. The list owner can promote other users to owner or admin.
  • Lists can have children (sub-lists). Developers already approved the development for the feature to collaborate on sublists.

Productivity:

  • Install Chrome extension
  • Install iOS app

Connecting Karakeep to n8n via Webhooks

Understanding the lifecycle

Karakeep n8n workflow
  1. Trigger event: A bookmark is added to Karakeep. It spins up Chrome headless, parses and extracts the page and generates an event bookmark.crawled.
  2. Webhook: Karakeep sends an HTTP POST request containing a light payload to n8n.
  3. Authentication: The n8n Webhook node validates the request against Header Authentication: Authorization: Bearer <token>.
  4. API call: n8n sends an authenticated HTTP GET request back to the Karakeep API to retrieve the complete object of a bookmark.

Webhook configuration on n8n

1. Configure the n8n Webhook node

  • Node type: Webhook
  • HTTP Method: POST
  • Authentication: Header Auth
  • Credentials setup:
    • Create a new credential.
      • Name: Authorization
      • Value: Bearer YOUR_SECRET_TOKEN.
    • Execution: Save the node and copy the Production URL or Test URL for the next step.

2. Configure Karakeep webhook settings

  • Navigate to SettingsWebhooksAdd Endpoint in your Karakeep instance.
  • Target URL: Paste the URL copied from your n8n Webhook node.
  • Secret / Token: Paste only your raw token string (Do not include the word Bearer or spaces here; Karakeep appends the standard prefix automatically).
  • Trigger events: crawled, created, edited.

Note: Using created executes too quickly, before Karakeep finishes fetching page summaries, titles, and screenshots. crawled ensures the full webpage data is already processed.

Fetching complete bookmark content

Create a Karakeep API Key

Go to your Karakeep account settings and generate a new API Key.

Configure the n8n HTTP Request Node

Add an HTTP Request node immediately following your Webhook node.

  • Method: GET
  • URL (Expression):
    https://karakeep.domain.tld/api/v1/bookmarks/{{ $('On: Bookmark').item.json.body.bookmarkId }}
    
  • Authentication: Predefined credential type
  • Credential Type: Header Auth
  • Credential Parameters:
    • Name: Authorization
    • Value: Bearer <YOUR_KARAKEEP_API_KEY>.

Note:

The object payload does not contain lists. Karakeep maintains a structural separation between items and collections. To locate which list the processed bookmark belongs to, you must fetch all lists and filter them inside your workflow.

Connecting n8n to Matrix

Create a Matrix bot

To protect your infrastructure's identity, always deploy isolated bots with specialized permissions rather than using your own profile.

  1. Create a Matrix user for the bot from the homeserver:
    register_new_matrix_user \
      -u "$USERNAME" \
      -p "$PASSWORD" \
      -c /data/homeserver.yaml \
      http://localhost:8008
    
  2. Get Matrix bot access token by logging in and fetching the token in SettingsHelp & AboutAdvancedAccess Token
  3. Invite the Matrix bot to the room where you want to share bookmarks
  4. Join the room with the bot (need to accept the invite from the web UI) otherwise Matrix bot won't be able to send messages to the room.
  5. Create credentials for Matrix bot in n8n

Credentials for Matrix bot

  • Create credentials for Matrix bot
    • Go to SettingsCredentialsCreate Credentials
    • Credential Type: Matrix Bot
    • Credential Parameters:
      • Name: Matrix Bot
      • User ID: @bot:your-domain.com
      • Access Token: YOUR_MATRIX_BOT_ACCESS_TOKEN

Sending Matrix message

Use the Matrix Bot node to send the bookmark to the Matrix room.

The message in the node can be:

{{ $('Fetch: Bookmark Details').item.json.content.title }}

{{ $('Fetch: Bookmark Details').item.json.content.description }}

{{ $('Fetch: Bookmark Details').item.json.content.url }}

Production readiness

Well, this is a prototype for now. When it comes to production, here are some things to consider.

Documentation

Document this software and its operations. What is not documented does not exist.

Backup and restore

Because Karakeep relies on a local SQLite, backup the file /data/karakeep.db.

Don't forget to lock the file first or the database will corrupt itself.

Healthchecks and monitoring

An example of probes to add to the statefulset:

livenessProbe:
  httpGet:
    path: /api/health
    port: 3000
    scheme: HTTP
  initialDelaySeconds: 10
  timeoutSeconds: 1
  periodSeconds: 10
  successThreshold: 1
  failureThreshold: 3
readinessProbe:
  httpGet:
    path: /api/health
    port: 3000
    scheme: HTTP
  initialDelaySeconds: 10
  timeoutSeconds: 1
  periodSeconds: 10
  successThreshold: 1
  failureThreshold: 3

The path karakeep.domain.tld/api/health should show:

{ "status": "ok", "message": "Web app is working" }

Increase crawlers and resources

Increase the CRAWLER_NUM_WORKERS (default 1).

You can also increase pods' resources.

Upgrades

Follow the official documentation for upgrading Karakeep.