Back to Cheatsheets
Cheatsheet

ownCloud Cheatsheet

ownCloud is a self-hosted file sync and share platform. This cheatsheet covers daily operations, configuration, and maintenance.

Installation

services:
  owncloud:
    image: owncloud/server:latest
    restart: unless-stopped
    ports:
      - "8080:8080"
    environment:
      OWNCLOUD_ADMIN_USERNAME: admin
      OWNCLOUD_ADMIN_PASSWORD: adminpass
      OWNCLOUD_DB_TYPE: mysql
      OWNCLOUD_DB_NAME: owncloud
      OWNCLOUD_DB_USERNAME: owncloud
      OWNCLOUD_DB_PASSWORD: dbpass
      OWNCLOUD_DB_HOST: db
      OWNCLOUD_REDIS_ENABLED: "true"
      OWNCLOUD_REDIS_HOST: redis
      OWNCLOUD_TRUSTED_DOMAINS: "localhost 192.168.1.100 cloud.example.com"
      OWNCLOUD_OVERWRITE_CLI_URL: "https://cloud.example.com"
      OWNCLOUD_OVERWRITEPROTOCOL: "https"
    volumes:
      - owncloud_data:/mnt/data
    depends_on:
      - db
      - redis
 
  db:
    image: mariadb:10.11
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: rootpass
      MYSQL_DATABASE: owncloud
      MYSQL_USER: owncloud
      MYSQL_PASSWORD: dbpass
    volumes:
      - db_data:/var/lib/mysql
 
  redis:
    image: redis:7-alpine
    restart: unless-stopped
 
volumes:
  owncloud_data:
  db_data:
docker compose up -d                              # Start stack
docker compose logs -f owncloud                   # Watch logs
docker compose exec owncloud occ status           # Check status

Manual (LAMP Stack)

# Prerequisites: Apache, PHP 8.1+, MariaDB/MySQL
 
# Download
wget https://download.owncloud.com/server/owncloud-10.15.0.tar.bz2
tar -xjf owncloud-10.15.0.tar.bz2 -C /var/www/
chown -R www-data:www-data /var/www/owncloud
 
# Apache vhost
cat > /etc/apache2/sites-available/owncloud.conf << 'EOF'
Alias /owncloud "/var/www/owncloud/"
<Directory /var/www/owncloud/>
    Options +FollowSymlinks
    AllowOverride All
    Require all granted
    SetEnv HOME /var/www/owncloud
    SetEnv HTTP_HOME /var/www/owncloud
</Directory>
EOF
a2ensite owncloud && systemctl reload apache2
 
# Database
mysql -u root -p -e "CREATE DATABASE owncloud; \
  GRANT ALL ON owncloud.* TO 'owncloud'@'localhost' IDENTIFIED BY 'dbpass';"

occ CLI

All occ commands must run as the web server user. In Docker: docker compose exec owncloud occ .... On bare metal: sudo -u www-data php occ ....

Core Commands

occ status                                        # Show version & install status
occ list                                          # List all available commands
occ check                                        # Check environment & dependencies
occ config:system:get version                     # Get config value
occ config:system:set trusted_domains 1 --value="cloud.example.com"
occ config:system:set maintenance --value=false   # Toggle maintenance mode
occ maintenance:mode --on                         # Enable maintenance mode
occ maintenance:mode --off                        # Disable maintenance mode

Upgrade & Update

occ upgrade                                      # Run upgrade after version bump
occ maintenance:repair                           # Repair database inconsistencies
occ db:add-missing-indices                       # Add missing DB indices
occ db:add-missing-columns                       # Add missing DB columns
occ db:add-missing-primary-keys                  # Add missing PKs
occ db:convert-type --all mysql                  # Convert DB storage type
occ migrations:execute <app> <version>           # Run specific migration

User Management

occ user:add --display-name="John Doe" \
  --email="[email protected]" \
  --password-from-env john                       # Add user (set OC_PASS env first)
occ user:delete john                             # Delete user
occ user:list                                   # List all users
occ user:info john                              # Show user details
occ user:setting john read config                # Get user setting
occ user:setting john core language en           # Set user language
occ user:setting john files quota "10G"          # Set quota
occ user:resetpassword john                      # Reset password
occ user:report                                  # User statistics report

Groups

