From 611c498d375375601d7ed225f77260e91d96bbef Mon Sep 17 00:00:00 2001 From: Kyle Anderson Date: Tue, 12 Aug 2025 13:53:55 -0700 Subject: [PATCH] Ente: Initial package add for the Photo Manager Ente is an encrypted self-hosted photo management app. This packages it natively. It depends on Minio object storage and Postgres. Minio is already a syno package, we can use that. Synology NASs come with Postgres, so the readme has instructions on how to just use that, but you could connect it to any postgres you wanted to. Fixes #6305. Relates to https://github.com/ente-io/ente/discussions/4057. --- cross/ente-web/Makefile | 31 ++++ cross/ente-web/PLIST | 1 + cross/ente-web/digests | 3 + cross/ente/Makefile | 46 +++++ cross/ente/PLIST | 2 + cross/ente/digests | 3 + spk/ente/Makefile | 49 +++++ spk/ente/README.md | 88 +++++++++ spk/ente/src/app/help/enu/index.html | 100 +++++++++++ spk/ente/src/ente.png | Bin 0 -> 4716 bytes spk/ente/src/museum.yaml | 97 ++++++++++ spk/ente/src/service-setup.sh | 257 +++++++++++++++++++++++++++ spk/ente/src/wizard/install_uifile | 18 ++ 13 files changed, 695 insertions(+) create mode 100644 cross/ente-web/Makefile create mode 100644 cross/ente-web/PLIST create mode 100644 cross/ente-web/digests create mode 100644 cross/ente/Makefile create mode 100644 cross/ente/PLIST create mode 100644 cross/ente/digests create mode 100644 spk/ente/Makefile create mode 100644 spk/ente/README.md create mode 100644 spk/ente/src/app/help/enu/index.html create mode 100644 spk/ente/src/ente.png create mode 100644 spk/ente/src/museum.yaml create mode 100644 spk/ente/src/service-setup.sh create mode 100644 spk/ente/src/wizard/install_uifile diff --git a/cross/ente-web/Makefile b/cross/ente-web/Makefile new file mode 100644 index 00000000000..0356a9724a5 --- /dev/null +++ b/cross/ente-web/Makefile @@ -0,0 +1,31 @@ +PKG_NAME = ente-web +PKG_VERS = 1.7.14 +PKG_EXT = tar.gz +PKG_DIST_NAME = photosd-v$(PKG_VERS).$(PKG_EXT) +PKG_DIST_SITE = https://github.com/ente-io/ente/archive +PKG_DIST_FILE = $(PKG_NAME)-$(PKG_VERS).$(PKG_EXT) +PKG_DIR = ente-photosd-v$(PKG_VERS) + +BUILD_DEPENDS = native/nodejs + +HOMEPAGE = https://ente.io +COMMENT = Ente Photos web frontend - self-hosted photo storage and sharing +LICENSE = AGPL-3.0 + +INSTALL_TARGET = ente_web_install + +include ../../mk/spksrc.install-resources.mk + +ENV += NPM_CONFIG_USER=root +PATH := $(WORK_DIR)/../../../native/nodejs/work-native/node/bin:$(PATH) + +.PHONY: ente_web_install +ente_web_install: + @$(MSG) "Installing yarn globally" + cd $(WORK_DIR)/$(PKG_DIR)/web && PATH=$(PATH) npm install -g yarn + @$(MSG) "Building Ente Photos web app" + cd $(WORK_DIR)/$(PKG_DIR)/web && PATH=$(PATH) yarn install --frozen-lockfile + cd $(WORK_DIR)/$(PKG_DIR)/web && PATH=$(PATH) yarn build:photos + @$(MSG) "Installing Ente Photos web app" + install -m 755 -d $(STAGING_INSTALL_PREFIX)/web + cp -R $(WORK_DIR)/$(PKG_DIR)/web/apps/photos/out/* $(STAGING_INSTALL_PREFIX)/web/ \ No newline at end of file diff --git a/cross/ente-web/PLIST b/cross/ente-web/PLIST new file mode 100644 index 00000000000..8edb7d6f6d6 --- /dev/null +++ b/cross/ente-web/PLIST @@ -0,0 +1 @@ +web:web \ No newline at end of file diff --git a/cross/ente-web/digests b/cross/ente-web/digests new file mode 100644 index 00000000000..76ec4631455 --- /dev/null +++ b/cross/ente-web/digests @@ -0,0 +1,3 @@ +ente-web-1.7.14.tar.gz SHA1 c95e584760f338af653fb7d385e90ba4d9b45233 +ente-web-1.7.14.tar.gz SHA256 1212ca299767b5143fd8d0d625b8985af49c2ac270de08c5e74a075117421035 +ente-web-1.7.14.tar.gz MD5 d47480510a7622be973361c2995201dd \ No newline at end of file diff --git a/cross/ente/Makefile b/cross/ente/Makefile new file mode 100644 index 00000000000..4a9f8c72269 --- /dev/null +++ b/cross/ente/Makefile @@ -0,0 +1,46 @@ +PKG_NAME = ente +PKG_VERS = 1.7.14 +PKG_EXT = tar.gz +PKG_DIST_NAME = photosd-v$(PKG_VERS).$(PKG_EXT) +PKG_DIST_SITE = https://github.com/ente-io/ente/archive +PKG_DIST_FILE = $(PKG_NAME)-$(PKG_VERS).$(PKG_EXT) +PKG_DIR = $(PKG_NAME)-photosd-v$(PKG_VERS) + +UNSUPPORTED_ARCHS = $(ARMv5_ARCHS) + +DEPENDS = cross/libsodium +BUILD_DEPENDS = native/go + +HOMEPAGE = https://ente.io/ +COMMENT = End-to-end encrypted platform for photos and authenticators +LICENSE = AGPLv3 + +CGO_ENABLED = 1 +COMPILE_TARGET = ente_compile_target +INSTALL_TARGET = ente_install_target + +# Go source is in server subdirectory + +export EXTRA_GOFLAGS=-buildvcs=false + +include ../../mk/spksrc.cross-go.mk + +ENV += CGO_ENABLED=1 +ENV += CGO_CFLAGS=-I$(STAGING_INSTALL_PREFIX)/include +ENV += CGO_LDFLAGS=-L$(STAGING_INSTALL_PREFIX)/lib + +.PHONY: ente_compile_target +ente_compile_target: + @cd $(WORK_DIR)/$(PKG_DIR)/server && env $(ENV) go build -o ../museum cmd/museum/main.go + +.PHONY: ente_install_target +ente_install_target: + @install -m 755 -d $(STAGING_INSTALL_PREFIX)/bin + @install -m 755 -d $(STAGING_INSTALL_PREFIX)/share/server + @install -m 755 $(WORK_DIR)/$(PKG_DIR)/museum $(STAGING_INSTALL_PREFIX)/bin/ + @cp -r $(WORK_DIR)/$(PKG_DIR)/server/configurations $(STAGING_INSTALL_PREFIX)/share/server/ + @cp -r $(WORK_DIR)/$(PKG_DIR)/server/migrations $(STAGING_INSTALL_PREFIX)/share/server/ + @cp -r $(WORK_DIR)/$(PKG_DIR)/server/mail-templates $(STAGING_INSTALL_PREFIX)/share/server/ + @cp -r $(WORK_DIR)/$(PKG_DIR)/server/web-templates $(STAGING_INSTALL_PREFIX)/share/server/ + @echo "Patching migrations for PostgreSQL transaction limitations" + @find $(STAGING_INSTALL_PREFIX)/share/server/migrations/ -name "*.up.sql" -exec sed -i '/ALTER TYPE.*ADD VALUE/d' {} \; diff --git a/cross/ente/PLIST b/cross/ente/PLIST new file mode 100644 index 00000000000..98de1b62c5c --- /dev/null +++ b/cross/ente/PLIST @@ -0,0 +1,2 @@ +bin:bin/museum +share:share/server \ No newline at end of file diff --git a/cross/ente/digests b/cross/ente/digests new file mode 100644 index 00000000000..8958423e111 --- /dev/null +++ b/cross/ente/digests @@ -0,0 +1,3 @@ +ente-1.7.14.tar.gz SHA1 c95e584760f338af653fb7d385e90ba4d9b45233 +ente-1.7.14.tar.gz SHA256 1212ca299767b5143fd8d0d625b8985af49c2ac270de08c5e74a075117421035 +ente-1.7.14.tar.gz MD5 d47480510a7622be973361c2995201dd diff --git a/spk/ente/Makefile b/spk/ente/Makefile new file mode 100644 index 00000000000..0cb8d7c5f51 --- /dev/null +++ b/spk/ente/Makefile @@ -0,0 +1,49 @@ +SPK_NAME = ente +SPK_VERS = 1.7.14 +SPK_REV = 1 +SPK_ICON = src/ente.png + +DEPENDS = cross/ente cross/ente-web + +SPK_DEPENDS = "minio" + +UNSUPPORTED_ARCHS = $(32bit_ARCHS) $(ARMv5_ARCHS) + +MAINTAINER = SynoCommunity +DESCRIPTION = "End-to-end encrypted platform for photos and authenticators. Self-hosted alternative to Google Photos with privacy-first design." +DISPLAY_NAME = Ente +CHANGELOG = "Initial release of Ente server v1.7.14" +HOMEPAGE = https://ente.io +HELPURL = https://help.ente.io/self-hosting +SUPPORTURL = https://github.com/ente-io/ente/discussions + +LICENSE = AGPLv3 +LICENSE_FILE = $(WORK_DIR)/$(SPK_NAME)-photosd-v$(SPK_VERS)/LICENSE + +WIZARDS_DIR = src/wizard/ + +# 'auto' reserved value grabs SPK_NAME +SERVICE_USER = auto +SERVICE_SETUP = src/service-setup.sh +STARTABLE = yes + +# Service configuration +SERVICE_PORT = 8097 +SERVICE_PORT_TITLE = Ente (HTTP) + +# Admin link +ADMIN_PORT = $(SERVICE_PORT) + +POST_STRIP_TARGET = ente_extra_install + +include ../../mk/spksrc.spk.mk + +.PHONY: ente_extra_install +ente_extra_install: + @$(MSG) "Install configuration template" + @install -m 755 -d $(STAGING_DIR)/var + @install -m 644 src/museum.yaml $(STAGING_DIR)/var/museum.yaml + @$(MSG) "Install server configurations from cross/ente" + @if [ -d $(WORK_DIR)/install/$(INSTALL_PREFIX)/share ]; then \ + cp -r $(WORK_DIR)/install/$(INSTALL_PREFIX)/share $(STAGING_DIR)/; \ + fi diff --git a/spk/ente/README.md b/spk/ente/README.md new file mode 100644 index 00000000000..15f8c333e63 --- /dev/null +++ b/spk/ente/README.md @@ -0,0 +1,88 @@ +# Ente for Synology NAS + +End-to-end encrypted platform for photos. +Self-hosted alternative to Google Photos with privacy-first design. + +## Prerequisites + +**Important:** This package requires manual setup of external dependencies. + +### 1. PostgreSQL Database Setup +Ente requires PostgreSQL. Use the built-in PostgreSQL on your Synology NAS: + +```bash +# SSH into your Synology NAS as admin +sudo -u postgres createdb sc-ente +sudo -u postgres psql -c "GRANT ALL ON DATABASE \"sc-ente\" TO \"sc-ente\";" +``` + +**Note:** This creates a database named `sc-ente` that matches the service user name, using PostgreSQL's secure peer authentication (no passwords required). + +### 2. MinIO Storage Setup +1. MinIO will be automatically installed as a dependency +2. Access MinIO web interface at `http://your-nas-ip:9001` +3. Login with default credentials: username=`minioadmin`, password=`minioadmin` +4. **Create a new bucket named `ente-data`** (this must be done manually) +5. Set the bucket policy to allow public read access if needed + +## Installation + +1. **Set up PostgreSQL first** (see prerequisites above) +2. **Set up MinIO bucket** (see prerequisites above) +3. Install ente package through Package Center +4. **The web interface will be available on port 8097** +5. **Security keys are automatically generated** during installation +6. **Edit database credentials** at `/var/packages/ente/var/work/credentials.yaml` + +## Post-Installation Configuration + +### 1. Database Configuration + +Database connection is automatically configured. + +- Uses PostgreSQL Unix socket authentication +- No manual credentials.yaml editing required +- Database: `sc-ente`, User: `sc-ente` (matches service user) +- No passwords needed (secure peer authentication) + +### 2. Security Keys + +Security keys are automatically generated during installation! + +- Fresh cryptographic keys are created for each installation +- No manual key generation needed +- Keys are securely stored in `/var/packages/ente/var/museum.yaml` + +### 3. Database Schema Setup + +The museum binary will automatically create the necessary database schema on first run when you start the service. + +## Usage + +1. **Start the service** in Package Center after configuration +2. **Access the web interface** at: `http://your-nas-ip:8097` +3. **Create an account** and start uploading photos +4. **Use official Ente mobile apps** and configure them to connect to your NAS + +## Important Security Notes + +- **Security keys are automatically generated** for each installation +- **Database uses secure Unix socket authentication** (no passwords) +- **Consider enabling HTTPS** for production deployments +- **Regularly backup** your PostgreSQL database and MinIO storage +- **Keep the package updated** for security fixes + +## Troubleshooting + +- **Check service logs** at `/var/packages/ente/var/data/museum.log` +- **Verify database connectivity** using the credentials in credentials.yaml +- **Ensure MinIO service is running** and accessible +- **Verify storage bucket** `ente-data` exists in MinIO interface +- **Check firewall settings** for port 8097 +- **Ensure PostgreSQL database** exists and user has proper permissions + +## Support + +- Official Ente documentation: https://help.ente.io/self-hosting +- SynoCommunity forums: https://github.com/SynoCommunity/spksrc/discussions +- Ente GitHub: https://github.com/ente-io/ente diff --git a/spk/ente/src/app/help/enu/index.html b/spk/ente/src/app/help/enu/index.html new file mode 100644 index 00000000000..6e886f10f7c --- /dev/null +++ b/spk/ente/src/app/help/enu/index.html @@ -0,0 +1,100 @@ + + + + Ente + + + +

Ente

+

Ente is an end-to-end encrypted platform for + photos and authenticators. It provides a self-hosted alternative to Google Photos + with privacy-first design, allowing you to store and sync your photos securely + on your own NAS.

+ +

Prerequisites

+

⚠️ Important: Ente requires manual setup of PostgreSQL and MinIO before use.

+

You must create a PostgreSQL database first:

+
    +
  1. SSH into your NAS as admin user
  2. +
  3. Run this one-liner: +
    sudo -u postgres createdb sc-ente && sudo -u postgres psql -c "GRANT ALL ON DATABASE \"sc-ente\" TO \"sc-ente\";" +
  4. +
+

Note: This creates a database named sc-ente that matches the service user name, using PostgreSQL's secure peer authentication (no passwords required).

+ +

Installation

+

Once you have set up PostgreSQL:

+
    +
  1. Install Ente through Package Center
  2. +
  3. MinIO will be automatically installed as a dependency
  4. +
  5. The service will be available on port 8097
  6. +
  7. Security keys will be automatically generated during installation
  8. +
+

After installation, you'll need to manually create the MinIO storage bucket.

+ +

Configuration

+

Good news: Most configuration is automatic!

+ +

Database Settings

+

Automatic: Database connection is pre-configured using Unix socket authentication.

