Edgible cards

Cards / linkding

linkding

linkding, a minimal bookmark manager, for your browsers and its extension

App cardpassed 2026-10-11, Edgible 1.4.6Source on GitHub

The apps, ports, auth modes, and places in the linkding card

Apps

AppWhatWho can reach itPlace
linkdinglinkding, for the web and the browser extensionopen to anyonelinkding

Machine

A place is one serving device. Minimum recommended for each:

PlaceMemoryDiskArchitectureGPU
linkding384 MB1.5 GBamd64, arm64, armnone

Needs it answers

Why

Bookmarks kept in one browser's sync are tied to that browser and that company. linkding is a small, fast bookmark manager with tags, search, and a browser extension, that keeps your bookmarks on a machine you own.

What

One app, linkding, on the place linkding, on none. That is deliberate: the linkding browser extension and the community phone apps call its API with a token, and cannot get past an Edgible sign-in, so org would lock them out. linkding's own login takes its place: it has no sign-up page, so the only account is the admin made from LINKDING_ADMIN_USER and LINKDING_ADMIN_PASSWORD on first start, and the admin adds anyone else under Admin. Logins and saves come from the public hostname, so LD_CSRF_TRUSTED_ORIGINS is https://linkding.<ORG_LABEL>.edgible.com, or LINKDING_URL on your own domain. The image is ghcr.io/sissbruecker/linkding:1.47.0, from GitHub's registry, with its own healthcheck. Its -plus variant adds Chromium for saving pages as HTML snapshots, at several times the size.

Bookmarks, tags, users and settings live in the SQLite database in the volume linkding-data. Back it up. Minimum recommended for the place linkding: 384 MB of memory and 1.5 GB of disk, on an arm64, amd64 or 32-bit arm machine, with no GPU.

The Compose file is docker-compose.yml, the settings card.env, the card card.yml, and the last test test.yml.

How

Five steps. Edit card.env before you start.

1. Fetch

mkdir -p linkding
curl -fsSL https://github.com/Edgible/cards/archive/refs/heads/main.tar.gz \
  | tar -xz --strip-components=2 -C linkding cards-main/linkding

2. Edit card.env

Set DEVICE to a name edgible device list prints, and ORG_LABEL to the part after the app name in a hostname edgible app list prints. The admin password is generated in the next step.

nano linkding/card.env

3. Check

curl -fsSLo check-env.py https://raw.githubusercontent.com/Edgible/card-kit/main/check-env.py
python3 check-env.py linkding

It fills each empty secret and moves a taken port, as lines to paste. Run it again until it says no conflicts.

4. Start

docker compose --env-file linkding/card.env -f linkding/docker-compose.yml up -d --wait
docker compose --env-file linkding/card.env -f linkding/docker-compose.yml ps

--wait returns when each service is running, and healthy when it has a healthcheck. The admin is made on first start, from card.env, so there is no setup page for a stranger to find once it is published.

5. Publish

set -euo pipefail
set -a
. linkding/card.env
set +a
device_id=$(edgible device list --json | jq -er --arg name "$DEVICE" '
  map(select(.name == $name))
  | if length == 1 then .[0].id
    else error("need exactly one device named " + $name + " (" + (map(.status + " " + .id) | join(", ")) + ")")
    end
')
edgible app create existing \
  --non-interactive \
  --name linkding \
  --port "$LINKDING_PORT" \
  --protocol https \
  --auth-modes none \
  --device-id "$device_id"
edgible app list

Verify

linkding uses none.

curl -sS -o /dev/null -w '%{http_code}\n' "https://<linkding hostname>"

The login page, with no Edgible sign-in, as the browser extension needs. Sign in as LINKDING_ADMIN_USER with LINKDING_ADMIN_PASSWORD, and change the password under Settings. For the browser extension, copy the REST API token from Settings → Integrations.

The rest of the setup is in the linkding docs.

Tear down

Four steps, in this order. Step 1 runs wherever edgible is logged in. Steps 2 to 4 run on the machine that runs the containers. Steps 2 and 3 read card.env, so keep it until step 4.

1. Unpublish

edgible app delete linkding --yes

2. Stop

docker compose --env-file linkding/card.env -f linkding/docker-compose.yml down

3. Delete the data

Skip this step to keep the data. The loop copies each volume to a .tgz file in this directory first.

for volume in $(docker volume ls -q --filter label=com.docker.compose.project=linkding); do
  docker run --rm -v "$volume:/data:ro" -v "$PWD:/backup" alpine tar -czf "/backup/$volume.tgz" -C /data .
done
docker compose --env-file linkding/card.env -f linkding/docker-compose.yml down --volumes

4. Remove the card

rm -rf linkding