Skip to content

Deploying Ente

Introduction

Ente is a fully open-source, end-to-end encrypted platform for storing your data in the cloud without needing to trust the service provider. Built with privacy as its foundation, Ente provides two flagship products: Ente Photos (a powerful alternative to Apple and Google Photos) and Ente Auth (a 2FA alternative to the deprecated Authy). The beauty of Ente’s architecture is that the server (called “Museum”) never has access to your unencrypted data—everything is encrypted on your device before it even leaves.

Ente’s server-side component, Museum, is a single statically compiled Go binary that’s built for simplicity, robustness, and containerization. It proxies data access, handles billing functions, and triggers replication of encrypted user data across three cloud providers for reliability. The end-to-end encrypted cryptography ensures your photos, videos, and authentication tokens remain private, even from the server itself.

Why Ente?

Ente stands out with its focus on privacy, security, and user control:

  • Complete End-to-End Encryption: Your data is encrypted on your device before upload; the server never sees unencrypted content
  • Zero-Knowledge Architecture: Even Ente cannot decrypt your data—only you hold the keys
  • Google Photos Alternative: Full-featured photo backup with face detection, semantic search, and collaborative albums
  • 2FA Without Compromise: Secure authenticator app with cloud backups that remain encrypted
  • Triple Replication: Data automatically replicated across three different cloud providers
  • Private Sharing: Share photos and albums without compromising encryption
  • Family Plans: Support for multiple users and family organization
  • Cross-Platform: iOS, Android, F-Droid, Web, Linux, macOS, and Windows clients
  • Background Uploads: Automatic photo backup without manual intervention
  • Easy Import/Export: Simple migration from other services with full data portability
  • Semantic Search: Find photos by content without compromising privacy
  • Face Detection: Automatic face recognition that respects your privacy
  • Collaborative Albums: Share and collaborate while maintaining encryption
  • Externally Audited: Security audited by Cure53, Symbolic Software, and Fallible
  • Self-Hosting Ready: Single Docker container that’s easy to deploy
  • Open Source: AGPL-3.0 licensed with active community development
  • 10GB Free Storage: Generous free tier with paid plans for more storage

Ente is perfect for privacy-conscious individuals, families, photographers, and organizations that want complete control over their photo backup and 2FA data without sacrificing features or usability.

Why Deploy on Klutch.sh?

Deploying Ente on Klutch.sh offers significant advantages:

  • Simplified Deployment: Deploy directly from GitHub with automatic Docker detection
  • Persistent Storage: Built-in volume support for encrypted photos and database
  • Database Integration: Easy PostgreSQL setup with TCP connectivity
  • HTTPS by Default: Automatic SSL certificates for secure access
  • Environment Management: Secure configuration of API keys and secrets
  • Scalable Resources: Adjust resources as your photo library grows
  • High Availability: Reliable infrastructure ensures your photos are always accessible
  • Custom Domains: Use your own domain for a professional photo backup service
  • S3 Compatible Storage: Easy integration with object storage for photos

Prerequisites

Before deploying Ente, ensure you have:

  • A Klutch.sh account
  • A GitHub account with a repository for your deployment configuration
  • A PostgreSQL database (see our PostgreSQL deployment guide)
  • S3-compatible storage (AWS S3, MinIO, Wasabi, Backblaze B2, or similar)
  • (Optional) SMTP credentials for email notifications
  • Basic familiarity with Docker and environment variables

Preparing Your Repository

Create a new GitHub repository for your Ente deployment with the following structure:

ente-deploy/
├── Dockerfile
├── .env.example
├── museum.yaml.example
├── .dockerignore
├── README.md
└── .gitignore

Dockerfile

Create a production-ready Dockerfile for Ente Museum:

FROM ghcr.io/ente-io/server:latest
# Set working directory
WORKDIR /app
# Environment variables will be set via Klutch.sh
ENV MUSEUM_PORT=8080
# Expose the application port
EXPOSE 8080
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
CMD curl -f http://localhost:8080/ping || exit 1
# The official Ente image already includes the entrypoint
# No additional configuration needed

Configuration File Template

Create a museum.yaml.example file to document configuration options:

