9 Commits

Author SHA1 Message Date
Andreas Dueren
aba8af9bb4 Force rebuild: Update asset routing with version bump 2025-08-01 14:02:07 -06:00
Andreas Dueren
7fc40ce970 Bump version to 0.1.81 for asset routing fix 2025-08-01 13:56:09 -06:00
Andreas Dueren
a0af6ec84c 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.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-01 13:55:53 -06:00
Andreas Dueren
f9171c6ca4 Resolve merge conflicts with updated version 0.1.79 2025-08-01 13:46:59 -06:00
Andreas Dueren
8fbf29fc45 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.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-01 13:46:17 -06:00
Your Name
e95ad5c25f 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
Your Name
d964d7d264 Remove large ente-source directory to fix build uploads
🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-25 19:47:47 -06:00
Your Name
06e0f5075e 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.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-25 19:27:11 -06:00
Your Name
c7b9ab18bb 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
5 changed files with 306 additions and 146 deletions

158
CLAUDE.md Normal file
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

View File

@@ -7,7 +7,7 @@
"contactEmail": "contact@ente.io",
"tagline": "Open Source End-to-End Encrypted Photos & Authentication",
"upstreamVersion": "1.0.0",
"version": "0.1.64",
"version": "0.1.82",
"healthCheckPath": "/ping",
"httpPort": 3080,
"memoryLimit": 1073741824,

View File

@@ -27,11 +27,9 @@ RUN apt-get update && apt-get install -y git && \
# Will help default to yarn version 1.22.22
RUN corepack enable
# Set environment variables for web app build
# Set the API endpoint to use current origin - this will work at runtime
# Set environment variables for web app build - use relative endpoint
ENV NEXT_PUBLIC_ENTE_ENDPOINT="/api"
# Use relative path so it works with any domain
RUN echo "Building with NEXT_PUBLIC_ENTE_ENDPOINT=/api, will work with any domain via Caddy proxy"
RUN echo "Building with relative NEXT_PUBLIC_ENTE_ENDPOINT=/api for self-hosted deployment"
# Debugging the repository structure
RUN find . -type d -maxdepth 3 | sort

38
debug-network.html Normal file
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>

244
start.sh
View File

