DEV Community

Cover image for Setting Up Immich: The Operational Cost of Google Photos Convenience
Mustafa ERBAY
Mustafa ERBAY

Posted on Originally published at mustafaerbay.com.tr

Setting Up Immich: The Operational Cost of Google Photos Convenience

What Is Immich and What Are Its System Requirements?

Immich is a self-hosted photo and video management platform that runs components such as PostgreSQL, Redis, and Nginx inside Docker containers. For a baseline setup, a minimum of 4 CPU cores, 8 GiB RAM, and a 100 GiB SSD is recommended. The following command verifies the kernel version on Ubuntu 22.04 LTS:

uname -r
Enter fullscreen mode Exit fullscreen mode
5.15.0-1049-azure
Enter fullscreen mode Exit fullscreen mode

This output confirms that the Linux kernel belongs to the 5.15 branch and smoothly supports Docker's kernel-level features (cgroups v2, overlay2). Once these prerequisites are met, running Immich's components isolated within separate containers provides significant advantages in terms of both security and scalability.

Deployment with Docker Compose (Sample Scenario)

The docker-compose.yml file below pulls official images from Docker Hub. The configuration includes PostgreSQL 15, Redis 7, and Nginx-proxy-manager 2.10.

version: "3.9"
services:
  server:
    image: ghcr.io/immich-app/immich-server:latest
    depends_on:
      - redis
      - postgres
    environment:
      - DB_HOST=postgres
      - REDIS_HOST=redis
    ports:
      - "3001:3001"
  redis:
    image: redis:7-alpine
  postgres:
    image: postgres:15-alpine
    environment:
      POSTGRES_PASSWORD=immich
      POSTGRES_DB=immich
    volumes:
      - pgdata:/var/lib/postgresql/data
volumes:
  pgdata:
Enter fullscreen mode Exit fullscreen mode

Verifying container status after startup:

docker compose ps --format "table {{.Service}}\t{{.State}}"
Enter fullscreen mode Exit fullscreen mode
SERVICE   STATE
server    running
redis     running
postgres  running
Enter fullscreen mode Exit fullscreen mode

Seeing all services in the running state confirms that core dependencies have booted properly. The docker compose logs -f server command generates an entry confirming a successful database connection during initial boot:

2024-10-12 08:15:23.123 INFO  [server] Connected to PostgreSQL at postgres:5432
Enter fullscreen mode Exit fullscreen mode

Storage and Network Cost Analysis

Immich stores media files directly on an attached disk (e.g., /mnt/immich-data). To inspect disk usage:

df -h /mnt/immich-data
Enter fullscreen mode Exit fullscreen mode
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1       200G   45G  145G  24% /mnt/immich-data
Enter fullscreen mode Exit fullscreen mode

This output shows 24% utilization, running 45 GiB of photo/video data on a 200 GiB SSD. Network throughput can be monitored with iftop; here is a sample one-minute capture:

Total send rate: 12.3 Mb/s   Total receive rate: 9.8 Mb/s
Enter fullscreen mode Exit fullscreen mode

These numbers indicate ample bandwidth for an average family's photo-streaming workload. Google Photos offers a free tier with a fixed storage quota; Immich's SSD expense, on the other hand, depends on the regional pricing model of your chosen infrastructure provider.

Performance Monitoring and Defining SLOs

Immich collects metrics using a Prometheus exporter. Running docker compose exec server curl -s http://localhost:3001/metrics | grep http_requests_total reveals the total count of HTTP requests:

http_requests_total{method="GET",handler="/api/assets"} 124578
Enter fullscreen mode Exit fullscreen mode

This volume points to an average of roughly 124k requests per day, highlighting that our SLO should aim to keep 99.9% of request response times under 200 ms. A Grafana dashboard can be attached for real-time observability; for instance, auto-scaling could be triggered if CPU consumption exceeds 65%.

Rollback and Update Strategy

Upgrading Immich versions is handled by updating the image tag in your Docker Compose file. Always take a fresh database dump before updating:

docker compose exec postgres pg_dump -U postgres -d immich > immich_backup_$(date +%F).sql
Enter fullscreen mode Exit fullscreen mode

This command stamps the backup file with today's date. If an issue surfaces following the upgrade, rolling back is straightforward:

docker compose down
docker compose up -d
docker compose exec -T postgres psql -U postgres -d immich < immich_backup_$(date +%F).sql
Enter fullscreen mode Exit fullscreen mode

The rollback sequence restores the previous release without data loss. Command execution order is critical here: stop the database service first, bring up the targeted version, and restore the snapshot.

Cost Comparison with Google Photos

Beyond its initial 15 GB free allowance, Google Photos offers a 100 GB tier at $1.99/month. Hosting an equivalent capacity on an SSD-backed VPS running Immich—for example, a 2 vCPU, 8 GiB RAM instance—runs around $12 (Azure B2s) + $20 (200 GiB SSD) = $32/month. The trade-off is clear: Immich delivers total data privacy and full customization, whereas Google Photos involves corporate data processing and potential ad-targeting implications.

