18 min read

How to Self-Host Nextcloud and Access It from Anywhere

Nextcloud is the most complete self-hosted alternative to Google Drive, Dropbox, and Google Photos. This guide covers two installation paths: Docker Compose on any Linux machine, and a dedicated Raspberry Pi setup using the official NextcloudPi script.

Nextcloud · Self-Hosting · Docker · Raspberry Pi · 2026

How to Self-Host Nextcloud and Access It from Anywhere (No Port Forwarding)

Nextcloud is the most complete self-hosted alternative to Google Drive, Dropbox, and Google Photos. This guide covers two installation paths: Docker Compose on any Linux machine, and a dedicated Raspberry Pi setup using the official NextcloudPi script. Both end with a Localtonet tunnel that gives your Nextcloud a public HTTPS URL accessible from any device, anywhere in the world, without port forwarding, a static IP, or a VPS.

🐳 Docker Compose · MariaDB · Redis 🍓 Raspberry Pi 4 / 5 🌐 Remote Access · No Port Forwarding · CGNAT

What Is Nextcloud?

Nextcloud is an open-source, self-hosted collaboration platform. At its core it is a file sync and share server, but the app ecosystem makes it much more: calendar and contacts sync, photo gallery, office document editing (via Collabora or OnlyOffice), video calls, password manager, and more. Every piece of data stays on hardware you own.

📁 File Sync and Share Desktop and mobile clients keep files in sync across all your devices. Selective sync, versioning, and deleted file recovery included.
📷 Photo Backup (Memories App) The Memories app turns Nextcloud into a Google Photos alternative with face recognition, timeline view, and album sharing.
📅 Calendar and Contacts CalDAV and CardDAV sync with iOS, Android, Thunderbird, and any standards-compliant client.
📝 Office Documents Edit .docx, .xlsx, and .pptx files in the browser via Collabora Online or OnlyOffice integration.
🔒 End-to-End Encryption Client-side encryption for specific folders so even the server cannot read those files.
👥 Multi-User and Teams Create multiple user accounts, groups, and quotas. Share files and folders with internal users or external guests via link.
Self-Hosting vs Google Drive / Dropbox
  • Your files never leave your hardware
  • No per-user monthly fee, no storage cap beyond your disk
  • No scanning, no advertising, no data sharing
  • GDPR and HIPAA compliance under your control
  • Works on your local network even without internet
Responsibilities
  • You manage updates and security patches
  • You are responsible for backups
  • Uptime depends on your hardware and power
  • Initial setup takes more effort than signing up for a service

Requirements

Component Minimum Recommended
CPU 64-bit, 2 cores 4 cores (Raspberry Pi 4 / 5 or x86_64 server)
RAM 2 GB 4 GB+ (Redis + MariaDB + Nextcloud all run simultaneously)
Storage 16 GB (OS + app) SSD for OS/DB, large HDD/external drive for user data
OS Debian 12, Ubuntu 22.04+, Raspberry Pi OS Ubuntu 24.04 LTS or Raspberry Pi OS Bookworm (64-bit)
Docker Docker 24+, Docker Compose v2 Latest stable Docker Engine
Network Any internet connection (including CGNAT) Stable broadband. Localtonet handles CGNAT automatically.
CGNAT users: port forwarding will not work for you

Many ISPs in 2026 use CGNAT (Carrier Grade NAT), which means you do not have a real public IP address at your home. Port forwarding on your router does nothing. Localtonet's outbound tunnel solves this completely because it does not require any inbound port to be open.

Installation Path 1: Docker Compose on Linux

This is the recommended method for any Linux machine (Ubuntu, Debian, or any x86_64 server). It installs Nextcloud together with MariaDB and Redis in isolated containers, making upgrades easy and the host system clean.

Step 1: Install Docker

# Install Docker (one-line official script):
curl -fsSL https://get.docker.com | sudo sh

# Add your user to the docker group (no sudo needed):
sudo usermod -aG docker $USER

# Log out and back in, then verify:
docker --version
docker compose version

Expected output:

Docker version 27.x.x, build xxxxxxx
Docker Compose version v2.x.x