# Database Configuration
db:
host: your-postgres-app.klutch.sh
port: 8000
name: ente
user: ente
password: your_secure_password
sslmode: require
# S3 Storage Configuration
s3:
endpoint: s3.amazonaws.com # or your S3-compatible endpoint
region: us-east-1
bucket: ente-photos
access_key: your_access_key
secret_key: your_secret_key
# B2 Storage (Alternative to S3)
b2:
endpoint: s3.us-west-004.backblazeb2.com
region: us-west-004
bucket: ente-photos
access_key: your_b2_key_id
secret_key: your_b2_application_key
# Server Configuration
server:
port: 8080
url: https://example-app.klutch.sh
# SMTP Configuration (Optional)
smtp:
host: smtp.gmail.com
port: 587
username: your-email@gmail.com
password: your_app_password
from: noreply@example.com
# JWT Secret (Generate a secure random string)
jwt:
secret: your_very_long_random_secret_min_64_chars

Environment Variables File

Create a .env.example file:

Terminal window
# Database Configuration (Required)
ENTE_DB_HOST=your-postgres-app.klutch.sh
ENTE_DB_PORT=8000
ENTE_DB_NAME=ente
ENTE_DB_USER=ente
ENTE_DB_PASSWORD=your_secure_password
# S3 Storage Configuration (Required)
ENTE_S3_ENDPOINT=s3.amazonaws.com
ENTE_S3_REGION=us-east-1
ENTE_S3_BUCKET=ente-photos
ENTE_S3_ACCESS_KEY=your_access_key
ENTE_S3_SECRET_KEY=your_secret_key
# Alternative: Backblaze B2 Configuration
# ENTE_S3_ENDPOINT=s3.us-west-004.backblazeb2.com
# ENTE_S3_REGION=us-west-004
# ENTE_S3_BUCKET=ente-photos
# ENTE_S3_ACCESS_KEY=your_b2_key_id
# ENTE_S3_SECRET_KEY=your_b2_application_key
# Server Configuration
MUSEUM_PORT=8080
MUSEUM_URL=https://example-app.klutch.sh
# JWT Secret (Required - Generate with: openssl rand -base64 64)
JWT_SECRET=your_very_long_random_secret_key_at_least_64_characters_long
# SMTP Configuration (Optional)
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USERNAME=your-email@gmail.com
SMTP_PASSWORD=your_app_password
SMTP_FROM=noreply@example.com
# Feature Flags
ENABLE_FAMILY_PLANS=true
ENABLE_SHARING=true
ENABLE_FACE_DETECTION=true
# Admin Configuration
ADMIN_EMAIL=admin@example.com

Docker Ignore File

Create a .dockerignore file:

.git
.gitignore
.env
.env.example
*.md
README.md
museum.yaml.example
.vscode
.idea
*.log
.DS_Store
node_modules
__pycache__
*.pyc

Git Ignore File

Create a .gitignore file:

.env
museum.yaml
*.log
.DS_Store
.vscode/
.idea/
__pycache__/
*.pyc

