mirror of
https://github.com/okxlin/appstore.git
synced 2026-09-22 16:00:58 +00:00
Add LubeLogger app
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
PANEL_APP_PORT_HTTP=8080
|
||||
LUBELOGGER_ROOT_USERNAME=admin
|
||||
LUBELOGGER_ROOT_PASSWORD=LubeLogger_Admin_2026!
|
||||
TIME_ZONE=Etc/UTC
|
||||
APP_DATA_DIR=./data
|
||||
CONTAINER_NAME=
|
||||
@@ -0,0 +1,86 @@
|
||||
additionalProperties:
|
||||
formFields:
|
||||
- default: 8080
|
||||
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: admin
|
||||
edit: true
|
||||
envKey: LUBELOGGER_ROOT_USERNAME
|
||||
labelEn: Root Username
|
||||
labelZh: 根管理员用户名
|
||||
label:
|
||||
en: Root Username
|
||||
zh: 根管理员用户名
|
||||
zh-Hant: 根管理員使用者名稱
|
||||
ja: ルート管理者ユーザー名
|
||||
ko: 루트 관리자 사용자 이름
|
||||
ru: Имя корневого администратора
|
||||
ms: Nama Pengguna Pentadbir Root
|
||||
pt-br: Nome do Administrador Raiz
|
||||
required: true
|
||||
rule: paramCommon
|
||||
type: text
|
||||
- default: LubeLogger_Admin_2026!
|
||||
edit: true
|
||||
envKey: LUBELOGGER_ROOT_PASSWORD
|
||||
labelEn: Root Password
|
||||
labelZh: 根管理员密码
|
||||
label:
|
||||
en: Root Password
|
||||
zh: 根管理员密码
|
||||
zh-Hant: 根管理員密碼
|
||||
ja: ルート管理者パスワード
|
||||
ko: 루트 관리자 비밀번호
|
||||
ru: Пароль корневого администратора
|
||||
ms: Kata Laluan Pentadbir Root
|
||||
pt-br: Senha do Administrador Raiz
|
||||
random: true
|
||||
required: true
|
||||
rule: paramComplexity
|
||||
type: password
|
||||
- default: Etc/UTC
|
||||
edit: true
|
||||
envKey: TIME_ZONE
|
||||
labelEn: Time Zone
|
||||
labelZh: 时区
|
||||
label:
|
||||
en: Time Zone
|
||||
zh: 时区
|
||||
zh-Hant: 時區
|
||||
ja: タイムゾーン
|
||||
ko: 시간대
|
||||
ru: Часовой пояс
|
||||
ms: Zon Masa
|
||||
pt-br: Fuso Horario
|
||||
required: true
|
||||
type: text
|
||||
- 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: Diretorio de Dados
|
||||
required: true
|
||||
type: text
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
services:
|
||||
lubelogger:
|
||||
image: "ghcr.io/hargata/lubelogger:v1.7.0@sha256:01bdb486af71e641c3ae41499e0412a21f2e04fa31b25c5c6531b42c112938e5"
|
||||
container_name: ${CONTAINER_NAME}
|
||||
restart: unless-stopped
|
||||
init: true
|
||||
user: "1000:1000"
|
||||
networks:
|
||||
- 1panel-network
|
||||
ports:
|
||||
- "${PANEL_APP_PORT_HTTP}:8080"
|
||||
env_file:
|
||||
- path: "${APP_DATA_DIR}/.lubelogger-auth.env"
|
||||
required: false
|
||||
environment:
|
||||
- HOME=/App/data
|
||||
- TZ=${TIME_ZONE}
|
||||
- ASPNETCORE_HTTP_PORTS=8080
|
||||
- Kestrel__EndpointDefaults__Protocols=Http1
|
||||
- DOTNET_SYSTEM_NET_HTTP_SOCKETSHTTPHANDLER_HTTP2SUPPORT=false
|
||||
- LUBELOGGER_LOCALE_OVERRIDE=en_US
|
||||
- LUBELOGGER_LOCALE_DT_OVERRIDE=en_US
|
||||
read_only: true
|
||||
tmpfs:
|
||||
- /tmp:size=64m,mode=1777
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
cap_drop:
|
||||
- ALL
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD-SHELL
|
||||
- >-
|
||||
bash -lc 'exec 3<>/dev/tcp/127.0.0.1/8080; exec 3>&-; exec 3<&-'
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
start_period: 15s
|
||||
retries: 3
|
||||
volumes:
|
||||
- "${APP_DATA_DIR}:/App/data"
|
||||
labels:
|
||||
createdBy: "Apps"
|
||||
|
||||
networks:
|
||||
1panel-network:
|
||||
external: true
|
||||
Executable
+123
@@ -0,0 +1,123 @@
|
||||
#!/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}"
|
||||
}
|
||||
|
||||
reject_control_characters() {
|
||||
local name="$1"
|
||||
local value="$2"
|
||||
if [[ "$value" == *$'\n'* || "$value" == *$'\r'* ]]; then
|
||||
printf '%s must not contain line breaks\n' "$name" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
prepare_lubelogger() {
|
||||
local raw path username password username_hash password_hash auth_file temp_file
|
||||
|
||||
raw="$(configured_value APP_DATA_DIR ./data)"
|
||||
username="$(configured_value LUBELOGGER_ROOT_USERNAME admin)"
|
||||
password="$(configured_value LUBELOGGER_ROOT_PASSWORD '')"
|
||||
|
||||
[[ -n "$raw" ]] || {
|
||||
printf '%s\n' 'APP_DATA_DIR must not be empty' >&2
|
||||
exit 1
|
||||
}
|
||||
if [[ "$raw" = /* ]]; then
|
||||
printf '%s\n' 'APP_DATA_DIR must be relative to the application version directory' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
path="$(realpath -m -- "$ROOT_DIR/${raw#./}")"
|
||||
case "$path" in
|
||||
"$ROOT_DIR"/*) ;;
|
||||
*)
|
||||
printf '%s\n' 'APP_DATA_DIR must remain inside the application version directory' >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
install -d -m 0750 "$path"
|
||||
path="$(realpath -e -- "$path")"
|
||||
case "$path" in
|
||||
"$ROOT_DIR"/*) ;;
|
||||
*)
|
||||
printf '%s\n' 'APP_DATA_DIR resolves outside the application version directory' >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
[[ -n "$username" && ${#username} -le 128 ]] || {
|
||||
printf '%s\n' 'LUBELOGGER_ROOT_USERNAME must contain 1 to 128 characters' >&2
|
||||
exit 1
|
||||
}
|
||||
[[ ${#password} -ge 12 && ${#password} -le 256 ]] || {
|
||||
printf '%s\n' 'LUBELOGGER_ROOT_PASSWORD must contain 12 to 256 characters' >&2
|
||||
exit 1
|
||||
}
|
||||
reject_control_characters LUBELOGGER_ROOT_USERNAME "$username"
|
||||
reject_control_characters LUBELOGGER_ROOT_PASSWORD "$password"
|
||||
|
||||
username_hash="$(printf '%s' "$username" | sha256sum | cut -d ' ' -f 1)"
|
||||
password_hash="$(printf '%s' "$password" | sha256sum | cut -d ' ' -f 1)"
|
||||
[[ "$username_hash" =~ ^[0-9a-f]{64}$ && "$password_hash" =~ ^[0-9a-f]{64}$ ]] || {
|
||||
printf '%s\n' 'Failed to generate LubeLogger credential hashes' >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
auth_file="$path/.lubelogger-auth.env"
|
||||
if [[ -L "$auth_file" ]]; then
|
||||
printf '%s\n' 'LubeLogger authentication file must not be a symbolic link' >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ -e "$auth_file" && ! -f "$auth_file" ]]; then
|
||||
printf '%s\n' 'LubeLogger authentication path must be a regular file' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
umask 077
|
||||
temp_file="$(mktemp "$path/.lubelogger-auth.env.tmp.XXXXXX")"
|
||||
trap 'rm -f -- "${temp_file:-}"' EXIT
|
||||
printf '%s\n' \
|
||||
'EnableAuth=true' \
|
||||
"UserNameHash=$username_hash" \
|
||||
"UserPasswordHash=$password_hash" \
|
||||
'DisableRegistration=true' \
|
||||
'LUBELOGGER_OPEN_REGISTRATION=false' >"$temp_file"
|
||||
chmod 0600 "$temp_file"
|
||||
chown 1000:1000 "$temp_file"
|
||||
mv -f -- "$temp_file" "$auth_file"
|
||||
trap - EXIT
|
||||
|
||||
chown 1000:1000 "$path"
|
||||
chmod 0750 "$path"
|
||||
[[ "$(stat -c '%a' -- "$auth_file")" = 600 ]] || {
|
||||
printf '%s\n' 'LubeLogger authentication file permissions must be 0600' >&2
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
prepare_lubelogger
|
||||
Executable
+2
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
docker-compose down --volumes
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
"$(dirname "$0")/init.sh"
|
||||
@@ -0,0 +1,71 @@
|
||||
# LubeLogger
|
||||
|
||||
## 产品介绍
|
||||
|
||||
LubeLogger 是一个自托管的车辆管理工具,用于记录车辆保养、维修、加油、里程、提醒、升级、税费、碰撞和相关文档。
|
||||
|
||||
## 主要功能
|
||||
|
||||
- 管理多辆车辆及其里程、燃油和费用记录
|
||||
- 维护保养计划、提醒和历史记录
|
||||
- 保存车辆图片、票据和其他文档
|
||||
- 支持 CSV 导入导出、报表和可选的通知集成
|
||||
|
||||
## 访问说明
|
||||
|
||||
安装后通过 `http://<服务器 IP>:<端口>` 访问,并使用安装时设置的根管理员用户名和密码登录。安装脚本只把凭据的 SHA-256 哈希传给应用,默认启用认证并关闭开放注册和邀请注册页面。
|
||||
|
||||
上游根用户认证使用普通 SHA-256,而不是专用密码哈希算法;必须保留 1Panel 自动生成的高强度随机密码,不要使用短密码或复用密码。LubeLogger 1.7.0 的登录接口没有请求限速,认证 Cookie 也没有显式设置 `Secure`、`HttpOnly` 或 `SameSite`。明文 HTTP 端口只适合可信局域网;公网访问必须使用可信 HTTPS 反向代理、阻止公网直接访问应用端口,并在代理层增加登录限速。
|
||||
|
||||
## 数据持久化
|
||||
|
||||
`APP_DATA_DIR` 挂载到 `/App/data`,保存 LiteDB 数据库、图片、文档、配置和会话 DataProtection 密钥。该路径必须位于应用版本目录内,默认值为 `./data`;初始化脚本拒绝绝对路径、目录逃逸和认证文件符号链接,并把目录交给 UID/GID `1000:1000`。卸载脚本不会删除绑定目录中的用户数据,升级或迁移前仍应单独备份。
|
||||
|
||||
## 安全与漏洞说明
|
||||
|
||||
- 容器以 UID/GID `1000:1000` 运行,根文件系统只读,丢弃全部 Linux capabilities,并启用 `no-new-privileges`;CPU、内存和进程上限由 1Panel 的应用资源设置统一管理。应用只监听内部明文 HTTP/1;TLS 应由 1Panel 或其他可信反向代理终止。可选 WebHook、OIDC、SMTP 和通知集成默认未配置,包内同时禁用 .NET HTTP 客户端的 HTTP/2 支持。
|
||||
- 对固定镜像执行的 2026-07-28 Trivy 扫描发现 `0` 个 Critical 和 `5` 个 High,均来自镜像中的 .NET 10.0.9,修复版本为 10.0.10。当前上游 v1.7.0 镜像尚未包含修复,应在上游发布使用 .NET 10.0.10 或更高版本的镜像后尽快更新。
|
||||
- `CVE-2026-47302` 是 XML 加密解析导致的资源耗尽。LubeLogger 源码和默认依赖路径没有使用 `System.Security.Cryptography.Xml`、`System.Xml` 或 `EncryptedXml`,默认部署未发现可达入口。
|
||||
- `CVE-2026-50524` 是畸形 TLS 握手导致的拒绝服务,`CVE-2026-50528` 是 `SslStream` 授权绕过。此包内 Kestrel 只提供 HTTP/1 明文服务,不处理入站 TLS;默认也未配置 OIDC、Webhook、SMTP 或通知等外部 TLS 集成。用户启用这些集成后应把远端视为额外风险边界。
|
||||
- `CVE-2026-50651` 是 .NET HTTP/2 客户端处理 SETTINGS/PING ACK flood 时可能内存耗尽。LubeLogger 有可选的出站 HTTP 客户端路径,但此包通过 `DOTNET_SYSTEM_NET_HTTP_SOCKETSHTTPHANDLER_HTTP2SUPPORT=false` 禁用 HTTP/2,并默认不配置相关集成。
|
||||
- `CVE-2026-57108` 是解析特制 X.509 证书时的类型混淆拒绝服务。默认内部 HTTP 服务不解析入站证书;打开 Sponsors 页面或启用外部 TLS 集成时会产生出站证书解析路径,因此该项不能视为完全不可达。只连接可信端点,并在修复镜像可用后立即升级。
|
||||
|
||||
## Introduction
|
||||
|
||||
LubeLogger is a self-hosted vehicle management application for tracking maintenance, repairs, fuel, mileage, reminders, upgrades, taxes, collisions, and related documents.
|
||||
|
||||
## Features
|
||||
|
||||
- Manage multiple vehicles and their mileage, fuel, and cost records
|
||||
- Track maintenance plans, reminders, and service history
|
||||
- Store vehicle images, receipts, and other documents
|
||||
- Import and export CSV data, generate reports, and configure optional notifications
|
||||
|
||||
## Access And Authentication
|
||||
|
||||
Access the service at `http://<server-ip>:<port>` and sign in with the root username and password selected during installation. The initialization script passes only SHA-256 credential hashes to the application. Authentication is enabled by default, while open registration and the invitation registration page are disabled.
|
||||
|
||||
Upstream root authentication uses plain SHA-256 rather than a password-specific KDF. Keep the high-entropy password generated by 1Panel; do not use a short or reused password. LubeLogger 1.7.0 does not rate-limit login requests, and its authentication cookie does not explicitly set `Secure`, `HttpOnly`, or `SameSite`. Direct plain-HTTP access is suitable only on a trusted LAN. For public access, use a trusted HTTPS reverse proxy, block public access to the application port, and add login rate limiting at the proxy.
|
||||
|
||||
## Data Persistence
|
||||
|
||||
`APP_DATA_DIR` is mounted at `/App/data` and stores the LiteDB database, images, documents, configuration, and DataProtection session keys. It must remain inside the application version directory and defaults to `./data`. The initializer rejects absolute paths, directory escapes, and a symlinked authentication file, then assigns the directory to UID/GID `1000:1000`. Uninstall does not remove bind-mounted user data; back it up before upgrades or migration.
|
||||
|
||||
## Security And Vulnerability Notes
|
||||
|
||||
- The container runs as UID/GID `1000:1000`, uses a read-only root filesystem, drops all Linux capabilities, and enables `no-new-privileges`. CPU, memory, and process limits are managed through 1Panel's application resource settings. The application serves internal plain HTTP/1 only; terminate TLS at 1Panel or another trusted reverse proxy. Optional webhook, OIDC, SMTP, and notification integrations are not configured, and .NET HTTP client HTTP/2 support is disabled.
|
||||
- A 2026-07-28 Trivy scan of the pinned image found 0 Critical and 5 High findings, all in .NET 10.0.9. The fixes are in .NET 10.0.10. Upstream v1.7.0 has not yet published an image with those fixes; update promptly when it does.
|
||||
- `CVE-2026-47302` is an XML-encryption parsing resource-exhaustion issue. LubeLogger source and default dependencies do not use `System.Security.Cryptography.Xml`, `System.Xml`, or `EncryptedXml`, so no default reachable entry point was found.
|
||||
- `CVE-2026-50524` is a malformed TLS-handshake denial of service, and `CVE-2026-50528` is an `SslStream` authorization bypass. Kestrel serves only internal plain HTTP/1 in this package and does not process inbound TLS. OIDC, webhook, SMTP, and notification integrations are also unconfigured by default. Enabling them adds a separate outbound TLS risk boundary.
|
||||
- `CVE-2026-50651` is an HTTP/2 client SETTINGS/PING ACK flood that may cause an out-of-memory condition. LubeLogger has optional outbound HTTP client paths, but this package sets `DOTNET_SYSTEM_NET_HTTP_SOCKETSHTTPHANDLER_HTTP2SUPPORT=false` and leaves those integrations unconfigured.
|
||||
- `CVE-2026-57108` is a type-confusion denial of service while parsing a crafted X.509 certificate. The internal HTTP service does not parse inbound certificates. Opening the Sponsors view or enabling outbound TLS integrations does create certificate-parsing paths, so this finding is not considered completely unreachable. Connect only to trusted endpoints and upgrade as soon as a fixed image is available.
|
||||
|
||||
## References
|
||||
|
||||
- Project: <https://github.com/hargata/lubelog>
|
||||
- Release: <https://github.com/hargata/lubelog/releases/tag/v1.7.0>
|
||||
- Container source: <https://github.com/hargata/lubelog/blob/v1.7.0/Dockerfile>
|
||||
- Deployment documentation: <https://docs.lubelogger.com/Installation/Getting%20Started>
|
||||
- Configuration documentation: <https://docs.lubelogger.com/Advanced/Environment%20Variables>
|
||||
- License: <https://github.com/hargata/lubelog/blob/v1.7.0/LICENSE> (MIT)
|
||||
- .NET advisories: <https://github.com/advisories/GHSA-cvvh-rhrc-wg4q>, <https://github.com/advisories/GHSA-w7cw-xp7h-6j5j>, <https://github.com/advisories/GHSA-qvw7-jm5c-6hqw>, <https://github.com/advisories/GHSA-wp74-jgxh-gv4q>, <https://github.com/advisories/GHSA-rp2p-6cmp-jxj9>
|
||||
@@ -0,0 +1,30 @@
|
||||
name: LubeLogger
|
||||
tags:
|
||||
- Tool
|
||||
title: 车辆维护、保养与油耗记录工具
|
||||
description: 车辆维护、保养与油耗记录工具
|
||||
additionalProperties:
|
||||
key: lubelogger
|
||||
name: LubeLogger
|
||||
tags:
|
||||
- Tool
|
||||
shortDescZh: 车辆维护、保养与油耗记录工具
|
||||
shortDescEn: Vehicle maintenance, service, and fuel mileage tracking
|
||||
description:
|
||||
en: Vehicle maintenance, service, and fuel mileage tracking
|
||||
zh: 车辆维护、保养与油耗记录工具
|
||||
zh-Hant: 車輛維護、保養與油耗記錄工具
|
||||
ja: 車両の整備、サービス、燃費を記録するツール
|
||||
ko: 차량 정비, 서비스 및 연비 기록 도구
|
||||
ru: Учет обслуживания, ремонта и расхода топлива автомобилей
|
||||
ms: Penjejakan penyelenggaraan, servis dan penggunaan bahan api kenderaan
|
||||
pt-br: Controle de manutencao, servicos e consumo de veiculos
|
||||
type: website
|
||||
crossVersionUpdate: true
|
||||
limit: 0
|
||||
website: https://lubelogger.com/
|
||||
github: https://github.com/hargata/lubelog
|
||||
document: https://docs.lubelogger.com/
|
||||
architectures:
|
||||
- amd64
|
||||
- arm64
|
||||
@@ -0,0 +1,25 @@
|
||||
LubeLogger logo
|
||||
|
||||
Source: https://github.com/hargata/lubelog/blob/v1.7.0/wwwroot/defaults/lubelogger_icon_192.png
|
||||
License: MIT
|
||||
Copyright (c) 2024 Hargata Softworks
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
Reference in New Issue
Block a user