+ + +

Security Keys

+

Automatic: Security keys are automatically generated during installation!

+ + +

Usage

+

After configuration:

+
    +
  1. Start the service in Package Center
  2. +
  3. Access the web interface at: http://your-nas-ip:8097
  4. +
  5. Create an account and start uploading photos
  6. +
  7. Use official Ente mobile apps and configure them to connect to your NAS
  8. +
+ +

Storage Management

+

Ente uses MinIO for S3-compatible local storage:

+
    +
  1. Access MinIO web interface: http://your-nas-ip:9001
  2. +
  3. Login with default credentials: username minioadmin, password minioadmin
  4. +
  5. Create a bucket named ente-data
  6. +
  7. Set the bucket policy to allow public read access if needed
  8. +
+

Photos will be stored in the ente-data bucket, and you can monitor storage usage through the MinIO interface.

+ +

Troubleshooting

+

If you experience issues:

+ + +

Security Notes

+ + +

Support

+

For additional help:

+ + + diff --git a/spk/ente/src/ente.png b/spk/ente/src/ente.png new file mode 100644 index 0000000000000000000000000000000000000000..8a84dfb18ae2ecf4287284f61a1dff859561efb4 GIT binary patch literal 4716 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 literal 0 HcmV?d00001 diff --git a/spk/ente/src/museum.yaml b/spk/ente/src/museum.yaml new file mode 100644 index 00000000000..94486f10c8c --- /dev/null +++ b/spk/ente/src/museum.yaml @@ -0,0 +1,97 @@ +# Ente Museum Configuration for Synology NAS +# Based on official configuration structure from https://help.ente.io/self-hosting/installation/config + +# HTTP server configuration +http: + bind-address: "127.0.0.1" + # Port will be set in credentials.yaml based on installation wizard + +# S3 configuration for object storage +s3: + # Enable local bucket mode for MinIO/filesystem storage + are_local_buckets: true + use_path_style_urls: true + + # Primary storage bucket - MinIO configuration + # Note: NAS_IP will be replaced with your NAS IP during installation + b2-eu-cen: + key: minioadmin + secret: minioadmin + endpoint: http://ENTE_NAS_IP_PLACEHOLDER:9000 + region: us-east-1 + bucket: ente-data + +# Security keys (will be randomly generated during installation) +key: + encryption: "ENTE_ENCRYPTION_KEY_PLACEHOLDER" + hash: "ENTE_HASH_KEY_PLACEHOLDER" + +# JWT configuration for authentication +jwt: + secret: "ENTE_JWT_SECRET_PLACEHOLDER" + +# Email configuration (optional - for user notifications) +# smtp: +# host: "smtp.gmail.com" +# port: 587 +# username: "" +# password: "" +# from: "photos@yourdomain.com" + +# WebP conversion settings +webp: + # Enable WebP conversion for better compression + enabled: true + # Quality setting (0-100) + quality: 75 + +# Background job configuration +jobs: + # Disable cron-based cleanup jobs for small installations + cron: + skip: true + # Enable background processing + background: + enabled: true + +# Machine learning features (optional) +ml: + # Disable ML features to reduce resource usage + enabled: false + +# Replication settings (for multi-instance setups) +replication: + enabled: false + +# Internal server settings +internal: + # Enable logging for debugging + silent: false + # Allow new user registration + disable-registration: false + # Maximum file size (in bytes) - 100MB default + max-file-size: 104857600 + +# Rate limiting +rate-limit: + # Requests per minute per IP + requests-per-minute: 100 + +# CORS settings for web interface +cors: + # Allow requests from web interface + allowed-origins: + - "https://localhost" + - "http://localhost" + # Allow credentials + allow-credentials: true + +# Feature flags +feature-flags: + # Enable two-factor authentication + two-factor: true + # Enable face recognition (requires ML) + face-recognition: false + # Enable magic links for login + magic-links: true + diff --git a/spk/ente/src/service-setup.sh b/spk/ente/src/service-setup.sh new file mode 100644 index 00000000000..15e6ae05321 --- /dev/null +++ b/spk/ente/src/service-setup.sh @@ -0,0 +1,257 @@ +MUSEUM="${SYNOPKG_PKGDEST}/bin/museum" +CONFIG_FILE="${SYNOPKG_PKGVAR}/museum.yaml" +DATA_DIR="${SYNOPKG_PKGVAR}/data" +NGINX_CONFIG="${SYNOPKG_PKGVAR}/nginx.conf" + +if [ $SYNOPKG_DSM_VERSION_MAJOR -lt 7 ]; then + SYNOPKG_PKGHOME="${SYNOPKG_PKGVAR}" +fi + +WORK_DIR="${SYNOPKG_PKGVAR}/work" + +# Set group based on DSM version +if [ ${SYNOPKG_DSM_VERSION_MAJOR} -ge 7 ]; then + GROUP="synocommunity" +else + GROUP="sc-ente" +fi + +if [ ${SYNOPKG_DSM_VERSION_MAJOR} -lt 7 ]; then + ENV="HOME=${SYNOPKG_PKGHOME} LD_LIBRARY_PATH=${SYNOPKG_PKGDEST}/lib GIN_MODE=release" +else + ENV="HOME=${SYNOPKG_PKGHOME} LD_LIBRARY_PATH=${SYNOPKG_PKGDEST}/lib GIN_MODE=release" +fi + +SVC_CWD="${WORK_DIR}" +# Start both museum server and nginx web server +SERVICE_COMMAND="env ${ENV} ${MUSEUM} --config ${CONFIG_FILE} +nginx -c ${NGINX_CONFIG}" +SVC_BACKGROUND=y +SVC_WRITE_PID=y +PID_FILE="${SYNOPKG_PKGVAR}/ente.pid" + +generate_random_keys () +{ + # Generate cryptographically secure keys matching Ente's requirements + # - Encryption: 32 bytes (crypto_secretbox_KEYBYTES) -> base64 standard encoding + # - Hash: 64 bytes (crypto_generichash_KEYBYTES_MAX) -> base64 standard encoding + # - JWT: 32 bytes (crypto_secretbox_KEYBYTES) -> base64 URL encoding for JWT spec + ENCRYPTION_KEY=$(openssl rand -base64 32) + HASH_KEY=$(openssl rand -base64 64) + # Use base64url encoding for JWT (replace + with -, / with _, remove padding =) + JWT_SECRET=$(openssl rand -base64 32 | tr '+/' '-_' | tr -d '=') +} + +service_postinst () +{ + if [ "${SYNOPKG_PKG_STATUS}" == "INSTALL" ]; then + # Get NAS IP address for configuration + IP=$(ip route get 1 2>/dev/null | awk '{print $(NF);exit}' || echo "localhost") + + # Create data directory + mkdir -p "${DATA_DIR}" + + # Set up initial configuration if config file doesn't exist + if [ ! -f "${CONFIG_FILE}" ]; then + # Copy template configuration and update with detected IP for fresh installs only + cp "${SYNOPKG_PKGDEST}/var/museum.yaml" "${CONFIG_FILE}" + # Replace NAS IP placeholder with detected IP (fresh installs only) + sed -i "s|ENTE_NAS_IP_PLACEHOLDER|${IP}|g" "${CONFIG_FILE}" + + # Generate fresh security keys for production use + generate_random_keys + + # Replace placeholder keys with generated ones + sed -i "s|ENTE_ENCRYPTION_KEY_PLACEHOLDER|${ENCRYPTION_KEY}|g" "${CONFIG_FILE}" + sed -i "s|ENTE_HASH_KEY_PLACEHOLDER|${HASH_KEY}|g" "${CONFIG_FILE}" + sed -i "s|ENTE_JWT_SECRET_PLACEHOLDER|${JWT_SECRET}|g" "${CONFIG_FILE}" + + chown ${EFF_USER}:${GROUP} "${CONFIG_FILE}" 2>/dev/null || true + + # Update help documentation with detected IP (fresh installs only) + HELP_FILE="${SYNOPKG_PKGDEST}/app/help/enu/index.html" + if [ -f "${HELP_FILE}" ]; then + sed -i "s|host: localhost|host: ${IP}|g" "${HELP_FILE}" + # Also update any other localhost references in help + sed -i "s|http://localhost:|http://${IP}:|g" "${HELP_FILE}" + fi + fi + + # MinIO bucket must be created manually + + # Create symlinks so museum can find required directories from any working directory + WORK_DIR="${SYNOPKG_PKGVAR}/work" + mkdir -p "${WORK_DIR}" + if [ ! -L "${WORK_DIR}/configurations" ]; then + ln -sf "${SYNOPKG_PKGDEST}/share/server/configurations" "${WORK_DIR}/configurations" + fi + if [ ! -L "${WORK_DIR}/migrations" ]; then + ln -sf "${SYNOPKG_PKGDEST}/share/server/migrations" "${WORK_DIR}/migrations" + fi + if [ ! -L "${WORK_DIR}/mail-templates" ]; then + ln -sf "${SYNOPKG_PKGDEST}/share/server/mail-templates" "${WORK_DIR}/mail-templates" + fi + if [ ! -L "${WORK_DIR}/web-templates" ]; then + ln -sf "${SYNOPKG_PKGDEST}/share/server/web-templates" "${WORK_DIR}/web-templates" + fi + if [ ! -L "${WORK_DIR}/museum.yaml" ]; then + ln -sf "${CONFIG_FILE}" "${WORK_DIR}/museum.yaml" + fi + + # Create credentials.yaml with Synology-specific database settings + # Uses PostgreSQL peer authentication with database name = username + if [ ! -f "${WORK_DIR}/credentials.yaml" ]; then + + cat > "${WORK_DIR}/credentials.yaml" << EOF +# Synology NAS configuration overrides for Ente +# +# This file overrides default settings from local.yaml and museum.yaml +# Config loading order: local.yaml -> credentials.yaml -> museum.yaml +# +# This provides the correct Synology-specific configuration for database, +# HTTP port, logging, and web endpoints. +# Synology NAS database credentials (using Unix socket) +db: + host: /run/postgresql + port: 5432 + user: sc-ente + name: sc-ente + sslmode: disable + +# HTTP configuration override +http: + port: 8080 + +# Log file override +log-file: ${DATA_DIR}/museum.log + +# Web app endpoints override +apps: + public-albums: "http://${IP:-localhost}:8097" +EOF + chown ${EFF_USER}:${GROUP} "${WORK_DIR}/credentials.yaml" 2>/dev/null || true + fi + + # Create nginx configuration for web interface (regenerate on every install) + # Remove old config to ensure we use the latest version + rm -f "${NGINX_CONFIG}" + # Create nginx working directories + mkdir -p "${SYNOPKG_PKGVAR}/nginx/logs" + mkdir -p "${SYNOPKG_PKGVAR}/nginx/client_body_temp" + mkdir -p "${SYNOPKG_PKGVAR}/nginx/proxy_temp" + mkdir -p "${SYNOPKG_PKGVAR}/nginx/fastcgi_temp" + mkdir -p "${SYNOPKG_PKGVAR}/nginx/uwsgi_temp" + mkdir -p "${SYNOPKG_PKGVAR}/nginx/scgi_temp" + + cat > "${NGINX_CONFIG}" << EOF +pid ${SYNOPKG_PKGVAR}/nginx/nginx.pid; +error_log ${SYNOPKG_PKGVAR}/nginx/logs/error.log; + +events { + worker_connections 1024; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + access_log ${SYNOPKG_PKGVAR}/nginx/logs/access.log; + + client_body_temp_path ${SYNOPKG_PKGVAR}/nginx/client_body_temp; + proxy_temp_path ${SYNOPKG_PKGVAR}/nginx/proxy_temp; + fastcgi_temp_path ${SYNOPKG_PKGVAR}/nginx/fastcgi_temp; + uwsgi_temp_path ${SYNOPKG_PKGVAR}/nginx/uwsgi_temp; + scgi_temp_path ${SYNOPKG_PKGVAR}/nginx/scgi_temp; + + sendfile on; + keepalive_timeout 65; + + server { + listen 8097; + server_name _; + + # Root directory for Ente web static files + root /volume1/@appstore/ente/web; + index index.html; + + # Serve static files + location / { + try_files \$uri \$uri/ /index.html; + + # Add CORS headers for API calls + add_header 'Access-Control-Allow-Origin' '*' always; + add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always; + add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-Auth-Token,X-Auth-Access-Token,X-Cast-Access-Token,X-Auth-Access-Token-JWT,X-Client-Package,X-Client-Version' always; + add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range,X-Request-Id' always; + } + + # Proxy API calls to museum server + location /api { + proxy_pass http://127.0.0.1:8080; + proxy_set_header Host \$host; + proxy_set_header X-Real-IP \$remote_addr; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto \$scheme; + + # Handle CORS preflight requests + if (\$request_method = 'OPTIONS') { + add_header 'Access-Control-Allow-Origin' '*'; + add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS'; + add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-Auth-Token,X-Auth-Access-Token,X-Cast-Access-Token,X-Auth-Access-Token-JWT,X-Client-Package,X-Client-Version'; + add_header 'Access-Control-Max-Age' 1728000; + add_header 'Content-Type' 'text/plain; charset=utf-8'; + add_header 'Content-Length' 0; + return 204; + } + } + + # Proxy health check endpoint + location /ping { + proxy_pass http://127.0.0.1:8080; + proxy_set_header Host \$host; + proxy_set_header X-Real-IP \$remote_addr; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto \$scheme; + } + + # Handle Next.js assets + location /_next/ { + expires 1y; + add_header Cache-Control "public, immutable"; + } + + # Handle images and static assets + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { + expires 1y; + add_header Cache-Control "public, immutable"; + } + } +} +EOF + chown ${EFF_USER}:${GROUP} "${NGINX_CONFIG}" 2>/dev/null || true + + # Set permissions (only needed for DSM < 7) + if [ $SYNOPKG_DSM_VERSION_MAJOR -lt 7 ]; then + chown -R ${EFF_USER}:${GROUP} "${SYNOPKG_PKGVAR}" + fi + chmod -R u+rw "${SYNOPKG_PKGVAR}" + fi +} + + +service_restore () +{ + if [ ${SYNOPKG_DSM_VERSION_MAJOR} -lt 7 ]; then + # Make a copy of the new config file before it gets overwritten by restore + [ -f "${CONFIG_FILE}" ] && cp -f "${CONFIG_FILE}" "${TMP_DIR}/museum.yaml.new" + fi +} + +service_poststop () +{ + # Clean up any remaining nginx processes + if [ -f "${NGINX_CONFIG}" ]; then + # Kill any nginx processes using our config file + pkill -f "nginx -c ${NGINX_CONFIG}" 2>/dev/null || true + fi +} \ No newline at end of file diff --git a/spk/ente/src/wizard/install_uifile b/spk/ente/src/wizard/install_uifile new file mode 100644 index 00000000000..47bb12eac86 --- /dev/null +++ b/spk/ente/src/wizard/install_uifile @@ -0,0 +1,18 @@ +[ + { + "step_title": "Ente Configuration", + "items": [ + { + "desc": "⚠️ IMPORTANT: Ente requires manual setup before use:" + }, { + "desc": "1. Create PostgreSQL database 'ente_db'" + }, { + "desc": "2. Create MinIO bucket 'ente-data' via MinIO web interface" + }, { + "desc": "3. The web interface will be available on port 8097 after installation" + }, { + "desc": "4. Check the help documentation for detailed setup instructions" + } + ] + } +] \ No newline at end of file