occ group:add staff                              # Create group
occ group:delete staff                           # Delete group
occ group:list                                   # List all groups
occ group:list-members staff                     # List members of group
occ group:add-user john staff                    # Add user to group
occ group:remove-user john staff                 # Remove user from group

File Operations

occ files:scan --all                             # Scan all files for all users
occ files:scan john                              # Scan files for specific user
occ files:scan --path="/john/files/Photos"       # Scan specific path
occ files:scan-app-data                          # Scan app data directory
occ files:cleanup                                # Clean up file cache
occ files:transfer-ownership john jane           # Transfer all files from john to jane
occ trashbin:cleanup john                        # Empty trash for user
occ trashbin:cleanup --all                       # Empty trash for all users
occ versions:cleanup john                        # Clean versions for user
occ versions:cleanup --all                       # Clean versions for all users
occ files_external:list                          # List external storage mounts
occ files_external:verify                        # Verify external storage config

Apps Management

occ app:list                                    # List installed apps
occ app:install calendar                         # Install app from marketplace
occ app:enable calendar                          # Enable app
occ app:disable calendar                         # Disable app
occ app:uninstall calendar                       # Uninstall app
occ app:update --all                             # Update all apps
occ app:check                                    # Check app compatibility
occ market:install <app-id>                      # Install from marketplace
occ market:upgrade <app-id>                      # Upgrade from marketplace

Configuration (config.php)

Important Settings

<?php
$CONFIG = [
    'trusted_domains' => ['cloud.example.com', '192.168.1.100'],
    'overwrite.cli.url' => 'https://cloud.example.com',
    'overwriteprotocol' => 'https',
    'htaccess.RewriteBase' => '/',
 
    'dbtype' => 'mysql',
    'dbname' => 'owncloud',
    'dbhost' => 'localhost',
    'dbuser' => 'owncloud',
    'dbpassword' => 'dbpass',
    'dbtableprefix' => 'oc_',
 
    'mail_domain' => 'example.com',
    'mail_from_address' => 'noreply',
    'mail_smtpmode' => 'smtp',
    'mail_smtphost' => 'smtp.example.com',
    'mail_smtpport' => '587',
    'mail_smtpsecure' => 'tls',
    'mail_smtpauth' => true,
    'mail_smtpname' => 'user',
    'mail_smtppassword' => 'pass',
 
    'redis' => [
        'host' => 'localhost',
        'port' => 6379,
    ],
    'memcache.local' => '\OC\Memcache\APCu',
    'memcache.distributed' => '\OC\Memcache\Redis',
    'memcache.locking' => '\OC\Memcache\Redis',
 
    'filelocking.enabled' => true,
    'debug' => false,
    'log_type' => 'owncloud',
    'logfile' => '/var/log/owncloud.log',
    'loglevel' => 2,  // 0=DEBUG, 1=INFO, 2=WARN, 3=ERROR
    'log_rotate_size' => 104857600,  // 100MB
 
    'maintenance' => false,
];

Managing Config via occ

occ config:system:set trusted_domains 1 --value="cloud.example.com"
occ config:system:set overwrite.cli.url --value="https://cloud.example.com"
occ config:system:get trusted_domains
occ config:system:delete debug
occ config:app:set core import_max_size --value="524288000"
occ config:app:get core import_max_size

S3 / R2 as Primary Storage

occ config:system:set objectstore enabled --value=true
occ config:system:set objectstore class --value="\OC\Files\ObjectStore\S3"
occ config:system:set objectstore arguments bucket --value="owncloud-data"
occ config:system:set objectstore arguments key --value="ACCESS_KEY"
occ config:system:set objectstore arguments secret --value="SECRET_KEY"
occ config:system:set objectstore arguments hostname --value="r2.cloudflarestorage.com"
occ config:system:set objectstore arguments region --value="auto"
occ config:system:set objectstore arguments use_path_style --value=true

External Storage (Secondary)

# Enable External Storage app
occ app:enable files_external
 
# Add S3 external storage
occ files_external:create \
  --config '{"bucket":"backup","key":"AK","secret":"SK","hostname":"s3.amazonaws.com","region":"us-east-1"}' \
  "S3 Backup" \
  amazons3 \
  null::null
 
# List external storages
occ files_external:list
 
# Verify configuration
occ files_external:verify 1

Performance Tuning

Redis Caching

