All templates

Linkwarden

v1.0.0

Collaborative bookmarks with archived screenshots, PDFs, and search.

bookmarksproductivity by getarcaneapp
x-arcane:
  icon: "https://cdn.jsdelivr.net/gh/selfhst/icons@main/svg/linkwarden.svg"
  urls:
    - "https://docs.linkwarden.app/self-hosting/installation"
services:
  linkwarden:
    image: "ghcr.io/linkwarden/linkwarden:latest"
    restart: "unless-stopped"
    ports:
      - "${PORT:-3000}:3000"
    environment:
      DATABASE_URL: "postgresql://linkwarden:${DB_PASSWORD:?Set DB_PASSWORD in .env}@db:5432/linkwarden"
      NEXTAUTH_URL: "${NEXTAUTH_URL:-http://localhost:3000/api/v1/auth}"
      NEXTAUTH_SECRET: "${NEXTAUTH_SECRET:?Set NEXTAUTH_SECRET in .env}"
      MEILI_HOST: "http://meilisearch:7700"
      MEILI_MASTER_KEY: "${MEILI_MASTER_KEY:?Set MEILI_MASTER_KEY in .env}"
      NEXT_PUBLIC_DISABLE_REGISTRATION: "${DISABLE_REGISTRATION:-false}"
    volumes:
      - "data:/data/data"
    depends_on:
      db:
        condition: "service_healthy"
      meilisearch:
        condition: "service_healthy"
    labels:
      com.getarcaneapp.arcane.icon: "https://cdn.jsdelivr.net/gh/selfhst/icons@main/svg/linkwarden.svg"
  db:
    image: "postgres:16-alpine"
    restart: "unless-stopped"
    environment:
      POSTGRES_DB: "linkwarden"
      POSTGRES_USER: "linkwarden"
      POSTGRES_PASSWORD: "${DB_PASSWORD:?Set DB_PASSWORD in .env}"
    volumes:
      - "db-data:/var/lib/postgresql/data"
    healthcheck:
      test:
        - "CMD-SHELL"
        - "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"
      interval: "10s"
      timeout: "5s"
      retries: 10
      start_period: "30s"
    labels:
      com.getarcaneapp.arcane.icon: https://cdn.jsdelivr.net/gh/selfhst/icons@main/svg/postgresql.svg
  meilisearch:
    image: "getmeili/meilisearch:v1.13.3"
    restart: "unless-stopped"
    environment:
      MEILI_MASTER_KEY: "${MEILI_MASTER_KEY:?Set MEILI_MASTER_KEY in .env}"
      MEILI_NO_ANALYTICS: "true"
    volumes:
      - "search-data:/meili_data"
    healthcheck:
      test:
        - "CMD"
        - "curl"
        - "-f"
        - "http://localhost:7700/health"
      interval: "10s"
      timeout: "5s"
      retries: 10
      start_period: "30s"
    labels:
      com.getarcaneapp.arcane.icon: https://cdn.jsdelivr.net/gh/selfhst/icons@main/svg/meilisearch.svg
volumes:
  data: {}
  db-data: {}
  search-data: {}

README

Collaborative bookmarks with archived screenshots, PDFs, and search.

Copy .env.example to .env, review the settings, then run docker compose up -d. In Arcane, import the template and supply the same environment variables. Replace every change-me value before starting. Generate independent secrets with openssl rand -hex 32; use hexadecimal database passwords so connection URLs need no escaping. Use docker compose ps and docker compose logs to check startup.

Open http://localhost:3000 and register the first user. Set DISABLE_REGISTRATION=true after provisioning users. NEXTAUTH_URL must include /api/v1/auth after the public origin. Bookmark records live in PostgreSQL, archives in the data volume, and search indexes in Meilisearch.

Named volumes preserve server data across container recreation. Back up these volumes before upgrades; docker compose down -v deletes them. Set PORT to an unused host port. For remote browser access, put HTTPS in front of the application and update its public URL setting where provided.

Upstream documentation: Linkwarden deployment.