Self‑hosting di Ente Foto con Docker Compose e Backblaze B2
Ente Foto è un servizio per l’archiviazione e la sincronizzazione di foto e video con una forte attenzione alla privacy. Per funzionalità ricorda Google Foto o Apple Foto (backup automatico, app mobile, organizzazione per album), ma con una differenza fondamentale: crittografia end‑to‑end e possibilità di hostarlo sul proprio server.
In questo articolo racconto la mia esperienza di installazione di Ente Foto in un ambiente di test, utilizzando Docker Compose e come storage un bucket S3 compatibile su Backblaze B2.
Mi sono basato sulla documentazione ufficiale di Ente e sugli appunti di alcuni amici nerd, adattando il tutto alla mia infrastruttura.
Perché Ente Foto
Se stai cercando un’alternativa self‑hosted a Google Foto che non sacrifichi la privacy, Ente è una delle soluzioni più interessanti oggi disponibili:
- Crittografia end‑to‑end reale
- Supporto a storage S3 compatibili
- App ufficiali (Android, iOS, desktop)
- Installazione relativamente semplice via Docker
L’unico vero requisito è avere un minimo di confidenza con Docker e con la gestione di servizi web.
Prerequisiti
Nel mio setup ho utilizzato:
- Sistema operativo Linux (Debian 13)
- Docker e Docker Compose installati
- Un bucket S3 su Backblaze B2
Naturalmente puoi adattare la guida ad altre distribuzioni Linux o ad altri provider S3 compatibili.
Clonare il repository di Ente
Per iniziare cloniamo il repository ufficiale di Ente e ci spostiamo nella directory di configurazione del server:
git clone https://github.com/ente-io/ente
cd ente/server/config
All’interno di questa directory troviamo i file di esempio necessari per l’installazione.
Preparazione dei file di configurazione
Rinominiamo i file di esempio che useremo:
cp example.env .env
cp example.yaml museum.yaml
File .env
# Copy this file to .env in the same directory in which this file is present
# This file contains the environment variables needed for Ente's cluster to run properly.
# This file is split based on services declared in Docker Compose file
#
# Service: Postgres
# This is used for storing data in database pertaining to collections, files, users, subscriptions, etc.
# These credentials are needed for accessing the database via Museum.
# Please set a strong password for accessing the database.
# Enter these values in museum.yaml file under `db`.
# This need not be defined if using external DB (i. e. no Compose service for PostgreSQL is used)
POSTGRES_USER=pguser
POSTGRES_PASSWORD=postgrespassword
POSTGRES_DB=ente_db
# Service: MinIO
# This is used for MinIO object storage service that's shipped by default with the compose file
# to reduce need for an external S3-compatible bucket for quick testing.
# It is recommended to use an external bucket for long-term usage.
# The credentials required for accessing the object storage is documented below.
# It is not needed to configure these variables if you are using an external bucket
# Enter the user value into key and password in secret for buckets in museum.yaml under `s3` section.
MINIO_ROOT_USER=
MINIO_ROOT_PASSWORD=
# Service: Web
# This is used for configuring public albums, API endpoints, etc.
# Replace the below endpoints to the correct subdomains of your choice.
ENTE_API_ORIGIN=https://api.ente.culturanerd.it
ENTE_ALBUMS_ORIGIN=https://albums.ente.culturanerd.it
ENTE_PHOTOS_ORIGIN=https://web.ente.culturanerd.it
Nel file .env ho effettuato poche modifiche:
- Impostato
POSTGRES_PASSWORDcon una password sicura - Valorizzato le variabili:
ENTE_API_ORIGIN=
ENTE_ALBUMS_ORIGIN=
ENTE_PHOTOS_ORIGIN=
utilizzando i nomi DNS per la mia installazione
Queste variabili sono fondamentali per il corretto funzionamento delle app client.
File museum.yaml
# Copy this file to museum.yaml in the same directory in which this file is present
# This section is meant for configuration of database.
# Museum uses these values and credentials for connecting
# to the database.
# Set a strong password and if using PostgreSQL Docker container
# provided in Docker Compose file, ensure db.password is same
# as POSTGRES_PASSWORD
# Similarly ensure db.user and db.name are same as POSTGRES_USER and
# POSTGRES_DB respectively
db:
host: postgres
port: 5432
name: ente_db
user: pguser
password: postgrespassword
# This section is for configuring storage buckets. Omit this section if
# you only intend to use Ente Auth
s3:
# Change this to false if enabling SSL
are_local_buckets: false
# Only path-style URL works if disabling are_local_buckets with MinIO
use_path_style_urls: true
b2-eu-cen:
# Uncomment the below configuration to override the top-level configuration
# are_local_buckets: true
# use_path_style_urls: true
key: _KEY_
secret: _SECRET_
endpoint: s3.us-west-001.backblazeb2.com
region: eu-central-2
bucket: _NOMEBUCKET_
wasabi-eu-central-2-v3:
# are_local_buckets: true
# use_path_style_urls: true
key: <key>
secret: <secret>
endpoint: localhost:3200
region: eu-central-2
bucket: wasabi-eu-central-2-v3
compliance: false
scw-eu-fr-v3:
# are_local_buckets: true
# use_path_style_urls: true
key: <key>
secret: <secret>
endpoint: localhost:3200
region: eu-central-2
bucket: scw-eu-fr-v3
# Specify the base endpoints for various web apps
apps:
# If you're running a self hosted instance and wish to serve public links,
# set this to the URL where your albums web app is running.
public-albums: https://albums.ente.culturanerd.it
cast: https://cast.ente.culturanerd.it
embed-albums: https://share.ente.culturanerd.it
# Set this to the URL where your accounts web app is running, primarily used for
# passkey based 2FA.
accounts: https://accounts.ente.culturanerd.it
# Key used for encrypting customer emails before storing them in DB
#
# To make it easy to get started, some randomly generated (but fixed) values are
# provided here. But if you're really going to be using museum, please generate
# new keys. You can use `go run tools/gen-random-keys/main.go` for that.
#
# Replace values in key and JWT for security
key:
encryption: _ENCRYPTION_
hash: _HASH_
# JWT secrets
jwt:
secret: _SECRET_
Nel file museum.yaml ho modificato solo le sezioni necessarie, adattandole alla mia installazione.
In particolare:
- Configurazione dello storage S3
- Credenziali e endpoint di Backblaze B2
- Bucket dedicato alle foto
I dati di accesso a Backblaze (key, secret, endpoint) si ottengono una volta creato il bucket dal pannello di controllo.
Bisogna solo modificare i valori:
key secret endopoint bucket
Lasciare inalterati gli altri parametri in quanto sono hardcoded nell'applicazione
Generazione delle chiavi crittografiche
Ente richiede alcune chiavi casuali definite nel file museum.yaml per:
encryptionhashjwt
Per generarle è necessario installare Go:
apt install golang
Dopodiché eseguire lo script fornito dal progetto:
go ../tools/gen-random-keys/main.go
L’output andrà copiato nelle rispettive sezioni del file museum.yaml.
Avvio dei container
A questo punto siamo pronti per buildare e avviare i container Docker:
docker compose up -d
Il primo avvio richiede un po’ di tempo, soprattutto per il download delle immagini e l’inizializzazione dei servizi.
Al termine, se tutto è andato a buon fine, il server Ente sarà operativo.
Reverse proxy con Caddy
Per esporre Ente in HTTPS ho utilizzato Caddy come reverse proxy.
L’installazione e la configurazione di Caddy in Docker sono descritte in dettaglio in questo articolo
Una volta configurato Caddy, è sufficiente creare i VirtualHost in Caddyfile per:
- API
- Albums
- Photos
puntando ai rispettivi servizi Docker di Ente.
# For Museum
api.ente.culturanerd.it {
reverse_proxy http://localhost:8080
}
# For Ente Photos web app
web.ente.culturanerd.it {
reverse_proxy http://localhost:3000
}
# For Ente Accounts web app
accounts.ente.culturanerd.it {
reverse_proxy http://localhost:3001
}
# For Ente Albums web app
albums.ente.culturanerd.it {
reverse_proxy http://localhost:3002
}
# For Ente Auth web app
auth.ente.culturanerd.it {
reverse_proxy http://localhost:3003
}
# For Ente Cast web app
cast.ente.culturanerd.it {
reverse_proxy http://localhost:3004
}
# For Ente Public Locker web app
share.ente.culturanerd.it {
reverse_proxy http://localhost:3005
}
# For Ente Embed web app
embed.ente.culturanerd.it {
reverse_proxy http://localhost:3006
}
Creazione dell’account e conferma
All’apertura della pagina di login, create un account. Attenzione: non avendo ancora un server SMTP, la conferma via mail non arriverà. Per ottenere il codice di conferma:
docker compose logs

