28 Commits

Author SHA1 Message Date
Your Name
9c3605d935 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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-21 20:56:27 -06:00
Your Name
77d0326a70 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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-21 20:29:46 -06:00
Your Name
1738af7f61 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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-21 19:58:39 -06:00
Your Name
37cd205a07 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

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-21 19:20:15 -06:00
Your Name
61046f1d42 Auto-configure CLI endpoint 2025-09-30 09:34:25 -06:00
Your Name
7a5fac90ab Persist Museum configuration for manual edits 2025-09-29 22:36:37 -06:00
Your Name
b38bd6a249 Make Ente CLI usable out of the box 2025-09-29 22:05:24 -06:00
Your Name
a8b22a95c8 Bundle Ente CLI for Cloudron console 2025-09-29 21:37:33 -06:00
Your Name
93cdf1f2f1 Remove OTT log highlighter 2025-09-29 21:26:21 -06:00
Your Name
8d6fc6fde0 Document S3 examples and refresh template 2025-09-29 21:18:19 -06:00
Your Name
b1e8df29e7 Allow runtime S3 configuration overrides 2025-09-29 20:59:57 -06:00
Your Name
176d23c086 Fix SPA asset routing for web apps 2025-09-29 20:47:07 -06:00
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
Your Name
b7fcf5c01d 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
Your Name
da50bf4773 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
Your Name
4290a33ba9 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

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-22 08:58:53 -06:00
Your Name
62b6f7f9ac 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.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-21 20:44:19 -06:00
Your Name
e3eb1b0491 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.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-21 20:41:58 -06:00
Your Name
fc82e988e9 Update CloudronManifest version to 1.0.1
Increment version after multiple iterations of S3 configuration fixes and port conflict resolution.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-21 20:37:07 -06:00
Your Name
5068e12025 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.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-21 17:18:51 -06:00
5 changed files with 74 additions and 357 deletions

View File

@@ -12,13 +12,13 @@
git clone https://github.com/andreasdueren/ente-cloudron.git
cd ente-cloudron
```
2. Build the image via the Cloudron build service. Adjust `--tag` to match `CloudronManifest.json` (`0.4.3`) and optionally override the Ente git ref:
2. Build the image via the Cloudron build service. Adjust `--tag` to match `CloudronManifest.json` (`0.2.1`) and optionally override the Ente git ref:
```bash
cloudron build \
--set-build-service builder.docker.due.ren \
--build-service-token e3265de06b1d0e7bb38400539012a8433a74c2c96a17955e \
--set-repository andreasdueren/ente-cloudron \
--tag 0.4.3 \
--tag 0.2.1 \
--build-arg ENTE_GIT_REF=main
```
Use a tagged Ente release for reproducible builds (e.g. `--build-arg ENTE_GIT_REF=v0.9.0`).
@@ -28,7 +28,7 @@ Always uninstall the dev instance before reinstalling.
```bash
cloudron install \
--location ente.due.ren \
--image andreasdueren/ente-cloudron:0.4.3
--image andreasdueren/ente-cloudron:0.2.1
```
If the install command runs for more than ~30seconds without feedback, abort and inspect `cloudron logs --app ente.due.ren`.
@@ -54,7 +54,6 @@ Optional: set `CLOUDRON_OIDC_IDENTIFIER`, `CLOUDRON_OIDC_CLIENT_ID`, and `CLOUDR
## Troubleshooting
- **S3 errors**: Verify credentials in `/app/data/config/s3.env`; check connectivity using `aws s3 ls --endpoint-url ...` from a trusted host.
- **Startup issues**: Inspect `/app/data/logs/startup.log` (also mirrored to `cloudron logs`) for rendered configuration and error messages.
- **Museum not starting**: Inspect `/app/data/museum/configurations/local.yaml` for syntax issues; delete to regenerate.
- **Frontend stale after update**: Restart the app—the startup script re-syncs static assets on each boot.
- **OIDC issues**: Confirm the callback URL `/api/v1/session/callback` is allowed in the Cloudron SSO client configuration.
@@ -64,5 +63,4 @@ Optional: set `CLOUDRON_OIDC_IDENTIFIER`, `CLOUDRON_OIDC_CLIENT_ID`, and `CLOUDR
cloudron exec --app ente.due.ren -- cat /app/data/museum/configurations/local.yaml
cloudron exec --app ente.due.ren -- ente --help
cloudron logs --app ente.due.ren -f
cloudron exec --app ente.due.ren -- tail -f /app/data/logs/startup.log
```

View File

@@ -1,40 +1,9 @@
# Changelog
## 0.4.5 (2025-10-30)
* Serve photos UI on the primary hostname and mount other apps on `accounts/auth/cast/albums/family.<root-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
## 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

View File

@@ -7,7 +7,7 @@
"contactEmail": "contact@ente.io",
"website": "https://ente.io",
"tagline": "Open source, end-to-end encrypted photo backup",
"version": "0.4.3",
"version": "0.3.2",
"upstreamVersion": "git-main",
"healthCheckPath": "/health",
"httpPort": 3080,
@@ -17,8 +17,7 @@
"localstorage": {},
"postgresql": {},
"sendmail": {
"supportsDisplayName": true,
"requiresValidCertificate": true
"supportsDisplayName": true
}
},
"checklist": {

View File

@@ -18,20 +18,16 @@ database:
maxIdleConns: 25
connMaxLifetime: "1h"
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:
storage:
type: "s3"
s3:
endpoint: "%%S3_ENDPOINT%%"
region: "%%S3_REGION%%"
bucket: "%%S3_BUCKET%%"
key: "%%S3_ACCESS_KEY%%"
secret: "%%S3_SECRET_KEY%%"
path_prefix: "%%S3_PREFIX%%"
accessKey: "%%S3_ACCESS_KEY%%"
secretKey: "%%S3_SECRET_KEY%%"
prefix: "%%S3_PREFIX%%"
forcePathStyle: true
email:
smtp:
@@ -52,19 +48,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

359
start.sh
View File

@@ -28,15 +28,7 @@ STARTUP_FLAG="$DATA_DIR/startup.lock"
mkdir -p "$LOG_DIR" "$CONFIG_DIR" "$TMP_DIR" "$SECRETS_DIR" "$MUSEUM_RUNTIME_DIR" "$WEB_RUNTIME_DIR" "$MUSEUM_CONFIG_DIR"
chown -R cloudron:cloudron "$DATA_DIR"
LOG_FILE="$LOG_DIR/startup.log"
touch "$LOG_FILE"
chown cloudron:cloudron "$LOG_FILE"
chmod 640 "$LOG_FILE"
# Mirror all output to a persistent log file while retaining stdout/stderr for Cloudron aggregation
exec > >(tee -a "$LOG_FILE") 2>&1
log INFO "Starting Ente for Cloudron"
log INFO "Startup logs are mirrored to $LOG_FILE"
if ! command -v setpriv >/dev/null 2>&1; then
log ERROR "setpriv command not found"
@@ -50,61 +42,14 @@ fi
touch "$STARTUP_FLAG"
trap 'rm -f "$STARTUP_FLAG"' EXIT
APP_FQDN="${CLOUDRON_APP_DOMAIN:-${CLOUDRON_APP_FQDN:-localhost}}"
BASE_URL="${CLOUDRON_APP_ORIGIN:-https://$APP_FQDN}"
BASE_URL="${CLOUDRON_APP_ORIGIN:-https://$CLOUDRON_APP_FQDN}"
BASE_URL="${BASE_URL%/}"
ROOT_DOMAIN="$APP_FQDN"
if [ "$APP_FQDN" != "localhost" ] && expr "$APP_FQDN" : '.*\..*' >/dev/null; then
ROOT_DOMAIN="${APP_FQDN#*.}"
fi
PHOTOS_HOST="$APP_FQDN"
ACCOUNTS_HOST="$APP_FQDN"
AUTH_HOST="$APP_FQDN"
CAST_HOST="$APP_FQDN"
ALBUMS_HOST="$APP_FQDN"
FAMILY_HOST="$APP_FQDN"
USE_SUBDOMAIN_ROUTING=false
if [ "$APP_FQDN" != "localhost" ] && [ "$ROOT_DOMAIN" != "$APP_FQDN" ]; then
ACCOUNTS_HOST="accounts.${ROOT_DOMAIN}"
AUTH_HOST="auth.${ROOT_DOMAIN}"
CAST_HOST="cast.${ROOT_DOMAIN}"
ALBUMS_HOST="albums.${ROOT_DOMAIN}"
FAMILY_HOST="family.${ROOT_DOMAIN}"
USE_SUBDOMAIN_ROUTING=true
fi
PHOTOS_URL="https://${PHOTOS_HOST}"
if [ "$USE_SUBDOMAIN_ROUTING" = true ]; then
ACCOUNTS_URL="https://${ACCOUNTS_HOST}"
AUTH_URL="https://${AUTH_HOST}"
CAST_URL="https://${CAST_HOST}"
FAMILY_URL="https://${FAMILY_HOST}"
ALBUMS_URL="https://${ALBUMS_HOST}"
else
ACCOUNTS_URL="${BASE_URL}/accounts"
AUTH_URL="${BASE_URL}/auth"
CAST_URL="${BASE_URL}/cast"
FAMILY_URL="${BASE_URL}/family"
ALBUMS_URL="${BASE_URL}/albums"
fi
if [ "$APP_FQDN" != "localhost" ]; then
API_BASE="https://${APP_FQDN}"
else
API_BASE="$BASE_URL"
fi
API_ORIGIN="${API_BASE}/api"
RP_ID="$PHOTOS_HOST"
RP_ID="${CLOUDRON_APP_FQDN:-${CLOUDRON_APP_DOMAIN:-localhost}}"
API_ORIGIN="${BASE_URL}/api"
log INFO "Application base URL: $BASE_URL"
log INFO "Relying party ID: $RP_ID"
log INFO "API origin: $API_ORIGIN"
if [ "$USE_SUBDOMAIN_ROUTING" = true ]; then
log INFO "Serving frontend hosts: photos=${PHOTOS_HOST}, accounts=${ACCOUNTS_HOST}, auth=${AUTH_HOST}, cast=${CAST_HOST}"
fi
S3_CONFIG_FILE="$CONFIG_DIR/s3.env"
if [ ! -f "$S3_CONFIG_FILE" ]; then
@@ -167,64 +112,26 @@ if [ "$S3_NOT_CONFIGURED" = "false" ]; then
fi
log INFO "Using S3 endpoint $S3_ENDPOINT_HOST (region $S3_REGION, bucket $S3_BUCKET)"
S3_REGION_LOWER="$(printf '%s' "$S3_REGION" | tr '[:upper:]' '[:lower:]')"
if printf '%s' "$S3_ENDPOINT_HOST" | grep -q '\.r2\.cloudflarestorage\.com$' && [ "$S3_REGION_LOWER" != "auto" ]; then
log WARN "Cloudflare R2 endpoints require S3_REGION=auto; current value '$S3_REGION' may cause upload failures"
fi
else
S3_ENDPOINT_HOST="s3.example.com"
log WARN "S3 not configured - using placeholder values"
fi
DEFAULT_FORCE_PATH_STYLE="true"
if printf '%s' "$S3_ENDPOINT_HOST" | grep -q '\.r2\.cloudflarestorage\.com$'; then
if [ -z "${S3_FORCE_PATH_STYLE:-}" ] && [ -z "${ENTE_S3_FORCE_PATH_STYLE:-}" ]; then
log INFO "Detected Cloudflare R2 endpoint; defaulting to path-style URLs (required by R2)"
fi
fi
S3_FORCE_PATH_STYLE_RAW="${S3_FORCE_PATH_STYLE:-${ENTE_S3_FORCE_PATH_STYLE:-$DEFAULT_FORCE_PATH_STYLE}}"
S3_FORCE_PATH_STYLE="$(printf '%s' "$S3_FORCE_PATH_STYLE_RAW" | tr '[:upper:]' '[:lower:]')"
S3_ARE_LOCAL_BUCKETS="$(printf '%s' "${S3_ARE_LOCAL_BUCKETS:-${ENTE_S3_ARE_LOCAL_BUCKETS:-false}}" | tr '[:upper:]' '[:lower:]')"
S3_PRIMARY_DC="${ENTE_S3_PRIMARY_DC:-b2-eu-cen}"
S3_SECONDARY_DC="${ENTE_S3_SECONDARY_DC:-$S3_PRIMARY_DC}"
S3_DERIVED_DC="${ENTE_S3_DERIVED_DC:-$S3_PRIMARY_DC}"
S3_DCS=()
add_s3_dc() {
local candidate="$1"
if [ -z "$candidate" ]; then
return
fi
for existing in "${S3_DCS[@]}"; do
if [ "$existing" = "$candidate" ]; then
return
fi
done
S3_DCS+=("$candidate")
}
add_s3_dc "$S3_PRIMARY_DC"
add_s3_dc "$S3_SECONDARY_DC"
add_s3_dc "$S3_DERIVED_DC"
S3_PREFIX_DISPLAY="${S3_PREFIX:-<none>}"
log INFO "Resolved S3 configuration: host=$S3_ENDPOINT_HOST region=$S3_REGION pathStyle=$S3_FORCE_PATH_STYLE localBuckets=$S3_ARE_LOCAL_BUCKETS primaryDC=$S3_PRIMARY_DC derivedDC=$S3_DERIVED_DC prefix=$S3_PREFIX_DISPLAY"
DEFAULT_GIN_TRUSTED_PROXIES="127.0.0.1,::1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"
GIN_TRUSTED_PROXIES="${GIN_TRUSTED_PROXIES:-$DEFAULT_GIN_TRUSTED_PROXIES}"
export GIN_TRUSTED_PROXIES
log INFO "Configured trusted proxy ranges for Museum: $GIN_TRUSTED_PROXIES"
MASTER_KEY_FILE="$SECRETS_DIR/master_key"
HASH_KEY_FILE="$SECRETS_DIR/hash_key"
JWT_SECRET_FILE="$SECRETS_DIR/jwt_secret"
SESSION_SECRET_FILE="$SECRETS_DIR/session_secret"
SMTP_HOST="${CLOUDRON_MAIL_SMTP_SERVER:-mail}"
SMTP_PORT="${CLOUDRON_MAIL_SMTPS_PORT:-2465}"
SMTP_ENCRYPTION="tls"
SMTP_HOST="${CLOUDRON_MAIL_SMTP_SERVER:-}"
SMTP_PORT="${CLOUDRON_MAIL_SMTP_PORT:-25}"
SMTP_ENCRYPTION="${CLOUDRON_MAIL_SMTP_ENCRYPTION:-}"
if [ -n "${CLOUDRON_MAIL_SMTPS_PORT:-}" ]; then
SMTP_PORT="${CLOUDRON_MAIL_SMTPS_PORT}"
SMTP_ENCRYPTION="tls"
if [ -n "${CLOUDRON_MAIL_DOMAIN:-}" ]; then
SMTP_HOST="mail.${CLOUDRON_MAIL_DOMAIN}"
fi
fi
SMTP_USERNAME="${CLOUDRON_MAIL_SMTP_USERNAME:-}"
SMTP_PASSWORD="${CLOUDRON_MAIL_SMTP_PASSWORD:-}"
SMTP_EMAIL="${CLOUDRON_MAIL_FROM:-no-reply@$RP_ID}"
@@ -239,7 +146,7 @@ fi
normalize_b64() {
local value="$1"
value="$(printf '%s' "$value" | tr -d '\r\n')"
value="$(printf '%s' "$value" | tr -- '-_' '+/')"
value="$(printf '%s' "$value" | tr '-_' '+/')"
local mod=$(( ${#value} % 4 ))
if [ $mod -eq 2 ]; then
value="${value}=="
@@ -254,7 +161,7 @@ normalize_b64() {
normalize_b64url() {
local value="$1"
value="$(printf '%s' "$value" | tr -d '\r\n')"
value="$(printf '%s' "$value" | tr -- '+/' '-_')"
value="$(printf '%s' "$value" | tr '+/' '-_')"
local mod=$(( ${#value} % 4 ))
if [ $mod -eq 2 ]; then
value="${value}=="
@@ -273,7 +180,7 @@ generate_b64() {
generate_b64url() {
local bytes="$1"
openssl rand -base64 "$bytes" | tr -- '+/' '-_' | tr -d '\n'
openssl rand -base64 "$bytes" | tr '+/' '-_' | tr -d '\n'
}
ensure_secret() {
@@ -337,22 +244,22 @@ if [ ! -x "$MUSEUM_BIN" ]; then
exit 1
fi
# Always regenerate Museum config to pick up S3 changes
log INFO "Rendering Museum configuration"
cat > "$MUSEUM_CONFIG" <<EOF_CFG
if [ ! -f "$MUSEUM_CONFIG" ]; then
log INFO "Rendering Museum configuration"
cat > "$MUSEUM_CONFIG" <<EOF_CFG
log-file: ""
http:
port: 8080
use-tls: false
apps:
public-albums: "$ALBUMS_URL"
public-locker: "$PHOTOS_URL"
accounts: "$ACCOUNTS_URL"
cast: "$CAST_URL"
family: "$FAMILY_URL"
public-albums: "$BASE_URL/albums"
public-locker: "$BASE_URL/photos"
accounts: "$BASE_URL/accounts"
cast: "$BASE_URL/cast"
family: "$BASE_URL/family"
custom-domain:
cname: "${APP_FQDN}"
cname: "${CLOUDRON_APP_DOMAIN:-localhost}"
db:
host: ${CLOUDRON_POSTGRESQL_HOST}
@@ -363,30 +270,19 @@ db:
sslmode: disable
s3:
are_local_buckets: ${S3_ARE_LOCAL_BUCKETS}
use_path_style_urls: ${S3_FORCE_PATH_STYLE}
are_local_buckets: false
use_path_style_urls: true
hot_storage:
primary: ${S3_PRIMARY_DC}
secondary: ${S3_SECONDARY_DC}
derived-storage: ${S3_DERIVED_DC}
EOF_CFG
for dc in "${S3_DCS[@]}"; do
cat >> "$MUSEUM_CONFIG" <<EOF_CFG
$dc:
primary: primary-storage
secondary: primary-storage
primary-storage:
key: "$S3_ACCESS_KEY"
secret: "$S3_SECRET_KEY"
endpoint: "$S3_ENDPOINT_HOST"
region: "$S3_REGION"
bucket: "$S3_BUCKET"
EOF_CFG
if [ -n "$S3_PREFIX" ]; then
printf ' path_prefix: "%s"\n' "$S3_PREFIX" >> "$MUSEUM_CONFIG"
fi
printf '\n' >> "$MUSEUM_CONFIG"
done
path_prefix: "$S3_PREFIX"
cat >> "$MUSEUM_CONFIG" <<EOF_CFG
smtp:
host: "${SMTP_HOST}"
port: "${SMTP_PORT}"
@@ -403,7 +299,7 @@ internal:
webauthn:
rpid: "$RP_ID"
rporigins:
- "$PHOTOS_URL"
- "$BASE_URL"
key:
encryption: $MASTER_KEY
@@ -424,12 +320,15 @@ oidc:
issuer: "${CLOUDRON_OIDC_IDENTIFIER}"
client_id: "${CLOUDRON_OIDC_CLIENT_ID}"
client_secret: "${CLOUDRON_OIDC_CLIENT_SECRET}"
redirect_url: "$API_BASE/api/v1/session/callback"
redirect_url: "$BASE_URL/api/v1/session/callback"
EOF_CFG
fi
chown cloudron:cloudron "$MUSEUM_CONFIG"
chmod 600 "$MUSEUM_CONFIG"
chown cloudron:cloudron "$MUSEUM_CONFIG"
chmod 600 "$MUSEUM_CONFIG"
else
log INFO "Museum configuration already present; leaving untouched"
fi
log INFO "Preparing frontend assets"
if [ -d "$WEB_SOURCE_DIR" ]; then
@@ -500,14 +399,14 @@ if [ -d "$WEB_RUNTIME_DIR" ]; then
FRONTEND_REPLACEMENTS=(
"ENTE_API_ORIGIN_PLACEHOLDER|$API_ORIGIN"
"https://api.ente.io|$API_ORIGIN"
"https://accounts.ente.io|$ACCOUNTS_URL"
"https://auth.ente.io|$AUTH_URL"
"https://cast.ente.io|$CAST_URL"
"https://photos.ente.io|$PHOTOS_URL"
"https://web.ente.io|$PHOTOS_URL"
"https://albums.ente.io|$ALBUMS_URL"
"https://family.ente.io|$FAMILY_URL"
"https://ente.io|$PHOTOS_URL"
"https://accounts.ente.io|$BASE_URL/accounts"
"https://auth.ente.io|$BASE_URL/auth"
"https://cast.ente.io|$BASE_URL/cast"
"https://photos.ente.io|$BASE_URL/photos"
"https://web.ente.io|$BASE_URL/photos"
"https://albums.ente.io|$BASE_URL/albums"
"https://family.ente.io|$BASE_URL/family"
"https://ente.io|$BASE_URL"
)
OLD_IFS="$IFS"
for entry in "${FRONTEND_REPLACEMENTS[@]}"; do
@@ -530,14 +429,10 @@ chown -R cloudron:cloudron "$DATA_DIR/home"
chmod 700 "$DATA_DIR/home"
log INFO "Rendering Caddy configuration"
if [ "$USE_SUBDOMAIN_ROUTING" = true ]; then
cat > "$CADDY_CONFIG" <<EOF_CADDY
{
admin off
auto_https off
servers {
trusted_proxies static private_ranges
}
}
:3080 {
@@ -550,178 +445,44 @@ cat > "$CADDY_CONFIG" <<EOF_CADDY
@options {
method OPTIONS
header Origin *
}
handle @options {
header Access-Control-Allow-Origin "{http.request.header.Origin}"
header Access-Control-Allow-Origin "*"
header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
header Access-Control-Allow-Headers "*"
header Access-Control-Allow-Credentials "true"
header Access-Control-Max-Age "3600"
header Vary "Origin"
respond 204
}
handle_path /api/* {
reverse_proxy localhost:8080 {
header_up Host {http.request.host}
header_up X-Real-IP {http.request.header.X-Forwarded-For}
header_up X-Forwarded-For {http.request.header.X-Forwarded-For}
header_up X-Forwarded-Proto {http.request.header.X-Forwarded-Proto}
header_up X-Real-IP {http.request.remote}
header_up X-Forwarded-For {http.request.remote}
header_up X-Forwarded-Proto {http.request.scheme}
}
@api_cors {
header Origin *
}
header -Access-Control-Allow-Origin
header -Access-Control-Allow-Credentials
header @api_cors {
Access-Control-Allow-Origin {http.request.header.Origin}
Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
Access-Control-Allow-Headers "*"
Access-Control-Allow-Credentials "true"
Vary "Origin"
}
}
handle /health {
rewrite * /ping
reverse_proxy localhost:8080 {
header_up Host {http.request.host}
header_up X-Real-IP {http.request.header.X-Forwarded-For}
header_up X-Forwarded-For {http.request.header.X-Forwarded-For}
header_up X-Forwarded-Proto {http.request.header.X-Forwarded-Proto}
}
}
handle /ping {
reverse_proxy localhost:8080 {
header_up Host {http.request.host}
header_up X-Real-IP {http.request.header.X-Forwarded-For}
header_up X-Forwarded-For {http.request.header.X-Forwarded-For}
header_up X-Forwarded-Proto {http.request.header.X-Forwarded-Proto}
}
}
handle /public/* {
reverse_proxy localhost:8080
}
@photos_host host ${PHOTOS_HOST}
handle @photos_host {
root * $WEB_RUNTIME_DIR/photos
try_files {path} {path}/index.html /photos/index.html
file_server
}
@accounts_host host ${ACCOUNTS_HOST}
handle @accounts_host {
root * $WEB_RUNTIME_DIR/accounts
try_files {path} {path}/index.html /accounts/index.html
file_server
}
@auth_host host ${AUTH_HOST}
handle @auth_host {
root * $WEB_RUNTIME_DIR/auth
try_files {path} {path}/index.html /auth/index.html
file_server
}
@cast_host host ${CAST_HOST}
handle @cast_host {
root * $WEB_RUNTIME_DIR/cast
try_files {path} {path}/index.html /cast/index.html
file_server
}
@albums_host host ${ALBUMS_HOST}
handle @albums_host {
root * $WEB_RUNTIME_DIR/albums
try_files {path} {path}/index.html /albums/index.html
file_server
}
@family_host host ${FAMILY_HOST}
handle @family_host {
root * $WEB_RUNTIME_DIR/family
try_files {path} {path}/index.html /family/index.html
file_server
}
handle {
respond "Not Found" 404
}
}
EOF_CADDY
else
cat > "$CADDY_CONFIG" <<EOF_CADDY
{
admin off
auto_https off
servers {
trusted_proxies static private_ranges
}
}
:3080 {
log {
level INFO
output stdout
}
encode gzip
@options {
method OPTIONS
header Origin *
}
handle @options {
header Access-Control-Allow-Origin "{http.request.header.Origin}"
header Access-Control-Allow-Origin "*"
header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
header Access-Control-Allow-Headers "*"
header Access-Control-Allow-Credentials "true"
header Access-Control-Max-Age "3600"
header Vary "Origin"
respond 204
}
handle_path /api/* {
reverse_proxy localhost:8080 {
header_up Host {http.request.host}
header_up X-Real-IP {http.request.header.X-Forwarded-For}
header_up X-Forwarded-For {http.request.header.X-Forwarded-For}
header_up X-Forwarded-Proto {http.request.header.X-Forwarded-Proto}
}
@api_cors {
header Origin *
}
header -Access-Control-Allow-Origin
header -Access-Control-Allow-Credentials
header @api_cors {
Access-Control-Allow-Origin {http.request.header.Origin}
Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
Access-Control-Allow-Headers "*"
Access-Control-Allow-Credentials "true"
Vary "Origin"
}
}
handle /health {
rewrite * /ping
reverse_proxy localhost:8080 {
header_up Host {http.request.host}
header_up X-Real-IP {http.request.header.X-Forwarded-For}
header_up X-Forwarded-For {http.request.header.X-Forwarded-For}
header_up X-Forwarded-Proto {http.request.header.X-Forwarded-Proto}
header_up X-Real-IP {http.request.remote}
header_up X-Forwarded-For {http.request.remote}
header_up X-Forwarded-Proto {http.request.scheme}
}
}
handle /ping {
reverse_proxy localhost:8080 {
header_up Host {http.request.host}
header_up X-Real-IP {http.request.header.X-Forwarded-For}
header_up X-Forwarded-For {http.request.header.X-Forwarded-For}
header_up X-Forwarded-Proto {http.request.header.X-Forwarded-Proto}
header_up X-Real-IP {http.request.remote}
header_up X-Forwarded-For {http.request.remote}
header_up X-Forwarded-Proto {http.request.scheme}
}
}
@@ -735,11 +496,6 @@ cat > "$CADDY_CONFIG" <<EOF_CADDY
file_server
}
handle /images/* {
root * $WEB_RUNTIME_DIR/photos
file_server
}
handle /auth/* {
root * $WEB_RUNTIME_DIR
try_files {path} {path}/index.html /auth/index.html
@@ -783,7 +539,6 @@ cat > "$CADDY_CONFIG" <<EOF_CADDY
}
}
EOF_CADDY
fi
chown cloudron:cloudron "$CADDY_CONFIG"