Step 2: Create the project directory and .env file

mkdir ~/nextcloud && cd ~/nextcloud

Create a .env file with your passwords. Never commit this file to Git:

cat > .env << 'EOF'
MYSQL_ROOT_PASSWORD=change_this_root_password
MYSQL_PASSWORD=change_this_db_password
MYSQL_DATABASE=nextcloud
MYSQL_USER=nextcloud
NEXTCLOUD_ADMIN_USER=admin
NEXTCLOUD_ADMIN_PASSWORD=change_this_admin_password
NEXTCLOUD_TRUSTED_DOMAINS=localhost
EOF

Step 3: Create docker-compose.yml

cat > docker-compose.yml << 'EOF'
version: "3.8"

services:

  db:
    image: mariadb:11
    container_name: nextcloud-db
    restart: unless-stopped
    command: --transaction-isolation=READ-COMMITTED --log-bin=binlog --binlog-format=ROW
    volumes:
      - db_data:/var/lib/mysql
    env_file: .env
    environment:
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
      - MYSQL_DATABASE=${MYSQL_DATABASE}
      - MYSQL_USER=${MYSQL_USER}
      - MYSQL_PASSWORD=${MYSQL_PASSWORD}

  redis:
    image: redis:alpine
    container_name: nextcloud-redis
    restart: unless-stopped

  app:
    image: nextcloud:stable-apache
    container_name: nextcloud-app
    restart: unless-stopped
    ports:
      - "8080:80"
    depends_on:
      - db
      - redis
    volumes:
      - nextcloud_html:/var/www/html
      - ./data:/var/www/html/data
    env_file: .env
    environment:
      - MYSQL_HOST=db
      - MYSQL_DATABASE=${MYSQL_DATABASE}
      - MYSQL_USER=${MYSQL_USER}
      - MYSQL_PASSWORD=${MYSQL_PASSWORD}
      - REDIS_HOST=redis
      - NEXTCLOUD_ADMIN_USER=${NEXTCLOUD_ADMIN_USER}
      - NEXTCLOUD_ADMIN_PASSWORD=${NEXTCLOUD_ADMIN_PASSWORD}
      - NEXTCLOUD_TRUSTED_DOMAINS=${NEXTCLOUD_TRUSTED_DOMAINS}
      - APACHE_DISABLE_REWRITE_IP=1
      - TRUSTED_PROXIES=172.16.0.0/12 192.168.0.0/16 10.0.0.0/8

volumes:
  db_data:
  nextcloud_html:
EOF

Step 4: Start Nextcloud

docker compose up -d

The first run pulls images and runs the Nextcloud installer automatically. Wait about 2 minutes, then open http://localhost:8080 in your browser. You should see the Nextcloud login screen.

# Check that all three containers are running:
docker compose ps

Expected output:

NAME               IMAGE                    STATUS
nextcloud-app      nextcloud:stable-apache  Up 2 minutes
nextcloud-db       mariadb:11               Up 2 minutes
nextcloud-redis    redis:alpine             Up 2 minutes

Step 5: Set up the background cron job

Nextcloud requires periodic background tasks (file scanning, notifications, cleanup). The default AJAX-based cron only runs when someone is logged in. Switch to a proper system cron:

# Add a cron job that runs every 5 minutes:
(crontab -l 2>/dev/null; echo "*/5 * * * * docker exec --user www-data nextcloud-app php -f /var/www/html/cron.php") | crontab -

# Then set the cron type in Nextcloud to "cron":
docker exec --user www-data nextcloud-app php occ background:cron

Expected output:

Set mode for background jobs to 'cron'

Installation Path 2: Raspberry Pi (NextcloudPi)

The Raspberry Pi deserves its own section because it is the most popular self-hosting hardware for Nextcloud. The official NextcloudPi project provides a dedicated OS image and install script that sets everything up automatically, including Apache, PHP, MariaDB, and Redis, optimized for the Pi's constraints.

Recommended Pi hardware

