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


Office Suite Backend OnlyOffice Docs

Introduction OnlyOffice Docs

Welcome to this comprehensive guide on self-hosting OnlyOffice Docs, the powerful backend document server that provides real-time collaborative editing capabilities for text documents, spreadsheets, and presentations. Unlike traditional office suites that run locally on your computer, OnlyOffice Docs operates as a web service. It doesn't provide a user-facing file management system itself; instead, it integrates seamlessly with various frontend platforms often referred to as "sync & share" solutions or content management systems like Nextcloud, ownCloud, Alfresco, Confluence, or OnlyOffice's own frontend, OnlyOffice Workspace (formerly Community Server/Group).

What is OnlyOffice Docs?

OnlyOffice Docs (previously known as OnlyOffice Document Server) is the engine that powers the editing experience. When you open a document from an integrated platform (like Nextcloud), the frontend platform communicates with the OnlyOffice Docs server, passing the document and necessary authentication information. OnlyOffice Docs then loads the document into its appropriate editor (Text Document, Spreadsheet, or Presentation) within your web browser. All editing operations and collaboration happen via this Docs server, which then saves the changes back to your original storage platform.

Key Components:

  1. Document Editors: The core web-based editors for DOCX, XLSX, and PPTX files, offering high compatibility with Microsoft Office formats and a familiar tabbed interface.
  2. Document Server: The backend component that manages document loading, processing, conversion, and real-time collaboration communication between users.
  3. Supporting Services: Includes services for document conversion, thumbnail generation, font rendering, and spell checking.

Why Self-Host OnlyOffice Docs?

Self-hosting OnlyOffice Docs offers several significant advantages over relying on third-party cloud services or desktop applications:

  1. Data Sovereignty and Privacy: Your documents remain entirely within your infrastructure. You control where your data is stored and processed, ensuring compliance with privacy regulations (like GDPR) and maintaining confidentiality. No third party has access unless you explicitly grant it.
  2. Cost-Effectiveness: While commercial versions exist, the community edition of OnlyOffice Docs is free to use (with certain limitations, like the number of simultaneous connections, which was 20 at the time of writing, but check the official license). This can be significantly cheaper than per-user subscription fees for cloud-based office suites, especially for larger organizations or communities.
  3. Customization and Integration: Self-hosting allows for deeper customization of the editing interface (e.g., branding) and fine-tuned integration with your existing self-hosted platforms. You control the update cycle and configuration settings.
  4. Offline Access (within your network): If hosted on a local network, users within that network can access and collaborate on documents even if the external internet connection is down (provided the frontend platform is also accessible locally).
  5. Learning and Skill Development: Setting up and managing a service like OnlyOffice Docs provides valuable experience in server administration, Docker, networking, security, and application integration.

Scope of this Guide:

This guide focuses specifically on the self-hosting of the OnlyOffice Docs server (the backend). We will cover installation, configuration, integration, scaling, security, and troubleshooting. We will primarily use Docker for deployment, as it's the officially recommended and most straightforward method for getting started. We assume you have a server (physical or virtual) running a compatible Linux distribution (like Ubuntu, Debian, CentOS) and basic familiarity with the command line. We will explore integrations primarily using Nextcloud as a common example frontend, but the principles apply to other compatible platforms.

Let's embark on the journey of deploying and managing your own powerful, private, and collaborative online office suite backend!

Basic

This section covers the fundamental knowledge and steps required to get your first OnlyOffice Docs instance up and running using Docker.

1. Understanding OnlyOffice Docs Architecture

Before diving into installation, it's crucial to understand the components of OnlyOffice Docs and how they interact. This knowledge will help you make informed decisions during setup and troubleshooting later.

Core Components:

  1. Document Editors: These are the JavaScript-based applications that run in the user's web browser. They provide the user interface for viewing and editing documents, spreadsheets, and presentations. They communicate heavily with the Document Server component.
  2. Document Server Core (DocService): This is the central backend service. It handles requests from the frontend platform (like Nextcloud) and the Document Editors. Its primary responsibilities include:
    • Receiving documents from the frontend platform.
    • Managing collaborative editing sessions (tracking changes, broadcasting updates to connected users in real-time).
    • Processing and saving document changes back to the frontend platform.
    • Coordinating tasks with other supporting services (like conversion).
  3. Conversion Service (Converter): Responsible for converting documents between various formats (e.g., DOC to DOCX, ODT to DOCX, generating PDFs or thumbnails). OnlyOffice Docs internally works primarily with the OOXML formats (DOCX, XLSX, PPTX), so conversion is essential for compatibility.
  4. Database (PostgreSQL & Redis):
    • PostgreSQL: Stores information necessary for the server's operation, such as file locks and cached data related to document compilation.
    • Redis: An in-memory data structure store, used for caching session information, managing message queues for collaborative editing updates, and improving performance by reducing database load.
  5. Messaging Queue (RabbitMQ): Facilitates asynchronous communication between different internal services of OnlyOffice Docs. This helps decouple services and ensures reliable task processing, especially for operations like conversion or broadcasting updates during collaboration.
  6. Nginx: Acts as an internal reverse proxy within the OnlyOffice Docs container/installation. It serves the static files for the editors (HTML, CSS, JavaScript) and routes API requests to the appropriate backend services (DocService, Converter, etc.). This is separate from any external reverse proxy you might set up for HTTPS.

Interaction Flow (Example with Nextcloud):

  1. User Action: A user clicks on a .docx file within their Nextcloud web interface.
  2. Nextcloud Request: The Nextcloud server, using its configured OnlyOffice Connector App, sends a request to the OnlyOffice Docs server URL. This request includes:
    • Information about the document (URL to download it from Nextcloud).
    • User information (ID, name for collaboration).
    • Permissions (read-only, edit).
    • A security token (JWT - JSON Web Token) signed with a secret key shared between Nextcloud and OnlyOffice Docs.
  3. OnlyOffice Docs Verification: The Docs server validates the JWT using the shared secret key. If valid, it proceeds.
  4. Document Fetch: The Docs server uses the provided URL to download the document directly from Nextcloud.
  5. Editor Loading: The Docs server prepares an editing session and instructs the user's browser to load the appropriate Document Editor (Text Document editor in this case). Static editor files (HTML, JS, CSS) are served to the browser.
  6. Collaboration: As the user types, the browser sends changes to the Docs server (DocService). The Docs server processes these changes and broadcasts them to any other users collaborating on the same document in real-time via WebSockets or similar technology managed through Redis and RabbitMQ.
  7. Saving: When the last user closes the document (or periodically), the Docs server compiles the final version of the document and sends a request back to a specific callback URL on the Nextcloud server, instructing it to save the updated file. Nextcloud replaces the old version with the new one provided by OnlyOffice Docs.

The Role of JWT (JSON Web Token):

JWT is critical for securing the communication between your frontend platform (e.g., Nextcloud) and the OnlyOffice Docs server. Without it, anyone who knows your Docs server URL could potentially send requests to it, instructing it to fetch and potentially modify documents from your frontend.

  • Shared Secret: You configure a secret key (a long, random string) in both the OnlyOffice Docs server configuration and the connector settings on your frontend platform.
  • Signing: When the frontend sends a request to OnlyOffice Docs (e.g., to open a file), it creates a JWT containing details about the request (file ID, user ID, permissions) and signs it using the shared secret.
  • Verification: OnlyOffice Docs receives the request and the JWT. It uses its copy of the shared secret to verify the signature on the JWT.
    • If the signature is valid, OnlyOffice Docs trusts that the request genuinely came from the authorized frontend platform and processes it.
    • If the signature is invalid (meaning the wrong secret was used, or the token was tampered with), OnlyOffice Docs rejects the request, preventing unauthorized access.

System Requirements:

While exact requirements depend on usage (number of simultaneous users, document complexity), here are general guidelines for a small-to-medium deployment:

  • CPU: 2 cores minimum, 4+ cores recommended for better performance.
  • RAM: 6 GB minimum, 8 GB+ strongly recommended. The services, especially the converter and editor backend, can be memory-intensive. Insufficient RAM is a common cause of instability or slow performance.
  • Disk Space: 40 GB minimum free space for the host OS, Docker images/containers, system logs, fonts, and OnlyOffice Docs cache. Document storage itself happens on the frontend platform (like Nextcloud), not usually within the Docs server's persistent storage (unless explicitly configured for caching large files).
  • Operating System: A modern 64-bit Linux distribution that supports Docker (e.g., Ubuntu 20.04/22.04, Debian 11/12, CentOS Stream 8/9).
  • Software: Docker Engine and Docker Compose are highly recommended for ease of deployment and management.

Understanding these architectural pieces and interactions is fundamental before proceeding with the installation.

Workshop Installing Docker and Docker Compose

Goal: Install Docker Engine and Docker Compose on a Linux server (Ubuntu/Debian example) to prepare for deploying OnlyOffice Docs.

Prerequisites:

  • A server running a fresh installation of Ubuntu 22.04 LTS (or Debian 11/12). Adapt commands slightly for other distributions.
  • Access to the server via SSH or direct console.
  • A user account with sudo privileges.

Steps:

  1. Update Package Index: Ensure your system's package list is up-to-date.

    sudo apt update
    sudo apt upgrade -y # Optional but recommended
    
    Explanation: apt update refreshes the list of available packages from the repositories defined in /etc/apt/sources.list and related files. apt upgrade installs the newest versions of all packages currently installed on the system. The -y flag automatically confirms prompts.

  2. Install Prerequisite Packages: Install packages required to allow apt to use repositories over HTTPS.

    sudo apt install apt-transport-https ca-certificates curl software-properties-common gnupg lsb-release -y
    
    Explanation:

    • apt-transport-https: Allows apt to retrieve packages over HTTPS.
    • ca-certificates: Allows the system to check the security certificates of HTTPS connections.
    • curl: A command-line tool for transferring data using various protocols, used here to download the Docker GPG key.
    • software-properties-common: Provides helper scripts for managing software repositories (like add-apt-repository).
    • gnupg: Utility for handling GPG keys, needed to verify the Docker repository's authenticity.
    • lsb-release: Provides information about the Linux distribution, used by Docker's scripts.
  3. Add Docker's Official GPG Key: Download Docker's GPG key to verify the authenticity of the Docker packages.

    sudo mkdir -p /etc/apt/keyrings
    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
    
    Explanation:

    • sudo mkdir -p /etc/apt/keyrings: Creates the directory where apt expects to find keyring files (a recommended practice over older methods).
    • curl -fsSL ...: Downloads the GPG key. -f fails silently on server errors, -s runs silently, -S shows errors if -s is used, -L follows redirects.
    • |: Pipes the downloaded key to the gpg command.
    • sudo gpg --dearmor -o ...: Converts the key from the standard ASCII-armored format to the binary format apt uses and saves it to the specified file.
  4. Set Up Docker Repository: Add Docker's official APT repository to your system's sources.

    echo \
      "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
      $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
    
    Explanation:

    • echo "...": Prints the repository configuration line.
      • deb: Specifies a binary package repository.
      • [arch=$(dpkg --print-architecture) signed-by=...]: Specifies the architecture (e.g., amd64) dynamically and tells apt where to find the GPG key to verify packages from this repo.
      • https://download.docker.com/linux/ubuntu: The base URL of the repository.
      • $(lsb_release -cs): Dynamically gets the codename of your Ubuntu release (e.g., jammy for 22.04).
      • stable: Specifies the release channel (stable, edge, test).
    • | sudo tee ...: Pipes the output of echo to the tee command, which writes it to the specified file (/etc/apt/sources.list.d/docker.list) and also prints it to the console (redirected to /dev/null here to keep the output clean). Using sudo tee is necessary because simple redirection (>) might not work due to permission issues when run with sudo only on the echo part.
  5. Update Package Index Again: Update the package index to include the packages from the newly added Docker repository.

    sudo apt update
    

  6. Install Docker Engine: Install Docker Engine, containerd (container runtime), and Docker CLI.

    sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
    
    Explanation:

    • docker-ce: Docker Community Edition - the main engine.
    • docker-ce-cli: Command Line Interface tool to interact with the Docker daemon.
    • containerd.io: The underlying container runtime that Docker Engine uses.
    • docker-buildx-plugin: Enables advanced build capabilities with BuildKit.
    • docker-compose-plugin: Integrates docker compose (v2 syntax) directly into the Docker CLI (you run docker compose instead of docker-compose). This is the modern way.
  7. Verify Docker Installation: Check if Docker is installed and running.

    sudo systemctl status docker
    
    (Press q to exit the status view). You should see active (running). Run the hello-world container to confirm Docker works:
    sudo docker run hello-world
    
    You should see a message confirming that your installation appears to be working correctly.

  8. Add User to Docker Group (Optional but Recommended): To run docker commands without sudo every time, add your user to the docker group.

    sudo usermod -aG docker $USER
    
    Explanation: usermod -aG adds the user ($USER expands to your current username) to the specified supplementary group (docker). Important: You need to log out and log back in (or run newgrp docker in your current shell, though logging out/in is cleaner) for this group change to take effect. Security Note: Adding a user to the docker group grants privileges equivalent to root access, as they can run containers that can interact with the host system. Only add trusted users to this group.

  9. Verify Docker Compose Plugin: Check if the Docker Compose plugin (v2 syntax) is working.

    docker compose version
    
    You should see the version information for Docker Compose.

