{
  "schema_version": 1,
  "generated_at": "2026-10-23T00:00:00.000Z",
  "canonical_url": "https://openlogs.fyi/tools/linkwarden",
  "slug": "linkwarden",
  "name": "Linkwarden",
  "tagline": "Bookmark manager that saves pages and organizes links into collections.",
  "replaces": {
    "summary": "Paid read-later services, such as Pocket.",
    "products": [
      {
        "slug": "pocket",
        "name": "Pocket",
        "vendor": "Mozilla",
        "url": "https://openlogs.fyi/alternatives/pocket"
      }
    ]
  },
  "stack": [
    {
      "kind": "language",
      "name": "TypeScript"
    },
    {
      "kind": "database",
      "name": "PostgreSQL"
    }
  ],
  "deployment_methods": [
    "docker_compose"
  ],
  "requirements": {
    "min_ram_mb": null,
    "min_cpu_cores": null,
    "source_url": null
  },
  "license": {
    "spdx": "AGPL-3.0",
    "class": "osi",
    "source_url": "https://github.com/linkwarden/linkwarden/blob/952ac4540657cae3a67c3ca59433899d2fda8374/LICENSE.md"
  },
  "business_model": {
    "value": "unknown",
    "notes": "The README at the pinned commit does not state a business model, so it stays unknown.",
    "source_url": "https://github.com/linkwarden/linkwarden/blob/952ac4540657cae3a67c3ca59433899d2fda8374/README.md",
    "checked_at": "2026-10-22"
  },
  "difficulty": {
    "value": "medium",
    "reason": "3 services (2 database or broker: postgres, meilisearch), 3 volume mounts, 2 env values to set, no elevated host access. Heuristic score 5 of 11: medium."
  },
  "repository": {
    "owner": "linkwarden",
    "name": "linkwarden",
    "url": "https://github.com/linkwarden/linkwarden"
  },
  "compose_check": {
    "status": "config_ok",
    "validated_at": "2026-10-22",
    "summary": "config_ok on 2026-10-22"
  },
  "recipe": {
    "version": 1,
    "source_path": "docker-compose.yml",
    "source_repo": "linkwarden/linkwarden",
    "source_commit_sha": "952ac4540657cae3a67c3ca59433899d2fda8374",
    "source_kind": "app_repo",
    "source_url": "https://github.com/linkwarden/linkwarden/blob/952ac4540657cae3a67c3ca59433899d2fda8374/docker-compose.yml"
  },
  "install_steps": [
    {
      "order": 1,
      "kind": "prerequisite",
      "language": "text",
      "label": "Docker with the Compose plugin",
      "body": "A host with Docker and the Docker Compose plugin. This entry runs from a compose file.",
      "source_url": "https://github.com/linkwarden/docs/blob/53e2dceda5b2a1b22d280298fba6b2123010f16d/docs/self-hosting/setup.md",
      "validation_status": "unvalidated"
    },
    {
      "order": 2,
      "kind": "compose",
      "language": "yaml",
      "label": "Save the compose file as docker-compose.yml",
      "body": "services:\n  postgres:\n    image: postgres:16-alpine\n    env_file: .env\n    restart: always\n    volumes:\n      - ./pgdata:/var/lib/postgresql/data\n  linkwarden:\n    env_file: .env\n    environment:\n      - DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/postgres\n    restart: always\n    image: ghcr.io/linkwarden/linkwarden:latest\n    ports:\n      - 3000:3000\n    volumes:\n      - ./data:/data/data\n    depends_on:\n      - postgres\n      - meilisearch\n  meilisearch:\n    image: getmeili/meilisearch:v1.13.3\n    restart: always\n    env_file:\n      - .env\n    volumes:\n      - ./meili_data:/meili_data\n",
      "source_url": "https://github.com/linkwarden/linkwarden/blob/952ac4540657cae3a67c3ca59433899d2fda8374/docker-compose.yml",
      "validation_status": "config_ok"
    },
    {
      "order": 3,
      "kind": "env",
      "language": "dotenv",
      "label": "Save as .env next to the compose file",
      "body": "# Full list of environment variables with descriptions can be found in the documentation: https://docs.linkwarden.app/self-hosting/environment-variables\n\nNEXTAUTH_URL=http://localhost:3000/api/v1/auth\nNEXTAUTH_SECRET=\n\n# Manual installation database settings\n# Example: DATABASE_URL=postgresql://user:password@localhost:5432/linkwarden\nDATABASE_URL=\n\n# Docker installation database settings\nPOSTGRES_PASSWORD=\n\n# Additional Optional Settings\nPAGINATION_TAKE_COUNT=\nSTORAGE_FOLDER=\nAUTOSCROLL_TIMEOUT=\nNEXT_PUBLIC_DISABLE_REGISTRATION=\nNEXT_PUBLIC_CREDENTIALS_ENABLED=\nDISABLE_NEW_SSO_USERS=\nMAX_LINKS_PER_USER=\nARCHIVE_TAKE_COUNT=\nBROWSER_TIMEOUT=\nBROWSER_LIFECYCLE=\nIGNORE_URL_SIZE_LIMIT=\nNEXT_PUBLIC_DEMO=\nNEXT_PUBLIC_DEMO_USERNAME=\nNEXT_PUBLIC_DEMO_PASSWORD=\nNEXT_PUBLIC_ADMIN=\nNEXT_PUBLIC_MAX_FILE_BUFFER=\nPDF_MAX_BUFFER=\nSCREENSHOT_MAX_BUFFER=\nREADABILITY_MAX_BUFFER=\nPREVIEW_MAX_BUFFER=\nMONOLITH_MAX_BUFFER=\nMONOLITH_CUSTOM_OPTIONS=\nIMPORT_LIMIT=\nPLAYWRIGHT_LAUNCH_OPTIONS_EXECUTABLE_PATH=\nPLAYWRIGHT_WS_URL=\nMAX_WORKERS=\nDISABLE_BROWSER=\nNEXT_PUBLIC_RSS_POLLING_INTERVAL_MINUTES=\nRSS_SUBSCRIPTION_LIMIT_PER_USER=\nTEXT_CONTENT_LIMIT=\nSEARCH_FILTER_LIMIT=\nINDEX_TAKE_COUNT=\nMEILI_TIMEOUT=\nALLOW_PRIVATE_NETWORK_ACCESS=\nALLOW_INSECURE_TLS=\nNEXT_PUBLIC_USER_CONTENT_DOMAIN=\nNEXT_PUBLIC_MOBILE_APP_REDIRECT_ENABLED=\n\n# AI Settings\nNEXT_PUBLIC_OLLAMA_ENDPOINT_URL=\nOLLAMA_MODEL=\n\n# https://ai-sdk.dev/providers/openai-compatible-providers\nOPENAI_API_KEY=\nOPENAI_MODEL=\n# Optional: Set a custom OpenAI base URL and name (for third-party providers)\nCUSTOM_OPENAI_BASE_URL=\nCUSTOM_OPENAI_NAME=\n\n# https://sdk.vercel.ai/providers/ai-sdk-providers/azure\nAZURE_API_KEY=\nAZURE_RESOURCE_NAME=\nAZURE_MODEL=\n\n# https://sdk.vercel.ai/providers/ai-sdk-providers/anthropic\nANTHROPIC_API_KEY=\nANTHROPIC_MODEL=\n\n# https://github.com/OpenRouterTeam/ai-sdk-provider\nOPENROUTER_API_KEY=\nOPENROUTER_MODEL=\n\n# https://ai-sdk.dev/providers/ai-sdk-providers/perplexity\nPERPLEXITY_API_KEY=\nPERPLEXITY_MODEL=\n\n# MeiliSearch Settings\nMEILI_HOST=\nMEILI_MASTER_KEY=\n\n# AWS S3 Settings\nSPACES_KEY=\nSPACES_SECRET=\nSPACES_ENDPOINT=\nSPACES_BUCKET_NAME=\nSPACES_REGION=\nSPACES_FORCE_PATH_STYLE=\n\n# SMTP Settings\nNEXT_PUBLIC_EMAIL_PROVIDER=\nEMAIL_FROM=\nEMAIL_SERVER=\nBASE_URL=\n\n# Proxy settings\nPROXY=\nPROXY_USERNAME=\nPROXY_PASSWORD=\nPROXY_BYPASS=\n\n# PDF archive settings\nPDF_MARGIN_TOP=\nPDF_MARGIN_BOTTOM=\n\n#################\n# SSO Providers #\n#################\n\n# 42 School\nNEXT_PUBLIC_FORTYTWO_ENABLED=\nFORTYTWO_CUSTOM_NAME=\nFORTYTWO_CLIENT_ID=\nFORTYTWO_CLIENT_SECRET=\n\n# Apple\nNEXT_PUBLIC_APPLE_ENABLED=\nAPPLE_CUSTOM_NAME=\nAPPLE_CLIENT_ID=\nAPPLE_TEAM_ID=\nAPPLE_KEY_ID=\nAPPLE_PRIVATE_KEY=\nAPPLE_CLIENT_SECRET=\n\n# Atlassian\nNEXT_PUBLIC_ATLASSIAN_ENABLED=\nATLASSIAN_CUSTOM_NAME=\nATLASSIAN_CLIENT_ID=\nATLASSIAN_CLIENT_SECRET=\nATLASSIAN_SCOPE=\n\n# Auth0\nNEXT_PUBLIC_AUTH0_ENABLED=\nAUTH0_CUSTOM_NAME=\nAUTH0_ISSUER=\nAUTH0_CLIENT_SECRET=\nAUTH0_CLIENT_ID=\n\n# Authelia\nNEXT_PUBLIC_AUTHELIA_ENABLED=\nAUTHELIA_CLIENT_ID=\nAUTHELIA_CLIENT_SECRET=\nAUTHELIA_WELLKNOWN_URL=\n\n# Authentik\nNEXT_PUBLIC_AUTHENTIK_ENABLED=\nAUTHENTIK_CUSTOM_NAME=\nAUTHENTIK_ISSUER=\nAUTHENTIK_CLIENT_ID=\nAUTHENTIK_CLIENT_SECRET=\n\n# Azure AD B2C\nNEXT_PUBLIC_AZURE_AD_B2C_ENABLED=\nAZURE_AD_B2C_TENANT_NAME=\nAZURE_AD_B2C_CLIENT_ID=\nAZURE_AD_B2C_CLIENT_SECRET=\nAZURE_AD_B2C_PRIMARY_USER_FLOW=\n\n# Azure AD\nNEXT_PUBLIC_AZURE_AD_ENABLED=\nAZURE_AD_CLIENT_ID=\nAZURE_AD_CLIENT_SECRET=\nAZURE_AD_TENANT_ID=\n\n# Battle.net\nNEXT_PUBLIC_BATTLENET_ENABLED=\nBATTLENET_CUSTOM_NAME=\nBATTLENET_CLIENT_ID=\nBATTLENET_CLIENT_SECRET=\nBATTLENET_ISSUER=\n\n# Box\nNEXT_PUBLIC_BOX_ENABLED=\nBOX_CUSTOM_NAME=\nBOX_CLIENT_ID=\nBOX_CLIENT_SECRET=\n\n# Bungie\nNEXT_PUBLIC_BUNGIE_ENABLED=\nBUNGIE_CUSTOM_NAME=\nBUNGIE_CLIENT_ID=\nBUNGIE_CLIENT_SECRET=\nBUNGIE_API_KEY=\n\n# Cognito\nNEXT_PUBLIC_COGNITO_ENABLED=\nCOGNITO_CUSTOM_NAME=\nCOGNITO_CLIENT_ID=\nCOGNITO_CLIENT_SECRET=\nCOGNITO_ISSUER=\n\n# Coinbase\nNEXT_PUBLIC_COINBASE_ENABLED=\nCOINBASE_CUSTOM_NAME=\nCOINBASE_CLIENT_ID=\nCOINBASE_CLIENT_SECRET=\n\n# Discord\nNEXT_PUBLIC_DISCORD_ENABLED=\nDISCORD_CUSTOM_NAME=\nDISCORD_CLIENT_ID=\nDISCORD_CLIENT_SECRET=\n\n# Dropbox\nNEXT_PUBLIC_DROPBOX_ENABLED=\nDROPBOX_CUSTOM_NAME=\nDROPBOX_CLIENT_ID=\nDROPBOX_CLIENT_SECRET=\n\n# DuendeIndentityServer6\nNEXT_PUBLIC_DUENDE_IDS6_ENABLED=\nDUENDE_IDS6_CUSTOM_NAME=\nDUENDE_IDS6_CLIENT_ID=\nDUENDE_IDS6_CLIENT_SECRET=\nDUENDE_IDS6_ISSUER=\n\n# EVE Online\nNEXT_PUBLIC_EVEONLINE_ENABLED=\nEVEONLINE_CUSTOM_NAME=\nEVEONLINE_CLIENT_ID=\nEVEONLINE_CLIENT_SECRET=\n\n# Facebook\nNEXT_PUBLIC_FACEBOOK_ENABLED=\nFACEBOOK_CUSTOM_NAME=\nFACEBOOK_CLIENT_ID=\nFACEBOOK_CLIENT_SECRET=\n\n# FACEIT\nNEXT_PUBLIC_FACEIT_ENABLED=\nFACEIT_CUSTOM_NAME=\nFACEIT_CLIENT_ID=\nFACEIT_CLIENT_SECRET=\n\n# Foursquare\nNEXT_PUBLIC_FOURSQUARE_ENABLED=\nFOURSQUARE_CUSTOM_NAME=\nFOURSQUARE_CLIENT_ID=\nFOURSQUARE_CLIENT_SECRET=\nFOURSQUARE_APIVERSION=\n\n# Freshbooks\nNEXT_PUBLIC_FRESHBOOKS_ENABLED=\nFRESHBOOKS_CUSTOM_NAME=\nFRESHBOOKS_CLIENT_ID=\nFRESHBOOKS_CLIENT_SECRET=\n\n# FusionAuth\nNEXT_PUBLIC_FUSIONAUTH_ENABLED=\nFUSIONAUTH_CUSTOM_NAME=\nFUSIONAUTH_CLIENT_ID=\nFUSIONAUTH_CLIENT_SECRET=\nFUSIONAUTH_ISSUER=\nFUSIONAUTH_TENANT_ID=\n\n# GitHub\nNEXT_PUBLIC_GITHUB_ENABLED=\nGITHUB_CUSTOM_NAME=\nGITHUB_ID=\nGITHUB_SECRET=\n\n# GitLab\nNEXT_PUBLIC_GITLAB_ENABLED=\nGITLAB_CUSTOM_NAME=\nGITLAB_CLIENT_ID=\nGITLAB_CLIENT_SECRET=\nGITLAB_AUTH_URL=\n\n# Google\nNEXT_PUBLIC_GOOGLE_ENABLED=\nGOOGLE_CUSTOM_NAME=\nGOOGLE_CLIENT_ID=\nGOOGLE_CLIENT_SECRET=\n\n# HubSpot\nNEXT_PUBLIC_HUBSPOT_ENABLED=\nHUBSPOT_CUSTOM_NAME=\nHUBSPOT_CLIENT_ID=\nHUBSPOT_CLIENT_SECRET=\n\n# IdentityServer4\nNEXT_PUBLIC_IDS4_ENABLED=\nIDS4_CUSTOM_NAME=\nIDS4_CLIENT_ID=\nIDS4_CLIENT_SECRET=\nIDS4_ISSUER=\n\n# Kakao\nNEXT_PUBLIC_KAKAO_ENABLED=\nKAKAO_CUSTOM_NAME=\nKAKAO_CLIENT_ID=\nKAKAO_CLIENT_SECRET=\n\n# Keycloak\nNEXT_PUBLIC_KEYCLOAK_ENABLED=\nKEYCLOAK_CUSTOM_NAME=\nKEYCLOAK_ISSUER=\nKEYCLOAK_CLIENT_ID=\nKEYCLOAK_CLIENT_SECRET=\n\n# LINE\nNEXT_PUBLIC_LINE_ENABLED=\nLINE_CUSTOM_NAME=\nLINE_CLIENT_ID=\nLINE_CLIENT_SECRET=\n\n# LinkedIn\nNEXT_PUBLIC_LINKEDIN_ENABLED=\nLINKEDIN_CUSTOM_NAME=\nLINKEDIN_CLIENT_ID=\nLINKEDIN_CLIENT_SECRET=\n\n# Mailchimp\nNEXT_PUBLIC_MAILCHIMP_ENABLED=\nMAILCHIMP_CUSTOM_NAME=\nMAILCHIMP_CLIENT_ID=\nMAILCHIMP_CLIENT_SECRET=\n\n# Mail.ru\nNEXT_PUBLIC_MAILRU_ENABLED=\nMAILRU_CUSTOM_NAME=\nMAILRU_CLIENT_ID=\nMAILRU_CLIENT_SECRET=\n\n# Naver\nNEXT_PUBLIC_NAVER_ENABLED=\nNAVER_CUSTOM_NAME=\nNAVER_CLIENT_ID=\nNAVER_CLIENT_SECRET=\n\n# Netlify\nNEXT_PUBLIC_NETLIFY_ENABLED=\nNETLIFY_CUSTOM_NAME=\nNETLIFY_CLIENT_ID=\nNETLIFY_CLIENT_SECRET=\n\n# Okta\nNEXT_PUBLIC_OKTA_ENABLED=\nOKTA_CUSTOM_NAME=\nOKTA_CLIENT_ID=\nOKTA_CLIENT_SECRET=\nOKTA_ISSUER=\n\n# OneLogin\nNEXT_PUBLIC_ONELOGIN_ENABLED=\nONELOGIN_CUSTOM_NAME=\nONELOGIN_CLIENT_ID=\nONELOGIN_CLIENT_SECRET=\nONELOGIN_ISSUER=\n\n# Osso\nNEXT_PUBLIC_OSSO_ENABLED=\nOSSO_CUSTOM_NAME=\nOSSO_CLIENT_ID=\nOSSO_CLIENT_SECRET=\nOSSO_ISSUER=\n\n# osu!\nNEXT_PUBLIC_OSU_ENABLED=\nOSU_CUSTOM_NAME=\nOSU_CLIENT_ID=\nOSU_CLIENT_SECRET=\n\n# Patreon\nNEXT_PUBLIC_PATREON_ENABLED=\nPATREON_CUSTOM_NAME=\nPATREON_CLIENT_ID=\nPATREON_CLIENT_SECRET=\n\n# Pinterest\nNEXT_PUBLIC_PINTEREST_ENABLED=\nPINTEREST_CUSTOM_NAME=\nPINTEREST_CLIENT_ID=\nPINTEREST_CLIENT_SECRET=\n\n# Pipedrive\nNEXT_PUBLIC_PIPEDRIVE_ENABLED=\nPIPEDRIVE_CUSTOM_NAME=\nPIPEDRIVE_CLIENT_ID=\nPIPEDRIVE_CLIENT_SECRET=\n\n# Reddit\nNEXT_PUBLIC_REDDIT_ENABLED=\nREDDIT_CUSTOM_NAME=\nREDDIT_CLIENT_ID=\nREDDIT_CLIENT_SECRET=\n\n# Salesforce\nNEXT_PUBLIC_SALESFORCE_ENABLED=\nSALESFORCE_CUSTOM_NAME=\nSALESFORCE_CLIENT_ID=\nSALESFORCE_CLIENT_SECRET=\n\n# Slack\nNEXT_PUBLIC_SLACK_ENABLED=\nSLACK_CUSTOM_NAME=\nSLACK_CLIENT_ID=\nSLACK_CLIENT_SECRET=\n\n# Spotify\nNEXT_PUBLIC_SPOTIFY_ENABLED=\nSPOTIFY_CUSTOM_NAME=\nSPOTIFY_CLIENT_ID=\nSPOTIFY_CLIENT_SECRET=\n\n# Strava\nNEXT_PUBLIC_STRAVA_ENABLED=\nSTRAVA_CUSTOM_NAME=\nSTRAVA_CLIENT_ID=\nSTRAVA_CLIENT_SECRET=\n\n# Synology\nNEXT_PUBLIC_SYNOLOGY_ENABLED=\nSYNOLOGY_CUSTOM_NAME=\nSYNOLOGY_CLIENT_ID=\nSYNOLOGY_CLIENT_SECRET=\nSYNOLOGY_WELLKNOWN_URL=\n\n# Todoist\nNEXT_PUBLIC_TODOIST_ENABLED=\nTODOIST_CUSTOM_NAME=\nTODOIST_CLIENT_ID=\nTODOIST_CLIENT_SECRET=\n\n# Twitch\nNEXT_PUBLIC_TWITCH_ENABLED=\nTWITCH_CUSTOM_NAME=\nTWITCH_CLIENT_ID=\nTWITCH_CLIENT_SECRET=\n\n# United Effects\nNEXT_PUBLIC_UNITED_EFFECTS_ENABLED=\nUNITED_EFFECTS_CUSTOM_NAME=\nUNITED_EFFECTS_CLIENT_ID=\nUNITED_EFFECTS_CLIENT_SECRET=\nUNITED_EFFECTS_ISSUER=\n\n# VK\nNEXT_PUBLIC_VK_ENABLED=\nVK_CUSTOM_NAME=\nVK_CLIENT_ID=\nVK_CLIENT_SECRET=\n\n# Wikimedia\nNEXT_PUBLIC_WIKIMEDIA_ENABLED=\nWIKIMEDIA_CUSTOM_NAME=\nWIKIMEDIA_CLIENT_ID=\nWIKIMEDIA_CLIENT_SECRET=\n\n# Wordpress.com\nNEXT_PUBLIC_WORDPRESS_ENABLED=\nWORDPRESS_CUSTOM_NAME=\nWORDPRESS_CLIENT_ID=\nWORDPRESS_CLIENT_SECRET=\n\n# Yandex\nNEXT_PUBLIC_YANDEX_ENABLED=\nYANDEX_CUSTOM_NAME=\nYANDEX_CLIENT_ID=\nYANDEX_CLIENT_SECRET=\n\n# Zitadel\nNEXT_PUBLIC_ZITADEL_ENABLED=\nZITADEL_CUSTOM_NAME=\nZITADEL_CLIENT_ID=\nZITADEL_CLIENT_SECRET=\nZITADEL_ISSUER=\n\n# Zoho\nNEXT_PUBLIC_ZOHO_ENABLED=\nZOHO_CUSTOM_NAME=\nZOHO_CLIENT_ID=\nZOHO_CLIENT_SECRET=\n\n# Zoom\nNEXT_PUBLIC_ZOOM_ENABLED=\nZOOM_CUSTOM_NAME=\nZOOM_CLIENT_ID=\nZOOM_CLIENT_SECRET=\n\n# Generic OIDC\nNEXT_PUBLIC_OIDC_ENABLED=\nOIDC_CUSTOM_NAME=\nOIDC_WELLKNOWN_URL=\nOIDC_CLIENT_ID=\nOIDC_CLIENT_SECRET=\nOIDC_SCOPES=\n",
      "source_url": "https://github.com/linkwarden/linkwarden/blob/952ac4540657cae3a67c3ca59433899d2fda8374/.env.sample",
      "validation_status": "unvalidated"
    },
    {
      "order": 4,
      "kind": "note",
      "language": "text",
      "label": "What the compose file check ran with",
      "body": "The compose file check ran together with .env.sample from the same commit, saved as .env. The folder held only these files. The self-hosting guide tells the reader to download docker-compose.yml and .env.sample (saved as .env), change the secrets and run docker compose up.",
      "source_url": "https://github.com/linkwarden/docs/blob/53e2dceda5b2a1b22d280298fba6b2123010f16d/docs/self-hosting/setup.md",
      "validation_status": "unvalidated"
    },
    {
      "order": 5,
      "kind": "shell",
      "language": "bash",
      "label": "Start it",
      "body": "docker compose up -d",
      "source_url": "https://github.com/linkwarden/docs/blob/53e2dceda5b2a1b22d280298fba6b2123010f16d/docs/self-hosting/setup.md",
      "validation_status": "unvalidated"
    },
    {
      "order": 6,
      "kind": "verify",
      "language": "text",
      "label": "Open the app",
      "body": "Open http://localhost:3000. The compose file publishes host port 3000 for the linkwarden service.",
      "source_url": "https://github.com/linkwarden/linkwarden/blob/952ac4540657cae3a67c3ca59433899d2fda8374/docker-compose.yml",
      "validation_status": "unvalidated"
    }
  ],
  "notes": [
    {
      "kind": "gotcha",
      "title": "Some images use the latest tag or no tag",
      "body": "Images without a pinned version: linkwarden: ghcr.io/linkwarden/linkwarden:latest. A later pull can get a different version.",
      "source_url": "https://github.com/linkwarden/linkwarden/blob/952ac4540657cae3a67c3ca59433899d2fda8374/docker-compose.yml",
      "checked_at": "2026-10-22"
    },
    {
      "kind": "gotcha",
      "title": "The compose file publishes host ports",
      "body": "Host ports: 3000 (linkwarden). A port without a host address listens on all host network interfaces.",
      "source_url": "https://github.com/linkwarden/linkwarden/blob/952ac4540657cae3a67c3ca59433899d2fda8374/docker-compose.yml",
      "checked_at": "2026-10-22"
    },
    {
      "kind": "gotcha",
      "title": "The compose file mounts host folders",
      "body": "Host paths mounted into containers: ./pgdata at /var/lib/postgresql/data (postgres), ./data at /data/data (linkwarden), ./meili_data at /meili_data (meilisearch).",
      "source_url": "https://github.com/linkwarden/linkwarden/blob/952ac4540657cae3a67c3ca59433899d2fda8374/docker-compose.yml",
      "checked_at": "2026-10-22"
    }
  ],
  "signals": {
    "captured_at": "2026-10-22",
    "stars": 20176,
    "forks": 874,
    "open_issues": 688,
    "last_push": "2026-10-19",
    "days_since_push": 3,
    "latest_release": "v2.16.3",
    "latest_release_date": "2026-09-09",
    "days_since_release": 43
  },
  "links": {
    "html": "https://openlogs.fyi/tools/linkwarden",
    "markdown": "https://openlogs.fyi/tools/linkwarden.md",
    "json": "https://openlogs.fyi/tools/linkwarden.json"
  },
  "updated_at": "2026-10-22"
}