Raspberry Pi 4 (4 GB RAM) or Raspberry Pi 5 (4 GB or 8 GB RAM) are the minimum for a usable Nextcloud experience. Pi 3 works for personal use with few files. Pi Zero and Pi 1 are too slow. Use a quality microSD card (A2-rated) or, better, a USB-attached SSD for the OS and Nextcloud data. An external USB HDD is fine for bulk storage.

Option A: NextcloudPi OS Image (Recommended for beginners)

1

Download the NextcloudPi image

Go to github.com/nextcloud/nextcloudpi/releases and download the latest .img.xz file for your Pi model. Use Raspberry Pi Imager to flash it to your SD card or SSD.

2

Boot and find the Pi's IP address

Connect the Pi to your router via Ethernet and power it on. Find its local IP from your router's DHCP list or run ping nextcloudpi.local from another machine on the same network.

3

Open the activation wizard

Navigate to https://<pi-ip>:4443 in your browser. Accept the self-signed certificate warning. The NextcloudPi activation wizard guides you through setting the admin password and configuring storage.

4

Access Nextcloud

After activation, Nextcloud is available at https://<pi-ip> on your local network. The NextcloudPi panel is at https://<pi-ip>:4443.

Option B: Install NextcloudPi on Existing Raspberry Pi OS

If your Pi already runs Raspberry Pi OS Bookworm (64-bit), install NextcloudPi on top with the official script:

# Update the system first:
sudo apt update && sudo apt upgrade -y

# Run the NextcloudPi installer:
curl -sSL https://raw.githubusercontent.com/nextcloud/nextcloudpi/master/install.sh | sudo bash

The installer takes 5-15 minutes depending on your Pi model and internet speed. When complete it prints:

NextcloudPi instance already running on this machine.

 First run wizard
 ---------------------------------------------------------------
 It seems this is your first run of NextcloudPi.
 Navigate to https://<your-pi-ip>:4443
 to complete the initial configuration.
 ---------------------------------------------------------------

Option C: Docker Compose on Raspberry Pi

If you prefer Docker on your Pi (for easier updates and multi-container management), the same docker-compose.yml from Path 1 works on Raspberry Pi OS 64-bit without changes. The nextcloud:stable-apache image includes an ARM64 build.

# Install Docker on Raspberry Pi OS:
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker pi
# Log out and back in, then run the same docker-compose.yml from Path 1
Use 64-bit Raspberry Pi OS

Nextcloud's official Docker image requires a 64-bit OS. The default Raspberry Pi OS for older Pi models is 32-bit. Flash the 64-bit version of Raspberry Pi OS from the Raspberry Pi Imager before installing Docker. You can verify with uname -m: it should return aarch64, not armv7l.

Raspberry Pi: Mounting an External Drive for Data

Storing Nextcloud data on the SD card will wear it out quickly. Mount an external USB SSD or HDD:

# Find the drive:
lsblk

# Create a mount point and mount:
sudo mkdir -p /mnt/nextcloud-data
sudo mount /dev/sda1 /mnt/nextcloud-data

# Make mount permanent (add to /etc/fstab):
echo "UUID=$(sudo blkid -s UUID -o value /dev/sda1)  /mnt/nextcloud-data  ext4  defaults,nofail  0  2" | sudo tee -a /etc/fstab

# Fix permissions for Nextcloud (www-data user):
sudo chown -R www-data:www-data /mnt/nextcloud-data

In Docker Compose on Pi, point the data volume to this path:

volumes:
  - /mnt/nextcloud-data:/var/www/html/data

Critical: trusted_proxies Configuration for Tunnel Access

This is the most common point of failure when exposing Nextcloud through any reverse proxy or tunnel. If trusted_proxies is not configured, Nextcloud rejects requests that come through the tunnel and logs errors like "Blocked request from an untrusted proxy" or shows a blank page after login.

Without trusted_proxies, the Localtonet tunnel will not work

Nextcloud must be told which IP addresses are allowed to act as a proxy. When traffic arrives via the Localtonet tunnel, it looks like it comes from the Docker bridge network. Without the trusted_proxies setting, Nextcloud blocks it.

For Docker Compose installs