Conclusion: You have successfully installed Docker Engine and the Docker Compose plugin on your server. Your system is now ready to deploy containerized applications like OnlyOffice Docs.

2. Simple Docker Installation

The easiest and officially recommended way to deploy OnlyOffice Docs is by using its official Docker container. This encapsulates the application and all its dependencies (Nginx, PostgreSQL, Redis, RabbitMQ, services) into a single, isolated image.

Prerequisites:

  • Docker and Docker Compose installed (as per the previous workshop).
  • Sufficient RAM (min. 6GB, 8GB+ recommended) and CPU (min. 2 cores).
  • Internet connection to download the Docker image.
  • Basic understanding of Docker concepts (images, containers, ports, volumes).

Choosing the Right Image:

OnlyOffice provides several Docker images. For general use, the primary image is onlyoffice/documentserver. There are also variations like onlyoffice/documentserver-ee (Enterprise Edition) and potentially others. We will use the standard community edition image: onlyoffice/documentserver.

Deployment Method: docker run

This command directly runs a container from the specified image. It's simpler for a quick start but less manageable for complex configurations compared to Docker Compose.

Steps:

  1. Pull the Latest Image (Optional but Recommended): Ensures you have the most recent version of the OnlyOffice Docs image.

    sudo docker pull onlyoffice/documentserver
    
    Explanation: docker pull downloads the specified image (and its layers) from Docker Hub (or another configured registry) to your local machine.

  2. Run the Container: Execute the docker run command to start the OnlyOffice Docs container.

    sudo docker run -i -t -d --restart=always \
        -p 8080:80 \
        -p 4433:443 \
        -e JWT_ENABLED=true \
        -e JWT_SECRET=your_super_secret_key \
        --name onlyoffice-docs \
        onlyoffice/documentserver
    
    Explanation:

    • sudo docker run: Command to create and start a new container.
    • -i: Keep STDIN open even if not attached (interactive).
    • -t: Allocate a pseudo-TTY. Often used together with -i.
    • -d: Detached mode - run the container in the background and print the container ID.
    • --restart=always: Automatically restart the container if it stops (e.g., after a server reboot or crash). Other options include no, on-failure, unless-stopped.
    • -p 8080:80: Map port 8080 on the host machine to port 80 inside the container. Port 80 is the default HTTP port used by the Nginx service within the OnlyOffice container. You can choose any unused port on your host instead of 8080.
    • -p 4433:443: Map port 4433 on the host machine to port 443 inside the container. Port 443 is the default HTTPS port used by the Nginx service within the container. Note: By default, the container uses self-signed certificates for HTTPS on port 443. For production, you should not expose this port directly but rather use a reverse proxy to handle valid HTTPS certificates (covered later). For initial testing, mapping it can be useful, but accessing https://your_server_ip:4433 will likely result in browser security warnings. We map it here for completeness but will primarily use the HTTP port 8080 for initial setup and integration, letting a reverse proxy handle external HTTPS.
    • -e JWT_ENABLED=true: An environment variable passed into the container. This enables the JWT security feature, which is crucial. It forces OnlyOffice Docs to require a valid JWT from connecting clients. Always set this to true for security.
    • -e JWT_SECRET=your_super_secret_key: This environment variable sets the shared secret key used for signing and verifying JWTs. Replace your_super_secret_key with a very strong, unique, and random string. Keep this secret safe! It must match the secret configured in your frontend application (e.g., Nextcloud connector).
    • --name onlyoffice-docs: Assigns a specific name to the container, making it easier to manage (e.g., docker stop onlyoffice-docs). If omitted, Docker assigns a random name.
    • onlyoffice/documentserver: The name of the Docker image to use.
  3. Verify Container Status: Check if the container is running.

    sudo docker ps
    
    You should see an entry for the onlyoffice-docs container with status Up and port mappings like 0.0.0.0:8080->80/tcp. It might take a minute or two for the internal services to fully initialize after starting.

  4. Check Container Logs: View the logs generated by the container to monitor startup progress and check for errors.

    sudo docker logs onlyoffice-docs
    
    To follow the logs in real-time:
    sudo docker logs -f onlyoffice-docs
    
    (Press Ctrl+C to stop following). Look for messages indicating that services like Nginx, DocService, PostgreSQL, Redis, RabbitMQ have started successfully.

  5. Initial Access Test: Open your web browser and navigate to http://<your_server_ip>:8080. You should see the OnlyOffice Docs welcome page, often displaying a message like "ONLYOFFICE Docs Community Edition is running". This confirms the server is up and accessible. Do not proceed with integration until you see this page.

Important Considerations:

  • JWT Secret: The -e JWT_SECRET=... is critical. Never use a weak secret or the example value. Generate a strong random string (e.g., using openssl rand -hex 32).
  • Persistence: This simple docker run command does not configure persistent storage for logs, cache, or database data outside the container. If you remove the container (docker rm onlyoffice-docs), this data will be lost. For more robust setups, you'd use Docker volumes (-v flag or Docker Compose) to store this data on the host filesystem. We will cover volumes in intermediate sections. For basic use and testing, non-persistent is often acceptable initially.
  • HTTPS: As mentioned, this setup exposes OnlyOffice Docs over HTTP (port 8080). This is not secure for production use over the internet. Sensitive data (like JWTs or document content snippets) could be intercepted. You must use a reverse proxy (like Nginx, Apache, Caddy, Traefik) to handle HTTPS termination externally. This will be covered in the Intermediate section. The internal HTTPS on port 443 uses self-signed certificates and should generally not be exposed directly.

You have now successfully deployed a basic instance of OnlyOffice Docs using Docker. The next step is typically to configure a reverse proxy for HTTPS and then integrate it with a frontend platform.

Workshop Deploying OnlyOffice Docs via Docker

Goal: Deploy OnlyOffice Docs using the docker run command, configure a secure JWT secret, and verify the installation.

Prerequisites:

  • Docker installed and running on your Linux server.
  • Access to the server's command line with sudo privileges (or user added to the docker group).
  • Your server's IP address.
  • Port 8080 available on the host machine (or choose another available port).

Steps:

  1. Generate a Secure JWT Secret: Use a command-line tool like openssl or pwgen to create a strong random string. We'll use openssl.

    openssl rand -hex 32
    
    Explanation: openssl rand generates random bytes. -hex formats the output as a hexadecimal string. 32 specifies the number of random bytes to generate, resulting in a 64-character hex string. Copy the generated string. You will need it immediately and also later when configuring your frontend (e.g., Nextcloud). Let's assume the generated secret is a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2. Use your own generated secret!

  2. Stop and Remove Any Previous Instances (If Applicable): If you previously tried running onlyoffice-docs, stop and remove the old container to avoid conflicts.

    sudo docker stop onlyoffice-docs
    sudo docker rm onlyoffice-docs
    
    Explanation: docker stop gracefully stops the container. docker rm removes the stopped container. Ignore errors if the container doesn't exist.

  3. Pull the Latest Image: Ensure you have the latest onlyoffice/documentserver image.

    sudo docker pull onlyoffice/documentserver
    

  4. Run the OnlyOffice Docs Container: Use the docker run command, substituting YOUR_SECRET_KEY_HERE with the secret you generated in Step 1. We will map host port 8080 to container port 80.

    sudo docker run -i -t -d --restart=always \
        -p 8080:80 \
        -e JWT_ENABLED=true \
        -e JWT_SECRET=a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2 `# <-- Replace with YOUR generated secret` \
        --name onlyoffice-docs \
        onlyoffice/documentserver
    
    Remember to replace the example secret with your own!

  5. Verify Container is Running: Wait about 30-60 seconds for the container to initialize its internal services. Then, check its status:

    sudo docker ps
    
    Expected Output (simplified):
    CONTAINER ID   IMAGE                     COMMAND                  CREATED          STATUS          PORTS                                       NAMES
    abcdef123456   onlyoffice/documentserver   "/app/ds/run-document…"   A minute ago     Up A minute     0.0.0.0:8080->80/tcp, :::8080->80/tcp       onlyoffice-docs
    
    Look for STATUS Up and the correct port mapping (0.0.0.0:8080->80/tcp).

  6. Check Initial Logs: Quickly check the logs for any obvious startup errors.

    sudo docker logs --tail 50 onlyoffice-docs
    
    Explanation: --tail 50 shows only the last 50 lines of the log, which is usually sufficient to see if the main services started correctly. You should see lines indicating services like Nginx, DS (DocService), Conv (Converter), PostgreSQL, Redis, RabbitMQ starting up without critical errors.

  7. Test Access via Web Browser: Open your web browser (on a machine that can reach your server) and navigate to: http://<YOUR_SERVER_IP>:8080 Replace <YOUR_SERVER_IP> with the actual IP address of the server where you ran the container. Expected Result: You should see the OnlyOffice Docs welcome page, typically stating "ONLYOFFICE Docs Community Edition is running".

Troubleshooting:

  • Connection Refused:
    • Did you use the correct IP address?
    • Is a firewall on the server blocking port 8080? (e.g., sudo ufw status or sudo firewall-cmd --list-all). You might need to allow the port: sudo ufw allow 8080/tcp or sudo firewall-cmd --permanent --add-port=8080/tcp && sudo firewall-cmd --reload.
    • Is the container actually running (docker ps)? Check docker logs onlyoffice-docs for errors.
    • Did you wait long enough for it to start?
  • Page Not Loading or Errors: Check docker logs onlyoffice-docs for specific error messages. Insufficient RAM is a common cause of instability. Use docker stats onlyoffice-docs to monitor resource usage.

Conclusion: You have successfully deployed OnlyOffice Docs using Docker, enabled JWT security with a unique secret, and verified basic accessibility. The server is running on HTTP at port 8080 and is ready for the next steps: setting up a reverse proxy for HTTPS and integrating it with a frontend application. Remember to save the JWT secret you generated!

Intermediate

