Skip to content

How to Deploy Karakeep on a VPS

Updated Sep 2026

verified on Ubuntu 26.04 · Sep 2026
We earn commissions when you shop through the links below. Full disclosure →

Self-host Karakeep (formerly Hoarder) on a VPS with Docker Compose — bookmarks, notes and images crawled and full-text searchable, with signups closed and the crawler's risks understood.

Before you start
  • A VPS with 2 GB RAM or more — the headless Chrome crawler is the heavy part
  • A fresh Ubuntu 24.04 or 26.04 server with root/sudo SSH access
  • A domain you can point at the server
  • Docker Engine + Compose installed (see the base guide below)
Need a box for this guide? Kamatera's free tier lets you spin one up now.Start free on Kamatera → (opens in new tab)

What Karakeep is

Karakeep — called Hoarder until its rename — is a "bookmark everything" app. You save links, notes, images and PDFs; Karakeep crawls each link, keeps the page's title, description and content, and makes all of it full-text searchable. Optional AI tagging, through OpenAI or a local model via Ollama, labels things for you as they come in. Browser extensions and mobile apps make saving a one-tap job.

It is a TypeScript / Next.js application under the AGPL-3.0 licence. The official Compose stack runs three containers: the Karakeep web app (which also runs the background workers), a headless Chrome used by the crawler, and Meilisearch for search.

If you only need a list of links with tags, linkding is much lighter; Karakeep vs linkding compares the two. Karakeep earns its extra weight when you want the content of what you saved, not just the URL.

Server sizing

The catalog lists 2 GB of RAM as the minimum. On our test box — a GCP e2-standard-2 with Ubuntu 26.04 and Docker 29.8.1 — the three containers sat at about 679 MB of RAM idle, and the images plus volumes used about 2.8 GB of disk. Crawling is where memory goes: every saved link opens a page in Chrome, so a burst of imports briefly costs much more than idle.

Disk grows with what you save. Pages, screenshots and uploaded files live in the data volume; the search index in the meilisearch volume. Start with 20–40 GB.

Prepare the server

This guide assumes Docker Engine and the Compose plugin are installed, with a ufw firewall. If not, start with Docker & Compose on Ubuntu.

sudo ufw allow OpenSSH
sudo ufw allow 80
sudo ufw allow 443
sudo ufw --force enable
sudo ufw status verbose
Where to host itaffiliate disclosure
Hetzner Cloudrun it on
2 vCPU · 4 GB RAM · 80 GB SSD · $23.59/mo
Get Hetzner Cloud (opens in new tab)
Kamaterafree trial
1 vCPU · 1 GB RAM · 20 GB SSD · $4.00/mo
Start free on Kamatera → (opens in new tab)
DigitalOceanalso works on
1 vCPU · 1 GB RAM · 25 GB SSD · $6.00/mo
Deploy on DigitalOcean → (opens in new tab)

Paid link — we earn a commission if you shop through it.

Install Karakeep (Docker Compose)

Follow the upstream Docker install: make a directory, download the official Compose file into it, and write a .env beside it.

mkdir -p ~/karakeep && cd ~/karakeep
curl -fsSL -o docker-compose.yml https://raw.githubusercontent.com/karakeep-app/karakeep/main/docker/docker-compose.yml

The upstream file publishes port 3000 on every interface. Bind it to loopback so Caddy is the only way in:

cd ~/karakeep
sed -i 's|- 3000:3000|- 127.0.0.1:3000:3000|' docker-compose.yml
grep -n '3000' docker-compose.yml

Now the environment. NEXTAUTH_SECRET and MEILI_MASTER_KEY must be random — the docs suggest openssl rand -base64 36 — and NEXTAUTH_URL should be the address users will reach, which after the HTTPS step is your domain:

cd ~/karakeep
[ -f .env ] || cat > .env <<EOF
KARAKEEP_VERSION=release
NEXTAUTH_SECRET=$(openssl rand -base64 36)
MEILI_MASTER_KEY=$(openssl rand -base64 36)
NEXTAUTH_URL=https://bookmarks.example.com
EOF
docker compose up -d
docker compose ps

KARAKEEP_VERSION=release follows the latest stable release. Upstream suggests pinning a version instead (for example KARAKEEP_VERSION=0.33.2) if you want to decide when upgrades happen.

Wait for the web app to answer:

for i in $(seq 1 60); do
  code=$(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:3000/)
  case "$code" in 200|307|302) echo "Karakeep is up ($code)"; break ;; esac
  sleep 5