Deploying on Klutch.sh

  1. Set Up PostgreSQL Database

    Before deploying Ente, you need a PostgreSQL database. Follow our PostgreSQL deployment guide to set up a database on Klutch.sh.

    When creating your PostgreSQL instance, note the following:

    • Database name: ente
    • Username: ente
    • Password: Choose a secure password
    • Connection details: your-postgres-app.klutch.sh:8000
  2. Set Up S3-Compatible Storage

    Ente requires S3-compatible object storage for storing encrypted photos and videos. You have several options:

    AWS S3:

    1. Create an S3 bucket (e.g., ente-photos)
    2. Generate IAM credentials with S3 access
    3. Note the region and endpoint

    Backblaze B2:

    1. Create a B2 bucket
    2. Generate application keys
    3. Use the S3-compatible API endpoint

    MinIO (Self-Hosted):

    1. Deploy MinIO on Klutch.sh
    2. Create a bucket
    3. Generate access keys

    Wasabi:

    1. Create a Wasabi bucket
    2. Generate access keys
    3. Use the Wasabi S3-compatible endpoint
  3. Create a New Project

    Log in to the Klutch.sh dashboard and create a new project for your Ente deployment.

  4. Connect Your GitHub Repository

    In your Klutch.sh project:

    1. Navigate to the Apps section
    2. Click “Create New App”
    3. Select GitHub as your source
    4. Choose the repository containing your Ente Dockerfile
    5. Select the branch you want to deploy (typically main or master)
  5. Configure Build Settings

    Klutch.sh will automatically detect your Dockerfile. No additional configuration needed for the build process.

  6. Set Traffic Type

    In the deployment settings:

    1. Select HTTP as the traffic type
    2. Set the internal port to 8080
    3. Klutch.sh will automatically route traffic to your Ente application
  7. Configure Environment Variables

    In your Klutch.sh app settings, add the following environment variables:

    Required Variables:

    Terminal window
    ENTE_DB_HOST=your-postgres-app.klutch.sh
    ENTE_DB_PORT=8000
    ENTE_DB_NAME=ente
    ENTE_DB_USER=ente
    ENTE_DB_PASSWORD=your_secure_password
    ENTE_S3_ENDPOINT=s3.amazonaws.com
    ENTE_S3_REGION=us-east-1
    ENTE_S3_BUCKET=ente-photos
    ENTE_S3_ACCESS_KEY=your_access_key
    ENTE_S3_SECRET_KEY=your_secret_key
    MUSEUM_PORT=8080
    MUSEUM_URL=https://example-app.klutch.sh
    JWT_SECRET=generate_with_openssl_rand_base64_64

    Optional Variables (Email):

    Terminal window
    SMTP_HOST=smtp.gmail.com
    SMTP_PORT=587
    SMTP_USERNAME=your-email@gmail.com
    SMTP_PASSWORD=your_app_password
    SMTP_FROM=noreply@example.com

    Optional Variables (Features):

    Terminal window
    ADMIN_EMAIL=admin@example.com
    ENABLE_FAMILY_PLANS=true
    ENABLE_SHARING=true

    Mark sensitive values like ENTE_DB_PASSWORD, ENTE_S3_SECRET_KEY, JWT_SECRET, and SMTP_PASSWORD as secret.

  8. Attach Persistent Volume

    Ente needs persistent storage for temporary files and caching:

    1. In your Klutch.sh app settings, navigate to Volumes
    2. Click “Add Volume”
    3. Set the mount path to /data
    4. Choose an appropriate size (start with 5GB for cache)
    5. Save the volume configuration

    Note: Your main photo storage is in S3, so this volume is primarily for temporary files and cache.

  9. Deploy the Application

    Click “Deploy” to start the deployment process. Klutch.sh will:

    1. Pull your code from GitHub
    2. Build the Docker image
    3. Configure networking and volumes
    4. Start your Ente Museum server

    The initial deployment may take 2-3 minutes.

  10. Verify Deployment

    Once deployed, verify your Ente instance:

    Terminal window
    curl https://example-app.klutch.sh/ping

    You should receive a response like:

    {
    "message": "pong"
    }

Initial Configuration

Create Admin Account

After deployment, you’ll need to create your first admin account:

    1. Download the Ente Photos mobile app or web client
    2. Configure the app to point to your self-hosted instance:
      • Go to settings
      • Set custom server endpoint to https://example-app.klutch.sh
    3. Create a new account with your email
    4. Verify your email (if SMTP is configured)
    5. Set a strong master password

    Important: Your master password is never sent to the server. It’s used to derive encryption keys locally. If you lose it, your data cannot be recovered.

Configure Storage Settings

Set up your storage preferences:

    1. Log in to your Ente account
    2. Navigate to SettingsStorage
    3. Review your storage quota
    4. Configure backup preferences
    5. Set up automatic backup schedules

Set Up 2FA

Enable two-factor authentication for added security:

    1. Go to SettingsSecurity
    2. Click “Enable Two-Factor Authentication”
    3. Scan the QR code with Ente Auth or another authenticator app
    4. Enter the verification code
    5. Save your recovery codes in a secure location

Using Ente Photos

Uploading Photos

Mobile Apps (iOS/Android):

    1. Download Ente Photos from the App Store or Google Play
    2. Log in with your account
    3. Enable automatic backup in settings
    4. Select albums to backup
    5. Photos will upload automatically in the background

Web Client:

    1. Navigate to https://example-app.klutch.sh
    2. Log in with your credentials
    3. Click the upload button
    4. Select photos and videos
    5. Wait for upload and encryption to complete

Desktop Apps:

    1. Download Ente Photos for Windows, macOS, or Linux
    2. Log in with your account
    3. Configure watched folders for automatic backup
    4. Set backup preferences
    5. Photos sync automatically

