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└── .gitignoreDockerfile
Create a production-ready Dockerfile for Ente Museum:
FROM ghcr.io/ente-io/server:latest
# Set working directoryWORKDIR /app
# Environment variables will be set via Klutch.shENV MUSEUM_PORT=8080
# Expose the application portEXPOSE 8080
# Health checkHEALTHCHECK --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 neededConfiguration File Template
Create a museum.yaml.example file to document configuration options:
# Database Configurationdb: host: your-postgres-app.klutch.sh port: 8000 name: ente user: ente password: your_secure_password sslmode: require
# S3 Storage Configurations3: 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 Configurationserver: 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_charsEnvironment Variables File
Create a .env.example file:
# Database Configuration (Required)ENTE_DB_HOST=your-postgres-app.klutch.shENTE_DB_PORT=8000ENTE_DB_NAME=enteENTE_DB_USER=enteENTE_DB_PASSWORD=your_secure_password
# S3 Storage Configuration (Required)ENTE_S3_ENDPOINT=s3.amazonaws.comENTE_S3_REGION=us-east-1ENTE_S3_BUCKET=ente-photosENTE_S3_ACCESS_KEY=your_access_keyENTE_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 ConfigurationMUSEUM_PORT=8080MUSEUM_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.comSMTP_PORT=587SMTP_USERNAME=your-email@gmail.comSMTP_PASSWORD=your_app_passwordSMTP_FROM=noreply@example.com
# Feature FlagsENABLE_FAMILY_PLANS=trueENABLE_SHARING=trueENABLE_FACE_DETECTION=true
# Admin ConfigurationADMIN_EMAIL=admin@example.comDocker Ignore File
Create a .dockerignore file:
.git.gitignore.env.env.example*.mdREADME.mdmuseum.yaml.example.vscode.idea*.log.DS_Storenode_modules__pycache__*.pycGit Ignore File
Create a .gitignore file:
.envmuseum.yaml*.log.DS_Store.vscode/.idea/__pycache__/*.pycDeploying on Klutch.sh
-
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
- Database name:
-
Set Up S3-Compatible Storage
Ente requires S3-compatible object storage for storing encrypted photos and videos. You have several options:
AWS S3:
- Create an S3 bucket (e.g.,
ente-photos) - Generate IAM credentials with S3 access
- Note the region and endpoint
Backblaze B2:
- Create a B2 bucket
- Generate application keys
- Use the S3-compatible API endpoint
MinIO (Self-Hosted):
- Deploy MinIO on Klutch.sh
- Create a bucket
- Generate access keys
Wasabi:
- Create a Wasabi bucket
- Generate access keys
- Use the Wasabi S3-compatible endpoint
- Create an S3 bucket (e.g.,
-
Create a New Project
Log in to the Klutch.sh dashboard and create a new project for your Ente deployment.
-
Connect Your GitHub Repository
In your Klutch.sh project:
- Navigate to the Apps section
- Click “Create New App”
- Select GitHub as your source
- Choose the repository containing your Ente Dockerfile
- Select the branch you want to deploy (typically
mainormaster)
-
Configure Build Settings
Klutch.sh will automatically detect your Dockerfile. No additional configuration needed for the build process.
-
Set Traffic Type
In the deployment settings:
- Select HTTP as the traffic type
- Set the internal port to 8080
- Klutch.sh will automatically route traffic to your Ente application
-
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.shENTE_DB_PORT=8000ENTE_DB_NAME=enteENTE_DB_USER=enteENTE_DB_PASSWORD=your_secure_passwordENTE_S3_ENDPOINT=s3.amazonaws.comENTE_S3_REGION=us-east-1ENTE_S3_BUCKET=ente-photosENTE_S3_ACCESS_KEY=your_access_keyENTE_S3_SECRET_KEY=your_secret_keyMUSEUM_PORT=8080MUSEUM_URL=https://example-app.klutch.shJWT_SECRET=generate_with_openssl_rand_base64_64Optional Variables (Email):
Terminal window SMTP_HOST=smtp.gmail.comSMTP_PORT=587SMTP_USERNAME=your-email@gmail.comSMTP_PASSWORD=your_app_passwordSMTP_FROM=noreply@example.comOptional Variables (Features):
Terminal window ADMIN_EMAIL=admin@example.comENABLE_FAMILY_PLANS=trueENABLE_SHARING=trueMark sensitive values like
ENTE_DB_PASSWORD,ENTE_S3_SECRET_KEY,JWT_SECRET, andSMTP_PASSWORDas secret. -
Attach Persistent Volume
Ente needs persistent storage for temporary files and caching:
- In your Klutch.sh app settings, navigate to Volumes
- Click “Add Volume”
- Set the mount path to
/data - Choose an appropriate size (start with 5GB for cache)
- Save the volume configuration
Note: Your main photo storage is in S3, so this volume is primarily for temporary files and cache.
-
Deploy the Application
Click “Deploy” to start the deployment process. Klutch.sh will:
- Pull your code from GitHub
- Build the Docker image
- Configure networking and volumes
- Start your Ente Museum server
The initial deployment may take 2-3 minutes.
-
Verify Deployment
Once deployed, verify your Ente instance:
Terminal window curl https://example-app.klutch.sh/pingYou should receive a response like:
{"message": "pong"}
Initial Configuration
Create Admin Account
After deployment, you’ll need to create your first admin account:
- Download the Ente Photos mobile app or web client
- Configure the app to point to your self-hosted instance:
- Go to settings
- Set custom server endpoint to
https://example-app.klutch.sh
- Create a new account with your email
- Verify your email (if SMTP is configured)
- 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:
- Log in to your Ente account
- Navigate to Settings → Storage
- Review your storage quota
- Configure backup preferences
- Set up automatic backup schedules
Set Up 2FA
Enable two-factor authentication for added security:
- Go to Settings → Security
- Click “Enable Two-Factor Authentication”
- Scan the QR code with Ente Auth or another authenticator app
- Enter the verification code
- Save your recovery codes in a secure location
Using Ente Photos
Uploading Photos
Mobile Apps (iOS/Android):
- Download Ente Photos from the App Store or Google Play
- Log in with your account
- Enable automatic backup in settings
- Select albums to backup
- Photos will upload automatically in the background
Web Client:
- Navigate to
https://example-app.klutch.sh - Log in with your credentials
- Click the upload button
- Select photos and videos
- Wait for upload and encryption to complete
Desktop Apps:
- Download Ente Photos for Windows, macOS, or Linux
- Log in with your account
- Configure watched folders for automatic backup
- Set backup preferences
- 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:
- Select photos or albums to share
- Click the share button
- Generate a secure sharing link
- Set expiration date (optional)
- Set password protection (optional)
- Share the link with recipients
Recipients can view and download photos without creating an account. All data remains encrypted.
Collaborative Albums:
- Create a new album
- Enable collaboration
- Invite users by email
- They can add photos to the album
- All photos remain end-to-end encrypted
Family Plans
Set up family sharing:
- Navigate to Settings → Family
- Create a family plan
- Invite family members
- Each member gets their own private space
- Create shared family albums
- Manage storage allocation
Using Ente Auth
Ente Auth is a free, end-to-end encrypted 2FA authenticator with cloud backup:
Setting Up Ente Auth
- Download Ente Auth from your app store
- Use the same account credentials
- Your authentication tokens sync across devices
- Set up a lock code for the app
Adding 2FA Tokens
Scan QR Code:
- Click the + button in Ente Auth
- Scan the QR code from the service
- Token is encrypted and backed up to cloud
- Available on all your devices
Manual Entry:
- Click + button
- Choose manual entry
- Enter the secret key
- Configure token settings
- 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:
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); }}
// UsageuploadPhoto('./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
# Usagealbums = get_albums()if albums and len(albums) > 0: get_album_photos(albums[0]['id'])Sharing Albums (cURL):
# Create a sharing link for an albumcurl -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 detailscurl -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:
-
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)
-
Configure DNS:
-
Add a CNAME record in your DNS provider:
Type: CNAMEName: photosValue: example-app.klutch.shTTL: 3600
-
-
Update Environment Variables:
Terminal window MUSEUM_URL=https://photos.example.com -
Redeploy:
- Redeploy your application for changes to take effect
- Wait for DNS propagation (typically 5-30 minutes)
-
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:
-
Using Gmail:
Terminal window SMTP_HOST=smtp.gmail.comSMTP_PORT=587SMTP_USERNAME=your-email@gmail.comSMTP_PASSWORD=your-app-specific-passwordSMTP_FROM=noreply@example.comNote: Use an App Password, not your regular Gmail password.
-
Using SendGrid:
Terminal window SMTP_HOST=smtp.sendgrid.netSMTP_PORT=587SMTP_USERNAME=apikeySMTP_PASSWORD=your-sendgrid-api-keySMTP_FROM=noreply@example.com -
Using AWS SES:
Terminal window SMTP_HOST=email-smtp.us-east-1.amazonaws.comSMTP_PORT=587SMTP_USERNAME=your-ses-usernameSMTP_PASSWORD=your-ses-passwordSMTP_FROM=noreply@example.com -
Test Email Configuration:
- Create a new account
- Verify email delivery
- Check spam folder if emails don’t arrive
Alternative Storage Backends
Using Wasabi:
ENTE_S3_ENDPOINT=s3.wasabisys.comENTE_S3_REGION=us-east-1ENTE_S3_BUCKET=ente-photosENTE_S3_ACCESS_KEY=your_wasabi_access_keyENTE_S3_SECRET_KEY=your_wasabi_secret_keyUsing DigitalOcean Spaces:
ENTE_S3_ENDPOINT=nyc3.digitaloceanspaces.comENTE_S3_REGION=nyc3ENTE_S3_BUCKET=ente-photosENTE_S3_ACCESS_KEY=your_spaces_access_keyENTE_S3_SECRET_KEY=your_spaces_secret_keyUsing Self-Hosted MinIO:
ENTE_S3_ENDPOINT=minio.example.comENTE_S3_REGION=us-east-1ENTE_S3_BUCKET=ente-photosENTE_S3_ACCESS_KEY=your_minio_access_keyENTE_S3_SECRET_KEY=your_minio_secret_keyScaling for Large Photo Libraries
For installations with many users or large photo libraries:
Database Optimization:
-
Scale your PostgreSQL instance:
- Increase memory for better caching
- Add read replicas for heavy read workloads
- Optimize connection pooling
-
Regular maintenance:
-- Run VACUUM ANALYZE regularlyVACUUM ANALYZE;-- Monitor table bloatSELECT schemaname, tablename,pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) AS sizeFROM pg_tablesORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESCLIMIT 10;
S3 Optimization:
- Enable S3 Transfer Acceleration for faster uploads
- Use lifecycle policies to transition old photos to cheaper storage tiers
- Enable versioning for photo protection
- Configure CORS for direct browser uploads
Application Scaling:
-
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
-
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
.envfiles 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:
-
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 -
Schedule daily backups
-
Store backups off-site
-
Test restore procedures quarterly
S3 Backups:
- Enable S3 versioning on your bucket
- Configure lifecycle policies
- Use cross-region replication for disaster recovery
- 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:
curl https://example-app.klutch.sh/pingExpected 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:
- Navigate to your app
- Click “Logs”
- Monitor for errors or warnings
- 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:
# Increase cache size for busy instancesCACHE_SIZE=1GBCACHE_TTL=3600Database Connection Pooling:
DB_MAX_CONNECTIONS=100DB_MIN_CONNECTIONS=10DB_CONNECTION_TIMEOUT=30S3 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:
- Use S3 Intelligent-Tiering for automatic cost savings
- Implement lifecycle policies:
- Move old photos to Glacier after 1 year
- Delete incomplete multipart uploads after 7 days
- Choose cost-effective S3-compatible providers like Backblaze B2
- Regularly audit and clean up orphaned data
Compute Costs:
- Right-size your Klutch.sh instance
- Use auto-scaling if available
- Schedule low-traffic period maintenance
- Optimize database queries to reduce CPU usage
Troubleshooting
Application Won’t Start
Check Database Connection:
# Test PostgreSQL connectivitycurl -v telnet://your-postgres-app.klutch.sh:8000Verify 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:
-
Enable slow query logging
-
Analyze query performance:
-- Find slow queriesSELECT * FROM pg_stat_statementsORDER BY total_time DESCLIMIT 10; -
Add missing indexes
-
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:
- Ensure correct server URL in client app
- Verify HTTPS is working
- Check for certificate issues
- 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:
# List all objects and their sizesaws s3 ls s3://ente-photos --recursive --human-readable --summarizeOptimize Storage:
- Enable compression
- Implement lifecycle policies
- Remove duplicate uploads
- Clean up orphaned files
Additional Resources
- Ente Official Website
- Ente GitHub Repository
- Ente Cryptography Architecture
- Official Self-Hosting Documentation
- Ente Discord Community
- GitHub Discussions
- PostgreSQL Deployment Guide
- Persistent Volumes Documentation
- Deployment Configuration
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.