Rimozione dei limiti di storage
Per impostazione predefinita, lo storage è limitato a 10GB. Per rimuovere questo limite è necessario usare Ente CLI.
Installazione di Ente CLI e configurazione
Installiamo alcune dipendenze:
apt install gnome-keyring libsecret-1-0 dbus-x11
E lanciamo questi comandi per i quali, ancora una volta, ringrazio l'amico roughnecks
eval "$(dbus-launch --sh-syntax)"
mkdir -p ~/.cache
mkdir -p ~/.local/share/keyrings # where the automatic keyring is created
# 1. Create the keyring manually with a dummy password in stdin
eval "$(printf '\n' | gnome-keyring-daemon --unlock)"
# 2. Start the daemon, using the password to unlock the just-created keyring:
eval "$(printf '\n' | /usr/bin/gnome-keyring-daemon --start)"
Scaricare e estrarre Ente CLI:
wget https://github.com/ente-io/ente/releases/download/cli-v0.2.3/ente-cli-v0.2.3-linux-amd64.tar.gz
tar zxvf ente-cli-v0.2.3-linux-amd64.tar.gz
Creare il file config.yaml con questo contenuto e nella stessa posizione dell'eseguibile ente di ente-cli
endpoint:
api: "http://localhost:8080"
Aggiungere l’account:
./ente account add
e recuperare lo user id:
./ente account list
Rendere l’utente admin modificando museum.yaml e inserendo in fondo al file:
internal:
admin: _USER_ID_
Riavviare i container:
docker compose down && docker compose up -d
Infine, rimuovere il limite dello storage:
./ente admin update-subscription -u email@vostrodominio.tld --no-limit true
Fix errori CORS con Backblaze
Se non riuscite a caricare o visualizzare foto dalla webapp, potrebbe essere un problema di CORS. Procedura:
- Installare il CLI Backblaze:
wget https://github.com/Backblaze/B2_Command_Line_Tool/releases/latest/download/b2-linux
chmod +x b2-linux
mv b2-linux /usr/local/bin
- Creare una nuova Application Key dall'interfaccia web di BackBlaze e autorizzarsi:
b2 authorize-account
- Creare cors.json e applicarlo al bucket:
[
{
"corsRuleName": "entephotos",
"allowedOrigins": [
"*"
],
"allowedHeaders": [
"*"
],
"allowedOperations": [
"b2_download_file_by_id",
"b2_download_file_by_name",
"b2_upload_file",
"b2_upload_part",
"s3_get",
"s3_post",
"s3_put",
"s3_head"
],
"exposeHeaders": [
"X-Amz-Request-Id",
"X-Amz-Id-2",
"ETag"
],
"maxAgeSeconds": 3600
}
]
b2 bucket update --cors-rules "$(<./cors.json)" _NOME_BUCKET_ allPrivate
Apps
L’app Android funziona perfettamente. Per collegare la vostra istanza:
-
Tappare 7 volte il logo per abilitare le opzioni sviluppatore
-
Inserire l’URL delle API, ad esempio:
https://api.ente.culturanerd.it