done
case "$code" in 200|307|302) true ;; *) docker compose logs --tail 50 web; false ;; esac

Optional: AI tagging

AI tagging is off until you give it a provider. For OpenAI, add the key to .env and re-run docker compose up -d:

cd ~/karakeep
echo "OPENAI_API_KEY=sk-..." >> .env
docker compose up -d

For local inference, the upstream "different AI providers" page covers Ollama; see Deploy Ollama on a VPS for running it. A tagging model on CPU is slow, so budget RAM for it separately from Karakeep.

HTTPS + domain

Point an A record for bookmarks.example.com at the server — it must match NEXTAUTH_URL exactly, or sign-in and sign-out redirect to the wrong address. Then terminate TLS in front of 127.0.0.1:3000, following Automatic HTTPS with Caddy:

bookmarks.example.com {
    reverse_proxy 127.0.0.1:3000
}

If Caddy runs in a container, 127.0.0.1 is its own loopback: put it in the same Compose project and proxy to web:3000 instead.

First account, then close signups

Open https://bookmarks.example.com and sign up. The first account created becomes the admin. Then close registration, so nobody else who finds the URL can create an account:

cd ~/karakeep
grep -q '^DISABLE_SIGNUPS=' .env || echo "DISABLE_SIGNUPS=true" >> .env
docker compose up -d

Every change to .env needs another docker compose up -d to take effect. With DISABLE_SIGNUPS=true, the signup button is disabled. The Admin Settings page lists users and lets an administrator reset their passwords; to add someone later, remove the line, let them sign up, and put it back.

Install the browser extension and mobile app next, pointed at your server URL — that is where most saving happens in practice.

Securing it: the crawler

Karakeep's upstream docs have a security page that is worth reading before you share an instance, because the crawler is a real browser running on your server:

  • Anyone with an account can make your server fetch any URL, and see the result.
  • Crawling a site the user controls reveals your server's IP address, even if the app itself sits behind a CDN.
  • Requests come from inside your network, so they could reach internal endpoints (Karakeep has basic SSRF protections, which upstream says mitigate only some of this).

The upstream mitigations: keep accounts to trusted users, route the browser's traffic through a VPN or proxy with restricted network access, or run the browser container somewhere else. For a personal instance with signups closed, the first one is usually enough.

Backups

State lives in two named volumes: data (the database, saved pages and assets) and meilisearch (the search index). With the project directory named karakeep, Compose names them karakeep_data and karakeep_meilisearch. Stop the stack for a consistent copy:

cd ~/karakeep
docker compose stop
docker run --rm -v karakeep_data:/data -v "$(pwd)":/backup alpine \
  tar czf /backup/karakeep-data-$(date +%F).tar.gz -C /data .
docker run --rm -v karakeep_meilisearch:/meili -v "$(pwd)":/backup alpine \
  tar czf /backup/karakeep-meili-$(date +%F).tar.gz -C /meili .
docker compose start
ls -la karakeep-*.tar.gz

Keep .env with the backups (it holds the secrets the data was created with), confirm the volume names with docker volume ls, and copy everything off the server. Karakeep also has an API for creating and downloading backups, if you prefer to script it that way.

Upgrades

How you upgrade depends on KARAKEEP_VERSION. With release, force a fresh pull:

cd ~/karakeep
docker compose up --pull always -d

With a pinned version, bump it in .env and run docker compose up -d. The Compose file pins Meilisearch separately; upstream's troubleshooting page covers upgrading or migrating Meilisearch versions, which needs more care than the app itself. Back up first.

Troubleshooting

Links save but have no content or preview. The crawler can't reach Chrome. Check docker compose ps shows the chrome container running, and docker compose logs web for crawler errors.

Sign-in or sign-out lands on the wrong address. NEXTAUTH_URL doesn't match the URL in the browser. Fix it in .env and run docker compose up -d.

Search returns nothing. Check the meilisearch container is up and that MEILI_MASTER_KEY hasn't changed since the index was created.

The box runs out of memory during an import. Crawling many links at once launches many pages; import in smaller batches or add RAM.

Verification + next steps

You're done when you can load https://bookmarks.example.com over a valid certificate, save a link from the browser extension and find it by searching for a word in the page's text, see the signup button disabled in a private window, and have a backup of both volumes off the box.

If you want page archives with screenshots and PDFs and shared collections, compare Linkwarden. For hosts, see Best VPS for Self-Hosting.

