Last updated: March 22, 2026

Privacy-Focused Photo Storage Solutions

Google Photos and Apple iCloud analyze every photo you upload. detecting faces, locations, objects, and content. This analysis powers their search features, but also creates detailed behavioral profiles. Alternatives range from self-hosted solutions you run yourself to zero-knowledge cloud options where the provider can’t read your photos.

Table of Contents

What Photo Services Analyze

Google Photos:

Google’s face recognition clusters photos of the same person and links them to contacts in your address book. This analysis runs server-side on uploaded originals. Google’s privacy policy allows them to use your content to improve their AI models on the free plan.

Apple iCloud:

Apple’s differentiation is that most AI analysis happens on-device rather than in the cloud. However, without Advanced Data Protection enabled, Apple has the technical ability to access your iCloud photos. Law enforcement requests to Apple are far more common than requests to Ente or self-hosted providers.

Amazon Photos (with Prime):


Prerequisites

Before you begin, make sure you have the following ready:

Step 1 - Option 1: Self-Hosted. Immich

Immich is the most actively developed self-hosted Google Photos alternative. Face recognition, map view, timeline, mobile backup. feature parity with Google Photos without the surveillance. The project has grown from a side project to a dedicated team with over 40,000 GitHub stars as of 2026.

Install Immich via Docker Compose
mkdir -p ~/immich && cd ~/immich

curl -L https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml -o docker-compose.yml
curl -L https://github.com/immich-app/immich/releases/latest/download/example.env -o .env

Edit .env with your settings:
nano .env
.env
UPLOAD_LOCATION=./library     # Where photos are stored on disk
DB_PASSWORD=your_db_password
IMMICH_VERSION=release
Start Immich
docker compose up -d

Check all services are running
docker compose ps

Access - http://your-server:2283
Create admin account on first login
Set up mobile app - immich.app → download iOS/Android client
Enter server address → log inenable automatic backup

Immich features:

The machine learning features in Immich run on the immich-machine-learning container using your server’s CPU or GPU. On a modest server (4-core, 8GB RAM), initial indexing of 50,000 photos takes several hours in the background. After that, new photos are indexed within minutes of upload.

Expose Immich Securely

Never expose Immich directly. use a reverse proxy with TLS
Nginx config:

server {
    listen 443 ssl;
    server_name photos.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/photos.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/photos.yourdomain.com/privkey.pem;

    client_max_body_size 50000M;
    proxy_read_timeout 600s;

    location / {
        proxy_pass http://127.0.0.1:2283;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Use Certbot to obtain a free Let’s Encrypt TLS certificate:

sudo certbot --nginx -d photos.yourdomain.com

If you don’t want a public DNS record, run Immich over Tailscale. assign a Tailscale IP to your server and access it via https://server-name.tailnet-name.ts.net:2283 from any Tailscale device without exposing a port to the internet.


Step 2 - Option 2: Self-Hosted. PhotoPrism

PhotoPrism is more privacy-conservative in its AI features. you control which analysis runs. It’s optimized for browsing large libraries and works well as a read-heavy archive viewer rather than a live backup target.

Install PhotoPrism via Docker
mkdir -p ~/photoprism/storage ~/photoprism/originals

cat > ~/photoprism/docker-compose.yml << 'EOF'
version: '3.5'
services:
  photoprism:
    image: photoprism/photoprism:latest
    restart: unless-stopped
    ports:
      - "2342:2342"
    environment:
      PHOTOPRISM_AUTH_MODE: "password"
      PHOTOPRISM_ADMIN_PASSWORD: "StrongPassword!"
      PHOTOPRISM_SITE_URL: "https://photos.yourdomain.com/"
      PHOTOPRISM_ORIGINALS_LIMIT: 5000   # MB per upload
      PHOTOPRISM_DETECT_NSFW: "false"
      PHOTOPRISM_UPLOAD_NSFW: "true"
      # Disable AI features for maximum privacy:
      PHOTOPRISM_DISABLE_TENSORFLOW: "false"  # set true to disable all ML
      PHOTOPRISM_DISABLE_FACES: "false"
    volumes:
      - "~/photoprism/originals:/photoprism/originals"
      - "~/photoprism/storage:/photoprism/storage"
EOF

docker compose up -d

PhotoPrism works well with existing file structures. point it at directories organized by year/month and it indexes them without moving anything. This is useful if you have years of photos already on disk and want browsing capabilities without restructuring.

PhotoPrism requires a MariaDB or SQLite database for its index. For large libraries (100,000+ photos), MariaDB performs substantially better. Run photoprism index from the container shell to re-index after adding files manually.


Step 3 - Option 3: Ente Photos (Zero-Knowledge Cloud)

Ente Photos is a cloud service with zero-knowledge encryption. your photos are encrypted on your device before upload. Ente cannot see your photos, and this is verifiable because the client is open source (github.com/ente-io/ente).

Ente Photos - ente.io
Plans from $2/month for 50GB

Android/iOS - download from app stores
Desktop - available for Linux, macOS, Windows

The key difference from Google Photos:
- Photos encrypted with your master key before upload
- Ente holds only ciphertext
- Face recognition runs on-device (not on Ente's servers)

CLI tool for bulk operations:
npm install -g @ente/cli

Configure
ente config set email you@example.com
ente auth

Upload a folder
ente upload /path/to/photos "Album Name"

Download / export
ente download --album "Album Name" /local/path

Ente’s encryption uses libsodium (ChaCha20-Poly1305 for content, XSalsa20-Poly1305 for key derivation). The master key is derived from your password client-side using Argon2. Ente’s servers never see the password or the master key.

Trade-off - Ente lacks advanced search and organization features compared to Google Photos. No object search or automatic location tagging (these would require server-side analysis). The mobile app is well-polished and supports automatic backup from camera roll. The desktop app and CLI are suitable for bulk uploads from existing photo libraries.

Ente also offers an open-source self-hosted backend (ente-server) with your own storage, but the server setup is complex. For most users, Ente’s paid cloud is the practical choice.


Step 4 - Option 4: Encrypted Sync with Cryptomator

Keep photos in any cloud provider (Dropbox, S3, Backblaze) but encrypt them first:

Cryptomator creates an encrypted vault
Photos go in vault → encrypted → uploaded to cloud provider

Install Cryptomator
Download from cryptomator.org or:
flatpak install org.cryptomator.Cryptomator

Create new vault in your cloud sync folder (e.g., ~/Dropbox/Photos-Vault)
Set a strong password (20+ characters, random)
Mount the vault → drag photos in
Dropbox/cloud syncs the encrypted files

On mobile - Cryptomator iOS/Android app unlocks vault
Thumbnails are NOT generated server-side (provider sees only ciphertext)

Cryptomator encrypts both file contents and file names. Dropbox sees files with names like 6IQFHU4APB3MSNB.c9r rather than vacation-2025.jpg. This prevents the cloud provider from inferring anything about your library structure.

The main limitation is browsing - you can only view photos while the vault is mounted on a device with Cryptomator installed. There is no web interface for browsing your encrypted photos remotely, and no server-side search or organization tools.


Step 5 - Strip EXIF Metadata Before Sharing

Photos contain metadata that reveals: GPS location, camera model, date/time, sometimes even software used. Before sharing photos publicly or with services that might retain metadata, strip it.

Install ExifTool
sudo apt install libimage-exiftool-perl   # Debian/Ubuntu
brew install exiftool                      # macOS

Strip all metadata from a photo
exiftool -all= photo.jpg

Strip GPS only (keep date/camera info)
exiftool -gps:all= photo.jpg

Batch process an entire directory
exiftool -all= ~/photos/to-share/

Verify metadata was removed
exiftool photo.jpg | grep GPS
Should show nothing

Keep originals as backup (exiftool renames originals to .jpg_original by default)
To skip backup creation:
exiftool -all= -overwrite_original photo.jpg

MAT2 (Metadata Anonymization Toolkit) is an alternative that handles a broader range of file formats including PDF, LibreOffice documents, and audio:

sudo apt install mat2
mat2 photo.jpg
mat2 --inplace photo.jpg   # overwrite original

Step 6 - Backup Strategy for Self-Hosted Photos

Self-hosted photos require a separate backup strategy. the server itself can fail.

3-2-1 backup rule: 3 copies, 2 different media, 1 offsite

Immich - backup the originals directory and database
Database backup (run as cron job):
docker exec immich_postgres pg_dump -U postgres immich > ~/backup/immich-db-$(date +%Y%m%d).sql

Photo files backup to external drive:
rsync -av --delete ~/immich/library/ /media/external-backup/immich/

Offsite encrypted backup to Backblaze B2 using rclone with crypt remote:
Configure rclone with a crypt remote pointing at your B2 bucket
rclone sync ~/immich/library/ b2crypt:photos-backup/

Verify rclone backup integrity:
rclone check ~/immich/library/ b2crypt:photos-backup/

Configure rclone’s crypt remote with Backblaze B2 for zero-knowledge offsite backup:

rclone config
name: b2crypt
type: crypt
remote: b2:your-photos-bucket/encrypted
filename_encryption: standard
directory_name_encryption: true
password: (generate a strong random password)

This gives you encrypted off-site copies that Backblaze cannot read, even though your local Immich installation stores photos unencrypted for performance.


Comparison Summary

Solution Privacy Features Cost Complexity
Immich (self-hosted) High Full Server cost Medium
PhotoPrism (self-hosted) High Good Server cost Medium
Ente Photos High (ZK) Limited $2+/month Low
Cryptomator + cloud High None (browsing only) Cloud cost Low-Medium
Google Photos Low Best Free/paid None
iCloud + ADP Medium Good $1+/month Low

For most users starting from scratch: Ente Photos is the quickest path to meaningful privacy improvement. install the app, pay $2/month, and your photos are encrypted before they leave your device. For developers with a home server: Immich combined with rclone/Backblaze B2 offsite backup delivers Google Photos parity with full control.


Troubleshooting

Configuration changes not taking effect

Restart the relevant service or application after making changes. Some settings require a full system reboot. Verify the configuration file path is correct and the syntax is valid.

Permission denied errors

Run the command with sudo for system-level operations, or check that your user account has the necessary permissions. On macOS, you may need to grant terminal access in System Settings > Privacy & Security.

Connection or network-related failures

Check your internet connection and firewall settings. If using a VPN, try disconnecting temporarily to isolate the issue. Verify that the target server or service is accessible from your network.

Related Articles