Organizing Photos

Albums:

Create and manage photo albums:

  • Create new albums from selected photos
  • Share albums with family and friends (encrypted)
  • Collaborative albums where others can add photos
  • Archive albums to hide from main view

Face Detection:

Ente’s privacy-preserving face detection:

  • Automatically detects and groups faces
  • All processing happens on your device
  • Name people in photos
  • Search for photos by person
  • Face data never leaves your device unencrypted

Semantic Search:

Find photos without metadata:

  • Search by objects (“sunset”, “dog”, “beach”)
  • Search by colors
  • Search by date ranges
  • Search by location (if geo-tagged)
  • All search indexing happens client-side

Sharing Photos

Private Sharing:

    1. Select photos or albums to share
    2. Click the share button
    3. Generate a secure sharing link
    4. Set expiration date (optional)
    5. Set password protection (optional)
    6. Share the link with recipients

Recipients can view and download photos without creating an account. All data remains encrypted.

Collaborative Albums:

    1. Create a new album
    2. Enable collaboration
    3. Invite users by email
    4. They can add photos to the album
    5. All photos remain end-to-end encrypted

Family Plans

Set up family sharing:

    1. Navigate to SettingsFamily
    2. Create a family plan
    3. Invite family members
    4. Each member gets their own private space
    5. Create shared family albums
    6. Manage storage allocation

Using Ente Auth

Ente Auth is a free, end-to-end encrypted 2FA authenticator with cloud backup:

Setting Up Ente Auth

    1. Download Ente Auth from your app store
    2. Use the same account credentials
    3. Your authentication tokens sync across devices
    4. Set up a lock code for the app

Adding 2FA Tokens

Scan QR Code:

    1. Click the + button in Ente Auth
    2. Scan the QR code from the service
    3. Token is encrypted and backed up to cloud
    4. Available on all your devices

Manual Entry:

    1. Click + button
    2. Choose manual entry
    3. Enter the secret key
    4. Configure token settings
    5. Save

Exporting and Importing Tokens

Export:

  • Go to Settings → Export
  • Choose encrypted export
  • Save the file securely
  • Use for backup or migration

Import:

  • Support for importing from Authy, Google Authenticator, etc.
  • Upload backup file
  • All tokens are re-encrypted with your keys

Sample Code and Getting Started

Using the Ente API

Ente provides APIs for custom integrations and automation.

Authentication:

Terminal window
curl -X POST https://example-app.klutch.sh/users/login \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "your_password"
}'

Response:

{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"keyAttributes": {...},
"encryptedToken": "...",
"id": 12345
}

Uploading Photos via API (Node.js):

const fetch = require('node-fetch');
const FormData = require('form-data');
const fs = require('fs');
const crypto = require('crypto');
const ENTE_URL = "https://example-app.klutch.sh";
const AUTH_TOKEN = "your_auth_token";
async function uploadPhoto(filePath, albumId) {
// Read file
const fileBuffer = fs.readFileSync(filePath);
// Encrypt file (simplified - use Ente's encryption library)
const encryptionKey = crypto.randomBytes(32);
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv('aes-256-gcm', encryptionKey, iv);
let encrypted = cipher.update(fileBuffer);
encrypted = Buffer.concat([encrypted, cipher.final()]);
const authTag = cipher.getAuthTag();
// Create form data
const formData = new FormData();
formData.append('file', encrypted, {
filename: 'encrypted.bin',
contentType: 'application/octet-stream'
});
// Upload
const response = await fetch(`${ENTE_URL}/files`, {
method: 'POST',
headers: {
'X-Auth-Token': AUTH_TOKEN
},
body: formData
});
if (response.ok) {
const result = await response.json();
console.log("Photo uploaded successfully:", result);
return result;
} else {
console.error("Upload failed:", response.statusText);
}
}
// Usage
uploadPhoto('./photo.jpg', 12345);

Fetching Albums (Python):

import requests
ENTE_URL = "https://example-app.klutch.sh"
AUTH_TOKEN = "your_auth_token"
def get_albums():
"""Fetch all albums"""
headers = {
"X-Auth-Token": AUTH_TOKEN
}
response = requests.get(
f"{ENTE_URL}/collections",
headers=headers
)
if response.status_code == 200:
albums = response.json()
print(f"Found {len(albums)} albums:")
for album in albums:
print(f"- {album['name']}: {album['id']}")
return albums
else:
print(f"Error: {response.status_code}")
return None
def get_album_photos(album_id):
"""Get photos in an album"""
headers = {
"X-Auth-Token": AUTH_TOKEN
}
response = requests.get(
f"{ENTE_URL}/collections/{album_id}/files",
headers=headers
)
if response.status_code == 200:
photos = response.json()
print(f"Album has {len(photos)} photos")
return photos
else:
print(f"Error: {response.status_code}")
return None
# Usage
albums = get_albums()
if albums and len(albums) > 0:
get_album_photos(albums[0]['id'])

Sharing Albums (cURL):

Terminal window
# Create a sharing link for an album
curl -X POST https://example-app.klutch.sh/collections/share \
-H "X-Auth-Token: your_auth_token" \
-H "Content-Type: application/json" \
-d '{
"collectionID": 12345,
"validTill": 1735689600,
"enableDownload": true,
"enableCollect": false,
"passwordHash": null
}'
# Get shared album details
curl -X GET https://example-app.klutch.sh/collections/share/abc123def456 \
-H "X-Auth-Token: your_auth_token"

Export Data (Go):

package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
const (
enteURL = "https://example-app.klutch.sh"
authToken = "your_auth_token"
)
type Photo struct {
ID int64 `json:"id"`
OwnerID int64 `json:"ownerID"`
CollectionID int64 `json:"collectionID"`
File File `json:"file"`
}
type File struct {
EncryptedData string `json:"encryptedData"`
DecryptionHeader string `json:"decryptionHeader"`
}
func exportAllPhotos() ([]Photo, error) {
client := &http.Client{}
req, err := http.NewRequest("GET", enteURL+"/files", nil)
if err != nil {
return nil, err
}
req.Header.Set("X-Auth-Token", authToken)
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var photos []Photo
err = json.Unmarshal(body, &photos)
if err != nil {
return nil, err
}
fmt.Printf("Exported %d photos\n", len(photos))
return photos, nil
}
func main() {
photos, err := exportAllPhotos()
if err != nil {
fmt.Println("Error:", err)
return
}
// Process or save photos
for _, photo := range photos {
fmt.Printf("Photo ID: %d, Collection: %d\n",
photo.ID, photo.CollectionID)
}
}

Advanced Configuration

Custom Domain Setup

Use your own domain for your Ente instance:

    1. Add Custom Domain in Klutch.sh:

      • Navigate to your app in the Klutch.sh dashboard
      • Go to Domains section
      • Click “Add Custom Domain”
      • Enter your domain (e.g., photos.example.com)
    2. Configure DNS:

      • Add a CNAME record in your DNS provider:

        Type: CNAME
        Name: photos
        Value: example-app.klutch.sh
        TTL: 3600
    3. Update Environment Variables:

      Terminal window
      MUSEUM_URL=https://photos.example.com
    4. Redeploy:

      • Redeploy your application for changes to take effect
      • Wait for DNS propagation (typically 5-30 minutes)
    5. Update Client Apps:

      • Reconfigure mobile and desktop apps with new endpoint
      • Users will need to update their app settings

Email Configuration

Set up email notifications for sharing, family invites, and account recovery:

    1. Using Gmail:

      Terminal window
      SMTP_HOST=smtp.gmail.com
      SMTP_PORT=587
      SMTP_USERNAME=your-email@gmail.com
      SMTP_PASSWORD=your-app-specific-password
      SMTP_FROM=noreply@example.com

      Note: Use an App Password, not your regular Gmail password.

    2. Using SendGrid:

      Terminal window
      SMTP_HOST=smtp.sendgrid.net
      SMTP_PORT=587
      SMTP_USERNAME=apikey
      SMTP_PASSWORD=your-sendgrid-api-key
      SMTP_FROM=noreply@example.com
    3. Using AWS SES:

      Terminal window
      SMTP_HOST=email-smtp.us-east-1.amazonaws.com
      SMTP_PORT=587
      SMTP_USERNAME=your-ses-username
      SMTP_PASSWORD=your-ses-password
      SMTP_FROM=noreply@example.com
    4. Test Email Configuration:

      • Create a new account
      • Verify email delivery
      • Check spam folder if emails don’t arrive

