A community fork of Alfresco Search Services, maintained by Jeci — the team behind Pristy.
Status: beta. This is an independent community fork, not affiliated with Hyland and not supported on Alfresco Enterprise. Don't put it in production yet. Do try it, break it, and tell us what's missing.
Why this fork exists
If you run Alfresco Community Edition, your search tier is probably still riding on an Alfresco-patched Apache Solr 6, a release line whose upstream Lucene 6 reached end of life years ago. The patched build ties you to an old Java, an old logging stack (Log4j 1.x), and a Solr you can't simply swap for a current Apache release.
| |
Before (upstream Community) |
Jeci Fork |
|---|
| Solr / Lucene |
6.6.5 patched / Lucene 6 |
9.10.1 vanilla Apache / Lucene 9.12.3 |
| Java |
11 |
17 |
| Logging |
Log4j 1.x / reload4j |
Log4j 2 |
| Indexing trackers |
inside the Solr webapp |
standalone Spring Boot service |
| Enterprise modules |
Insight Engine, Zeppelin bundled |
removed (Community-focused) |
The headline is "Solr 9," but the structural change matters just as much: the indexing trackers now run as their own service. Solr only serves queries and stores the index; a separate alfresco-indexing-trackers process reads from the repository and feeds Solr. You can restart, scale, monitor, and re-tune indexing without touching query serving and re-tune a running stack with environment variables, no image rebuild.
What stays exactly the same
This is the part that makes adoption low-risk. Your queries don't change.
- The AFTS query language and the public Search API are unchanged.
- ACL permission filtering behaves identically, denied documents stay hidden.
- Faceting, highlighting, ancestor-path (APATH) drill-down all work as before.
- The default cores are still
alfresco and archive.
A query that worked against the upstream Community search engine returns the same results here. What changed is the engine underneath and the deployment shape — not the contract.
Want to just try it? Jump to Try it in one command below: the community alfresco-docker-installer now has a --searchType=jeci option that stands up a full Alfresco 26.1 + Solr 9 stack and indexes your content with no manual setup.
What you give up
- Insight Engine is gone: the SQL/JDBC connector (
/sql), Zeppelin notebooks, and the Enterprise analytics. If you depend on those, this fork is not for you yet.
- A full re-index is mandatory. Lucene 9 cannot read a Lucene 6 index. You start with empty cores and let the trackers rebuild from the repository. Plan a re-indexing window proportional to your repository size.
The architecture in one diagram
+--------------------------+
| Alfresco Repository |
| (Community Edition) |
+-----------+--------------+
tracking API (pull) | ^ search API
+ shared secret | | (AFTS / CMIS)
v |
+------------------------+ +----+-------------------+
| alfresco-indexing- | | Solr 9 |
| trackers (Spring Boot) |-->| (query + index store) |
| Metadata / Content / | | cores: alfresco, |
| Acl / Commit / Cascade| | archive |
| / Model / Repair | +------------------------+
| :8085 actuator+admin |
+------------------------+
- MetadataTracker indexes properties, paths, and aspects: a document is findable by name and metadata within a few seconds. If it has content, it's flagged "content outdated."
- ContentTracker runs on a slower schedule, pulls the outdated docs, fetches extracted text from the repository (via the transform service), and indexes it: now findable by full text.
- CommitTracker commits and reopens the searcher: what actually makes new docs visible.
So full-text search lags metadata search. The dominant lever is the content cron, and every tracker setting is an ALFRESCO_TRACKER_* environment variable you can change live.
Try it in one command
The fastest way to kick the tyres is the community installer, alfresco-docker-installer: the Yeoman generator (yo alfresco-docker-installer) that produces a Docker Compose stack for Alfresco Community. It now has first-class support for this fork: pick the Jeci search engine and it wires up the two-service layout (Solr 9 + standalone trackers) for you.
Interactive
npm install -g yo generator-alfresco-docker-installer
yo alfresco-docker-installer
When prompted "Which search engine would you like to use?", choose:
Alfresco Search Services (stock, Solr 6)
> Jeci community fork (vanilla Solr 9 / Java 17, standalone trackers)
Pick ACS 26.1 (the version this option targets today). The installer forces shared-secret comms automatically: it's the mode this fork supports end to end.
Then just bring it up
docker compose up --build -d
docker compose logs -f trackers # watch indexing cycles
The first up --build clones and compiles the fork (Solr 9 distribution + the trackers JAR) inside Docker — that takes a while the first time; subsequent builds are cached. The generated stack runs postgres, alfresco, transform-core-aio, share, content-app, a proxy, and the two search services solr6 (query + index) and trackers (indexing), all pre-wired with a shared secret.
Note on scope. The --searchType=jeci option currently targets ACS 26.1. Extending it to 23.x / 25.x is straightforward and on the backlog — a friendly contribution if you want one.
Deployment guide
Most people should use the one-command installer above. This section is the manual path, useful if you want to understand the moving parts, run a different ACS version, or build the images yourself.
Heads-up on images. The fork's CI currently publishes images to a private registry, so there is no public docker pull yet. So here you build the two images from source. It's three commands.
0. Prerequisites
- Docker + Docker Compose
- Java 17 (Temurin) and Maven 3.9+ — or just mise, which pins both for you (
mise install)
1. Build the distribution and the two images
git clone https://github.com/jecicorp/AlfrescoSearchServices.git
cd AlfrescoSearchServices
# Build the Solr distribution ZIP + the trackers Spring Boot JAR
mise run install # or: mvn clean install -DskipTests -pl \
# search-services/alfresco-solrclient-lib,search-services/alfresco-search,search-services/packaging -am
mise run trackers:build # or: cd search-services && mvn package -pl alfresco-indexing-trackers -am -DskipTests
# Build the Solr image
docker build -t alfresco/alfresco-search-services:local \
search-services/packaging/target/docker-resources/
# Build the trackers image
docker build -t alfresco/alfresco-indexing-trackers:local \
-f search-services/packaging/src/docker/Dockerfile.trackers \
search-services/alfresco-indexing-trackers/target/
2. The Compose file
This is a minimal Alfresco Community 23.x stack using shared-secret auth between the repository and the search tier (the simplest secure-by-default option). It mirrors the project's own working docker-compose.dev.yml, trimmed to the essentials.
# compose.yml
services:
postgres:
image: postgres:16
environment:
POSTGRES_DB: alfresco
POSTGRES_USER: alfresco
POSTGRES_PASSWORD: alfresco
command: postgres -c max_connections=200
healthcheck:
test: ["CMD", "pg_isready", "-U", "alfresco"]
interval: 10s
retries: 5
activemq:
image: alfresco/alfresco-activemq:5.17.1-jre17-rockylinux8
ports: ["8161:8161", "61616:61616", "5672:5672"]
transform-core-aio:
image: alfresco/alfresco-transform-core-aio:5.1.2
environment:
JAVA_OPTS: "-XX:MinRAMPercentage=50 -XX:MaxRAMPercentage=80"
alfresco:
image: alfresco/alfresco-content-repository-community:23.4.1
mem_limit: 3g
healthcheck:
test: ["CMD", "curl", "--fail",
"http://localhost:8080/alfresco/api/-default-/public/alfresco/versions/1/probes/-ready-"]
interval: 10s
retries: 10
start_period: 60s
environment:
JAVA_TOOL_OPTIONS: >-
-Ddb.driver=org.postgresql.Driver
-Ddb.username=alfresco
-Ddb.password=alfresco
-Ddb.url=jdbc:postgresql://postgres:5432/alfresco
-Dindex.subsystem.name=solr6
-Dsolr.secureComms=secret
-Dsolr.sharedSecret=please-change-me
-Dsolr.host=solr
-Dsolr.port=8983
-Dmessaging.broker.url="failover:(nio://activemq:61616)?timeout=3000&jms.useCompression=true"
-Dtransform.service.enabled=true
-Dlocal.transform.service.enabled=true
-DlocalTransform.core-aio.url=http://transform-core-aio:8090/
-Dcsrf.filter.enabled=false
depends_on:
postgres: { condition: service_healthy }
solr:
image: alfresco/alfresco-search-services:local # built in step 1
mem_limit: 2g
# solr-init-core.sh creates the alfresco + archive cores from the rerank template on first boot
entrypoint: ["/opt/alfresco-search-services/solr-init-core.sh"]
environment:
SOLR_ALFRESCO_HOST: alfresco
SOLR_ALFRESCO_PORT: "8080"
SOLR_SOLR_HOST: solr
SOLR_SOLR_PORT: "8983"
SOLR_CREATE_ALFRESCO_DEFAULTS: alfresco,archive
ALFRESCO_SECURE_COMMS: secret
JAVA_TOOL_OPTIONS: "-Dalfresco.secureComms.secret=please-change-me"
ports: ["8983:8983"]
depends_on:
alfresco: { condition: service_healthy }
volumes:
- solr-data:/opt/alfresco-search-services/data
trackers:
image: alfresco/alfresco-indexing-trackers:local # built in step 1
mem_limit: 512m
environment:
ALFRESCO_TRACKER_SOLR_URL: http://solr:8983/solr
ALFRESCO_TRACKER_SOLR_COLLECTIONS: alfresco,archive
ALFRESCO_TRACKER_REPOSITORY_URL: http://alfresco:8080/alfresco
ALFRESCO_TRACKER_REPOSITORY_SECURECOMMS: secret
ALFRESCO_TRACKER_REPOSITORY_SHAREDSECRET: please-change-me
# Optional: make full-text appear faster on a low-volume / demo stack
# ALFRESCO_TRACKER_CRON_CONTENT: "0/5 * * * * ?"
# ALFRESCO_TRACKER_NEW_SEARCHER_INTERVAL: "1500"
ports: ["8085:8085"]
depends_on:
alfresco: { condition: service_healthy }
volumes:
solr-data:
docker compose -f compose.yml up -d
docker compose -f compose.yml logs -f trackers # watch the indexing cycles
3. Verify it works
- Solr answers:
curl <a href="http://localhost:8983/solr/" target="_blank" rel="noopener nofollow noreferrer">http://localhost:8983/solr/</a> (the admin UI requires the secret header).
- Trackers are healthy:
curl <a href="http://localhost:8085/actuator/health" target="_blank" rel="noopener nofollow noreferrer">http://localhost:8085/actuator/health</a> : {"status":"UP"}.
- Upload a document in Alfresco. Within a few seconds it's findable by name; within 25–30 s (default cadence) it's findable by its content.
- Watch progress: the trackers expose a Solr-compatible report at
curl "<a href="http://localhost:8085/solr/admin/cores?action=SUMMARY&wt=json" target="_blank" rel="noopener nofollow noreferrer">http://localhost:8085/solr/admin/cores?action=SUMMARY&wt=json</a>".
Reaching the Solr admin UI. Solr 9 + shared-secret means every request needs an X-Alfresco-Search-Secret header. Either use a browser extension like ModHeader, or front Solr with a tiny reverse proxy that injects it, the repo ships a Caddyfile that does exactly this on port 8984.
4. Tuning
Every tracker knob is an environment variable on the trackers service.
| Variable |
Default |
Effect |
|---|
ALFRESCO_TRACKER_CRON_CONTENT |
0/20 * * * * ? |
Full-text freshness. Lower → text searchable sooner, more transform load. |
ALFRESCO_TRACKER_CRON_METADATA |
0/5 * * * * ? |
Metadata freshness. |
ALFRESCO_TRACKER_CRON_ACL |
0/5 * * * * ? |
How fast permission changes apply to search. |
ALFRESCO_TRACKER_BATCH_COUNT |
5000 |
Nodes per tracking call; higher → faster bulk indexing, more memory. |
ALFRESCO_TRACKER_NEW_SEARCHER_INTERVAL |
3000 (ms) |
Delay before new docs become visible. |
Full reference: tracker-configuration.md.
How you can help
This is a community project and it grows with the community. Concrete ways to contribute, roughly easiest-first:
- Run it and report back. Stand up the one-command installer stack against your real custom content models and tell us what indexes correctly and what doesn't. Bug reports with a reproducible model are gold.
- Extend the installer. The
--searchType=jeci option covers ACS 26.1 today, extending it to 23.x / 25.x is a well-scoped, friendly PR.
- Documentation. The
search-services/README.md still carries stale Solr 6 / Insight Engine content, leaning it up is a friendly first PR.
- Packaging & distribution. Help us publish public images and tagged releases so adoption doesn't even need a first-build compile.
- Code. Pick something from the backlog: mTLS for the trackerto Solr leg, SolrCloud support, observability dashboards, a Helm chart...
See CONTRIBUTING.md for the branch model and PR conventions, and the issues backlog for ready-to-pick tasks.
Project home: https://github.com/jecicorp/AlfrescoSearchServices
Commercial support on Alfresco Community & this module: Jeci
Further reading
License: LGPL-3.0. Alfresco and the Alfresco logo are trademarks of Hyland; this project is an independent community fork and is not affiliated with or endorsed by Hyland.