This project contains 4 sub-projects :
- collabora-platform-extension : extension for Alfresco Content Services
- collabora-share-extension : extension for lagacy Share interface
- collabora-aca-extension : extension for Angular interface, Alfresco Content Application
- collabora-vue-component : component for Pristy
If the user has the write permission, the extension adds an action Edit with Collabora™ Online on documents which can be opened with Collabora Online.
The document will be opened in an iFrame. Many users can open the same document at the same time.
You can clone the project and compile all projects :
git clone git@github.com:CollaboraOnline/alfresco-collabora-online.git
cd alfresco-collabora-online
./run.sh build
or with mise
mise install
mise run start
- Java: 17 or higher
- Alfresco Content Services: 7.2+ (tested with 25.3.0)
- Alfresco Share: 7.2+ (tested with 25.3.0)
- Collabora Online: 6.4+ (tested with 25.04)
- Docker Compose: Only for testing
-
Copy the extension JAR to Alfresco's library folder:
cp collabora-platform-extension-<version>.jar $ALFRESCO_HOME/webapps/alfresco/WEB-INF/lib/
-
Configure
alfresco-global.properties(see Configuration Reference for details):# Public URLs (accessible from browser) collabora.public.url=https://<collabora_server_domain>:<port>/ alfresco.public.url=https://<alfresco_server_domain>:<port>/alfresco/ # Private URLs (optional, for internal network) collabora.private.url=${collabora.public.url} alfresco.private.url=${alfresco.public.url} # Token time-to-live (24 hours in milliseconds) lool.wopi.token.ttl=86400000
-
Restart Alfresco
-
Copy the extension JAR to Share's library folder:
cp collabora-share-extension-<version>.jar $ALFRESCO_HOME/webapps/share/WEB-INF/lib/
-
Restart Share
You can start the application for local test with docker-compose.
./run.sh build_start
To compile and reload a project independently you can use :
# Build and reload only Alfresco Content Services
./run.sh reload_acs
# Build and reload only Alfresco Share
./run.sh reload_share
Then you can access applications :
Understanding the network flows is important for a secure deployment.
┌─────────────┐ ┌──────────────────┐ ┌─────────────┐
│ Browser │ ◄──────HTTPS─────► │ Reverse Proxy │ ◄──────HTTP──────► │ Collabora │
│ (User) │ │ │ │ Online │
└─────────────┘ └──────────────────┘ └─────────────┘
│
│ HTTP (WOPI)
│
▼
┌─────────────────────────────────────────────────────┐
│ Alfresco Repository │
│ - Serves WOPI endpoints │
│ - Fetches discovery XML at startup ONLY │
└─────────────────────────────────────────────────────┘
- Browser ↔ Collabora Online: Users' browsers load the Collabora Online editor interface via
collabora.public.url - Browser ↔ Alfresco: WOPI protocol communication (CheckFileInfo, GetFile, PutFile) via
alfresco.public.url - Alfresco → Collabora: Only at startup - Alfresco fetches
/hosting/discoveryto know which file types are supported
For maximum security, you can avoid opening network traffic from Alfresco to Collabora Online by hosting the discovery XML internally.
Steps:
-
Download the discovery XML once:
curl https://collabora.example.com/hosting/discovery > discovery.xml -
Host it on your reverse proxy or internal web server:
# Nginx example location /collabora-discovery/hosting/discovery { alias /var/www/discovery.xml; default_type application/xml; }
-
Configure Alfresco to use the internal URL:
collabora.public.url=https://collabora.example.com/ collabora.private.url=https://proxy-internal/collabora-discovery/
Result: No direct network communication between Alfresco and Collabora Online. The discovery XML is loaded from your internal infrastructure.
Note: Remember to update the discovery XML when upgrading Collabora Online, as supported file formats may change.
All configuration properties should be defined in $ALFRESCO_HOME/tomcat/shared/classes/alfresco-global.properties.
Type: URL
Default: http://localhost:9980/
Public URL of the Collabora Online server, accessible from the user's browser. This URL is used to load the Collabora Online editor in the user's web browser.
Example:
collabora.public.url=https://collabora.example.com/Type: URL
Default: ${collabora.public.url}
Internal URL of the Collabora Online server. Use this if Collabora Online is accessible via a different URL from within the Alfresco server's network (e.g., internal hostname or IP address).
Important: This URL is used by Alfresco at startup to fetch the WOPI discovery XML from <collabora.private.url>/hosting/discovery. This is the only network communication needed between Alfresco and Collabora Online.
Example:
collabora.private.url=http://collabora-internal:9980/Special case - Avoiding outbound network traffic:
If you want to avoid opening network traffic from Alfresco to Collabora Online (recommended for security), you can:
- Copy the content of
https://collabora.example.com/hosting/discoveryto your reverse proxy or internal web server - Configure
collabora.private.urlto point to this internal copy
Example configuration:
# Public URL for browser access
collabora.public.url=https://collabora.example.com/
# Private URL pointing to local copy of discovery XML
collabora.private.url=https://proxy-internal/collabora-discovery/
# The discovery XML should be available at:
# https://proxy-internal/collabora-discovery/hosting/discoveryThis way, Alfresco loads the discovery configuration from an internal source, while browsers still access Collabora Online via the public URL. No direct network communication is needed between Alfresco and Collabora Online.
Type: URL
Default: ${alfresco.protocol}://${alfresco.host}:${alfresco.port}/${alfresco.context}
Public URL of the Alfresco server, accessible from the user's browser. This URL is used by the browser to communicate with Alfresco.
Example:
alfresco.public.url=https://alfresco.example.com/alfresco/Type: URL
Default: ${alfresco.public.url}
Internal URL of the Alfresco server used by Collabora Online to fetch documents. Use this if Alfresco is accessible via a different URL from within Collabora's network.
Example:
alfresco.private.url=http://alfresco-internal:8080/alfresco/Type: Integer (milliseconds)
Default: 500
Connect and read timeout for fetching the WOPI discovery XML from Collabora Online at startup. Increase this value if Collabora Online is hosted on a remote server with higher latency.
Example:
# 2 seconds (for remote servers)
fr.jeci.collabora.discovery.readTimeoutMs=2000Note: If the discovery fetch fails at startup (e.g., Collabora Online not yet available), you can reload it at runtime via the admin UI or by calling GET /collabora/admin/status?reload=true.
Type: Integer (milliseconds)
Default: 86400000 (24 hours)
Time-to-live for WOPI access tokens in milliseconds. After this period, tokens expire and users must reload the document.
Examples:
# 12 hours
lool.wopi.token.ttl=43200000
# 24 hours (default)
lool.wopi.token.ttl=86400000
# 48 hours
lool.wopi.token.ttl=172800000Note: Tokens shorter than 1 hour (3600000 ms) will generate a warning in the logs.
Type: Comma-separated list
Default: imgpreview,medium,doclib,pdf
List of renditions to automatically regenerate after a document is saved with Collabora Online. This ensures thumbnails and previews are updated with the latest content.
Available renditions:
imgpreview- Image previewmedium- Medium size thumbnaildoclib- Document library thumbnailpdf- PDF rendition
Example:
# Generate only essential renditions
fr.jeci.collabora.renditions=doclib,pdf
# Disable automatic rendition generation
fr.jeci.collabora.renditions=This feature implements Collabora Online Remote Configuration to allow Alfresco to serve configuration and custom fonts to Collabora Online. Collabora polls the remote config endpoint every 60 seconds using ETag-based caching.
Configuration and fonts are stored in the Alfresco repository under /Data Dictionary/collabora-online/. The remote configuration is disabled by default and can be enabled via the admin UI in pristy-portail or via the status endpoint.
Type: String
Default: collabora-online
Folder name under /Data Dictionary/ for storing the Collabora configuration and fonts.
Type: URL
Default: ${alfresco.public.url}/s/collabora/fonts
Public base URL for serving font files. This URL is used in the font configuration JSON to build font URIs.
| Endpoint | Method | Description |
|---|---|---|
/collabora/admin/status |
GET | Returns connection status (online), server URL, and remoteConfigEnabled flag |
/collabora/admin/status?reload=true |
GET | Re-attempts connection to Collabora Online (useful when Alfresco starts before Collabora) |
/collabora/admin/status?enableRemoteConfig=true |
GET | Enables remote configuration (creates default config and fonts folder) |
/collabora/admin/status?enableRemoteConfig=false |
GET | Disables remote configuration (deletes config file and fonts folder) |
These endpoints are called by Collabora Online directly and require no authentication. Secure them at the network/reverse proxy level.
| Endpoint | Method | Description |
|---|---|---|
/collabora/remote-config |
GET | Main configuration JSON (polled by coolwsd every 60s, supports ETag/If-None-Match) |
/collabora/fonts-config |
GET | Font configuration JSON (stored in repository, regenerated on font changes) |
/collabora/fonts/{font_name} |
GET | Serves individual font files |
| Endpoint | Method | Description |
|---|---|---|
/collabora/admin/remote-config |
GET | Read current configuration |
/collabora/admin/remote-config |
POST | Update configuration (JSON body with "kind": "configuration", validated and re-serialized) |
/collabora/admin/fonts |
GET | List available fonts |
/collabora/admin/fonts?name={name}&mimeType={mimeType?} |
POST | Upload a font file (binary body, only font/ttf, font/otf, font/woff, font/woff2 accepted) |
/collabora/admin/fonts/{font_name} |
DELETE | Delete a font |
Configure coolwsd.xml to point to the Alfresco remote config endpoint:
<remote_config>
<remote_url type="string" default="">https://alfresco.example.com/alfresco/s/collabora/remote-config</remote_url>
</remote_config>Use the pristy-init example configuration to preload fonts:
pristy-init --server http://localhost:8080 --app collabora-online --init-file examples/collabora-online/init.yamlSee pristy-init/examples/collabora-online/ for the full configuration.
This feature implements Collabora Online Feature Restriction to manage user licenses. When enabled, only users belonging to a configurable Alfresco group can fully edit documents. Other users receive IsUserLocked=true in the WOPI CheckFileInfo response, which — combined with feature_lock.is_lock_readonly=true in Collabora's coolwsd.xml — forces them into read-only mode.
Type: Boolean
Default: false
Enable or disable group-based license restriction.
Type: String (Alfresco group full name)
Default: GROUP_COLLABORA_ONLINE
The Alfresco group whose members are considered licensed. The group is automatically created on first startup if it does not exist. Users in this group (including via nested groups) get full editing access.
Type: Integer
Default: -1 (unlimited)
Maximum number of users that can be added to the licensed group. Set to -1 for unlimited. This value is persisted via Alfresco's AttributeService and can be updated at runtime via the admin webscript without restarting Alfresco.
For the feature restriction to enforce read-only mode, you must configure Collabora Online's coolwsd.xml:
<feature_lock>
<is_lock_readonly type="bool" default="true">true</is_lock_readonly>
</feature_lock>All license management webscripts require admin authentication.
| Endpoint | Method | Description |
|---|---|---|
/collabora/license |
GET | List license status: enabled flag, count, max, and licensed user IDs |
/collabora/license/grant?user={userId} |
POST | Grant a license to a user (add to group) |
/collabora/license/revoke?user={userId} |
POST | Revoke a license from a user (remove from group) |
/collabora/license/config?maxLicenses={n} |
POST | Update the maximum number of licenses at runtime |
Examples:
# List licensed users
curl -u admin:admin "http://localhost:8080/alfresco/s/collabora/license"
# Grant a license
curl -u admin:admin -X POST "http://localhost:8080/alfresco/s/collabora/license/grant?user=jdoe"
# Revoke a license
curl -u admin:admin -X POST "http://localhost:8080/alfresco/s/collabora/license/revoke?user=jdoe"
# Set max licenses to 50
curl -u admin:admin -X POST "http://localhost:8080/alfresco/s/collabora/license/config?maxLicenses=50"Each grant or revoke operation is logged at INFO level with the total license count.
This feature implements the Collabora Online WOPI Settings API so Collabora can store and retrieve per-user and shared settings (AutoText, dictionaries, interface preferences xcu, and the browsersetting.json UI state) directly in the Alfresco repository. It also exposes the settings management iframe used by pristy-portail (a per-user preferences page and an admin shared-settings tab).
Settings are loaded in two ways: when a document is opened, CheckFileInfo advertises UserSettings and SharedSettings (each a {uri, stamp} pointing at /wopi/settings) so Collabora fetches them automatically; and through the standalone settings management iframe (launched via /collabora/settings-config).
Requirement: Collabora Online 24.04 or newer — for the standalone iframe, the /hosting/discovery must advertise the Settings app (<app name="Settings"><action name="iframe" .../></app>). If absent, the launch endpoint returns 501.
Settings are persisted in the repository:
- systemconfig (shared) →
/Data Dictionary/<remoteConfig.basePath>/shared-settings/. Writing requires administrator rights; readable by all. - userconfig (per user) →
<user home>/<settings.userPath>/, under the authenticated user.
Settings files receive the cm:versionable aspect (auto-version on change).
Type: String
Default: Configuration/Collabora Online
Relative folder path under each user's home folder where per-user (userconfig) settings are stored.
Type: URL
Default: ${alfresco.public.url}/s/wopi/settings
The full /wopi/settings endpoint Collabora calls back. Collabora appends the query string (Fetch/Delete) or /download / /upload directly to this base, so it must point at /wopi/settings (not /wopi). Sent to the settings iframe as wopi_setting_base_url and used to build the download URI in Fetch settings.
Called by Collabora Online directly (the access token is validated to a user, not bound to a document). Secure them at the network/reverse proxy level.
| Endpoint | Method | Description |
|---|---|---|
/wopi/settings?type={userconfig|systemconfig}&fileId=-1&access_token= |
GET | Fetch settings: list available files per category |
/wopi/settings/download?fileId={/settings/...}&access_token= |
GET | Download a single settings file (incl. browsersetting.json) |
/wopi/settings/upload?fileId={/settings/...}&access_token= |
POST | Create/replace a settings file (multipart file) |
/wopi/settings?fileId={/settings/...}&access_token= |
DELETE | Delete a settings file |
Access token delivery (query or Authorization: Bearer). These endpoints accept the access token from either the access_token query parameter or an Authorization: Bearer <token> header. This is required because Collabora delivers the token differently depending on the call:
- Fetch and Download use URLs that the WOPI host itself builds, so the token is embedded in the
access_tokenquery parameter. - The preset round-trip upload (
wordbook,xcu,themes— e.g. words added via Add to dictionary) is built by Collabora'sDocumentBroker::uploadPresetsToWopiHost, which — unlike every other WOPI call — does not add the token to the query and sends it only as anAuthorization: Bearerheader.
Without the header fallback, those round-trip uploads are rejected (HTTP 401) and never persist, so the saved settings (the user dictionary in particular) silently fail to reload on the next document open. Every rejected settings request is now logged at WARN (Rejected settings request <path>: <reason>).
| Endpoint | Method | Description |
|---|---|---|
/collabora/settings-config?type={user|admin} |
GET | User authentication. Returns access_token, access_token_ttl, settings_url (discovery iframe urlsrc), wopi_setting_base_url and iframe_type to launch the settings management iframe. type=admin requires administrator rights; returns 501 when the Collabora server does not advertise the settings iframe. |
The lock cleanup job is deprecated since version 1.0.0. Alfresco's native lock management is now used instead.
Type: Boolean
Default: false
Enable or disable the lock cleanup job. Should remain disabled in version 1.0+.
Type: Cron expression
Default: 0 0/5 * * * ? (every 5 minutes)
Cron schedule for the lock cleanup job. Only used if enabled.
Type: Integer (milliseconds)
Default: 240000 (4 minutes)
Delay before the first execution of the cleanup job after Alfresco startup.
# ============================================
# Alfresco Collabora Online Configuration
# ============================================
# Connection URLs
collabora.public.url=https://collabora.example.com/
collabora.private.url=http://collabora-internal:9980/
alfresco.public.url=https://alfresco.example.com/alfresco/
alfresco.private.url=http://alfresco-internal:8080/alfresco/
# Token configuration
lool.wopi.token.ttl=86400000
# Discovery timeout (optional, default 500ms)
#fr.jeci.collabora.discovery.readTimeoutMs=500
# Renditions (optional)
fr.jeci.collabora.renditions=imgpreview,medium,doclib,pdf
# Remote/Dynamic Configuration (optional)
fr.jeci.collabora.remoteConfig.basePath=collabora-online
fr.jeci.collabora.remoteConfig.fontsUrl=https://alfresco.example.com/alfresco/s/collabora/fonts
# Feature Restriction (optional - disabled by default)
fr.jeci.collabora.featureRestriction.enabled=false
fr.jeci.collabora.featureRestriction.group=GROUP_COLLABORA_ONLINE
fr.jeci.collabora.featureRestriction.maxLicenses=-1
# Lock cleanup job (deprecated - keep disabled)
job.fr.jeci.collabora.cleanLock.enabled=false
job.fr.jeci.collabora.cleanLock.cron=0 0/5 * * * ?
job.fr.jeci.collabora.cleanLock.cronstartdelay=240000For detailed release history and changelog, see CHANGELOG.md.
Current version: 1.4.0
If you are upgrading from a version prior to 0.3.1, you need to update your configuration properties.
Remove old properties from alfresco-global.properties:
# OLD - Remove these:
lool.wopi.url=...
lool.wopi.alfresco.host=...
lool.wopi.url.discovery=...Add new properties:
# NEW - Add these:
collabora.public.url=https://<collabora_server_domain>:<port>/
alfresco.public.url=https://<alfresco_server_domain>:<port>/alfresco/
# Optional - for internal network
collabora.private.url=${collabora.public.url}
alfresco.private.url=${alfresco.public.url}Version 1.0.0 introduced a major change: the extension now uses Alfresco's native LockService instead of custom aspects.
Before migration:
- Locks were managed using the
collabora:collaboraOnlineaspect - Custom lock properties were stored on documents
- Automatic cleanup job removes obsolete locks
After migration:
- Locks use Alfresco's standard lock mechanism
Required actions:
-
Lock cleanup job - The lock cleanup job is now deprecated and disabled by default in version 1.0+. Alfresco's native lock management is used instead. If you have the job enabled from a previous configuration, you should disable it in
alfresco-global.properties:job.fr.jeci.collabora.cleanLock.enabled=false -
Clean up old aspects (optional, recommended for large repositories):
After upgrading, you may want to remove old
collabora:collaboraOnlineaspects from documents. This can be done via:- JavaScript console in Alfresco
- Custom migration script
- Manual cleanup using the Node Browser
Example JavaScript to remove old aspects:
var nodes = search.luceneSearch("ASPECT:\"collabora:collaboraOnline\""); for (var i = 0; i < nodes.length; i++) { if (nodes[i].hasAspect("collabora:collaboraOnline")) { nodes[i].removeAspect("collabora:collaboraOnline"); nodes[i].save(); } } logger.log("Cleaned up " + nodes.length + " nodes");
-
Verify lock behavior:
- Test document editing with multiple users
- Verify lock indicators appear correctly in Share
- Check that locks are automatically released
Version 1.0.0 also introduced automatic rendition generation after document changes.
Configure renditions in alfresco-global.properties (optional):
# Comma-separated list of rendition names to generate
fr.jeci.collabora.renditions=imgpreview,medium,doclib,pdfVerify:
- Edit a document with Collabora Online
- Save changes
- Check that thumbnails are regenerated automatically
This project is maintained by Jeci a french company that specializes in Free and Open Source technologies (FLOSS).
For any question or professional services, please send us an email info@jeci.fr