Alternative Storage Backends

Using Wasabi:

Terminal window
ENTE_S3_ENDPOINT=s3.wasabisys.com
ENTE_S3_REGION=us-east-1
ENTE_S3_BUCKET=ente-photos
ENTE_S3_ACCESS_KEY=your_wasabi_access_key
ENTE_S3_SECRET_KEY=your_wasabi_secret_key

Using DigitalOcean Spaces:

Terminal window
ENTE_S3_ENDPOINT=nyc3.digitaloceanspaces.com
ENTE_S3_REGION=nyc3
ENTE_S3_BUCKET=ente-photos
ENTE_S3_ACCESS_KEY=your_spaces_access_key
ENTE_S3_SECRET_KEY=your_spaces_secret_key

Using Self-Hosted MinIO:

Terminal window
ENTE_S3_ENDPOINT=minio.example.com
ENTE_S3_REGION=us-east-1
ENTE_S3_BUCKET=ente-photos
ENTE_S3_ACCESS_KEY=your_minio_access_key
ENTE_S3_SECRET_KEY=your_minio_secret_key

Scaling for Large Photo Libraries

For installations with many users or large photo libraries:

Database Optimization:

    1. Scale your PostgreSQL instance:

      • Increase memory for better caching
      • Add read replicas for heavy read workloads
      • Optimize connection pooling
    2. Regular maintenance:

      -- Run VACUUM ANALYZE regularly
      VACUUM ANALYZE;
      -- Monitor table bloat
      SELECT schemaname, tablename,
      pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) AS size
      FROM pg_tables
      ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC
      LIMIT 10;

S3 Optimization:

    1. Enable S3 Transfer Acceleration for faster uploads
    2. Use lifecycle policies to transition old photos to cheaper storage tiers
    3. Enable versioning for photo protection
    4. Configure CORS for direct browser uploads

Application Scaling:

    1. Vertical scaling:

      • Start with 2GB RAM / 1 CPU
      • Scale to 4GB RAM / 2 CPU for 100+ users
      • Scale to 8GB RAM / 4 CPU for 1000+ users
    2. Horizontal scaling:

      • Deploy multiple instances behind a load balancer
      • Use sticky sessions for better performance
      • Share storage backend across instances

Production Best Practices

Security Hardening

Environment Variables:

  • Never commit .env files to version control

  • Use Klutch.sh’s secret management for sensitive values

  • Rotate secrets regularly (every 90 days recommended)

  • Use strong random values for JWT_SECRET:

    Terminal window
    openssl rand -base64 64

HTTPS Only:

Enforce HTTPS for all traffic (Klutch.sh handles this automatically)

Database Security:

  • Use strong database passwords
  • Enable SSL connections to PostgreSQL
  • Restrict database access to Ente’s IP range
  • Regular security updates

S3 Security:

  • Use IAM roles with minimum required permissions
  • Enable bucket versioning for data protection
  • Configure bucket policies to restrict access
  • Enable server-side encryption

Backup and Recovery

Database Backups:

    1. Set up automated PostgreSQL backups:

      Terminal window
      pg_dump -h your-postgres-app.klutch.sh -p 8000 \
      -U ente -d ente > ente-backup-$(date +%Y%m%d).sql
    2. Schedule daily backups

    3. Store backups off-site

    4. Test restore procedures quarterly

S3 Backups:

    1. Enable S3 versioning on your bucket
    2. Configure lifecycle policies
    3. Use cross-region replication for disaster recovery
    4. Regular integrity checks

Configuration Backups:

  • Export environment variables to secure password manager
  • Version control your Dockerfile and configuration
  • Document all custom settings
  • Keep recovery procedures updated

Monitoring and Observability

Health Check Endpoint:

Monitor your Ente instance:

Terminal window
curl https://example-app.klutch.sh/ping

Expected response:

{
"message": "pong"
}

Application Metrics:

Track key metrics:

  • Upload success rate
  • API response times
  • Active user count
  • Storage usage
  • Database connection pool
  • S3 request latency

Log Monitoring:

Access logs through Klutch.sh dashboard:

  1. Navigate to your app
  2. Click “Logs”
  3. Monitor for errors or warnings
  4. Set up alerts for critical issues

Alerting:

Set up alerts for:

  • API endpoint failures
  • Database connection issues
  • S3 access problems
  • High memory usage
  • Disk space warnings

