172 Commits

Author SHA1 Message Date
Andreas Dueren 58e40897a5 Add share/embed/payments frontends and hosts 2025-11-20 23:15:37 -06:00
Andreas Dueren 95758de781 Restore start.sh from 0.5.5 2025-11-20 14:22:13 -06:00
Andreas Dueren f984184b39 Revert /api matcher nesting 2025-11-20 13:22:24 -06:00
Andreas Dueren 37ce044181 Use handle wrapper for /api matcher 2025-11-20 13:07:26 -06:00
Andreas Dueren 12537896f2 Fix Caddy matcher syntax 2025-11-20 12:43:00 -06:00
Andreas Dueren ef00dde487 Restrict museum routes to primary host 2025-11-20 12:36:02 -06:00
Andreas Dueren 6ff0b1756d Bump version to 0.5.7 2025-11-20 12:24:21 -06:00
Andreas Dueren d39a1d86a9 Fix accounts passkey routing 2025-11-20 12:15:01 -06:00
Andreas Dueren 617236558e Bundle families frontend and billing data 2025-11-20 11:54:40 -06:00
Andreas Dueren f29b570b82 Inject API origin bootstrap and update docs 2025-11-18 21:05:58 -06:00
Andreas Dueren 3b7a853c71 Harden S3 DC handling 2025-11-18 11:57:32 -06:00
Andreas Dueren 42c4c1f38f Document S3 defaults and align DC names 2025-11-18 10:47:57 -06:00
Andreas Dueren 1c37a2b930 Respect user-defined S3 DCs 2025-11-18 10:31:57 -06:00
Andreas Dueren 632dea4517 Support optional S3 replication 2025-11-18 09:37:15 -06:00
Andreas Dueren 8f3a34a277 chore: auto-bootstrap cli config 2025-11-05 05:58:50 -06:00
Andreas Dueren fc9abad56b docs: add backblaze cors guidance 2025-11-05 05:55:18 -06:00
Andreas Dueren 6cf536bc67 Fix suffix normalization 2025-11-04 19:11:44 -06:00
Andreas Dueren 55808e9afa Normalize httpPort hostnames 2025-11-04 18:37:45 -06:00
Andreas Dueren fe7bc72131 Document required S3 CORS for cast 2025-11-04 18:20:43 -06:00
Andreas Dueren 953ee82a97 Fix httpPorts host detection 2025-11-04 18:09:21 -06:00
Andreas Dueren c9e554c9a8 Clarify admin bootstrap steps 2025-11-04 18:02:46 -06:00
Andreas Dueren 0652dde795 Document CLI bootstrap steps 2025-11-04 17:49:15 -06:00
Andreas Dueren 5549f03f6e Route Museum GET endpoints 2025-11-04 17:10:32 -06:00
andreas 98b26537a1 Document admin whitelist and quota commands 2025-10-30 13:38:09 -06:00
andreas a2810a720f Enable Ente CLI persistence and update docs 2025-10-30 13:20:39 -06:00
andreas 66c3625633 Enable Ente CLI persistence and update docs 2025-10-30 12:43:50 -06:00
andreas 18d14d09df Enable Ente CLI persistence and update docs 2025-10-30 12:31:37 -06:00
andreas f62914d566 Fix Caddy trusted proxies syntax 2025-10-30 12:25:32 -06:00
andreas 1bf9fc6a9c Fix Caddy trusted proxies syntax 2025-10-30 11:03:30 -06:00
andreas 2b13ee7163 Fix CORS handling and real IP logging 2025-10-30 10:49:54 -06:00
andreas f28b82db3f Update to version 0.4.3 with S3 configuration improvements
- Always regenerate Museum configuration on startup to enable runtime S3 credential changes
- Improve S3 configuration logging and validation for Cloudflare R2 endpoints
- Update SMTP configuration to use SMTPS port 2465 with TLS encryption
- Fix Caddy proxy headers to properly forward client information
- Add startup.log for enhanced troubleshooting
- Update build instructions and changelog for version 0.4.3
2025-10-30 08:57:37 -06:00
andreas 9d4849ee38 Add back SMTP authentication for port 2525
Restore SMTP username and password for authenticated relay on port
2525. According to Cloudron docs, this port should work with plain
SMTP and authentication without STARTTLS.
2025-10-22 09:18:02 -06:00
andreas 3e23a8b9d6 Revert to port 2525 without authentication for internal mail relay
The STARTTLS port 2587 requires TLS certificate verification, but
Cloudron's internal mail relay uses a wildcard cert for *.due.ren
which doesn't match the hostname 'mail'. Port 2525 is the internal
plain SMTP relay that doesn't require authentication or TLS for
connections from within the same container network.
2025-10-22 09:12:46 -06:00
andreas 626a5b5031 Use Cloudron STARTTLS port 2587 for SMTP
Switch from plain SMTP on port 2525 to STARTTLS on port 2587.
The Go smtp.SendMail function automatically handles STARTTLS
negotiation when encryption is empty, which is required by
Cloudron's sendmail addon on the STARTTLS port.
2025-10-22 09:05:28 -06:00
andreas f0c225961a Add SMTP authentication using Cloudron sendmail credentials
Configure Museum to use CLOUDRON_MAIL_SMTP_USERNAME and
CLOUDRON_MAIL_SMTP_PASSWORD for authenticated SMTP relay.
This fixes the "550 I cannot deliver mail" error by properly
authenticating with the Cloudron sendmail addon.
2025-10-22 08:54:03 -06:00
andreas 212da52a7a Fix SMTP configuration to use Cloudron sendmail hostname
Change SMTP host from localhost/127.0.0.1 to 'mail' as per Cloudron
sendmail addon documentation. The sendmail addon provides a local SMTP
relay accessible via hostname 'mail' on port 2525.
2025-10-22 08:47:18 -06:00
andreas 50cc98abb2 Use localhost for SMTP instead of Docker bridge IP
Change SMTP host from 172.18.0.1 to localhost to properly connect
to Cloudron's sendmail relay running inside the container.
2025-10-22 08:38:12 -06:00
andreas 82ab3c25e9 Fix SMTP configuration to use Cloudron mail relay
Use Cloudron's internal mail relay at 172.18.0.1:2525 instead of
external SMTP server to fix email sending timeouts during registration.
2025-10-22 08:17:48 -06:00
andreas f20a55768b Add Caddy handler for static image assets 2025-10-21 22:04:39 -06:00
andreas aaee86823e Fix redirect loop by using dummy albums domain
Instead of trying to match the albums host with current host
(which always fails in path-based routing), use a dummy domain
'albums.localhost.invalid' that will never match the actual host.
This prevents the automatic redirect to /shared-albums.

Version bump to 0.3.2
2025-10-21 20:56:27 -06:00
andreas 6d3aaf7277 Fix redirect loop by setting NEXT_PUBLIC_ENTE_ALBUMS_ENDPOINT
The app was redirecting to /shared-albums because albumsAppOrigin()
returned the same host as the current URL after runtime replacement.
By setting NEXT_PUBLIC_ENTE_ALBUMS_ENDPOINT at build time to a
placeholder and replacing it at runtime with the full path-based URL,
the host comparison will fail and prevent the redirect loop.

Version bump to 0.3.1
2025-10-21 20:29:46 -06:00
andreas 98c8185655 Improve URL replacement strategy for frontend assets
- Enhanced rewrite_frontend_reference function to handle multiple URL encoding formats
- Now replaces plain URLs, backslash-escaped URLs, and double-backslash-escaped URLs
- Added https://ente.io -> BASE_URL replacement
- Version bump to 0.3.0
2025-10-21 19:58:39 -06:00
andreas 00d7269e00 Fix Ente Cloudron packaging issues
- Fixed admin-helper.sh to use correct Museum binary path (/app/museum-bin/museum)
- Updated start.sh to handle missing S3 configuration gracefully
  - App now starts in configuration mode when S3 is not configured
  - Shows helpful configuration page instead of failing health checks
  - Properly starts Museum server once S3 is configured
- Updated CloudronManifest.json to version 0.2.2
- All web frontends (photos, accounts, auth, cast, albums, family) verified working
- Museum API server running successfully with S3 storage
2025-10-21 19:20:15 -06:00
andreas 801ae12029 Auto-configure CLI endpoint 2025-09-30 09:34:25 -06:00
andreas 2ccc6bd65c Persist Museum configuration for manual edits 2025-09-29 22:36:37 -06:00
andreas 5d2e5919b1 Make Ente CLI usable out of the box 2025-09-29 22:05:24 -06:00
andreas 1d16c17c35 Bundle Ente CLI for Cloudron console 2025-09-29 21:37:33 -06:00
andreas 760a4ba44a Remove OTT log highlighter 2025-09-29 21:26:21 -06:00
andreas 5d62c2de4f Document S3 examples and refresh template 2025-09-29 21:18:19 -06:00
andreas 65717243a5 Allow runtime S3 configuration overrides 2025-09-29 20:59:57 -06:00
andreas 8f94e35bf5 Fix SPA asset routing for web apps 2025-09-29 20:47:07 -06:00
andreas 3785b3b4d1 Force rebuild: Update asset routing with version bump 2025-08-01 14:02:07 -06:00
andreas 7b1c28a8c9 Bump version to 0.1.81 for asset routing fix 2025-08-01 13:56:09 -06:00
andreas 762d594e80 Fix static asset routing for all web apps
- Add specific _next asset routes for accounts, auth, cast apps
- Add image asset routes for each app
- Ensure each app's assets are served from correct directory
- Keep photos app routing unchanged

Should fix accounts/auth/cast apps loading issues.
2025-08-01 13:55:53 -06:00
andreas 0f80f13d50 Resolve merge conflicts with updated version 0.1.79 2025-08-01 13:46:59 -06:00
andreas e60248cf80 Fix API endpoint configuration and domain references
- Change NEXT_PUBLIC_ENTE_ENDPOINT to relative /api for domain flexibility
- Remove runtime JS endpoint replacement (fragile, now unnecessary)
- Fix all domain references to use CLOUDRON_APP_DOMAIN consistently
- Add /ping health check endpoint to Caddy configuration
- Update placeholder server to use dynamic domain

Photos app now working, other apps may need additional fixes.
2025-08-01 13:46:17 -06:00
andreas bc5013f160 Fix web app endpoint configuration
- Use relative /api endpoint in Dockerfile build
- Remove complex runtime replacement logic
- Simplify start.sh to avoid read-only filesystem issues
- Restore working Caddy configuration

Version 0.1.78 ready for deployment
2025-07-26 20:28:15 -06:00
andreas c688f894d8 Remove large ente-source directory to fix build uploads 2025-07-25 19:47:47 -06:00
andreas 1df089cd21 Implement comprehensive web app API endpoint fix
- Patch origins.ts during Docker build to use window.location.origin + '/api'
- Update version to 0.1.69 to force rebuild
- Add browser compatibility check for server-side rendering
- Fix both API and uploader endpoint redirections

