Deployment guide

Ente

Overview

Ente Photos is an open source, fully end-to-end-encrypted photo storage and backup platform. Every photo, video and its metadata is encrypted on your device before upload, so the server stores only ciphertext. No one, including you as the operator, can read the library without your password.

This SecureAnyCloud image runs Ente Photos on Ubuntu 24.04 LTS. The same self-hosted server works with the Ente web, mobile (iOS/Android) and desktop apps, giving you automatic encrypted backup from every device.

Ente self-hosts as a small set of services, orchestrated by Docker Compose and managed by systemd:

  • museum: the Ente API server (Go), listening on :8080
  • web: the Photos web app, on :3000
  • postgres: PostgreSQL 15, holding account, collection and file metadata (never exposed off the instance)
  • minio: an S3-compatible object store on :3200, holding the encrypted photo and video blobs

nginx on port 80 serves the Photos web app at /, proxies the API at /api/, and answers an unauthenticated /healthz for load-balancer probes. Clients upload encrypted blobs directly to the object store, so the object store is published on port 3200.

What you get:

  • The full Ente self-host stack (museum, web, PostgreSQL, MinIO), run under Docker Compose by an ente.service systemd unit from images pinned by digest
  • The Photos web app and API on :80 behind nginx, and the encrypted object store on :3200
  • Every secret generated fresh per VM on first boot: the PostgreSQL password, the object-store access and secret keys, and the three museum master secrets (encryption key, hash key, JWT secret). No baked default survives into the image.
  • No server-side admin password. Because Ente is end-to-end encrypted, you create your account from the app and your keys are generated on your device.
  • PostgreSQL and the encrypted blob store on a dedicated Azure data disk at /var/lib/ente, captured into the image
  • An unauthenticated /healthz endpoint for Azure Load Balancer health probes
  • 24/7 SecureAnyCloud support

Prerequisites

You need an active Azure subscription, an SSH key pair, and a VNet with a subnet in the target region. Standard_B2s (2 vCPU / 4 GiB RAM) is a sensible starting point. Choose a larger size for big libraries or many devices.

Configure the network security group (NSG) to allow inbound 22/tcp from your management network, and 80/tcp (web app and API) and 3200/tcp (encrypted object storage) from your clients. Both ports must be reachable from every device you upload from, because clients upload encrypted blobs directly to the object store.

Assign a static public IP. The upload endpoint is derived from the VM's public IP on first boot and embedded in the object-store URLs the client uses. If the IP later changes, uploads break until the endpoint is refreshed. A static public IP avoids this.

Ente serves plain HTTP here. For production, put your own domain and TLS in front of both the web app and the object store.

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Ente Photos by SecureAnyCloud, and select Create.

On the Basics tab, pick your subscription, resource group, region and size. Under Administrator account, choose SSH public key and paste your key. Under Inbound port rules, allow SSH (22).

Review the dedicated data disk on the Disks tab, then select Review + create and Create. After the VM is created, also open ports 80 and 3200. Step 2 shows the CLI equivalent.

Step 2 - Deploy from the Azure CLI

# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:ente-ubuntu-24-04:default:latest
az vm create \
  --resource-group <your-rg> \
  --name ente \
  --image sac1647283583153:ente-ubuntu-24-04:default:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_ed25519.pub \
  --vnet-name <your-vnet> --subnet <your-subnet> \
  --public-ip-sku Standard
az vm open-port --resource-group <your-rg> --name ente --port 80 --priority 1010
az vm open-port --resource-group <your-rg> --name ente --port 3200 --priority 1020

Step 3 - Connect to your VM

ssh azureuser@<vm-public-ip>

On the first boot, ente-firstboot.service generates every per-VM secret, sets the public-IP endpoints, brings the Compose stack up on fresh volumes and installs the object-store network rule. On a fresh VM this takes a minute or two.

Step 4 - Confirm the services are running

Ente runs as a Docker Compose stack behind nginx. Confirm that the systemd units are active and the four containers are up:

systemctl is-active docker nginx ente
sudo docker compose -f /opt/ente/compose.yaml ps

Expected output:

active active active NAME SERVICE STATUS PORTS ente-minio-1 minio Up About a minute 0.0.0.0:3200->3200/tcp ente-museum-1 museum Up About a minute (healthy) 127.0.0.1:8080->8080/tcp ente-postgres-1 postgres Up About a minute (healthy) 5432/tcp ente-web-1 web Up About a minute 127.0.0.1:3000->3000/tcp

Both the unauthenticated health endpoint and the museum API should answer:

curl -s http://localhost/healthz
curl -s http://localhost:8080/ping
ok {"id":"0137a0c754ac0fe4f2c4c7421727c349327eb990","message":"pong"}

Step 5 - Retrieve the per-VM secrets

Every secret is generated fresh on this VM's first boot and written to a root-only file. There is no admin password, because Ente is end-to-end encrypted and you create your account from the app. The file records the object-store and database secrets, the server URL and the account-creation steps. Read it with sudo:

sudo cat /root/ente-credentials.txt
# Ente Photos self-host - generated on first boot by ente-firstboot.service.
# These per-VM secrets are unique to THIS VM. Store them somewhere safe. ENTE_URL=http://20.55.x.x/ ENTE_MINIO_ACCESS_KEY=minio-user-HHm4Cp62 ENTE_MINIO_SECRET_KEY=zhb8nfls**************** (unique per VM) ENTE_DB_PASSWORD=/Iw5abXpr**************** (unique per VM)
# HOW TO CREATE YOUR ACCOUNT
# Ente is end-to-end encrypted, so there is NO server-side admin password: you create
# your account from the web app and your keys are generated on your device...

Step 6 - Create your end-to-end-encrypted account

Open the Photos web app at http://<vm-public-ip>/ and choose Sign up. Enter your email and a password.

The password derives your encryption key on your device. Keep it safe, because the server cannot recover it.

Ente normally sends a 6-digit verification code by email. This appliance does not send email, so it writes the code to the server logs instead. Retrieve it with:

sudo docker compose -f /opt/ente/compose.yaml logs museum | grep -i "verification code" | tail -1
INFO email.go:111 Skipping sending email to you@example.com: Verification code: 140076

Enter that code in the web app to finish creating your account.

Step 7 - Sign in and upload your first photos

After verification, you land in your encrypted library.

Click Upload and choose Files or Folder, or drag and drop into the window, to add photos and videos. Each item is encrypted in your browser before it leaves your device. It is then stored as an opaque blob in the object store on port 3200, so the server holds only ciphertext.

Step 8 - Connect the mobile and desktop apps

Install the official Ente Photos app (iOS, Android, macOS, Windows or Linux). On the sign-in screen, open the developer/self-host option and set the endpoint to your server. Then sign in with the same account:

http://<vm-public-ip>/api

The mobile apps can then back up your camera roll automatically, encrypted end to end, to storage you control.

Health checks and troubleshooting

  • Health probe: curl -s http://<vm-public-ip>/healthz returns ok.
  • Restart the stack: sudo systemctl restart ente
  • View server logs: sudo docker compose -f /opt/ente/compose.yaml logs museum
  • Uploads fail from a phone or another machine: confirm that port 3200 is open in your NSG and that the public IP has not changed since first boot. The object-store endpoint is pinned to the boot-time IP, so use a static IP.

Support

SecureAnyCloud maintains this image and provides 24/7 support. The Ente project is developed at github.com/ente-io/ente and is licensed under the GNU Affero General Public License v3.0.

Deploy on Azure

Launch Ente Photos on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure