Add robust configuration injection and debugging tools
This commit is contained in:
parent
38f08c135e
commit
12b486ace3
465
start.sh
465
start.sh
@ -206,7 +206,7 @@ if ! command -v caddy &> /dev/null; then
|
||||
fi
|
||||
|
||||
# Set up the API endpoint for the web apps
|
||||
API_ENDPOINT=${CLOUDRON_APP_ORIGIN}/api
|
||||
API_ENDPOINT="${CLOUDRON_APP_ORIGIN}/api"
|
||||
echo "==> Setting API endpoint to $API_ENDPOINT"
|
||||
|
||||
# Set environment variables for the web apps
|
||||
@ -216,100 +216,249 @@ export REACT_APP_ENTE_ENDPOINT=$API_ENDPOINT
|
||||
export VUE_APP_ENTE_ENDPOINT=$API_ENDPOINT
|
||||
echo "==> Set environment variables for web apps"
|
||||
|
||||
# Create a very simple Caddy configuration
|
||||
mkdir -p /app/data/caddy
|
||||
# Create directory for direct modifications
|
||||
mkdir -p /app/data/scripts
|
||||
|
||||
# Create a script that will directly define the ENTE_CONFIG global in window
|
||||
cat > /app/data/scripts/ente-config.js <<EOT
|
||||
// Direct configuration script - should be loaded before any app code
|
||||
window.ENTE_CONFIG = {
|
||||
API_URL: "${API_ENDPOINT}"
|
||||
};
|
||||
console.log("Ente config loaded, API_URL =", window.ENTE_CONFIG.API_URL);
|
||||
EOT
|
||||
|
||||
# Set up Caddy server
|
||||
echo "==> Setting up Caddy server for web apps"
|
||||
mkdir -p /app/data/caddy/public
|
||||
cat > /app/data/caddy/Caddyfile <<EOT
|
||||
{
|
||||
admin off
|
||||
auto_https off
|
||||
log {
|
||||
output file /app/data/caddy/caddy.log
|
||||
format console
|
||||
output file /app/data/caddy/caddy.log {
|
||||
roll_size 10MB
|
||||
roll_keep 10
|
||||
}
|
||||
}
|
||||
servers {
|
||||
protocols h1 h2c
|
||||
}
|
||||
}
|
||||
|
||||
:3080 {
|
||||
:8000 {
|
||||
log {
|
||||
output file /app/data/caddy/access.log
|
||||
format console
|
||||
output file /app/data/caddy/access.log {
|
||||
roll_size 10MB
|
||||
roll_keep 10
|
||||
}
|
||||
}
|
||||
|
||||
# Add security headers to enable WebAssembly and IndexedDB
|
||||
# Allow WebAssembly and IndexedDB
|
||||
header {
|
||||
# Security headers
|
||||
Strict-Transport-Security "max-age=31536000; includeSubDomains"
|
||||
X-Content-Type-Options "nosniff"
|
||||
X-Frame-Options "SAMEORIGIN"
|
||||
Referrer-Policy "strict-origin-when-cross-origin"
|
||||
|
||||
# Content Security Policy that allows WebAssembly
|
||||
Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self' ${CLOUDRON_APP_ORIGIN} https://*.${CLOUDRON_APP_DOMAIN}; worker-src 'self' blob:;"
|
||||
|
||||
# CORS headers for API access
|
||||
Access-Control-Allow-Origin "*"
|
||||
Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
|
||||
Access-Control-Allow-Headers "Content-Type, Authorization"
|
||||
Access-Control-Allow-Credentials "true"
|
||||
Cross-Origin-Embedder-Policy "credentialless"
|
||||
Cross-Origin-Opener-Policy "same-origin"
|
||||
Cross-Origin-Resource-Policy "cross-origin"
|
||||
}
|
||||
|
||||
# Simple JavaScript file that defines the API endpoint
|
||||
handle /api-config.js {
|
||||
header Content-Type "application/javascript"
|
||||
respond "window.ENTE_CONFIG = { API_URL: '${API_ENDPOINT}' };" 200
|
||||
# Serve config scripts directly
|
||||
handle /config.js {
|
||||
root * /app/data/public
|
||||
file_server
|
||||
}
|
||||
|
||||
# Photos app - root path
|
||||
# Serve debug script and page
|
||||
handle /debug.js {
|
||||
root * /app/data/public
|
||||
file_server
|
||||
}
|
||||
|
||||
handle /debug {
|
||||
root * /app/data/public
|
||||
rewrite * /debug.html
|
||||
file_server
|
||||
}
|
||||
|
||||
# Health check response
|
||||
handle /health {
|
||||
respond "OK" 200
|
||||
}
|
||||
|
||||
# Serve our custom config-injected landing pages
|
||||
handle /photos-config {
|
||||
root * /app/data/public
|
||||
rewrite * /photos-config.html
|
||||
file_server
|
||||
}
|
||||
|
||||
handle /accounts-config {
|
||||
root * /app/data/public
|
||||
rewrite * /accounts-config.html
|
||||
file_server
|
||||
}
|
||||
|
||||
handle /auth-config {
|
||||
root * /app/data/public
|
||||
rewrite * /auth-config.html
|
||||
file_server
|
||||
}
|
||||
|
||||
handle /cast-config {
|
||||
root * /app/data/public
|
||||
rewrite * /cast-config.html
|
||||
file_server
|
||||
}
|
||||
|
||||
# Root handler - serve our custom index.html
|
||||
handle / {
|
||||
root * /app/data/public
|
||||
file_server
|
||||
}
|
||||
|
||||
# Serve the photos web app with local config support
|
||||
handle /photos* {
|
||||
uri strip_prefix /photos
|
||||
uri replace /photos /
|
||||
root * /app/web/photos
|
||||
try_files {path} /index.html
|
||||
file_server
|
||||
}
|
||||
|
||||
# Accounts app
|
||||
handle /accounts/* {
|
||||
uri strip_prefix /accounts
|
||||
# Serve the accounts web app
|
||||
handle /accounts* {
|
||||
uri replace /accounts /
|
||||
root * /app/web/accounts
|
||||
try_files {path} /index.html
|
||||
file_server
|
||||
}
|
||||
|
||||
# Auth app
|
||||
handle /auth/* {
|
||||
uri strip_prefix /auth
|
||||
# Serve the auth web app
|
||||
handle /auth* {
|
||||
uri replace /auth /
|
||||
root * /app/web/auth
|
||||
try_files {path} /index.html
|
||||
file_server
|
||||
}
|
||||
|
||||
# Cast app
|
||||
handle /cast/* {
|
||||
uri strip_prefix /cast
|
||||
# Serve the cast web app
|
||||
handle /cast* {
|
||||
uri replace /cast /
|
||||
root * /app/web/cast
|
||||
try_files {path} /index.html
|
||||
file_server
|
||||
}
|
||||
|
||||
# API endpoints - proxy to Museum server
|
||||
handle /api/* {
|
||||
# Proxy API calls to the backend server
|
||||
handle /api* {
|
||||
reverse_proxy localhost:8080
|
||||
}
|
||||
|
||||
# Health check endpoint for Cloudron
|
||||
handle /healthcheck {
|
||||
respond "OK" 200
|
||||
}
|
||||
|
||||
# Default to photos app
|
||||
handle {
|
||||
root * /app/web/photos
|
||||
try_files {path} /index.html
|
||||
file_server
|
||||
}
|
||||
}
|
||||
EOT
|
||||
|
||||
echo "==> Caddy configuration created at /app/data/caddy/Caddyfile"
|
||||
|
||||
# Create HTML transformer script to modify all index.html files on load
|
||||
mkdir -p /app/data/scripts
|
||||
cat > /app/data/scripts/insert-config.sh <<EOT
|
||||
#!/bin/bash
|
||||
# This script injects our configuration into all index.html files
|
||||
|
||||
# List of web app directories
|
||||
WEB_APPS=("/app/web/photos" "/app/web/accounts" "/app/web/auth" "/app/web/cast")
|
||||
|
||||
for app_dir in "\${WEB_APPS[@]}"; do
|
||||
if [ -f "\$app_dir/index.html" ]; then
|
||||
echo "Processing \$app_dir/index.html"
|
||||
|
||||
# Create a writable copy
|
||||
cp "\$app_dir/index.html" "/app/data/temp.html"
|
||||
|
||||
# Insert our config script right before the closing head tag
|
||||
sed -i 's|</head>|<script>window.ENTE_CONFIG = { API_URL: "${API_ENDPOINT}" };</script></head>|' "/app/data/temp.html"
|
||||
|
||||
# Create a symlink from the modified file to the original
|
||||
# Only if the temp file was created and modified successfully
|
||||
if [ -f "/app/data/temp.html" ]; then
|
||||
mkdir -p "/app/data/transformed/\$(basename \$app_dir)"
|
||||
cp "/app/data/temp.html" "/app/data/transformed/\$(basename \$app_dir)/index.html"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
echo "All index.html files processed"
|
||||
EOT
|
||||
chmod +x /app/data/scripts/insert-config.sh
|
||||
|
||||
# Run the transformer script to create modified index.html files
|
||||
mkdir -p /app/data/transformed
|
||||
echo "==> Creating modified index.html files with injected configuration"
|
||||
/app/data/scripts/insert-config.sh
|
||||
|
||||
# Create direct configuration files for different frameworks
|
||||
mkdir -p /app/data/public
|
||||
echo "==> Creating framework-specific configuration files"
|
||||
|
||||
# Create a Next.js public runtime configuration
|
||||
cat > /app/data/public/env.js <<EOT
|
||||
// Next.js runtime configuration
|
||||
window.ENV = {
|
||||
NEXT_PUBLIC_ENTE_ENDPOINT: "${API_ENDPOINT}"
|
||||
};
|
||||
window.process = window.process || {};
|
||||
window.process.env = window.process.env || {};
|
||||
window.process.env.NEXT_PUBLIC_ENTE_ENDPOINT = "${API_ENDPOINT}";
|
||||
EOT
|
||||
|
||||
# Create a simple JSON config
|
||||
cat > /app/data/public/config.json <<EOT
|
||||
{
|
||||
"API_URL": "${API_ENDPOINT}"
|
||||
}
|
||||
EOT
|
||||
|
||||
# Create additional HTML files with the config directly embedded
|
||||
for app_name in "photos" "accounts" "auth" "cast"; do
|
||||
cat > "/app/data/public/${app_name}-config.html" <<EOT
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Loading ${app_name}</title>
|
||||
<script src="/debug.js"></script>
|
||||
<script>
|
||||
// Set the global configuration
|
||||
window.ENTE_CONFIG = {
|
||||
API_URL: "${API_ENDPOINT}"
|
||||
};
|
||||
|
||||
// Set Next.js environment variables
|
||||
window.process = window.process || {};
|
||||
window.process.env = window.process.env || {};
|
||||
window.process.env.NEXT_PUBLIC_ENTE_ENDPOINT = "${API_ENDPOINT}";
|
||||
|
||||
// Store in localStorage as a fallback mechanism
|
||||
localStorage.setItem('ENTE_CONFIG', JSON.stringify(window.ENTE_CONFIG));
|
||||
localStorage.setItem('NEXT_PUBLIC_ENTE_ENDPOINT', "${API_ENDPOINT}");
|
||||
|
||||
// Log the configuration
|
||||
console.log("Ente ${app_name} config loaded:", window.ENTE_CONFIG);
|
||||
|
||||
// Redirect to the main app after a brief delay
|
||||
setTimeout(function() {
|
||||
window.location.href = "/${app_name}/";
|
||||
}, 100);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Loading ${app_name}...</h1>
|
||||
<p>If you are not redirected automatically, <a href="/${app_name}/">click here</a>.</p>
|
||||
<p><a href="/debug">Debug Information</a></p>
|
||||
</body>
|
||||
</html>
|
||||
EOT
|
||||
done
|
||||
|
||||
echo "==> Created app-specific config loading pages with debug info"
|
||||
|
||||
# Looking for Museum (Go server component)
|
||||
echo "==> Looking for Museum (Go server component)"
|
||||
|
||||
@ -813,3 +962,215 @@ echo "==> Caddy: PID $CADDY_PID"
|
||||
# Wait for child processes to exit
|
||||
wait $SERVER_PID
|
||||
wait $CADDY_PID
|
||||
|
||||
# Create a special root index.html that loads the config and redirects
|
||||
cat > /app/data/public/index.html <<EOT
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Ente</title>
|
||||
<script src="/debug.js"></script>
|
||||
<script>
|
||||
// Define configuration globally
|
||||
window.ENTE_CONFIG = {
|
||||
API_URL: "${API_ENDPOINT}"
|
||||
};
|
||||
|
||||
// Set environment variables for Next.js apps
|
||||
window.process = window.process || {};
|
||||
window.process.env = window.process.env || {};
|
||||
window.process.env.NEXT_PUBLIC_ENTE_ENDPOINT = "${API_ENDPOINT}";
|
||||
|
||||
// Store in localStorage as a fallback mechanism
|
||||
localStorage.setItem('ENTE_CONFIG', JSON.stringify(window.ENTE_CONFIG));
|
||||
localStorage.setItem('NEXT_PUBLIC_ENTE_ENDPOINT', "${API_ENDPOINT}");
|
||||
|
||||
// Redirect to photos app after a small delay to let the configuration load
|
||||
setTimeout(function() {
|
||||
window.location.href = "/photos/";
|
||||
}, 100);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Loading Ente...</h1>
|
||||
<p>You will be redirected automatically.</p>
|
||||
<p><a href="/debug">Debug Information</a></p>
|
||||
</body>
|
||||
</html>
|
||||
EOT
|
||||
|
||||
echo "==> Created special root index.html with configuration"
|
||||
|
||||
# Create debug script for frontend
|
||||
mkdir -p /app/data/public
|
||||
mkdir -p /app/data/debug
|
||||
|
||||
echo "==> Creating debug scripts"
|
||||
cat > /app/data/public/debug.js <<EOT
|
||||
// Debugging script for Ente
|
||||
(function() {
|
||||
console.log("Debug script loaded");
|
||||
|
||||
// Intercept URL constructor
|
||||
const originalURL = window.URL;
|
||||
window.URL = function(url, base) {
|
||||
console.log("URL constructor called with:", url, base);
|
||||
try {
|
||||
return new originalURL(url, base);
|
||||
} catch (e) {
|
||||
console.error("URL construction failed:", e.message);
|
||||
console.error("URL:", url);
|
||||
console.error("Base:", base);
|
||||
console.error("Stack:", e.stack);
|
||||
|
||||
// Try to fix common issues
|
||||
if (url && !url.startsWith("http") && !url.startsWith("/")) {
|
||||
console.log("Attempting to fix relative URL by adding leading slash");
|
||||
return new originalURL("/" + url, base);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
||||
// Create debug overlay
|
||||
const debugDiv = document.createElement('div');
|
||||
debugDiv.style.position = 'fixed';
|
||||
debugDiv.style.bottom = '10px';
|
||||
debugDiv.style.right = '10px';
|
||||
debugDiv.style.backgroundColor = 'rgba(0,0,0,0.7)';
|
||||
debugDiv.style.color = 'white';
|
||||
debugDiv.style.padding = '10px';
|
||||
debugDiv.style.borderRadius = '5px';
|
||||
debugDiv.style.zIndex = '9999';
|
||||
debugDiv.style.maxWidth = '400px';
|
||||
debugDiv.style.maxHeight = '200px';
|
||||
debugDiv.style.overflow = 'auto';
|
||||
debugDiv.innerHTML = '<h3>Ente Debug Info</h3>';
|
||||
|
||||
// Add configuration info
|
||||
const configInfo = document.createElement('div');
|
||||
configInfo.innerHTML = 'ENTE_CONFIG: ' + JSON.stringify(window.ENTE_CONFIG || {}) + '<br>' +
|
||||
'process.env.NEXT_PUBLIC_ENTE_ENDPOINT: ' + (window.process?.env?.NEXT_PUBLIC_ENTE_ENDPOINT || 'undefined') + '<br>' +
|
||||
'localStorage ENTE_CONFIG: ' + localStorage.getItem('ENTE_CONFIG') + '<br>' +
|
||||
'localStorage NEXT_PUBLIC_ENTE_ENDPOINT: ' + localStorage.getItem('NEXT_PUBLIC_ENTE_ENDPOINT');
|
||||
debugDiv.appendChild(configInfo);
|
||||
|
||||
// Add toggle button
|
||||
const toggleButton = document.createElement('button');
|
||||
toggleButton.innerText = 'Toggle Debug Info';
|
||||
toggleButton.style.marginTop = '10px';
|
||||
toggleButton.onclick = function() {
|
||||
configInfo.style.display = configInfo.style.display === 'none' ? 'block' : 'none';
|
||||
};
|
||||
debugDiv.appendChild(toggleButton);
|
||||
|
||||
// Add to document when it's ready
|
||||
if (document.body) {
|
||||
document.body.appendChild(debugDiv);
|
||||
} else {
|
||||
window.addEventListener('DOMContentLoaded', function() {
|
||||
document.body.appendChild(debugDiv);
|
||||
});
|
||||
}
|
||||
})();
|
||||
EOT
|
||||
|
||||
# Create debug info script that prints environment info
|
||||
cat > /app/data/debug/debug_env.js <<EOT
|
||||
#!/usr/bin/env node
|
||||
|
||||
console.log('=== Ente Environment Debug ===');
|
||||
console.log('CLOUDRON_APP_ORIGIN:', process.env.CLOUDRON_APP_ORIGIN);
|
||||
console.log('API_ENDPOINT:', process.env.API_ENDPOINT);
|
||||
console.log('NEXT_PUBLIC_ENTE_ENDPOINT:', process.env.NEXT_PUBLIC_ENTE_ENDPOINT);
|
||||
console.log('HOSTNAME:', process.env.HOSTNAME);
|
||||
console.log('===============================');
|
||||
EOT
|
||||
chmod +x /app/data/debug/debug_env.js
|
||||
|
||||
# Create debug info HTML
|
||||
cat > /app/data/public/debug.html <<EOT
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Ente Debug Info</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; margin: 20px; }
|
||||
.debug-section { margin-bottom: 20px; padding: 10px; border: 1px solid #ccc; }
|
||||
h1 { color: #333; }
|
||||
pre { background-color: #f5f5f5; padding: 10px; border-radius: 5px; overflow-x: auto; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Ente Debug Information</h1>
|
||||
|
||||
<div class="debug-section">
|
||||
<h2>Frontend Configuration</h2>
|
||||
<pre id="config-info">Loading...</pre>
|
||||
</div>
|
||||
|
||||
<div class="debug-section">
|
||||
<h2>URL Test</h2>
|
||||
<p>Testing URL construction with API endpoint:</p>
|
||||
<pre id="url-test">Running test...</pre>
|
||||
</div>
|
||||
|
||||
<div class="debug-section">
|
||||
<h2>API Health Check</h2>
|
||||
<pre id="api-health">Checking API health...</pre>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Define configuration globally
|
||||
window.ENTE_CONFIG = {
|
||||
API_URL: "${CLOUDRON_APP_ORIGIN}/api"
|
||||
};
|
||||
|
||||
// Set environment variables for Next.js apps
|
||||
window.process = window.process || {};
|
||||
window.process.env = window.process.env || {};
|
||||
window.process.env.NEXT_PUBLIC_ENTE_ENDPOINT = "${CLOUDRON_APP_ORIGIN}/api";
|
||||
|
||||
// Store in localStorage
|
||||
localStorage.setItem('ENTE_CONFIG', JSON.stringify(window.ENTE_CONFIG));
|
||||
localStorage.setItem('NEXT_PUBLIC_ENTE_ENDPOINT', "${CLOUDRON_APP_ORIGIN}/api");
|
||||
|
||||
// Display configuration
|
||||
document.getElementById('config-info').textContent =
|
||||
'window.ENTE_CONFIG = ' + JSON.stringify(window.ENTE_CONFIG, null, 2) + '\n' +
|
||||
'window.process.env.NEXT_PUBLIC_ENTE_ENDPOINT = ' + window.process.env.NEXT_PUBLIC_ENTE_ENDPOINT + '\n' +
|
||||
'localStorage[\'ENTE_CONFIG\'] = ' + localStorage.getItem('ENTE_CONFIG') + '\n' +
|
||||
'localStorage[\'NEXT_PUBLIC_ENTE_ENDPOINT\'] = ' + localStorage.getItem('NEXT_PUBLIC_ENTE_ENDPOINT');
|
||||
|
||||
// Test URL construction
|
||||
try {
|
||||
const apiUrl = window.ENTE_CONFIG.API_URL;
|
||||
const testUrl = new URL('/users/ott', apiUrl);
|
||||
document.getElementById('url-test').textContent =
|
||||
'API URL: ' + apiUrl + '\n' +
|
||||
'Test URL (/users/ott): ' + testUrl.toString() + '\n' +
|
||||
'Result: SUCCESS';
|
||||
} catch (e) {
|
||||
document.getElementById('url-test').textContent =
|
||||
'Error: ' + e.message + '\n' +
|
||||
'Stack: ' + e.stack;
|
||||
}
|
||||
|
||||
// Test API health
|
||||
fetch('/api/health')
|
||||
.then(response => {
|
||||
if (response.ok) return response.text();
|
||||
throw new Error('API returned status: ' + response.status);
|
||||
})
|
||||
.then(data => {
|
||||
document.getElementById('api-health').textContent = 'API health check: OK\nResponse: ' + data;
|
||||
})
|
||||
.catch(err => {
|
||||
document.getElementById('api-health').textContent = 'API health check failed: ' + err.message;
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
EOT
|
Loading…
x
Reference in New Issue
Block a user