# config.php
occ config:system:set redis host --value="localhost"
occ config:system:set redis port --value=6379 --type=integer
occ config:system:set memcache.local --value="\OC\Memcache\APCu"
occ config:system:set memcache.distributed --value="\OC\Memcache\Redis"
occ config:system:set memcache.locking --value="\OC\Memcache\Redis"
occ config:system:set filelocking.enabled --value=true --type=boolean

PHP-FPM Tuning

; /etc/php/8.1/fpm/pool.d/www.conf
pm = dynamic
pm.max_children = 120
pm.start_servers = 12
pm.min_spare_servers = 6
pm.max_spare_servers = 18
pm.max_requests = 500
 
; php.ini
memory_limit = 512M
upload_max_filesize = 16G
post_max_size = 16G
max_execution_time = 3600
opcache.enable = 1
opcache.memory_consumption = 256
opcache.max_accelerated_files = 20000
apc.enable_cli = 1

Background Jobs

# Switch to cron (recommended)
occ config:system:set mode --value="cron" --type=string
 
# Add cron job (run every 15 min)
echo "*/15 * * * * sudo -u www-data php /var/www/owncloud/occ system:cron" | sudo tee /etc/cron.d/owncloud
 
# In Docker, use the built-in cron
docker compose exec owncloud occ system:cron

Security

.htaccess & Headers

occ maintenance:update:htaccess                   # Regenerate .htaccess
# Ensure AllowOverride All in Apache vhost

Brute Force Protection

occ config:system:set auth.bruteforce.protection.enabled --value=true --type=boolean
occ config:system:set auth.bruteforce.protection.max_attempts --value=50 --type=integer
occ config:system:set auth.bruteforce.protection.time_window --value=300 --type=integer

Two-Factor Authentication

occ app:enable twofactor_totp                    # Enable TOTP 2FA
occ twofactor:enforce john                       # Enforce 2FA for user
occ twofactor:disable john                       # Disable 2FA for user
occ twofactor:state john                         # Check 2FA state

fail2ban Integration

# /etc/fail2ban/filter.d/owncloud.conf
[Definition]
failregex = ^.*"remoteAddr":"<HOST>".*"app":"core".*"message":"Login failed:.*".*$
            ^.*"remoteAddr":"<HOST>".*"app":"core".*"message":"Brute-force attempt".*$
ignoreregex =
# /etc/fail2ban/jail.d/owncloud.conf
[owncloud]
enabled = true
filter = owncloud
logpath = /var/www/owncloud/data/owncloud.log
maxretry = 5
bantime = 900
findtime = 300

Backup & Restore

Full Backup Procedure

# 1. Enable maintenance mode
occ maintenance:mode --on
 
# 2. Backup database
mysqldump -u root -p owncloud > owncloud_db_$(date +%F).sql
 
# 3. Backup data directory
tar -czf owncloud_data_$(date +%F).tar.gz /var/www/owncloud/data/
 
# 4. Backup config
tar -czf owncloud_config_$(date +%F).tar.gz /var/www/owncloud/config/
 
# 5. Disable maintenance mode
occ maintenance:mode --off

Docker Backup

# Database
docker compose exec db mysqldump -u root -prootpass owncloud > backup.sql
 
# Data volume
docker run --rm -v $(pwd)/owncloud_data:/backup \
  -v project_owncloud_data:/data alpine \
  tar -czf /backup/data.tar.gz -C /data .
 
# Restore
docker compose exec db mysql -u root -prootpass owncloud < backup.sql
docker run --rm -v $(pwd)/owncloud_data:/backup \
  -v project_owncloud_data:/data alpine \
  tar -xzf /backup/data.tar.gz -C /data

Restore Procedure

# 1. Enable maintenance mode
occ maintenance:mode --on
 
# 2. Restore database
mysql -u root -p owncloud < owncloud_db_2024-01-01.sql
 
# 3. Restore data
tar -xzf owncloud_data_2024-01-01.tar.gz -C /var/www/owncloud/
 
# 4. Restore config
tar -xzf owncloud_config_2024-01-01.tar.gz -C /var/www/owncloud/
 
# 5. Run repair
occ maintenance:repair
 
# 6. Disable maintenance mode
occ maintenance:mode --off

Upgrade Procedure

Docker Upgrade

# 1. Backup (see backup section above)
 
# 2. Enable maintenance mode
docker compose exec owncloud occ maintenance:mode --on
 
