diff --git a/apps/hermitstash/1.13.21/.env.sample b/apps/hermitstash/1.13.21/.env.sample new file mode 100644 index 000000000..1a1bbdc7e --- /dev/null +++ b/apps/hermitstash/1.13.21/.env.sample @@ -0,0 +1,4 @@ +PANEL_APP_PORT_HTTP=3000 +APP_DATA_DIR=./data +APP_UPLOADS_DIR=./uploads +CONTAINER_NAME= diff --git a/apps/hermitstash/1.13.21/data.yml b/apps/hermitstash/1.13.21/data.yml new file mode 100644 index 000000000..7ec3a1867 --- /dev/null +++ b/apps/hermitstash/1.13.21/data.yml @@ -0,0 +1,51 @@ +additionalProperties: + formFields: + - default: 3000 + edit: true + envKey: PANEL_APP_PORT_HTTP + labelEn: Port + labelZh: 端口 + label: + en: Port + zh: 端口 + zh-Hant: 埠 + ja: ポート + ko: 포트 + ru: Порт + ms: Port + pt-br: Porta + required: true + rule: paramPort + type: number + - default: ./data + edit: true + envKey: APP_DATA_DIR + labelEn: Data Directory + labelZh: 数据目录 + label: + en: Data Directory + zh: 数据目录 + zh-Hant: 資料目錄 + ja: データディレクトリ + ko: 데이터 디렉터리 + ru: Каталог данных + ms: Direktori data + pt-br: Diretório de dados + required: true + type: text + - default: ./uploads + edit: true + envKey: APP_UPLOADS_DIR + labelEn: Uploads Directory + labelZh: 上传目录 + label: + en: Uploads Directory + zh: 上传目录 + zh-Hant: 上傳目錄 + ja: アップロードディレクトリ + ko: 업로드 디렉터리 + ru: Каталог загрузок + ms: Direktori muat naik + pt-br: Diretório de uploads + required: true + type: text diff --git a/apps/hermitstash/1.13.21/data/.gitkeep b/apps/hermitstash/1.13.21/data/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/hermitstash/1.13.21/docker-compose.yml b/apps/hermitstash/1.13.21/docker-compose.yml new file mode 100644 index 000000000..c22930390 --- /dev/null +++ b/apps/hermitstash/1.13.21/docker-compose.yml @@ -0,0 +1,38 @@ +services: + hermitstash: + image: "ghcr.io/dotcoocoo/hermitstash:1.13.21@sha256:03d5183b3242616aca540e914377b713779c65c1a7ddc54f319b9c95e12fd74a" + container_name: ${CONTAINER_NAME} + restart: unless-stopped + init: true + user: "1000:1000" + networks: + - 1panel-network + ports: + - "${PANEL_APP_PORT_HTTP}:3000" + environment: + - NODE_ENV=production + - HERMITSTASH_TMPDIR=/dev/shm + - PORT=3000 + - LOCAL_AUTH=true + - REGISTRATION_OPEN=false + - PUBLIC_UPLOAD=false + - PASSKEY_ENABLED=true + - CA_KEY_SEALED=auto + - TLS_KEY_SEALED=auto + shm_size: 256m + read_only: true + tmpfs: + - /tmp:size=16m,mode=1777 + security_opt: + - no-new-privileges:true + cap_drop: + - ALL + volumes: + - "${APP_DATA_DIR}:/app/data" + - "${APP_UPLOADS_DIR}:/app/uploads" + labels: + createdBy: "Apps" + +networks: + 1panel-network: + external: true diff --git a/apps/hermitstash/1.13.21/scripts/init.sh b/apps/hermitstash/1.13.21/scripts/init.sh new file mode 100755 index 000000000..d1f26584e --- /dev/null +++ b/apps/hermitstash/1.13.21/scripts/init.sh @@ -0,0 +1,67 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)" +ENV_FILE="${ENV_FILE:-$ROOT_DIR/.env}" + +read_env_value() { + local key="$1" + [[ -f "$ENV_FILE" ]] || return 0 + local value + value="$(sed -n "s/^${key}=//p" "$ENV_FILE" | tail -n 1)" + case "$value" in + \"*\") value="${value#\"}"; value="${value%\"}" ;; + \'*\') value="${value#\'}"; value="${value%\'}" ;; + esac + printf '%s\n' "$value" +} + +configured_value() { + local key="$1" + local default_value="$2" + local value="${!key:-}" + if [[ -z "$value" ]]; then + value="$(read_env_value "$key")" + fi + printf '%s\n' "${value:-$default_value}" +} + +prepare_app_path() { + local key="$1" + local default_value="$2" + local raw path + raw="$(configured_value "$key" "$default_value")" + + [[ -n "$raw" ]] || { + printf '%s must not be empty\n' "$key" >&2 + exit 1 + } + if [[ "$raw" = /* ]]; then + printf '%s must be relative to the application version directory\n' "$key" >&2 + exit 1 + fi + + path="$(realpath -m -- "$ROOT_DIR/${raw#./}")" + case "$path" in + "$ROOT_DIR"/*) ;; + *) + printf '%s must remain inside the application version directory\n' "$key" >&2 + exit 1 + ;; + esac + + install -d -m 0700 "$path" + path="$(realpath -e -- "$path")" + case "$path" in + "$ROOT_DIR"/*) ;; + *) + printf '%s resolves outside the application version directory\n' "$key" >&2 + exit 1 + ;; + esac + chmod 0700 "$path" + chown -R --no-dereference 1000:1000 "$path" +} + +prepare_app_path APP_DATA_DIR ./data +prepare_app_path APP_UPLOADS_DIR ./uploads diff --git a/apps/hermitstash/1.13.21/scripts/uninstall.sh b/apps/hermitstash/1.13.21/scripts/uninstall.sh new file mode 100755 index 000000000..6e877466e --- /dev/null +++ b/apps/hermitstash/1.13.21/scripts/uninstall.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +set -euo pipefail diff --git a/apps/hermitstash/1.13.21/scripts/upgrade.sh b/apps/hermitstash/1.13.21/scripts/upgrade.sh new file mode 100755 index 000000000..692e341e2 --- /dev/null +++ b/apps/hermitstash/1.13.21/scripts/upgrade.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -euo pipefail + +"$(dirname "$0")/init.sh" diff --git a/apps/hermitstash/1.13.21/uploads/.gitkeep b/apps/hermitstash/1.13.21/uploads/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/hermitstash/README.md b/apps/hermitstash/README.md new file mode 100644 index 000000000..62bc31256 --- /dev/null +++ b/apps/hermitstash/README.md @@ -0,0 +1,57 @@ +# HermitStash + +## 产品介绍 + +HermitStash 是自托管的加密文件分享服务,使用 ML-KEM-1024 与 P-384 混合密钥协商,并避免在持久化存储中保留明文数据库。 + +## 主要功能 + +- 加密文件上传、分享和访问控制 +- 本地账户、通行密钥与管理界面 +- 加密数据库、密钥及上传文件的持久化存储 + +## 访问说明 + +安装后通过 `http://<服务器 IP>:<端口>` 访问,实际端口以 `PANEL_APP_PORT_HTTP` 为准。默认启用本地认证,同时关闭公开注册和匿名上传。 + +首次启动会为 `admin@hermitstash.com` 生成随机管理员密码。该密码会打印到容器日志,并写入 `APP_DATA_DIR/initial-admin-password.txt`。在仅受信任人员可读取 1Panel 日志和数据目录的环境中获取密码并立即登录,然后完成设置向导、更换管理员邮箱和密码,并配置站点及会话设置。向导完成后,上游会自动删除明文密码文件。在首次设置完成前不要向公网开放端口。 + +## 数据持久化 + +`APP_DATA_DIR` 保存加密数据库、保险库密钥和 TLS 资料,`APP_UPLOADS_DIR` 保存上传内容。两个路径必须位于应用版本目录内;初始化脚本会拒绝绝对路径和目录外路径,并设置为容器要求的 UID/GID `1000:1000`。卸载不会删除这些目录。务必单独备份 `APP_DATA_DIR/vault.key`;该文件丢失会导致已加密数据无法恢复。 + +## 安全与部署风险 + +- 容器采用上游官方 rootless 模式,固定以 UID/GID `1000:1000` 运行,丢弃全部 Linux capabilities,并启用只读根文件系统和 `no-new-privileges`。初始化脚本会在启动前准备绑定目录权限。 +- 首次管理员密码在完成设置前同时存在于容器日志和数据目录中。能读取任一位置的人员可接管初始管理员账户,因此必须限制日志、备份和宿主机目录权限,并尽快完成首次设置。 +- 数据库明文工作副本位于 256 MiB 的 `/dev/shm`。不要移除共享内存配置或将 `HERMITSTASH_TMPDIR` 改为磁盘路径。 +- 固定镜像的 Trivy 扫描未发现 Critical 或 High 漏洞;镜像升级前仍应重新扫描。 + +## Introduction + +HermitStash is a self-hosted encrypted file sharing service using hybrid ML-KEM-1024 and P-384 key agreement while keeping its plaintext database off persistent storage. + +## Features + +- Encrypted file uploads, sharing, and access controls +- Local accounts, passkeys, and an administration interface +- Persistent encrypted database, keys, and uploaded files + +## Usage Notes + +- Access the service at `http://:`. Local authentication is enabled while open registration and anonymous uploads are disabled by default. +- On first boot, retrieve the generated password for `admin@hermitstash.com` from the container logs or `APP_DATA_DIR/initial-admin-password.txt`. Sign in from a trusted network and complete the setup wizard immediately. Upstream removes the plaintext password file after setup. Do not expose the port publicly before this is complete. +- `APP_DATA_DIR` and `APP_UPLOADS_DIR` must remain relative to the application version directory. Back up `APP_DATA_DIR/vault.key`; encrypted data cannot be recovered without it. + +## Security and Deployment Risks + +- The container uses upstream's official rootless mode, runs as UID/GID `1000:1000`, drops all Linux capabilities, and enables a read-only root filesystem plus `no-new-privileges`. The initialization script prepares bind-mount ownership before startup. +- Until setup completes, the generated administrator password is present in both container logs and the data directory. Restrict access to logs, backups, and host paths and finish setup promptly. +- The plaintext working database requires the configured 256 MiB `/dev/shm`; do not move `HERMITSTASH_TMPDIR` to persistent storage. + +## References + +- Project: +- Rootless Docker deployment: +- Threat model: +- License: (AGPL-3.0-or-later) diff --git a/apps/hermitstash/data.yml b/apps/hermitstash/data.yml new file mode 100644 index 000000000..3811d570e --- /dev/null +++ b/apps/hermitstash/data.yml @@ -0,0 +1,30 @@ +name: HermitStash +tags: + - Security +title: 后量子加密文件分享服务 +description: 后量子加密文件分享服务 +additionalProperties: + key: hermitstash + name: HermitStash + tags: + - Security + shortDescZh: 后量子加密文件分享服务 + shortDescEn: A post-quantum encrypted file sharing service + description: + en: A post-quantum encrypted file sharing service + zh: 后量子加密文件分享服务 + zh-Hant: 後量子加密檔案分享服務 + ja: 耐量子暗号化ファイル共有サービス + ko: 양자 내성 암호화 파일 공유 서비스 + ru: Сервис обмена файлами с постквантовым шифрованием + ms: Perkhidmatan perkongsian fail disulitkan pasca-kuantum + pt-br: Serviço de compartilhamento de arquivos com criptografia pós-quântica + type: website + crossVersionUpdate: true + limit: 0 + website: https://hermitstash.com/ + github: https://github.com/dotCooCoo/hermitstash + document: https://github.com/dotCooCoo/hermitstash/blob/main/docker-compose.rootless.yml + architectures: + - amd64 + - arm64 diff --git a/apps/hermitstash/logo.png b/apps/hermitstash/logo.png new file mode 100644 index 000000000..a8f33310c Binary files /dev/null and b/apps/hermitstash/logo.png differ