This section delves into configuring your OnlyOffice Docs instance, securing it with HTTPS using a reverse proxy, and integrating it with a frontend platform like Nextcloud.

3. Configuration and Customization

While the Docker environment variables handle basic setup like JWT, more advanced configuration and customization often involve modifying OnlyOffice Docs' main configuration file, local.json, or using specific environment variables if available.

Understanding local.json:

The core configuration file for OnlyOffice Docs is typically located at /etc/onlyoffice/documentserver/local.json inside the container. This JSON file controls various aspects of the server's behavior, including service connections, paths, logging, cache settings, and enabling/disabling certain features.

Accessing local.json (Docker):

To modify local.json persistently, you need to use Docker volumes to map the configuration file (or its directory) from inside the container to your host machine.

  1. Create Host Directories: Prepare directories on your host system to store persistent data.

    sudo mkdir -p /app/onlyoffice/DocumentServer/logs
    sudo mkdir -p /app/onlyoffice/DocumentServer/data
    sudo mkdir -p /app/onlyoffice/DocumentServer/lib # For PostgreSQL data
    sudo mkdir -p /app/onlyoffice/DocumentServer/db # For Redis/RabbitMQ if needed (less common to persist)
    # Set permissions (adjust user/group if not running rootless Docker)
    sudo chown -R 99:99 /app/onlyoffice/DocumentServer # User/Group ID used inside some older OnlyOffice images, may vary check image docs. Often 101:101 or specific names. Or simply `chmod -R 755` if permissions aren't strict. Modern images might use a non-root user. Check container user ID if issues arise. Let's start broadly permissive for now, refine later if needed.
    sudo chmod -R 755 /app/onlyoffice/DocumentServer
    
    Explanation: We create directories on the host under /app/onlyoffice (you can choose a different base path) to map the container's logs, data (cache, file uploads), database files, etc. chown and chmod set appropriate permissions so the container's internal processes can write to these directories. The exact UID/GID might need checking (e.g., docker exec onlyoffice-docs id -u and docker exec onlyoffice-docs id -g).

  2. Run Container with Volumes: Stop and remove the old container, then run it again, adding -v volume mounts.

    # Stop and remove the previous container
    sudo docker stop onlyoffice-docs
    sudo docker rm onlyoffice-docs
    
    # Run with volumes (replace YOUR_SECRET_KEY_HERE)
    sudo docker run -i -t -d --restart=always \
        -p 8080:80 \
        -e JWT_ENABLED=true \
        -e JWT_SECRET=YOUR_SECRET_KEY_HERE \
        -v /app/onlyoffice/DocumentServer/logs:/var/log/onlyoffice \
        -v /app/onlyoffice/DocumentServer/data:/var/www/onlyoffice/Data \
        -v /app/onlyoffice/DocumentServer/lib:/var/lib/postgresql \
        # Add other volumes as needed, e.g., for Redis/RabbitMQ persistence if required
        --name onlyoffice-docs \
        onlyoffice/documentserver
    
    Explanation:

    • -v /host/path:/container/path: Maps a directory (or file) on the host to a directory (or file) inside the container. Changes made in the container path are reflected on the host and vice-versa. Data persists on the host even if the container is removed.
    • /var/log/onlyoffice: Standard log directory inside the container.
    • /var/www/onlyoffice/Data: Used for caching, temporary file uploads, etc.
    • /var/lib/postgresql: Default data directory for the PostgreSQL database inside the container. Persisting this ensures your database state survives container restarts/recreations.
  3. Modifying local.json:

    • Copy Default: First, copy the default local.json from a running container to your host if you don't have it.
      sudo docker cp onlyoffice-docs:/etc/onlyoffice/documentserver/local.json /app/onlyoffice/DocumentServer/local.json.default
      # Make a working copy
      sudo cp /app/onlyoffice/DocumentServer/local.json.default /app/onlyoffice/DocumentServer/local.json
      # Adjust permissions if needed
      sudo chown 99:99 /app/onlyoffice/DocumentServer/local.json # Match container user if necessary
      sudo chmod 644 /app/onlyoffice/DocumentServer/local.json
      
    • Add Volume Mount for local.json: Stop/remove the container again and add a volume mount specifically for the configuration file.
      sudo docker stop onlyoffice-docs
      sudo docker rm onlyoffice-docs
      
      sudo docker run -i -t -d --restart=always \
          -p 8080:80 \
          -e JWT_ENABLED=true \
          -e JWT_SECRET=YOUR_SECRET_KEY_HERE \
          -v /app/onlyoffice/DocumentServer/logs:/var/log/onlyoffice \
          -v /app/onlyoffice/DocumentServer/data:/var/www/onlyoffice/Data \
          -v /app/onlyoffice/DocumentServer/lib:/var/lib/postgresql \
          -v /app/onlyoffice/DocumentServer/local.json:/etc/onlyoffice/documentserver/local.json \
          --name onlyoffice-docs \
          onlyoffice/documentserver
      
    • Edit on Host: Now you can edit /app/onlyoffice/DocumentServer/local.json on your host system using a text editor like nano or vim.
      sudo nano /app/onlyoffice/DocumentServer/local.json
      
    • Restart Container: After saving changes to local.json on the host, you must restart the container for them to take effect.
      sudo docker restart onlyoffice-docs
      

Common local.json Customizations:

  • Changing Internal Ports: You might need to change the ports used internally by services if they conflict with other services you plan to run within the same Docker network (less common when running standalone). Look for sections like services.CoAuthoring.port or settings related to Nginx configuration snippets included by local.json. Caution: Modifying these requires careful understanding and is often unnecessary. Changing the external port mapping (-p host:container) is usually sufficient.
  • Log Levels: Adjust the verbosity of logs. Find the logging section (it might be nested under services). You can often set levels like "debug", "info", "warn", "error".
    {
      "services": {
        "CoAuthoring": {
          // ... other settings
          "log": {
            "level": "info" // Change to "debug" for more details or "warn"/"error" for less
          }
          // ...
        }
      },
      // ... other top-level settings
      "logging": { // Global or specific service logging might be here
          "level": "info",
          // Potentially settings for file rotation, size limits etc.
      }
    }
    
  • Database Connection: If you were running PostgreSQL externally (not recommended for simplicity unless scaling requires it), you would modify the database connection parameters here (host, port, user, password).
  • Redis/RabbitMQ Connection: Similar to the database, connection details for Redis and RabbitMQ are in local.json.
  • Enabling/Disabling Features: Some features, like spell checking or specific integrations, might have configuration flags within local.json. This depends heavily on the OnlyOffice Docs version.
  • Customizing Interface: While deep UI customization often requires the commercial version or custom builds, some minor tweaks (like hiding menu items) might be possible via configuration, though often undocumented or subject to change. Refer to official documentation for supported options.

Using Docker Compose for Easier Management:

Managing multiple volumes and environment variables with docker run becomes cumbersome. Docker Compose uses a YAML file (docker-compose.yml) to define services, networks, and volumes, making deployment declarative and reproducible.

# docker-compose.yml
version: '3.8'

services:
  onlyoffice-docs:
    container_name: onlyoffice-docs
    image: onlyoffice/documentserver:latest # Pin to a specific version in production (e.g., :7.5.1)
    restart: always
    ports:
      - "8080:80" # Host port : Container port
      # - "4433:443" # Optional mapping for internal HTTPS (usually handled by external reverse proxy)
    environment:
      - JWT_ENABLED=true
      - JWT_SECRET=YOUR_SECRET_KEY_HERE # Replace with your actual secret
      # Add other environment variables if needed (e.g., WOOPI_ENABLED=false to disable welcome page)
    volumes:
      - ./data:/var/www/onlyoffice/Data # Maps ./data in current dir to container path
      - ./logs:/var/log/onlyoffice      # Maps ./logs in current dir to container path
      - ./lib:/var/lib/postgresql       # Maps ./lib in current dir to container path
      - ./local.json:/etc/onlyoffice/documentserver/local.json # Map local.json file

volumes: # Define named volumes (alternative to bind mounts shown above)
  # data:
  # lib:
  # logs:
  # If using named volumes, change the volume mounts above like:
  # - data:/var/www/onlyoffice/Data
  # - logs:/var/log/onlyoffice
  # - lib:/var/lib/postgresql
  # Named volumes are managed by Docker and often preferred over bind mounts for application data.
  # Bind mounts (like ./local.json) are better for configuration files you edit directly on the host.

To use Docker Compose:

  1. Save the content above as docker-compose.yml in a dedicated directory (e.g., /opt/onlyoffice-docs-compose).
  2. Create the subdirectories (data, logs, lib) and the local.json file (copying the default first) in the same directory as docker-compose.yml.
  3. Replace YOUR_SECRET_KEY_HERE in docker-compose.yml.
  4. Navigate to that directory in your terminal: cd /opt/onlyoffice-docs-compose.
  5. Run sudo docker compose up -d to start the services in detached mode.
  6. Run sudo docker compose down to stop and remove the services defined in the file.
  7. Logs can be viewed with sudo docker compose logs -f.

Docker Compose simplifies managing the configuration and deployment lifecycle significantly.

Workshop Customizing Ports and Enabling HTTPS via Reverse Proxy

Goal: Configure OnlyOffice Docs to run on a non-standard internal port (demonstrating configuration modification) and set up a Caddy reverse proxy to provide secure HTTPS access on the standard port 443.

