OnlyOffice: Self-Hosted Document Suite
Microsoft Office-compatible document editing. Integration with Nextcloud and other platforms.
Introduction
ONLYOFFICE Document Server is a powerful, self-hosted office suite that provides comprehensive document editing capabilities for your homelab. Think of it as your own private Microsoft Office 365 or Google Workspace, but running entirely on your infrastructure with complete data control.
What is ONLYOFFICE?
ONLYOFFICE Document Server is an open-source office suite that enables viewing, editing, and collaborative editing of text documents, spreadsheets, and presentations directly in your web browser. It supports all major Microsoft Office formats including DOCX, XLSX, and PPTX, making it a seamless replacement for cloud-based office suites.
Why Self-Host ONLYOFFICE?
Complete Data Privacy
When you self-host ONLYOFFICE, every document stays on your infrastructure. There’s no third-party accessing your sensitive business plans, financial spreadsheets, or personal documents. This is particularly crucial for businesses handling confidential information or individuals concerned about privacy.
Zero Licensing Costs
Microsoft 365 costs $6-22 per user per month. Google Workspace ranges from $6-18 per user per month. For a small team of 5 users, you’re looking at $360-1,320 annually. ONLYOFFICE Community Edition is completely free for self-hosting, with unlimited users.
Real-Time Collaboration
Multiple users can edit the same document simultaneously with real-time updates. Changes appear instantly for all collaborators, complete with user cursors, comments, and tracked changes - just like Google Docs.
Microsoft Office Compatibility
ONLYOFFICE provides the highest fidelity Microsoft Office format support among open-source alternatives. Complex documents with formatting, macros, and embedded objects maintain their structure better than other solutions.
ONLYOFFICE vs Alternatives
| Feature | ONLYOFFICE | Collabora | LibreOffice Online | Microsoft 365 |
|---|---|---|---|---|
| MS Office Compatibility | Excellent | Good | Fair | Perfect |
| Real-time Collaboration | Yes | Yes | Limited | Yes |
| Self-Hosted | Yes | Yes | Yes | No |
| Cost (5 users) | Free | Free | Free | $360-1,100/year |
| Mobile Editing | Yes | Yes | Limited | Yes |
| Nextcloud Integration | Excellent | Excellent | Good | N/A |
| Performance | Fast | Medium | Medium | Fast |
Architecture Overview
Understanding the ONLYOFFICE architecture helps you deploy and troubleshoot effectively:
┌─────────────────────────────────────────────┐
│ Users (Web Browsers) │
└────────────────┬────────────────────────────┘
│
┌──────▼──────┐
│ Reverse Proxy│ (Nginx/Traefik)
│ + SSL │
└──────┬──────┘
│
┌────────────┼────────────┐
│ │ │
┌───▼────┐ ┌───▼─────┐ ┌──▼──────┐
│Nextcloud│ │ONLYOFFICE│ │ Other │
│ or │ │ Document │ │ Apps │
│Platform │ │ Server │ │ │
└───┬────┘ └────┬─────┘ └────────┘
│ │
└────────────┼────────────┐
│ │
┌──────▼──────┐ ┌──▼──────┐
│ PostgreSQL │ │ RabbitMQ│
│ (Optional) │ │(Optional)│
└─────────────┘ └─────────┘ Components:
- Document Server: Core service handling document editing, conversion, and collaboration
- Nextcloud/Integration Platform: File management system that stores documents
- PostgreSQL: Database for document history and collaboration data (optional, for production)
- RabbitMQ: Message queue for handling concurrent editing sessions (optional, for production)
- Reverse Proxy: HTTPS termination and routing
Prerequisites
Before deploying ONLYOFFICE, ensure you have:
- Docker and Docker Compose installed
- 4GB RAM minimum (8GB recommended for production)
- 2 CPU cores minimum
- 20GB storage space
- Domain name with DNS access (for SSL certificates)
- Basic understanding of Docker networking
- Reverse proxy setup (Nginx, Traefik, or Caddy)
Basic Deployment: Standalone ONLYOFFICE
Let’s start with a basic ONLYOFFICE deployment that can be integrated with various platforms.
Step 1: Create Project Directory
# Create directory structure
mkdir -p ~/onlyoffice && cd ~/onlyoffice
# Create environment file
cat > .env <<EOF
# ONLYOFFICE Configuration
ONLYOFFICE_JWT_SECRET=your-super-secret-jwt-token-change-this
ONLYOFFICE_JWT_HEADER=Authorization
# PostgreSQL Configuration (optional)
POSTGRES_DB=onlyoffice
POSTGRES_USER=onlyoffice
POSTGRES_PASSWORD=your-secure-postgres-password
# Domain Configuration
DOMAIN=office.yourdomain.com
EOF
# Secure the environment file
chmod 600 .env Step 2: Basic Docker Compose Configuration
Create docker-compose.yml:
version: '3.8'
services:
onlyoffice:
image: onlyoffice/documentserver:latest
container_name: onlyoffice-documentserver
restart: unless-stopped
environment:
# JWT Configuration for security
- JWT_ENABLED=true
- JWT_SECRET=${ONLYOFFICE_JWT_SECRET}
- JWT_HEADER=${ONLYOFFICE_JWT_HEADER}
# Performance settings
- WOPI_ENABLED=false
- USE_UNAUTHORIZED_STORAGE=false
ports:
- "8080:80"
volumes:
# Persist data, logs, and configuration
- onlyoffice_data:/var/www/onlyoffice/Data
- onlyoffice_logs:/var/log/onlyoffice
- onlyoffice_cache:/var/lib/onlyoffice
- onlyoffice_fonts:/usr/share/fonts
networks:
- onlyoffice-net
volumes:
onlyoffice_data:
onlyoffice_logs:
onlyoffice_cache:
onlyoffice_fonts:
networks:
onlyoffice-net:
driver: bridge Step 3: Launch ONLYOFFICE
# Start the service
docker-compose up -d
# Check logs
docker-compose logs -f onlyoffice
# Verify it's running
curl http://localhost:8080/healthcheck Access ONLYOFFICE at http://localhost:8080 - you should see a welcome screen.
Production Deployment with PostgreSQL
For production use with better performance and scalability, add PostgreSQL:
version: '3.8'
services:
# PostgreSQL Database
postgresql:
image: postgres:15-alpine
container_name: onlyoffice-postgres
restart: unless-stopped
environment:
- POSTGRES_DB=${POSTGRES_DB}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
volumes:
- postgresql_data:/var/lib/postgresql/data
networks:
- onlyoffice-net
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
interval: 10s
timeout: 5s
retries: 5
# RabbitMQ for message queuing
rabbitmq:
image: rabbitmq:3-management-alpine
container_name: onlyoffice-rabbitmq
restart: unless-stopped
environment:
- RABBITMQ_DEFAULT_USER=onlyoffice
- RABBITMQ_DEFAULT_PASS=${ONLYOFFICE_JWT_SECRET}
volumes:
- rabbitmq_data:/var/lib/rabbitmq
networks:
- onlyoffice-net
healthcheck:
test: ["CMD", "rabbitmq-diagnostics", "ping"]
interval: 10s
timeout: 5s
retries: 5
# ONLYOFFICE Document Server
onlyoffice:
image: onlyoffice/documentserver:latest
container_name: onlyoffice-documentserver
restart: unless-stopped
depends_on:
postgresql:
condition: service_healthy
rabbitmq:
condition: service_healthy
environment:
# Database Configuration
- DB_TYPE=postgres
- DB_HOST=postgresql
- DB_PORT=5432
- DB_NAME=${POSTGRES_DB}
- DB_USER=${POSTGRES_USER}
- DB_PWD=${POSTGRES_PASSWORD}
# RabbitMQ Configuration
- AMQP_URI=amqp://onlyoffice:${ONLYOFFICE_JWT_SECRET}@rabbitmq
# JWT Configuration
- JWT_ENABLED=true
- JWT_SECRET=${ONLYOFFICE_JWT_SECRET}
- JWT_HEADER=${ONLYOFFICE_JWT_HEADER}
# Performance Tuning
- WOPI_ENABLED=false
- USE_UNAUTHORIZED_STORAGE=false
ports:
- "8080:80"
volumes:
- onlyoffice_data:/var/www/onlyoffice/Data
- onlyoffice_logs:/var/log/onlyoffice
- onlyoffice_cache:/var/lib/onlyoffice
- onlyoffice_fonts:/usr/share/fonts
networks:
- onlyoffice-net
volumes:
postgresql_data:
rabbitmq_data:
onlyoffice_data:
onlyoffice_logs:
onlyoffice_cache:
onlyoffice_fonts:
networks:
onlyoffice-net:
driver: bridge Nextcloud Integration
One of ONLYOFFICE’s most powerful features is seamless integration with Nextcloud. Here’s how to set it up.
Option 1: Using Docker Compose Network
If you’re running Nextcloud in Docker, add ONLYOFFICE to the same network:
# In your Nextcloud docker-compose.yml, add the network
networks:
nextcloud-net:
external: true
# In your ONLYOFFICE docker-compose.yml
networks:
onlyoffice-net:
external: true
name: nextcloud_nextcloud-net Option 2: Complete Nextcloud + ONLYOFFICE Stack
Here’s a complete stack with both services:
version: '3.8'
services:
# MariaDB for Nextcloud
nextcloud-db:
image: mariadb:11
container_name: nextcloud-db
restart: unless-stopped
command: --transaction-isolation=READ-COMMITTED --log-bin=binlog --binlog-format=ROW
environment:
- MYSQL_ROOT_PASSWORD=secure-root-password
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_PASSWORD=secure-nextcloud-password
volumes:
- nextcloud_db:/var/lib/mysql
networks:
- collaboration-net
# Redis Cache
nextcloud-redis:
image: redis:7-alpine
container_name: nextcloud-redis
restart: unless-stopped
networks:
- collaboration-net
# Nextcloud
nextcloud:
image: nextcloud:29-fpm-alpine
container_name: nextcloud
restart: unless-stopped
depends_on:
- nextcloud-db
- nextcloud-redis
- onlyoffice
environment:
- MYSQL_HOST=nextcloud-db
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_PASSWORD=secure-nextcloud-password
- REDIS_HOST=nextcloud-redis
volumes:
- nextcloud_app:/var/www/html
- nextcloud_data:/var/www/html/data
networks:
- collaboration-net
# Nextcloud Web Server
nextcloud-web:
image: nginx:alpine
container_name: nextcloud-web
restart: unless-stopped
depends_on:
- nextcloud
ports:
- "8081:80"
volumes:
- nextcloud_app:/var/www/html:ro
- ./nextcloud-nginx.conf:/etc/nginx/nginx.conf:ro
networks:
- collaboration-net
# PostgreSQL for ONLYOFFICE
onlyoffice-db:
image: postgres:15-alpine
container_name: onlyoffice-db
restart: unless-stopped
environment:
- POSTGRES_DB=onlyoffice
- POSTGRES_USER=onlyoffice
- POSTGRES_PASSWORD=secure-onlyoffice-password
volumes:
- onlyoffice_db:/var/lib/postgresql/data
networks:
- collaboration-net
# ONLYOFFICE Document Server
onlyoffice:
image: onlyoffice/documentserver:latest
container_name: onlyoffice
restart: unless-stopped
depends_on:
- onlyoffice-db
environment:
- DB_TYPE=postgres
- DB_HOST=onlyoffice-db
- DB_PORT=5432
- DB_NAME=onlyoffice
- DB_USER=onlyoffice
- DB_PWD=secure-onlyoffice-password
- JWT_ENABLED=true
- JWT_SECRET=your-jwt-secret-token
- JWT_HEADER=Authorization
ports:
- "8080:80"
volumes:
- onlyoffice_data:/var/www/onlyoffice/Data
- onlyoffice_logs:/var/log/onlyoffice
networks:
- collaboration-net
volumes:
nextcloud_db:
nextcloud_app:
nextcloud_data:
onlyoffice_db:
onlyoffice_data:
onlyoffice_logs:
networks:
collaboration-net:
driver: bridge Configure Nextcloud Integration
After both services are running:
# Install ONLYOFFICE app in Nextcloud
docker exec -u www-data nextcloud php occ app:install onlyoffice
# Configure ONLYOFFICE server URL
docker exec -u www-data nextcloud php occ config:system:set onlyoffice DocumentServerUrl --value="http://onlyoffice/"
# Set JWT secret (must match ONLYOFFICE configuration)
docker exec -u www-data nextcloud php occ config:app:set onlyoffice jwt_secret --value="your-jwt-secret-token"
# Enable JWT verification
docker exec -u www-data nextcloud php occ config:app:set onlyoffice jwt_header --value="Authorization" Alternatively, configure via web UI:
- Log into Nextcloud as admin
- Go to Settings > Administration > ONLYOFFICE
- Enter Document Server address:
http://onlyoffice/ - Enter JWT Secret:
your-jwt-secret-token - Click Save
Now when you open any Office document in Nextcloud, it will open in ONLYOFFICE!
Reverse Proxy Setup
For production deployment with HTTPS, configure your reverse proxy.
Nginx Configuration
# /etc/nginx/sites-available/onlyoffice.conf
upstream onlyoffice {
server localhost:8080;
}
server {
listen 80;
server_name office.yourdomain.com;
# Redirect to HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name office.yourdomain.com;
# SSL Configuration
ssl_certificate /etc/letsencrypt/live/office.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/office.yourdomain.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
# Increase upload size for documents
client_max_body_size 100M;
# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
location / {
proxy_pass http://onlyoffice;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket support
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
} Traefik Configuration (Labels)
Add these labels to your ONLYOFFICE service:
services:
onlyoffice:
# ... other configuration ...
labels:
- "traefik.enable=true"
- "traefik.http.routers.onlyoffice.rule=Host(`office.yourdomain.com`)"
- "traefik.http.routers.onlyoffice.entrypoints=websecure"
- "traefik.http.routers.onlyoffice.tls.certresolver=letsencrypt"
- "traefik.http.services.onlyoffice.loadbalancer.server.port=80"
# WebSocket support
- "traefik.http.middlewares.onlyoffice-headers.headers.customrequestheaders.X-Forwarded-Proto=https" Caddy Configuration
office.yourdomain.com {
reverse_proxy onlyoffice:80 {
header_up X-Forwarded-Proto {scheme}
header_up X-Forwarded-For {remote}
}
} Performance Tuning
Optimize ONLYOFFICE for better performance in your homelab.
Memory and CPU Optimization
Create a custom configuration file:
# Create custom configuration directory
mkdir -p ./onlyoffice-config
# Create local.json configuration
cat > ./onlyoffice-config/local.json <<EOF
{
"services": {
"CoAuthoring": {
"sql": {
"max_allowed_packet": 1048575
},
"redis": {
"name": "redis",
"host": "redis",
"port": 6379
},
"server": {
"port": 8000,
"workerpercpu": 1
},
"autoAssembly": {
"enable": true,
"interval": "5m"
}
}
},
"queue": {
"visibilityTimeout": 300,
"retentionPeriod": 900
},
"storage": {
"fs": {
"secretString": "your-secret-string"
}
}
}
EOF Add Redis for caching:
services:
# Redis cache for ONLYOFFICE
redis:
image: redis:7-alpine
container_name: onlyoffice-redis
restart: unless-stopped
command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru
networks:
- onlyoffice-net
onlyoffice:
# ... other configuration ...
depends_on:
- redis
volumes:
- ./onlyoffice-config/local.json:/etc/onlyoffice/documentserver/local.json Concurrent Users Optimization
For handling multiple simultaneous editors:
# Enter the ONLYOFFICE container
docker exec -it onlyoffice-documentserver bash
# Edit configuration
nano /etc/onlyoffice/documentserver/local.json Add these settings:
{
"services": {
"CoAuthoring": {
"server": {
"edit_singleton": false
},
"requestDefaults": {
"timeout": 120000
}
}
},
"FileConverter": {
"converter": {
"maxDownloadBytes": 104857600,
"downloadTimeout": 120000
}
}
} Font Installation for Better Compatibility
Add custom fonts for better document rendering:
# Create fonts directory
mkdir -p ./custom-fonts
# Download Microsoft fonts (if licensed)
# Or use open alternatives like Liberation fonts
# Add to docker-compose.yml
volumes:
- ./custom-fonts:/usr/share/fonts/truetype/custom:ro Then regenerate font cache:
docker exec onlyoffice-documentserver fc-cache -f -v
docker restart onlyoffice-documentserver Security Hardening
Enable JWT Authentication
JWT (JSON Web Token) is essential for security. Always enable it:
environment:
- JWT_ENABLED=true
- JWT_SECRET=your-super-long-random-secret-at-least-32-characters
- JWT_HEADER=Authorization
- JWT_IN_BODY=true Generate a secure JWT secret:
openssl rand -hex 32 Firewall Configuration
Restrict access to ONLYOFFICE:
# Allow only from your network
sudo ufw allow from 192.168.1.0/24 to any port 8080
# Or allow through reverse proxy only
sudo ufw deny 8080 Regular Updates
Keep ONLYOFFICE updated:
# Pull latest image
docker-compose pull onlyoffice
# Recreate container
docker-compose up -d onlyoffice
# Check version
docker exec onlyoffice-documentserver documentserver-version.sh Monitoring and Maintenance
Health Checks
Monitor ONLYOFFICE health:
# Health check endpoint
curl http://localhost:8080/healthcheck
# Expected response: {"status":"OK"}
# Detailed status
docker exec onlyoffice-documentserver supervisorctl status Log Management
Access and manage logs:
# View all logs
docker-compose logs -f onlyoffice
# View specific service logs
docker exec onlyoffice-documentserver tail -f /var/log/onlyoffice/documentserver/converter/out.log
docker exec onlyoffice-documentserver tail -f /var/log/onlyoffice/documentserver/docservice/out.log
# Clear old logs
docker exec onlyoffice-documentserver find /var/log/onlyoffice -name "*.log" -mtime +30 -delete Backup Strategy
Backup important data:
# Create backup script
cat > ~/onlyoffice-backup.sh <<'EOF'
#!/bin/bash
BACKUP_DIR="/mnt/backups/onlyoffice"
DATE=$(date +%Y%m%d_%H%M%S)
# Backup volumes
docker run --rm -v onlyoffice_onlyoffice_data:/data:ro -v $BACKUP_DIR:/backup alpine tar czf /backup/onlyoffice-data-$DATE.tar.gz -C /data .
# Backup database if using PostgreSQL
docker exec onlyoffice-postgres pg_dump -U onlyoffice onlyoffice > $BACKUP_DIR/onlyoffice-db-$DATE.sql
# Remove backups older than 30 days
find $BACKUP_DIR -name "*.tar.gz" -mtime +30 -delete
find $BACKUP_DIR -name "*.sql" -mtime +30 -delete
echo "Backup completed: $DATE"
EOF
chmod +x ~/onlyoffice-backup.sh
# Schedule weekly backups
crontab -e
# Add: 0 2 * * 0 /home/user/onlyoffice-backup.sh Troubleshooting
Issue: Documents Won’t Open
# Check JWT configuration matches in both ONLYOFFICE and integration
docker exec onlyoffice-documentserver grep -r "JWT_SECRET" /etc/onlyoffice/
# Verify service is running
curl http://localhost:8080/healthcheck
# Check logs for errors
docker-compose logs onlyoffice | grep -i error Issue: Slow Document Loading
# Check resource usage
docker stats onlyoffice-documentserver
# Increase memory limits
docker-compose down
# Edit docker-compose.yml, add:
# deploy:
# resources:
# limits:
# memory: 4G
docker-compose up -d
# Add Redis cache if not present Issue: Connection Refused from Nextcloud
# Verify both services are on same network
docker network inspect onlyoffice_onlyoffice-net
# Test connectivity from Nextcloud container
docker exec nextcloud-app curl http://onlyoffice/healthcheck
# Check firewall rules
sudo ufw status Issue: “Download Failed” Error
This usually indicates JWT mismatch:
# Ensure JWT_SECRET matches in:
# 1. ONLYOFFICE environment variables
# 2. Nextcloud ONLYOFFICE app settings
# Regenerate JWT secret
NEW_SECRET=$(openssl rand -hex 32)
echo "New JWT Secret: $NEW_SECRET"
# Update in both places
docker exec -u www-data nextcloud php occ config:app:set onlyoffice jwt_secret --value="$NEW_SECRET"
# Update docker-compose.yml and restart Advanced Features
Mobile Editing
ONLYOFFICE supports mobile editing through responsive web interface:
- Access through mobile browser at your ONLYOFFICE URL
- Full editing capabilities on tablets
- View-only mode optimized for smartphones
- Native mobile apps available for iOS and Android (ONLYOFFICE Documents app)
Custom Branding
Customize ONLYOFFICE appearance:
# Create custom logo directory
mkdir -p ./onlyoffice-custom
# Add your logo files (logo.png, favicon.ico)
# Then mount in docker-compose.yml:
volumes:
- ./onlyoffice-custom/logo.png:/var/www/onlyoffice/documentserver/web-apps/apps/common/main/resources/img/header/header-logo.png
- ./onlyoffice-custom/favicon.ico:/var/www/onlyoffice/documentserver/favicon.ico Document Conversion API
Use ONLYOFFICE for batch document conversion:
# Convert DOCX to PDF
curl -X POST http://localhost:8080/ConvertService.ashx -H "Content-Type: application/json" -d '{
"async": false,
"filetype": "docx",
"key": "unique-document-key",
"outputtype": "pdf",
"title": "document.docx",
"url": "http://example.com/document.docx"
}' Conclusion
You now have a fully functional ONLYOFFICE Document Server that provides:
- Complete Microsoft Office compatibility
- Real-time collaborative editing
- Secure, self-hosted document management
- Seamless Nextcloud integration
- Production-ready performance
Next Steps
- Configure mobile apps for remote access
- Set up automated backups
- Integrate with other platforms (ownCloud, Seafile)
- Customize branding and themes
- Implement monitoring with Prometheus/Grafana
Resources
Your self-hosted office suite is ready for production use!