The Question We Hear Often

“We need file sharing for our team, but we’re not comfortable putting client documents on someone else’s cloud. What are our options?”

We hear this from Canadian businesses every week. Healthcare providers handling PHIPA-protected records. Law firms with privileged client files. Marketing agencies with proprietary campaign assets. They all need collaboration tools, but the mainstream options feel like a compliance gamble.

Dropbox stores your files in US data centres subject to the CLOUD Act. Google Drive scans documents for “security purposes.” OneDrive ties you into the Microsoft ecosystem. For many Canadian organizations, these are deal-breakers.

Enter Nextcloud — a self-hosted alternative that gives you Dropbox-like functionality on infrastructure you control. File sync, sharing, calendar, contacts, real-time document editing, and even video calls — all running on your own server.

Here is how to set up Nextcloud on a VPS the right way: Docker-based deployment, proper SSL, and production-ready configuration.

What You Will Need

Nextcloud is not lightweight. It is a full collaboration suite, and it needs resources to run smoothly. Here is what we recommend:

Component Minimum Recommended
CPU 2 cores 4 cores
RAM 2 GB 4 GB
Storage 50 GB 100+ GB (scales with files)
OS Ubuntu 22.04 LTS Ubuntu 24.04 LTS

For this setup, we recommend a Cloud VPS from Canadian Web Hosting. Our Vancouver and Toronto data centres keep your data in Canada, with SOC 2 Type II certification and 24/7 support if you need help along the way.

Step-by-Step Installation

1. Prepare Your Server

Start with a fresh Ubuntu server. SSH in and update everything:

sudo apt update && sudo apt upgrade -y
sudo apt install -y docker.io docker-compose-v2

Enable Docker to start on boot:

sudo systemctl enable --now docker
sudo usermod -aG docker $USER

Log out and back in so your group membership takes effect.

2. Create the Project Directory

Nextcloud needs persistent storage for files, database, and configuration. Create a dedicated structure:

mkdir -p ~/nextcloud/{db,html,data,redis}
cd ~/nextcloud

3. Create the Docker Compose File

Create docker-compose.yml with the following configuration. This sets up Nextcloud with MariaDB for the database and Redis for caching (essential for performance):

services:
  db:
    image: mariadb:10.11
    restart: always
    volumes:
      - ./db:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: your-root-password-here
      MYSQL_DATABASE: nextcloud
      MYSQL_USER: nextcloud
      MYSQL_PASSWORD: your-db-password-here

  redis:
    image: redis:alpine
    restart: always

  app:
    image: nextcloud:latest
    restart: always
    volumes:
      - ./html:/var/www/html
      - ./data:/var/www/html/data
    ports:
      - "8080:80"
    environment:
      MYSQL_HOST: db
      MYSQL_DATABASE: nextcloud
      MYSQL_USER: nextcloud
      MYSQL_PASSWORD: your-db-password-here
      REDIS_HOST: redis
      NEXTCLOUD_TRUSTED_DOMAINS: your-domain.com
    depends_on:
      - db
      - redis

Important: Replace your-root-password-here, your-db-password-here, and your-domain.com with your actual values.

4. Launch Nextcloud

Start the containers:

docker compose up -d

Check that everything is running:

docker compose ps

You should see three containers: nextcloud-db-1, nextcloud-redis-1, and nextcloud-app-1, all showing “Up” status.

Initial Configuration

Create Your Admin Account

Open your browser and navigate to http://your-server-ip:8080. You will see the Nextcloud setup screen:

  1. Username: Create an admin username (not “admin” — too predictable)
  2. Password: Use a strong, unique password
  3. Database: Click “MySQL/MariaDB” and enter:
    • Database user: nextcloud
    • Database password: (the password you set in docker-compose.yml)
    • Database name: nextcloud
    • Database host: db

Click “Install” and wait a few minutes while Nextcloud sets up the database and creates default folders.

Configure Redis Caching

Redis is already running, but Nextcloud needs to know to use it. Edit the configuration:

sudo nano ~/nextcloud/html/config/config.php

Add these lines inside the $CONFIG = array ( block, before the closing );:

  'memcache.local' => '\OC\Memcache\Redis',
  'memcache.distributed' => '\OC\Memcache\Redis',
  'memcache.locking' => '\OC\Memcache\Redis',
  'redis' => [
    'host' => 'redis',
    'port' => 6379,
  ],

Restart the app container to apply:

docker compose restart app

Verify Everything Works

Before moving to production, verify each component:

1. File Upload Test: Upload a test file through the web interface. Check it appears in ~/nextcloud/data/[username]/files/ on the server.

