Self-hosted • Privacy-first • No tracking
Home / Homelab / Nextcloud v34 vs Immich: The Ultimate Self-Hosted Photo Backup Guide
Homelab #homelab#docker-compose#immich#nextcloud#photo-backup ⏱ 12 min • 👁 2 • Sep 04, 2026

Nextcloud v34 vs Immich: The Ultimate Self-Hosted Photo Backup Guide

Compare Nextcloud v34 and Immich for photo backup in your homelab. Step-by-step Docker Compose install guides, performance expectations, and troubleshooting.

AdSense — Top (970x90) • Responsive
Nextcloud v34 vs Immich: The Ultimate Self-Hosted Photo Backup Guide

Introduction

Choosing the right platform for self-hosted photo backup is a critical decision for any homelab enthusiast. Nextcloud has long been the Swiss Army knife of file synchronization, offering a complete suite of productivity tools alongside file storage. In 2026, Nextcloud v34 (specifically v34.0.3) continues this legacy with improved performance and a refined interface. On the other hand, Immich has emerged as a dedicated solution, engineered specifically for photo and video management, boasting machine-learning-powered search and a mobile-first experience that rivals commercial cloud services.

This guide aims to provide a technical, side-by-side comparison and installation walkthrough for both systems. You will learn how to deploy Nextcloud v34.0.3 and Immich using Docker Compose, configure them for a homelab environment, and understand the critical differences in storage architecture, backup strategies, and hardware expectations. We will not provide fictional benchmark numbers; instead, we will focus on the architectural factors that influence performance.

By the end of this guide, you will have a clear understanding of which platform fits your specific needs—whether you require a full-fledged file sync suite or a laser-focused photo management tool. Both installation paths are presented with production-ready Docker Compose files, environment variable management, and common troubleshooting steps. The goal is to give you a functional deployment that you can extend and harden according to your homelab standards.

Let's dive straight into the prerequisites, followed by a step-by-step installation for each platform. We will then cover advanced configurations like reverse proxies and backups, and conclude with a detailed FAQ section.

Prerequisites

Before you begin, ensure your homelab server meets the following baseline requirements. These are typical estimates; actual usage will vary based on the number of users, library size, and enabled features like full-text search or facial recognition.

Component Nextcloud v34 (Recommended) Immich (Recommended) Notes
CPU 2-4 cores (x86_64/ARM64) 4-6 cores (x86_64/ARM64) Immich's ML pipeline benefits from more cores.
RAM 2-4 GB (typical) 4-6 GB (typical) Allocated to DB, PHP-FPM, and Redis.
Storage 20 GB + data volume 50 GB + data volume Use SSD for DB volume, HDD for bulk data.
OS Ubuntu 22.04/24.04, Debian 12 Ubuntu 22.04/24.04, Debian 12 Linux with kernel >= 5.10 for io_uring support in DB.
Software Docker Engine 24+, Docker Compose v2 Docker Engine 24+, Docker Compose v2 Ensure docker compose plugin is installed.

Core Services Required by Both:

  • Reverse Proxy (Optional but Recommended): Nginx Proxy Manager, Traefik, or Caddy. Needed for SSL termination and domain-based routing.
  • Domain Name: A subdomain like cloud.example.com or photos.example.com. If you don't have a domain, configure access via IP and port, but SSL will be tricky.
  • Port Availability: Ensure ports 80, 443, and 8080 (for Immich) are free or properly mapped.

Step-by-Step Installation Guide

We will deploy both applications in separate directories with dedicated .env files. This ensures isolation and simplifies upgrades. We are using the latest verified versions: Nextcloud v34.0.3 and Immich latest (check the official releases page before pinning).

Part 1: Nextcloud v34.0.3 Setup

Step 1: Create Directory Structure and .env File

First, create the base directory and navigate into it. Then, create the .env file that will hold your secrets. Never commit this file to your Git repository.

mkdir -p ~/nextcloud-34 && cd ~/nextcloud-34 &&
touch .env && chmod 600 .env

Now, edit the .env file with your preferred text editor (e.g., nano .env). Populate it with the following content. Replace the passwords with strong, unique values.

# Nextcloud v34.0.3 Installation Environment Variables
NEXTCLOUD_VERSION=34.0.3
MYSQL_DATABASE=nextcloud
MYSQL_USER=nextcloud
MYSQL_PASSWORD=choose_a_strong_password
MYSQL_ROOT_PASSWORD=choose_a_different_strong_root_password
NEXTCLOUD_ADMIN_USER=admin
NEXTCLOUD_ADMIN_PASSWORD=choose_a_strong_admin_password

Step 2: Create Docker Compose File

Create a docker-compose.yml file in the same directory. This file defines the Nextcloud application, a MySQL database, and a Redis cache. The configuration is complete and production-ready.

