Installing Karakeep on Your Server: Your Own Bookmark Manager with Docker
Install Karakeep, the bookmark manager for everything, on your own server using Docker and Docker Compose. Includes a reverse proxy with Caddy and optional AI integration.

Table of Contents
In this blog post, we’ll take a closer look at Karakeep. Karakeep is a promising bookmark app that aims to enable bookmarking for everything. Whether it’s websites, notes, images, or even RSS feeds – Karakeep aims to become your central hub.
We will install Karakeep together on a server, secure it for external access, and even explore some of its optional AI features.
What is Karakeep?
Karakeep is an open-source bookmark manager designed to store more than just URLs. You can:
- Save and archive websites (Full Page Archive).
- Add notes and images.
- Have tags automatically assigned by AI.
- Have content summarized by AI.
- Subscribe to and read RSS feeds.
- Import bookmarks from browsers or other services.
- Quickly add content via browser extensions and mobile apps.
Since it’s a self-hosted application, you retain full control over your data.
Glossary: Important Terms and Technologies
Term | Description |
---|---|
Karakeep | The open-source bookmark management software we are installing. |
Server | A computer that provides services. Can be a home server (e.g., a Raspberry Pi or old PC) or a Virtual Private Server (VPS). |
VPS | Virtual Private Server; a rented virtual server from a hosting provider. |
Docker | A platform for creating, deploying, and running applications in containers. |
Docker Compose | A tool for defining and running multi-container Docker applications. Configuration is done via a compose.yaml file. |
Image | A template with instructions for creating a Docker container. |
Container | A running instance of a Docker image. |
Bind Mount | Links a directory on the host system with a directory in the container to store persistent data. |
.env File | A file for storing environment variables. |
Reverse Proxy | A server that receives requests from the internet and forwards them to the appropriate internal service (here, Karakeep). |
Caddy | A modern, easy-to-configure web server and reverse proxy that automatically manages HTTPS certificates. |
API Key | A unique code used for authentication and authorization when accessing an API (Application Programming Interface). |
OCR | Optical Character Recognition; text recognition in images. |
OpenRouter | A service that provides access to various AI models via a unified API. |
Prerequisites
Before we start, make sure you have the following:
- A Server: This can be a home server or a public VPS. For this guide, I’m using a VPS from Hetzner (Affiliate link: As a new customer, you’ll receive a €20 starting credit with this link). The server should be running a Linux operating system (e.g., Ubuntu).
- (Optional, but recommended) A Domain: If you want to access Karakeep securely and easily over the internet, a domain pointing to your server’s IP address is very useful.
Installing Karakeep with Docker Compose
Installing Karakeep is relatively straightforward thanks to Docker Compose. Since Karakeep is still under development (beta status), it’s advisable to always keep an eye on the official Karakeep documentation, as details may change.
0. Install Docker and Docker Compose
First, we connect to our server via SSH and ensure Docker is installed. If not, Docker and Docker Compose need to be installed. It’s best to follow the official documentation.
For Ubuntu, execute the following:
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
And then:
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
1. Create a Directory and compose.yaml
File
We create a directory for Karakeep.
mkdir karakeep
cd karakeep
Next, we create the compose.yaml
file. This file describes how our Karakeep application should be started with Docker.
nano compose.yaml
Copy the following content into the file. Make sure to adjust the image version!
services:
web:
image: ghcr.io/karakeep-app/karakeep:0.24.1 # Check the current version on GitHub!
container_name: karakeep_web # Needed later for the reverse proxy
restart: unless-stopped
ports:
- "3005:3000" # Host-Port:Container-Port (can be adjusted)
env_file:
- .env
volumes:
- ./data:/data # Bind mount for Karakeep data
depends_on:
- chrome
- meilisearch
networks: # Needed later for the reverse proxy
- internal
# - proxy # Commented out for now, add later
chrome:
image: gcr.io/zenika-hub/alpine-chrome:123
restart: unless-stopped
command:
- --no-sandbox
- --disable-gpu
- --disable-dev-shm-usage
- --remote-debugging-address=0.0.0.0
- --remote-debugging-port=9222
- --hide-scrollbars
networks:
- internal
meilisearch:
image: getmeili/meilisearch:v1.13.3
restart: unless-stopped
env_file:
- .env
environment:
MEILI_NO_ANALYTICS: "true"
volumes:
- ./meilisearch_data:/meili_data
networks:
internal:
external: false
# proxy: # Commented out for now
# external: true # Commented out for now
Important notes on compose.yaml
:
- Image Version: I used
0.24.1
. Go to Karakeep GitHub Packages and find the latest stable version (avoidlatest
, as this can lead to unexpected updates). Adjust the version forweb
andchrome
if necessary. - Volumes: I’m using bind mounts here (
./data
and./meilisearch_data
). This means the data will be stored in subdirectories relative to yourcompose.yaml
. Create these folders:mkdir data mkdir meilisearch_data
- Ports:
3005:3000
means Karakeep will be accessible on port 3005 of your server and will forward requests to port 3000 in the container. If port 3005 is busy, choose another one (e.g.,3006:3000
). - Networks: The
proxy
network definitions are commented out for now. We will activate them later for the reverse proxy.
Save the file (in nano
with Ctrl+X
, then Y
and Enter
).
2. Create the .env
File
The .env
file contains configuration variables.
nano .env
Add the following content and adjust the values:
MEILI_MASTER_KEY=YOUR_SUPER_SECRET_KEY_1
NEXTAUTH_SECRET=YOUR_SUPER_SECRET_KEY_2
NEXTAUTH_URL=http://localhost:3000
Important:
Replace YOUR_SUPER_SECRET_KEY_1
and _2
with long, random strings. You can generate them, for example, like this:
openssl rand -base64 36
Run the command twice and copy the results into the .env
file.
Save the file.
3. Start Karakeep Containers
Now we can start Karakeep:
sudo docker compose up -d
Docker will now download the images and start the containers in the background (-d
). This might take a while the first time.
You can check the status of the containers:
sudo docker compose ps
# Or view the logs:
sudo docker compose logs -f
# Or check resource usage:
sudo docker compose stats
Normally, the containers should be running after a short time. The logs can be very helpful in case of problems. On the first start, Meilisearch might need some time for indexing.
4. First Access and Create Admin Account
Open your web browser and enter the IP address with the port from your compose.yaml
.
You should see the Karakeep login screen.
- Click on “Sign up”.
- Create your user account. The first user automatically becomes the administrator.
Log in and explore the interface! You can change the language in the user settings (gear icon top right -> User Settings -> Interface).
Basic Configuration and First Steps
After successful installation and the first login, I recommend making a few basic settings.
Disable Signups (DISABLE_SIGNUPS)
Once you’ve created your admin account, it’s advisable to disable public registration unless you want anyone to be able to sign up.
- Open the
.env
file:nano .env
- Add the following line:
DISABLE_SIGNUPS=true
- Save the file and restart Karakeep for the changes to take effect:
sudo docker compose down sudo docker compose up -d
If you now log out and try to register again (“Sign up”), you should see a message that registrations are disabled.
Set OCR Languages (OCR_LANGS)
If you want Karakeep to recognize text in images (OCR), you can set the languages for it.
- Open the
.env
file. - Add (e.g., for English and German):
OCR_LANGS=eng,deu
- Save and restart Karakeep:
sudo docker compose down sudo docker compose up -d
(Optional) Advanced Features with AI
Karakeep offers optional AI features like automatic tagging and summaries. This is not active by default. If you want to use your own API key (e.g., from OpenAI or OpenRouter):
I like to use OpenRouter as it gives me access to various models.
- Get an API Key: Create an account at OpenRouter.ai and generate an API key. Top up your balance if necessary.
- Adjust the
.env
file:
Add/change the following variables:nano .env
You can find a list of available models on the OpenRouter website.OPENAI_API_KEY=YOUR_OPENROUTER_API_KEY # Your key from OpenRouter OPENAI_BASE_URL=https://openrouter.ai/api/v1 INFERENCE_TEXT_MODEL=google/gemini-2.5-flash-preview INFERENCE_IMAGE_MODEL=google/gemini-2.5-flash-preview
- Restart Karakeep:
sudo docker compose down sudo docker compose up -d
Now, when you add bookmarks, tags should be generated automatically. You can also try to have articles summarized. Using the API costs money, but with moderate use and inexpensive models (like Gemini Flash), the costs are manageable (often less than a cent per request). Free models are also available, but they are less reliable (not in terms of results, but regarding rate limits, etc.).
Integrate RSS Feeds
Under “User Settings” -> “RSS”, you can add RSS feeds (e.g., from your favorite blog https://deployn.de/rss.xml
). Karakeep will then import the articles, and you can read and manage them directly in the app – optionally, have them automatically tagged too!
Set up a Reverse Proxy with Caddy (HTTPS and Domain)
To securely access Karakeep via a domain with HTTPS (e.g., https://karakeep.yourdomain.com
), we’ll set up a reverse proxy with Caddy. Caddy automatically handles SSL certificates from Let’s Encrypt.
1. Prepare Karakeep
a) Adjust Container Name and Networks in Karakeep’s compose.yaml
:
We have already defined container_name: karakeep_web
in Karakeep’s compose.yaml
. Now, we’ll adjust the network settings.
Open Karakeep’s compose.yaml
:
cd ~/karakeep # Make sure you are in the Karakeep directory
nano compose.yaml
Remove the port mapping and activate the proxy
network for the web
service:
services:
web:
image: ghcr.io/karabot/karakeep/web:0.24.1
container_name: karakeep_web # Important for Caddy
restart: unless-stopped
# ports: # Comment out or delete this line
# - "3005:3000" # Comment out or delete this line
env_file:
- .env
volumes:
- ./data:/data
depends_on:
- chrome
- meilisearch
networks: # Adjust networks
- internal
- proxy # Add this network
chrome:
image: ghcr.io/karabot/karakeep/chrome:0.24.1
restart: unless-stopped
shm_size: '1gb'
cap_add:
- SYS_ADMIN
networks: # Only internal
- internal
meilisearch:
image: getmeili/meilisearch:v1.7
restart: unless-stopped
environment:
- MEILI_ENV=production
- MEILI_MASTER_KEY=${MEILISEARCH_MASTER_KEY}
volumes:
- ./meilisearch_data:/meili_data
networks: # Only internal
- internal
networks:
internal:
driver: bridge
proxy: # Activate this section
external: true # Means the network is managed outside this Compose file
Save the changes.
b) Adjust NEXTAUTH_URL
in .env
:
Open Karakeep’s .env
file:
nano .env
Change NEXTAUTH_URL
to your future HTTPS domain:
NEXTAUTH_URL=https://karakeep.yourdomain.com
Save the file.
2. Create Docker Network for the Proxy
This network will be shared by Caddy and Karakeep.
sudo docker network create proxy
(If it already exists, that’s okay.)
3. Set up Caddy
We will create a separate directory for Caddy.
cd ~ # Go to home directory
mkdir caddy
cd caddy
mkdir data config # Subdirectories for Caddy data and configuration
a) Create Caddy compose.yaml
:
nano compose.yaml
Content:
services:
caddy:
image: caddy:latest
container_name: caddy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile # Configuration file
- ./data:/data # For certificates and other data
- ./config:/config # For Caddy configuration
networks:
- proxy # Assign Caddy to the proxy network
networks:
proxy:
external: true
Save the file.
b) Create Caddyfile
:
This is the configuration file for Caddy.
nano Caddyfile
Content (replace karakeep.yourdomain.com
with your domain and provide your email address for Let’s Encrypt notifications):
karakeep.yourdomain.com {
encode gzip
# Forward to the Karakeep web container via the Docker network
# karakeep_web is the container_name from the Karakeep compose.yaml
# 3000 is the internal port of Karakeep in the container
reverse_proxy karakeep_web:3000
}
Save the file. Make sure your domain (e.g., karakeep.yourdomain.com
) points to your server’s IP address via a DNS A-record!
4. Restart Caddy and Karakeep
First, we start Caddy:
cd ~/caddy # Change to the Caddy directory
sudo docker compose up -d
Then, we restart Karakeep so it picks up the network changes:
cd ~/karakeep # Change to the Karakeep directory
sudo docker compose down # Stops and removes the old containers
sudo docker compose up -d # Starts Karakeep with the new configuration
5. Access via HTTPS Domain
Wait a moment for Caddy to issue the SSL certificate. You should now be able to reach Karakeep at https://karakeep.yourdomain.com
.
Updating Karakeep
To update Karakeep:
- Check Karakeep GitHub Packages for a new version.
- Stop the running Karakeep containers:
cd ~/karakeep sudo docker compose down
- Edit your
compose.yaml
and change the image tags forweb
andchrome
to the new version. - Pull the new images:
sudo docker compose pull
- Restart Karakeep:
sudo docker compose up -d
Always read the release notes in case there are breaking changes!
Conclusion
Karakeep is a powerful and flexible bookmark manager that can be self-hosted relatively easily thanks to Docker and Docker Compose. With a reverse proxy like Caddy, access becomes secure and user-friendly. The optional AI features and RSS integration complete the package, making Karakeep a central hub.
I hope this guide has helped you! Are you already using a self-hosted bookmark manager? Which features are most important to you? Feel free to write it in the comments!
FAQ
FAQs
What is Karakeep?
Karakeep is an open-source application for managing bookmarks, notes, images, and RSS feeds. It can be hosted on your own server.
Why should I use Docker Compose for the installation?
Docker Compose simplifies the definition and execution of applications consisting of multiple containers (like Karakeep with its web service, Chrome service, and Meilisearch database). The entire configuration is bundled in a `compose.yaml` file.
Can I use the 'latest' tag for Docker images?
It is generally recommended to use specific version tags (e.g., `0.24.1`) instead of `latest`. The `latest` tag can change unexpectedly and lead to incompatibilities or errors, especially with beta software.
What is a bind mount and why is it used here?
A bind mount links a directory on your host system (the server) directly with a directory in the Docker container. This ensures that Karakeep's data (bookmarks, configuration, etc.) and Meilisearch's data (search index) are stored persistently, even if the containers are stopped or recreated.
Do I absolutely need a reverse proxy like Caddy?
Not strictly necessary for pure functionality, but highly recommended. A reverse proxy allows access via an easy-to-remember domain, provides HTTPS (encrypted connection), and can enhance security. Caddy also automates the procurement and renewal of SSL certificates.
How do I update Karakeep to a newer version?
Stop the containers (`sudo docker compose down`), change the image version in your `compose.yaml` file, pull the new images (`sudo docker compose pull`), and restart the containers (`sudo docker compose up -d`).
What should I do if something doesn't work after starting?
Check the container logs with `sudo docker compose logs -f web` (or `chrome`, `meilisearch`). Error messages indicating the problem are often found there. Also, ensure that all paths and environment variables are set correctly.