Skip to content
Author Nejat Hakan
eMail nejat.hakan@outlook.de
PayPal Me https://paypal.me/nejathakan


Office Suite Backend Collabora Online

Introduction Collabora Online

Welcome to this comprehensive guide on self-hosting Collabora Online, the powerful open-source online office suite backend based on LibreOffice technology. This document will take you from the fundamental concepts to advanced deployment strategies, equipping you with the knowledge and practical skills needed to run your own secure and private collaborative document editing environment.

Collabora Online enables users to collaboratively edit text documents, spreadsheets, and presentations directly within a web browser. It acts as a backend service that integrates with various frontend file hosting platforms like Nextcloud, ownCloud, Seafile, Moodle, and others using the standard WOPI (Web Application Open Platform Interface) protocol.

Why self-host Collabora Online?

  1. Data Sovereignty and Privacy: Keep your sensitive documents entirely within your own infrastructure. You control who has access and where the data resides, eliminating reliance on third-party cloud providers and their privacy policies.
  2. Control and Customization: Tailor the environment to your specific needs. Modify configuration settings, integrate with existing authentication systems, and even apply custom branding.
  3. Cost-Effectiveness (Potentially): While requiring server resources and maintenance time, self-hosting can be more cost-effective in the long run compared to per-user subscription fees of commercial cloud services, especially for larger organizations or communities.
  4. Security: You manage the security updates, firewall rules, and access controls, allowing for security postures tailored to your organization's requirements.
  5. Learning Opportunity: Setting up and managing a service like Collabora Online provides invaluable experience in server administration, containerization, networking, and security.

This guide is structured into Basic, Intermediate, and Advanced levels, catering to different skill sets and deployment goals. Each section includes theoretical explanations followed by practical workshops designed to reinforce learning through hands-on experience. We assume you have a foundational understanding of Linux server administration, basic networking concepts, and familiarity with the command line.

Let's begin by understanding the core components and architecture. Collabora Online Development Edition (CODE), the freely available version we'll focus on, typically runs as a Docker container. It consists of several key components:

  • loolwsd (LibreOffice Online WebSocket Daemon): The main service daemon. It listens for incoming WebSocket connections from the frontend application (via a reverse proxy), manages user sessions, and orchestrates document rendering and editing. It acts as the WOPI host.
  • loolforkit: A process responsible for spawning sandboxed LibreOffice instances (loolkit) for each active document being edited. This ensures isolation between documents and users.
  • loolkit: The actual LibreOffice process, running in a chrooted environment, that handles the document rendering and editing tasks based on instructions received from loolwsd.

The typical interaction flow is as follows:

  1. A user clicks a document in their file hosting platform (e.g., Nextcloud).
  2. Nextcloud (the WOPI client) makes a request to Collabora Online (loolwsd, the WOPI host), providing information about the document and the user via the WOPI protocol.
  3. loolwsd validates the request and instructs loolforkit to start a dedicated loolkit process for that document session.
  4. loolwsd establishes a WebSocket connection back to the user's browser (usually proxied through Nextcloud and a reverse proxy).
  5. Document tiles (rendered images of document parts) and user interface elements are sent to the browser, and user input (keystrokes, mouse clicks) is sent back to loolwsd to be processed by loolkit.
  6. Changes are periodically saved back to the file hosting platform via WOPI PutFile requests initiated by loolwsd.

Understanding this architecture is crucial for installation, configuration, and troubleshooting.

General Prerequisites:

  • A Linux server (physical or virtual) with root/sudo access. Distributions like Ubuntu, Debian, or CentOS are common choices.
  • Docker and Docker Compose installed on the server.
  • A registered domain name (essential for proper SSL/TLS setup, especially beyond basic testing).
  • Basic understanding of DNS records (A or CNAME records).
  • Familiarity with a command-line text editor (like nano, vim, or emacs).
  • Network connectivity allowing connections on specific ports (typically 80, 443, and the Collabora port like 9980).

Let's dive into the basic setup.

1. Basic Level

This section covers the fundamentals of Collabora Online CODE, including its core components, resource needs, basic installation using Docker, and initial integration with a file hosting platform like Nextcloud.

Understanding Collabora Online CODE

Collabora Online Development Edition (CODE) is the freely available version of Collabora Online, provided primarily for home users, developers, and small teams. It contains the full feature set but comes with limitations on the number of concurrent connections and documents compared to the commercially supported version (Collabora Enterprise). For educational purposes and many self-hosting scenarios, CODE is perfectly adequate.

CODE vs. LibreOffice

It's important to distinguish CODE from the standard LibreOffice desktop suite:

  • LibreOffice: A powerful, open-source desktop office suite (Writer, Calc, Impress, Draw, Math, Base) installed directly on a user's computer.
  • Collabora Online (CODE): A server application that uses the LibreOffice core engine (libreofficikit) to render and enable editing of documents within a web browser. It requires integration with a separate file management frontend. Users interact with it via their browser, not a desktop application.

CODE essentially takes the core document processing capabilities of LibreOffice and makes them accessible over the web through the loolwsd daemon and WebSocket communication.

Key Components Revisited

Let's reiterate the main parts running inside the CODE Docker container:

  • loolwsd: The central nervous system. It handles:
    • WOPI protocol communication with the frontend (Nextcloud, etc.).
    • Managing WebSocket connections to user browsers.
    • Authentication/Authorization checks based on WOPI tokens.
    • Distributing editing tasks to loolkit instances.
    • Saving documents back to the host.
    • Serving static assets (JavaScript, CSS) for the editing interface.
  • loolforkit: The process spawner. When loolwsd needs a document opened, it asks loolforkit to create a new, isolated loolkit process specifically for that document session. This enhances security and stability.
  • loolkit: The workhorse. This is a modified LibreOffice instance that actually loads the document, renders it into viewable tiles, processes user input, and calculates changes. Each open document typically gets its own loolkit process.

These components work together seamlessly to provide the online editing experience.

Resource Requirements

Collabora Online can be resource-intensive, particularly regarding CPU and RAM, as it effectively runs instances of LibreOffice on the server for each active document.

  • Minimum Requirements (for light use, 1-2 concurrent users/documents):
    • CPU: 2 Cores
    • RAM: 2 GB (+ RAM for the host OS and other services)
    • Disk Space: 5 GB (for the Docker image and logs, document storage is handled by the frontend)
  • Recommended Requirements (for small teams, ~10 concurrent users/documents):
    • CPU: 4+ Cores
    • RAM: 4-8 GB (+ RAM for host OS/other services)
    • Disk Space: 10+ GB

Important Considerations:

  • Concurrent Users vs. Concurrent Documents: CODE's performance is more directly tied to the number of actively edited documents than the total number of users who might use it. Each open document consumes significant RAM and CPU.
  • Document Complexity: Large or complex documents (e.g., spreadsheets with many formulas, presentations with high-resolution images) require more resources per session.
  • Host System: Ensure the underlying host operating system has sufficient resources in addition to those allocated for Collabora Online. Running other services (like Nextcloud itself, databases, web servers) on the same machine requires careful resource planning.

Insufficient resources will lead to slow loading times, unresponsive editing, and potentially crashes of the loolkit processes.

Workshop Basic Installation (Docker)

This workshop guides you through installing Collabora Online CODE using the official Docker image. This is the simplest and most recommended way to get started.

Goal: Run a basic CODE instance accessible on your local server.

Prerequisites:

  • A Linux server with Docker installed and running.
  • Sudo/root privileges.
  • Internet connection to download the Docker image.

