Ente Photos 2026.10.28 on AWS User Guide
Overview
This guide covers launching and using the Ente Photos 2026.10.28 on Ubuntu 24.04 AMI from cloudimg on Amazon EC2. It is one version of the cloudimg file sharing and sync listing on AWS Marketplace; you pick it as the software version when you subscribe and launch.
Ente is an open source, end-to-end encrypted alternative to cloud photo services. Your photos and videos are encrypted on your own devices (the web app, the Ente mobile apps or the desktop app) before they are uploaded, so the server stores only encrypted files and cannot see their content. This AMI runs Ente's own server, museum, the Ente Photos web app, PostgreSQL for account and album metadata, and an S3-compatible object store for the encrypted files, and adds the security work below.
- HTTPS from the first boot. nginx serves everything on port 443 with a certificate generated on your instance's first boot: the web app at
/, the Ente API at/api, and the upload and download paths of the object store. Port 80 redirects to HTTPS, and requests for a host name the instance does not serve are dropped. - Sign-up is closed. Upstream Ente lets anyone who can reach the server create an account. On this image nobody can sign up until you open a short sign-up window from the instance (Step 5); the window only accepts your own address and closes itself after 30 minutes, when you close it, and on every reboot.
- Every key generated on your instance. museum's encryption key, hashing key and token secret, the PostgreSQL password, the object store's access key and secret key and the TLS key are created on first boot. No password, key or database is baked into the image, and the database and the object store are created on first boot.
- Uploads on the same HTTPS address. Ente clients upload and download encrypted files directly to the object store with short-lived signed links. Upstream's quickstart puts the object store on its own port (3200) on every network interface; here it listens on the instance itself only, and every signed link points at
https://<your-host>/, through nginx. Only the three storage paths Ente uses are passed through, and a request type with a known unfixed problem (S3 Select) is refused. - Ente's server built with a patched Go. museum is built on the instance at build time from Ente's own production source commit, with Go 1.26.10. The binary in upstream's container image was built with Go 1.26.9, which has a certificate verification advisory (GO-2026-6809). No source code is changed.
- Nothing else on the network. Only SSH (22) and nginx (80, 443) listen on the instance's addresses. museum, the object store and PostgreSQL are reachable from the containers' private network only, and from the instance itself only by root and nginx.
- No container can reach the metadata service. museum, PostgreSQL and the object store are blocked from the EC2 instance metadata service, and the AMI requires IMDSv2.
- Cross site protection. Only the Ente desktop app may call the API from another origin (museum itself would answer any web site). A request that changes data is refused when it carries another web site's
Origin, and the one address that changes data on a plain link (/api/users/recover-account) needs proof that the request comes from your own pages. - Your photos on their own volume. The PostgreSQL database and the encrypted files live on a dedicated 32 GiB EBS volume mounted at
/var/lib/ente, which you can resize independently. - Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.
What is on the image: Ente museum (ente-io/ente commit 20fb6316, Ente's production server of 9 October 2026, built with Go 1.26.10), the Ente Photos web app (ente-io/ente commit 4a3e62d4, 28 October 2026), PostgreSQL 15.19, Silo RELEASE.2026-10-26T00-00-00Z (the community maintained MinIO fork that Ente's own quickstart uses), Docker Engine 29 with the Compose plugin, nginx, Ubuntu 24.04 LTS, cloud-init and the AWS Systems Manager agent. Ente publishes no numbered self-host releases; its server and web images are named after the source commit they were built from, and 2026.10.28 is the date of the newest build in this image.
Default user: ubuntu · Architecture: x86_64 · Recommended instance type: m5.large (larger for big libraries or many users)
Prerequisites
- An AWS account subscribed to the listing, an EC2 key pair and a VPC subnet with a route to the internet (or a private route you use for management).
- A security group that allows TCP 22 (SSH), TCP 443 (Ente) and TCP 80 (redirects to HTTPS) from the networks your devices use. Nothing else needs to be open.
Step 1: Launch the instance
In the AWS Marketplace listing choose Continue to Subscribe, then Continue to Configuration, pick Ente Photos 2026.10.28 on Ubuntu 24.04 as the software version and your Region, then Launch through EC2. Choose m5.large (or larger), your key pair, a security group as above, and a subnet. Under Configure storage you will see two volumes: the root volume and the 32 GiB data volume for your photos; raise the data volume's size now if you already know you need more.
With the AWS CLI (replace the values in angle brackets):
aws ec2 run-instances --region <region> --image-id <ami-id-from-the-listing> \
--instance-type m5.large --key-name <your-key-pair> \
--security-group-ids <your-security-group> --subnet-id <your-subnet> \
--metadata-options HttpTokens=required,HttpEndpoint=enabled \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=ente}]'
Your phone and the Ente apps connect to the instance by its address. For an address that never changes, attach an Elastic IP before you set up your devices (a stop and start without one gives the instance a new public address, see Step 9).
Step 2: Connect to your instance
| Version | SSH user |
|---|---|
| Ente Photos 2026.10.28 on Ubuntu 24.04 | ubuntu |
ssh -i <your-key.pem> ubuntu@<public-ip>
Step 3: Check the services
First boot generates every key and password, creates the database and the object store and starts Ente. It takes under a minute:
systemctl is-active docker cloudimg-ente-netguard ente-firstboot ente nginx
active
active
active
active
active
The three containers run under Docker Compose:
sudo docker compose -f /opt/ente/compose.yaml --env-file /etc/ente/stack.env ps --format '{{.Service}} {{.State}}'
museum running
postgres running
s3 running
Only SSH (22) and nginx (80, 443) listen on the network. museum (8080) and the object store (3200) are on loopback only, and the other two are Ubuntu's local DNS resolver:
sudo ss -lntp | awk 'NR>1 {print $4}' | sort -u
0.0.0.0:22
0.0.0.0:443
0.0.0.0:80
127.0.0.1:3200
127.0.0.1:8080
127.0.0.53%lo:53
127.0.0.54:53
[::]:22
[::]:443
[::]:80
If nginx is not active, first boot has not finished (or failed, in which case nginx stays down). Check systemctl status ente-firstboot and journalctl -u ente-firstboot.
Step 4: Get your address
sudo cat /root/ente-credentials.txt
The file is readable by root only:
# Ente Photos 2026.10.28 on Ubuntu 24.04 (cloudimg). Generated ON THIS INSTANCE at first boot.
ENTE_URL=https://ec2-<public-ip-dashed>.compute-1.amazonaws.com/
ENTE_API_ENDPOINT=https://ec2-<public-ip-dashed>.compute-1.amazonaws.com/api
ENTE_TLS_SHA256=<certificate fingerprint>
ENTE_S3_ACCESS_KEY=<ENTE_S3_ACCESS_KEY>
ENTE_S3_SECRET_KEY=<ENTE_S3_SECRET_KEY>
ENTE_DB_PASSWORD=<ENTE_DB_PASSWORD>
ENTE_URL is the web app; ENTE_API_ENDPOINT is what you give the mobile and desktop apps. The address is the instance's public DNS name from EC2 instance metadata, and the certificate also names the public and private IP addresses. To use your own DNS name, see Step 9. Ente has no administrator password: you create your account in Step 5. The object store and database secrets are only needed for backups and troubleshooting; nothing outside the instance can use them.
The built in self test checks the whole chain without creating anything:
sudo ente-selftest
SELFTEST-OK (https://ec2-<public-ip-dashed>.compute-1.amazonaws.com/ museum 20fb6316, web app, object store behind nginx, sign-up closed, metadata blocked in 3 containers)
Step 5: Create your account
The certificate is self signed, so your browser asks you to confirm it the first time. Before you accept it, compare the fingerprint your browser shows with the one on the instance (or install your own certificate, Step 9):
sudo openssl x509 -in /etc/ssl/ente/ente.crt -noout -fingerprint -sha256
Open ENTE_URL in your browser. The sign-in page names your instance at the bottom:

Sign-up is closed, so if you try Signup now the web app reports that something went wrong:
sudo ente-signup status
sign-up: closed

Open a sign-up window for your own address. Run it in your SSH session from the same network as your browser: it reads your address from the session (or give it with --from <your-ip>), and closes itself after 30 minutes:
sudo ente-signup open
ente-signup: sign-up OPEN for <your-ip> for 30 minutes. Create the account at https://ec2-<public-ip-dashed>.compute-1.amazonaws.com/
ente-signup: then read the e-mail verification code with: sudo ente-signup code <your-email>
In the browser choose Signup, enter your email address and a strong password (Ente derives your encryption key from it on your device; nobody can reset it for you), accept the terms and choose Create account. Your browser generates your encryption keys (a few seconds), then asks for a verification code. E-mail is not configured on the instance, so you read the code on the instance instead of in your mailbox:
sudo ente-signup code you@example.com

Enter the code, and Ente shows your recovery key. Save it somewhere safe: it is the only way back into your photos if you forget your password.

Choose Continue with free plan (your own server has no paid plans; Step 7 raises the quota), and your empty library opens:

Close the sign-up window as soon as your accounts exist:
sudo ente-signup close
The first account created is the instance's administrator in Ente's own terms. To add family members later, open a window for their address the same way (sudo ente-signup open --from <their-ip>), or --from any for a few minutes if they sign up from a mobile network whose address you do not know (they still need the code you read on the instance).
Step 6: Upload photos and connect your devices
Choose Upload in the web app and pick files or folders. The browser encrypts each file and uploads it directly to the object store at https://<your-host>/:

To use the Ente mobile apps (Android, iOS) or the desktop app with your server: on the app's welcome screen tap the screen seven times (on the desktop app, click it seven times) to open the developer settings, enter ENTE_API_ENDPOINT from Step 4 (for example https://<your-host>/api) and save, then log in with your email and password. The apps must trust the certificate: a self signed certificate is fine in a browser once you accept it, but a phone app needs a certificate it trusts, so for mobile use point a DNS name at the instance and install a certificate from a public authority (Step 9).
Step 7: Storage quota
Ente gives every new account its 10 GiB free plan. On your own instance raise it to what your data volume can hold:
sudo ente-storage list
id | created | quota | used
----+---------+-------+------
(0 rows)
On your instance the list shows each account (its numeric id, creation date, quota and space used). To set a quota:
sudo ente-storage set <user-id> 200
sudo ente-storage set all 200
Step 8: What the image changes from upstream's defaults
- Sign-up (
internal.disable-registrationin museum's configuration) is on, and onlyente-signupturns it off for a window. A reboot always closes it. - Public links. Ente's sharing links (public albums, Locker, Paste, Memories, Cast) need Ente's other web apps, each on its own web address. This image serves the Photos app only, and points every link museum generates at your own instance, so no link sends your viewers to an
ente.comaddress. Sharing between accounts on your instance works in the apps as usual. - E-mail. This image configures no mail server, so museum sends no e-mail: verification codes are read on the instance with
ente-signup code, and Ente's notification e-mails (for example storage or sharing notices) are not sent. museum's configuration file is generated by the image's helpers, so contact cloudimg support if you need museum to send e-mail through your own mail server. - Passkeys and family plans use Ente's separate accounts web app, which this image does not serve, so they are not available. Two-factor authentication with an authenticator app works from the Photos app's settings.
Step 9: Use your own host name and certificate
Point a DNS record at the instance (an Elastic IP keeps the address across stop and start), then tell Ente its name. This mints a new self signed certificate for that name, updates nginx, the cross site guards and the web app, points museum's signed upload links at the new name, and keeps the name across reboots:
sudo ente-set-hostname photos.example.com
To use a certificate from a public authority instead, replace /etc/ssl/ente/ente.crt (full chain) and /etc/ssl/ente/ente.key (mode 0600, owned by root) with your own, copy the new certificate to museum's trust file and restart it:
sudo install -m 0444 /etc/ssl/ente/ente.crt /etc/ente/tls/trust.pem
sudo systemctl reload nginx
sudo docker compose -f /opt/ente/compose.yaml --env-file /etc/ente/stack.env restart museum
Running ente-set-hostname again later would replace them with a new self signed pair. After a name change, point your apps at the new https://<name>/api.
Without your own name, each boot checks the instance's names: after a stop and start that changed the public address, the next boot issues a new certificate for the new name and updates Ente; your apps then need the new address. Nothing changes on a boot where the names are the same.
Step 10: Storage, backups and persistence
The database and every encrypted file are on the data volume:
findmnt -no SOURCE,SIZE,TARGET /var/lib/ente
sudo ls /var/lib/ente
/dev/nvme1n1 31.2G /var/lib/ente
db
lost+found
objects
To grow it, increase the volume's size in the EC2 console (or aws ec2 modify-volume), then sudo resize2fs /dev/nvme1n1 (check the device name with findmnt). The simplest complete backup is an EBS snapshot of both volumes (or AWS Backup on the instance); for a consistent snapshot, stop the stack first with sudo systemctl stop ente and start it again afterwards. Keep /etc/ente in your backups too: museum's keys in it are needed to read the database (the photos themselves stay encrypted with your account's keys).
Every service is enabled, so Ente returns after a reboot or a stop and start, and unattended security upgrades keep the operating system, nginx and Docker patched:
systemctl is-enabled docker ente ente-set-host nginx unattended-upgrades
enabled
enabled
enabled
enabled
enabled
The secrets the containers use are files under /etc/ente (root only). The compose project is /opt/ente/compose.yaml; its images are pinned and are never pulled at boot.
Security notes
- No shared secret ships in the image. No password, key, certificate or database exists until your instance's first boot creates them, and nginx does not start before that has finished. Every secret reaches the containers as a read only file, never as a container environment value. museum's image still contains upstream's development configuration with its public example keys; the per instance configuration replaces every one of them.
- Sign-up and accounts. Sign-up is refused by museum itself while closed; while a window is open, nginx passes the two account creation calls only from the address you named. Verification codes appear only in museum's log, readable by root.
- Containers run unprivileged. museum runs as its own user on a read only file system, the object store and PostgreSQL as their own users, all with every Linux capability dropped. From the instance itself only root and nginx can reach museum and the object store, and only root can reach the containers' own addresses.
- Advisories. Ente's published advisories (GHSA-2hxj-953x-c2vw, emergency contacts could skip the recovery notice period; GHSA-v6x7-rrch-9q9w, 2of3 recovery cards) are fixed in the commits this image runs. museum is built with Go 1.26.10, so the Go standard library advisory GO-2026-6809 in upstream's binary does not apply; a scan of the built binary finds no reachable Go advisory. Two Go libraries museum depends on carry advisories with no fix (golang.org/x/crypto/openpgp GO-2026-5932, and the aws-sdk-go S3 encryption client GO-2022-0646/GO-2022-0635); museum does not use either code path.
- Reviewed residuals. The object store has one published high severity advisory with no fix yet (CVE-2026-39414, memory use in S3 Select): it needs a request signed with the instance's own object store key, and nginx refuses S3 Select requests outright. PostgreSQL's image carries a helper (gosu) built with an old Go; it never runs, because the database container starts as its own user. cloudimg rebuilds this version when upstream ships fixes.
- No access to the metadata service. The containers, Docker and nginx are blocked from the EC2 instance metadata address.
- Logs. nginx logs requests without their query strings, so the short-lived signed upload and download links never reach a log file.
- Restrict 22/tcp to your management network and 80/443 to the networks your devices use.
Architecture summary
| Component | Detail |
|---|---|
| API server | Ente museum, commit 20fb6316 built with Go 1.26.10 (AGPL-3.0), container museum, 127.0.0.1:8080, served at https://<host>/api |
| Web app | Ente Photos, commit 4a3e62d4 (AGPL-3.0), static files served by nginx at https://<host>/ |
| Object store | Silo RELEASE.2026-10-26T00-00-00Z (AGPL-3.0), container s3, 127.0.0.1:3200, buckets served at https://<host>/<bucket>/ |
| Database | PostgreSQL 15.19, container postgres, not published |
| Web server | nginx on 443 (HTTPS, per instance certificate in /etc/ssl/ente), 80 redirects to HTTPS, /healthz for load balancer checks |
| Data | /var/lib/ente on its own EBS volume (db PostgreSQL, objects encrypted files) |
| Credentials | /root/ente-credentials.txt, mode 0600, root only; container secrets and museum's configuration in /etc/ente |
| Helpers | ente-selftest, ente-signup, ente-storage, ente-set-hostname (in /usr/local/sbin) |
| First boot | ente-firstboot.service; the stack ente.service; host name check on every later boot ente-set-host.service |
| Ports | 22 SSH, 80 redirect, 443 Ente |
| Base image | Ubuntu 24.04 LTS, fully patched, unattended security upgrades enabled, IMDSv2 required |
Support
cloudimg provides 24/7 support for this image, the Ubuntu operating system and its deployment. Email support@cloudimg.co.uk with your AWS account ID and the instance ID. For Ente itself, see Ente's self-hosting documentation and the ente-io/ente repository on GitHub. The complete source of the AGPL software in this image is at the commits named above; /usr/share/doc/cloudimg-ente on the instance lists them. Ente is a trademark of Ente Technologies, Inc.; cloudimg is not affiliated with or endorsed by Ente. MinIO is a trademark of MinIO, Inc.; Silo is a community fork maintained by PGSTY.