Run Linkding as a Self-Hosted Bookmark Manager With Docker Compose

Stand up a clean private bookmark manager that is easy to back up, easy to proxy, and modest enough not to turn a simple personal knowledge tool into an infrastructure project.

Linkding Docker Compose Bookmarks
Illustrated guide cover for Run Linkding as a Self-Hosted Bookmark Manager With Docker Compose
Linkding • Docker Compose • Bookmarks
What you learn

How to deploy Linkding with Compose, persist its SQLite data, create the initial admin account, and proxy it without breaking host headers.

Best for

People who want a small self-hosted place for bookmarks, saved articles, and browser-extension captures without a heavy knowledge-management suite.

Risk to watch

The easy mistake is forgetting the first-user setup or misconfiguring proxy headers so login and CSRF-protected actions fail in annoying ways.

Before you begin

  • A Docker host with the Compose plugin.
  • A private or authenticated hostname, such as links.example.com.
  • A directory for persistent data.
  • A plan for backups if the bookmarks matter.

Linkding's installation docs still describe Docker and Docker Compose as the primary deployment path. The project uses SQLite by default, stores its data under /etc/linkding/data, and does not create an initial user for you unless you configure an automatic superuser option.

Expected outcome: you will finish with Linkding available through a private URL, with persistent storage in place and a real admin account you created intentionally.

Step 1: Create the Compose files

Create the stack directory:

mkdir -p /opt/stacks/linkding/data
cd /opt/stacks/linkding

Save this as compose.yaml:

services:
  linkding:
    image: sissbruecker/linkding:latest
    container_name: linkding
    restart: unless-stopped
    ports:
      - 127.0.0.1:9090:9090
    volumes:
      - ./data:/etc/linkding/data
    env_file:
      - .env

Create a minimal .env:

LD_DISABLE_BACKGROUND_TASKS=False

The official docs provide an upstream docker-compose.yml and .env.sample. For a small local deployment, the simplified pattern above is enough as long as the data path is persistent.

Step 2: Start Linkding and create the first user

Start the stack:

docker compose up -d
docker compose ps

Then create the initial superuser:

docker compose exec linkding python manage.py createsuperuser --username=joe --email=joe@example.com

The project docs are explicit here: the Docker image does not provide an initial user by default, so you must create one after setup unless you intentionally use an automatic superuser option like LD_SUPERUSER_NAME.

Once the command completes, verify you can log in through the local bind before adding a reverse proxy.

Step 3: Put it behind Caddy or Nginx

A simple Caddy entry:

links.example.com {
  reverse_proxy 127.0.0.1:9090
}

A minimal Nginx server block:

server {
  listen 80;
  server_name links.example.com;

  location / {
    proxy_pass http://127.0.0.1:9090;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }
}

Linkding's docs warn that reverse proxies may need to forward the correct Host header or configure LD_CSRF_TRUSTED_ORIGINS when login or CSRF-protected requests fail.

Step 4: Operate and back it up

Routine checks:

docker compose ps
docker logs linkding --tail 50
ls -la /opt/stacks/linkding/data

For a small installation using SQLite, your backup boundary is straightforward: the data directory is the thing that matters. Protect it before upgrades and before experimenting with archiving-heavy features.

Step 5: Update the installation cleanly

Update Linkding by pulling the image and recreating the container against the same data directory:

cd /opt/stacks/linkding
docker compose pull
docker compose up -d

If you later switch to a different image variant, such as one that includes HTML snapshot archiving, review the extra disk and memory costs before making the change permanent.

Rollback notes

Linkding is easy to recover if you preserve the data mount. A rollback usually means restoring the previous image tag or putting the backed-up /etc/linkding/data contents back in place.

If login fails after a proxy change, revert the proxy headers first before assuming the application data is damaged.

Troubleshooting

The app starts but you cannot log in.
Confirm you actually created the initial superuser and are reaching the same instance you initialized.

Login works locally but fails behind Nginx.
Forward the correct Host and X-Forwarded-Proto headers, or set LD_CSRF_TRUSTED_ORIGINS.

Bookmarks vanish after a rebuild.
Check that the data path is mounted to /etc/linkding/data and not left inside the container filesystem.

You want a full team wiki, not just bookmarks.
That is a different product category. Linkding is strongest when it stays a fast, focused bookmark manager.