Steps:

  1. Pull the Docker Image: Open a terminal on your server and download the latest CODE image from Docker Hub:

    sudo docker pull collabora/code:latest
    
    This command fetches the image layers. It might take a few minutes depending on your internet speed.

  2. Run the CODE Container: Now, start the container. We need to expose the default port 9980 and provide the domain name of the frontend application (like Nextcloud) that will be allowed to connect. Replace nextcloud\.example\.com with the actual domain name of your Nextcloud instance (or the domain you plan to use). Crucially, you need to escape the dots (.) with backslashes (\) because this is treated as a regular expression. If your Nextcloud runs on cloud.mydomain.org, use cloud\.mydomain\.org. If you are just testing locally without a real domain yet, you might use the server's IP address, escaping the dots (e.g., 192\.168\.1\.100).

    sudo docker run -t -d -p 127.0.0.1:9980:9980 \
        -e "domain=nextcloud\.example\.com" \
        --restart always \
        --cap-add MKNOD \
        --name code \
        collabora/code:latest
    

    Explanation of options:

    • -t: Allocate a pseudo-TTY.
    • -d: Run the container in detached mode (in the background).
    • -p 127.0.0.1:9980:9980: Map port 9980 inside the container to port 9980 on the host machine's localhost interface only. This is a security measure for now; we only want local access until we set up a reverse proxy. If you need access from other machines without a reverse proxy (not recommended for production), you might use -p 9980:9980.
    • -e "domain=nextcloud\.example\.com": Set the domain environment variable. This is crucial. It tells loolwsd which WOPI client domains are allowed to connect. It's a regular expression, hence the escaped dots. You can allow multiple domains using a pipe | character, e.g., "domain=cloud\.example\.com|office\.example\.com".
    • --restart always: Automatically restart the container if it stops or if the server reboots.
    • --cap-add MKNOD: Required by loolwsd to create device nodes within its chroot jail environment. This capability allows the container process to create special files using the mknod system call, which is necessary for the sandboxing mechanism (loolforkit) to function correctly.
    • --name code: Assign a convenient name (code) to the container for easier management (e.g., docker logs code, docker stop code).
    • collabora/code:latest: The image to use.
  3. Verify Container Status: Check if the container is running:

    sudo docker ps
    
    You should see an entry for the code container with status "Up".

  4. Check Container Logs: View the initial logs to ensure there are no immediate errors:

    sudo docker logs code
    
    Look for lines indicating wsd (the web service daemon) has started successfully and is listening on port 9980. You might see lines like wsd-000xx-000xx [ loolwsd ] INFO Initialized WOPI storage. or wsd-000xx-000xx [ loolwsd ] INFO Listening on IPv4 address [::]:9980. (Note: [::] indicates it's listening on all interfaces inside the container, but our -p 127.0.0.1:9980:9980 restricts host access to localhost).

  5. Access Basic Admin Consoles (Optional but Recommended): Even without a frontend connected, CODE provides some endpoints for basic checks. Since we bound it to 127.0.0.1, you need to access these from the server itself, for example using curl:

    • Discovery URL: This XML file tells potential WOPI clients about CODE's capabilities.

      curl http://127.0.0.1:9980/hosting/discovery
      
      You should see XML output describing supported file types and actions.

    • Admin Console: CODE has a basic admin interface.

      curl http://127.0.0.1:9980/loleaflet/dist/admin/admin.html
      
      You should get HTML output. To view this properly, you'd typically access it through a browser via a reverse proxy later. For now, getting any HTML back confirms the service is responding.

    • Health Check: A simple health check endpoint.

      curl http://127.0.0.1:9980/lool/healthz
      
      You should see an ok response.

Outcome: You now have a running Collabora Online CODE container on your server, listening on port 9980 of the localhost interface, and configured to allow connections only from the domain specified in the domain environment variable. It's ready to be integrated with a frontend application.

Integrating with Nextcloud/ownCloud (Basic)

Collabora Online doesn't function standalone for users; it needs a frontend file management system that acts as a WOPI client. Nextcloud and ownCloud are the most popular choices for this integration.

Conceptual Overview (WOPI Protocol)

The integration relies on the WOPI (Web Application Open Platform Interface) protocol. Think of it as a standardized language that allows a file server (like Nextcloud) to communicate with an office editing server (like Collabora Online).

Here's a simplified breakdown:

  1. Discovery: Nextcloud needs to know where Collabora Online is and what it can do. It fetches the /hosting/discovery XML file from Collabora.
  2. User Action: A user in Nextcloud clicks on a document (e.g., mydocument.docx).
  3. Generate WOPI Token & URL: Nextcloud generates a unique, short-lived access token specific to that user and that document. It then constructs a special URL containing:
    • The Collabora server's editing endpoint (e.g., https://collabora.example.com/loleaflet/dist/loleaflet.html).
    • A WOPISrc parameter pointing back to a unique URL on the Nextcloud server for that specific file.
    • An access_token parameter containing the generated token.
  4. Redirect User: Nextcloud redirects the user's browser to this constructed URL.
  5. Collabora Loads: The user's browser connects to Collabora Online. Collabora's JavaScript (loleaflet.html) uses the WOPISrc URL and access_token to make calls back to Nextcloud (e.g., "CheckFileInfo", "GetFile").
  6. Nextcloud Validates: Nextcloud receives these calls, validates the access_token, and provides Collabora with the file contents or information requested.
  7. Editing Session: Collabora establishes the WebSocket connection for the editing session. Changes are sent back to Nextcloud using WOPI "PutFile" requests.

The key takeaway is that Collabora never directly accesses Nextcloud's file system. All interaction happens via these WOPI API calls, secured by the access token.

Installing the Connector App

Both Nextcloud and ownCloud require a specific "connector" application to enable the WOPI integration.

  • For Nextcloud: Navigate to "Apps" -> "Office & text". Find the "Nextcloud Office" app (which bundles the Collabora Connector) and click "Download and enable".
  • For ownCloud: Navigate to "Market" -> "Tools". Find the "Collabora Online" app and click "Install".

Basic Configuration (URL)

Once the connector app is enabled, you need to tell Nextcloud/ownCloud where your Collabora Online server is running.

  • For Nextcloud: Go to "Administration settings" -> "Nextcloud Office".
  • For ownCloud: Go to "Settings" -> "Admin" -> "Additional".

In the relevant section, you will find a field asking for the "URL (and port) of Collabora Online server".

You need to enter the URL that Nextcloud can use to reach your Collabora server. Crucially, this must match what Collabora expects based on its configuration (like the domain variable and reverse proxy setup, which we'll cover later).

For our basic workshop setup where Collabora is running on http://127.0.0.1:9980 and only accessible from the server itself, direct integration isn't usually possible unless Nextcloud is also running on the exact same server and can access 127.0.0.1:9980.

The next workshop demonstrates this, assuming a local Nextcloud instance for simplicity. In real-world scenarios, you'll almost always use a reverse proxy, which we'll configure in the Intermediate section.

Workshop Basic Integration

This workshop demonstrates integrating the locally running CODE container (from the previous workshop) with a Nextcloud instance running on the same server. This is primarily for testing the basic connection.

Goal: Connect Nextcloud to the local CODE container and test opening a document.

Prerequisites:

  • Collabora Online CODE running locally, listening on 127.0.0.1:9980 (as per the previous workshop).
  • A Nextcloud instance installed and accessible on the same server. For testing, this could be a Docker-based Nextcloud or a manual installation accessible via http://localhost or http://<server_IP>.
  • The domain= parameter used when starting the CODE container must match the domain/IP Nextcloud uses to identify itself (e.g., if Nextcloud is accessed via http://192.168.1.100, the CODE container should have been started with domain=192\.168\.1\.100). If they don't match, stop the CODE container (sudo docker stop code), remove it (sudo docker rm code), and restart it with the correct -e "domain=..." value.

Steps:

  1. Access Nextcloud: Log in to your Nextcloud instance as an administrator.
  2. Install Nextcloud Office App:
    • Go to "Apps" (click your user icon in the top right).
    • Navigate to the "Office & text" category.
    • Find "Nextcloud Office" and click "Download and enable". Wait for the installation to complete.
  3. Configure Collabora Server URL:

    • Go to "Administration settings" (click your user icon).
    • In the left sidebar under "Administration", click "Nextcloud Office".
    • Select "Use your own server".
    • In the "URL (and port) of Collabora Online server" field, enter: http://127.0.0.1:9980
    • Click "Save". Nextcloud will attempt to connect to this URL to verify the setup. It should show a success message like "Collabora Online server is reachable." If it fails, double-check:
      • Is the CODE container running (docker ps)?
      • Is it listening on 127.0.0.1:9980?
      • Are Nextcloud and CODE running on the same machine?
      • Check CODE logs (docker logs code) for connection attempt errors (e.g., "Unauthorized WOPI host"). This usually means the domain= parameter in your docker run command doesn't match how Nextcloud identifies itself.
  4. Test Document Editing:

    • Navigate to "Files" in Nextcloud.
    • Click the "+" button -> "New document" (or "New spreadsheet", "New presentation"). Give it a name (e.g., Test.docx).
    • Click on the newly created file.
    • If the integration is working, the Collabora Online interface should load within Nextcloud, allowing you to edit the document.
    • Type some text, wait a few seconds for the "Saving..." and "Saved" indicators (usually a checkmark icon).
    • Close the document tab/window.
    • Re-open the document to verify your changes were saved.

Outcome: You have successfully integrated a local Nextcloud instance with a local Collabora Online CODE container. You can now create and collaboratively edit documents directly within Nextcloud, albeit without the security and accessibility benefits of a proper reverse proxy and SSL setup. This confirms the basic WOPI communication is functional.

2. Intermediate Level

Now that you have a basic understanding and a functional local setup, we'll move on to more robust and realistic configurations. This involves setting up a reverse proxy for secure access, enabling SSL/TLS encryption, and exploring more advanced configuration options within Collabora Online.

Reverse Proxy Setup (Nginx/Apache)

Running Collabora Online directly exposed to the internet or even just your local network on port 9980 is not recommended for several reasons:

  • Security: Exposes the Collabora service directly, increasing the attack surface.
  • SSL/TLS Encryption: Collabora Online can handle SSL itself, but managing certificates directly within the container is cumbersome and less flexible. Centralizing SSL termination at the reverse proxy is standard practice.
  • Port Conflicts: Only one application can listen on standard ports 80 (HTTP) and 443 (HTTPS). A reverse proxy allows multiple web services (Nextcloud, Collabora, websites, etc.) to coexist behind a single public IP address and standard ports.
  • Load Balancing: Reverse proxies are the foundation for distributing traffic across multiple Collabora instances for scalability (covered in Advanced).
  • URL Rewriting/Path Handling: Allows cleaner URLs and maps external paths to internal services.

A reverse proxy acts as an intermediary server. It receives requests from clients (like web browsers or the Nextcloud server), forwards those requests to the appropriate backend service (Collabora Online on port 9980), and relays the backend's response back to the client.

We will cover configurations for two popular web servers often used as reverse proxies: Nginx and Apache.

Configuring Nginx for Collabora

Nginx is a high-performance web server frequently used as a reverse proxy. Configuration typically involves creating a server block in your Nginx configuration files (often within /etc/nginx/sites-available/).

Key Nginx Directives:

  • server_name: Defines the domain name this block applies to (e.g., collabora.example.com).
  • listen: Specifies the port to listen on (80 for HTTP, 443 for HTTPS).
  • ssl_certificate, ssl_certificate_key: Paths to your SSL certificate and private key files (for HTTPS).
  • location /: Defines how to handle requests for the root path and potentially subpaths.
  • proxy_pass: The core directive that forwards requests to the backend Collabora service (e.g., http://127.0.0.1:9980).
  • proxy_set_header: Modifies or adds HTTP headers sent to the backend. Essential for passing information like the original host, client IP, and protocol.
  • WebSocket Support: Collabora relies heavily on WebSockets for real-time communication. Nginx needs specific directives to correctly proxy WebSocket connections:
    • proxy_http_version 1.1;
    • proxy_set_header Upgrade $http_upgrade;
    • proxy_set_header Connection "upgrade";
    • proxy_set_header Host $host;
    • proxy_read_timeout 3600s; (or longer, to prevent premature disconnection)

Example Nginx Configuration Snippet (HTTPS):

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name collabora.example.com; # Your Collabora domain

    # SSL configuration
    ssl_certificate /etc/letsencrypt/live/collabora.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/collabora.example.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf; # Recommended SSL parameters
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # Diffie-Hellman parameters

    # static files
    location ^~ /loleaflet {
        proxy_pass http://127.0.0.1:9980; # Collabora backend
        proxy_set_header Host $http_host; # Use $http_host NOT $host with proxy_pass
    }

    # WOPI discovery URL
    location ^~ /hosting/discovery {
        proxy_pass http://127.0.0.1:9980;
        proxy_set_header Host $http_host;
    }

    # Main websocket channel (loolwsd)
    # Note: Ensure your Nginx version is >= 1.4 for WebSocket proxying
    location ^~ /lool {
        proxy_pass http://127.0.0.1:9980;
        proxy_set_header Host $http_host;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 3600s; # Set higher timeout for long editing sessions
    }

    # Admin Console websocket channel (loolwsd)
    location ^~ /lool/adminws {
        proxy_pass http://127.0.0.1:9980;
        proxy_set_header Host $http_host;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 3600s;
    }

    # Optional: Add security headers
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Content-Type-Options nosniff;
    add_header X-Frame-Options SAMEORIGIN;
    add_header X-XSS-Protection "1; mode=block";
    add_header Referrer-Policy "no-referrer"; # Adjust if needed
}

# Optional: Redirect HTTP to HTTPS
server {
    listen 80;
    listen [::]:80;
    server_name collabora.example.com;
    location / {
        return 301 https://$host$request_uri;
    }
}

Remember to replace collabora.example.com and the proxy_pass target (127.0.0.1:9980) if your setup differs.

Configuring Apache for Collabora

Apache httpd can also function as a reverse proxy using modules like mod_proxy, mod_proxy_http, and crucially, mod_proxy_wstunnel for WebSocket support. Configuration is typically done within a VirtualHost block.

Key Apache Modules:

  • mod_proxy: Core proxy functionality.
  • mod_proxy_http: Proxying HTTP requests.
  • mod_proxy_wstunnel: Proxying WebSocket connections (essential!).
  • mod_ssl: For handling HTTPS.
  • mod_headers: For manipulating HTTP headers.
  • mod_rewrite: Often used for conditional proxying or URL manipulation.

Example Apache Configuration Snippet (HTTPS):

<VirtualHost *:443>
    ServerName collabora.example.com

    # SSL Configuration
    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/collabora.example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/collabora.example.com/privkey.pem
    # Include recommended SSL settings if available, e.g., from Let's Encrypt/Certbot
    # Include /etc/letsencrypt/options-ssl-apache.conf

    # Proxy Basic Settings
    ProxyPreserveHost On
    ProxyRequests Off # Crucial for security: Off means Reverse Proxy mode

    # AllowEncodedSlashes NoDecode needed for WOPI URLs
    AllowEncodedSlashes NoDecode

    # Proxy WebSocket setup for /lool endpoint
    ProxyPass        /lool ws://127.0.0.1:9980/lool retry=0
    ProxyPassReverse /lool ws://127.0.0.1:9980/lool retry=0

    # Proxy WebSocket setup for /lool/adminws endpoint (Admin Console)
    ProxyPass        /lool/adminws ws://127.0.0.1:9980/lool/adminws retry=0
    ProxyPassReverse /lool/adminws ws://127.0.0.1:9980/lool/adminws retry=0

    # Proxy all other requests for Collabora static files and discovery
    ProxyPass        / http://127.0.0.1:9980/ retry=0
    ProxyPassReverse / http://127.0.0.1:9980/ retry=0

    # Set timeouts to handle long connections
    ProxyTimeout 3600

    # Optional: Add security headers
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set Referrer-Policy "no-referrer"
    Header always set X-XSS-Protection "1; mode=block"

</VirtualHost>

# Optional: Redirect HTTP to HTTPS
<VirtualHost *:80>
    ServerName collabora.example.com
    Redirect permanent / https://collabora.example.com/
</VirtualHost>

Remember to enable the necessary Apache modules (a2enmod proxy proxy_http proxy_wstunnel ssl headers rewrite) and adjust domain names and the backend URL.

SSL/TLS Termination (Let's Encrypt)

Securing the connection between the user's browser and your Collabora instance is paramount. HTTPS encrypts the traffic, preventing eavesdropping. Terminating SSL at the reverse proxy means the proxy handles the encryption/decryption, and the connection between the proxy and the Collabora container can be plain HTTP (if they are on the same secure host or network).

Let's Encrypt is a free, automated, and open Certificate Authority (CA) that provides SSL/TLS certificates. The easiest way to obtain and manage Let's Encrypt certificates is using the Certbot client.

Using Certbot:

  1. Install Certbot: Follow the official Certbot instructions for your OS and web server (Nginx/Apache): https://certbot.eff.org/
  2. Obtain Certificate: Certbot can often automatically obtain the certificate and configure your web server.
    • For Nginx: sudo certbot --nginx -d collabora.example.com
    • For Apache: sudo certbot --apache -d collabora.example.com
    • Alternatively, obtain only the certificate: sudo certbot certonly --webroot -w /var/www/html -d collabora.example.com (adjust webroot path) or sudo certbot certonly --standalone -d collabora.example.com (requires temporarily stopping your web server).
  3. Auto-Renewal: Certbot typically sets up automatic renewal via a systemd timer or cron job. Verify this with sudo systemctl list-timers or sudo crontab -l.

Once you have the certificate files (usually in /etc/letsencrypt/live/yourdomain.com/), you reference them in your Nginx/Apache SSL configuration directives as shown in the examples above.

Workshop Secure Access with Reverse Proxy and SSL

This workshop guides you through setting up Nginx as a reverse proxy for your Collabora Online container, securing it with a Let's Encrypt SSL certificate.

Goal: Make Collabora Online accessible via HTTPS on a dedicated subdomain (e.g., https://collabora.example.com), with Nginx handling SSL termination.

Prerequisites:

  • Collabora Online CODE running in Docker, listening on 127.0.0.1:9980.
  • A registered domain name (e.g., example.com).
  • DNS configured: An A record for a subdomain (e.g., collabora.example.com) pointing to your server's public IP address.
  • Nginx installed on your server.
  • Certbot installed on your server.
  • Ports 80 and 443 open on your server's firewall.
  • Sudo/root privileges.

Steps:

  1. Stop and Remove Existing CODE Container (If Necessary): If your previous CODE container was bound publicly or had SSL enabled internally, it's best to reconfigure it for proxying. Ensure the domain= variable used previously still correctly reflects your Nextcloud domain. We need to add options to disable internal SSL handling and tell it SSL is terminated externally.

    sudo docker stop code
    sudo docker rm code
    
  2. Restart CODE Container for Proxying: Restart the container, ensuring it listens only on 127.0.0.1 and adding the ssl.enable=false and ssl.termination=true parameters via the extra_params environment variable. Replace nextcloud\.example\.com with your actual Nextcloud domain (dots escaped).

    sudo docker run -t -d -p 127.0.0.1:9980:9980 \
        -e "domain=nextcloud\.example\.com" \
        -e "extra_params=--o:ssl.enable=false --o:ssl.termination=true" \
        --restart always \
        --cap-add MKNOD \
        --name code \
        collabora/code:latest
    
    • -e "extra_params=--o:ssl.enable=false --o:ssl.termination=true": These crucial parameters tell loolwsd not to handle SSL itself but to expect the reverse proxy to do it.
  3. Obtain SSL Certificate with Certbot: Use Certbot to get a certificate for your Collabora subdomain. Using the Nginx plugin is often easiest if Nginx is already installed. Replace collabora.example.com with your chosen subdomain.

    sudo certbot --nginx -d collabora.example.com
    
    Follow the prompts. Certbot will ask about email registration and agreeing to terms. It should detect your domain, obtain the certificate, and offer to configure Nginx automatically (usually creating or modifying the SSL parts of the server block). Choose the option to redirect HTTP to HTTPS if prompted.

  4. Configure Nginx Reverse Proxy: Certbot might have created a basic configuration. You need to ensure it includes the necessary proxy_pass and WebSocket settings for Collabora. Edit the Nginx configuration file for your site (often /etc/nginx/sites-available/collabora.example.com or /etc/nginx/conf.d/collabora.conf, depending on your setup and Certbot's actions).

    Make sure your server block for port 443 looks similar to the Nginx example provided earlier, specifically including:

    • Correct server_name.
    • Correct ssl_certificate and ssl_certificate_key paths (Certbot usually sets these).
    • The location blocks for /loleaflet, /hosting/discovery, /lool, and /lool/adminws with the correct proxy_pass http://127.0.0.1:9980; directive and WebSocket headers for the /lool locations.

    Example Snippet to Ensure is Present/Correct within the server { listen 443 ssl ... } block:

        # static files
        location ^~ /loleaflet {
            proxy_pass http://127.0.0.1:9980;
            proxy_set_header Host $http_host;
        }
    
        # WOPI discovery URL
        location ^~ /hosting/discovery {
            proxy_pass http://127.0.0.1:9980;
            proxy_set_header Host $http_host;
        }
    
        # Main websocket channel (loolwsd)
        location ^~ /lool {
            proxy_pass http://127.0.0.1:9980;
            proxy_set_header Host $http_host;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_read_timeout 3600s; # Important for stability
            proxy_buffering off; # Useful for WebSockets
        }
    
        # Admin Console websocket channel (loolwsd)
        location ^~ /lool/adminws {
            proxy_pass http://127.0.0.1:9980;
            proxy_set_header Host $http_host;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_read_timeout 3600s;
            proxy_buffering off;
        }
    

  5. Test Nginx Configuration and Reload: Always test your Nginx configuration before applying it:

    sudo nginx -t
    
    If it reports "syntax is ok" and "test is successful", reload Nginx to apply the changes:
    sudo systemctl reload nginx
    

  6. Update Nextcloud Configuration:

    • Go back to your Nextcloud instance -> Administration settings -> Nextcloud Office.
    • Change the "URL (and port) of Collabora Online server" to your new HTTPS URL: https://collabora.example.com (no port number needed as it's standard HTTPS port 443).
    • Click "Save". Nextcloud should confirm that the server is reachable via the new secure URL.
  7. Test Access and Editing:

    • Try accessing https://collabora.example.com/hosting/discovery in your browser. You should see the XML file.
    • Try accessing https://collabora.example.com/loleaflet/dist/admin/admin.html. You should see the admin login page (though you likely don't have credentials configured yet).
    • Go to Nextcloud -> Files and try opening or creating an office document. It should load successfully via the secure reverse proxy connection. Check your browser's address bar and security indicators to confirm HTTPS is active.

Outcome: You have successfully configured Nginx as a reverse proxy for Collabora Online, secured the connection with Let's Encrypt SSL/TLS, and updated Nextcloud to use the secure endpoint. Your Collabora setup is now significantly more secure and accessible.

Advanced Configuration Options

While environment variables cover basic settings, Collabora Online's behavior is primarily controlled by an XML configuration file, typically loolwsd.xml. When using Docker, you can override settings using environment variables (like extra_params we used) or by mounting a custom loolwsd.xml file into the container. For more extensive customization, using a custom file is often cleaner.

loolwsd.xml Overview

The default loolwsd.xml file resides within the container, usually at /etc/loolwsd/loolwsd.xml. It contains numerous sections controlling various aspects of the service.

Key Sections:

  • <server_name>: The hostname the server identifies as. Should match the public URL.
  • <storage desc="Backend storage">: Contains information about allowed WOPI hosts (<host>). This is where the domain environment variable typically injects its value. You can manually list allowed host regex patterns here.
    <storage desc="Backend storage">
        <filesystem allow="false"/> <!-- Usually false, rely on WOPI -->
        <wopi desc="Allow/deny wopi storage. Mutually exclusive with webdav." allow="true">
            <!-- List of regex patterns for allowed WOPI hosts (e.g., Nextcloud domain) -->
            <host allow="true">nextcloud\.example\.com</host>
            <host allow="true">192\.168\.1\. S+$</host> <!-- Example: Allow local subnet -->
            <!-- <host allow="false">.*</host> --> <!-- Optional: Explicitly deny others -->
        </wopi>
        <!-- ... other storage options like webdav ... -->
    </storage>
    
  • <net desc="Network settings">: Controls listening interfaces, allowed connection addresses, and SSL settings (if handled internally).
    • <listen>: Typically all or specific IPs.
    • <connection_idle_timeout_secs>: How long idle connections are kept.
    • <allowed_connect_hosts>: Which IPs can connect directly to loolwsd (important if not using a loopback proxy pass).
  • <ssl desc="SSL settings">: Configures SSL if handled by loolwsd. The enable and termination attributes are key here. When using a reverse proxy for SSL, these should be false and true, respectively.
    <ssl desc="SSL settings">
        <enable type="bool" default="true">false</enable> <!-- Set to false when using reverse proxy for SSL -->
        <termination type="bool" default="true">true</termination> <!-- Set to true when using reverse proxy for SSL -->
        <!-- cert_file_path, key_file_path, ca_file_path are ignored if enable=false -->
    </ssl>
    
  • <logging>: Configures log levels (trace, debug, info, warning, error, critical) and output locations.
    <logging>
        <level type="string" default="warning">info</level> <!-- e.g., change to info or debug -->
        <file enable="true">
            <property name="path" desc="Log file path.">[REMOVED]/loolwsd.log</property>
            <!-- Other log file properties -->
        </file>
        <console enable="false" /> <!-- Logs go to file/syslog, not usually console in container -->
    </logging>
    
  • <per_document>: Controls resource limits per document instance (loolkit).
    • <max_concurrency>: Max threads per document.
    • <idle_timeout_secs>: How long an inactive document stays loaded.
    • <inactive_timeout_secs>: How long an unused document (no viewers) stays loaded.
  • <per_view>: Controls limits per active view/connection.
  • <admin_console>: Configuration for the admin console (/loleaflet/dist/admin/admin.html), including authentication.
    <admin_console desc="Admin console settings">
        <enable type="bool" default="true">true</enable>
        <username desc="Admin username" type="string" default="admin">your_admin_user</username>
        <password desc="Admin password" type="string" default="admin">your_secure_password</password>
        <!-- ... other settings ... -->
    </admin_console>
    
  • <branding>: Allows basic customization like changing logos and welcome messages (requires preparing image files).

Modifying loolwsd.xml with Docker

To use a custom configuration file:

  1. Extract the Default: Copy the default file from a running container:
    sudo docker cp code:/etc/loolwsd/loolwsd.xml ./my_loolwsd.xml
    
  2. Edit: Modify my_loolwsd.xml using your text editor.
  3. Mount: Stop the container and restart it, mounting your custom file read-only:
    sudo docker stop code
    sudo docker rm code
    # Start command modified to mount the file
    sudo docker run -t -d -p 127.0.0.1:9980:9980 \
        -v $(pwd)/my_loolwsd.xml:/etc/loolwsd/loolwsd.xml:ro \
        # -e options are less critical now as settings are in the file, but domain can still be useful
        -e "domain=nextcloud\.example\.com" \
        # No need for extra_params if SSL settings are correct in the XML
        --restart always \
        --cap-add MKNOD \
        --name code \
        collabora/code:latest
    
    (Note: Using -v $(pwd)/my_loolwsd.xml... assumes my_loolwsd.xml is in your current directory. Use the full path if needed). The :ro makes the mount read-only inside the container, which is good practice for configuration files.

Changes in the mounted loolwsd.xml require a container restart (docker restart code) to take effect.

Workshop Customizing Basic Settings

This workshop demonstrates how to modify the loolwsd.xml configuration file to change the logging level and set admin console credentials.

Goal: Increase log verbosity for debugging and secure the admin console with a custom username and password.

Prerequisites:

  • A running Collabora Online CODE container managed via Docker (ideally behind the reverse proxy set up previously).
  • Sudo/root privileges.
  • Access to the server's command line.

Steps:

  1. Extract Default Configuration: If you don't already have it, copy the default loolwsd.xml from your running container:

    sudo docker cp code:/etc/loolwsd/loolwsd.xml ./my_loolwsd.xml
    # Verify it copied
    ls -l my_loolwsd.xml
    

  2. Edit my_loolwsd.xml: Open the copied file my_loolwsd.xml in a text editor (e.g., nano my_loolwsd.xml).

    • Change Log Level: Locate the <logging> section. Find the <level> tag. Change its content from warning (or whatever the default is) to info or debug. info provides more general operational details, while debug is very verbose. Let's use info for now.

      <logging>
          <level type="string" default="warning">info</level>
          <!-- ... rest of logging section ... -->
      </logging>
      

    • Set Admin Credentials: Locate the <admin_console> section. Find the <username> and <password> tags. Change their content to your desired secure credentials. Choose strong, unique values.

      <admin_console desc="Admin console settings">
          <enable type="bool" default="true">true</enable>
          <username desc="Admin username" type="string" default="admin">mycooladmin</username>
          <password desc="Admin password" type="string" default="admin">MySuperSecretP@ssw0rd!</password>
          <!-- ... rest of admin_console section ... -->
      </admin_console>
      

    • Verify SSL Settings (Crucial): While editing, double-check the <ssl> section. Ensure <enable> is false and <termination> is true, as required for our reverse proxy setup.

      <ssl desc="SSL settings">
          <enable type="bool" default="true">false</enable>
          <termination type="bool" default="true">true</termination>
          <!-- ... -->
      </ssl>
      

    • Verify Allowed Hosts (Crucial): Check the <storage><wopi><host> entries. Ensure the regex pattern correctly matches your Nextcloud domain(s). Using the domain environment variable often handles this, but if you rely solely on the XML, it must be correct here.

      <storage desc="Backend storage">
          <wopi desc="Allow/deny wopi storage..." allow="true">
              <host allow="true">nextcloud\.example\.com</host> <!-- Ensure this matches! -->
          </wopi>
      </storage>
      

    Save the changes and exit the editor.

  3. Stop and Remove the Old Container:

    sudo docker stop code
    sudo docker rm code
    

  4. Start New Container with Mounted Config: Use the docker run command, adding the -v option to mount your modified my_loolwsd.xml. Make sure the path to my_loolwsd.xml is correct (using $(pwd) works if it's in the current directory).

    # Assuming my_loolwsd.xml is in the current directory
    sudo docker run -t -d -p 127.0.0.1:9980:9980 \
        -v $(pwd)/my_loolwsd.xml:/etc/loolwsd/loolwsd.xml:ro \
        # You might still include -e "domain=..." as a fallback or for clarity
        -e "domain=nextcloud\.example\.com" \
        # No need for extra_params for SSL if set in XML
        --restart always \
        --cap-add MKNOD \
        --name code \
        collabora/code:latest
    
  5. Verify Changes:

    • Check Logs: Wait a minute for the container to start fully, then check the logs:
      sudo docker logs code
      
      You should now see more detailed logs (INFO level) compared to the default warning level. Look for lines explicitly marked [ loolwsd ] INFO ....
    • Test Admin Console: Open your browser and navigate to the admin console URL via your reverse proxy: https://collabora.example.com/loleaflet/dist/admin/admin.html. You should now be prompted for a username and password. Enter the credentials you set in my_loolwsd.xml (mycooladmin and MySuperSecretP@ssw0rd! in our example). You should gain access to the admin dashboard.
    • Test Document Editing: Ensure document editing in Nextcloud still works correctly. This confirms that the core functionality wasn't broken by the configuration changes.

Outcome: You have successfully customized Collabora Online's behavior using the loolwsd.xml file, specifically changing the log level and securing the admin console. You now have a method for applying more fine-grained configuration adjustments.

3. Advanced Level

This section delves into scaling your Collabora Online deployment for more users, ensuring high availability, implementing monitoring, and tackling common troubleshooting scenarios. These topics are crucial for running a reliable service for larger groups or organizations.

Scaling Collabora Online

The single CODE container setup, while simple, has limitations. As the number of concurrent documents and users grows, a single instance will become a bottleneck, primarily limited by CPU and RAM. Scaling involves distributing the load across multiple Collabora Online instances.

Understanding Limitations

  • Vertical Scaling: Increasing the CPU cores and RAM allocated to the single CODE server/container. This is the simplest approach but has physical/virtual limits and becomes expensive.
  • Horizontal Scaling: Adding more identical CODE instances (running on the same or different physical/virtual machines) and distributing incoming connections among them using a load balancer. This is generally more flexible and cost-effective for significant growth.

Collabora Online itself is largely stateless regarding user sessions (session information is managed, but document data resides in the WOPI host like Nextcloud). This makes it well-suited for horizontal scaling.

Horizontal Scaling Concepts

The core idea is:

  1. Deploy Multiple Instances: Set up two or more identical CODE containers/servers. They should have the same configuration (loolwsd.xml or equivalent environment variables), particularly the allowed WOPI hosts (domain=...) and SSL settings (expecting termination at the proxy/balancer). Each instance will listen on its own internal IP/port (e.g., 192.168.1.10:9980, 192.168.1.11:9980, or on the same machine 127.0.0.1:9980, 127.0.0.1:9981).
  2. Introduce a Load Balancer: Place a load balancer in front of the CODE instances. This load balancer becomes the single entry point that your frontend (Nextcloud) and reverse proxy (if separate) point to. Its job is to distribute incoming connections across the available CODE instances.
  3. Configure Integration: Update your Nextcloud/ownCloud settings and your main reverse proxy (if the load balancer isn't also handling external SSL/proxying) to point to the load balancer's address instead of a single CODE instance.

Load Balancing Strategies

Load balancers use different algorithms to decide which backend server gets the next request:

  • Round Robin: Distributes connections sequentially to each server in the pool (Server1, Server2, Server3, Server1, ...). Simple but doesn't account for server load.
  • Least Connections: Sends the next connection to the server currently handling the fewest active connections. Generally better for long-lived connections like Collabora's WebSockets, as it balances based on actual load.
  • IP Hash: Assigns a client to a specific server based on their IP address. This ensures a user consistently hits the same backend, which can sometimes be helpful but might lead to uneven load distribution. Less ideal for Collabora unless specific session persistence issues arise (which are uncommon).
  • Weighted Variations: Allows assigning weights to servers (e.g., send twice as much traffic to a more powerful server).

For Collabora, Least Connections is often the preferred strategy.

Setting up Multiple CODE Instances

Using Docker, you can easily launch multiple instances on the same host by mapping them to different host ports:

  • Instance 1 (already running): docker run ... -p 127.0.0.1:9980:9980 ... --name code1 ...
  • Instance 2: docker run ... -p 127.0.0.1:9981:9980 ... --name code2 ... (Note the host port 9981)
  • Instance 3: docker run ... -p 127.0.0.1:9982:9980 ... --name code3 ...

If running on different hosts, each would typically listen on 127.0.0.1:9980 (or 0.0.0.0:9980 if the load balancer is on a separate machine) within its own environment, and the load balancer would use the distinct host IPs (e.g., 192.168.1.10:9980, 192.168.1.11:9980).

Using a Dedicated Load Balancer (HAProxy/Nginx)

Both Nginx and dedicated load balancers like HAProxy can perform this role.

  • Nginx as Load Balancer: Nginx can load balance using an upstream block.

    # Define the pool of backend Collabora servers
    upstream collabora_backends {
        # least_conn; # Use Least Connections algorithm
        ip_hash; # Use IP Hash for session persistence if needed
        server 127.0.0.1:9980; # Instance 1
        server 127.0.0.1:9981; # Instance 2
        # Add more servers as needed
    }
    
    server {
        listen 443 ssl http2;
        server_name collabora.example.com; # Public facing domain
    
        # SSL configuration... (as before)
    
        # Proxy requests to the upstream group
        location / {
            proxy_pass http://collabora_backends; # Pass to the upstream group
    
            # WebSocket headers NEEDED here too!
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_read_timeout 3600s;
            proxy_buffering off; # Recommended for WebSockets
        }
    }
    
    In this setup, Nginx acts as both the SSL termination point/reverse proxy and the load balancer. Requests to collabora.example.com are distributed to the servers defined in the collabora_backends upstream block.

  • HAProxy: A popular, high-performance, dedicated load balancer. Configuration (usually in /etc/haproxy/haproxy.cfg) might look like:

    frontend collabora_frontend
        bind *:443 ssl crt /etc/letsencrypt/live/collabora.example.com/combined.pem # Path to combined cert+key
        mode http
        option httplog
        # Redirect HTTP to HTTPS if needed
        # redirect scheme https if !{ ssl_fc }
        default_backend collabora_backend
    
    backend collabora_backend
        mode http
        balance leastconn # Use Least Connections
        # Use cookie for persistence if needed, but often not required for Collabora
        # cookie SERVERID insert indirect nocache
        option forwardfor # Pass client IP
        # Health checks to ensure servers are up
        option httpchk GET /lool/healthz HTTP/1.1\r\nHost:\ collabora.example.com
        http-check expect status 200
        server code1 127.0.0.1:9980 check # Instance 1
        server code2 127.0.0.1:9981 check # Instance 2
        # Add more servers
        # Define timeouts
        timeout connect 5s
        timeout server 3600s # Long timeout for editing
        timeout client 3600s
    
    HAProxy handles SSL and load balancing, forwarding traffic to the backend CODE instances. Note the use of health checks (check and option httpchk) to automatically remove unresponsive instances from the pool.

Workshop Setting up a Load-Balanced Collabora Cluster

This workshop guides you through setting up two CODE instances on the same host and using Nginx to load balance traffic between them.

Goal: Create a small, horizontally scaled Collabora cluster load balanced by Nginx.

Prerequisites:

  • A working single CODE instance behind an Nginx reverse proxy with SSL (as per the Intermediate workshop).
  • Nginx installed and configured for the single instance.
  • Docker installed.
  • Sudo/root privileges.
  • Enough server resources (CPU/RAM) to comfortably run two CODE instances plus Nginx and the OS. (~4+ cores, 4-6GB+ RAM free for Collabora).

Steps:

  1. Prepare Configuration (If Using XML): If you are using a custom my_loolwsd.xml, ensure it's suitable for both instances (especially allowed hosts and SSL settings: enable=false, termination=true). No instance-specific changes should be needed in the XML itself.

  2. Stop Existing Single Instance: Stop the current code container. We'll rename it for clarity.

    sudo docker stop code
    sudo docker rm code
    

  3. Launch First CODE Instance (code1): Launch the first instance, naming it code1 and ensuring it listens on 127.0.0.1:9980. Use either environment variables or your mounted XML file for configuration.

    Using environment variables:

    sudo docker run -t -d -p 127.0.0.1:9980:9980 \
        -e "domain=nextcloud\.example\.com" \
        -e "extra_params=--o:ssl.enable=false --o:ssl.termination=true" \
        --restart always \
        --cap-add MKNOD \
        --name code1 \
        collabora/code:latest
    
    Using mounted XML:
    sudo docker run -t -d -p 127.0.0.1:9980:9980 \
        -v $(pwd)/my_loolwsd.xml:/etc/loolwsd/loolwsd.xml:ro \
        -e "domain=nextcloud\.example\.com" \
        --restart always \
        --cap-add MKNOD \
        --name code1 \
        collabora/code:latest
    

  4. Launch Second CODE Instance (code2): Launch the second instance similarly, but name it code2 and map it to a different host port, e.g., 127.0.0.1:9981.

    Using environment variables:

    sudo docker run -t -d -p 127.0.0.1:9981:9980 \
        -e "domain=nextcloud\.example\.com" \
        -e "extra_params=--o:ssl.enable=false --o:ssl.termination=true" \
        --restart always \
        --cap-add MKNOD \
        --name code2 \
        collabora/code:latest
    
    Using mounted XML:
    sudo docker run -t -d -p 127.0.0.1:9981:9980 \
        -v $(pwd)/my_loolwsd.xml:/etc/loolwsd/loolwsd.xml:ro \
        -e "domain=nextcloud\.example\.com" \
        --restart always \
        --cap-add MKNOD \
        --name code2 \
        collabora/code:latest
    

  5. Verify Both Instances Running:

    sudo docker ps
    
    You should see both code1 (mapping 127.0.0.1:9980->9980/tcp) and code2 (mapping 127.0.0.1:9981->9980/tcp) listed and running.

  6. Configure Nginx for Load Balancing: Edit your Nginx site configuration file for collabora.example.com.

    • Add upstream block: Before the server block, define the upstream group:
      upstream collabora_backends {
          least_conn; # Use Least Connections balancing
          server 127.0.0.1:9980; # Instance 1
          server 127.0.0.1:9981; # Instance 2
      }
      
    • Modify proxy_pass: Inside the server { ... } block, find all location blocks that currently have proxy_pass http://127.0.0.1:9980;. Change the target to http://collabora_backends;. This includes locations /, /loleaflet, /hosting/discovery, /lool, /lool/adminws.

      Example change for /lool:

      location ^~ /lool {
          # proxy_pass http://127.0.0.1:9980; # OLD line
          proxy_pass http://collabora_backends; # NEW line
      
          # Keep WebSocket and other headers!
          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection "upgrade";
          proxy_set_header Host $host;
          # ... other headers if you have them ...
          proxy_read_timeout 3600s;
          proxy_buffering off;
      }
      
      Apply this change to all proxy_pass directives pointing to the old single instance.

  7. Test Nginx Configuration and Reload:

    sudo nginx -t
    sudo systemctl reload nginx
    

  8. Test Load Balancing and Failover:

    • Basic Functionality: Open Nextcloud and edit a document. It should work seamlessly. You don't directly see which backend is used, but Nginx is now distributing the requests.
    • Monitor Connections (Optional): Access the admin console https://collabora.example.com/loleaflet/dist/admin/admin.html (if you secured it, log in). Navigate to the "Analytics" or "Monitoring" section. Open a few documents. You might see connections being distributed across both instances listed (if the admin console provides such detail, or check server stats).
    • Simulate Failure: Stop one of the containers:
      sudo docker stop code2
      
    • Test Again: Immediately try opening a new document or continue editing an existing one in Nextcloud. It should still work (perhaps after a slight delay for Nginx to detect the stopped backend if it doesn't have active health checks configured in the free version). Nginx should redirect traffic to the remaining active instance (code1).
    • Restore: Start the stopped container again:
      sudo docker start code2
      
    • Test Again: Functionality should remain normal. Nginx will reintegrate code2 into the load balancing pool.

Outcome: You have successfully set up a basic horizontally scaled Collabora Online cluster with two backend instances and configured Nginx to load balance traffic between them using the least_conn method. You've also demonstrated basic fault tolerance – the service remains available even if one backend instance fails.

High Availability Considerations

Load balancing provides scalability and some resilience, but true High Availability (HA) requires eliminating single points of failure throughout the stack.

  • Load Balancer Redundancy: If your Nginx/HAProxy load balancer itself fails, the entire service goes down. For HA, you need redundant load balancers. Common techniques include:
    • Keepalived + VRRP: Two identical load balancers share a Virtual IP address. Keepalived monitors the health of the primary; if it fails, the secondary takes over the Virtual IP.
    • DNS Failover: Using DNS services that monitor health and automatically update DNS records to point to a secondary load balancer IP (often slower failover).
    • Cloud Provider Load Balancers: Cloud platforms (AWS ELB, GCP Load Balancer, Azure Load Balancer) offer managed HA load balancing services.
  • Collabora Instance Redundancy: Already addressed by having multiple instances in the load balancer pool. Ensure instances are spread across different physical hosts or availability zones if possible.
  • Frontend (Nextcloud/ownCloud) Redundancy: Your file host also needs to be highly available (clustered web servers, redundant database, distributed storage like NFS/GlusterFS/Ceph). This is outside the scope of Collabora setup but critical for overall service HA.
  • Network Redundancy: Redundant network switches, routers, and internet connections.
  • Monitoring and Alerting: Continuous monitoring of all components (load balancers, CODE instances, frontend servers, network) is crucial to detect failures quickly. Alerting systems (e.g., Prometheus + Alertmanager, Nagios, Zabbix) should notify administrators of issues.

Implementing full HA is complex and depends heavily on the specific infrastructure and requirements.

Workshop Implementing Basic Monitoring

This workshop focuses on setting up simple monitoring for your load-balanced Collabora setup using built-in tools and a basic external health check script.

Goal: Monitor the status of individual CODE instances and the overall service availability.

Prerequisites:

  • Load-balanced Collabora setup (as per the previous workshop).
  • Access to the server hosting Nginx and the CODE containers.
  • Admin console access for Collabora (https://collabora.example.com/loleaflet/dist/admin/admin.html) configured and accessible.
  • curl command-line tool installed.

Steps:

  1. Using the Admin Console:

    • Navigate to https://collabora.example.com/loleaflet/dist/admin/admin.html and log in.
    • Explore the available tabs/sections. Look for:
      • Active Documents: A list of currently open documents.
      • Active Users: Number of connected users.
      • Server Stats: Information about memory usage, CPU load, and potentially metrics per backend instance if the load balancer passes identifying information (less common with basic Nginx setup).
    • This provides a real-time snapshot but isn't persistent or automated alerting. Regularly checking this dashboard manually can help spot issues.
  2. Basic External Health Check Script: We can create a simple script that checks the /lool/healthz endpoint of each backend instance directly, bypassing the load balancer for individual checks, and also checks the main public URL.

    • Create the Script: Create a file named check_collabora.sh:
      nano check_collabora.sh
      
    • Add Script Content: Paste the following script, adjusting URLs and ports:

      #!/bin/bash
      
      # --- Configuration ---
      INSTANCE1_URL="http://127.0.0.1:9980/lool/healthz"
      INSTANCE2_URL="http://127.0.0.1:9981/lool/healthz"
      PUBLIC_URL="https://collabora.example.com/lool/healthz" # Check via LB/Proxy
      LOG_FILE="/var/log/collabora_health.log"
      # --- End Configuration ---
      
      TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
      STATUS_OK="ok"
      OVERALL_STATUS="OK"
      
      echo "[$TIMESTAMP] Starting health check..." >> $LOG_FILE
      
      # Check Instance 1
      echo -n "Checking Instance 1 ($INSTANCE1_URL)... " >> $LOG_FILE
      RESPONSE1=$(curl -s -m 5 $INSTANCE1_URL) # -s silent, -m timeout 5s
      if [ "$RESPONSE1" == "$STATUS_OK" ]; then
          echo "OK" >> $LOG_FILE
      else
          echo "FAILED (Response: '$RESPONSE1')" >> $LOG_FILE
          OVERALL_STATUS="FAILED"
      fi
      
      # Check Instance 2
      echo -n "Checking Instance 2 ($INSTANCE2_URL)... " >> $LOG_FILE
      RESPONSE2=$(curl -s -m 5 $INSTANCE2_URL)
      if [ "$RESPONSE2" == "$STATUS_OK" ]; then
          echo "OK" >> $LOG_FILE
      else
          echo "FAILED (Response: '$RESPONSE2')" >> $LOG_FILE
          OVERALL_STATUS="FAILED"
      fi
      
      # Check Public URL (via Load Balancer/Proxy)
      echo -n "Checking Public URL ($PUBLIC_URL)... " >> $LOG_FILE
      # Use -k if using self-signed cert for internal checks, but public should be valid
      RESPONSE_PUBLIC=$(curl -s -m 10 $PUBLIC_URL)
      if [ "$RESPONSE_PUBLIC" == "$STATUS_OK" ]; then
          echo "OK" >> $LOG_FILE
      else
          echo "FAILED (Response: '$RESPONSE_PUBLIC')" >> $LOG_FILE
          OVERALL_STATUS="FAILED"
      fi
      
      echo "[$TIMESTAMP] Overall Status: $OVERALL_STATUS" >> $LOG_FILE
      echo "--------------------------------------" >> $LOG_FILE
      
      # Optional: Add alerting logic here if status is FAILED
      # e.g., send email, trigger webhook, etc.
      if [ "$OVERALL_STATUS" == "FAILED" ]; then
         echo "ALERT: Collabora health check failed!"
         # mail -s "Collabora Health Alert" admin@example.com < $LOG_FILE
      fi
      
      exit 0
      
    • Make Executable:

      chmod +x check_collabora.sh
      

    • Initial Test Run: Execute the script manually:

      sudo ./check_collabora.sh
      
      Check the output and the contents of /var/log/collabora_health.log (you might need sudo tail -n 10 /var/log/collabora_health.log). It should report "OK" for all checks if everything is running.

  3. Schedule Regular Checks (Cron Job): Automate the script to run periodically using cron.

    • Edit Crontab:
      sudo crontab -e
      
      (Choose an editor if prompted).
    • Add Cron Job: Add a line to run the script every 5 minutes. Adjust the path /path/to/check_collabora.sh to the actual location of your script.
      */5 * * * * /path/to/check_collabora.sh
      
    • Save and exit the editor. Cron will now execute your health check script every 5 minutes.
  4. Simulate Failure and Check Logs:

    • Stop one instance: sudo docker stop code2
    • Wait for the next cron job execution (up to 5 minutes).
    • Check the log file: sudo tail /var/log/collabora_health.log
    • You should now see entries where Instance 2 reports "FAILED", and the Overall Status is "FAILED". If you added alerting, that should also trigger. The Public URL should still report "OK" as code1 is handling the load.
    • Start the instance again: sudo docker start code2
    • After the next check, the logs should return to showing "OK" for all components.

Outcome: You have implemented basic monitoring using the built-in admin console for real-time checks and an automated script that checks the health of individual instances and the public endpoint, logging the results. This provides early warnings of potential issues. For production, integrate this with a more robust monitoring system like Prometheus/Grafana or Zabbix.

Troubleshooting Common Issues

Even with careful setup, issues can arise. Here’s a breakdown of common problems and how to diagnose them.

Connection Problems ("Unable to connect", "Service Unavailable")

  • Symptom: Nextcloud shows an error trying to load Collabora; accessing the Collabora URL directly fails.
  • Diagnosis:
    1. Check CODE Container(s): Are they running? (sudo docker ps). Check logs (sudo docker logs code1, sudo docker logs code2) for startup errors or crashes.
    2. Check Reverse Proxy/Load Balancer: Is Nginx/HAProxy running? (sudo systemctl status nginx). Check its error logs (/var/log/nginx/error.log or equivalent). Look for errors related to connecting to the upstream (Collabora backend).
    3. Firewall: Is port 443 (and 80 for redirects) open on the server firewall? Is the reverse proxy allowed to connect to the backend ports (9980, 9981) on 127.0.0.1 or the relevant internal IPs?
    4. Network Path: Can the Nextcloud server resolve and reach the Collabora URL? From the Nextcloud server, try: curl -v https://collabora.example.com/hosting/discovery. Check for DNS issues or network blocks.
    5. Nginx/Apache Config: Double-check the proxy_pass directives and upstream server definitions. Ensure ports and IPs are correct. Reload the service after changes (sudo systemctl reload nginx).

"Unauthorized WOPI Host" Error

  • Symptom: Collabora loads partially or shows an error specifically mentioning unauthorized host or domain.
  • Diagnosis:
    1. Check CODE Logs: Look in sudo docker logs code1 (and code2) for lines like WRN WOPI::CheckFileInfo Failed. Error: Unauthorized WOPI host... or similar permission errors. The log should mention the domain that tried to connect.
    2. Verify domain Setting: Ensure the domain= environment variable used when starting the CODE containers (or the <host> entries in loolwsd.xml) contains a correct regular expression matching the domain name as Nextcloud knows it. If Nextcloud is accessed via https://cloud.mydomain.internal, then the domain= variable needs to include cloud\.mydomain\.internal. Remember to escape dots (.) and use | to separate multiple domains if needed (e.g., domain=nextcloud\.example\.com|cloud\.mydomain\.internal).
    3. Restart CODE Containers: If you changed the domain environment variable or the loolwsd.xml file, you must restart the CODE containers (sudo docker restart code1 code2).

Performance Bottlenecks (Slow Loading, Unresponsive Editing)

  • Symptom: Documents take a long time to load; typing lags; Collabora feels sluggish.
  • Diagnosis:
    1. Server Resources: Check CPU, RAM, and Disk I/O usage on the server(s) hosting the CODE containers while the issue is occurring. Use tools like htop, vmstat, iotop. Are CPU cores maxed out? Is the system swapping heavily (low RAM)?
    2. Container Limits: Are the Docker containers themselves resource-limited (e.g., via docker-compose deploy limits or cgroup settings)?
    3. Network Latency: Check network latency between the user -> Nextcloud -> Collabora -> Nextcloud. High latency can impact responsiveness. Use ping and traceroute.
    4. Document Complexity: Is the issue specific to very large or complex documents? Test with a simple, blank document.
    5. Scale Up/Out: If resources are the bottleneck, you may need to vertically scale (more RAM/CPU) or horizontally scale (add more CODE instances to the load balancer pool).
    6. Check loolwsd.xml Limits: Review <per_document> settings like max_concurrency in loolwsd.xml. Unlikely to be the issue unless heavily customized.

SSL/TLS Errors

  • Symptom: Browser shows certificate warnings; connection fails with SSL errors.
  • Diagnosis:
    1. Certificate Validity: Check the expiry date and chain of the SSL certificate served by your reverse proxy (Nginx/HAProxy). Use browser developer tools or online SSL checkers (e.g., SSL Labs). Has the certificate expired? Is the intermediate chain missing?
    2. Mixed Content: Ensure Nextcloud and Collabora are both accessed via HTTPS. Check browser developer console for "mixed content" warnings.
    3. Reverse Proxy SSL Config: Review the Nginx/Apache/HAProxy SSL configuration (ssl_certificate, ssl_certificate_key, protocols, ciphers). Ensure it's correct and using strong, modern settings.
    4. CODE Internal SSL: Verify that internal SSL is disabled in CODE (ssl.enable=false, ssl.termination=true) if the reverse proxy handles termination. Check loolwsd.xml or extra_params in the docker run command.

Log Analysis Techniques

  • Collabora Logs (docker logs codeX): Set log level to info or debug in loolwsd.xml for more detail during troubleshooting. Look for ERR (Error) or WRN (Warning) messages. Correlate timestamps with user actions. Search for specific document IDs or WOPI URLs.
  • Reverse Proxy Logs (/var/log/nginx/access.log, /var/log/nginx/error.log): Check access.log for requests to Collabora URLs (status codes 200 OK, 4xx errors, 5xx errors). Check error.log for connection issues to backends, SSL problems, or configuration errors.
  • Nextcloud Logs (data/nextcloud.log inside Nextcloud data directory): Look for errors related to the "Nextcloud Office" app or WOPI client functionality around the time of the issue. Set Nextcloud's log level higher if needed (Admin -> Logging).
  • Browser Developer Tools (F12): Check the "Console" tab for JavaScript errors or failed resource loading. Check the "Network" tab to see requests to Collabora, their status codes, and timings. Look for failed WebSocket connections.

Workshop Debugging an Integration Problem

This workshop simulates a common issue – Nextcloud failing to connect to Collabora – and walks through the debugging process.

Goal: Diagnose and fix a simulated "Unable to connect" error between Nextcloud and Collabora.

Prerequisites:

  • Working load-balanced Collabora setup behind Nginx.
  • Access to Nextcloud admin, server command line (for Docker, Nginx logs).
  • Ability to stop/start services/containers.

Scenario: Users report that clicking on documents in Nextcloud results in an error message like "Failed to connect to Collabora Online server" or similar, instead of loading the editor.

Debugging Steps:

  1. Reproduce and Gather Info:

    • Try opening a document yourself in Nextcloud. Note the exact error message displayed.
    • Note the timestamp when the error occurred.
  2. Check Nextcloud Admin:

    • Go to Nextcloud -> Administration settings -> Nextcloud Office.
    • Verify the Collabora URL (https://collabora.example.com) is correct.
    • Click "Save". Does it show "Collabora Online server is reachable." or an error? If it shows an error here, the problem lies in the basic connectivity or Collabora/proxy service status.
  3. Check Service Status:

    • CODE Containers: sudo docker ps. Are code1 and code2 running?
    • Nginx: sudo systemctl status nginx. Is it active (running)?
  4. Simulate the Problem (Choose ONE):

    • Option A: Stop Nginx: sudo systemctl stop nginx
    • Option B: Stop CODE Containers: sudo docker stop code1 code2
    • Option C: Introduce Firewall Block (If possible/applicable): Block traffic to 127.0.0.1:9980 and 127.0.0.1:9981 from Nginx (less easy to simulate quickly).
    • Option D: Misconfigure Nginx proxy_pass: Edit the Nginx config, change proxy_pass http://collabora_backends; to something incorrect like proxy_pass http://localhost:12345;, then run sudo nginx -t && sudo systemctl reload nginx.
  5. Diagnose (Following the Scenario Above):

    • Check Nginx Logs: sudo tail -n 50 /var/log/nginx/error.log

      • If you stopped Nginx (A), this log won't update, but attempts to connect will fail immediately.
      • If you stopped CODE (B) or misconfigured proxy_pass (D), you'll likely see errors like [error] connect() failed (111: Connection refused) while connecting to upstream or (111: Connection refused) while connecting to upstream, client: ..., server: collabora.example.com, request: "GET /lool/... ", upstream: "http://127.0.0.1:9980/lool/...". This clearly points to Nginx being unable to reach the defined backend(s).
      • If a firewall blocked (C), similar "Connection refused" or potentially "Connection timed out" errors might appear.
    • Check CODE Logs: sudo docker logs code1 and sudo docker logs code2

      • If CODE containers were stopped (B), these logs won't show new entries related to the connection attempt.
      • If Nginx couldn't reach them (C, D), the CODE logs would show no sign of the incoming connection attempt from Nginx.
    • Check Connectivity from Nginx Host:

      • Try curling the backends directly from the Nginx server:
        curl http://127.0.0.1:9980/lool/healthz
        curl http://127.0.0.1:9981/lool/healthz
        
      • If CODE is stopped (B) or firewalled (C), these will fail ("Connection refused" or timeout).
      • If only Nginx is misconfigured (D), these should still return "ok" (proving CODE itself is fine).
  6. Identify the Cause: Based on the log messages and connectivity tests:

    • Nginx errors "Connection refused" + curl to backend fails => CODE containers are stopped/unreachable.
    • Nginx errors "Connection refused" + curl to backend succeeds => Nginx configuration (proxy_pass, upstream) is likely wrong.
    • No Nginx errors, but connection fails => Nginx might be stopped, or a firewall before Nginx is blocking, or DNS is wrong for collabora.example.com.
    • Nextcloud admin check fails => Confirms basic connectivity issue.
  7. Fix the Simulated Problem:

    • If Nginx stopped (A): sudo systemctl start nginx
    • If CODE stopped (B): sudo docker start code1 code2
    • If Firewall (C): Remove the blocking rule.
    • If Nginx config bad (D): Correct the proxy_pass directive, run sudo nginx -t && sudo systemctl reload nginx.
  8. Verify Fix:

    • Retry opening a document in Nextcloud.
    • Re-check the connection in Nextcloud Admin -> Nextcloud Office. It should now succeed.
    • Check Nginx access.log and error.log – errors should stop, and successful requests (200 OK) should appear.

Outcome: You have walked through a methodical troubleshooting process for a common integration failure, using logs and direct connectivity checks to pinpoint the cause (whether it's the reverse proxy, the backend service, or the connection between them) and verify the fix. This approach can be adapted to diagnose various connectivity and configuration issues.

Conclusion

Congratulations on completing this guide to self-hosting Collabora Online! You have journeyed from understanding the fundamental concepts and performing a basic Docker installation to implementing a secure, load-balanced, and monitored deployment suitable for more demanding environments.

Recap of Key Learnings:

  • Core Concepts: You learned about Collabora Online's architecture (CODE, loolwsd, loolforkit), its role as a WOPI host, and the importance of integrating it with a frontend like Nextcloud.
  • Basic Setup: You successfully deployed CODE using Docker and performed an initial integration test.
  • Secure Access: You mastered setting up a reverse proxy (Nginx/Apache) to handle SSL/TLS termination using Let's Encrypt, significantly enhancing security and accessibility.
  • Configuration: You explored the loolwsd.xml file and learned how to customize settings like logging and admin access.
  • Scaling & HA: You implemented horizontal scaling using multiple CODE instances and a load balancer (Nginx) and understood the broader considerations for High Availability.
  • Monitoring & Troubleshooting: You set up basic monitoring and practiced a systematic approach to diagnosing common integration problems using logs and diagnostic tools.

By self-hosting Collabora Online, you gain full control over your collaborative document editing environment, ensuring data privacy and sovereignty. While it requires ongoing effort for maintenance and updates, the benefits of a tailored, private office suite backend are substantial.

Next Steps and Further Exploration:

  • Deeper loolwsd.xml Customization: Explore advanced options for branding, font management, language settings, and fine-tuning resource limits.
  • Advanced Monitoring: Integrate your Collabora setup with robust monitoring solutions like Prometheus, Grafana, Zabbix, or the ELK stack for comprehensive dashboards and alerting.
  • Alternative Integrations: Experiment with integrating Collabora Online with other WOPI-compatible frontends (ownCloud, Seafile, Moodle, etc.).
  • Security Hardening: Implement stricter firewall rules, intrusion detection systems, and regular security audits. Explore advanced Nginx/Apache security configurations.
  • Backup Strategy: While Collabora itself is largely stateless, ensure you have robust backup strategies for your configuration files, SSL certificates, and critically, the data stored in your frontend (Nextcloud/ownCloud).
  • Performance Tuning: Analyze performance under heavy load using profiling tools and optimize server/network configurations.

Remember that the open-source community around Collabora Online and related projects is a valuable resource. Consult official documentation, forums, and community channels when you encounter challenges or want to learn more.

Self-hosting is a rewarding journey that empowers you with control and knowledge. Keep learning, stay updated with security patches, and enjoy the benefits of your private, collaborative office suite!