@@ -104,15 +104,6 @@ port: 8080
host: 0.0.0.0
log_level: info
# Key used for encrypting customer data (REQUIRED)
key:
encryption: yvmG/RnzKrbCb9L3mgsmoxXr9H7i2Z4qlbT0mL3ln4w=
hash: KXYiG07wC7GIgvCSdg+WmyWdXDAn6XKYJtp/wkEU7x573+byBRAYtpTP0wwvi8i/4l37uicX1dVTUzwH3sLZyw==
# JWT secrets (REQUIRED)
jwt:
secret: i2DecQmfGreG6q1vBj5tCokhlN41gcfS2cjOs9Po-u8=
# Database configuration
db:
host: ${CLOUDRON_POSTGRESQL_HOST}
@@ -129,17 +120,14 @@ cors:
# S3 storage configuration
s3:
# For Wasabi, we need path style URLs
are_local_buckets: false
use_path_style_urls: true
# Primary bucket configuration (named bucket structure required by Museum)
b2-eu-cen:
endpoint: "${S3_ENDPOINT}"
region: "${S3_REGION}"
key: "${S3_ACCESS_KEY}"
secret: "${S3_SECRET_KEY}"
access_key: "${S3_ACCESS_KEY}"
secret_key: "${S3_SECRET_KEY}"
bucket: "${S3_BUCKET}"
# For Wasabi, we need path style URLs
use_path_style_urls: true
are_local_buckets: false
# Email settings
email:
@@ -148,13 +136,19 @@ email:
port: ${CLOUDRON_MAIL_SMTP_PORT:-25}
username: "${CLOUDRON_MAIL_SMTP_USERNAME:-}"
password: "${CLOUDRON_MAIL_SMTP_PASSWORD:-}"
from: "${CLOUDRON_MAIL_FROM:-no-reply@${CLOUDRON_APP_FQDN:-localhost}}"
from: "${CLOUDRON_MAIL_FROM:-no-reply@${CLOUDRON_APP_DOMAIN:-localhost}}"
# WebAuthn configuration for passkey support
webauthn:
rpid: "${CLOUDRON_APP_FQDN:-localhost}"
rpid: "${CLOUDRON_APP_DOMAIN:-localhost}"
rporigins:
- "https://${CLOUDRON_APP_FQDN:-localhost}"
- "https://${CLOUDRON_APP_DOMAIN:-localhost}"
# Additional Museum server configuration
http:
allowed_hosts:
- "${CLOUDRON_APP_DOMAIN:-localhost}"
base_url: "https://${CLOUDRON_APP_DOMAIN:-localhost}"
EOF
chmod 600 "$MUSEUM_CONFIG"
log "INFO" "Created Museum configuration at ${MUSEUM_CONFIG}"
@@ -224,17 +218,6 @@ else
log "INFO" "Web templates already exist or source not available"
fi
# Copy mail templates to Museum working directory (required for email functionality)
MUSEUM_MAIL_TEMPLATES_DIR="/app/data/ente/server/mail-templates"
REPO_MAIL_TEMPLATES_DIR="/app/data/ente/repository/server/mail-templates"
if [ ! -d "$MUSEUM_MAIL_TEMPLATES_DIR" ] && [ -d "$REPO_MAIL_TEMPLATES_DIR" ]; then
log "INFO" "Copying mail templates"
cp -r "$REPO_MAIL_TEMPLATES_DIR" "$MUSEUM_MAIL_TEMPLATES_DIR"
log "INFO" "Copied mail templates to $MUSEUM_MAIL_TEMPLATES_DIR"
else
log "INFO" "Mail templates already exist or source not available"
fi
# Check if Museum binary exists and is valid
log "INFO" "Checking for Museum binary at: $MUSEUM_BIN"
if [ -f "$MUSEUM_BIN" ]; then
@@ -264,9 +247,7 @@ fi
# ===============================================
# Web Application Setup
# ===============================================
log "INFO" "Web applications are pre-built and available in /app/web/"
# Web apps are pre-built with relative API paths (/api) that work with any domain
log "INFO" "Web applications are pre-built with relative API endpoint /api"
# ===============================================
# Node.js Placeholder Server
@@ -396,7 +377,7 @@ const apiHandlers = {
token: 'placeholder-jwt-token-' + Date.now(),
user: {
id: 1,
email: 'placeholder@example.com',
email: 'placeholder@' + (process.env.CLOUDRON_APP_DOMAIN || 'localhost'),
name: 'Placeholder User'
}
}));
@@ -425,7 +406,7 @@ const apiHandlers = {
token: 'placeholder-jwt-token-' + Date.now(),
user: {
id: 1,
email: 'placeholder@example.com',
email: 'placeholder@' + (process.env.CLOUDRON_APP_DOMAIN || 'localhost'),
name: 'New User'
}
}));
@@ -638,11 +619,10 @@ cat > "$CADDY_CONFIG" << EOF
# Enable compression
encode gzip
# Root redirect - must be first
redir / /photos/ 301
# CORS preflight handling
@options method OPTIONS
@options {
method OPTIONS
}
handle @options {
header {
Access-Control-Allow-Origin "*"
@@ -653,9 +633,14 @@ cat > "$CADDY_CONFIG" << EOF
respond 204
}
# API endpoints - STRIP /api prefix and proxy to Museum server
# API endpoints with CORS - strip /api prefix before forwarding
handle_path /api/* {
reverse_proxy localhost:8080
reverse_proxy localhost:8080 {
header_up Host {http.request.host}
header_up X-Real-IP {http.request.remote}
header_up X-Forwarded-For {http.request.remote}
header_up X-Forwarded-Proto {http.request.scheme}
}
header {
Access-Control-Allow-Origin "*"
Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
@@ -664,63 +649,102 @@ cat > "$CADDY_CONFIG" << EOF
}
}
# API endpoints for auth app
handle_path /auth/api/* {
# Public albums endpoint
handle /public/* {
reverse_proxy localhost:8080
header {
Access-Control-Allow-Origin "*"
Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
Access-Control-Allow-Headers "*"
Access-Control-Allow-Credentials "true"
}
}
# API endpoints for cast app
handle_path /cast/api/* {
# Health check endpoints
handle /health {
reverse_proxy localhost:8080
header {
Access-Control-Allow-Origin "*"
Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
Access-Control-Allow-Headers "*"
Access-Control-Allow-Credentials "true"
}
}
# API endpoints for accounts app
handle_path /accounts/api/* {
reverse_proxy localhost:8080
header {
Access-Control-Allow-Origin "*"
Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
Access-Control-Allow-Headers "*"
Access-Control-Allow-Credentials "true"
}
}
# Health check endpoint (direct, no /api prefix)
handle /ping {
reverse_proxy localhost:8080
}
# Static files for Next.js assets from all apps
# Next.js assets for cast app - Fixed routing v2
handle_path /cast/_next/* {
root * /app/web/cast
file_server
header {
Cache-Control "public, max-age=31536000"
Access-Control-Allow-Origin "*"
}
}
# Next.js assets for accounts app
handle_path /accounts/_next/* {
root * /app/web/accounts
file_server
header {
Cache-Control "public, max-age=31536000"
Access-Control-Allow-Origin "*"
}
}
# Next.js assets for auth app
handle_path /auth/_next/* {
root * /app/web/auth
file_server
header {
Cache-Control "public, max-age=31536000"
Access-Control-Allow-Origin "*"
}
}
# Next.js assets for photos app
handle_path /photos/_next/* {
root * /app/web/photos
file_server
header {
Cache-Control "public, max-age=31536000"
Access-Control-Allow-Origin "*"
}
}
# Generic _next assets (fallback to photos)
handle /_next/* {
root * /app/web/photos
file_server
header {
Cache-Control "public, max-age=31536000"
Access-Control-Allow-Origin "*"
}
}
# Static images and assets (served from photos app by default)
handle /images/* {
root * /app/web/photos
# Images for cast app
handle_path /cast/images/* {
root * /app/web/cast
file_server
header {
Cache-Control "public, max-age=86400"
}
}
handle /favicon.ico {
# Images for accounts app
handle_path /accounts/images/* {
root * /app/web/accounts
file_server
header {
Cache-Control "public, max-age=86400"
}
}
# Images for auth app
handle_path /auth/images/* {
root * /app/web/auth
file_server
header {
Cache-Control "public, max-age=86400"
}
}
# Images for photos app
handle_path /photos/images/* {
root * /app/web/photos
file_server
header {
@@ -756,9 +780,8 @@ cat > "$CADDY_CONFIG" << EOF
file_server
}
# Root redirect - specifically match root path only
@root path /
handle @root {
# Root redirect
handle / {
redir /photos/ permanent
}
}
@@ -806,34 +829,19 @@ cat > /app/data/SETUP-INSTRUCTIONS.md << EOF
2. **Museum Server**: The server configuration is at \`/app/data/ente/server/museum.yaml\` if you need to customize settings.
## API Endpoint
## Troubleshooting
The Ente API is available at: **https://${CLOUDRON_APP_FQDN}/api**
This endpoint can be used to:
- Configure Ente CLI tools
- Integrate with third-party applications
- Access the Museum server API directly
For admin operations, use the Ente CLI with:
\`\`\`bash
ente admin --api-url https://${CLOUDRON_APP_FQDN}/api
\`\`\`
- **Logs**: Check the logs at \`/app/data/logs/\` for any issues.
- **Restart**: If you change configuration, restart the app to apply changes.
## Web Applications
The following web applications are available:
- **Photos**: https://${CLOUDRON_APP_FQDN}/photos/ - Main photo storage and management
- **Auth**: https://${CLOUDRON_APP_FQDN}/auth/ - 2FA authenticator app
- **Accounts**: https://${CLOUDRON_APP_FQDN}/accounts/ - Account management
- **Cast**: https://${CLOUDRON_APP_FQDN}/cast/ - Photo casting to devices
## Troubleshooting
- **Logs**: Check the logs at \`/app/data/logs/\` for any issues.
- **Restart**: If you change configuration, restart the app to apply changes.
- **API Issues**: All apps use the API endpoint at \`/api\`. If apps show loading spinners, check API connectivity.
- Photos: https://${CLOUDRON_APP_DOMAIN}/photos/
- Accounts: https://${CLOUDRON_APP_DOMAIN}/accounts/
- Auth: https://${CLOUDRON_APP_DOMAIN}/auth/
- Cast: https://${CLOUDRON_APP_DOMAIN}/cast/
## Support
@@ -857,48 +865,6 @@ else
log "ERROR" "Caddy server is not running!"
fi
# ===============================================
# OTP Email Monitor Setup
# ===============================================
log "INFO" "Setting up OTP Email Monitor"
# Install Node.js dependencies if not already installed
if [ ! -d "/app/data/node_modules" ]; then
log "INFO" "Installing Node.js dependencies for OTP Email Monitor"
cd /app/data
cp /app/pkg/package.json .
npm install --production --no-save
log "INFO" "Node.js dependencies installed successfully"
else
log "INFO" "Node.js dependencies already installed"
fi
# Start OTP Email Monitor
log "INFO" "Starting OTP Email Monitor"
cd /app/data
NODE_PATH="/app/data/node_modules" node /app/pkg/otp-email-monitor.js > /app/data/logs/otp-email.log 2>&1 &
OTP_MONITOR_PID=$!
log "INFO" "OTP Email Monitor started with PID: $OTP_MONITOR_PID"
# Wait a moment to check if OTP monitor starts successfully
sleep 2
if ps -p $OTP_MONITOR_PID > /dev/null; then
log "INFO" "OTP Email Monitor is running successfully"
else
log "WARN" "OTP Email Monitor may have failed to start"
log "WARN" "Last 10 lines of OTP email log:"
tail -n 10 /app/data/logs/otp-email.log | while read -r line; do
log "WARN" " $line"
done
fi
# Copy admin helper script for easy access
if [ -f "/app/pkg/admin-helper.sh" ]; then
cp /app/pkg/admin-helper.sh /app/data/
chmod +x /app/data/admin-helper.sh
log "INFO" "Admin helper script available at /app/data/admin-helper.sh"
fi
log "INFO" "Ente Cloudron app startup complete"
# Keep the script running to prevent container exit