The TRUSTED_PROXIES environment variable in the docker-compose.yml above already covers all private IP ranges. Verify it is set:

TRUSTED_PROXIES=172.16.0.0/12 192.168.0.0/16 10.0.0.0/8
APACHE_DISABLE_REWRITE_IP=1

After changing, restart the app container:

docker compose restart app

For NextcloudPi (Raspberry Pi) installs

Edit the Nextcloud config file directly:

# On NextcloudPi, config.php is at:
sudo nano /var/www/nextcloud/config/config.php

# Add or update this block inside the $CONFIG array:
'trusted_proxies' =>
  array (
    0 => '127.0.0.1',
    1 => '::1',
    2 => '172.16.0.0/12',
    3 => '192.168.0.0/16',
    4 => '10.0.0.0/8',
  ),
'overwriteprotocol' => 'https',

Then restart Apache:

sudo systemctl restart apache2

Expose Nextcloud to the Internet with Localtonet

With Nextcloud running locally, the next step is making it accessible from anywhere. Localtonet creates an encrypted outbound tunnel from your machine to a public HTTPS endpoint. No port forwarding, no static IP, and it works behind CGNAT.

1

Install Localtonet

# Linux (Ubuntu, Debian, Raspberry Pi OS):
curl -fsSL https://localtonet.com/install.sh | sh

# Verify:
localtonet --version
2

Authenticate with your AuthToken

Register at localtonet.com, go to Dashboard → My Tokens, copy your token, and authenticate:

localtonet --authtoken YOUR_TOKEN_HERE
3

Create an HTTP tunnel for Nextcloud

Go to localtonet.com/tunnel/http and fill in:

  • IP: 127.0.0.1
  • Port: 8080 (Docker Compose) or 80 (NextcloudPi)
  • AuthToken: Select your token
  • Custom Subdomain (optional): e.g. mycloud

Click Create, then Start.

4

Add the public URL to Nextcloud's trusted domains

The dashboard shows your public URL, e.g. https://mycloud.localto.net. Add it as a trusted domain so Nextcloud accepts requests from it:

# Docker Compose:
docker exec --user www-data nextcloud-app php occ config:system:set trusted_domains 1 --value="mycloud.localto.net"

# NextcloudPi:
sudo -u www-data php /var/www/nextcloud/occ config:system:set trusted_domains 1 --value="mycloud.localto.net"

Expected output:

System config value trusted_domains => 1 set to string mycloud.localto.net
5

Also set overwritehost and overwriteprotocol

This tells Nextcloud to generate links using your public domain and HTTPS:

# Docker Compose:
docker exec --user www-data nextcloud-app php occ config:system:set overwritehost --value="mycloud.localto.net"
docker exec --user www-data nextcloud-app php occ config:system:set overwriteprotocol --value="https"

# NextcloudPi:
sudo -u www-data php /var/www/nextcloud/occ config:system:set overwritehost --value="mycloud.localto.net"
sudo -u www-data php /var/www/nextcloud/occ config:system:set overwriteprotocol --value="https"
6

Run Localtonet as a service (always-on)

sudo localtonet --install-service --authtoken YOUR_TOKEN_HERE
sudo localtonet --start-service --authtoken YOUR_TOKEN_HERE

The tunnel now starts automatically on every reboot alongside Nextcloud.

Essential occ Commands for Nextcloud Administration

The occ (ownCloud Console) tool is the Nextcloud command-line administration tool. Many settings that look confusing in the web UI are one-liners via occ. Always run it as the www-data user.

Task Docker Compose Command
Check overall status docker exec --user www-data nextcloud-app php occ status
List all config values docker exec --user www-data nextcloud-app php occ config:list
Add trusted domain docker exec --user www-data nextcloud-app php occ config:system:set trusted_domains 2 --value="yourdomain.com"
Enable maintenance mode docker exec --user www-data nextcloud-app php occ maintenance:mode --on
Disable maintenance mode docker exec --user www-data nextcloud-app php occ maintenance:mode --off
Run database migrations docker exec --user www-data nextcloud-app php occ db:add-missing-indices
Scan all user files docker exec --user www-data nextcloud-app php occ files:scan --all
List installed apps docker exec --user www-data nextcloud-app php occ app:list
Install an app docker exec --user www-data nextcloud-app php occ app:install memories
Upgrade Nextcloud docker exec --user www-data nextcloud-app php occ upgrade
Create a user docker exec --user www-data nextcloud-app php occ user:add username

