Nextcloud is an amazing open-source, self-hosted alternative to Google Drive or Dropbox. However, hosting it on an affordable VPS often means you quickly run into local storage limitations. The solution? Integrating S3 Object Storage!

In this tutorial, I’ll walk you through deploying Nextcloud via a Docker container on a VPS, configuring an S3 bucket (e.g., AWS S3, Wasabi, or Hetzner Storage Box) directly as your primary storage component.

Warning: This tutorial does not cover backup setups (for the database and server configurations). A comprehensive backup strategy is strictly required for any production deployment!

Prerequisites

  • A cloud server (VPS) running Ubuntu 24.04 (at least 2 GB of RAM recommended).
  • S3 Credentials: A completely empty S3 bucket with its respective keys (bucket_name, endpoint_url, access_key, and secret_key).
  • A domain name with an A-Record already pointing to the public IP of your VPS.

Step 1: Install Docker and Docker Compose

Before we begin, ensure Docker and Docker Compose are installed. On a fresh Ubuntu system, the easiest way is via the official installation script:

sudo apt-get update && sudo apt-get upgrade -y
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

Step 2: Prepare Directory Structure

Create a project directory on your server. This is where we will mount the configuration files and the database:

mkdir -p ~/nextcloud/db ~/nextcloud/html
cd ~/nextcloud

Step 3: Create the Docker Compose File

Generate a docker-compose.yml file with the following setup:

version: '3.8'

services:
  db:
    image: mariadb:10.11
    restart: always
    command: --transaction-isolation=READ-COMMITTED --log-bin=binlog --binlog-format=ROW
    volumes:
      - ./db:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=VerySecureRootPassword!
      - MYSQL_PASSWORD=VerySecureDbPassword
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=nextcloud

  app:
    image: nextcloud:apache
    restart: always
    ports:
      - 8080:80
    volumes:
      - ./html:/var/www/html
    environment:
      - MYSQL_PASSWORD=VerySecureDbPassword
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=nextcloud
      - MYSQL_HOST=db
      # Primary Storage S3 configurations
      - OBJECTSTORE_S3_BUCKET=your-bucket-name
      - OBJECTSTORE_S3_REGION=eu-central-1
      - OBJECTSTORE_S3_HOST=s3.eu-central-1.amazonaws.com # or Hetzner/Wasabi Endpoint
      - OBJECTSTORE_S3_KEY=your-access-key
      - OBJECTSTORE_S3_SECRET=your-secret-key
      - OBJECTSTORE_S3_SSL=true
      - OBJECTSTORE_S3_PORT=443
      - OBJECTSTORE_S3_USEPATH_STYLE=true
    depends_on:
      - db

  cron:
    image: nextcloud:apache
    restart: always
    volumes:
      - ./html:/var/www/html
    entrypoint: /cron.sh
    depends_on:
      - db

Configuration Breakdown:

  • S3 Settings: We pass the S3 credentials to Nextcloud directly as environment variables. The attribute USEPATH_STYLE=true is especially required for third-party providers like MinIO or Hetzner.
  • Cron Service: Nextcloud requires regular background execution for optimal performance. The cron container gracefully handles this without us needing to mess with the host’s cron setup.
  • Warning: Replace the default database credentials and S3 keys with your own secure values!

Step 4: Initializing Primary S3 Storage & Starting Up

Upon the first run, Nextcloud reads the OBJECTSTORE_S3 environment variables and injects them automatically into config.php for primary storage. Ensure your designated S3 Bucket is entirely empty before doing this.

Boot the setup with:

sudo docker compose up -d

It takes a couple of minutes for the database and Nextcloud to initialize. You can check the progress by running sudo docker compose logs -f app.

Step 5: Add a Reverse Proxy & SSL (e.g., Caddy)

Running your cloud without HTTPS (SSL) is highly insecure. The cleanest way to manage this is by placing a reverse proxy like Caddy in front of your container.

Install Caddy on your VPS (refer to official Caddy Docs) and configure your domain in /etc/caddy/Caddyfile:

nextcloud.yourdomain.ch {
    reverse_proxy localhost:8080
}

Reload Caddy and navigate to your selected domain in a browser. You should now be greeted by the Nextcloud setup screen (secured actively via Let’s Encrypt). There, you will establish your admin account and password!

Conclusion

That’s it! Your private Nextcloud instance is online. Rather than exhausting the limited (and often expensive) NVMe capacities typical for VPS rentals, all data is transparently pushed to your scalable, highly-available S3 bucket.

This approach provides cost efficiency, scalable data architecture, and reliability. Enjoy self-hosting! Should you require further aid setting this up or need consultancy on Corporate IT matters, don’t hesitate to reach out as a Freelancer!