The Mermaid diagram below illustrates the architectural differences between the two approaches:

Data Backup Strategy

A disciplined backup regimen is essential for data integrity and continuity. The first line of defense is dumping the PostgreSQL database on a daily or weekly schedule using pg_dump:

docker compose exec postgres pg_dump -U postgres -d immich > /backup/immich_$(date +%F).sql
Enter fullscreen mode Exit fullscreen mode

For media files, archiving them with tar and shipping them off to secondary storage is recommended:

tar czf /backup/immich_media_$(date +%F).tar.gz /mnt/immich-data
Enter fullscreen mode Exit fullscreen mode

Transferring these backups to a secure remote destination (such as AWS S3, Azure Blob Storage, or another off-site cloud store) shields your data from local hardware failures. You can automate this process by adding an entry to crontab:

0 2 * * * /usr/local/bin/immich-backup.sh >> /var/log/immich/backup.log 2>&1
Enter fullscreen mode Exit fullscreen mode

Testing your restore pipeline is the single most reliable way to prevent catastrophic data loss. Restoring the database backup looks like this:

docker compose exec -T postgres psql -U postgres -d immich < /backup/immich_2024-09-06.sql
Enter fullscreen mode Exit fullscreen mode

Shape your backup lifecycle around your recovery time and recovery point objectives: daily backups for critical assets, weekly snapshots for less dynamic content. Pruning or archiving historical snapshots at the end of every backup cycle keeps long-term storage bills predictable.

Security and Compliance Controls

Shielding your self-hosted setup from external threats is vital for both privacy and regulatory compliance. The first step is enforcing end-to-end TLS encryption across all inbound traffic. You can issue a free Let's Encrypt certificate using certbot:

certbot certonly --webroot -w /var/www/html -d immich.example.com
Enter fullscreen mode Exit fullscreen mode

Configure the nginx reverse proxy in your Docker Compose file to consume this certificate:

  nginx:
    image: nginx:alpine
    volumes:
      - /etc/letsencrypt:/etc/letsencrypt:ro
      - /var/www/html:/usr/share/nginx/html
    ports:
      - "80:80"
      - "443:443"
Enter fullscreen mode Exit fullscreen mode

In addition, isolate inter-container communication so services only touch networks on necessary ports. For example, the server container only needs access to postgres and redis:

  server:
    networks:
      - immich_net
    depends_on:
      - postgres
      - redis
Enter fullscreen mode Exit fullscreen mode

For identity management, integrating OAuth2 or LDAP allows you to manage user access through a centralized provider. To protect data at rest, the underlying storage volume holding your media assets can be secured with a LUKS encryption layer:

cryptsetup luksFormat /dev/sda1
cryptsetup open /dev/sda1 immich-data
Enter fullscreen mode Exit fullscreen mode

Comprehensive audit trails and system monitoring should also be configured. Tools like auditd help trace unauthorized system calls and catch modifications to sensitive configuration files.

Operational Cost Breakdown

A detailed breakdown of ongoing operational costs comes down to three pillars: compute resources, storage capacity, and bandwidth egress. In a standard VPS environment, monthly compute expenses for a 2 vCPU / 8 GiB RAM box are determined by your provider's hourly rate:

Compute Cost = (Hourly Rate) × 24 × 30
Enter fullscreen mode Exit fullscreen mode

Storage expenses track directly with the volume of allocated SSD or HDD capacity:

Storage Cost = (GB per Month) × (Price per GB per Month)
Enter fullscreen mode Exit fullscreen mode

Data transfer costs are billed based on outbound egress traffic:

Bandwidth Cost = (GB Outbound) × (Price per GB)
Enter fullscreen mode Exit fullscreen mode

Secondary storage fees for backups will reflect the storage tier you pick. Storing a 200 GiB compressed backup snapshot each month scales linearly with that provider's per-gigabyte pricing. Tallying up each line item gives you the actual monthly operating bill.

Several tactics can help optimize these numbers: commit to reserved instances or leverage spot capacity for predictable workloads to shrink compute overhead. Auto-scaling lets your setup expand during heavy sync periods and dial back during quiet hours. Finally, placing a CDN in front of assets and enabling media compression will trim outbound network bills while boosting load times for end users. Combining these approaches keeps Immich financially viable and performant over the long haul.

Conclusion

Spinning up Immich via Docker Compose delivers a polished, open-source alternative for managing personal media libraries, though infrastructure and storage costs will easily outpace Google Photos' entry-level pricing. Establishing active monitoring, setting strict SLOs, and defining safe rollback paths are what keep operational overhead manageable over time. If your primary driver is rock-bottom price, Google Photos wins on convenience. If total data sovereignty, uncompromised privacy, and flexibility take precedence, hosting Immich on your own infrastructure is the way to go. A logical next step: wire up a production Prometheus-Grafana stack to generate real-time performance metrics and cost projections.

Official Sources

Top comments (0)