# 3. Pull new image
docker compose pull owncloud
 
# 4. Restart with new image
docker compose up -d owncloud
 
# 5. Run upgrade
docker compose exec owncloud occ upgrade
 
# 6. Run repair
docker compose exec owncloud occ maintenance:repair
 
# 7. Disable maintenance mode
docker compose exec owncloud occ maintenance:mode --off
 
# 8. Verify
docker compose exec owncloud occ status

Manual Upgrade

# 1. Backup everything
 
# 2. Enable maintenance mode
sudo -u www-data php occ maintenance:mode --on
 
# 3. Download new version
wget https://download.owncloud.com/server/owncloud-10.15.0.tar.bz2
 
# 4. Extract over existing (keep data/ and config/)
tar -xjf owncloud-10.15.0.tar.bz2 -C /var/www/
 
# 5. Run upgrade
sudo -u www-data php occ upgrade
 
# 6. Run repair
sudo -u www-data php occ maintenance:repair
 
# 7. Disable maintenance mode
sudo -u www-data php occ maintenance:mode --off
 
# 8. Verify
sudo -u www-data php occ status

Troubleshooting

Check System

occ status                                       # Version & install status
occ check                                       # Environment check
occ configcheck                                 # Validate config.php
occ integrity:check                              # Verify file integrity
occ system:report                               # Full system report

Logs

# View log file
occ log:tail                                     # Tail log (Docker)
tail -f /var/www/owncloud/data/owncloud.log     # Bare metal
 
# Change log level
occ config:system:set loglevel --value=0 --type=integer   # DEBUG
occ config:system:set loglevel --value=1 --type=integer   # INFO
occ config:system:set loglevel --value=2 --type=integer   # WARN (default)
occ config:system:set loglevel --value=3 --type=integer   # ERROR
 
# Log to syslog
occ config:system:set log_type --value="syslog"

Stuck in Maintenance Mode

# Force disable maintenance mode
occ config:system:set maintenance --value=false --type=boolean
 
# If occ fails, edit config.php directly
sed -i "s/'maintenance' => true/'maintenance' => false/" config/config.php

Upgrade Failed

# Check upgrade log
occ upgrade --verbose
 
# Skip specific migration
occ migrations:execute --dry-run <app>
 
# Reset upgrade state
occ config:system:set upgraded --value=true --type=boolean
occ maintenance:repair
 
# Last resort: re-run from scratch
occ upgrade --force

Database Issues

# Repair sequences
occ maintenance:repair
 
# Convert to InnoDB (if still on MyISAM)
occ db:convert-type --all mysql
 
# Add missing indices
occ db:add-missing-indices
occ db:add-missing-columns
occ db:add-missing-primary-keys

File Scan Issues

# Full rescan (slow)
occ files:scan --all --verbose
 
# Scan specific user with debug
occ files:scan john -v
 
# Clean file cache
occ files:cleanup
 
# Rebuild share cache
occ shares:migrate

Common Problems

# "Trusted domains" error
occ config:system:set trusted_domains 1 --value="cloud.example.com"
 
# Upload size too small
occ config:system:set max_upload_size --value=17179869184 --type=integer
# Also set in php.ini: upload_max_filesize, post_max_size
 
# Cron not running
occ system:cron                                   # Manual trigger
occ config:system:set mode --value="cron"         # Switch from AJAX to cron
 
# Redis connection refused
occ config:system:get redis                       # Verify config
docker compose restart redis                      # Restart Redis

Useful API Endpoints

# Status (public)
curl https://cloud.example.com/status.php
 
# OCS API - list users (admin auth)
curl -u admin:password \
  -H "OCS-APIREQUEST: true" \
  https://cloud.example.com/ocs/v1.php/cloud/users
 
# WebDAV - list files
curl -u john:password \
  -X PROPFIND \
  -H "Depth: 1" \
  https://cloud.example.com/remote.php/dav/files/john/
 
# Upload file via WebDAV
curl -u john:password \
  -T localfile.txt \
  https://cloud.example.com/remote.php/dav/files/john/localfile.txt
 
# Share file via API
curl -u admin:password \
  -X POST \
  -H "OCS-APIREQUEST: true" \
  "https://cloud.example.com/ocs/v1.php/apps/files_sharing/api/v1/shares" \
  -d "path=/Photos/test.jpg&shareType=3&permissions=1"