Backing Up Your Nextcloud

Nextcloud data lives in three places that all must be backed up together: the database, the application config, and the user data files.

Docker Compose Backup Script

Docker
#!/bin/bash
# Save as ~/nextcloud/backup.sh and run via cron: 0 2 * * * ~/nextcloud/backup.sh

BACKUP_DIR="/mnt/backup/nextcloud/$(date +%F)"
mkdir -p "$BACKUP_DIR"

cd ~/nextcloud

# 1. Enable maintenance mode:
docker exec --user www-data nextcloud-app php occ maintenance:mode --on

# 2. Dump the database:
docker exec nextcloud-db mysqldump \
  -u nextcloud -p"$MYSQL_PASSWORD" nextcloud \
  > "$BACKUP_DIR/nextcloud-db.sql"

# 3. Back up config and data:
rsync -a ./data/ "$BACKUP_DIR/data/"
rsync -a $(docker volume inspect nextcloud_nextcloud_html --format '{{.Mountpoint}}'/config) "$BACKUP_DIR/config/"

# 4. Disable maintenance mode:
docker exec --user www-data nextcloud-app php occ maintenance:mode --off

echo "Backup complete: $BACKUP_DIR"

NextcloudPi Backup (Raspberry Pi)

Raspberry Pi

NextcloudPi has a built-in backup tool accessible from the panel at https://<pi-ip>:4443. Go to Config → nc-backup to set a backup path and schedule. Or use the command-line:

# Manual backup via ncp-config:
sudo ncp-config

# Navigate to: Config > nc-backup
# Set the destination path (e.g., /mnt/backup)
# Run backup

# Or directly:
sudo -u www-data php /var/www/nextcloud/occ maintenance:mode --on
sudo rsync -a /var/www/nextcloud/data/ /mnt/backup/nextcloud-data/
sudo mysqldump -u nextcloud -p nextcloud > /mnt/backup/nextcloud-db.sql
sudo -u www-data php /var/www/nextcloud/occ maintenance:mode --off

Updating Nextcloud

Update with Docker Compose

Docker
cd ~/nextcloud

# Pull new images:
docker compose pull

# Recreate containers:
docker compose up -d --remove-orphans

# Run the Nextcloud upgrade:
docker exec --user www-data nextcloud-app php occ upgrade

# Fix any missing database indices:
docker exec --user www-data nextcloud-app php occ db:add-missing-indices

# Clear caches:
docker exec --user www-data nextcloud-app php occ maintenance:repair
Never skip major versions

Do not upgrade from Nextcloud 28 directly to Nextcloud 30. Upgrade one major version at a time (28 → 29 → 30). Check docker exec --user www-data nextcloud-app php occ status before and after each upgrade to confirm the version.

Update with NextcloudPi

Raspberry Pi
# Via the web panel at https://<pi-ip>:4443:
# Navigate to: Updates > nc-update-nextcloud

# Or via command line:
sudo ncp-update

# To update only Nextcloud (not the Pi OS):
sudo -u www-data php /var/www/nextcloud/updater/updater.phar

Troubleshooting