Prerequisites:

  • Docker and Docker Compose installed.
  • An OnlyOffice Docs instance deployable via Docker Compose (we'll adapt the previous compose file).
  • A domain name (e.g., onlyoffice.yourdomain.com) pointing to your server's public IP address.
  • Ports 80 and 443 open on your server's firewall (Caddy needs port 80 for ACME HTTP-01 challenge and 443 for HTTPS).

Part 1: Modifying OnlyOffice Internal Port (via local.json)

Note: This is primarily for demonstration. Changing the internal Nginx port is rarely needed in practice, as Docker port mapping handles external access. We'll change a less critical service port for illustration, or simulate the need. For this workshop, we'll stick to changing the external mapping which is more common and useful. We will modify the docker-compose.yml to expose OnlyOffice Docs on host port 8888 instead of 8080.

Part 2: Setting up Caddy Reverse Proxy

Caddy is a modern web server known for its automatic HTTPS feature using Let's Encrypt.

Steps:

  1. Prepare Directory Structure: Create a directory for your Caddy configuration and the updated OnlyOffice Compose file.

    sudo mkdir -p /opt/onlyoffice-secure
    cd /opt/onlyoffice-secure
    sudo mkdir -p ./onlyoffice/data ./onlyoffice/logs ./onlyoffice/lib # For OnlyOffice volumes
    # You might need to copy/create a default local.json if mounting it, but not needed for this workshop goal.
    

  2. Create docker-compose.yml: Create a docker-compose.yml file that defines both OnlyOffice Docs and Caddy services.

    sudo nano docker-compose.yml
    
    Paste the following content, replacing onlyoffice.yourdomain.com with your actual domain and YOUR_SECRET_KEY_HERE with your JWT secret:

    version: '3.8'
    
    services:
      onlyoffice-docs:
        container_name: onlyoffice-docs
        image: onlyoffice/documentserver:latest
        restart: always
        # No 'ports' section here - access will be through Caddy via the Docker network
        environment:
          - JWT_ENABLED=true
          - JWT_SECRET=YOUR_SECRET_KEY_HERE # Replace with your secret
          - WOOPI_ENABLED=false # Optional: Disable the default welcome page for cleaner access via proxy
        volumes:
          - ./onlyoffice/data:/var/www/onlyoffice/Data
          - ./onlyoffice/logs:/var/log/onlyoffice
          - ./onlyoffice/lib:/var/lib/postgresql
        networks:
          - onlyoffice-net # Connect to custom network
    
      caddy:
        container_name: caddy-proxy
        image: caddy:latest
        restart: always
        ports:
          - "80:80"   # Needed for ACME HTTP-01 challenge
          - "443:443" # Standard HTTPS port
        volumes:
          - ./Caddyfile:/etc/caddy/Caddyfile # Mount Caddy configuration file
          - caddy_data:/data                 # Persist Caddy's state (certs, etc.)
          - caddy_config:/config             # Persist Caddy's config cache
        environment:
          # Set your domain and email for Caddy's automatic HTTPS
          - MY_DOMAIN=onlyoffice.yourdomain.com # Replace with your domain
          - MY_EMAIL=your_email@example.com     # Replace with your email (for Let's Encrypt)
          # Pass the internal OnlyOffice Docs hostname to Caddy config (service name from this compose file)
          - ONLYOFFICE_UPSTREAM=onlyoffice-docs:80 # Service name and internal port
        networks:
          - onlyoffice-net # Connect to custom network
    
    networks:
      onlyoffice-net: # Define the custom Docker network
        driver: bridge
    
    volumes: # Define named volumes for Caddy
      caddy_data:
      caddy_config:
    
  3. Create Caddyfile: This file tells Caddy how to handle incoming requests.

    sudo nano Caddyfile
    
    Paste the following configuration:

    {
        # Email for ACME TLS certificate registration
        email {$MY_EMAIL}
        # Optional: Staging endpoint for testing Let's Encrypt without hitting rate limits
        # acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
    }
    
    {$MY_DOMAIN} {
        # Enable compression
        encode gzip zstd
    
        # Reverse proxy requests to the OnlyOffice Docs container
        # 'onlyoffice-docs:80' matches the service name and internal port in docker-compose.yml
        reverse_proxy {$ONLYOFFICE_UPSTREAM} {
            # Required headers for OnlyOffice Docs to function correctly behind a proxy
            header_up Host {http.reverse_proxy.upstream.hostport}
            header_up X-Real-IP {http.request.remote.ip}
            header_up X-Forwarded-Host {http.request.host}
            header_up X-Forwarded-Proto {http.request.scheme}
            # Increase proxy timeouts for potentially long operations
            transport http {
                dial_timeout 10s
                response_header_timeout 120s
            }
        }
    
        # Optional: Add security headers
        header {
            # Enable HTTP Strict Transport Security (HSTS)
            Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
            # Prevent search engine indexing
            X-Robots-Tag "noindex, nofollow, nosnippet, noarchive"
            # Recommended security headers
            X-Frame-Options "SAMEORIGIN"
            X-Content-Type-Options "nosniff"
            Referrer-Policy "strict-origin-when-cross-origin"
            Permissions-Policy "interest-cohort=()"
            # Remove Caddy's signature
            -Server
        }
    
        # Logging configuration (optional)
        log {
            output file /data/logs/access.log {
                roll_size 100mb
                roll_keep 5
                roll_keep_for 720h
            }
            level INFO # Adjust log level (DEBUG, INFO, WARN, ERROR)
        }
    }
    
    Explanation:

    • The {$MY_DOMAIN} block defines configuration for your specific domain.
    • email {$MY_EMAIL} uses the environment variable for Let's Encrypt.
    • encode gzip zstd enables compression for faster loading.
    • reverse_proxy {$ONLYOFFICE_UPSTREAM} forwards traffic to the onlyoffice-docs service on port 80 within the Docker network. {$ONLYOFFICE_UPSTREAM} gets replaced by the environment variable value onlyoffice-docs:80.
    • header_up ... lines pass necessary information to the backend application so it knows the original request details (original host, protocol). This is crucial for OnlyOffice Docs.
    • Security headers enhance the security of your site.
    • The log block configures access logging.
  4. Ensure Domain DNS is Correct: Double-check that onlyoffice.yourdomain.com points to your server's public IP address. Propagation might take time.

  5. Start the Services: Navigate back to the /opt/onlyoffice-secure directory.

    cd /opt/onlyoffice-secure
    sudo docker compose up -d
    
    Docker will pull the Caddy image, create the onlyoffice-net network, and start both containers. Caddy will automatically attempt to obtain an SSL certificate from Let's Encrypt for your domain.

  6. Monitor Logs: Check the logs for both services, especially Caddy during the first startup, to ensure the certificate was obtained successfully.

    sudo docker compose logs -f caddy
    
    Look for messages related to obtaining/renewing certificates and successful startup. Check OnlyOffice logs too:
    sudo docker compose logs -f onlyoffice-docs
    

  7. Test Access: Open your web browser and navigate to https://onlyoffice.yourdomain.com (using HTTPS). Expected Result: You should see the OnlyOffice Docs interface (or nothing if WOOPI_ENABLED=false, which is fine - it means the proxy is working). The connection should be secure (padlock icon in the address bar), using a valid certificate issued by Let's Encrypt.

Troubleshooting:

  • Certificate Errors (NET::ERR_CERT_AUTHORITY_INVALID):
    • Did Caddy fail to get a certificate? Check docker compose logs caddy. Common issues include:
      • Incorrect domain name or DNS not pointing correctly.
      • Firewall blocking port 80 (needed for Let's Encrypt HTTP-01 validation).
      • Let's Encrypt rate limits (if you requested too many times). Try using the staging CA first by uncommenting the acme_ca line in Caddyfile, testing, then commenting it out again for a real certificate.
      • Incorrect email format or temporary Let's Encrypt server issues.
  • 5xx Server Errors:
    • Check Caddy logs (docker compose logs caddy) - it might indicate it cannot reach the upstream onlyoffice-docs service. Ensure onlyoffice-docs is running (docker ps) and healthy (docker compose logs onlyoffice-docs).
    • Verify the {$ONLYOFFICE_UPSTREAM} variable in Caddyfile matches the service name (onlyoffice-docs) and the internal port (80) where OnlyOffice listens within the Docker network.
  • OnlyOffice Docs Functionality Issues (e.g., cannot save): Often related to missing X-Forwarded-* headers or incorrect Host header being passed by the proxy. Double-check the header_up directives in the Caddyfile. Also ensure the Document Server address configured in your frontend (e.g., Nextcloud) uses the correct public HTTPS URL (https://onlyoffice.yourdomain.com).

Conclusion: You have successfully configured OnlyOffice Docs to be securely accessible via HTTPS using a Caddy reverse proxy. Caddy handles the SSL certificate management automatically. You are now ready to integrate this secure endpoint with frontend platforms like Nextcloud. Remember to use https://onlyoffice.yourdomain.com as the Document Server URL in the frontend configuration.

4. Integration with Frontend Platforms

OnlyOffice Docs is designed to be the backend editing engine. To manage files, users, and sharing, you need to integrate it with a frontend platform. Common choices include Nextcloud, ownCloud, Seafile, Alfresco, Confluence, Moodle, or OnlyOffice's own Workspace. The integration process typically involves:

  1. Installing a Connector App: The frontend platform usually requires a specific application or plugin (often called a "connector") to communicate with OnlyOffice Docs.
  2. Configuring the Connector: You need to provide the connector with the URL of your OnlyOffice Docs server and the shared JWT secret.

Key Integration Concepts:

  • Document Server URL: This is the publicly accessible URL where your OnlyOffice Docs server can be reached by the frontend platform and by the end-users' browsers. In our previous workshop example, this would be https://onlyoffice.yourdomain.com. It must be the URL managed by your reverse proxy (handling HTTPS).
  • JWT Secret: The same secret key you configured when launching the OnlyOffice Docs container (using -e JWT_SECRET=... or in docker-compose.yml). This must match exactly in both the Docs server configuration and the frontend connector settings.
  • JWT Header: By default, OnlyOffice Docs expects the JWT to be passed in the Authorization HTTP header when requests are made from the frontend server to the Docs server. Sometimes, the browser might also send the token in the request body. The default header is usually Authorization, but some connectors might allow customization (e.g., X-OnlyOffice-Authorization). Ensure this matches on both ends if changed. The standard Docker setup expects the token in the Authorization header, prefixed with Bearer (e.g., Authorization: Bearer <your_jwt_token>). The connector app usually handles adding the Bearer prefix correctly.
  • Callback URL: OnlyOffice Docs needs to send requests back to the frontend platform, primarily to signal that a document has been edited and needs saving. The frontend connector usually handles registering the correct callback URL automatically when communicating with the Docs server. Firewall rules must allow the OnlyOffice Docs server to reach the frontend server's internal or public URL.
  • Internal Addressing (Advanced): For improved security and potentially better performance (avoiding hairpinning through public IPs), you can configure the frontend and backend to communicate directly using internal Docker network names or internal IP addresses, while still providing the public URL for browser access.
    • Document Server Public URL: https://onlyoffice.yourdomain.com (for browser access).
    • Document Server Internal URL: http://onlyoffice-docs (for server-to-server communication if both frontend and backend are in the same Docker network, e.g., onlyoffice-net). Many connectors offer separate fields for this. Using HTTP internally is acceptable within a trusted Docker network.
    • Frontend Internal URL: The OnlyOffice Docs server needs to be able to reach the frontend's callback URL. If they are in the same Docker network, this could be http://nextcloud-app:80/callback-path (using the frontend's service name).

Example Integration: Nextcloud

Nextcloud is a very popular self-hosted file sync & share platform that integrates well with OnlyOffice Docs.

Steps (within Nextcloud):

  1. Login as Admin: Access your Nextcloud instance with an administrator account.
  2. Navigate to Apps: Go to the "Apps" section (usually accessible from the user menu in the top right).
  3. Find and Enable the Connector: Go to the "Office & text" category, find the "ONLYOFFICE" connector app, and click "Download and enable".
  4. Navigate to Settings: Go to "Administration settings" (usually under the user menu).
  5. Find ONLYOFFICE Settings: In the left sidebar under "Administration", find the "ONLYOFFICE" section.
  6. Configure Server Settings:
    • ONLYOFFICE Docs address: Enter the publicly accessible HTTPS URL of your OnlyOffice Docs server (e.g., https://onlyoffice.yourdomain.com). Crucially, do not add /welcome or other paths unless specifically required by your setup (usually not).
    • Secret key: Enter the exact same JWT secret key that you configured for your OnlyOffice Docs container.
    • (Advanced) ONLYOFFICE Docs address for internal requests from the server: If Nextcloud and OnlyOffice Docs are running in the same Docker network (like onlyoffice-net from the Caddy workshop), you can enter the internal address here (e.g., http://onlyoffice-docs). This allows Nextcloud's backend to talk to OnlyOffice directly without going through the public internet/reverse proxy.
    • (Advanced) Server address for internal requests from ONLYOFFICE Docs: If using an internal address above, you also need to tell the connector what URL OnlyOffice Docs should use to call back to Nextcloud (e.g., http://nextcloud-app/index.php/... if Nextcloud's service name is nextcloud-app in the same Docker network). This often requires careful setup and ensuring the container names are resolvable. If left blank, it typically defaults to the main Nextcloud public URL.
  7. Save Settings: Click the "Save" button. Nextcloud will attempt to communicate with your OnlyOffice Docs server using the provided settings.
  8. Check Connectivity: A successful save usually indicates basic connectivity is working. Look for any error messages. Common errors include:
    • "Error when trying to connect" (Check URL, firewall, DNS, ensure Docs server is running).
    • JWT errors (Ensure the secret key matches exactly and JWT is enabled on the Docs server).
  9. Test Editing: Navigate to your Files app in Nextcloud, upload or create a .docx, .xlsx, or .pptx file, and click on it. It should open within the OnlyOffice editor embedded in the Nextcloud interface. Test typing and saving.

Troubleshooting Integration:

  • Network Issues: Can the Nextcloud server reach the OnlyOffice Docs URL? Can the OnlyOffice Docs server reach the Nextcloud callback URL? Use tools like curl or ping from within the respective containers (docker exec -it <container_name> bash) to test connectivity. Check firewalls on both the host and potentially within Docker networks.
  • JWT Mismatch: This is extremely common. Double-check the secret key in both OnlyOffice Docs (JWT_SECRET environment variable or local.json) and the Nextcloud connector settings. Ensure JWT_ENABLED=true is set for the Docs server.
  • Reverse Proxy Configuration: Ensure your reverse proxy (Caddy, Nginx, etc.) is passing the necessary X-Forwarded-* headers and the correct Host header. Check the proxy logs and the OnlyOffice Docs logs (/var/log/onlyoffice/documentserver/docservice/out.log inside the container) for clues.
  • Mixed Content Errors: If Nextcloud is running on HTTPS but you configured the Docs server URL as HTTP in Nextcloud, browsers will block the connection. Always use the HTTPS URL for the Docs server in the connector settings.
  • Permissions: Ensure file permissions within Nextcloud allow the web server user (e.g., www-data) to access and modify the files being opened.

Successful integration allows your users to seamlessly edit and collaborate on documents directly within their familiar frontend platform environment, leveraging the power of your self-hosted OnlyOffice Docs backend.

Workshop Integrating OnlyOffice Docs with Nextcloud

Goal: Install the OnlyOffice connector in Nextcloud and configure it to use the secure OnlyOffice Docs instance set up in the previous workshop (behind the Caddy reverse proxy).

Prerequisites:

  • A running Nextcloud instance (assumed to be accessible at https://nextcloud.yourdomain.com). You need admin access.
  • A running OnlyOffice Docs instance accessible via HTTPS through a reverse proxy (as set up in the Caddy workshop, accessible at https://onlyoffice.yourdomain.com).
  • The JWT secret key used for your OnlyOffice Docs instance.
  • Both Nextcloud and OnlyOffice Docs servers should ideally be able to reach each other over the network. For simplicity in this workshop, we'll assume public URL access works, but mention the internal URL optimization.

Scenario:

  • Nextcloud URL: https://nextcloud.yourdomain.com
  • OnlyOffice Docs URL: https://onlyoffice.yourdomain.com
  • JWT Secret: a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2 (Use your actual secret)

Steps:

  1. Log in to Nextcloud: Access https://nextcloud.yourdomain.com and log in as an administrator.

  2. Open the Apps Management:

    • Click your user icon/avatar in the top-right corner.
    • Select "Apps" from the dropdown menu.
  3. Install the ONLYOFFICE Connector:

    • In the left sidebar, click on the "Office & text" category.
    • Find the "ONLYOFFICE" app in the list.
    • Click the "Download and enable" button. Wait for the installation to complete. It might take a minute.
  4. Navigate to ONLYOFFICE Admin Settings:

    • Click your user icon/avatar again in the top-right corner.
    • Select "Administration settings".
    • In the left sidebar under the "Administration" section, scroll down and click on "ONLYOFFICE".
  5. Configure the Connection: You will now see the ONLYOFFICE settings page. Fill in the following fields:

    • ONLYOFFICE Docs address: Enter the full, correct HTTPS URL of your OnlyOffice Docs server: https://onlyoffice.yourdomain.com (Make sure there are no typos and no trailing slash unless specifically required, which is rare).
    • Disable certificate verification (insecure): Leave this unchecked. Your Caddy setup provides a valid Let's Encrypt certificate, so verification should work and is essential for security.
    • Secret key: Carefully enter the exact JWT secret key that your OnlyOffice Docs container is using. Paste the value you saved earlier: a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2 (Use your own secret here!)

    • (Optional but Recommended) Advanced Server Settings: Click "Advanced server settings" to expand this section.

      • ONLYOFFICE Docs address for internal requests from the server: If your Nextcloud and OnlyOffice Docs containers are running within the same Docker network (e.g., onlyoffice-net created in the Caddy workshop), you can improve performance and security by using the internal Docker DNS name. Enter: http://onlyoffice-docs (This assumes your OnlyOffice Docs service name in docker-compose.yml is onlyoffice-docs and it listens internally on port 80. Using HTTP here is safe within the trusted Docker network). If they are not in the same network, leave this blank.
      • Server address for internal requests from ONLYOFFICE Docs: If you filled the previous field, you might also need to provide the internal URL for OnlyOffice Docs to call back to Nextcloud. This depends on your Nextcloud container's service name and network setup. For example, if Nextcloud's service name is nextcloud-app in the same network, you might enter http://nextcloud-app. If unsure, or if Nextcloud isn't containerized in the same network, leave this blank; OnlyOffice will use the public Nextcloud URL, which should generally work (though might be slightly less efficient). For this workshop, let's assume you leave this blank unless you have a specific Docker network setup for both.
    • JWT Header: Leave this as the default (Authorization) unless you have explicitly changed it in your OnlyOffice Docs configuration (which is uncommon).

  6. Save the Configuration: Scroll down and click the "Save" button. Nextcloud will attempt to connect to the OnlyOffice Docs server using the details provided.

  7. Verify Connection Status: After clicking "Save", watch for messages at the top of the page or check the fields again.

    • Success: If the settings save without error messages, it indicates Nextcloud successfully communicated with the OnlyOffice Docs server (sent a health check or similar request) and likely received a valid response. You might see green checkmarks or confirmation messages depending on the Nextcloud/Connector version.
    • Error: If you see an error like "Error when trying to connect" or specific JWT errors:
      • Double-check the "ONLYOFFICE Docs address" URL (HTTPS, correct domain, no typos).
      • Triple-check the "Secret key" (copy-paste carefully).
      • Verify your OnlyOffice Docs container is running (sudo docker ps).
      • Check Caddy logs (sudo docker compose logs caddy) to ensure the reverse proxy is working.
      • Check OnlyOffice Docs logs (sudo docker compose logs onlyoffice-docs) for specific errors, especially related to JWT validation in the docservice logs.
      • Ensure firewalls aren't blocking traffic between Nextcloud and OnlyOffice Docs (especially if using public URLs). Test with curl https://onlyoffice.yourdomain.com from the Nextcloud server/container.
  8. Test Document Editing:

    • Navigate to the "Files" app in Nextcloud.
    • Click the "+" button and choose "New document", "New spreadsheet", or "New presentation". Give it a name (e.g., Test Document.docx).
    • Click on the newly created file.
    • Expected Result: The file should open within an embedded OnlyOffice editor interface inside Nextcloud. You should see the familiar ribbon interface.
    • Type some text into the document. Notice the save indicator (often a checkmark or floppy disk icon) shows changes are being saved automatically or when you pause typing.
    • Close the editor tab/window.
    • Re-open the same document. Your changes should be there.
  9. Test Collaboration (Optional):

    • Share the document with another Nextcloud user.
    • Have both users open the document simultaneously.
    • Expected Result: Both users should see each other's cursors and real-time typing edits.

Conclusion: You have successfully integrated your self-hosted, secure OnlyOffice Docs server with your Nextcloud instance. Users can now create, edit, and collaborate on office documents directly within Nextcloud, with all data remaining on your servers. This completes a typical intermediate setup.

Advanced

This section explores more complex topics like scaling your OnlyOffice Docs deployment, advanced security measures, and effective troubleshooting techniques.

5. Scaling and High Availability

As the usage of your OnlyOffice Docs instance grows (more simultaneous users, larger documents), you might encounter performance bottlenecks. Scaling involves distributing the load across multiple instances, while high availability (HA) aims to eliminate single points of failure.

Scaling OnlyOffice Docs:

The architecture of OnlyOffice Docs (separating editors, document server, conversion, database, cache) lends itself to horizontal scaling, meaning adding more server instances rather than just increasing the resources (CPU/RAM) of a single instance (vertical scaling).

Key Considerations:

  1. Load Balancer: The core component for scaling is a load balancer. It sits in front of multiple OnlyOffice Docs instances and distributes incoming requests among them based on chosen algorithms (e.g., round-robin, least connections). Examples include:
    • Hardware Load Balancers (e.g., F5 BIG-IP)
    • Software Load Balancers: Nginx, HAProxy, Traefik, Caddy.
  2. Multiple Docs Instances: You run two or more identical OnlyOffice Docs containers/servers. Each instance should ideally have its own resources (CPU, RAM).
  3. Shared Components: While each Docs instance runs its own DocService, Converter, and internal Nginx, they must connect to shared backend services for state management and messaging:
    • Shared Redis: Used for session management and locking across instances. All Docs instances must point to the same Redis server (or cluster).
    • Shared RabbitMQ: Used for the message queue coordinating tasks between instances. All Docs instances must point to the same RabbitMQ server (or cluster).
    • Shared PostgreSQL (Potentially): While much of the operational state is in Redis/RabbitMQ, PostgreSQL holds some configuration and potentially cache metadata. For a truly scaled setup, all Docs instances should connect to a central, potentially clustered, PostgreSQL database.
    • Shared Storage (for Data/Cache): If you persist /var/www/onlyoffice/Data, this potentially needs to be on shared storage accessible by all instances (e.g., NFS, GlusterFS, CephFS) or you need to configure Docs to use an object storage backend (like S3, MinIO) if supported for caching. This adds considerable complexity.
  4. Configuration (local.json): Each OnlyOffice Docs instance's local.json file must be updated to point to the shared Redis, RabbitMQ, and PostgreSQL services instead of their internal containerized versions.
  5. JWT: The same JWT secret must be configured on all Docs instances behind the load balancer.
  6. Health Checks: The load balancer needs to perform health checks on each backend Docs instance (e.g., by requesting the /healthcheck endpoint) to ensure it only sends traffic to healthy nodes.

Simplified Scaling (Community Edition Limitations):

True, robust HA and scaling often involve features and support found in the OnlyOffice Docs Enterprise Edition, which has specific clustering capabilities. However, you can achieve basic load balancing with the Community Edition using Docker Compose and a software load balancer:

  • Approach: Run multiple onlyoffice/documentserver containers. Place a load balancer container (like Nginx or HAProxy) in the same Docker Compose file. Configure the load balancer to distribute traffic between the OnlyOffice containers using their Docker service names.
  • Limitation: This simple setup usually means each Docs container still uses its own internal Redis, RabbitMQ, and PostgreSQL. This works for basic load balancing (distributing editing load) but doesn't provide true shared state or HA for the backend components themselves. If one Docs container goes down, users connected to it lose their session, but new connections can be established via the load balancer to other healthy containers. Collaboration within the same document might be disrupted if users are connected to different backend instances unless Redis/RabbitMQ are properly externalized and shared. For basic load distribution where users aren't heavily collaborating on the exact same document simultaneously across nodes, this can still improve overall throughput.

High Availability (HA):

HA goes beyond scaling by aiming for redundancy at every level to prevent service interruption even if a component fails.

  • Load Balancer HA: Run multiple load balancer instances (e.g., using VRRP/Keepalived for IP failover or DNS round-robin).
  • Docs Instance HA: Handled by having multiple instances behind the load balancer.
  • Backend Service HA: This is the most complex part. Requires setting up clustered Redis (Redis Sentinel/Cluster), clustered RabbitMQ, and clustered PostgreSQL (e.g., using Patroni, Streaming Replication). This is significantly more complex than running standalone services.
  • Shared Storage HA: If using shared filesystem storage, it also needs to be highly available (e.g., replicated GlusterFS, CephFS).

Achieving full HA for OnlyOffice Docs typically requires significant infrastructure and administrative effort, often justifying the Enterprise Edition which simplifies some of these aspects.

Summary for Self-Hosters (Community Edition):

Focus on basic load balancing first if performance becomes an issue. Use Docker Compose to manage multiple Docs instances and a load balancer container. Accept that true HA for the backend state components (Redis, RabbitMQ, PostgreSQL) is complex to achieve without external managed services or significant clustering expertise. Ensure your host server(s) and Docker setup are reliable, and implement --restart=always for containers. Regular backups of persistent volumes are critical.

Workshop Setting Up a Load Balancer with Docker Compose

Goal: Create a docker-compose.yml file to run two instances of OnlyOffice Docs and an Nginx container acting as a simple round-robin load balancer in front of them.

Prerequisites:

  • Docker and Docker Compose installed.
  • Sufficient server resources (recommend at least 4+ cores, 10GB+ RAM to run two Docs instances comfortably, plus Nginx).
  • Port 8080 (or another chosen port) available on the host for the load balancer.
  • Your JWT secret key.

Directory Structure:

/opt/onlyoffice-scaled/
├── docker-compose.yml
├── nginx.conf
├── onlyoffice1/
│   ├── data/
│   ├── logs/
│   └── lib/
└── onlyoffice2/
    ├── data/
    ├── logs/
    └── lib/

Steps:

  1. Create Directories:

    sudo mkdir -p /opt/onlyoffice-scaled/onlyoffice1/{data,logs,lib}
    sudo mkdir -p /opt/onlyoffice-scaled/onlyoffice2/{data,logs,lib}
    cd /opt/onlyoffice-scaled
    
    Set Permissions (Example - adjust if needed based on container user IDs):
    sudo chown -R 99:99 ./onlyoffice1 ./onlyoffice2 # Or use appropriate UID/GID
    sudo chmod -R 755 ./onlyoffice1 ./onlyoffice2
    

  2. Create Nginx Configuration (nginx.conf): This file tells Nginx how to load balance the traffic.

    sudo nano nginx.conf
    
    Paste the following:
    worker_processes auto;
    
    events {
        worker_connections 1024;
    }
    
    http {
        # Define the upstream group of OnlyOffice servers
        # Docker Compose will make 'onlyoffice-docs-1' and 'onlyoffice-docs-2' resolvable
        upstream onlyoffice_backend {
            # Simple round-robin load balancing
            server onlyoffice-docs-1:80;
            server onlyoffice-docs-2:80;
    
            # Optional: Add health checks (requires Nginx Plus or custom LUA scripts for basic Nginx)
            # check interval=5000 rise=2 fall=3 timeout=1000 type=http;
            # check_http_send "GET /healthcheck HTTP/1.0\r\nHost: onlyoffice\r\n\r\n";
            # check_http_expect_alive http_2xx;
        }
    
        server {
            listen 80; # Nginx listens on port 80 inside its container
    
            location / {
                proxy_pass http://onlyoffice_backend; # Pass requests to the upstream group
    
                # Standard proxy headers (Important!)
                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;
    
                # Increase timeouts if needed
                proxy_connect_timeout 60s;
                proxy_read_timeout 120s;
                proxy_send_timeout 60s;
            }
    
             # Optional: Expose healthcheck endpoint for external monitoring
            location = /nginx_health {
                access_log off;
                return 200 'Healthy';
                add_header Content-Type text/plain;
            }
        }
    }
    
    Explanation:

    • upstream onlyoffice_backend: Defines a group of servers named onlyoffice_backend.
    • server onlyoffice-docs-1:80;: Adds the first OnlyOffice service (named onlyoffice-docs-1 in Docker Compose) listening on internal port 80 to the group.
    • server onlyoffice-docs-2:80;: Adds the second instance. By default, Nginx uses round-robin to distribute requests between them.
    • listen 80;: Nginx listens on port 80 inside its container.
    • location / { ... }: Defines how to handle requests for the root path.
    • proxy_pass http://onlyoffice_backend;: Forwards the request to one of the servers in the onlyoffice_backend group.
    • proxy_set_header ...: Sets important headers for the backend OnlyOffice instances.
  3. Create docker-compose.yml:

    sudo nano docker-compose.yml
    
    Paste the following, replacing YOUR_SECRET_KEY_HERE with your JWT secret:

    version: '3.8'
    
    services:
      # First OnlyOffice Docs Instance
      onlyoffice-docs-1:
        container_name: onlyoffice-docs-1
        image: onlyoffice/documentserver:latest
        restart: always
        environment:
          - JWT_ENABLED=true
          - JWT_SECRET=YOUR_SECRET_KEY_HERE # Must be the same for all instances
          - WOOPI_ENABLED=false # Optional: Disable welcome page
        volumes:
          - ./onlyoffice1/data:/var/www/onlyoffice/Data
          - ./onlyoffice1/logs:/var/log/onlyoffice
          - ./onlyoffice1/lib:/var/lib/postgresql
        networks:
          - onlyoffice-net
    
      # Second OnlyOffice Docs Instance
      onlyoffice-docs-2:
        container_name: onlyoffice-docs-2
        image: onlyoffice/documentserver:latest
        restart: always
        environment:
          - JWT_ENABLED=true
          - JWT_SECRET=YOUR_SECRET_KEY_HERE # Must be the same for all instances
          - WOOPI_ENABLED=false # Optional: Disable welcome page
        volumes:
          - ./onlyoffice2/data:/var/www/onlyoffice/Data
          - ./onlyoffice2/logs:/var/log/onlyoffice
          - ./onlyoffice2/lib:/var/lib/postgresql
        networks:
          - onlyoffice-net
    
      # Nginx Load Balancer
      nginx-lb:
        container_name: nginx-lb
        image: nginx:latest
        restart: always
        ports:
          - "8080:80" # Expose Nginx on host port 8080
        volumes:
          - ./nginx.conf:/etc/nginx/nginx.conf:ro # Mount Nginx config (read-only)
        depends_on: # Wait for backend services to be created (doesn't guarantee they are ready)
          - onlyoffice-docs-1
          - onlyoffice-docs-2
        networks:
          - onlyoffice-net
    
    networks:
      onlyoffice-net:
        driver: bridge
    
    Explanation:

    • Defines three services: onlyoffice-docs-1, onlyoffice-docs-2, and nginx-lb.
    • Each OnlyOffice instance uses the same image and JWT secret but mounts its own volumes from separate host directories (onlyoffice1, onlyoffice2). This isolates their internal databases/caches in this simple setup.
    • The nginx-lb service uses the official nginx image, maps host port 8080 to its internal port 80, and mounts the nginx.conf you created.
    • depends_on helps with startup order but doesn't guarantee the OnlyOffice services are fully ready before Nginx starts.
    • All services are connected to the onlyoffice-net network, allowing them to resolve each other by service name (onlyoffice-docs-1, onlyoffice-docs-2).
  4. Start the Services:

    sudo docker compose up -d
    
    This will pull the images and start the three containers. It might take longer as it's starting two full OnlyOffice instances.

  5. Verify Services:

    sudo docker compose ps
    
    You should see all three containers (onlyoffice-docs-1, onlyoffice-docs-2, nginx-lb) in the Up state.

  6. Test Load Balancing:

    • Access the service via the load balancer's port: http://<YOUR_SERVER_IP>:8080. You should see the OnlyOffice interface (or nothing if WOOPI_ENABLED=false).
    • Check the logs of the Nginx load balancer to see requests being distributed:
      sudo docker compose logs nginx-lb
      
      (You might need to refresh the browser page a few times). Look for access log entries showing requests being proxied.
    • Check the logs of the individual OnlyOffice instances:
      sudo docker compose logs onlyoffice-docs-1
      sudo docker compose logs onlyoffice-docs-2
      
      You should see requests hitting both instances over time as you interact with the service via the load balancer.
  7. Integrate with Frontend: When configuring your frontend (like Nextcloud), use the load balancer's URL: http://<YOUR_SERVER_IP>:8080 (or https://... if you put another reverse proxy like Caddy in front of this Nginx load balancer to handle TLS). The JWT secret remains the same one used in the compose file.

Conclusion: You have set up a basic load-balanced OnlyOffice Docs environment. Nginx distributes incoming requests across two backend instances. While this improves throughput and provides some redundancy (if one instance fails, the other can take over), remember that in this simple setup, the internal state (Redis/RabbitMQ/PostgreSQL) is not shared, which limits true collaborative session resilience across nodes. For more robust scaling and HA, externalizing and clustering these backend components is necessary.

6. Security Hardening

Securing your self-hosted OnlyOffice Docs instance is crucial to protect your documents and prevent unauthorized access. Beyond the basics of using HTTPS and a strong JWT secret, consider these additional hardening steps:

1. Secure the JWT Secret:

  • Strength: Use a long, complex, randomly generated string (e.g., openssl rand -hex 32 or a password manager).
  • Rotation: Regularly change the JWT secret key. This is a critical security practice.
    • Procedure:
      1. Generate a new secret key.
      2. Update the JWT_SECRET environment variable (or local.json setting) for all your OnlyOffice Docs instances.
      3. Restart the OnlyOffice Docs containers/services for the new secret to take effect.
      4. Immediately update the secret key in the connector settings of all integrated frontend applications (Nextcloud, etc.).
    • Frequency: The ideal frequency depends on your security policy, but rotating every 3-12 months is a reasonable practice. Automate this if possible, but ensure the update happens simultaneously on both ends to avoid service disruption.
  • Access Control: Limit who has access to view or modify the configuration where the JWT secret is stored (e.g., docker-compose.yml, environment files, server configuration management).

2. Enforce HTTPS (Reverse Proxy):

  • Mandatory: Never expose OnlyOffice Docs directly over HTTP to the internet or untrusted networks. Always use a reverse proxy (Nginx, Caddy, Apache, Traefik) to terminate TLS (HTTPS).
  • Strong TLS Configuration: Configure your reverse proxy to use strong TLS protocols (TLS 1.2 minimum, TLS 1.3 preferred) and modern cipher suites. Disable outdated protocols like SSLv3, TLS 1.0, TLS 1.1. Tools like Qualys SSL Labs' SSL Server Test can help you assess your configuration.
  • HSTS (HTTP Strict Transport Security): Implement the Strict-Transport-Security header (as shown in the Caddy workshop) to instruct browsers to only connect via HTTPS.

3. Firewall Rules:

  • Principle of Least Privilege: Only open the ports that are absolutely necessary.
    • If using a reverse proxy handling HTTPS on port 443, the host firewall should allow inbound connections on port 443 (and potentially port 80 for Let's Encrypt validation if needed).
    • The port where the OnlyOffice Docs container listens (e.g., 8080 in our examples) should not be directly exposed to the internet. It only needs to be accessible by the reverse proxy.
    • Configure your host firewall (ufw, firewalld) to block direct access to the OnlyOffice Docs container port from external networks. Allow traffic only from the reverse proxy's IP address (if running on the same host, allow from 127.0.0.1 or the Docker bridge network IP range; if on a different host, allow from that specific IP).
  • Egress Control (Advanced): Consider restricting outgoing connections from the OnlyOffice Docs container/server to only allow necessary communication (e.g., to the frontend server's callback URL, DNS servers).

4. Regular Updates:

  • OnlyOffice Docs: Keep your onlyoffice/documentserver Docker image updated. Monitor OnlyOffice release notes for security patches and updates. Pinning to specific versions (e.g., onlyoffice/documentserver:7.5.1) in production and testing updates before rolling them out is recommended over using :latest. Update regularly (e.g., docker pull onlyoffice/documentserver:<version> and docker compose up -d).
  • Host OS and Docker: Keep the underlying host operating system and Docker Engine updated with security patches.
  • Reverse Proxy: Keep your reverse proxy software (Nginx, Caddy, etc.) updated.

5. Container Security:

  • Resource Limits: Configure Docker resource limits (CPU, memory) for the OnlyOffice Docs container(s) to prevent potential denial-of-service if a container consumes excessive resources. This can be done in docker-compose.yml.
      # Example resource limits in docker-compose.yml
      onlyoffice-docs:
        # ... other settings
        deploy:
          resources:
            limits:
              cpus: '2.0' # Limit to 2 CPU cores
              memory: 8G  # Limit to 8 GB RAM
            reservations: # Optional: Guarantee minimum resources
              cpus: '1.0'
              memory: 4G
    
  • Run as Non-Root (If Possible): While the official image manages internal processes, investigate if newer versions or community modifications allow running the main container process as a non-root user for better isolation from the host. This often requires careful volume permission management.
  • Security Scanning: Use tools like Trivy or Docker Scan to scan the OnlyOffice Docs image for known vulnerabilities in its OS packages or dependencies.

6. Logging and Monitoring:

  • Centralized Logging: Ship logs from OnlyOffice Docs (mapped to the host via volumes), the reverse proxy, and the host firewall to a centralized logging system (e.g., Elasticsearch/Logstash/Kibana (ELK) stack, Graylog, Loki). This allows for easier correlation of events and security analysis.
  • Monitoring: Monitor resource usage (CPU, RAM, disk I/O), network traffic, and application health (using health check endpoints). Set up alerts for anomalies (e.g., sudden spikes in traffic, high error rates, container restarts).

7. Disable Unnecessary Features:

  • Welcome Page: The default /welcome page can reveal version information. While not a major vulnerability, it's good practice to disable it in production if not needed. This can often be done with an environment variable (e.g., WOOPI_ENABLED=false as used in previous examples) or reverse proxy rules.
  • Example Files: Ensure any example documents or test features are disabled or removed in a production environment.

By implementing these layers of security, you significantly reduce the attack surface and improve the resilience of your self-hosted OnlyOffice Docs installation. Security is an ongoing process, not a one-time setup.

Workshop Implementing Firewall Rules and JWT Rotation

Goal: Configure host firewall rules using ufw to restrict direct access to the OnlyOffice Docs container port and outline a procedure for rotating the JWT secret.

Prerequisites:

  • An OnlyOffice Docs instance running via Docker/Docker Compose, listening on a host port (e.g., 8080).
  • A reverse proxy (e.g., Caddy or Nginx running via Docker Compose, or installed directly on the host) listening on port 443 and forwarding traffic to the OnlyOffice Docs container port (8080).
  • ufw (Uncomplicated Firewall) installed on the host Linux system (common on Ubuntu/Debian). If using CentOS/RHEL, adapt commands for firewalld.
  • sudo privileges.

Part 1: Implementing Firewall Rules with ufw

Scenario:

  • Reverse Proxy (Caddy/Nginx) listens on host ports 80 and 443.
  • OnlyOffice Docs container is mapped to host port 8080.
  • We want to allow public access to ports 80 (for HTTP redirect/ACME) and 443 (HTTPS).
  • We want to block all external access to port 8080.
  • We need to ensure the reverse proxy (running locally) can still access port 8080.

Steps:

  1. Check ufw Status:

    sudo ufw status verbose
    
    If it's inactive, enable it. Warning: Enabling the firewall without proper 'allow' rules can lock you out of SSH. Ensure SSH is allowed first!
    sudo ufw allow ssh # Or use specific port number, e.g., 'allow 22/tcp'
    sudo ufw enable
    
    Confirm the prompt by typing y.

  2. Allow Standard Web Ports: Allow incoming traffic on ports 80 and 443 from anywhere.

    sudo ufw allow http  # Equivalent to 'allow 80/tcp'
    sudo ufw allow https # Equivalent to 'allow 443/tcp'
    

  3. Identify Docker Network (If Proxy is Containerized): If your reverse proxy (like Caddy/Nginx in our Docker Compose examples) runs in a Docker container, it accesses the OnlyOffice container port (8080) via the Docker bridge network, not necessarily localhost (127.0.0.1). Find the Docker network's subnet used by your compose setup.

    docker network ls # List networks
    # Find the network used by your compose file (e.g., 'onlyoffice-secure_onlyoffice-net')
    docker network inspect <your_compose_network_name> | grep Subnet
    
    Look for the IPv4 subnet, for example "Subnet": "172.20.0.0/16". Note this subnet.

  4. Allow Access to Port 8080 ONLY from Reverse Proxy:

    • Option A: Proxy on Host (Not Docker): If Nginx/Caddy runs directly on the host, allow access only from localhost.
      sudo ufw allow from 127.0.0.1 to any port 8080 proto tcp
      
    • Option B: Proxy in Docker Container (Recommended): Allow access only from the Docker network subnet identified in the previous step. Replace 172.20.0.0/16 with your actual subnet.
      sudo ufw allow from 172.20.0.0/16 to any port 8080 proto tcp
      
      Explanation: This rule allows any IP address within the specified Docker subnet (172.20.0.0/16) to connect to any IP on the host on port 8080 via TCP. This ensures the containerized proxy can reach the containerized OnlyOffice Docs.
  5. Explicitly Deny External Access to 8080 (Optional but Good Practice): While ufw's default policy is often DENY, you can add an explicit deny rule for clarity or if your default policy is ALLOW. This rule should have lower precedence (or be added after allow rules). ufw usually handles precedence reasonably well.

    # This might be redundant if your default incoming policy is DENY
    # sudo ufw deny 8080/tcp
    
    It's generally better to rely on a default DENY policy and only add specific ALLOW rules.

  6. Verify Rules:

    sudo ufw status numbered
    
    Review the rules list. You should see rules allowing SSH, HTTP, HTTPS from anywhere, and a rule allowing traffic from your internal Docker network (or localhost) to port 8080. There should not be a general 'allow 8080' rule.

  7. Test:

    • Try accessing https://onlyoffice.yourdomain.com (via the proxy) - it should work.
    • Try accessing http://<YOUR_SERVER_IP>:8080 directly from an external machine (e.g., your laptop) - it should be blocked (timeout or connection refused).

Part 2: Procedure for JWT Secret Rotation

Goal: Outline the manual steps to rotate the JWT secret for OnlyOffice Docs and a connected Nextcloud instance.

Steps:

  1. Generate New Secret: Create a new, strong, random secret key.

    openssl rand -hex 32
    
    Copy this new secret. Let's call it NEW_SECRET_KEY.

  2. Update OnlyOffice Docs Configuration:

    • If using docker-compose.yml:
      • Edit your docker-compose.yml file.
      • Find the environment section for your OnlyOffice Docs service(s).
      • Update the JWT_SECRET value to the NEW_SECRET_KEY.
      • Save the file.
    • If using docker run with -e: You'll need to stop the container, remove it, and run it again with the updated -e JWT_SECRET=NEW_SECRET_KEY flag.
    • If configured via local.json: Edit the local.json file on your host (if volume mapped), update the relevant JWT secret field, and save.
  3. Restart OnlyOffice Docs Service(s): Apply the configuration change.

    • If using docker-compose.yml:
      cd /path/to/your/compose/file
      sudo docker compose up -d --force-recreate onlyoffice-docs # Or specific service name(s) if scaled
      
      (Using --force-recreate ensures the container picks up the new environment variable from the compose file. A simple restart might not be sufficient for environment variable changes.)
    • If using docker run: Execute the updated docker run command after stopping/removing the old container.
    • If configured via local.json:
      sudo docker restart onlyoffice-docs # Or container name(s)
      
  4. IMMEDIATELY Update Frontend Connector(s):

    • Log in to your Nextcloud instance as an administrator.
    • Go to Administration Settings -> ONLYOFFICE.
    • Paste the NEW_SECRET_KEY into the "Secret key" field.
    • (Important) Also update the secret in the "Advanced server settings" section if you previously entered it there.
    • Click "Save".
  5. Test Integration:

    • Open a document in Nextcloud. It should load correctly using the new JWT secret.
    • Check OnlyOffice Docs logs (docker compose logs onlyoffice-docs or docker logs onlyoffice-docs) - specifically the docservice logs (/var/log/onlyoffice/documentserver/docservice/out.log inside the container) - to ensure there are no JWT validation errors.

Automation Considerations:

Manually rotating keys, especially with multiple frontends or scaled backends, is error-prone. Consider scripting this process using configuration management tools (Ansible, Salt, Chef, Puppet) or custom scripts that can:

  • Generate a new key.
  • Use Docker API/CLI or SSH to update the backend configuration and restart services.
  • Use Nextcloud's occ command-line tool (or its API, if available) to update the connector settings non-interactively.
  • Perform health checks after the rotation.

Conclusion: You have hardened your server by restricting direct access to the OnlyOffice Docs port using ufw and established a clear procedure for rotating the critical JWT secret. Regularly performing this rotation significantly enhances security.

7. Troubleshooting Common Issues

Even with careful setup, issues can arise. Knowing how to diagnose and fix common problems is essential for maintaining a reliable OnlyOffice Docs service.

General Troubleshooting Strategy:

  1. Identify the Scope: Is the problem affecting all users or just one? All documents or specific types/sizes? Did it start after a specific change (update, configuration change)?
  2. Check Connectivity:
    • Can the user's browser resolve and reach the OnlyOffice Docs URL (via the reverse proxy)?
    • Can the frontend server (e.g., Nextcloud) reach the OnlyOffice Docs URL (publicly or internally)? Use curl from the frontend server/container.
    • Can the OnlyOffice Docs server reach the frontend server's callback URL? Use curl from the Docs container. Check firewalls.
  3. Inspect Logs: This is the most crucial step. Check logs from:
    • OnlyOffice Docs Container:
      • /var/log/onlyoffice/documentserver/docservice/out.log (or err.log): Core document service logs, including JWT errors, save errors, connection issues with Redis/RabbitMQ.
      • /var/log/onlyoffice/documentserver/converter/out.log: Document conversion errors.
      • /var/log/onlyoffice/documentserver/nginx.error.log: Internal Nginx errors within the container.
      • /var/log/onlyoffice/supervisor/: Logs related to process management within the container.
      • Access via docker logs <container_name> or directly in the volume mounts (e.g., /app/onlyoffice/DocumentServer/logs/...).
    • Reverse Proxy: Nginx/Caddy/Apache error logs and access logs. Look for connection errors to the backend (OnlyOffice Docs port), TLS handshake errors, 5xx errors.
    • Frontend Application: Nextcloud logs (data/nextcloud.log), connector app specific logs (if any). Look for errors related to connecting to the Docs server or processing callbacks.
    • Browser Developer Console: Open the browser's developer tools (F12), check the "Console" for JavaScript errors and the "Network" tab for failing HTTP requests (e.g., 4xx, 5xx errors, CORS issues, mixed content warnings) when trying to load the editor.
  4. Check Resource Usage: Monitor CPU, RAM, and disk I/O on the host server and within the container (docker stats <container_name>). Insufficient resources, especially RAM, are a common cause of instability and errors.
  5. Verify Configuration: Double-check:
    • JWT Secret (exact match between Docs server and frontend connector).
    • OnlyOffice Docs URL configured in the frontend connector (correct HTTPS URL, no typos).
    • Internal/Public URL settings if used.
    • Reverse proxy configuration (correct backend host/port, necessary headers).

Common Problems and Solutions:

  1. "Error when trying to connect" (in Frontend Connector):

    • Cause: Network issue, firewall block, DNS resolution failure, Docs server not running, incorrect URL.
    • Troubleshoot:
      • Verify Docs container is running (docker ps).
      • Check Docs logs for startup errors (docker logs onlyoffice-docs).
      • Verify the URL in the connector settings is correct (HTTPS, domain).
      • Use curl <OnlyOffice_Docs_URL>/healthcheck from the frontend server/container. It should return "true" or similar success indication. If curl fails, diagnose network/firewall/DNS issues between frontend and backend. Check reverse proxy logs.
  2. Document Editor Doesn't Load (Blank page, Spinner, Error Message):

    • Cause: JWT error, browser connectivity issue, JavaScript error, reverse proxy misconfiguration, resource exhaustion.
    • Troubleshoot:
      • Browser Console (F12): Check for JavaScript errors, failed network requests (often to /doc/... or WebSocket endpoints). Look for CORS errors or mixed content warnings.
      • OnlyOffice docservice Logs: Check for JWT validation errors (Invalid token). Verify the secret key again.
      • Reverse Proxy Logs: Check for errors proxying requests to the Docs backend. Ensure WebSockets are correctly proxied if your proxy requires specific configuration for them (Nginx often needs proxy_http_version 1.1;, proxy_set_header Upgrade $http_upgrade;, proxy_set_header Connection "upgrade";). Caddy usually handles this automatically.
      • Resource Usage: Check docker stats for high RAM/CPU usage on the onlyoffice-docs container.
  3. JWT Errors ("Invalid token", "Unauthorized"):

    • Cause: Mismatched secret key, JWT disabled on Docs server, incorrect JWT header expectation, token expired (less common unless custom logic).
    • Troubleshoot:
      • Verify Secret: The most common cause. Ensure the secret in the Docs server environment/config exactly matches the secret in the frontend connector. Copy-paste carefully.
      • Verify JWT_ENABLED=true: Ensure this environment variable is set for the Docs container.
      • Verify JWT Header: Ensure the frontend connector sends the token in the header expected by OnlyOffice Docs (usually Authorization: Bearer <token>). Check docservice logs for details on how the token was received (or if it was missing).
      • Restart Services: Restart both OnlyOffice Docs and potentially the frontend application after ensuring secrets match.
  4. Font Issues (Incorrect Rendering, Missing Characters, "Square Boxes"):

    • Cause: Required fonts are not available to the OnlyOffice Docs server. The container comes with a basic set, but specific documents might require additional fonts (e.g., Microsoft core fonts, CJK fonts).
    • Troubleshoot:
      • Install Fonts: The recommended way is to mount a host directory containing .ttf or .otf font files into the container's font directory and run a script to update the font cache.
        1. Create a font directory on the host: sudo mkdir -p /app/onlyoffice/DocumentServer/fonts
        2. Copy required .ttf/.otf files into this directory. (e.g., download msttcorefonts installer package, extract fonts, or copy from a Windows system /Windows/Fonts). Be mindful of font licensing.
        3. Add volume mount to docker-compose.yml or docker run: -v /app/onlyoffice/DocumentServer/fonts:/usr/share/fonts/truetype/custom (or another appropriate path inside /usr/share/fonts).
        4. Run the font update tool inside the container after starting: docker exec onlyoffice-docs documentserver-generate-allfonts.sh
        5. Restart the container: docker restart onlyoffice-docs (or docker compose restart onlyoffice-docs).
      • Check converter logs for font-related errors during document opening/saving.
  5. Performance Issues (Slow loading, laggy editing):

    • Cause: Insufficient CPU/RAM/IO resources, network latency, inefficient reverse proxy config, complex documents, too many simultaneous users for available resources.
    • Troubleshoot:
      • Monitor Resources: Use top, htop, iotop on the host; docker stats for containers. Identify bottlenecks.
      • Increase Resources: Allocate more RAM/CPU to the Docker container/host VM.
      • Optimize Reverse Proxy: Ensure caching (if applicable), compression, and efficient connection handling are configured.
      • Scaling: Consider load balancing across multiple instances (see previous section).
      • Network: Check latency between user->proxy, proxy->backend, backend->frontend.
      • Check docservice and converter logs: Look for warnings about long processing times.
  6. File Saving Issues ("Error saving document"):

    • Cause: Connectivity issue between Docs server and frontend callback URL, permissions error on the frontend storage, locking issues, JWT error during callback.
    • Troubleshoot:
      • Verify Callback Connectivity: Ensure the Docs server container can reach the frontend's URL (internal or public). Use curl from the Docs container. Check firewalls.
      • Frontend Logs: Check Nextcloud/ownCloud logs for errors related to file locking, permissions, or callback handling.
      • OnlyOffice docservice Logs: Look for errors related to the save callback request (Error CURLE_COULDNT_CONNECT, Callback process error, JWT errors during callback).
      • File System Permissions: Ensure the web server user on the frontend (e.g., www-data) has write permissions to the underlying storage location.

Effective troubleshooting involves systematically checking potential failure points, correlating information from different log sources, and understanding the interaction flow between the browser, frontend, reverse proxy, and OnlyOffice Docs server.

Workshop Analyzing Logs and Resolving a Connection Error

Goal: Simulate a common integration problem (incorrect Docs server URL in frontend), use logs to diagnose it, and apply the fix.

Prerequisites:

  • A working setup with Nextcloud integrated with OnlyOffice Docs via a reverse proxy (as per previous workshops).
  • Access to Nextcloud admin settings.
  • Access to the server terminal to view Docker container logs.

Scenario: The integration was working, but now users report documents won't open. We suspect a configuration issue.

Steps:

  1. Simulate the Problem:

    • Log in to Nextcloud as an administrator.
    • Go to Administration Settings -> ONLYOFFICE.
    • In the "ONLYOFFICE Docs address" field, introduce a typo. Change https://onlyoffice.yourdomain.com to https://onlyffice.yourdomain.com (note the missing 'o').
    • Click "Save". You will likely see an immediate error message like "Error when trying to connect", but let's assume for the workshop that sometimes the save happens but the use fails later.
    • Navigate to the Files app and try to open a .docx file.
    • Expected Failure: The editor fails to load. You might see a perpetual spinner, a Nextcloud error message, or a browser error page within the frame.
  2. Initial Checks (User Perspective):

    • Confirm the failure: The editor doesn't load.
    • Open Browser Developer Tools (F12) -> Network Tab. Reload the page/retry opening the document. Look for failing requests related to onlyffice.yourdomain.com. You'll likely see DNS resolution errors (e.g., ERR_NAME_NOT_RESOLVED) or connection timeouts for requests trying to reach the incorrect domain. This immediately points towards a URL issue.
    • Check the Console tab for related errors.
  3. Check Frontend Logs (Nextcloud):

    • Access your Nextcloud server (SSH or file access).
    • Locate the Nextcloud log file (usually in the Nextcloud data directory, e.g., /path/to/nextcloud/data/nextcloud.log).
    • View the end of the log file: tail -n 100 /path/to/nextcloud/data/nextcloud.log (adjust path).
    • Expected Logs: Look for errors logged around the time you tried to open the document. You might see messages indicating:
      • Failure to connect to the configured Document Server URL (https://onlyffice.yourdomain.com).
      • DNS resolution errors for onlyffice.yourdomain.com.
      • Timeout errors when attempting to contact the server.
      • Example (conceptual): {"reqId":"...","level":3,"time":"...","remoteAddr":"...","user":"...","app":"onlyoffice","method":"GET","url":"/apps/onlyoffice/ajax/config/status","message":"Exception: Error occurred in request callback: cURL error 6: Could not resolve host: onlyffice.yourdomain.com (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for https://onlyffice.yourdomain.com/healthcheck"}
  4. Check Reverse Proxy Logs (Optional in this case, but good practice):

    • If the error wasn't DNS resolution but a connection refused/timeout after DNS resolution (e.g., if the IP was correct but port wrong, or firewall blocked), the reverse proxy logs might show errors trying to connect upstream. In our typo scenario, the request likely won't even reach the proxy.
    • Check Caddy logs: sudo docker compose logs caddy
    • Check Nginx logs: sudo docker compose logs nginx-lb (or check /var/log/nginx/error.log if installed on host).
  5. Check OnlyOffice Docs Logs (Less Relevant for this specific error):

    • Since the connection from Nextcloud to the Docs server is failing due to the bad URL, the OnlyOffice Docs logs (docservice, etc.) likely won't show any relevant error messages for this specific failure, because the requests aren't reaching it.
    • Access logs: sudo docker compose logs onlyoffice-docs or sudo docker logs onlyoffice-docs. You would not expect to see incoming requests related to the failed document open attempt.
  6. Diagnosis:

    • The browser developer tools clearly showed failed network requests to https://onlyffice.yourdomain.com due to ERR_NAME_NOT_RESOLVED.
    • The Nextcloud logs confirmed connection/DNS resolution errors when trying to reach https://onlyffice.yourdomain.com.
    • This strongly indicates the "ONLYOFFICE Docs address" configured in Nextcloud is incorrect.
  7. Apply the Fix:

    • Go back to Nextcloud Administration Settings -> ONLYOFFICE.
    • Correct the typo in the "ONLYOFFICE Docs address" field. Change https://onlyffice.yourdomain.com back to https://onlyoffice.yourdomain.com.
    • Enter the JWT Secret again (sometimes required on save).
    • Click "Save". This time, it should save without error (or show success indicators).
  8. Verify the Fix:

    • Go back to the Files app in Nextcloud.
    • Try opening the same .docx file again.
    • Expected Result: The OnlyOffice editor should now load correctly.

Conclusion: By systematically checking logs starting from the client (browser) and moving towards the backend (Nextcloud logs), we quickly identified that the connection failure was due to an incorrect URL configured in the frontend application. This workshop demonstrates a typical troubleshooting workflow: observe the failure, check relevant logs (browser, frontend, proxy, backend), diagnose the root cause based on error messages, apply the fix, and verify the resolution.

Conclusion

Self-hosting OnlyOffice Docs provides a powerful, private, and cost-effective solution for online document editing and collaboration. Throughout this guide, we've journeyed from the fundamental architecture to advanced deployment and security considerations.

We began by understanding the components of OnlyOffice Docs and how it interacts with frontend platforms, emphasizing the critical role of JWT for security. The Basic section guided you through setting up Docker and deploying your first instance using simple commands, establishing a foundation.

In the Intermediate section, we enhanced the setup by exploring configuration via local.json and Docker Compose, implementing persistent storage, and crucially, securing the deployment with HTTPS using a reverse proxy like Caddy. We then walked through the vital step of integrating the secure Docs server with a popular frontend, Nextcloud.

The Advanced section tackled scalability, discussing the principles of load balancing and the complexities of achieving high availability, particularly concerning shared backend services like Redis, RabbitMQ, and PostgreSQL. We explored security hardening techniques beyond the basics, including firewall rules, regular updates, container security, and the essential practice of JWT secret rotation. Finally, we addressed common troubleshooting scenarios, outlining a systematic approach involving log analysis across the entire stack – browser, frontend, reverse proxy, and the Docs server itself – culminating in practical workshops to diagnose and resolve typical issues.

By mastering these concepts and practices, you gain control over your collaborative document editing environment, ensuring data sovereignty and tailoring the solution to your specific needs. Remember that self-hosting is an ongoing responsibility that requires regular maintenance, updates, and security vigilance. However, the benefits of a private, customizable, and potentially more economical office suite backend are substantial.

Continue exploring the official OnlyOffice documentation, engage with the community forums, and experiment with different configurations to further deepen your understanding and optimize your deployment. Happy self-hosting!