Performance Optimization

Cache Configuration:

Optimize caching for better performance:

Terminal window
# Increase cache size for busy instances
CACHE_SIZE=1GB
CACHE_TTL=3600

Database Connection Pooling:

Terminal window
DB_MAX_CONNECTIONS=100
DB_MIN_CONNECTIONS=10
DB_CONNECTION_TIMEOUT=30

S3 Upload Optimization:

  • Use multipart uploads for large files
  • Enable S3 Transfer Acceleration
  • Configure appropriate retry policies
  • Optimize chunk sizes

Client-Side Optimization:

  • Enable compression for API responses
  • Use CDN for static assets
  • Implement proper caching headers
  • Optimize image thumbnails

Cost Optimization

Storage Costs:

    1. Use S3 Intelligent-Tiering for automatic cost savings
    2. Implement lifecycle policies:
      • Move old photos to Glacier after 1 year
      • Delete incomplete multipart uploads after 7 days
    3. Choose cost-effective S3-compatible providers like Backblaze B2
    4. Regularly audit and clean up orphaned data

Compute Costs:

    1. Right-size your Klutch.sh instance
    2. Use auto-scaling if available
    3. Schedule low-traffic period maintenance
    4. Optimize database queries to reduce CPU usage

Troubleshooting

Application Won’t Start

Check Database Connection:

Terminal window
# Test PostgreSQL connectivity
curl -v telnet://your-postgres-app.klutch.sh:8000

Verify Environment Variables:

  • Ensure all required variables are set
  • Check for typos in variable names
  • Verify JWT_SECRET is at least 64 characters

Check Logs:

Review application logs in Klutch.sh dashboard for specific error messages.

Photos Not Uploading

S3 Connection Issues:

  • Verify S3 credentials are correct

  • Check bucket permissions

  • Ensure bucket exists

  • Test S3 connectivity:

    Terminal window
    aws s3 ls s3://ente-photos --endpoint-url=https://s3.amazonaws.com

File Size Limits:

  • Check maximum file size configuration
  • Verify S3 multipart upload settings
  • Review client app file size limits

Network Issues:

  • Check firewall rules
  • Verify Klutch.sh networking configuration
  • Test direct API access

Database Performance Issues

Slow Queries:

    1. Enable slow query logging

    2. Analyze query performance:

      -- Find slow queries
      SELECT * FROM pg_stat_statements
      ORDER BY total_time DESC
      LIMIT 10;
    3. Add missing indexes

    4. Optimize problematic queries

Connection Pool Exhaustion:

  • Increase max connections
  • Check for connection leaks
  • Optimize connection timeout settings
  • Monitor active connections

Email Delivery Problems

SMTP Issues:

  • Verify SMTP credentials
  • Check SMTP server allows connections from Klutch.sh IPs
  • Test with different email provider
  • Check spam folders

Gmail Specific:

  • Use App Passwords, not regular password
  • Enable “Less secure app access” if needed
  • Check Gmail sending limits

Client App Connection Issues

Custom Server Configuration:

    1. Ensure correct server URL in client app
    2. Verify HTTPS is working
    3. Check for certificate issues
    4. Test API endpoint accessibility

Authentication Problems:

  • Verify JWT secret hasn’t changed
  • Check token expiration settings
  • Review auth logs for errors
  • Try creating a new account

High Storage Costs

Audit Storage Usage:

Terminal window
# List all objects and their sizes
aws s3 ls s3://ente-photos --recursive --human-readable --summarize

Optimize Storage:

  • Enable compression
  • Implement lifecycle policies
  • Remove duplicate uploads
  • Clean up orphaned files

Additional Resources

Conclusion

Deploying Ente on Klutch.sh provides you with a complete, privacy-focused photo backup and 2FA solution with full end-to-end encryption. Whether you’re an individual seeking Google Photos alternative, a family looking for shared photo storage, or an organization requiring privacy-compliant photo management, Ente offers powerful features while ensuring your data remains encrypted and under your control. With Klutch.sh’s managed infrastructure, persistent storage, and database integration, your encrypted photos and authentication tokens are always available, secure, and performant.

Start backing up your photos with complete privacy by deploying Ente on Klutch.sh today and join the growing community of users who refuse to compromise on data privacy.