Compare commits
28 Commits
98b26537a1
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1189ec810d | ||
|
|
a64c28761b | ||
|
|
00433e664f | ||
|
|
e50abcb9a2 | ||
|
|
1d4c57c737 | ||
|
|
58e40897a5 | ||
|
|
95758de781 | ||
|
|
f984184b39 | ||
|
|
37ce044181 | ||
|
|
12537896f2 | ||
|
|
ef00dde487 | ||
|
|
6ff0b1756d | ||
|
|
d39a1d86a9 | ||
|
|
617236558e | ||
|
|
f29b570b82 | ||
|
|
3b7a853c71 | ||
|
|
42c4c1f38f | ||
|
|
1c37a2b930 | ||
|
|
632dea4517 | ||
|
|
8f3a34a277 | ||
|
|
fc9abad56b | ||
|
|
6cf536bc67 | ||
|
|
55808e9afa | ||
|
|
fe7bc72131 | ||
|
|
953ee82a97 | ||
|
|
c9e554c9a8 | ||
|
|
0652dde795 | ||
|
|
5549f03f6e |
@@ -9,21 +9,21 @@ cloudron build \
|
|||||||
--set-build-service builder.docker.due.ren \
|
--set-build-service builder.docker.due.ren \
|
||||||
--build-service-token e3265de06b1d0e7bb38400539012a8433a74c2c96a17955e \
|
--build-service-token e3265de06b1d0e7bb38400539012a8433a74c2c96a17955e \
|
||||||
--set-repository andreasdueren/ente-cloudron \
|
--set-repository andreasdueren/ente-cloudron \
|
||||||
--tag 0.4.5
|
--tag 0.5.3
|
||||||
```
|
```
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
```bash
|
```bash
|
||||||
cloudron install \
|
cloudron install \
|
||||||
--location ente.due.ren \
|
--location ente.due.ren \
|
||||||
--image andreasdueren/ente-cloudron:0.4.5
|
--image andreasdueren/ente-cloudron:0.5.3
|
||||||
```
|
```
|
||||||
|
|
||||||
## After Install
|
## 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.
|
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 Ente’s [object storage guide](https://ente.io/help/self-hosting/administration/object-storage) for example configs.
|
||||||
2. **Subdomains** – In the Cloudron *Domains* tab add aliases for `auth.<app-domain>`, `accounts.<app-domain>`, `cast.<app-domain>`, `albums.<app-domain>` and `family.<app-domain>`. Create matching DNS records pointing at the primary domain (for example, if the app is `ente.cloudron.io`, add `auth.ente.cloudron.io`, `accounts.ente.cloudron.io`, etc. → `ente.cloudron.io`).
|
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:
|
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://<app-host>` (the hostname you chose during install, main UI & uploads)
|
||||||
- `https://accounts.<app-domain>`
|
- `https://accounts.<app-domain>`
|
||||||
- `https://auth.<app-domain>`
|
- `https://auth.<app-domain>`
|
||||||
|
|||||||
73
CHANGELOG.md
73
CHANGELOG.md
@@ -1,5 +1,78 @@
|
|||||||
# Changelog
|
# 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 Museum’s `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)
|
## 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>`
|
* Serve photos UI on the primary hostname and mount other apps on `accounts/auth/cast/albums/family.<app-domain>`
|
||||||
|
|||||||
@@ -7,13 +7,70 @@
|
|||||||
"contactEmail": "contact@ente.io",
|
"contactEmail": "contact@ente.io",
|
||||||
"website": "https://ente.io",
|
"website": "https://ente.io",
|
||||||
"tagline": "Open source, end-to-end encrypted photo backup",
|
"tagline": "Open source, end-to-end encrypted photo backup",
|
||||||
"version": "0.4.5",
|
"version": "0.5.6",
|
||||||
"upstreamVersion": "git-main",
|
"upstreamVersion": "git-main",
|
||||||
"healthCheckPath": "/health",
|
"healthCheckPath": "/health",
|
||||||
"httpPort": 3080,
|
"httpPort": 3080,
|
||||||
"memoryLimit": 1610612736,
|
"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",
|
"postInstallMessage": "file://POSTINSTALL.md",
|
||||||
"multiDomain": true,
|
|
||||||
"addons": {
|
"addons": {
|
||||||
"localstorage": {},
|
"localstorage": {},
|
||||||
"postgresql": {},
|
"postgresql": {},
|
||||||
@@ -25,9 +82,6 @@
|
|||||||
"checklist": {
|
"checklist": {
|
||||||
"configure-object-storage": {
|
"configure-object-storage": {
|
||||||
"message": "Configure your S3-compatible storage in /app/data/config/s3.env before first use."
|
"message": "Configure your S3-compatible storage in /app/data/config/s3.env before first use."
|
||||||
},
|
|
||||||
"configure-subdomains": {
|
|
||||||
"message": "Create DNS records and add Cloudron aliases for accounts., auth., cast., albums. and family. (using the base domain of this app)."
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"icon": "file://logo.png",
|
"icon": "file://logo.png",
|
||||||
|
|||||||
56
Dockerfile
56
Dockerfile
@@ -1,12 +1,28 @@
|
|||||||
# syntax=docker/dockerfile:1
|
# syntax=docker/dockerfile:1
|
||||||
|
|
||||||
ARG ENTE_GIT_REF=main
|
ARG ENTE_GIT_REF=main
|
||||||
|
ARG FAMILIES_GIT_REF=main
|
||||||
|
|
||||||
FROM debian:bookworm AS ente-source
|
FROM debian:bookworm AS ente-source
|
||||||
ARG ENTE_GIT_REF
|
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 && \
|
RUN apt-get update && \
|
||||||
apt-get install -y --no-install-recommends ca-certificates git && \
|
apt-get install -y --no-install-recommends ca-certificates git && \
|
||||||
git clone --depth=1 --branch "${ENTE_GIT_REF}" https://github.com/ente-io/ente.git /src && \
|
git clone --depth=1 --branch "${FAMILIES_GIT_REF}" https://github.com/ente-io/families.git /families && \
|
||||||
rm -rf /var/lib/apt/lists/*
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
FROM golang:1.24-bookworm AS museum-builder
|
FROM golang:1.24-bookworm AS museum-builder
|
||||||
@@ -41,14 +57,17 @@ RUN apt-get update && \
|
|||||||
rm -rf /var/lib/apt/lists/*
|
rm -rf /var/lib/apt/lists/*
|
||||||
RUN corepack enable
|
RUN corepack enable
|
||||||
RUN yarn install --network-timeout 1000000
|
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; \
|
RUN set -e; \
|
||||||
yarn build:photos; \
|
yarn build:photos; \
|
||||||
yarn build:accounts; \
|
yarn build:accounts; \
|
||||||
yarn build:auth; \
|
yarn build:auth; \
|
||||||
yarn build:cast
|
yarn build:cast; \
|
||||||
|
yarn build:share; \
|
||||||
|
yarn build:embed; \
|
||||||
|
yarn build:payments
|
||||||
RUN if [ -d "apps" ]; then \
|
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 \
|
if [ -d "apps/${app}/out" ]; then \
|
||||||
rm -rf "/build/web/${app}"; \
|
rm -rf "/build/web/${app}"; \
|
||||||
mkdir -p "/build/web/${app}"; \
|
mkdir -p "/build/web/${app}"; \
|
||||||
@@ -63,9 +82,26 @@ RUN if [ -d "apps" ]; then \
|
|||||||
printf '<html><body><h1>Ente %s</h1><p>Build output missing.</p></body></html>\n' "${app}" > "/build/web/${app}/index.html"; \
|
printf '<html><body><h1>Ente %s</h1><p>Build output missing.</p></body></html>\n' "${app}" > "/build/web/${app}/index.html"; \
|
||||||
done; \
|
done; \
|
||||||
fi && \
|
fi && \
|
||||||
rm -rf /build/web/albums /build/web/family && \
|
rm -rf /build/web/albums && \
|
||||||
cp -r /build/web/photos /build/web/albums && \
|
cp -r /build/web/photos /build/web/albums
|
||||||
cp -r /build/web/photos /build/web/family
|
|
||||||
|
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
|
FROM cloudron/base:5.0.0@sha256:04fd70dbd8ad6149c19de39e35718e024417c3e01dc9c6637eaf4a41ec4e596c
|
||||||
|
|
||||||
@@ -80,6 +116,7 @@ RUN apt-get update && \
|
|||||||
RUN mkdir -p /app/pkg /app/web "$HOME" && chown -R cloudron:cloudron /app /app/web "$HOME"
|
RUN mkdir -p /app/pkg /app/web "$HOME" && chown -R cloudron:cloudron /app /app/web "$HOME"
|
||||||
|
|
||||||
COPY --from=ente-source /src ${APP_DIR}
|
COPY --from=ente-source /src ${APP_DIR}
|
||||||
|
COPY data ${APP_DIR}/data
|
||||||
RUN rm -rf ${APP_DIR}/.git
|
RUN rm -rf ${APP_DIR}/.git
|
||||||
|
|
||||||
RUN mkdir -p /app/museum-bin
|
RUN mkdir -p /app/museum-bin
|
||||||
@@ -98,7 +135,10 @@ 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/auth /app/web/auth
|
||||||
COPY --from=web-builder /build/web/cast /app/web/cast
|
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/albums /app/web/albums
|
||||||
COPY --from=web-builder /build/web/family /app/web/family
|
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
|
COPY start.sh /app/pkg/start.sh
|
||||||
COPY admin-helper.sh /app/pkg/admin-helper.sh
|
COPY admin-helper.sh /app/pkg/admin-helper.sh
|
||||||
|
|||||||
@@ -5,48 +5,86 @@ Your Ente installation is almost ready!
|
|||||||
Before using Ente, configure an S3-compatible object storage provider:
|
Before using Ente, configure an S3-compatible object storage provider:
|
||||||
|
|
||||||
1. Open the Cloudron dashboard and select your Ente app.
|
1. Open the Cloudron dashboard and select your Ente app.
|
||||||
2. Launch the web terminal.
|
2. Launch the file explorer.
|
||||||
3. Edit `/app/data/config/s3.env` and provide values for **all** required keys:
|
3. Open `/app/data/config/s3.env` and provide values for **all** required keys.
|
||||||
```bash
|
|
||||||
nano /app/data/config/s3.env
|
|
||||||
```
|
|
||||||
4. Save the file and restart the app from the Cloudron dashboard.
|
4. Save the file and restart the app from the Cloudron dashboard.
|
||||||
|
5. (Required for cast/slideshow) Configure your S3 bucket’s 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>
|
||||||
|
|
||||||
Supported variables:
|
# Inspect the current bucket type (usually allPrivate) and capture it
|
||||||
|
BUCKET_TYPE=$(b2 get-bucket ente-due-ren | awk -F'"' '/bucketType/ {print $4}')
|
||||||
|
|
||||||
|
# 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_ENDPOINT` (e.g. `https://<account>.r2.cloudflarestorage.com`)
|
||||||
- `S3_REGION`
|
- `S3_REGION`
|
||||||
- `S3_BUCKET`
|
- `S3_BUCKET`
|
||||||
- `S3_ACCESS_KEY`
|
- `S3_ACCESS_KEY`
|
||||||
- `S3_SECRET_KEY`
|
- `S3_SECRET_KEY`
|
||||||
- `S3_PREFIX` (optional path prefix)
|
- `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 [Ente’s object storage guide](https://ente.io/help/self-hosting/administration/object-storage) for sample layouts and discussion of reliability.
|
||||||
|
|
||||||
## Required: DNS Subdomains
|
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.
|
||||||
|
|
||||||
Ente now serves supporting apps on dedicated hosts. Create DNS records (CNAME or A) and add matching alias domains in Cloudron for:
|
## Required: Secondary Hostnames
|
||||||
|
|
||||||
- `auth.<app-domain>`
|
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.
|
||||||
- `accounts.<app-domain>`
|
|
||||||
- `cast.<app-domain>`
|
|
||||||
- `albums.<app-domain>`
|
|
||||||
- `family.<app-domain>`
|
|
||||||
|
|
||||||
For example, if you installed the app at `ente.cloudron.io`, create records for `auth.ente.cloudron.io`, `accounts.ente.cloudron.io`, etc., all pointing to `ente.cloudron.io`, then add each hostname as an alias in the Cloudron dashboard.
|
|
||||||
|
|
||||||
## Administration
|
## Administration
|
||||||
|
|
||||||
- Use the bundled CLI from the Cloudron web terminal (CLI state lives in `/app/data/cli-data`):
|
- **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 Museum’s 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
|
```bash
|
||||||
cloudron exec --app ente.cloudron.io -- sudo -u cloudron ente --help
|
# authenticate once (enter the OTP you receive by email)
|
||||||
|
sudo -u cloudron ente account add
|
||||||
|
|
||||||
# Whitelist an administrator
|
# inspect available commands
|
||||||
cloudron exec --app ente.cloudron.io -- sudo -u cloudron ente admin user whitelist --email admin@example.com
|
sudo -u cloudron ente --help
|
||||||
|
|
||||||
# Increase a user’s storage allocation (in GB)
|
|
||||||
cloudron exec --app ente.cloudron.io -- sudo -u cloudron ente admin user quota set --email user@example.com --storage-gb 500
|
|
||||||
```
|
```
|
||||||
See the upstream admin guides for further context: [user administration](https://ente.io/help/self-hosting/administration/users) and [CLI reference](https://ente.io/help/self-hosting/administration/cli).
|
After you’re 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).
|
||||||
|
|
||||||
Logs are streamed to the Cloudron dashboard. For deeper inspection use:
|
|
||||||
```bash
|
|
||||||
cloudron logs --app <location> -f
|
|
||||||
```
|
|
||||||
|
|||||||
83
README.md
83
README.md
@@ -55,24 +55,91 @@ The app is configured automatically using Cloudron's environment variables for:
|
|||||||
|
|
||||||
After installing on Cloudron remember to:
|
After installing on Cloudron remember to:
|
||||||
|
|
||||||
1. Open the File Manager for the app, edit `/app/data/config/s3.env` with your object storage endpoint/keys, and restart the app.
|
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 don’t 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:
|
||||||
2. Add alias domains for `auth.<app-domain>`, `accounts.<app-domain>`, `cast.<app-domain>`, `albums.<app-domain>` and `family.<app-domain>` in the Cloudron **Domains** tab. Create matching DNS records pointing to the primary hostname (for example, if you installed at `ente.cloudron.io`, add `auth.ente.cloudron.io`, `accounts.ente.cloudron.io`, etc.).
|
- `S3_ARE_LOCAL_BUCKETS=false` toggles SSL/subdomain-style URLs (`are_local_buckets` in `museum.yaml`); leave it at `true` for MinIO-style setups.
|
||||||
3. Use the bundled Ente CLI for admin tasks via `cloudron exec --app <location> -- sudo -u cloudron ente --help`. The CLI stores its state in `/app/data/cli-data` (exposed inside the container at `/cli-data`) and already trusts your app’s API endpoint. Typical workflows:
|
- `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. Copy‑pasting 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 bucket’s 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 Ente’s 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
|
```bash
|
||||||
# Whitelist an administrator (see https://ente.io/help/self-hosting/administration/users )
|
cloudron exec --app ente.cloudron.io -- bash -lc \
|
||||||
cloudron exec --app ente.cloudron.io -- sudo -u cloudron ente admin user whitelist --email admin@example.com
|
'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'
|
||||||
|
|
||||||
# Increase a user’s storage quota (see https://ente.io/help/self-hosting/administration/cli )
|
cloudron restart --app ente.cloudron.io
|
||||||
cloudron exec --app ente.cloudron.io -- sudo -u cloudron ente admin user quota set --email user@example.com --storage-gb 500
|
|
||||||
|
# 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.
|
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.** Museum’s 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 documentation’s `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
|
## Usage
|
||||||
|
|
||||||
### Web Client
|
### Web Client
|
||||||
|
|
||||||
After installation, you can access the Ente web client at your app's URL. Create the first user and whitelist them as an administrator using the CLI if desired.
|
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
|
### Mobile Apps
|
||||||
|
|
||||||
|
|||||||
186
data/billing/in-testing.json
Normal file
186
data/billing/in-testing.json
Normal 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
data/billing/us-testing.json
Normal file
186
data/billing/us-testing.json
Normal 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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
31
patches/museum-family-link.patch
Normal file
31
patches/museum-family-link.patch
Normal 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)
|
||||||
Reference in New Issue
Block a user