3 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
3 changed files with 125 additions and 90 deletions

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.5.7",
"version": "0.5.6",
"upstreamVersion": "git-main",
"healthCheckPath": "/health",
"httpPort": 3080,
@@ -40,6 +40,27 @@
"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)",

View File

@@ -57,14 +57,17 @@ RUN apt-get update && \
rm -rf /var/lib/apt/lists/*
RUN corepack enable
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
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:cast; \
yarn build:share; \
yarn build:embed; \
yarn build:payments
RUN if [ -d "apps" ]; then \
for app in photos accounts auth cast; do \
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}"; \
@@ -132,6 +135,9 @@ 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 start.sh /app/pkg/start.sh

180
start.sh
View File

@@ -107,6 +107,9 @@ AUTH_HOST="$(resolve_http_hostname "AUTH_DOMAIN" "auth.${APP_FQDN}")"
CAST_HOST="$(resolve_http_hostname "CAST_DOMAIN" "cast.${APP_FQDN}")"
ALBUMS_HOST="$(resolve_http_hostname "ALBUMS_DOMAIN" "albums.${APP_FQDN}")"
FAMILY_HOST="$(resolve_http_hostname "FAMILY_DOMAIN" "family.${APP_FQDN}")"
SHARE_HOST="$(resolve_http_hostname "SHARE_DOMAIN" "share.${APP_FQDN}")"
EMBED_HOST="$(resolve_http_hostname "EMBED_DOMAIN" "embed.${APP_FQDN}")"
PAYMENTS_HOST="$(resolve_http_hostname "PAYMENTS_DOMAIN" "payments.${APP_FQDN}")"
normalize_host() {
local host="$1"
@@ -121,76 +124,18 @@ normalize_host() {
esac
}
common_domain_suffix_two() {
local host_a="$1"
local host_b="$2"
local IFS='.'
local -a parts_a=()
local -a parts_b=()
read -ra parts_a <<< "$host_a"
read -ra parts_b <<< "$host_b"
local i=$(( ${#parts_a[@]} - 1 ))
local j=$(( ${#parts_b[@]} - 1 ))
local suffix=""
while [ $i -ge 0 ] && [ $j -ge 0 ]; do
if [ "${parts_a[$i]}" = "${parts_b[$j]}" ]; then
if [ -z "$suffix" ]; then
suffix="${parts_a[$i]}"
else
suffix="${parts_a[$i]}.$suffix"
fi
((i--))
((j--))
else
break
fi
done
printf '%s\n' "$suffix"
}
common_domain_suffix() {
if [ "$#" -eq 0 ]; then
return
fi
local suffix="$1"
shift
while [ "$#" -gt 0 ] && [ -n "$suffix" ]; do
suffix="$(common_domain_suffix_two "$suffix" "$1")"
shift
done
printf '%s\n' "$suffix"
}
derive_default_rp_id() {
local hosts=("$PHOTOS_HOST")
if [ "$USE_SUBDOMAIN_ROUTING" = true ]; then
hosts+=("$ACCOUNTS_HOST" "$AUTH_HOST" "$CAST_HOST" "$ALBUMS_HOST" "$FAMILY_HOST")
fi
local suffix
suffix="$(common_domain_suffix "${hosts[@]}")"
if [ -n "$suffix" ]; then
printf '%s\n' "$suffix"
else
printf '%s\n' "$PHOTOS_HOST"
fi
}
ACCOUNTS_HOST="$(normalize_host "$ACCOUNTS_HOST")"
AUTH_HOST="$(normalize_host "$AUTH_HOST")"
CAST_HOST="$(normalize_host "$CAST_HOST")"
ALBUMS_HOST="$(normalize_host "$ALBUMS_HOST")"
FAMILY_HOST="$(normalize_host "$FAMILY_HOST")"
SHARE_HOST="$(normalize_host "$SHARE_HOST")"
EMBED_HOST="$(normalize_host "$EMBED_HOST")"
PAYMENTS_HOST="$(normalize_host "$PAYMENTS_HOST")"
USE_SUBDOMAIN_ROUTING=false
if [ "$APP_FQDN" != "localhost" ]; then
if [ "$PHOTOS_HOST" != "$APP_FQDN" ] || [ "$ACCOUNTS_HOST" != "$APP_FQDN" ] || [ "$AUTH_HOST" != "$APP_FQDN" ] || [ "$CAST_HOST" != "$APP_FQDN" ] || [ "$ALBUMS_HOST" != "$APP_FQDN" ] || [ "$FAMILY_HOST" != "$APP_FQDN" ]; then
if [ "$PHOTOS_HOST" != "$APP_FQDN" ] || [ "$ACCOUNTS_HOST" != "$APP_FQDN" ] || [ "$AUTH_HOST" != "$APP_FQDN" ] || [ "$CAST_HOST" != "$APP_FQDN" ] || [ "$ALBUMS_HOST" != "$APP_FQDN" ] || [ "$FAMILY_HOST" != "$APP_FQDN" ] || [ "$SHARE_HOST" != "$APP_FQDN" ] || [ "$EMBED_HOST" != "$APP_FQDN" ] || [ "$PAYMENTS_HOST" != "$APP_FQDN" ]; then
USE_SUBDOMAIN_ROUTING=true
fi
fi
@@ -202,12 +147,18 @@ if [ "$USE_SUBDOMAIN_ROUTING" = true ]; then
CAST_URL="https://${CAST_HOST}"
FAMILY_URL="https://${FAMILY_HOST}"
ALBUMS_URL="https://${ALBUMS_HOST}"
SHARE_URL="https://${SHARE_HOST}"
EMBED_URL="https://${EMBED_HOST}"
PAYMENTS_URL="https://${PAYMENTS_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"
SHARE_URL="${BASE_URL}/share"
EMBED_URL="${BASE_URL}/embed"
PAYMENTS_URL="${BASE_URL}/payments"
fi
if [ "$APP_FQDN" != "localhost" ]; then
@@ -216,17 +167,17 @@ else
API_BASE="$BASE_URL"
fi
API_ORIGIN="${API_BASE}/api"
if [ -n "${WEBAUTHN_RP_ID:-}" ]; then
RP_ID="$WEBAUTHN_RP_ID"
if [[ "$PHOTOS_HOST" == *.*.* ]]; then
RP_ID="${PHOTOS_HOST#*.}"
else
RP_ID="$(derive_default_rp_id)"
RP_ID="$PHOTOS_HOST"
fi
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}"
log INFO "Serving frontend hosts: photos=${PHOTOS_HOST}, accounts=${ACCOUNTS_HOST}, auth=${AUTH_HOST}, cast=${CAST_HOST}, share=${SHARE_HOST}, embed=${EMBED_HOST}, payments=${PAYMENTS_HOST}"
fi
S3_CONFIG_FILE="$CONFIG_DIR/s3.env"
@@ -752,7 +703,8 @@ http:
apps:
public-albums: "$ALBUMS_URL"
public-locker: "$PHOTOS_URL"
embed-albums: "$EMBED_URL"
public-locker: "$SHARE_URL"
accounts: "$ACCOUNTS_URL"
cast: "$CAST_URL"
family: "$FAMILY_URL"
@@ -867,7 +819,7 @@ chmod 600 "$MUSEUM_CONFIG"
log INFO "Preparing frontend assets"
if [ -d "$WEB_SOURCE_DIR" ]; then
for app in photos accounts auth cast albums family; do
for app in photos accounts auth cast albums family share embed payments; do
if [ -d "$WEB_SOURCE_DIR/$app" ]; then
log INFO "Updating $app frontend assets"
rm -rf "$WEB_RUNTIME_DIR/$app"
@@ -969,6 +921,9 @@ if [ -d "$WEB_RUNTIME_DIR" ]; then
"https://web.ente.io|$PHOTOS_URL"
"https://albums.ente.io|$ALBUMS_URL"
"https://family.ente.io|$FAMILY_URL"
"https://share.ente.io|$SHARE_URL"
"https://embed.ente.io|$EMBED_URL"
"https://payments.ente.io|$PAYMENTS_URL"
"https://ente.io|$PHOTOS_URL"
)
OLD_IFS="$IFS"
@@ -1019,6 +974,10 @@ chmod 700 "$DATA_DIR/home"
log INFO "Rendering Caddy configuration"
if [ "$USE_SUBDOMAIN_ROUTING" = true ]; then
PHOTOS_HOST_MATCHERS="$PHOTOS_HOST"
if [ "$APP_FQDN" != "$PHOTOS_HOST" ]; then
PHOTOS_HOST_MATCHERS="$PHOTOS_HOST_MATCHERS $APP_FQDN"
fi
cat > "$CADDY_CONFIG" <<EOF_CADDY
{
admin off
@@ -1054,9 +1013,7 @@ cat > "$CADDY_CONFIG" <<EOF_CADDY
respond 204
}
@api_host host ${PHOTOS_HOST}
handle @api_host {
handle_path /api/* {
handle_path /api/* {
@api_cors_subdomain header Origin *
header @api_cors_subdomain {
Access-Control-Allow-Origin {http.request.header.Origin}
@@ -1073,12 +1030,12 @@ cat > "$CADDY_CONFIG" <<EOF_CADDY
header_up X-Forwarded-For {http.request.header.X-Forwarded-For}
header_up X-Forwarded-Proto {http.request.header.X-Forwarded-Proto}
}
}
}
handle /health {
rewrite * /ping
reverse_proxy localhost:8080 {
trusted_proxies private_ranges
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}
@@ -1088,6 +1045,7 @@ cat > "$CADDY_CONFIG" <<EOF_CADDY
handle /ping {
reverse_proxy localhost:8080 {
trusted_proxies private_ranges
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}
@@ -1096,12 +1054,19 @@ cat > "$CADDY_CONFIG" <<EOF_CADDY
}
handle /public/* {
reverse_proxy localhost:8080
reverse_proxy localhost:8080 {
trusted_proxies private_ranges
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}
}
}
@user_api path_regexp user_api ^/users($|/.*)
handle @user_api {
reverse_proxy localhost:8080 {
trusted_proxies private_ranges
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}
@@ -1110,12 +1075,12 @@ cat > "$CADDY_CONFIG" <<EOF_CADDY
}
@museum_api_get {
host ${PHOTOS_HOST}
method GET HEAD
path_regexp museum_api_get ^/(admin|authenticator|billing|cast|collections|custom-domain|diff|discount|email-hash|emails-from-hashes|emergency-contacts|family|file|file-link|files|fire|info|job|mail|metrics|multipart-upload-urls|offers|options|pass-info|passkeys|public-collection|push|queue|remote-store|storage-bonus|thumbnail|trash|unknown-api|upload-urls|user|user-entity|verify-password)(/|$)
}
handle @museum_api_get {
reverse_proxy localhost:8080 {
trusted_proxies private_ranges
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}
@@ -1124,12 +1089,12 @@ cat > "$CADDY_CONFIG" <<EOF_CADDY
}
@write_methods {
host ${PHOTOS_HOST}
not method GET
not method HEAD
}
handle @write_methods {
reverse_proxy localhost:8080 {
trusted_proxies private_ranges
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}
@@ -1137,7 +1102,7 @@ cat > "$CADDY_CONFIG" <<EOF_CADDY
}
}
@photos_host host ${PHOTOS_HOST}
@photos_host host ${PHOTOS_HOST_MATCHERS}
handle @photos_host {
root * $WEB_RUNTIME_DIR/photos
try_files {path} {path}/index.html {path}.html index.html
@@ -1179,6 +1144,27 @@ cat > "$CADDY_CONFIG" <<EOF_CADDY
file_server
}
@share_host host ${SHARE_HOST}
handle @share_host {
root * $WEB_RUNTIME_DIR/share
try_files {path} {path}/index.html {path}.html index.html
file_server
}
@embed_host host ${EMBED_HOST}
handle @embed_host {
root * $WEB_RUNTIME_DIR/embed
try_files {path} {path}/index.html {path}.html index.html
file_server
}
@payments_host host ${PAYMENTS_HOST}
handle @payments_host {
root * $WEB_RUNTIME_DIR/payments
try_files {path} {path}/index.html {path}.html index.html
file_server
}
handle {
respond "Not Found" 404
}
@@ -1220,11 +1206,7 @@ cat > "$CADDY_CONFIG" <<EOF_CADDY
respond 204
}
@api_photos {
host ${PHOTOS_HOST}
path /api/*
}
handle @api_photos {
handle_path /api/* {
@api_cors_path header Origin *
header @api_cors_path {
Access-Control-Allow-Origin {http.request.header.Origin}
@@ -1241,12 +1223,12 @@ cat > "$CADDY_CONFIG" <<EOF_CADDY
header_up X-Forwarded-For {http.request.header.X-Forwarded-For}
header_up X-Forwarded-Proto {http.request.header.X-Forwarded-Proto}
}
}
}
handle /health {
rewrite * /ping
reverse_proxy localhost:8080 {
trusted_proxies private_ranges
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}
@@ -1256,6 +1238,7 @@ cat > "$CADDY_CONFIG" <<EOF_CADDY
handle /ping {
reverse_proxy localhost:8080 {
trusted_proxies private_ranges
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}
@@ -1264,12 +1247,19 @@ cat > "$CADDY_CONFIG" <<EOF_CADDY
}
handle /public/* {
reverse_proxy localhost:8080
reverse_proxy localhost:8080 {
trusted_proxies private_ranges
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}
}
}
@user_api_path path_regexp user_api_path ^/users($|/.*)
handle @user_api_path {
reverse_proxy localhost:8080 {
trusted_proxies private_ranges
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}
@@ -1278,12 +1268,12 @@ cat > "$CADDY_CONFIG" <<EOF_CADDY
}
@museum_api_get_path {
host ${PHOTOS_HOST}
method GET HEAD
path_regexp museum_api_get_path ^/(admin|authenticator|billing|cast|collections|custom-domain|diff|discount|email-hash|emails-from-hashes|emergency-contacts|family|file|file-link|files|fire|info|job|mail|metrics|multipart-upload-urls|offers|options|pass-info|passkeys|public-collection|push|queue|remote-store|storage-bonus|thumbnail|trash|unknown-api|upload-urls|user|user-entity|verify-password)(/|$)
}
handle @museum_api_get_path {
reverse_proxy localhost:8080 {
trusted_proxies private_ranges
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}
@@ -1292,12 +1282,12 @@ cat > "$CADDY_CONFIG" <<EOF_CADDY
}
@write_methods_path {
host ${PHOTOS_HOST}
not method GET
not method HEAD
}
handle @write_methods_path {
reverse_proxy localhost:8080 {
trusted_proxies private_ranges
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}
@@ -1307,7 +1297,7 @@ cat > "$CADDY_CONFIG" <<EOF_CADDY
handle /_next/* {
root * $WEB_RUNTIME_DIR
try_files {path} auth{path} accounts{path} photos{path} cast{path} albums{path} family{path}
try_files {path} auth{path} accounts{path} photos{path} cast{path} albums{path} family{path} share{path} embed{path} payments{path}
file_server
}
@@ -1346,6 +1336,24 @@ cat > "$CADDY_CONFIG" <<EOF_CADDY
file_server
}
handle /share/* {
root * $WEB_RUNTIME_DIR
try_files {path} {path}/index.html /share/index.html
file_server
}
handle /embed/* {
root * $WEB_RUNTIME_DIR
try_files {path} {path}/index.html /embed/index.html
file_server
}
handle /payments/* {
root * $WEB_RUNTIME_DIR
try_files {path} {path}/index.html /payments/index.html
file_server
}
handle /photos/* {
root * $WEB_RUNTIME_DIR
try_files {path} {path}/index.html /photos/index.html