Problem Cause Fix
"Access through untrusted domain" The hostname used to access Nextcloud is not in trusted_domains Run: docker exec --user www-data nextcloud-app php occ config:system:set trusted_domains 1 --value="yourdomain"
Blank page or redirect loop after login via tunnel trusted_proxies not set or overwriteprotocol missing Add TRUSTED_PROXIES=172.16.0.0/12 192.168.0.0/16 10.0.0.0/8 and APACHE_DISABLE_REWRITE_IP=1 to docker-compose.yml environment. Restart app container.
Files not appearing after upload via external drive Nextcloud file index not updated Run: docker exec --user www-data nextcloud-app php occ files:scan --all
Database errors after upgrade Missing indices or columns from migration Run: docker exec --user www-data nextcloud-app php occ db:add-missing-indices and occ maintenance:repair
Nextcloud stuck in maintenance mode Failed upgrade or manual mode left on Run: docker exec --user www-data nextcloud-app php occ maintenance:mode --off
Slow performance on Raspberry Pi SD card I/O bottleneck or missing Redis cache Move data to USB SSD. Confirm Redis is running: docker compose ps nextcloud-redis. Add APCu for local cache in config.php.
Mobile app cannot connect via public URL overwriteprotocol or overwritehost not set Set both values via occ as shown in the tunnel setup section. The mobile app requires HTTPS links generated by Nextcloud to match the domain you are accessing.
Nextcloud container keeps restarting MariaDB not ready when Nextcloud starts Add depends_on: db to the app service in docker-compose.yml. If already present, check DB logs: docker compose logs db.

Frequently Asked Questions

Can I self-host Nextcloud without a static IP address?

Yes. A Localtonet tunnel creates an outbound connection from your machine to a public endpoint, so no inbound static IP or open port is required. The tunnel works even behind CGNAT (Carrier Grade NAT), which is common with home ISPs in 2026. Your Nextcloud gets a persistent public HTTPS URL regardless of your IP address.

What is the best Raspberry Pi model for self-hosting Nextcloud?

Raspberry Pi 4 (4 GB RAM) or Raspberry Pi 5 (4 GB or 8 GB RAM) are the minimum for a smooth experience. The Pi 5 is significantly faster and handles concurrent users and the Memories photo app much better. Always boot from a USB SSD rather than a microSD card for much better I/O performance and reliability. Pi Zero and Pi 3 are too slow for general Nextcloud use.

What is trusted_proxies in Nextcloud and why does it matter?

Nextcloud's trusted_proxies setting tells Nextcloud which IP addresses are allowed to act as reverse proxies. When you use a tunnel like Localtonet, traffic arrives with the tunnel's internal IP in the headers. Without trusted_proxies covering that IP range, Nextcloud rejects the request, resulting in a blank page, redirect loop, or "untrusted proxy" error. Setting TRUSTED_PROXIES=172.16.0.0/12 192.168.0.0/16 10.0.0.0/8 in the Docker environment covers all private IP ranges including Docker bridge networks.

How do I access Nextcloud on my phone?

Install the Nextcloud app for iOS or Android. Open it, tap "Add account", and enter your public HTTPS URL (e.g. https://mycloud.localto.net). Log in with your admin or user credentials. File sync, photo backup, calendar, and contacts all work through the app. Make sure overwriteprotocol is set to https and overwritehost matches your public domain, otherwise the app may generate incorrect internal links.

How much storage can I use with self-hosted Nextcloud?

As much as you attach to the machine. There is no artificial storage limit. A common setup is a Raspberry Pi with a 4 TB external USB hard drive for data. For larger setups, Nextcloud supports external storage backends including SMB/NFS network shares, Amazon S3, and other object storage services. The data directory can be changed after installation using the datadirectory setting in config.php.

Is self-hosted Nextcloud secure?

Yes, when configured correctly. Key security steps: use strong admin and user passwords, keep Nextcloud updated, always access via HTTPS (the Localtonet tunnel provides this automatically), enable two-factor authentication for the admin account, and do not expose ports 80 or 443 directly from your router if you use a tunnel. Run Nextcloud's built-in security scan at Settings → Administration → Overview to see any configuration warnings.

Access Your Self-Hosted Nextcloud from Anywhere

Localtonet creates a secure HTTPS tunnel for your Nextcloud instance without port forwarding, a static IP, or a VPS. Works behind CGNAT. Free to start.

Get Started Free →

Localtonet is a secure multi-protocol tunneling and proxy platform designed to expose localhost, devices, private services, and AI agents to the public internet supporting HTTP/HTTPS tunnels, TCP/UDP forwarding, mobile proxy infrastructure, file server publishing, latency-optimized game connectivity, and developer-ready AI agent endpoint exposure from a single unified control plane.

support