2. Sync Client Test: Download the Nextcloud desktop client, connect to your server, and verify sync works.

3. Redis Test: Check Redis is being used:

docker compose exec redis redis-cli ping

Should respond with PONG.

4. Database Test: Verify the database has tables:

docker compose exec db mariadb -u nextcloud -p -e "SHOW TABLES;" nextcloud

You should see 80+ tables listed.

Production Hardening

Running Nextcloud on port 8080 without encryption is fine for testing, but not for production. Here is how to secure it properly.

Set Up a Reverse Proxy with SSL

We recommend using Caddy for automatic HTTPS, or Nginx if you prefer manual configuration. Here is the Caddy approach:

Add a Caddy service to your docker-compose.yml:

  caddy:
    image: caddy:latest
    restart: always
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config
    depends_on:
      - app

volumes:
  caddy_data:
  caddy_config:

Create a Caddyfile in the same directory:

cloud.yourdomain.com {
    reverse_proxy app:80
    encode gzip
    header Strict-Transport-Security "max-age=31536000;"
}

Restart everything:

docker compose up -d

Caddy will automatically obtain and renew a Let’s Encrypt SSL certificate for your domain.

Configure Firewall Rules

Only expose the ports you need:

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https
sudo ufw enable

Set Up Backups

Nextcloud has three components to back up:

  1. Files: The ~/nextcloud/data directory
  2. Database: Use mysqldump or MariaDB backup tools
  3. Configuration: The ~/nextcloud/html/config directory

Create a simple backup script:

#!/bin/bash
DATE=$(date +%Y%m%d)
BACKUP_DIR="/backup/nextcloud"
mkdir -p $BACKUP_DIR

docker compose exec db mariadb-dump -u nextcloud -p'your-db-password' nextcloud > $BACKUP_DIR/db-$DATE.sql
tar -czf $BACKUP_DIR/files-$DATE.tar.gz ~/nextcloud/data
tar -czf $BACKUP_DIR/config-$DATE.tar.gz ~/nextcloud/html/config

# Keep only last 30 days
find $BACKUP_DIR -type f -mtime +30 -delete

Schedule it with cron: 0 2 * * * /home/user/backup-nextcloud.sh

For production deployments, consider CloudSafe Backup for offsite, encrypted backups with retention policies.

Enable Two-Factor Authentication

Nextcloud supports TOTP (Google Authenticator compatible). Install the Two-Factor TOTP app from the Nextcloud App Store and enable it for all admin accounts.

Troubleshooting Common Issues

“Internal Server Error” After Setup

Cause: Usually a database connection issue or permission problem.

Fix: Check the Nextcloud logs:

docker compose logs app | tail -50

Common fixes:

  • Verify database credentials match between docker-compose.yml and the Nextcloud config
  • Check file permissions: sudo chown -R 33:33 ~/nextcloud/html (33 is www-data)

Upload Fails with “413 Request Entity Too Large”

Cause: Default upload limits are too low for large files.

Fix: Edit ~/nextcloud/html/.htaccess or add to config.php:

'upload_max_filesize' => '10G',
'post_max_size' => '10G',

Also increase PHP memory limit in the container:

docker compose exec app php -d memory_limit=512M occ maintenance:repair

Sync Client Shows “Connection Refused”

Cause: The server is not accessible, or the trusted domains list is incorrect.

Fix: Add your domain to trusted domains in config.php:

'trusted_domains' =>
array (
  0 => 'localhost',
  1 => 'your-server-ip',
  2 => 'cloud.yourdomain.com',
),

Performance is Slow

Cause: Missing Redis caching, or insufficient resources.

Fix: Verify Redis is configured (see above). If Redis is working but still slow:

  • Increase RAM allocation to the VPS
  • Enable server-side encryption only if required (adds CPU overhead)
  • Disable unused apps in Nextcloud settings

When to Upgrade or Seek Help

If your team grows beyond 50 users, or you need enterprise features like SSO integration, audit logging, or advanced sharing controls, consider:

  • Upgrading to a Dedicated Server for more resources
  • Exploring Nextcloud Enterprise for advanced features
  • Contacting CWH Managed Support if you prefer not to manage it yourself

Conclusion

Self-hosting Nextcloud gives you control over your data without sacrificing collaboration features. You get file sync, sharing, calendars, and more — all on infrastructure you own and operate.

The key to a successful deployment is starting with adequate resources, configuring Redis caching from day one, and setting up proper backups before you store anything important.

If you run into issues or want help with the initial setup, contact Canadian Web Hosting. Our team has deployed Nextcloud for dozens of Canadian organizations and can help you get up and running quickly.

Related guides: