some thoughts on self hosting ente

8 min read min read

the most challenging part of migrating off of icloud? figuring out what to do with the photos. this is the culmination of what i've figured out for that...

some thoughts on self hosting ente
Photo by Ilya Pavlov / Unsplash

the problem

For awhile I’ve wanted to move away from iCloud. Step 1 is the most important - figuring out a photos solution. Photos are what’s most important to everyone and their footprint tends to be heavy - it’s not just a breeze to migrate from one solution to another. It's what holds the whole migration back.

where i've been

My first foray into figuring out a solution was with Immich. Immich is an awesome self-hosted solution actively being developed but because of said development pace it’s changing a lot. This has made everything a little bit challenging. The two biggest challenges have been:

  • Uploading on the mobile app and to a lesser extent the web app was incredibly flaky. It would work than struggle (especially from mobile). Sometimes uploading would stall out until the next version came out. This made it never feel stable enough to add my family to it.
  • Photos were stored locally on the server unencrypted. This then required needing a high level of trust if hosting externally. Most solutions didn't lock out nosey hosts (which they can be - just search a bit on LowEndTalk).

I will say that the install process was a breeze, as was updating (as long as you monitored the update pathways). I had just been holding off on moving my family to it because of initialization woes: if uploading was a pain for me it’d be ten times the pain for them.

Unfortunately the VPS I hosted it on had an issue in mid-July - the network attached HDD storage had some significant drive issues (bios issues on new drives). Data wasn’t lost but was going to take a long time to reinitialize so I opted for something different (I waited about 2 weeks and in that time decided to pivot). I had everything backed up (do this always) anyways so it wasn't that difficult of a choice.

enter ente

Ente is interesting. It's fully open source but also a fully paid SaaS solution (so you can just host with them if you want). It's fully end-to-end encrypted (a bonus over Immich). It also requires s3 compatible object storage which makes it a bit more difficult setup than Immich. Setup isn't too difficult though as they have their full stack hostable via docker.

I opted to install via cloning the git repo:

git clone https://github.com/ente-io/ente
cd ente/server/config

From here it's just making sure that files are updated appropriately. Key things to look at:

  • The compose.yaml file shouldn't need any changes - it pulls its variables from environment files. The one change I did make is the location of the docker postgres volume (but that's not a change that needs to be made).
  • The .env file is the first primary one you'll need to update. Set a hardened, random password for the postgres DB and set the api & albums endpoint based on your install needs (probably the domain you are hosting).
  • The museum.yaml file is the second and has a lot more you'll need to setup:
    • Make sure the database info matches the .env file.
    • Make sure the s3 section is appropriately setup. You'll need either 3 buckets (for replication) or a single one. Don't change the buckets designation in the file, only change the access key, secret, endpoint, region (pro tip: use us-east-1 if using minio), endpoint and bucket name. My minio bucket needed use_path_style_urls set to true as well.
    • Set the endpoints in the apps section appropriately (as in the .env file)
    • Set the encryption keys as well.
    • Set the SMTP settings so that you get email from the install.
👨‍💻
If you are in the ente/server/config directory, type "cd .." (no quotes). This command: "go run tools/gen-random-keys/main.go" (no quotes) will generate random keys for you.

You are about ready to start things at this point. The last thing to do is setup the reverse proxy. I use caddy, connected to cloudflare for negotiating LE certificates. I find it's the easiest web server/reverse proxy out there. Ente has a documentation page dedicated to setting caddy up here as well so check it out! Once you sort that, starting is just a simple:

docker compose up -d --build

Run this in the server/config directory

👉
Note all the subdomains you need to setup (especially if you plan to use all the features). Ente runs their api, photo server, albums server, auth server and cast server all on different subdomains. They'll need entries in caddy as described in their documentation.

Don't forget to make yourself an admin. After you've made your user by going to your site, head back to your server and run this command:

docker exec -it <postgres-ente-container-name> sh
psql -U pguser -d ente_db
SELECT * from users;

You are looking for the user ID which you can add to the museum.yaml file like so:

# add this at the end if there isn't an internal section
internal:
     admin: <user id>

I'd also recommend disabling user registrations which you can also do in the same section of the museum.yaml file:

internal:
     admin: <user id>
     disable-registration: true

You can then setup the Ente CLI to disable the 10gb quota (see here in their documentation). It's set automatically because that's the free tier in their SaaS solution; because you are self-hosting though you are only limited by system resources.

s3 storage you say?

I've never worked much with s3. That one of the reasons I opted for immich originally. There are lots of options out there, most really expensive. They charge for the storage space. Some also charge for traffic. Then API calls. Sometimes API calls are tiered and incur different charges. It's a wild landscape to navigate.

I initially opted for one I found on the previously mentioned LowEndTalk but had some issues interacting with the API to change CORS settings for ente (more on this soon). I then gave ente another a try using different s3 storage and it's working great. I'm using hstProv based in the Netherlands. They offer bulk storage priced at €0.50 per 100GB. It's backed up and they offer enterprise level security. They also claim to be powered solely by green energy which is a bonus! Their site says triple redundancy which sounds great too. They also aren't nickel and diming for API calls and the like. The price is the price which is perfect! And it's nice that you don't have to pay for a terabyte at a time. If you are going to give this project a try, give them a try!

the cors problem

I didn't spell that wrong, no matter what you think. This is something to look out for depending on the s3 storage you are using; you might need to fiddle with the CORS settings. Typically this is done through API calls using the aws command line or minio command line (depending on the storage in question).

If you are still wondering what this is - I experienced it my first go uploading from the desktop and web. My museum docker logs where filling with 403 errors complaining about an inability to get object sizes. CORS stands for Cross-Origin Resource Sharing (something I probably should have led with). Basically things weren't talking to each other as they should have been. It's fixed by letting the s3 bucket know what could talk to it. Ente has an example fix in their documentation that I'd recommend following. The initial object store I chose unfortunately didn't allow this to be updated (although they've since issued a fix I believe).

what i'm loving

Most of the processing is done in apps so the web server component is super light. It doesn't need much at all to run as a server. I just looked at average stats in Beszel and the museum and db container are using just under 100mb each of RAM while actively uploading and the web container is using just under 20mb of RAM. CPU usage is negligible as well. Intensive tasks like machine learning is done on devices with small local models (phone/desktop in particular) rather than on the server. This aspect of it makes it really accessible for self-hosting - you really don't need much power.

They have a great command line utility as well that you can install on your local machine. You use it primarily for exporting for local backup (you can also set quotas with it!). This makes backup a breeze - I can even setup an automated command for it if I wanted since it's just a simple command line utility.

The phone app is really well designed. Uploading from it is a breeze (although as I note below - use the desktop for your initial uploads). They also have some great built in management features. I love that scanning for duplicates is a breeze and that it easily lets me take care of that issue. It'll even scan for similar files (it found several of the same images that existed at different sizes in my library for example). That's awesome. Currently my library stands at 50gb and it scanned and found about 2 gb I could free up from similar files in about 5 seconds. Even better, all the "hits" were real.

some things to note

Use the initial desktop app to upload. Don’t try with your phone - it uses a lot of processing power locally on your phone. If you try to do your whole library at once from your phone it might just got so hot it decides to turn off for awhile (true story). I'm doing 2-5k photos at a time without issue from the desktop (and I've done that much without too much problem from my phone as well). I plan to use my phone to keep it up-to-date once the full library is on their.

Machine Learning (ML) is used locally to create indexes for searching. It's entirely on device and is ML. There isn’t any AI in the ChatGPT or Claude sense. I know this is important for many people (me included). I don't want my photo data sent externally for any kind of processing.

back that thing up

Backup always. No matter what. You never know when or how disaster might strike. My photos are in Ente (or soon to be), in a local backup and in another encrypted cloud backup. Plus the s3 storage I chose is closely monitored by the host as well (see above). This means my photos are in 3 different locations which gives some time to make a plan if something happens with one of them. It's just good sense. Less important but I'll still mention: I keep the server code backed up in a private forgejo repo as well in case I need to quickly rebuild.

should you do it?

If you want sure! I'm really connecting with ente as an app for photos. I'm still figuring out things like albums and casting (my focus has been on the initial import) but I really like how it functions. I like where it's going. I like that they value privacy and security. And I like that I feel empowered to know a bit more about what is going on in my photo library. Nothing is perfect though and if you aren't looking for a change I wouldn't take the plunge into something new like this as it is a lot of work. If you do decide to try it though let me know if you have questions and need a hand!

🗓️
Updated on 9/9/25 to clarify some grammar and add the docker compose run command.

Thanks for reading!

I'd love to hear from you if you have a comment, suggestion, clarification or anything! Feel free to email me or respond on Mastodon below. If you really loved it, you can buy me a coffee!