services:
  db:
    image: mariadb:11.4
    restart: always
    command: --transaction-isolation=READ-COMMITTED --log-bin=binlog --binlog-format=ROW
    volumes:
      - ./db:/var/lib/mysql
    environment:
      - MYSQL_DATABASE=${MYSQL_DATABASE}
      - MYSQL_USER=${MYSQL_USER}
      - MYSQL_PASSWORD=${MYSQL_PASSWORD}
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
    healthcheck:
      test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7.2-alpine
    restart: always
    command: redis-server --appendonly yes
    volumes:
      - ./redis:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

  app:
    image: nextcloud:${NEXTCLOUD_VERSION}
    restart: always
    ports:
      - "8080:80"
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    volumes:
      - ./nextcloud:/var/www/html
      - ./data:/var/www/html/data
    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=localhost,127.0.0.1,cloud.example.com
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:80/status.php"]
      interval: 30s
      timeout: 10s
      retries: 5

volumes: {}

Step 3: Deploy Nextcloud

Run the following command to pull the images and start the containers in detached mode.

cd ~/nextcloud-34 && docker compose up -d

Wait for the health checks to pass. You can monitor the status with docker compose ps. Once the app service is healthy, navigate to http://your-server-ip:8080. You should see the Nextcloud login page. Log in with the admin credentials you set in the .env file.

Part 2: Immich Setup

Immich consists of multiple services: a server, a machine-learning worker, a Redis cache, a Postgres database, and a web interface. We will use the official docker-compose.yml from the Immich GitHub repository, but we will parameterize the versions.

Step 4: Create Directory Structure and .env File

mkdir -p ~/immich && cd ~/immich &&
touch .env && chmod 600 .env

Populate the .env file with the following. Important: Immich requires a specific version tag for the server and machine-learning images. As of this writing, the latest release is v1.118.0. Since this is a rapidly moving target, we will use release as a tag, but you must check the official GitHub releases page before pinning a version. The version above may be outdated by now.

# Immich Installation Environment Variables
IMMICH_VERSION=release
DB_PASSWORD=choose_a_strong_db_password
DB_USERNAME=immich
DB_DATABASE_NAME=immich

Step 5: Create Docker Compose File

Create a docker-compose.yml file. This is a trimmed-down but fully functional version of the official Immich compose file. It includes the database, server, machine learning, and web frontend.

services:
  immich-server:
    container_name: immich_server
    image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION}
    command: ['start.sh', 'immich']
    volumes:
      - ./library:/usr/src/app/upload
      - ./model-cache:/usr/src/app/.cache
    env_file:
      - .env
    environment:
      - DB_HOSTNAME=immich-postgres
      - DB_PORT=5432
      - DB_USERNAME=${DB_USERNAME}
      - DB_PASSWORD=${DB_PASSWORD}
      - DB_DATABASE_NAME=${DB_DATABASE_NAME}
      - REDIS_HOSTNAME=immich-redis
    ports:
      - 2283:3001
    depends_on:
      - immich-redis
      - immich-postgres
    restart: always

  immich-machine-learning:
    container_name: immich_machine_learning
    image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION}
    volumes:
      - ./model-cache:/cache
    env_file:
      - .env
    environment:
      - DB_HOSTNAME=immich-postgres
      - DB_PORT=5432
      - DB_USERNAME=${DB_USERNAME}
      - DB_PASSWORD=${DB_PASSWORD}
      - DB_DATABASE_NAME=${DB_DATABASE_NAME}
      - REDIS_HOSTNAME=immich-redis
    depends_on:
      - immich-redis
      - immich-postgres
    restart: always

  immich-postgres:
    container_name: immich_postgres
    image: docker.io/tensorchord/pgvecto-rs:pg14-v0.2.0
    environment:
      - POSTGRES_PASSWORD=${DB_PASSWORD}
      - POSTGRES_USER=${DB_USERNAME}
      - POSTGRES_DB=${DB_DATABASE_NAME}
    volumes:
      - ./pgdata:/var/lib/postgresql/data
    restart: always

  immich-redis:
    container_name: immich_redis
    image: docker.io/redis:6.2-alpine
    restart: always

Step 6: Deploy Immich

cd ~/immich && docker compose up -d

After the containers start, give the server a minute to initialize. Access the web UI at http://your-server-ip:2283. Create your admin account on the first visit.

Advanced Setup and Optimization

Reverse Proxy and SSL

For a professional setup, you should place a reverse proxy in front of both services. This allows you to use standard ports (443) and enable HTTPS.

Step 7: Configure Reverse Proxy (Example with Nginx Proxy Manager)

Assuming you have Nginx Proxy Manager (NPM) running, add a Proxy Host for cloud.example.com pointing to http://your-server-ip:8080 (Nextcloud) and another for photos.example.com pointing to http://your-server-ip:2283 (Immich). Enable SSL via Let's Encrypt.

For Nextcloud, you must update the NEXTCLOUD_TRUSTED_DOMAINS in your docker-compose.yml and restart the container.

cd ~/nextcloud-34 && docker compose up -d

Backups

Step 8: Backup Strategy

  • Nextcloud: Stop the containers, back up the nextcloud (config) and data directories, and dump the MySQL database.
    cd ~/nextcloud-34 && docker compose exec -T db mysqldump -u root -p"${MYSQL_ROOT_PASSWORD}" --all-databases > backup.sql && tar -czf nextcloud_backup.tar.gz ./nextcloud ./data backup.sql
    
  • Immich: Immich provides an official backup script. It is best to use docker compose exec to dump the Postgres database and copy the library folder.
    cd ~/immich && docker compose exec -T immich-postgres pg_dump -U ${DB_USERNAME} -d ${DB_DATABASE_NAME} > immich_db_backup.sql && tar -czf immich_backup.tar.gz ./library immich_db_backup.sql
    

Optional Hardening

Warning: The following settings are advanced and can break containers if applied incorrectly. They must be adapted for each specific application and image. Do not copy them blindly.

For Nextcloud, you might add a security_opt and read_only to the app service, but this requires careful volume management for the data and config directories. For Immich, the machine-learning container requires a writable /cache directory. Adding cap_drop might break network operations. Always test in a staging environment first.

Troubleshooting Common Errors

Common Error Cause Solution
Nextcloud is not installed loop The NEXTCLOUD_ADMIN_USER and NEXTCLOUD_ADMIN_PASSWORD environment variables are not being read correctly. Ensure the .env file is in the same directory as your docker-compose.yml and that the variables are correctly named. Run docker compose config to see the resolved environment variables.
File not found in Nextcloud when accessing data The ./data volume is not mounted correctly or has permission issues. Check the volume path in your compose file. On the host, run id -u && id -g and verify against the image's documentation. The default user in the Nextcloud image is www-data (UID 33). You may need to adjust host directory ownership.
Immich server fails to start with ECONNREFUSED for Postgres The Postgres container is not healthy when the server tries to connect. Add a depends_on condition for the server service to wait for the database healthcheck. Increase the healthcheck interval in the Postgres service definition.
Immich ML container crashes with OOMKilled The machine-learning model requires more memory than the container has. Increase the memory limit for the container in the compose file (e.g., mem_limit: 4g). Also, check the IMMICH_MACHINE_LEARNING_WORKERS environment variable; reduce the number of workers to lower memory usage.
Slow uploads to Nextcloud The PHP memory limit is too low, or the opcache is not configured. Edit the nextcloud container's php.ini via a custom config file mounted into the container. Increase memory_limit to 1024M and upload_max_filesize to 10G.
Immich shows a blank screen after login The web frontend cannot connect to the server API. Check the browser's developer console for CORS errors. Ensure the IMMICH_SERVER_URL and IMMICH_WEB_URL environment variables are set correctly if you are using a reverse proxy.
docker compose up fails with a port conflict Another service is already using port 8080 or 2283. Change the host port mapping in your compose file (e.g., 8081:80 for Nextcloud).

Conclusion and FAQ

Choosing between Nextcloud and Immich is not a matter of which is objectively better, but which is better for your specific workflow. Nextcloud v34 offers an all-in-one solution that provides file sync, collaborative editing, and a robust API, making it ideal for users who want to replace Google Drive entirely. Immich, with its dedicated focus on media, delivers a superior photo management experience with features like semantic search and timeline clustering that are typically found in commercial services like Google Photos.

For a homelab, you can run both side-by-side without issue, as we have demonstrated. This gives you the flexibility of a general-purpose file sync tool and the specialized power of a media manager. Remember to always check the official release notes for updates, as the self-hosted ecosystem evolves rapidly.

FAQ

1. Can I migrate from Nextcloud's built-in photos app to Immich?

Yes, but there is no direct one-click migration tool. You can use the Nextcloud API to download all photos and then use Immich's web uploader to re-upload them. For a large library, consider using a CLI tool like rclone to sync from the Nextcloud WebDAV endpoint to a local folder, and then use the Immich CLI to import that folder.

2. Which platform uses less RAM on a typical homelab server?

Nextcloud is generally lighter on RAM if you disable expensive features like full-text search or server-side encryption. A typical Nextcloud deployment with a few users might use 1-2 GB of RAM. Immich, due to its machine-learning components, typically requires 3-4 GB of RAM to function smoothly. However, these are estimates; the actual usage depends on the number of background jobs and active users.

3. Is it safe to expose these services directly to the internet?

No, it is not recommended. You should always place a reverse proxy with HTTPS and strong authentication in front of them. For Nextcloud, use the built-in brute-force protection and consider adding two-factor authentication. For Immich, ensure your instance is not publicly accessible without a VPN or a secure proxy, as it is a newer project and may not have as many hardening features as Nextcloud.

4. How do I update Immich to the latest version?

Immich releases new versions frequently. The easiest method is to pull the latest images and recreate the containers. First, check the official release notes for any breaking changes. Then, run cd ~/immich && docker compose pull && docker compose up -d. It is good practice to back up your database and library directory before performing an update.

5. Can I use an external database for Nextcloud instead of the MariaDB container?

Yes, you can. You can configure Nextcloud to use an external PostgreSQL or MySQL instance. This is useful if you already have a centralized database server in your homelab. You would remove the db service from the compose file and change the MYSQL_HOST environment variable in the app service to point to your external database host. You will also need to manually create the database and user on the external server.

AdSense — In-article (responsive)

Related Guides