Next steps

How to self-host Karakeep →More self-hosted bookmarks tools →Automatic HTTPS with Caddy →Run Claude Code with Ollama on Your Own VPS →Deploy Coolify on a VPS →How to Deploy Actual Budget on a VPS →How to Deploy AnythingLLM on a VPS →How to Deploy Appwrite on a VPS →How to Deploy Audiobookshelf on a VPS →How to Deploy Authelia on a VPS →How to Deploy authentik on a VPS →How to Deploy Baserow on a VPS →How to Deploy Beszel on a VPS →How to Deploy Bitwarden on a VPS →How to Deploy BookStack on a VPS →How to Deploy CapRover on a VPS →How to Deploy Checkmate on a VPS →How to Deploy Directus on a VPS →How to Deploy docker-mailserver on a VPS →How to Deploy Docmost on a VPS →How to Deploy Dokku on a VPS →How to Deploy Dokploy on a VPS →How to Deploy Firefly III on a VPS →How to Deploy Forgejo on a VPS →How to Deploy Gatus on a VPS →How to Deploy Ghostfolio on a VPS →How to Deploy Gitea on a VPS →How to Deploy GitLab on a VPS →How to Deploy GlitchTip on a VPS →How to Deploy Grafana on a VPS →How to Deploy Graylog on a VPS →How to Deploy Headscale on a VPS →How to Deploy Healthchecks on a VPS →How to Deploy Home Assistant on a VPS →How to Deploy Immich on a VPS →How to Deploy Jan on a VPS →How to Deploy Jellyfin on a VPS →How to Deploy Keycloak on a VPS →How to Deploy Leantime on a VPS →How to Deploy LibreChat on a VPS →How to Deploy Linkwarden on a VPS →How to Deploy LocalAI on a VPS →How to Deploy Mailcow on a VPS →How to Deploy Mailu on a VPS →How to Deploy Matomo on a VPS →How to Deploy Mattermost on a VPS →How to Deploy Meilisearch on a VPS →How to Deploy Memos on a VPS →How to Deploy n8n on a VPS →How to Deploy Navidrome on a VPS →How to Deploy NetBird on a VPS →How to Deploy Netdata on a VPS →How to Deploy Nextcloud on a VPS →How to Deploy Next.js to a VPS →How to Deploy Nginx Proxy Manager on a VPS →How to Deploy NocoDB on a VPS →How to Deploy ntfy on a VPS →How to Deploy Ollama on a VPS →How to Deploy Open WebUI on a VPS →How to Deploy OpenHands on a VPS →How to Deploy OpenObserve on a VPS →How to Deploy OpenProject on a VPS →How to Deploy Outline on a VPS →How to Deploy Pangolin on a VPS →How to Deploy Paperless-ngx on a VPS →How to Deploy Passbolt on a VPS →How to Deploy Plane on a VPS →How to Deploy Plausible Analytics on a VPS →How to Deploy Pocket ID on a VPS →How to Deploy PocketBase on a VPS →How to Deploy Prometheus on a VPS →How to Deploy Psono on a VPS →How to Deploy Radarr on a VPS →How to Deploy Rocket.Chat on a VPS →How to Deploy SigNoz on a VPS →How to Deploy Sonarr on a VPS →How to Deploy Stalwart on a VPS →How to Deploy Stirling-PDF on a VPS →How to Deploy Supabase on a VPS →How to Deploy Synapse on a VPS →How to Deploy Taiga on a VPS →How to Deploy TeamPass on a VPS →How to Deploy Tinyauth on a VPS →How to Deploy Traefik on a VPS →How to Deploy Trilium on a VPS →How to Deploy Twenty CRM on a VPS →How to Deploy Umami on a VPS →How to Deploy Uptime Kuma on a VPS →How to Deploy Vaultwarden on a VPS →How to Deploy Vikunja on a VPS →How to Deploy wg-easy on a VPS →How to Deploy Wiki.js on a VPS →How to Deploy Zabbix on a VPS →How to Deploy Zitadel on a VPS →How to Deploy Zulip on a VPS →Docker & Compose on Ubuntu 26.04 →Building AI Workflows with n8n →Install Open WebUI with Ollama →Adding AI-Powered Insights to Plausible Analytics →Building AI-Powered Apps with Supabase and pgvector →

We use analytics cookies (Google Analytics, PostHog) to see which guides are useful. No ad networks, no cross-site tracking. See our privacy policy.