Author SHA1 Message Date
Lucas WintherandClaude Opus 5.5 a56257867f docs: mark recoll-modern obsolete in favour of Knowledgenet
Check and publish image / publish (push) Successful in 12s
Check and publish image / checks (push) Successful in 1m12s
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-08 03:25:19 +02:00
7 changed files with 52 additions and 44 deletions
-1
View File
@@ -26,7 +26,6 @@ coverage.xml
htmlcov/
# Local runtime state
data/
*.sqlite3
*.sqlite3-shm
*.sqlite3-wal
+2 -2
View File
@@ -3,8 +3,8 @@
A modern web UI and MCP server layered on Recoll full-text search: self-hosted via Docker, managing
several independent collections (e.g. `techbooks`, `cookbooks`).
**Status:** spec 001's authenticated search API and Docker deployment are implemented. The web UI,
MCP server, and multi-user management are later specs — see Workflow.
**Status:** obsolete and archived — superseded by Knowledgenet (see README). Spec 001's search API and
Docker deployment are implemented; the planned web UI, MCP server, and multi-user specs will not be built.
`AGENTS.md` is the single source of truth for agents here. `CLAUDE.md` and `GEMINI.md` only point here.
On demand: `docs/ARCHITECTURE.md`, `docs/DECISIONS.md`, `docs/TODO.md`, `PRODUCT.md`.
+23 -20
View File
@@ -1,5 +1,12 @@
# recoll-modern
> [!WARNING]
> **This project is obsolete and archived.** It has been superseded by
> [Knowledgenet](https://gitea.lucaswinther.info/lucasw89/knowledgenet), which replaces the
> Recoll/Python/FastAPI direction with direct Xapian integration and covers the planned web UI, MCP
> server and multi-user access. Knowledgenet is still at the proposal stage; this repository is kept
> read-only for reference and receives no further development.
A modern, self-hosted web UI and MCP server on top of [Recoll](https://www.lesbonscomptes.com/recoll/)
full-text search, with support for multiple independent collections.
@@ -44,7 +51,6 @@ RECOLL_MODERN_ADMIN_PASSWORD=use-a-long-unique-password
RECOLL_MODERN_IMAGE=gitea.lucaswinther.info/lucasw89/recoll-modern:main
EOF
docker compose -f compose.published.yaml pull
sudo install -d -m 0700 -o 10001 -g 10001 data/service-state data/recoll-index
docker compose -f compose.published.yaml up -d --no-build
docker compose -f compose.published.yaml ps
docker compose -f compose.published.yaml logs -f app
@@ -55,8 +61,8 @@ Once a version appears in Gitea Packages, edit `RECOLL_MODERN_IMAGE` in `.env` t
`RECOLL_MODERN_IMAGE` to use `:latest` after the first version tag is published. The image is published
only after the CI checks pass; a tag that has not been published cannot be pulled. To update, set the
desired tag and run `docker compose -f compose.published.yaml pull` followed
by `docker compose -f compose.published.yaml up -d --no-build` again. Keep the same Compose file
directory so the local data paths are reused.
by `docker compose -f compose.published.yaml up -d --no-build` again. Keep the same Compose project
directory so its named volumes are reused.
For a trusted local HTTP trial with `docker run`, export the settings for that shell:
@@ -66,14 +72,13 @@ export RECOLL_MODERN_ADMIN_USERNAME=admin
export RECOLL_MODERN_ADMIN_PASSWORD='use-a-long-unique-password'
export RECOLL_MODERN_IMAGE=gitea.lucaswinther.info/lucasw89/recoll-modern:main
docker pull "$RECOLL_MODERN_IMAGE"
sudo install -d -m 0700 -o 10001 -g 10001 data/service-state data/recoll-index
docker run -d --name recoll-modern --restart unless-stopped -p 127.0.0.1:8000:8000 \
-e RECOLL_MODERN_ADMIN_USERNAME -e RECOLL_MODERN_ADMIN_PASSWORD \
-e RECOLL_MODERN_HOST=0.0.0.0 -e RECOLL_MODERN_PORT=8000 \
-e RECOLL_MODERN_DEVELOPMENT_MODE=true \
--mount "type=bind,src=$RECOLL_MODERN_DOCUMENTS,dst=/documents,readonly" \
--mount "type=bind,src=$PWD/data/service-state,dst=/var/lib/recoll-modern" \
--mount "type=bind,src=$PWD/data/recoll-index,dst=/var/lib/recoll" \
--mount type=volume,src=recoll-modern-service-state,dst=/var/lib/recoll-modern \
--mount type=volume,src=recoll-modern-index,dst=/var/lib/recoll \
"$RECOLL_MODERN_IMAGE"
```
@@ -90,21 +95,19 @@ docker compose up -d --build
The service listens on host port 8000 by default; set `RECOLL_MODERN_PUBLISH_PORT` to change it. The
document directory is mounted read-only. SQLite, the membership map and generated Recoll configuration
live in `./data/service-state`; the index lives in `./data/recoll-index`, relative to the Compose file
directory. Both directories must be writable by container UID/GID `10001:10001`; create them with the
command above before starting either deployment. Back up both directories together and keep a separate
copy of the documents. Container replacement does not delete these bind-mounted directories. If you
already deployed with the earlier named volumes, copy both volumes' contents into these directories
while the old container is stopped, preserving ownership, before starting the new configuration. Do not
start against empty directories in place of existing data.
live in the `service-state` volume; the index lives in the separate `recoll-index` volume. Back up both
volumes together and keep a separate copy of the documents. `docker compose down` preserves the volumes;
never pass `-v` unless you intentionally want to delete the index and service state.
On first boot, the API is available but `/health` can return 503 with a Recoll database-open error until
a membership or reindex job has built the first index. Log in through `POST /auth/login`, create a
collection, then add file or directory sources through `POST /collections/{id}/memberships`. Mutations
return a durable job ID; inspect `GET /jobs/{id}` for completion or file errors. `POST /jobs/reindex`
refreshes the index without deleting it. The login seed applies only when no administrator exists;
changing the environment value later does not rotate an existing password. Protect and back up
`./data/service-state`.
For the direct `docker run` example, the volumes are named `recoll-modern-service-state` and
`recoll-modern-index`. Back up both together. Replacing a container does not delete these volumes.
On first boot, the API is available but `/health` may return 503 until a membership or reindex job has
built the first Recoll index. Log in through `POST /auth/login`, create a collection, then add file or
directory sources through `POST /collections/{id}/memberships`. Mutations return a durable job ID;
inspect `GET /jobs/{id}` for completion or file errors. `POST /jobs/reindex` refreshes the index without
deleting it. The login seed applies only when no administrator exists; changing the environment value
later does not rotate an existing password. Protect and back up the service-state volume.
Production sessions use Secure cookies, so serve the API over HTTPS. For a trusted local HTTP trial,
set `RECOLL_MODERN_DEVELOPMENT_MODE=true`; do not use that setting on a public endpoint. Set
+5 -2
View File
@@ -14,8 +14,8 @@ services:
RECOLL_MODERN_MEMBERSHIP_MAP: /var/lib/recoll-modern/membership.map
volumes:
- ${RECOLL_MODERN_DOCUMENTS:?Set documents directory}:/documents:ro
- ./data/service-state:/var/lib/recoll-modern
- ./data/recoll-index:/var/lib/recoll
- service-state:/var/lib/recoll-modern
- recoll-index:/var/lib/recoll
healthcheck:
test: ["CMD", "python", "-c", "import os,urllib.request; p=os.environ.get('RECOLL_MODERN_ROOT_PATH','/').rstrip('/'); urllib.request.urlopen('http://127.0.0.1:8000'+p+'/health',timeout=5)"]
interval: 30s
@@ -23,3 +23,6 @@ services:
retries: 3
start_period: 30s
restart: unless-stopped
volumes:
service-state:
recoll-index:
+5 -2
View File
@@ -15,8 +15,8 @@ services:
RECOLL_MODERN_MEMBERSHIP_MAP: /var/lib/recoll-modern/membership.map
volumes:
- ${RECOLL_MODERN_DOCUMENTS:?Set documents directory}:/documents:ro
- ./data/service-state:/var/lib/recoll-modern
- ./data/recoll-index:/var/lib/recoll
- service-state:/var/lib/recoll-modern
- recoll-index:/var/lib/recoll
healthcheck:
test: ["CMD", "python", "-c", "import os,urllib.request; p=os.environ.get('RECOLL_MODERN_ROOT_PATH','/').rstrip('/'); urllib.request.urlopen('http://127.0.0.1:8000'+p+'/health',timeout=5)"]
interval: 30s
@@ -24,3 +24,6 @@ services:
retries: 3
start_period: 30s
restart: unless-stopped
volumes:
service-state:
recoll-index:
+6 -6
View File
@@ -30,7 +30,7 @@ web UI and (b) an MCP server, running in Docker, with several independent collec
| `src/recoll_modern/indexing/handlers.py` | Scans membership sources before strict-mode mutations and records file errors |
| `src/recoll_modern/indexing/map_export.py` | Writes a durable atomic map from canonical paths to opaque collection IDs |
| `helper/` | C reader run by Recoll's `metadatacmds` for each indexed file |
| `Dockerfile`, `compose.yaml`, `docker/` | Non-root Recoll runtime, read-only document mount, persistent local state/index directories and config templates |
| `Dockerfile`, `compose.yaml`, `docker/` | Non-root Recoll runtime, read-only document mount, persistent state/index volumes and config templates |
| `compose.published.yaml` | Pull-only deployment with the same runtime settings and persistent mounts |
| `.gitea/workflows/image.yaml`, `scripts/image_tags.py`, `scripts/publish_image.sh` | CI checks and Gitea registry publication; Git refs select published tags |
| `src/recoll_modern/engine/` | Shared Protocol, deterministic fake, and isolated Recoll Python/indexer adapter |
@@ -65,7 +65,7 @@ future distribution track and starts only after the hosted product through 004 i
- A Python service owns Recoll through its native Python bindings (`from recoll import recoll`).
- SQLite holds collections, membership, indexing jobs, users and sessions.
- An HTTP API consumed by both the web UI and the MCP server, so the two never diverge.
- A Docker image containing Recoll itself, plus compose wiring for read-only documents and local index storage.
- A Docker image containing Recoll itself, plus compose wiring for document volumes and index storage.
- A packaging seam for a future desktop shell: application logic does not depend on Docker, state paths
and listen addresses are configurable, process startup/shutdown is explicit, and every UI operation
crosses the same HTTP API. Docker remains the only supported distribution through spec 004.
@@ -129,9 +129,9 @@ display is limited to safe media types.
The image installs Debian trixie's headless `recollcmd` package and Python binding.
It syncs the application into a system-site-packages venv so the binding remains
importable. A separate build stage compiles the C helper. The non-root process
copies Recoll config templates into the persistent state directory only when absent;
copies Recoll config templates into the persistent state volume only when absent;
Recoll may generate additional support files there. Compose mounts documents
read-only and keeps the SQLite/config and Xapian index bind mounts separate. Initial
read-only and keeps the SQLite/config and Xapian index volumes separate. Initial
health can be 503 until an indexing job creates the first index.
Gitea Actions tests and builds on pull requests, main pushes and version tags. A dependent job publishes
@@ -207,8 +207,8 @@ semantics and test strategy — are closed in the approved `docs/specs/001-searc
|---|---|
| Recoll (in-container) | All indexing and search. Not installed on the host — see `AGENTS.md` Rules. |
| Docker + compose | The only supported way to run the service. |
| Document bind mount | Nothing to index; collections resolve to empty. |
| Writable local directories for the index and SQLite | All state. The document directory itself may be mounted read-only. |
| Document volumes | Nothing to index; collections resolve to empty. |
| A writable volume for the index and SQLite | All state. The document volume itself may be mounted read-only. |
Docker is the only supported deployment for specs 001–004, not a permanent application-layer
dependency. Spec 005 will design cross-platform packaging of the web UI, API service, Recoll and its
+11 -11
View File
@@ -445,15 +445,15 @@ publishing and pulling still require a successful Gitea Actions run.
---
## 2026-09-28 — Keep Docker state beside the Compose file
## 2026-10-08 — Retire recoll-modern in favour of Knowledgenet
**Status:** accepted
**Context:** named Docker volumes hide the index and service database from operators managing a
deployment from its Compose directory. The non-root container needs writable state owned by UID/GID
`10001:10001`.
**Decision:** both Compose variants bind-mount `./data/service-state` and `./data/recoll-index`.
The direct `docker run` example uses the same local directories. Ignore `data/` in Git and require
operators to create the directories with the container's ownership before startup.
**Alternatives:** retain Docker-managed named volumes and require volume-specific backup commands.
**Consequences:** moving the Compose file changes the resolved data paths. Existing named-volume
deployments must copy both stores into the local directories before switching mounts; neither store
is deleted or rebuilt by this change.
**Context:** the Knowledgenet proposal (`lucasw89/knowledgenet`, `docs/PROPOSAL.md`) covers this
project's goals — search, web UI, MCP access, multiple collections and multi-user permissions — and
explicitly supersedes its direction: direct Xapian instead of Recoll, no Recoll/Python/FastAPI stack,
and permissions designed in from the start rather than added after search.
**Decision:** stop development here, mark the README obsolete, and archive the repository.
**Alternatives:** keep building the web UI and MCP specs on Recoll, which the Knowledgenet proposal
rules out.
**Consequences:** spec 001 (search API and Docker image) remains as a read-only reference. Later specs
listed in `docs/TODO.md` and `docs/ARCHITECTURE.md` will not be implemented here. Knowledgenet is still
a proposal with no implementation, so nothing currently replaces the running service.