This addresses the root cause where web apps were hardcoded to use
https://api.ente.io instead of the local Museum server.
2025-07-25 19:27:11 -06:00
andreas c4c674b4d0 Fix static asset routing and path handling for auth/accounts/cast apps
- Fixed Next.js static asset (_next/*) routing for each app separately
- Updated app path handling to work with both /app and /app/* patterns
- Resolved 404 errors for static assets from auth, accounts, and cast apps
- Updated to version 0.1.66
2025-07-25 11:12:27 -06:00
andreas 1e2cc6c64a Add comprehensive API documentation to Cloudron setup instructions
- Added detailed API endpoint information in SETUP-INSTRUCTIONS.md
- Documented API usage with Ente CLI
- Enhanced routing configuration for auth/cast/accounts apps
- Updated to version 0.1.64
2025-07-25 11:02:06 -06:00
andreas 94dac7a7b3 Add OTP email monitor to handle Museum skipped emails
- Implement comprehensive OTP email monitoring service
- Monitor Museum logs for "Skipping sending email" pattern
- Send verification emails using Cloudron email addon
- Add specific regex pattern for Museum's skip email format
- Version bump to 0.1.62

The monitor captures OTP codes from logs when Museum skips sending
emails and sends them via Cloudron's email system. This ensures
users receive their verification codes even when Museum's email
configuration is not sending directly.
2025-07-22 12:27:44 -06:00
andreas 4af60e1c64 Fix JavaScript URL construction error for API endpoint
- Change NEXT_PUBLIC_ENTE_ENDPOINT from "/api" to "https://example.com/api" during build to satisfy URL constructor requirements
- Add runtime replacement in start.sh to replace placeholder with actual domain endpoint
- This resolves the "TypeError: Failed to construct 'URL': Invalid URL" error in the frontend
2025-07-22 08:58:53 -06:00
andreas 9f89dd330f Fix S3 configuration - set are_local_buckets to true
- Changed are_local_buckets from false to true (required for external S3)
- Simplified S3 configuration to only use b2-eu-cen bucket
- Removed unnecessary replication buckets for single bucket setup

This aligns with Ente's documentation where are_local_buckets=true
is used for external S3 services like Wasabi.
2025-07-21 20:44:19 -06:00
andreas 89fd59f6a3 Hardcode Wasabi S3 configuration with proper Ente format
- Remove dynamic S3 configuration loading
- Hardcode Wasabi credentials as requested
- Use proper Ente S3 configuration format with datacenter names
- Configure all three storage buckets (b2-eu-cen, wasabi-eu-central-2-v3, scw-eu-fr-v3)
- Set are_local_buckets to false for external S3
- Add compliance flag for Wasabi bucket

This should fix the MissingRegion error by properly configuring S3 storage
according to Ente's expected format.
2025-07-21 20:41:58 -06:00
andreas 435a0568b4 Update CloudronManifest version to 1.0.1
Increment version after multiple iterations of S3 configuration fixes and port conflict resolution.
2025-07-21 20:37:07 -06:00
andreas b849e1d41a Fix port conflict between Museum server and Caddy
- Changed Museum server to run on port 8080 instead of 3080
- Updated all health check URLs to use port 8080
- Updated Caddy reverse proxy to forward API requests to port 8080
- Added clarifying comment about port usage

This resolves the circular reference where both Caddy and Museum were trying to use port 3080.
2025-07-21 17:18:51 -06:00
andreas 7986a0a58b Complete rewrite of Ente Cloudron app with cleaner architecture 2025-03-20 17:52:23 +01:00
andreas 5abfa15d93 Fix syntax error in validate_binary function 2025-03-20 17:38:20 +01:00
andreas af89daf278 Fix Museum binary validation and add Node.js fallback server 2025-03-20 17:29:12 +01:00
andreas f2116a5dbf Remove Node.js placeholder server completely and use actual Museum server 2025-03-20 17:14:12 +01:00
andreas fbfcb82f2c Enhance Node.js placeholder server with more API endpoints and improve user experience 2025-03-20 17:07:47 +01:00
andreas c5f631043b Fix Museum server binary issues using Docker approach 2025-03-20 16:35:30 +01:00
andreas f267b44f63 Fix Museum server binary issues and add Node.js fallback 2025-03-20 16:19:31 +01:00
andreas ec0950463b Replace Node.js placeholder with actual Museum server 2025-03-20 16:10:30 +01:00
andreas 321556f611 Fix infinite loop and implement reliable Node.js placeholder server 2025-03-20 16:03:16 +01:00
andreas 58a6d329be Fix infinite loop and implement reliable Node.js placeholder server 2025-03-20 15:59:51 +01:00
andreas 8fe05f6c47 Fix Go build environment and frontend URLs 2025-03-20 15:52:35 +01:00
andreas 20fe2bc96f Fix GitHub download URLs and implement placeholder server on port 3080 2025-03-20 15:41:24 +01:00
andreas 415be71ecf Fix GitHub download issues and provide fallback servers 2025-03-20 15:37:05 +01:00
andreas 593048373f Fix GitHub credentials issue, support s3.env, and ensure Caddy properly starts on port 3080 2025-03-20 15:33:49 +01:00
andreas 2ffd41cbad Add extensive debugging and more resilient startup 2025-03-20 15:29:43 +01:00
andreas 2d79243bb7 Remove mock server components and install real Ente server 2025-03-20 15:12:30 +01:00
andreas cdd6860521 Fix directory creation for static assets and web app files 2025-03-20 14:48:06 +01:00
andreas 263498c66d Implement comprehensive SRP Buffer polyfill to fix verification errors 2025-03-20 14:40:50 +01:00
andreas 049ed4aa49 Implement Caddy for web app serving and fix OTP verification issues 2025-03-20 14:32:26 +01:00
andreas e50a34747e Add browser compatibility fixes for URL constructor and Node.js functions 2025-03-20 14:18:30 +01:00
andreas 6596c652de Fix URL construction error and update verification endpoint with proper schema 2025-03-20 13:54:41 +01:00
andreas a94cd3de7f Replace Go mock server with Node.js implementation for better reliability 2025-03-20 13:45:58 +01:00
andreas 14842b8f4f Completely refactored startup script for proper museum server integration 2025-03-20 13:36:52 +01:00
andreas 70f0d8e419 Fix API server and URL handling for frontend connectivity 2025-03-20 13:22:13 +01:00
andreas 6c2646d093 Fix mock API server initialization and unbound variable issues 2025-03-20 13:04:11 +01:00
andreas 9aa4b171c2 Fix here-document syntax issues in runtime config generation and Go module setup for mock API server 2025-03-20 12:49:06 +01:00
andreas cad15b753c Fix here-document syntax error in runtime config generation and Go module initialization 2025-03-20 12:34:05 +01:00
andreas bbeb030fb1 Fix Go module structure for mock servers to resolve build issues 2025-03-18 21:52:41 +01:00
andreas 7453fe8e30 Fix mock API server startup issues on port 8080 2025-03-18 21:39:20 +01:00
andreas 2d7fe935b5 Fix mock server startup to ensure it starts properly and binds to the correct ports 2025-03-18 21:23:24 +01:00
andreas db4950a316 Fix verification parsing and make code validation more forgiving for testing 2025-03-18 20:54:41 +01:00
andreas 25371bcf8c Fix URL construction error by ensuring proper URL formats with protocol prefixes 2025-03-18 20:47:23 +01:00
andreas 589b93fda9 Fix syntax errors in mock servers and use HEREDOC with quoted delimiter to prevent shell interpretation issues 2025-03-18 20:42:29 +01:00
andreas 24051834f9 Fix syntax errors in mock API server Go code 2025-03-18 20:36:54 +01:00
andreas a1eacc6800 Replace hardcoded API URLs with dynamic CLOUDRON_APP_ORIGIN variable 2025-03-18 20:29:45 +01:00
andreas 53430140ca Update OTT handler to include required ID field in response 2025-03-18 20:28:45 +01:00
andreas 5ec5895638 Fixed signup verification code by adding a handler for /users/ott endpoint 2025-03-18 20:22:14 +01:00
andreas 91a066a900 Fixed empty HTML issue by copying and modifying the original HTML files 2025-03-18 20:16:12 +01:00
andreas 6e4346f2c1 Fixed Caddy filter directive and Go import issues 2025-03-18 20:12:30 +01:00
andreas edf2e457ea Fixed read-only filesystem issues by using Caddy's filter directives and improved mock servers 2025-03-18 20:08:15 +01:00
andreas 142b9927c0 Added registration code display in logs 2025-03-18 20:04:02 +01:00
andreas 9230cb7e8a Fixed frontend URL error by injecting config.js and runtime-config.js before Caddy starts 2025-03-18 20:03:16 +01:00
andreas 7a03dcdbdd Fixed Caddy config and Go module import issues 2025-03-18 19:58:49 +01:00
andreas 517ef4c0c6 Fixed Caddy config and file permissions issues 2025-03-18 19:55:11 +01:00
andreas 1150801603 Added MIME type configuration for Next.js assets in Caddy 2025-03-18 19:51:36 +01:00
andreas 14778231b1 Fixed mock servers by removing module flags and binding to all network interfaces 2025-03-18 19:43:42 +01:00
andreas a3c5d7b411 Fixed mock servers by removing module dependencies 2025-03-18 19:37:57 +01:00
andreas 71bf88f49a Implemented mock servers instead of trying to run Ente 2025-03-18 19:32:47 +01:00
andreas 0be5e84dc7 Fixed directory permissions and Go module handling 2025-03-18 19:26:22 +01:00
andreas 924ce9ced3 Fixed Go compiler errors and Caddy header syntax 2025-03-18 19:20:49 +01:00
andreas ee51507d2a Fixed creation of db_override.go in writable location 2025-03-18 19:15:11 +01:00
andreas 5307db4fa7 Fixed Caddy header syntax and moved db_override.go creation before server startup 2025-03-18 19:10:13 +01:00
andreas baca33c565 Fixed shell script syntax errors and created missing db_override.go file 2025-03-18 18:56:10 +01:00
andreas bf1ef9a8be Fixed filesystem access issues and network binding for dual-instance Ente setup 2025-03-18 18:48:26 +01:00
andreas 4cb24ede92 Add Caddy webserver implementation 2025-03-17 00:13:38 +01:00
andreas 70ace7fc9a Remove web server references from Dockerfile 2025-03-16 23:53:07 +01:00
andreas da8afdd97a Remove NGINX webserver implementation 2025-03-16 23:51:27 +01:00
andreas 121d10d6ce Fix NGINX config and aggressively patch database connection to prevent localhost 2025-03-16 23:47:43 +01:00
andreas a3a81a4439 Fix database connection issues by using standard PostgreSQL environment variables 2025-03-16 23:39:14 +01:00
andreas 6313f6528e Fix NGINX read-only filesystem and database connection issues 2025-03-16 23:33:59 +01:00
andreas cb85f771ac Switch from Caddy to NGINX and fix URL construction error 2025-03-16 23:29:27 +01:00
andreas 6716db77fe Fix unbound variable error by moving environment variable definitions earlier in the script 2025-03-16 23:24:56 +01:00
andreas 7e8e6796bb Fix database connection issues and serve photos app at root domain 2025-03-16 23:23:32 +01:00
andreas e3740e4c9e Fix cd command errors and ensure Caddy binds to all interfaces for healthchecks 2025-03-16 23:19:52 +01:00
andreas 736b1c5d75 Fix Go cache permission issues and ensure proper working directories 2025-03-16 23:17:47 +01:00
andreas 42c045aad3 Fix go.mod setup and improve mock server for better API compatibility 2025-03-16 23:14:36 +01:00
andreas 38ff54a341 Complete rewrite of Ente Cloudron app startup script with proper SERVER_DIR detection 2025-03-16 23:11:53 +01:00
andreas 035828dd1f Fix Caddy port configuration and improve connectivity testing 2025-03-16 23:05:14 +01:00
andreas 1907354bf8 Add robust configuration injection and debugging tools 2025-03-16 22:58:06 +01:00
andreas 29cda3bc2d Fix Caddyfile syntax for respond directive 2025-03-16 22:50:25 +01:00
andreas e300261f4f Remove hardcoded S3 credentials and simplify S3 configuration 2025-03-16 22:40:14 +01:00
andreas 62a0edfca3 Simplify Caddyfile configuration to fix syntax error 2025-03-16 22:32:18 +01:00
andreas 1648886ba2 Fix Caddyfile syntax error in rewrite_early directive 2025-03-16 22:21:03 +01:00
andreas 64459a39e4 Merge remote changes with local updates 2025-03-16 22:18:41 +01:00
andreas d777a26ab7 Update Cloudron app configuration and setup 2025-03-16 22:17:41 +01:00
andreas 4ad63bb672 Remove docs folder from repository 2025-03-16 22:16:53 +01:00
andreas 79e6b88e5f Update Readme 2025-03-16 20:36:42 +00:00
andreas 8f54d8aeb2 Fix permission issues with go.mod by using a writable copy 2025-03-14 23:41:56 +01:00
andreas 3cebe5d5df Update Go version to 1.24.1 to satisfy dependency requirements 2025-03-14 23:37:34 +01:00
andreas b902505524 Fix Go version compatibility issues and prevent automatic toolchain downloads 2025-03-14 23:35:14 +01:00
andreas bccf900ccb Fix Go version compatibility by using auto toolchain 2025-03-14 23:08:40 +01:00
andreas f784e5fd86 Fix Go version compatibility by explicitly using Go 1.22.2 2025-03-14 23:07:06 +01:00
andreas ebbf090373 Fix Go version compatibility by using local toolchain 2025-03-14 23:05:23 +01:00
andreas 0925d79852 Fix Go compatibility and mock server issues 2025-03-14 23:03:47 +01:00
andreas c40522d218 Fix Go compatibility for read-only filesystem 2025-03-14 23:00:26 +01:00
andreas d1b8fe0559 Fix Go version compatibility issues in start.sh 2025-03-14 22:57:54 +01:00
andreas 399e7e3b6b Improve start.sh with Cloudron best practices 2025-03-14 22:47:27 +01:00
andreas e9dfaecd72 Fix read-only filesystem issue with museum.yaml 2025-03-14 22:44:40 +01:00
andreas e6a75435a4 Fix user creation issues and add debugging 2025-03-14 22:29:21 +01:00
andreas ea12f23cfb Fix GOPATH permissions and properly generate random secrets 2025-03-14 22:24:26 +01:00
andreas 5337d19d1b Simplify NGINX configuration with correct directive placement 2025-03-14 22:16:39 +01:00
andreas ed70c9010f Fix NGINX configuration to use writable temp directories 2025-03-14 22:10:30 +01:00
andreas 3458f63aa2 Fix NGINX configuration to use writable directories 2025-03-14 22:07:22 +01:00
andreas d2a19463b2 Make scripts more robust to handle various repository structures 2025-03-14 21:59:22 +01:00
andreas df6aa7cdc4 Update to include both Museum server and web apps in single package 2025-03-14 21:45:09 +01:00
andreas 29acbdb9c8 Update config template for Museum server 2025-03-14 21:43:17 +01:00
andreas b492849666 Update Dockerfile to include Go and dependencies for Museum server 2025-03-14 21:42:45 +01:00
andreas 58dbd39bb7 Update start.sh to handle Museum Go server component 2025-03-14 21:42:26 +01:00
andreas 37c3f602b6 Enhance start.sh with improved server directory detection and debugging 2025-03-14 21:35:37 +01:00
andreas 87ce90b9e7 Finalize Dockerfile 2025-03-14 21:31:41 +01:00
andreas e535432e94 Update start.sh to handle different repository structures 2025-03-14 21:30:04 +01:00
andreas 435e3af06a Update Dockerfile to examine ente repository structure 2025-03-14 21:27:55 +01:00
andreas ac2da2db19 Add logo.png for Cloudron app 2025-03-14 21:20:52 +01:00
andreas 1d01c51099 Optimize build: remove embedded repositories from source and clone during Docker build 2025-03-14 21:03:47 +01:00
andreas a8858657dc Initial commit for Ente Cloudron package 2025-03-14 21:01:18 +01:00
22 changed files with 3113 additions and 957 deletions
+34
View File
@@ -0,0 +1,34 @@
# Ente Cloudron Quick Guide
## Build
```bash
git clone https://github.com/andreasdueren/ente-cloudron.git
cd ente-cloudron
cloudron build \
--set-build-service builder.docker.due.ren \
--build-service-token e3265de06b1d0e7bb38400539012a8433a74c2c96a17955e \
--set-repository andreasdueren/ente-cloudron \
--tag 0.5.3
```
## Install
```bash
cloudron install \
--location ente.due.ren \
--image andreasdueren/ente-cloudron:0.5.3
```
## After Install
1. **S3** In Cloudron File Manager open `/app/data/config/s3.env`, fill in your endpoint/region/bucket/access/secret, then restart the app from the dashboard. Optional replication: add both `S3_SECONDARY_*` (second hot bucket) **and** `S3_COLD_*` (cold bucket) variables to mirror uploads across three independent buckets. Replication is only enabled when all three buckets are present. See Entes [object storage guide](https://ente.io/help/self-hosting/administration/object-storage) for example configs.
2. **Secondary hostnames** During installation Cloudron now prompts for hostnames for the Accounts/Auth/Cast/Albums/Family web apps (powered by `httpPorts`). Ensure matching DNS records exist that point to the primary app domain. If you use Cloudron-managed DNS, those records are created automatically; otherwise create CNAME/A records such as `accounts.<app-domain> → <app-domain>`.
Once DNS propagates, use the dedicated hosts (defaults shown below — substitute the names you selected during install):
- `https://<app-host>` (the hostname you chose during install, main UI & uploads)
- `https://accounts.<app-domain>`
- `https://auth.<app-domain>`
- `https://cast.<app-domain>`
- `https://albums.<app-domain>`
- `https://family.<app-domain>`
Check `cloudron logs --app ente.due.ren -f` or `/app/data/logs/startup.log` if anything looks off.
+107 -1
View File
@@ -1,9 +1,115 @@
# Changelog
## 0.5.7 (2025-11-20)
* Bundle the Ente Families web app so `family.<domain>` serves the correct invite/management UI instead of the placeholder photos build.
* Ship built-in billing plan JSON so Museum can resolve subscriptions (`family/add-member`, invite acceptance) on self-hosted installs without manual DB edits.
* Fix passkey enrollment on the accounts host by ensuring only the photos domain matches the `/api` proxy block.
## 0.5.6 (2025-11-18)
* Allow the accounts frontend origin in Museums `webauthn.rporigins` when subdomain routing is enabled so passkey enrollment via the desktop flow succeeds
* Document the Ente desktop scheme (`ente://app`) in the recommended S3 CORS rules to keep signed URL fetches working for the desktop client
* Add full three-bucket replication support (hot primary, hot secondary, cold tier) and test the workflow with Backblaze (primary hot), Hetzner (secondary hot), and Scaleway Glacier (cold)
* Note that the cold bucket must accept the GLACIER storage class—point the `S3_COLD_*` variables at a provider that supports it, or enable `are_local_buckets`/`use_path_style_urls` so the start script switches Museum into local-bucket mode and skips the Glacier storage class entirely
## 0.5.5 (2025-11-18)
* Validate S3 data-center identifiers so replication only uses the canonical `b2-eu-cen`/`wasabi-eu-central-2-v3`/`scw-eu-fr-v3` keys and update the docs to reflect the upstream requirements
* Inject the API origin into all served HTML so the Next.js bundles (including `accounts/passkeys`) read the self-hosted endpoint instead of defaulting to `https://api.ente.io`
* Document the working Backblaze B2 CORS JSON that whitelists the wildcard origin + upload operations for desktop casts
## 0.5.4 (2025-11-18)
* Respect user-defined S3 data-center identifiers so replication targets use the intended buckets
## 0.5.1 (2025-11-05)
* Fix `httpPorts` host detection so accounts/cast/family/albums subdomains serve their static frontends again
## 0.5.2 (2025-11-05)
* Allow httpPort hostnames like `cast.ente`/`accounts.ente` so Cloudron can append the primary domain (`.due.ren`) automatically
## 0.5.3 (2025-11-05)
* Fix regression that could produce duplicated suffixes (e.g. `cast.due.due.ren`) when httpPort hostnames already included the full domain
## 0.5.0 (2025-11-04)
* Proxy Museum GET/HEAD routes (e.g. `/collections`, `/files`, `/remote-store`) so clients that talk to the primary host without `/api` still hit the backend
## 0.4.13 (2025-11-04)
* Forward all non-GET requests to the Museum backend so uploads and other write operations reach the API
## 0.4.12 (2025-11-04)
* Ensure dedicated hosts serve static `.html` exports and SPA fallbacks (`/gallery`, etc.) without 404s
## 0.4.11 (2025-11-04)
* Serve static `.html` exports for all dedicated hosts so routes like `/gallery` refresh and upload flows work again
## 0.4.10 (2025-11-04)
* Fix SPA fallbacks on dedicated hosts so `/gallery` and other client routes refresh correctly
## 0.4.9 (2025-11-04)
* Raise default memory allocation to 3 GiB for smoother media processing workloads
## 0.4.8 (2025-11-04)
* Allow persistent Museum overrides via `/app/data/config/museum.override.yaml` while keeping generated defaults intact
## 0.4.7 (2025-11-04)
* Proxy `/users` API endpoints through Caddy so mobile SRP/OTT flows reach the backend
## 0.4.6 (2025-11-04)
* Switch to Cloudron `httpPorts` so secondary web apps get provisioned domains automatically
* Teach the startup script to honour Cloudron-provided secondary domain variables (no manual aliasing required)
* Refresh post-install docs and build instructions to reflect the new installation flow
## 0.4.5 (2025-10-30)
* Serve photos UI on the primary hostname and mount other apps on `accounts/auth/cast/albums/family.<app-domain>`
* Enable multiDomain in the manifest so aliases can be set in Cloudron UI
* Simplified documentation for S3 setup and alias domains
* Fix CORS responses for auth subdomains and forward real client IPs from Cloudron proxy
* Remove unsupported Caddy `trusted_proxies` stanza while continuing to trust Cloudron-provided `X-Forwarded-For` headers for accurate logging
* Set CORS headers via reverse proxy response rewrites so cross-subdomain logins work reliably
## 0.4.4 (2025-10-30)
* Restore Cloudflare R2 path-style URLs and simplify to a single hot-storage data center
* Serve the frontend apps on dedicated subdomains (photos/accounts/auth/cast/albums/family)
* Startup script now regenerates Caddy and Museum configs for the new host layout
* Added post-install checklist entries and updated docs for required DNS records
## 0.4.3 (2025-10-29)
* Always regenerate Museum configuration on startup to pick up S3 credential changes
* Enables seamless workflow: add S3 credentials to /app/data/config/s3.env and restart
* Fixes issue where S3 configuration changes required manual intervention
## 0.4.2 (2025-10-29)
* Use SMTPS (port 2465) with TLS encryption for email delivery
* Fixes email sending with requiresValidCertificate flag on Cloudron 9
## 0.4.1 (2025-10-23)
* Fix email sending for user registration by enabling TLS certificate validation in sendmail addon
* Add requiresValidCertificate flag to sendmail configuration to ensure proper SMTP authentication with Go applications
* Note: Requires Cloudron 9 or later for requiresValidCertificate support
## 1.0.0 (2024-06-01)
* Initial release of Ente for Cloudron
* Integrates with PostgreSQL database
* Integrates with S3-compatible object storage
* Integrates with Cloudron mail system
* Provides web UI for photos and authentication
* Provides web UI for photos and authentication
+158
View File
@@ -0,0 +1,158 @@
Cloudron Application Packaging System Prompt
You are a Cloudron packaging expert specializing in creating complete, production-ready Cloudron packages. When a user requests packaging an application, follow this comprehensive process:
Core Process
1. Application Research: Research the target application's architecture, dependencies, configuration requirements, and deployment patterns
2. Package Generation: Create all required Cloudron packaging files
3. Documentation: Provide build and deployment instructions
Required Files to Generate
CloudronManifest.json
- Use reverse-domain notation for app ID (e.g., io.example.appname)
- Configure memory limits based on application requirements (minimum 128MB)
- Set httpPort matching NGINX configuration
- Include necessary addons: postgresql, mysql, mongodb, redis, localstorage, sendmail
- Add complete metadata: title, description, author, website, contactEmail
- Configure authentication: oidc (preferred) or ldap
- Include postInstallMessage with login credentials if applicable
- Add health check endpoints
- Set proper minBoxVersion (typically "7.0.0")
Dockerfile
- Base image: FROM cloudron/base:5.0.0
- Cloudron filesystem structure:
- /app/code - application code (read-only)
- /app/data - persistent data (backed up)
- /tmp - temporary files
- /run - runtime files
- Install dependencies and application
- Copy initialization data to /tmp/data
- Set proper permissions and ownership
- Configure services to log to stdout/stderr
- Entry point: CMD ["/app/code/start.sh"]
start.sh
- Initialize /app/data from /tmp/data on first run
- Configure application using Cloudron environment variables
- Handle addon configurations (database connections, etc.)
- Generate secrets/API keys on first run
- Set proper file permissions (chown cloudron:cloudron)
- Run database migrations if needed
- Configure authentication providers
- Launch application with supervisor or directly
NGINX Configuration
- Listen on port specified in CloudronManifest.json
- Handle proxy headers properly:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;
- Configure static file serving
- Set up authentication routes for OIDC callbacks
- Ensure logs go to stdout/stderr
Supervisor Configuration (if needed)
- Multiple process management
- Proper signal handling
- Run processes as cloudron user
- Configure log output to stdout/stderr
Authentication Integration
OIDC (Preferred)
- Environment variables: CLOUDRON_OIDC_IDENTIFIER, CLOUDRON_OIDC_CLIENT_ID, CLOUDRON_OIDC_CLIENT_SECRET
- Callback route: /api/v1/session/callback
- User provisioning and group mapping
- Session management compatible with Cloudron proxy
LDAP (Fallback)
- Environment variables: CLOUDRON_LDAP_SERVER, CLOUDRON_LDAP_PORT, CLOUDRON_LDAP_BIND_DN, CLOUDRON_LDAP_BIND_PASSWORD
- User search base and group mapping
- Proper LDAP query configuration
Cloudron Environment Variables
Always utilize these standard variables:
- CLOUDRON_APP_ORIGIN - Application URL
- CLOUDRON_MAIL_SMTP_* - Email configuration
- Database addon variables (e.g., CLOUDRON_POSTGRESQL_URL)
- CLOUDRON_LDAP_* - LDAP configuration
- CLOUDRON_OIDC_* - OIDC configuration
Best Practices
1. Security: Never expose secrets, use environment variables
2. Persistence: Store data in /app/data, initialize from /tmp/data
3. Updates: Handle schema migrations and configuration updates
4. Logging: All logs to stdout/stderr for Cloudron log aggregation
5. Health Checks: Implement endpoints for monitoring
6. Process Management: Use supervisor for multi-process applications
7. File Permissions: Ensure cloudron user can read/write necessary files
8. Building: use the cloudron build service under builder.docker.due.ren
9. Installation: always uninstall and install fresh, never update an app during development
Build Instructions Format
Create a markdown file with:
- Prerequisites and dependencies
- Build commands (cloudron build, cloudron install)
- Testing procedures
- Deployment steps
- Troubleshooting common issues
- Configuration examples
Documentation References
- Cloudron CLI: https://docs.cloudron.io/packaging/cli/
- Packaging Tutorial: https://docs.cloudron.io/packaging/tutorial/
- Manifest Reference: https://docs.cloudron.io/packaging/manifest/
- Addons Guide: https://docs.cloudron.io/packaging/addons/
Viewing logs
To view the logs of an app, use the logs command:
```cloudron logs --app blog.example.com```
```cloudron logs --app 52aae895-5b7d-4625-8d4c-52980248ac21```
Pass the -f to follow the logs. Note that not all apps log to stdout/stderr. For this reason, you may need to look further in the file system for logs:
```cloudron exec --app blog.example.com # shell into the app's file system```
``# tail -f /run/wordpress/wp-debug.log # note that log file path and name is specific to the app```
When packaging an application, research thoroughly, create production-ready configurations, and provide comprehensive documentation for successful deployment.
Always Build with the build service (switch out name and version) build with cloudron build --set-build-service builder.docker.due.ren --build-service-token
e3265de06b1d0e7bb38400539012a8433a74c2c96a17955e --set-repository andreasdueren/ente-cloudron --tag 0.1.0
cloudron install --location ente.due.ren --image andreasdueren/ente-cloudron:0.1.0
After install and build, dont wait more than 30 seconds for feedback. When there is an error during install, this will not finish and you will wait forever.
Remember all of this crucial information throughout the packaging process. Create a file for persistency if necessary to poll from later. 

Fix this packaging of ente for cloudron:
https://github.com/ente-io/ente/tree/main
There is documentation about self-hosting here: https://github.com/ente-io/ente/tree/main/docs/docs/self-hosting and here https://github.com/ente-io/ente/tree/main/server
Use Caddy as a reverse proxy. More info on setting it up: https://help.ente.io/self-hosting/reverse-proxy
Set up all web-apps (public-albums, cast, accounts, family). Use a path (/albums, /cast…) and not sub domains.: https://help.ente.io/self-hosting/museum
Stick to the original maintainers setup as close as possible while adhering to cordons restricti0ns. Use cloudrons postgresql as a database and an external s3 instance for object storage. You can use the following credentials for development but never commit these to any repository:
primary-storage:
key: "bbdfcc78c3d8aa970498fc309f1e5876" # Your S3 access key
secret: "4969ba66f326b4b7af7ca69716ee4a16931725a351a93643efce6447f81c9d68" # Your S3 secret key
endpoint: "40db7844966a4e896ccfac20ac9e7fb5.r2.cloudflarestorage.com" # S3 endpoint URL
region: "wnam" # S3 region (e.g. us-east-1)
bucket: "ente-due-ren" # Your bucket name
Here are the instructions as to how to use an external s3: https://help.ente.io/self-hosting/guides/external-s3
+21
View File
@@ -0,0 +1,21 @@
{
admin off
auto_https off
}
:3080 {
log {
output stdout
level DEBUG
}
# Simple health check that always works
handle /health {
respond "{\"status\": \"OK\"}" 200
}
# Catch-all for debugging
handle {
respond "Caddy is running on port 3080" 200
}
}
+75 -17
View File
@@ -1,38 +1,96 @@
{
"id": "io.ente.cloudronapp",
"title": "Ente",
"author": "Ente Authors",
"author": "Ente Development Team",
"description": "file://DESCRIPTION.md",
"changelog": "file://CHANGELOG.md",
"contactEmail": "contact@ente.io",
"tagline": "Open Source End-to-End Encrypted Photos & Authentication",
"upstreamVersion": "1.0.0",
"version": "0.1.62",
"healthCheckPath": "/ping",
"website": "https://ente.io",
"tagline": "Open source, end-to-end encrypted photo backup",
"version": "0.5.6",
"upstreamVersion": "git-main",
"healthCheckPath": "/health",
"httpPort": 3080,
"memoryLimit": 1073741824,
"httpPorts": {
"ACCOUNTS_DOMAIN": {
"title": "Accounts hostname",
"description": "Hostname for the Ente accounts web app (e.g. accounts)",
"containerPort": 3080,
"defaultValue": "accounts",
"aliasableDomain": true
},
"AUTH_DOMAIN": {
"title": "Auth hostname",
"description": "Hostname for the Ente authentication frontend (e.g. auth)",
"containerPort": 3080,
"defaultValue": "auth",
"aliasableDomain": true
},
"CAST_DOMAIN": {
"title": "Cast hostname",
"description": "Hostname for the Ente casting web app (e.g. cast)",
"containerPort": 3080,
"defaultValue": "cast",
"aliasableDomain": true
},
"ALBUMS_DOMAIN": {
"title": "Public albums hostname",
"description": "Hostname for the Ente public albums frontend (e.g. albums)",
"containerPort": 3080,
"defaultValue": "albums",
"aliasableDomain": true
},
"SHARE_DOMAIN": {
"title": "Public locker hostname",
"description": "Hostname for the Ente share/collaboration frontend (e.g. share)",
"containerPort": 3080,
"defaultValue": "share",
"aliasableDomain": true
},
"EMBED_DOMAIN": {
"title": "Embed hostname",
"description": "Hostname for the Ente embed frontend (e.g. embed)",
"containerPort": 3080,
"defaultValue": "embed",
"aliasableDomain": true
},
"PAYMENTS_DOMAIN": {
"title": "Payments hostname",
"description": "Hostname for the Ente payments frontend (e.g. payments)",
"containerPort": 3080,
"defaultValue": "payments",
"aliasableDomain": true
},
"FAMILY_DOMAIN": {
"title": "Family hostname",
"description": "Hostname for the Ente family web app (e.g. family)",
"containerPort": 3080,
"defaultValue": "family",
"aliasableDomain": true
}
},
"memoryLimit": 3221225472,
"postInstallMessage": "file://POSTINSTALL.md",
"addons": {
"localstorage": {},
"postgresql": {},
"email": {},
"sendmail": {
"supportsDisplayName": true
"supportsDisplayName": true,
"requiresValidCertificate": true
}
},
"checklist": {
"create-permanent-admin": {
"message": "Required: S3 Storage Configuration!"
"configure-object-storage": {
"message": "Configure your S3-compatible storage in /app/data/config/s3.env before first use."
}
},
"icon": "file://logo.png",
"tags": [
"photos",
"authentication",
"e2ee",
"encryption"
"encryption",
"backup",
"self-hosting"
],
"manifestVersion": 2,
"minBoxVersion": "8.1.0",
"website": "https://ente.io"
}
"minBoxVersion": "8.1.0"
}
+130 -149
View File
@@ -1,173 +1,154 @@
# Build Museum server from source
# syntax=docker/dockerfile:1
ARG ENTE_GIT_REF=main
ARG FAMILIES_GIT_REF=main
FROM debian:bookworm AS ente-source
ARG ENTE_GIT_REF
COPY patches /patches
RUN set -e; \
apt-get update && \
apt-get install -y --no-install-recommends ca-certificates git patch && \
git clone --depth=1 --branch "${ENTE_GIT_REF}" https://github.com/ente-io/ente.git /src && \
if [ -d /patches ]; then \
for patch_file in /patches/*.patch; do \
[ -f "$patch_file" ] || continue; \
(cd /src && patch -p1 < "$patch_file"); \
done; \
fi && \
rm -rf /var/lib/apt/lists/*
FROM debian:bookworm AS families-source
ARG FAMILIES_GIT_REF
RUN apt-get update && \
apt-get install -y --no-install-recommends ca-certificates git && \
git clone --depth=1 --branch "${FAMILIES_GIT_REF}" https://github.com/ente-io/families.git /families && \
rm -rf /var/lib/apt/lists/*
FROM golang:1.24-bookworm AS museum-builder
WORKDIR /ente
# Clone the repository for server building
RUN apt-get update && apt-get install -y git libsodium-dev && \
git clone --depth=1 https://github.com/ente-io/ente.git . && \
apt-get clean && apt-get autoremove && \
rm -rf /var/cache/apt /var/lib/apt/lists
# Build the Museum server
COPY --from=ente-source /src /ente
WORKDIR /ente/server
RUN go mod download && \
CGO_ENABLED=1 GOOS=linux go build -a -o museum ./cmd/museum
RUN apt-get update && \
apt-get install -y --no-install-recommends build-essential pkg-config libsodium-dev && \
rm -rf /var/lib/apt/lists/*
RUN mkdir -p /build/museum && \
CGO_ENABLED=1 GOOS=linux go build -o /build/museum/museum ./cmd/museum && \
for dir in migrations web-templates mail-templates assets; do \
rm -rf "/build/museum/$dir"; \
if [ -d "$dir" ]; then \
cp -r "$dir" "/build/museum/$dir"; \
else \
mkdir -p "/build/museum/$dir"; \
fi; \
done
FROM node:20-bookworm-slim as web-builder
FROM golang:1.24-bookworm AS cli-builder
COPY --from=ente-source /src /ente
WORKDIR /ente/cli
RUN go build -o /build/ente .
WORKDIR /ente
# Clone the repository for web app building
RUN apt-get update && apt-get install -y git && \
git clone --depth=1 https://github.com/ente-io/ente.git . && \
apt-get clean && apt-get autoremove && \
rm -rf /var/cache/apt /var/lib/apt/lists
# Will help default to yarn version 1.22.22
FROM node:20-bookworm-slim AS web-builder
ENV NEXT_PUBLIC_ENTE_ENDPOINT=ENTE_API_ORIGIN_PLACEHOLDER
ENV NEXT_PUBLIC_ENTE_ALBUMS_ENDPOINT=https://albums.localhost.invalid
COPY --from=ente-source /src /ente
WORKDIR /ente/web
RUN apt-get update && \
apt-get install -y --no-install-recommends build-essential python3 && \
rm -rf /var/lib/apt/lists/*
RUN corepack enable
# Set environment variables for web app build
# Set the API endpoint to use current origin - this will work at runtime
ENV NEXT_PUBLIC_ENTE_ENDPOINT="https://example.com/api"
# Add a note for clarity
RUN echo "Building with placeholder NEXT_PUBLIC_ENTE_ENDPOINT, will be served by Caddy proxy at /api"
# Debugging the repository structure
RUN find . -type d -maxdepth 3 | sort
# Check if web directory exists with apps subdirectory
RUN mkdir -p /build/web/photos /build/web/accounts /build/web/auth /build/web/cast && \
if [ -d "web" ] && [ -d "web/apps" ]; then \
echo "Found web/apps directory, building web apps"; \
cd web && \
yarn cache clean && \
yarn install --network-timeout 1000000000 && \
yarn build:photos && \
yarn build:accounts && \
yarn build:auth && \
yarn build:cast && \
if [ -d "apps/photos/out" ]; then \
cp -r apps/photos/out/* /build/web/photos/; \
fi && \
if [ -d "apps/accounts/out" ]; then \
cp -r apps/accounts/out/* /build/web/accounts/; \
fi && \
if [ -d "apps/auth/out" ]; then \
cp -r apps/auth/out/* /build/web/auth/; \
fi && \
if [ -d "apps/cast/out" ]; then \
cp -r apps/cast/out/* /build/web/cast/; \
fi; \
elif [ -d "web" ]; then \
echo "Found web directory, looking for alternative structure"; \
find web -type d | grep -v node_modules | sort; \
if [ -d "web/photos" ]; then \
echo "Building photos app"; \
cd web/photos && yarn install && yarn build && \
if [ -d "out" ]; then cp -r out/* /build/web/photos/; fi; \
fi; \
if [ -d "web/accounts" ]; then \
echo "Building accounts app"; \
cd web/accounts && yarn install && yarn build && \
if [ -d "out" ]; then cp -r out/* /build/web/accounts/; fi; \
fi; \
if [ -d "web/auth" ]; then \
echo "Building auth app"; \
cd web/auth && yarn install && yarn build && \
if [ -d "out" ]; then cp -r out/* /build/web/auth/; fi; \
fi; \
if [ -d "web/cast" ]; then \
echo "Building cast app"; \
cd web/cast && yarn install && yarn build && \
if [ -d "out" ]; then cp -r out/* /build/web/cast/; fi; \
RUN yarn install --network-timeout 1000000
RUN mkdir -p /build/web/photos /build/web/accounts /build/web/auth /build/web/cast /build/web/albums /build/web/family /build/web/share /build/web/embed /build/web/payments
RUN set -e; \
yarn build:photos; \
yarn build:accounts; \
yarn build:auth; \
yarn build:cast; \
yarn build:share; \
yarn build:embed; \
yarn build:payments
RUN if [ -d "apps" ]; then \
for app in photos accounts auth cast share embed payments; do \
if [ -d "apps/${app}/out" ]; then \
rm -rf "/build/web/${app}"; \
mkdir -p "/build/web/${app}"; \
cp -r "apps/${app}/out/." "/build/web/${app}/"; \
else \
printf 'Missing build output for %s\n' "${app}"; \
printf '<html><body><h1>Ente %s</h1><p>Build output missing.</p></body></html>\n' "${app}" > "/build/web/${app}/index.html"; \
fi; \
done; \
else \
echo "Web directory not found, creating placeholder web pages"; \
# Create placeholder HTML files for each app \
mkdir -p /build/web/photos /build/web/accounts /build/web/auth /build/web/cast; \
echo "<html><body><h1>Ente Photos</h1><p>Web app not available. Please check the build logs.</p></body></html>" > /build/web/photos/index.html; \
echo "<html><body><h1>Ente Accounts</h1><p>Web app not available. Please check the build logs.</p></body></html>" > /build/web/accounts/index.html; \
echo "<html><body><h1>Ente Auth</h1><p>Web app not available. Please check the build logs.</p></body></html>" > /build/web/auth/index.html; \
echo "<html><body><h1>Ente Cast</h1><p>Web app not available. Please check the build logs.</p></body></html>" > /build/web/cast/index.html; \
fi
for app in photos accounts auth cast; do \
printf '<html><body><h1>Ente %s</h1><p>Build output missing.</p></body></html>\n' "${app}" > "/build/web/${app}/index.html"; \
done; \
fi && \
rm -rf /build/web/albums && \
cp -r /build/web/photos /build/web/albums
FROM node:20-bookworm-slim AS families-builder
ENV NEXT_PUBLIC_ENTE_ENDPOINT=ENTE_API_ORIGIN_PLACEHOLDER \
NEXT_WEB_ENTE_ENDPOINT=ENTE_WEB_ENDPOINT_PLACEHOLDER \
NEXT_PUBLIC_IS_SENTRY_ENABLED=no \
NEXT_PUBLIC_SENTRY_ENV=local \
NEXT_PUBLIC_SENTRY_DSN= \
NEXT_TELEMETRY_DISABLED=1
COPY --from=families-source /families /families
WORKDIR /families
RUN apt-get update && \
apt-get install -y --no-install-recommends build-essential python3 && \
rm -rf /var/lib/apt/lists/*
RUN corepack enable
RUN yarn install --network-timeout 1000000
RUN mkdir -p /build/family && \
yarn build && \
./node_modules/.bin/next export -o /build/family
FROM cloudron/base:5.0.0@sha256:04fd70dbd8ad6149c19de39e35718e024417c3e01dc9c6637eaf4a41ec4e596c
# Install necessary packages and Caddy webserver
ENV APP_DIR=/app/code \
DATA_DIR=/app/data \
HOME=/app/data/home
RUN apt-get update && \
apt-get install -y curl git nodejs npm libsodium23 libsodium-dev pkg-config postgresql-client && \
npm install -g yarn serve && \
# Install Caddy for web server
apt-get install -y debian-keyring debian-archive-keyring apt-transport-https && \
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg && \
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | tee /etc/apt/sources.list.d/caddy-stable.list && \
apt-get update && \
apt-get install -y caddy && \
apt-get clean && apt-get autoremove && \
rm -rf /var/cache/apt /var/lib/apt/lists
apt-get install -y --no-install-recommends ca-certificates curl jq libsodium23 pkg-config postgresql-client caddy openssl && \
rm -rf /var/lib/apt/lists/*
# Install Go 1.24.1
RUN curl -L https://go.dev/dl/go1.24.1.linux-amd64.tar.gz -o go.tar.gz && \
rm -rf /usr/local/go && \
tar -C /usr/local -xzf go.tar.gz && \
rm go.tar.gz && \
ln -sf /usr/local/go/bin/go /usr/local/bin/go && \
ln -sf /usr/local/go/bin/gofmt /usr/local/bin/gofmt
RUN mkdir -p /app/pkg /app/web "$HOME" && chown -R cloudron:cloudron /app /app/web "$HOME"
# Set up directory structure
RUN mkdir -p /app/code /app/data/config /app/data/caddy /app/web
COPY --from=ente-source /src ${APP_DIR}
COPY data ${APP_DIR}/data
RUN rm -rf ${APP_DIR}/.git
WORKDIR /app/code
RUN mkdir -p /app/museum-bin
COPY --from=museum-builder /build/museum/museum /app/museum-bin/museum
COPY --from=museum-builder /build/museum/migrations ${APP_DIR}/server/migrations
COPY --from=museum-builder /build/museum/web-templates ${APP_DIR}/server/web-templates
COPY --from=museum-builder /build/museum/mail-templates ${APP_DIR}/server/mail-templates
COPY --from=museum-builder /build/museum/assets ${APP_DIR}/server/assets
RUN chmod +x /app/museum-bin/museum
# Clone the ente repository during build (for the Museum server)
RUN git clone --depth=1 https://github.com/ente-io/ente.git . && \
sed -i 's/go 1.23/go 1.24.1/' server/go.mod && \
mkdir -p /app/data/go && \
cp -r server/go.mod server/go.sum /app/data/go/ && \
chmod 777 /app/data/go/go.mod /app/data/go/go.sum
COPY --from=cli-builder /build/ente /app/code/ente
RUN ln -sf /app/code/ente /usr/local/bin/ente && chmod +x /app/code/ente
# Pre-download Go dependencies
RUN cd server && \
export GOMODCACHE="/app/data/go/pkg/mod" && \
export GOFLAGS="-modfile=/app/data/go/go.mod -mod=mod" && \
export GOTOOLCHAIN=local && \
export GO111MODULE=on && \
export GOSUMDB=off && \
mkdir -p /app/data/go/pkg/mod && \
chmod -R 777 /app/data/go && \
go mod download
# Set Go environment variables
ENV GOTOOLCHAIN=local
ENV GO111MODULE=on
ENV GOFLAGS="-modfile=/app/data/go/go.mod -mod=mod"
ENV PATH="/usr/local/go/bin:${PATH}"
ENV GOSUMDB=off
ENV GOMODCACHE="/app/data/go/pkg/mod"
# Copy the web app built files from the first stage
COPY --from=web-builder /build/web/photos /app/web/photos
COPY --from=web-builder /build/web/accounts /app/web/accounts
COPY --from=web-builder /build/web/auth /app/web/auth
COPY --from=web-builder /build/web/cast /app/web/cast
COPY --from=web-builder /build/web/albums /app/web/albums
COPY --from=web-builder /build/web/share /app/web/share
COPY --from=web-builder /build/web/embed /app/web/embed
COPY --from=web-builder /build/web/payments /app/web/payments
COPY --from=families-builder /build/family /app/web/family
# Copy Museum server binary from builder stage to app directory (not data volume)
RUN mkdir -p /app/museum-bin
COPY --from=museum-builder /ente/server/museum /app/museum-bin/museum
RUN chmod +x /app/museum-bin/museum
COPY start.sh /app/pkg/start.sh
COPY admin-helper.sh /app/pkg/admin-helper.sh
COPY admin-helper-direct.sh /app/pkg/admin-helper-direct.sh
# Copy configuration and startup scripts
ADD start.sh /app/pkg/
ADD config.template.yaml /app/pkg/
RUN chmod +x /app/pkg/start.sh /app/pkg/admin-helper.sh /app/pkg/admin-helper-direct.sh
RUN ln -s /app/data/cli-data /cli-data && \
rm -rf /home/cloudron && \
ln -s /app/data/home /home/cloudron
# Set proper permissions
RUN chmod +x /app/pkg/start.sh
EXPOSE 3080 8080
# Expose the web port (Cloudron expects port 3080)
EXPOSE 3080
# Also expose API port
EXPOSE 8080
# Start the application
CMD ["/app/pkg/start.sh"]
CMD ["/app/pkg/start.sh"]
+84 -19
View File
@@ -1,25 +1,90 @@
Your Ente installation is almost ready!
## Required: S3 Storage Configuration
## Required: External Object Storage
Before you can use Ente, you need to configure an S3-compatible storage service:
Before using Ente, configure an S3-compatible object storage provider:
1. Go to your Cloudron dashboard
2. Click on your Ente app
3. Click on "Terminal"
4. Edit the S3 configuration template:
```
nano /app/data/config/s3.env.template
```
5. Fill in your S3 credentials (AWS S3, MinIO, DigitalOcean Spaces, etc.)
6. Save the file and rename it:
```
mv /app/data/config/s3.env.template /app/data/config/s3.env
```
7. Restart your Ente app from the Cloudron dashboard
1. Open the Cloudron dashboard and select your Ente app.
2. Launch the file explorer.
3. Open `/app/data/config/s3.env` and provide values for **all** required keys.
4. Save the file and restart the app from the Cloudron dashboard.
5. (Required for cast/slideshow) Configure your S3 buckets CORS policy to allow the Ente domains you serve from Cloudron (e.g. `https://ente.due.ren`, `https://accounts.due.ren`, `https://cast.due.ren`, etc.). Without CORS, browsers will block the signed URLs that power the cast slideshow.
- **Backblaze B2 tip:** B2 ships with “native” CORS rules that block S3-style updates. Install the Backblaze CLI `pip install 'b2<4'`, then:
```bash
# Authorise once (replace with your key ID/secret)
b2 authorize-account <KEY_ID> <APP_KEY>
## Next Steps
# Inspect the current bucket type (usually allPrivate) and capture it
BUCKET_TYPE=$(b2 get-bucket ente-due-ren | awk -F'"' '/bucketType/ {print $4}')
1. Once S3 is configured, visit your app URL to create an admin account
2. Configure your mobile apps to use your custom self-hosted server (Settings → Advanced → Custom Server)
3. Enjoy your private, end-to-end encrypted photo storage!
# Clear any native rules without changing visibility
b2 update-bucket ente-due-ren "$BUCKET_TYPE" --cors-rules '[]'
# Apply the S3-compatible rule (adjust origins as needed)
cat >cors.json <<'EOF'
[
{
"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
}
]
EOF
b2 update-bucket ente-due-ren "$BUCKET_TYPE" --cors-rules "$(<cors.json)"
```
Verify with `curl -I -H 'Origin: https://ente.due.ren' <signed-url>`; you should see `Access-Control-Allow-Origin`.
Supported variables (these map directly to the fields described in the upstream “Configuring Object Storage” documentation):
- `S3_ENDPOINT` (e.g. `https://<account>.r2.cloudflarestorage.com`)
- `S3_REGION`
- `S3_BUCKET`
- `S3_ACCESS_KEY`
- `S3_SECRET_KEY`
- `S3_PREFIX` (optional path prefix)
- `S3_ARE_LOCAL_BUCKETS` (set to `false` when your provider uses HTTPS “real” domains instead of MinIO-style LAN endpoints)
- `S3_FORCE_PATH_STYLE` (set to `true` for MinIO, Cloudflare R2, Backblaze, or any host that requires `https://host/bucket/object` URLs)
- `S3_PRIMARY_DC`, `S3_SECONDARY_DC`, `S3_COLD_DC`, `S3_DERIVED_DC` (advanced: pick from the canonical data-center identifiers listed in the upstream docs. The names are hard-coded in Museum; leave them at `b2-eu-cen`, `wasabi-eu-central-2-v3`, `scw-eu-fr-v3` unless you know you need one of the legacy aliases such as `scw-eu-fr`.)
- Optional replication: define **both** `S3_SECONDARY_*` and `S3_COLD_*` (endpoints, keys, secrets, optional prefixes, DC names) to mirror uploads to a second hot bucket and a third cold bucket. Replication is only enabled when all three buckets are configured; otherwise the app stays in single-bucket mode. See [Entes object storage guide](https://ente.io/help/self-hosting/administration/object-storage) for sample layouts and discussion of reliability.
You should never edit the generated `/app/data/museum/configurations/local.yaml` directly. If you need to append extra settings (for example, defining `internal.super-admins`), create `/app/data/config/museum.override.yaml` and add only the keys you want to override. Copying the entire sample `s3:` block from the docs into that file will erase the credentials that the package renders from `s3.env` and break replication.
## Required: Secondary Hostnames
The installer now asks for dedicated hostnames for the Auth/Accounts/Cast/Albums/Family web apps (via Cloudron `httpPorts`). If you manage DNS outside of Cloudron, create CNAME/A records such as `accounts.<app-domain>`, `auth.<app-domain>`, etc., pointing at the primary app domain. With Cloudron-managed DNS the records are created automatically.
## Administration
- **Grant yourself admin privileges**
1. Open the Cloudron dashboard → your Ente app → **File Manager**.
2. Navigate to `/app/data/config/` and open (or create) `museum.override.yaml`.
3. Add your email to the super-admin list:
```yaml
internal:
super-admins:
- you@example.com
```
4. Save the file and restart the app. The override is appended to Museums configuration on every start.
- **Sign in to the bundled CLI**
*The package now preconfigures the CLI (config: `/app/data/cli-data/config.yaml`, exports: `/app/data/cli-data/export`).*
From the Cloudron **Terminal** run:
```bash
# authenticate once (enter the OTP you receive by email)
sudo -u cloudron ente account add
# inspect available commands
sudo -u cloudron ente --help
```
After youre signed in you can follow the upstream docs for tasks like increasing storage: see [user administration](https://ente.io/help/self-hosting/administration/users) and the [CLI reference](https://ente.io/help/self-hosting/administration/cli). The [object storage guide](https://ente.io/help/self-hosting/administration/object-storage) explains the reliability setup: fill out `S3_*`, `S3_SECONDARY_*`, and `S3_COLD_*` in `/app/data/config/s3.env`, and the package will automatically enable three-bucket replication when you restart (no extra toggle needed).
+81 -43
View File
@@ -9,28 +9,6 @@ This repository contains the Cloudron packaging for [Ente](https://ente.io), an
- Configured to use Cloudron's mail service for sending emails
- Easy to deploy and manage through the Cloudron interface
## Requirements
### Browser Compatibility
Ente uses modern web technologies for its end-to-end encryption:
- **WebAssembly**: Required for cryptographic operations
- **IndexedDB**: Required for client-side data storage
Most modern browsers support these features, but they may be blocked by:
- Browser privacy settings
- Content Security Policies
- Certain browser extensions
This package includes custom Caddy configuration with appropriate security headers to ensure these features work correctly.
### S3-Compatible Storage
Ente requires an S3-compatible object storage service. You can use:
- Cloudron's built-in object storage
- External services like AWS S3, Wasabi, or MinIO
## Building and Installing
### Option 1: Build and Install Manually
@@ -73,23 +51,95 @@ The app is configured automatically using Cloudron's environment variables for:
- SMTP mail service
- App origin URL
### Additional Configuration
### Cloudron Admin Notes
The package includes several enhancements to ensure proper functionality:
After installing on Cloudron remember to:
1. **Security Headers**: Custom Content-Security-Policy headers that allow WebAssembly and IndexedDB
2. **API Configuration**: Dynamic runtime configuration to ensure the frontend connects to the correct API endpoint
3. **CORS Headers**: Proper CORS configuration for API access
1. Open the File Manager for the app, edit `/app/data/config/s3.env`, and set the S3-compatible credentials that belong in `museum.yaml`. The upstream documentation expects the canonical keys `b2-eu-cen` (primary), `wasabi-eu-central-2-v3` (secondary) and `scw-eu-fr-v3` (cold); this package renders those blocks automatically from the environment variables below so you dont have to touch the generated config. At minimum set `S3_ENDPOINT`, `S3_REGION`, `S3_BUCKET`, `S3_ACCESS_KEY`, `S3_SECRET_KEY`, plus the optional `S3_PREFIX`. To enable replication you must also define **both** `S3_SECONDARY_*` and `S3_COLD_*` (endpoint, region, bucket, key, secret, optional prefix/DC overrides); after a restart the package will flip `replication.enabled` on your behalf when all three buckets are present. Advanced knobs from the documentation map to the following variables:
- `S3_ARE_LOCAL_BUCKETS=false` toggles SSL/subdomain-style URLs (`are_local_buckets` in `museum.yaml`); leave it at `true` for MinIO-style setups.
- `S3_FORCE_PATH_STYLE=true` translates to `use_path_style_urls=true` (required for R2/MinIO and most LAN storage).
- The data-center identifiers (`b2-eu-cen`, `wasabi-eu-central-2-v3`, `scw-eu-fr-v3`, etc.) are **hard-coded upstream**. Keep the defaults unless you know you are targeting one of the legacy names (as listed in the Ente docs). The start script will ignore unknown values to prevent replication from breaking with empty bucket names.
- Leave the generated `museum/configurations/local.yaml` alone—if you need to append extra settings, do so via `/app/data/config/museum.override.yaml` and only add the keys you actually want to change. Copypasting the full sample `s3:` block from the docs will overwrite the generated credentials with blanks.
- If you are using Cloudflare R2 or another hosted S3 provider, configure your buckets CORS policy to allow the Ente frontends (e.g. `https://ente.due.ren`, `https://accounts.due.ren`, `https://cast.due.ren`, **and** the desktop scheme `ente://app`) so that cast/slideshow playback and the desktop client can fetch signed URLs directly from storage. Backblaze B2 also requires clearing its “native” CORS rules; see the script in `POSTINSTALL.md`. When using the Backblaze CLI remember to preserve your bucket visibility (`allPrivate` for most installs): run `b2 get-bucket <bucket>` to confirm the current type, then invoke `b2 update-bucket <bucket> <bucketType> --cors-rules "$(<cors.json)"` so you only touch the CORS block. A minimal rule that works with Entes signed URLs looks like:
```bash
cat <<'EOF' >cors.json
[
{
"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
}
]
EOF
b2 update-bucket ente-due-ren allPrivate --cors-rules "$(<cors.json)"
```
Adjust the hostnames and bucket type as needed; afterwards verify with `curl -I -H 'Origin: https://cast.example.com' '<signed-url>'` and ensure `Access-Control-Allow-Origin` is present.
2. When prompted during installation, pick hostnames for the Accounts/Auth/Cast/Albums/Family web apps (they are exposed via Cloudron `httpPorts`). Ensure matching DNS records exist; Cloudron-managed DNS creates them automatically, otherwise point CNAME/A records such as `accounts.<app-domain>` at the primary hostname.
3. To persist tweaks to Museum (for example, seeding super-admin or whitelist entries), create `/app/data/config/museum.override.yaml`. Its contents are appended to the generated `museum/configurations/local.yaml` on every start, so you only need to declare the keys you want to override.
```yaml
# /app/data/config/museum.override.yaml
internal:
super-admins:
- admin@example.com
```
4. Use the bundled Ente CLI for admin tasks via `cloudron exec --app <location> -- sudo -u cloudron ente --help`. On a fresh install run the following once (initialises the CLI config, whitelists your admin, and clears the CLI DB):
```bash
cloudron exec --app ente.cloudron.io -- bash -lc \
'cat <<EOF >/cli-data/config.yaml
endpoint:
api: https://ente.cloudron.io/api
log:
http: false
EOF
mkdir -p /cli-data/export
chown cloudron:cloudron /cli-data /cli-data/config.yaml /cli-data/export
cat <<EOF >/app/data/config/museum.override.yaml
internal:
super-admins:
- admin@example.com
EOF
rm -f /cli-data/ente-cli.db
chown cloudron:cloudron /app/data/config/museum.override.yaml'
You need to manually set up and configure:
cloudron restart --app ente.cloudron.io
- S3-compatible object storage
# add your account (respond to prompts with the OTP sent to your email)
cloudron exec --app ente.cloudron.io -- sudo -u cloudron ente account add
```
Afterwards the usual admin commands work as documented. Example:
```bash
cloudron exec --app ente.cloudron.io -- sudo -u cloudron ente admin list-users --admin-user admin@example.com
```
The main photos UI continues to live on the hostname you selected during installation.
### Object storage quick reference
The upstream documentation at [ente.io/help/self-hosting/administration/object-storage](https://ente.io/help/self-hosting/administration/object-storage) is written for bare-metal installs where you edit `museum.yaml` by hand. The Cloudron package wraps those steps so you only maintain `/app/data/config/s3.env`, but the same concepts apply:
- **Canonical bucket names.** Museums schema ships with `b2-eu-cen`, `wasabi-eu-central-2-v3`, and `scw-eu-fr-v3`. You can point those identifiers at any S3-compatible provider, but you cannot rename them—replication logic only understands the upstream keys (or their documented legacy aliases). Leave the defaults in `s3.env` and only change the credentials/endpoints under each key.
- **Three buckets for replication.** Replication only works when two “hot” buckets and one “cold” bucket are configured. Populate `S3_*`, `S3_SECONDARY_*`, and `S3_COLD_*`; once all three have endpoints/keys/secrets the package automatically writes the `replication.enabled: true` stanza.
- **Transport settings.** Set `S3_ARE_LOCAL_BUCKETS=true`/`false` and `S3_FORCE_PATH_STYLE=true` to mirror the documentations `are_local_buckets`/`use_path_style_urls` toggles when talking to MinIO, Cloudflare R2, or other providers that require path-style URLs over HTTPS.
- **CORS.** If browsers cannot upload/download because of CORS, apply the recommended JSON from the docs (or the Backblaze helper script in `POSTINSTALL.md`). Ensure `Content-MD5` is listed in `AllowedHeaders` for providers with allow-lists.
- **Do not overwrite the generated config.** Keep `/app/data/config/museum.override.yaml` minimal (only the keys you need). Dropping the example `s3:` block from the docs into that file will clear the generated credentials and replication will fail with “PutObjectInput.Bucket” errors.
## Usage
### Web Client
After installation, you can access the Ente web client at your app's URL. Create an admin account on first use.
After installation, you can access the Ente web client at your app's URL. Create the first user and promote them to an administrator using the override file or upstream admin tooling as documented by Ente.
### Mobile Apps
@@ -107,18 +157,6 @@ To update to a newer version:
cloudron update --app ente.yourdomain.com
```
## Troubleshooting
### Common Issues
1. **"Failed to fetch" errors**: Check if your browser is blocking API requests to your domain
2. **WebAssembly errors**: Ensure your browser supports and allows WebAssembly (try using Chrome or Firefox)
3. **IndexedDB errors**: Make sure your browser allows IndexedDB (not in private/incognito mode)
For issues specific to the Cloudron packaging, please open an issue in this repository.
For issues with Ente itself, please refer to the [main Ente repository](https://github.com/ente-io/ente).
## License
This Cloudron package is licensed under the same license as Ente (Apache 2.0).
This Cloudron package is licensed under the same license as Ente (Apache 2.0).
+133
View File
@@ -0,0 +1,133 @@
#!/bin/bash
# Direct Database Admin Helper for Ente Cloudron
# This script directly updates the database for admin operations
# Function to update user subscription directly in database
update_subscription() {
local user_email="$1"
local storage_gb="$2"
local valid_days="$3"
if [ -z "$user_email" ] || [ -z "$storage_gb" ] || [ -z "$valid_days" ]; then
echo "Usage: $0 update-subscription <user-email> <storage-gb> <valid-days>"
echo "Example: $0 update-subscription user@example.com 100 365"
return 1
fi
echo "Updating subscription for: $user_email"
echo "Storage: ${storage_gb}GB"
echo "Valid for: ${valid_days} days"
# Convert GB to bytes (1 GB = 1073741824 bytes)
local storage_bytes=$((storage_gb * 1073741824))
# Calculate expiry timestamp (current time + valid_days)
local current_timestamp=$(date +%s)
local expiry_timestamp=$((current_timestamp + (valid_days * 86400)))
# Convert to microseconds for the database
local expiry_microseconds="${expiry_timestamp}000000"
# Update the database directly
PGPASSWORD="$CLOUDRON_POSTGRESQL_PASSWORD" psql \
-h "$CLOUDRON_POSTGRESQL_HOST" \
-p "$CLOUDRON_POSTGRESQL_PORT" \
-U "$CLOUDRON_POSTGRESQL_USERNAME" \
-d "$CLOUDRON_POSTGRESQL_DATABASE" << EOF
-- Update user's storage and subscription
UPDATE users
SET
storage_bonus = $storage_bytes,
subscription_expiry = $expiry_microseconds
WHERE email = '$user_email';
-- Show the updated values
SELECT
email,
storage_bonus / 1073741824.0 as storage_gb,
to_timestamp(subscription_expiry / 1000000) as subscription_expires
FROM users
WHERE email = '$user_email';
EOF
if [ $? -eq 0 ]; then
echo "✓ Subscription updated successfully"
else
echo "✗ Failed to update subscription"
return 1
fi
}
# Function to get user details
get_user_details() {
local user_email="$1"
if [ -z "$user_email" ]; then
echo "Usage: $0 get-user <user-email>"
return 1
fi
PGPASSWORD="$CLOUDRON_POSTGRESQL_PASSWORD" psql \
-h "$CLOUDRON_POSTGRESQL_HOST" \
-p "$CLOUDRON_POSTGRESQL_PORT" \
-U "$CLOUDRON_POSTGRESQL_USERNAME" \
-d "$CLOUDRON_POSTGRESQL_DATABASE" << EOF
SELECT
email,
storage_bonus / 1073741824.0 as storage_gb,
storage_consumed / 1073741824.0 as used_gb,
to_timestamp(subscription_expiry / 1000000) as subscription_expires,
CASE
WHEN subscription_expiry > (EXTRACT(EPOCH FROM NOW()) * 1000000) THEN 'Active'
ELSE 'Expired'
END as status
FROM users
WHERE email = '$user_email';
EOF
}
# Function to list all users
list_users() {
PGPASSWORD="$CLOUDRON_POSTGRESQL_PASSWORD" psql \
-h "$CLOUDRON_POSTGRESQL_HOST" \
-p "$CLOUDRON_POSTGRESQL_PORT" \
-U "$CLOUDRON_POSTGRESQL_USERNAME" \
-d "$CLOUDRON_POSTGRESQL_DATABASE" << EOF
SELECT
email,
storage_bonus / 1073741824.0 as storage_gb,
storage_consumed / 1073741824.0 as used_gb,
to_timestamp(subscription_expiry / 1000000) as expires,
CASE
WHEN subscription_expiry > (EXTRACT(EPOCH FROM NOW()) * 1000000) THEN 'Active'
ELSE 'Expired'
END as status
FROM users
ORDER BY email;
EOF
}
# Main command handler
case "$1" in
"update-subscription")
update_subscription "$2" "$3" "$4"
;;
"get-user")
get_user_details "$2"
;;
"list-users")
list_users
;;
*)
echo "Ente Direct Admin Helper"
echo ""
echo "Usage:"
echo " $0 update-subscription <user-email> <storage-gb> <valid-days>"
echo " $0 get-user <user-email>"
echo " $0 list-users"
echo ""
echo "Examples:"
echo " $0 update-subscription user@example.com 100 365"
echo " $0 get-user user@example.com"
echo " $0 list-users"
;;
esac
+93
View File
@@ -0,0 +1,93 @@
#!/bin/bash
# Ente Admin Helper Script for Cloudron
# This script simplifies admin operations in the Cloudron terminal
MUSEUM_BIN="/app/museum-bin/museum"
# Check if museum binary exists
if [ ! -f "$MUSEUM_BIN" ]; then
echo "Error: Museum binary not found at $MUSEUM_BIN"
exit 1
fi
# Function to update user subscription
update_subscription() {
local user_email="$1"
local storage_gb="$2"
local valid_days="$3"
if [ -z "$user_email" ] || [ -z "$storage_gb" ] || [ -z "$valid_days" ]; then
echo "Usage: $0 update-subscription <user-email> <storage-gb> <valid-days>"
echo "Example: $0 update-subscription user@example.com 100 365"
return 1
fi
echo "Updating subscription for: $user_email"
echo "Storage: ${storage_gb}GB"
echo "Valid for: ${valid_days} days"
cd /app/data/museum
# Use environment variables for database connection
export DB_HOST="$CLOUDRON_POSTGRESQL_HOST"
export DB_PORT="$CLOUDRON_POSTGRESQL_PORT"
export DB_NAME="$CLOUDRON_POSTGRESQL_DATABASE"
export DB_USERNAME="$CLOUDRON_POSTGRESQL_USERNAME"
export DB_PASSWORD="$CLOUDRON_POSTGRESQL_PASSWORD"
# Museum admin commands need specific syntax
"$MUSEUM_BIN" admin update-subscription "$user_email" "$storage_gb" "$valid_days"
}
# Function to get user details
get_user_details() {
local user_email="$1"
if [ -z "$user_email" ]; then
echo "Usage: $0 get-user <user-email>"
return 1
fi
cd /app/data/museum
"$MUSEUM_BIN" admin get-user-details --user "$user_email"
}
# Function to list all users
list_users() {
cd /app/data/museum
# Connect to PostgreSQL and list users
PGPASSWORD="$CLOUDRON_POSTGRESQL_PASSWORD" psql \
-h "$CLOUDRON_POSTGRESQL_HOST" \
-p "$CLOUDRON_POSTGRESQL_PORT" \
-U "$CLOUDRON_POSTGRESQL_USERNAME" \
-d "$CLOUDRON_POSTGRESQL_DATABASE" \
-c "SELECT email, storage_bonus, subscription_expiry FROM users ORDER BY email;"
}
# Main command handler
case "$1" in
"update-subscription")
update_subscription "$2" "$3" "$4"
;;
"get-user")
get_user_details "$2"
;;
"list-users")
list_users
;;
*)
echo "Ente Admin Helper"
echo ""
echo "Usage:"
echo " $0 update-subscription <user-email> <storage-gb> <valid-days>"
echo " $0 get-user <user-email>"
echo " $0 list-users"
echo ""
echo "Examples:"
echo " $0 update-subscription user@example.com 100 365"
echo " $0 get-user user@example.com"
echo " $0 list-users"
;;
esac
+15 -11
View File
@@ -18,16 +18,20 @@ database:
maxIdleConns: 25
connMaxLifetime: "1h"
storage:
type: "s3"
s3:
s3:
are_local_buckets: false
use_path_style_urls: true
hot_storage:
primary: b2-eu-cen
secondary: b2-eu-cen
derived-storage: b2-eu-cen
b2-eu-cen:
endpoint: "%%S3_ENDPOINT%%"
region: "%%S3_REGION%%"
bucket: "%%S3_BUCKET%%"
accessKey: "%%S3_ACCESS_KEY%%"
secretKey: "%%S3_SECRET_KEY%%"
prefix: "%%S3_PREFIX%%"
forcePathStyle: true
key: "%%S3_ACCESS_KEY%%"
secret: "%%S3_SECRET_KEY%%"
path_prefix: "%%S3_PREFIX%%"
email:
smtp:
@@ -48,19 +52,19 @@ auth:
logging:
level: "info"
format: "text"
# Additional settings based on Museum requirements
keygen:
master: "%%MASTER_KEY%%"
payments:
enabled: false
metadata:
localPath: "/app/data/storage/metadata"
tempDirectory: "/app/data/storage/temp"
memoryCache:
enabled: true
size: 100
size: 100
+186
View File
@@ -0,0 +1,186 @@
{
"IN": [
{
"id": "50gb_monthly_v4",
"androidID": "50gb_monthly_v4",
"iosID": "50gb_monthly_v4",
"stripeID": "50gb_monthly_v4",
"storage": 53687091200,
"price": "₹0",
"period": "month"
},
{
"id": "200gb_monthly_v4",
"androidID": "200gb_monthly_v4",
"iosID": "200gb_monthly_v4",
"stripeID": "200gb_monthly_v4",
"storage": 214748364800,
"price": "₹0",
"period": "month"
},
{
"id": "1000gb_monthly_v4",
"androidID": "1000gb_monthly_v4",
"iosID": "1000gb_monthly_v4",
"stripeID": "1000gb_monthly_v4",
"storage": 1073741824000,
"price": "₹0",
"period": "month"
},
{
"id": "2000gb_monthly_v4",
"androidID": "2000gb_monthly_v4",
"iosID": "2000gb_monthly_v4",
"stripeID": "2000gb_monthly_v4",
"storage": 2147483648000,
"price": "₹0",
"period": "month"
},
{
"id": "50gb_yearly_v4",
"androidID": "50gb_yearly_v4",
"iosID": "50gb_yearly_v4",
"stripeID": "50gb_yearly_v4",
"storage": 53687091200,
"price": "₹0",
"period": "year"
},
{
"id": "200gb_yearly_v4",
"androidID": "200gb_yearly_v4",
"iosID": "200gb_yearly_v4",
"stripeID": "200gb_yearly_v4",
"storage": 214748364800,
"price": "₹0",
"period": "year"
},
{
"id": "1000gb_yearly_v4",
"androidID": "1000gb_yearly_v4",
"iosID": "1000gb_yearly_v4",
"stripeID": "1000gb_yearly_v4",
"storage": 1073741824000,
"price": "₹0",
"period": "year"
},
{
"id": "2000gb_yearly_v4",
"androidID": "2000gb_yearly_v4",
"iosID": "2000gb_yearly_v4",
"stripeID": "2000gb_yearly_v4",
"storage": 2147483648000,
"price": "₹0",
"period": "year"
},
{
"id": "family",
"androidID": "family",
"iosID": "family",
"stripeID": "family",
"storage": 2147483648000,
"price": "₹0",
"period": "year"
},
{
"id": "free",
"androidID": "free",
"iosID": "free",
"stripeID": "free",
"storage": 10737418240,
"price": "₹0",
"period": "year"
}
],
"US": [
{
"id": "50gb_monthly_v4",
"androidID": "50gb_monthly_v4",
"iosID": "50gb_monthly_v4",
"stripeID": "50gb_monthly_v4",
"storage": 53687091200,
"price": "$0",
"period": "month"
},
{
"id": "200gb_monthly_v4",
"androidID": "200gb_monthly_v4",
"iosID": "200gb_monthly_v4",
"stripeID": "200gb_monthly_v4",
"storage": 214748364800,
"price": "$0",
"period": "month"
},
{
"id": "1000gb_monthly_v4",
"androidID": "1000gb_monthly_v4",
"iosID": "1000gb_monthly_v4",
"stripeID": "1000gb_monthly_v4",
"storage": 1073741824000,
"price": "$0",
"period": "month"
},
{
"id": "2000gb_monthly_v4",
"androidID": "2000gb_monthly_v4",
"iosID": "2000gb_monthly_v4",
"stripeID": "2000gb_monthly_v4",
"storage": 2147483648000,
"price": "$0",
"period": "month"
},
{
"id": "50gb_yearly_v4",
"androidID": "50gb_yearly_v4",
"iosID": "50gb_yearly_v4",
"stripeID": "50gb_yearly_v4",
"storage": 53687091200,
"price": "$0",
"period": "year"
},
{
"id": "200gb_yearly_v4",
"androidID": "200gb_yearly_v4",
"iosID": "200gb_yearly_v4",
"stripeID": "200gb_yearly_v4",
"storage": 214748364800,
"price": "$0",
"period": "year"
},
{
"id": "1000gb_yearly_v4",
"androidID": "1000gb_yearly_v4",
"iosID": "1000gb_yearly_v4",
"stripeID": "1000gb_yearly_v4",
"storage": 1073741824000,
"price": "$0",
"period": "year"
},
{
"id": "2000gb_yearly_v4",
"androidID": "2000gb_yearly_v4",
"iosID": "2000gb_yearly_v4",
"stripeID": "2000gb_yearly_v4",
"storage": 2147483648000,
"price": "$0",
"period": "year"
},
{
"id": "family",
"androidID": "family",
"iosID": "family",
"stripeID": "family",
"storage": 2147483648000,
"price": "$0",
"period": "year"
},
{
"id": "free",
"androidID": "free",
"iosID": "free",
"stripeID": "free",
"storage": 10737418240,
"price": "$0",
"period": "year"
}
]
}
+186
View File
@@ -0,0 +1,186 @@
{
"US": [
{
"id": "50gb_monthly_v4",
"androidID": "50gb_monthly_v4",
"iosID": "50gb_monthly_v4",
"stripeID": "50gb_monthly_v4",
"storage": 53687091200,
"price": "$0",
"period": "month"
},
{
"id": "200gb_monthly_v4",
"androidID": "200gb_monthly_v4",
"iosID": "200gb_monthly_v4",
"stripeID": "200gb_monthly_v4",
"storage": 214748364800,
"price": "$0",
"period": "month"
},
{
"id": "1000gb_monthly_v4",
"androidID": "1000gb_monthly_v4",
"iosID": "1000gb_monthly_v4",
"stripeID": "1000gb_monthly_v4",
"storage": 1073741824000,
"price": "$0",
"period": "month"
},
{
"id": "2000gb_monthly_v4",
"androidID": "2000gb_monthly_v4",
"iosID": "2000gb_monthly_v4",
"stripeID": "2000gb_monthly_v4",
"storage": 2147483648000,
"price": "$0",
"period": "month"
},
{
"id": "50gb_yearly_v4",
"androidID": "50gb_yearly_v4",
"iosID": "50gb_yearly_v4",
"stripeID": "50gb_yearly_v4",
"storage": 53687091200,
"price": "$0",
"period": "year"
},
{
"id": "200gb_yearly_v4",
"androidID": "200gb_yearly_v4",
"iosID": "200gb_yearly_v4",
"stripeID": "200gb_yearly_v4",
"storage": 214748364800,
"price": "$0",
"period": "year"
},
{
"id": "1000gb_yearly_v4",
"androidID": "1000gb_yearly_v4",
"iosID": "1000gb_yearly_v4",
"stripeID": "1000gb_yearly_v4",
"storage": 1073741824000,
"price": "$0",
"period": "year"
},
{
"id": "2000gb_yearly_v4",
"androidID": "2000gb_yearly_v4",
"iosID": "2000gb_yearly_v4",
"stripeID": "2000gb_yearly_v4",
"storage": 2147483648000,
"price": "$0",
"period": "year"
},
{
"id": "family",
"androidID": "family",
"iosID": "family",
"stripeID": "family",
"storage": 2147483648000,
"price": "$0",
"period": "year"
},
{
"id": "free",
"androidID": "free",
"iosID": "free",
"stripeID": "free",
"storage": 10737418240,
"price": "$0",
"period": "year"
}
],
"EU": [
{
"id": "50gb_monthly_v4",
"androidID": "50gb_monthly_v4",
"iosID": "50gb_monthly_v4",
"stripeID": "50gb_monthly_v4",
"storage": 53687091200,
"price": "€0",
"period": "month"
},
{
"id": "200gb_monthly_v4",
"androidID": "200gb_monthly_v4",
"iosID": "200gb_monthly_v4",
"stripeID": "200gb_monthly_v4",
"storage": 214748364800,
"price": "€0",
"period": "month"
},
{
"id": "1000gb_monthly_v4",
"androidID": "1000gb_monthly_v4",
"iosID": "1000gb_monthly_v4",
"stripeID": "1000gb_monthly_v4",
"storage": 1073741824000,
"price": "€0",
"period": "month"
},
{
"id": "2000gb_monthly_v4",
"androidID": "2000gb_monthly_v4",
"iosID": "2000gb_monthly_v4",
"stripeID": "2000gb_monthly_v4",
"storage": 2147483648000,
"price": "€0",
"period": "month"
},
{
"id": "50gb_yearly_v4",
"androidID": "50gb_yearly_v4",
"iosID": "50gb_yearly_v4",
"stripeID": "50gb_yearly_v4",
"storage": 53687091200,
"price": "€0",
"period": "year"
},
{
"id": "200gb_yearly_v4",
"androidID": "200gb_yearly_v4",
"iosID": "200gb_yearly_v4",
"stripeID": "200gb_yearly_v4",
"storage": 214748364800,
"price": "€0",
"period": "year"
},
{
"id": "1000gb_yearly_v4",
"androidID": "1000gb_yearly_v4",
"iosID": "1000gb_yearly_v4",
"stripeID": "1000gb_yearly_v4",
"storage": 1073741824000,
"price": "€0",
"period": "year"
},
{
"id": "2000gb_yearly_v4",
"androidID": "2000gb_yearly_v4",
"iosID": "2000gb_yearly_v4",
"stripeID": "2000gb_yearly_v4",
"storage": 2147483648000,
"price": "€0",
"period": "year"
},
{
"id": "family",
"androidID": "family",
"iosID": "family",
"stripeID": "family",
"storage": 2147483648000,
"price": "€0",
"period": "year"
},
{
"id": "free",
"androidID": "free",
"iosID": "free",
"stripeID": "free",
"storage": 10737418240,
"price": "€0",
"period": "year"
}
]
}
+35
View File
@@ -0,0 +1,35 @@
#!/bin/bash
echo "==> Debugging Caddy MIME type headers"
echo "==> Testing various file types..."
BASE_URL="${1:-https://ente.due.ren}"
echo
echo "Testing HTML files:"
curl -I "$BASE_URL/" 2>/dev/null | grep -i content-type || echo "No Content-Type header found"
curl -I "$BASE_URL/index.html" 2>/dev/null | grep -i content-type || echo "No Content-Type header found"
echo
echo "Testing JavaScript files:"
curl -I "$BASE_URL/config.js" 2>/dev/null | grep -i content-type || echo "No Content-Type header found"
echo
echo "Testing CSS files (if any):"
curl -I "$BASE_URL/styles.css" 2>/dev/null | grep -i content-type || echo "File not found or no Content-Type header"
echo
echo "Testing JSON files (if any):"
curl -I "$BASE_URL/manifest.json" 2>/dev/null | grep -i content-type || echo "File not found or no Content-Type header"
echo
echo "==> Full response headers for main page:"
curl -I "$BASE_URL/" 2>/dev/null || echo "Failed to connect to $BASE_URL"
echo
echo "==> To test from inside a container:"
echo "docker exec -it <container-name> curl -I http://localhost:3080/"
echo
echo "==> To view Caddy logs:"
echo "docker exec -it <container-name> tail -f /app/data/logs/caddy.log"
+38
View File
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<title>Debug Ente Auth Network Calls</title>
</head>
<body>
<h1>Debug Ente Auth Network Calls</h1>
<div id="output"></div>
<script>
// Override fetch to log all network requests
const originalFetch = window.fetch;
window.fetch = function(...args) {
console.log('FETCH REQUEST:', args[0], args[1]);
const output = document.getElementById('output');
output.innerHTML += '<p>FETCH: ' + args[0] + '</p>';
return originalFetch.apply(this, args)
.then(response => {
console.log('FETCH RESPONSE:', response.status, response.url);
output.innerHTML += '<p>RESPONSE: ' + response.status + ' ' + response.url + '</p>';
return response;
})
.catch(error => {
console.log('FETCH ERROR:', error);
output.innerHTML += '<p>ERROR: ' + error.message + '</p>';
throw error;
});
};
// Load the Ente Auth app in an iframe to see what happens
const iframe = document.createElement('iframe');
iframe.src = 'https://ente.due.ren/auth/';
iframe.style.width = '100%';
iframe.style.height = '400px';
document.body.appendChild(iframe);
</script>
</body>
</html>
Executable
+32
View File
@@ -0,0 +1,32 @@
#!/bin/bash
# Add this debugging section to your start.sh after line 350
# Start Caddy with more verbose logging
echo "==> Starting Caddy web server with debug logging"
echo "==> Validating Caddyfile first..."
caddy validate --config /app/data/Caddyfile --adapter caddyfile || {
echo "==> ERROR: Caddyfile validation failed!"
cat /app/data/Caddyfile
exit 1
}
echo "==> Starting Caddy..."
# Run Caddy in foreground first to see errors
timeout 10 caddy run --config /app/data/Caddyfile --adapter caddyfile 2>&1 | tee /app/data/logs/caddy-debug.log || {
echo "==> ERROR: Caddy failed to start"
echo "==> Last 50 lines of Caddy debug log:"
tail -50 /app/data/logs/caddy-debug.log
}
# Check if port is actually listening
echo "==> Checking if port 3080 is listening..."
netstat -tlnp | grep 3080 || lsof -i :3080 || {
echo "==> ERROR: Nothing listening on port 3080"
}
# Test the health endpoint
echo "==> Testing health endpoint..."
curl -v http://localhost:3080/health || {
echo "==> ERROR: Health check failed"
}
+64
View File
@@ -0,0 +1,64 @@
# Ente CLI Configuration for Custom Server
The Ente CLI expects configuration in `~/.ente/config.yaml`. Here's how to set it up:
## Method 1: Direct Configuration
1. Create the config file:
```bash
mkdir -p ~/.ente
cat > ~/.ente/config.yaml << EOF
api:
url: https://ente.due.ren
EOF
```
2. Add your account interactively:
```bash
ente account add
# It will ask for:
# - Export directory: /tmp/ente-export (or any directory)
# - Email: your-admin@email.com
# - Password: your-password
```
## Method 2: Using the Admin Commands Directly
If the interactive setup is problematic, you can use the admin commands with explicit parameters:
```bash
# Set the API endpoint
export ENTE_API_URL="https://ente.due.ren"
# Or pass it directly in the command
ente admin update-subscription \
--api-url https://ente.due.ren \
--admin-user admin@due.ren \
--user user@example.com \
--storage 1000 \
--valid-for 365
```
## Method 3: Direct Database Update (Fallback)
Since the CLI setup seems problematic, you can update the database directly in the Cloudron terminal:
```bash
# In Cloudron terminal
PGPASSWORD="$CLOUDRON_POSTGRESQL_PASSWORD" psql \
-h "$CLOUDRON_POSTGRESQL_HOST" \
-U "$CLOUDRON_POSTGRESQL_USERNAME" \
-d "$CLOUDRON_POSTGRESQL_DATABASE" << EOF
-- Update user to 1TB for 1 year
UPDATE users
SET storage_bonus = 1073741824000, -- 1000 GB in bytes
subscription_expiry = EXTRACT(EPOCH FROM NOW() + INTERVAL '365 days') * 1000000
WHERE email = 'andreas@due.ren';
-- Show the result
SELECT email,
storage_bonus / 1073741824.0 as storage_gb,
to_timestamp(subscription_expiry / 1000000) as expires
FROM users WHERE email = 'andreas@due.ren';
EOF
```
+31
View File
@@ -0,0 +1,31 @@
diff --git a/server/pkg/controller/family/admin.go b/server/pkg/controller/family/admin.go
index 1b58f6b8..8fd74a99 100644
--- a/server/pkg/controller/family/admin.go
+++ b/server/pkg/controller/family/admin.go
@@
- "github.com/ente-io/museum/pkg/utils/auth"
- "github.com/ente-io/museum/pkg/utils/billing"
+ "github.com/ente-io/museum/pkg/utils/auth"
+ "github.com/ente-io/museum/pkg/utils/billing"
emailUtil "github.com/ente-io/museum/pkg/utils/email"
"github.com/ente-io/stacktrace"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"github.com/sirupsen/logrus"
+ "github.com/spf13/viper"
)
@@
- FamilyPlainHost = "https://family.ente.io"
+ defaultFamilyHost = "https://family.ente.io"
)
+
+func familyInviteHost() string {
+ host := viper.GetString("apps.family")
+ if host != "" {
+ return host
+ }
+ return defaultFamilyHost
+}
@@
- templateData["FamilyInviteLink"] = fmt.Sprintf("%s?inviteToken=%s", FamilyPlainHost, *inviteToken)
+ templateData["FamilyInviteLink"] = fmt.Sprintf("%s?inviteToken=%s", familyInviteHost(), *inviteToken)
+20
View File
@@ -0,0 +1,20 @@
#!/bin/bash
# Setup Ente CLI for custom server
echo "Setting up Ente CLI for custom server..."
# Create config directory
mkdir -p ~/.ente
# Create the CLI config with custom endpoint
cat > ~/.ente/config.yaml << EOF
host: https://ente.due.ren
EOF
echo "Configuration created at ~/.ente/config.yaml"
echo ""
echo "Now you can add your account:"
echo " ente account add"
echo ""
echo "Then use admin commands:"
echo " ente admin update-subscription --admin-user admin@due.ren --user user@example.com --storage 1000 --valid-for 365"
Executable
+150
View File
@@ -0,0 +1,150 @@
#!/bin/bash
# Better signal handling - forward signals to child processes
trap 'kill -TERM $SERVER_PID; kill -TERM $CADDY_PID; exit' TERM INT
set -eu
echo "==> Starting Ente Cloudron app (DEBUG MODE)..."
# Create necessary directories
mkdir -p /app/data/config /app/data/logs /app/data/caddy
# Check if web directories exist
echo "==> Checking web app directories:"
for app in photos accounts auth cast; do
if [ -d "/app/web/$app" ]; then
echo "==> Found: /app/web/$app"
ls -la "/app/web/$app" | head -5
else
echo "==> WARNING: Missing /app/web/$app - creating placeholder"
mkdir -p "/app/web/$app"
echo "<html><body><h1>$app app placeholder</h1></body></html>" > "/app/web/$app/index.html"
fi
done
# Create a simple test Caddyfile first
echo "==> Creating simple test Caddyfile"
cat > /app/data/Caddyfile <<'EOT'
{
admin off
auto_https off
}
:3080 {
log {
output stdout
format console
level DEBUG
}
# Health check endpoint
handle /health {
header Content-Type "application/json"
respond "{\"status\": \"OK\", \"timestamp\": \"{{now | date \"2006-01-02T15:04:05Z07:00\"}}\"}" 200
}
# Test endpoint
handle /test {
respond "Caddy is working on port 3080!" 200
}
# API proxy to Museum server
handle /api/* {
uri strip_prefix /api
reverse_proxy localhost:8080 {
transport http {
read_timeout 60s
write_timeout 60s
}
# Add error handling
handle_errors {
respond "{\"error\": \"Museum server not available\"}" 503
}
}
}
# Serve web apps with fallback
handle {
root * /app/web/photos
try_files {path} {path}/ /index.html
file_server {
browse
}
}
}
EOT
# Start a simple Museum mock server for testing
echo "==> Starting mock Museum server on port 8080"
cat > /tmp/museum-mock.js <<'EOF'
const http = require('http');
const server = http.createServer((req, res) => {
console.log(`Museum mock: ${req.method} ${req.url}`);
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ status: 'ok', path: req.url, timestamp: new Date().toISOString() }));
});
server.listen(8080, '127.0.0.1', () => {
console.log('Museum mock server running on http://127.0.0.1:8080');
});
EOF
node /tmp/museum-mock.js > /app/data/logs/museum-mock.log 2>&1 &
SERVER_PID=$!
echo "==> Mock Museum server started (PID: $SERVER_PID)"
# Wait for Museum mock to be ready
sleep 2
# Test Museum mock
echo "==> Testing Museum mock server..."
curl -s http://localhost:8080/test || echo "WARNING: Museum mock not responding"
# Validate Caddyfile
echo "==> Validating Caddyfile..."
caddy validate --config /app/data/Caddyfile --adapter caddyfile || {
echo "==> ERROR: Caddyfile validation failed!"
exit 1
}
# Start Caddy with explicit environment
echo "==> Starting Caddy web server..."
CADDY_FORMAT=console caddy run --config /app/data/Caddyfile --adapter caddyfile 2>&1 | tee /app/data/logs/caddy-combined.log &
CADDY_PID=$!
echo "==> Caddy started (PID: $CADDY_PID)"
# Wait for Caddy to start
echo "==> Waiting for Caddy to start..."
for i in {1..30}; do
if curl -s http://localhost:3080/health > /dev/null; then
echo "==> Caddy is responding!"
break
fi
echo -n "."
sleep 1
done
echo
# Check process status
echo "==> Process status:"
ps aux | grep -E "(caddy|node)" | grep -v grep || echo "No processes found"
# Check port status
echo "==> Port status:"
netstat -tlnp 2>/dev/null | grep -E "(3080|8080)" || lsof -i :3080 -i :8080 2>/dev/null || echo "Cannot check port status"
# Test endpoints
echo "==> Testing endpoints:"
echo "Health check:"
curl -s http://localhost:3080/health | jq . || echo "Failed"
echo -e "\nTest endpoint:"
curl -s http://localhost:3080/test || echo "Failed"
echo -e "\nAPI proxy:"
curl -s http://localhost:3080/api/status | jq . || echo "Failed"
echo "==> Startup complete. Services:"
echo " - Caddy PID: $CADDY_PID"
echo " - Museum Mock PID: $SERVER_PID"
echo "==> Logs: /app/data/logs/"
# Keep running
wait $SERVER_PID $CADDY_PID
Regular → Executable
+1383 -717
View File
File diff suppressed because it is too large Load Diff
+57
View File
@@ -0,0 +1,57 @@
#!/bin/bash
# Script to update Ente user storage using the Ente CLI
# Run this from your local machine (not inside Cloudron)
# Check if ente CLI is installed
if ! command -v ente &> /dev/null; then
echo "Ente CLI is not installed. Please install it first:"
echo ""
echo "For macOS:"
echo " brew tap ente-io/ente"
echo " brew install ente-cli"
echo ""
echo "For other systems, download from:"
echo " https://github.com/ente-io/ente/releases"
exit 1
fi
# Your Ente instance
ENTE_ENDPOINT="https://ente.due.ren"
# Function to update subscription
update_subscription() {
local admin_email="$1"
local user_email="$2"
local storage_gb="$3"
local valid_days="$4"
echo "Updating subscription for: $user_email"
echo "Storage: ${storage_gb}GB"
echo "Valid for: ${valid_days} days"
echo "Using admin account: $admin_email"
echo ""
# Run the ente CLI command
ente admin update-subscription \
--host "$ENTE_ENDPOINT" \
--admin-user "$admin_email" \
--user "$user_email" \
--storage "$storage_gb" \
--valid-for "$valid_days"
}
# Check arguments
if [ $# -lt 4 ]; then
echo "Usage: $0 <admin-email> <user-email> <storage-gb> <valid-days>"
echo ""
echo "Example:"
echo " $0 admin@due.ren andreas@due.ren 1000 365"
echo ""
echo "Make sure you're logged in to the Ente CLI first:"
echo " ente account add"
echo " API endpoint: $ENTE_ENDPOINT"
exit 1
fi
# Run the update
update_subscription "$1" "$2" "$3" "$4"