mirror of
https://github.com/okxlin/appstore.git
synced 2026-10-02 16:00:16 +00:00
Merge pull request #5483 from okxlin/batch-770/podfetch-20260801
feat(app): add PodFetch
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
# PodFetch
|
||||
|
||||
## 产品介绍
|
||||
|
||||
PodFetch 是一个自托管的播客管理器和下载器,提供 Web 界面、全文检索以及多种移动端和订阅阅读器集成。
|
||||
|
||||
## 主要功能
|
||||
|
||||
- 订阅、刷新和下载公开播客源。
|
||||
- 使用 SQLite 保存订阅、用户和播放状态。
|
||||
- 将播客媒体保存到独立目录,便于备份或迁移。
|
||||
- 支持基本认证、OIDC、GPodder 和 Audiobookshelf 兼容接口。
|
||||
|
||||
## 访问说明
|
||||
|
||||
- 默认启用基本认证,请使用安装表单中的管理员用户名和密码登录。
|
||||
- `播客目录` 和 `数据库目录` 都是持久化边界,卸载应用时不会自动删除。
|
||||
- 如使用反向代理,请启用 WebSocket 并转发标准的 `X-Forwarded-*` 头。
|
||||
|
||||
## Introduction
|
||||
|
||||
PodFetch is a self-hosted podcast manager and downloader with a web interface, full-text search, and integrations for mobile apps and feed readers.
|
||||
|
||||
## Features
|
||||
|
||||
- Subscribe to, refresh, and download public podcast feeds.
|
||||
- Store subscriptions, users, and playback state in SQLite.
|
||||
- Keep downloaded media in a separate directory for backup and migration.
|
||||
- Supports Basic authentication, OIDC, GPodder, and Audiobookshelf-compatible APIs.
|
||||
|
||||
## 参考资料
|
||||
|
||||
- 文档:<https://samtv12345.github.io/PodFetch/>
|
||||
- 源码:<https://github.com/SamTV12345/PodFetch>
|
||||
@@ -0,0 +1,3 @@
|
||||
# PodFetch
|
||||
|
||||
See `README.md` for the bilingual product description, configuration, and persistence notes.
|
||||
@@ -0,0 +1,31 @@
|
||||
name: PodFetch
|
||||
tags:
|
||||
- 多媒体
|
||||
title: 自托管的播客管理器和下载器
|
||||
description: 自托管的播客管理器和下载器
|
||||
additionalProperties:
|
||||
key: podfetch
|
||||
name: PodFetch
|
||||
tags:
|
||||
- Media
|
||||
shortDescZh: 自托管的播客管理器和下载器
|
||||
shortDescEn: Self-hosted podcast manager and downloader
|
||||
description:
|
||||
en: Self-hosted podcast manager and downloader with web, mobile, and feed-reader integrations.
|
||||
zh: 支持 Web、移动端和订阅阅读器集成的自托管播客管理器与下载器。
|
||||
zh-Hant: 支援 Web、行動端和訂閱閱讀器整合的自託管播客管理器與下載器。
|
||||
ja: Web、モバイル、フィードリーダー連携に対応したセルフホスト型ポッドキャスト管理・ダウンロードツールです。
|
||||
ko: 웹, 모바일, 피드 리더 연동을 지원하는 자체 호스팅 팟캐스트 관리자 및 다운로더입니다.
|
||||
ru: Самостоятельно размещаемый менеджер и загрузчик подкастов с интеграциями.
|
||||
ms: Pengurus dan pemuat turun podcast dihos sendiri dengan integrasi web dan mudah alih.
|
||||
pt-br: Gerenciador e baixador de podcasts auto-hospedado com integracoes web e moveis.
|
||||
type: tool
|
||||
crossVersionUpdate: true
|
||||
limit: 0
|
||||
recommend: 0
|
||||
website: https://samtv12345.github.io/PodFetch/
|
||||
github: https://github.com/SamTV12345/PodFetch
|
||||
document: https://samtv12345.github.io/PodFetch/
|
||||
architectures:
|
||||
- amd64
|
||||
- arm64
|
||||
@@ -0,0 +1,11 @@
|
||||
CONTAINER_NAME=podfetch
|
||||
PANEL_APP_BIND_ADDRESS=0.0.0.0
|
||||
PANEL_APP_PORT_HTTP=40100
|
||||
PUID=1000
|
||||
PGID=1000
|
||||
POLLING_INTERVAL=60
|
||||
BASIC_AUTH=true
|
||||
PODFETCH_USERNAME=admin
|
||||
PODFETCH_PASSWORD=replace-with-a-strong-password
|
||||
PODCASTS_DIR=./data/podcasts
|
||||
DATABASE_DIR=./data/db
|
||||
@@ -0,0 +1,170 @@
|
||||
additionalProperties:
|
||||
formFields:
|
||||
- default: 0.0.0.0
|
||||
edit: true
|
||||
envKey: PANEL_APP_BIND_ADDRESS
|
||||
labelEn: Bind Address
|
||||
labelZh: 绑定地址
|
||||
label:
|
||||
en: Bind Address
|
||||
zh: 绑定地址
|
||||
zh-Hant: 綁定位址
|
||||
ja: バインドアドレス
|
||||
ko: 바인드 주소
|
||||
ru: Адрес привязки
|
||||
ms: Alamat ikatan
|
||||
pt-br: Endereco de vinculacao
|
||||
required: true
|
||||
type: text
|
||||
- default: 40100
|
||||
edit: true
|
||||
envKey: PANEL_APP_PORT_HTTP
|
||||
labelEn: HTTP Port
|
||||
labelZh: HTTP 端口
|
||||
label:
|
||||
en: HTTP Port
|
||||
zh: HTTP 端口
|
||||
zh-Hant: HTTP 連接埠
|
||||
ja: HTTP ポート
|
||||
ko: HTTP 포트
|
||||
ru: HTTP-порт
|
||||
ms: Port HTTP
|
||||
pt-br: Porta HTTP
|
||||
required: true
|
||||
rule: paramPort
|
||||
type: number
|
||||
- default: 1000
|
||||
edit: true
|
||||
envKey: PUID
|
||||
labelEn: User ID
|
||||
labelZh: 用户 ID
|
||||
label:
|
||||
en: User ID
|
||||
zh: 用户 ID
|
||||
zh-Hant: 使用者 ID
|
||||
ja: ユーザー ID
|
||||
ko: 사용자 ID
|
||||
ru: Идентификатор пользователя
|
||||
ms: ID pengguna
|
||||
pt-br: ID do usuario
|
||||
required: true
|
||||
type: number
|
||||
- default: 1000
|
||||
edit: true
|
||||
envKey: PGID
|
||||
labelEn: Group ID
|
||||
labelZh: 用户组 ID
|
||||
label:
|
||||
en: Group ID
|
||||
zh: 用户组 ID
|
||||
zh-Hant: 使用者群組 ID
|
||||
ja: グループ ID
|
||||
ko: 그룹 ID
|
||||
ru: Идентификатор группы
|
||||
ms: ID kumpulan
|
||||
pt-br: ID do grupo
|
||||
required: true
|
||||
type: number
|
||||
- default: 60
|
||||
edit: true
|
||||
envKey: POLLING_INTERVAL
|
||||
labelEn: Polling Interval
|
||||
labelZh: 检查间隔
|
||||
label:
|
||||
en: Polling Interval
|
||||
zh: 检查间隔
|
||||
zh-Hant: 檢查間隔
|
||||
ja: 確認間隔
|
||||
ko: 확인 간격
|
||||
ru: Интервал проверки
|
||||
ms: Selang semakan
|
||||
pt-br: Intervalo de verificacao
|
||||
required: true
|
||||
type: number
|
||||
- default: "true"
|
||||
edit: true
|
||||
envKey: BASIC_AUTH
|
||||
labelEn: Enable Basic Authentication
|
||||
labelZh: 启用基本认证
|
||||
label:
|
||||
en: Enable Basic Authentication
|
||||
zh: 启用基本认证
|
||||
zh-Hant: 啟用基本驗證
|
||||
ja: Basic 認証を有効化
|
||||
ko: 기본 인증 사용
|
||||
ru: Включить базовую аутентификацию
|
||||
ms: Dayakan pengesahan asas
|
||||
pt-br: Ativar autenticacao basica
|
||||
required: true
|
||||
type: select
|
||||
values:
|
||||
- label: "true"
|
||||
value: "true"
|
||||
- label: "false"
|
||||
value: "false"
|
||||
- default: admin
|
||||
edit: true
|
||||
envKey: PODFETCH_USERNAME
|
||||
labelEn: Administrator Username
|
||||
labelZh: 管理员用户名
|
||||
label:
|
||||
en: Administrator Username
|
||||
zh: 管理员用户名
|
||||
zh-Hant: 管理員使用者名稱
|
||||
ja: 管理者ユーザー名
|
||||
ko: 관리자 사용자 이름
|
||||
ru: Имя администратора
|
||||
ms: Nama pengguna pentadbir
|
||||
pt-br: Nome do administrador
|
||||
required: true
|
||||
type: text
|
||||
- default: ""
|
||||
edit: true
|
||||
envKey: PODFETCH_PASSWORD
|
||||
labelEn: Administrator Password
|
||||
labelZh: 管理员密码
|
||||
label:
|
||||
en: Administrator Password
|
||||
zh: 管理员密码
|
||||
zh-Hant: 管理員密碼
|
||||
ja: 管理者パスワード
|
||||
ko: 관리자 비밀번호
|
||||
ru: Пароль администратора
|
||||
ms: Kata laluan pentadbir
|
||||
pt-br: Senha do administrador
|
||||
random: true
|
||||
required: true
|
||||
rule: paramComplexity
|
||||
type: password
|
||||
- default: ./data/podcasts
|
||||
edit: true
|
||||
envKey: PODCASTS_DIR
|
||||
labelEn: Podcast Directory
|
||||
labelZh: 播客目录
|
||||
label:
|
||||
en: Podcast Directory
|
||||
zh: 播客目录
|
||||
zh-Hant: Podcast 目錄
|
||||
ja: ポッドキャストディレクトリ
|
||||
ko: 팟캐스트 디렉터리
|
||||
ru: Каталог подкастов
|
||||
ms: Direktori podcast
|
||||
pt-br: Diretorio de podcasts
|
||||
required: true
|
||||
type: text
|
||||
- default: ./data/db
|
||||
edit: true
|
||||
envKey: DATABASE_DIR
|
||||
labelEn: Database Directory
|
||||
labelZh: 数据库目录
|
||||
label:
|
||||
en: Database Directory
|
||||
zh: 数据库目录
|
||||
zh-Hant: 資料庫目錄
|
||||
ja: データベースディレクトリ
|
||||
ko: 데이터베이스 디렉터리
|
||||
ru: Каталог базы данных
|
||||
ms: Direktori pangkalan data
|
||||
pt-br: Diretorio do banco de dados
|
||||
required: true
|
||||
type: text
|
||||
@@ -0,0 +1,27 @@
|
||||
services:
|
||||
podfetch:
|
||||
image: "docker.io/samuel19982/podfetch:latest"
|
||||
container_name: ${CONTAINER_NAME}
|
||||
restart: unless-stopped
|
||||
user: "${PUID}:${PGID}"
|
||||
networks:
|
||||
- 1panel-network
|
||||
ports:
|
||||
- "${PANEL_APP_BIND_ADDRESS}:${PANEL_APP_PORT_HTTP}:8000"
|
||||
environment:
|
||||
- PORT=8000
|
||||
- POLLING_INTERVAL=${POLLING_INTERVAL}
|
||||
- DATABASE_URL=sqlite:///app/db/podcast.db
|
||||
- PODFETCH_FOLDER=/app/podcasts
|
||||
- BASIC_AUTH=${BASIC_AUTH}
|
||||
- USERNAME=${PODFETCH_USERNAME}
|
||||
- PASSWORD=${PODFETCH_PASSWORD}
|
||||
volumes:
|
||||
- "${PODCASTS_DIR}:/app/podcasts"
|
||||
- "${DATABASE_DIR}:/app/db"
|
||||
labels:
|
||||
createdBy: Apps
|
||||
|
||||
networks:
|
||||
1panel-network:
|
||||
external: true
|
||||
Executable
+64
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)"
|
||||
ENV_FILE="${ENV_FILE:-${ROOT_DIR}/.env}"
|
||||
|
||||
fail() {
|
||||
printf '%s\n' "$1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
read_env_value() {
|
||||
local key="$1"
|
||||
local value=""
|
||||
|
||||
value="$(grep -E "^${key}=" "$ENV_FILE" | tail -n 1 | cut -d '=' -f 2-)"
|
||||
case "$value" in
|
||||
\"*\" | \'*\') value="${value:1:${#value}-2}" ;;
|
||||
esac
|
||||
printf '%s\n' "$value"
|
||||
}
|
||||
|
||||
prepare_directory() {
|
||||
local key="$1"
|
||||
local raw="$2"
|
||||
local absolute=""
|
||||
|
||||
[[ -n "$raw" ]] || fail "${key} must not be empty"
|
||||
case "$raw" in
|
||||
*$'\n'* | *$'\r'* | *\\* | *'$'* | *'#'* | *'"'* | *"'"*) fail "${key} contains unsupported dotenv characters" ;;
|
||||
esac
|
||||
if [[ "$raw" = /* ]]; then
|
||||
[[ ! -L "$raw" ]] || fail "${key} must not be a symbolic link"
|
||||
absolute="$(realpath -m -- "$raw")"
|
||||
[[ "$absolute" != "/" ]] || fail "${key} must not be the filesystem root"
|
||||
if [[ -e "$absolute" ]]; then
|
||||
[[ -d "$absolute" ]] || fail "${key} must be a directory"
|
||||
[[ "$(stat -c '%u:%g' "$absolute")" == "${PUID}:${PGID}" ]] || fail "Existing ${key} must be owned by ${PUID}:${PGID}"
|
||||
else
|
||||
install -d -m 0750 -- "$absolute"
|
||||
chown "${PUID}:${PGID}" -- "$absolute"
|
||||
fi
|
||||
else
|
||||
absolute="$(realpath -m -- "${ROOT_DIR}/${raw#./}")"
|
||||
case "$absolute" in
|
||||
"${ROOT_DIR}"/*) ;;
|
||||
*) fail "Relative ${key} must remain inside the application version directory" ;;
|
||||
esac
|
||||
[[ ! -L "$absolute" ]] || fail "${key} must not be a symbolic link"
|
||||
install -d -m 0750 -- "$absolute"
|
||||
chown "${PUID}:${PGID}" -- "$absolute"
|
||||
fi
|
||||
}
|
||||
|
||||
[[ "$(id -u)" -eq 0 ]] || fail "PodFetch init must run as root"
|
||||
[[ -f "$ENV_FILE" ]] || fail "Environment file not found: ${ENV_FILE}"
|
||||
[[ ! -L "$ENV_FILE" ]] || fail "Environment file must not be a symbolic link"
|
||||
|
||||
PUID="${PUID:-$(read_env_value PUID)}"
|
||||
PGID="${PGID:-$(read_env_value PGID)}"
|
||||
[[ "$PUID" =~ ^[0-9]+$ && "$PGID" =~ ^[0-9]+$ ]] || fail "PUID and PGID must be numeric"
|
||||
|
||||
prepare_directory PODCASTS_DIR "${PODCASTS_DIR:-$(read_env_value PODCASTS_DIR)}"
|
||||
prepare_directory DATABASE_DIR "${DATABASE_DIR:-$(read_env_value DATABASE_DIR)}"
|
||||
Executable
+5
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Podcast media and the SQLite database are retained for recovery.
|
||||
exit 0
|
||||
Executable
+5
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# PodFetch applies its database migrations when the new container starts.
|
||||
exit 0
|
||||
@@ -0,0 +1,9 @@
|
||||
PodFetch logo
|
||||
|
||||
Source: https://github.com/SamTV12345/PodFetch/blob/b28002a56bd0291df3a4b184cf5673dcd99aceec/ui/public/logo.png
|
||||
Source commit: b28002a56bd0291df3a4b184cf5673dcd99aceec
|
||||
Source SHA-256: 3ad03a34777eff296167d19f38f0084c54096f7b78e725958953d05d7e8d58c4
|
||||
License: Apache License 2.0 (Apache-2.0)
|
||||
License text: https://github.com/SamTV12345/PodFetch/blob/b28002a56bd0291df3a4b184cf5673dcd99aceec/LICENSE
|
||||
|
||||
The store asset is a proportional rendering of the official project logo.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1,11 @@
|
||||
CONTAINER_NAME=podfetch
|
||||
PANEL_APP_BIND_ADDRESS=0.0.0.0
|
||||
PANEL_APP_PORT_HTTP=40100
|
||||
PUID=1000
|
||||
PGID=1000
|
||||
POLLING_INTERVAL=60
|
||||
BASIC_AUTH=true
|
||||
PODFETCH_USERNAME=admin
|
||||
PODFETCH_PASSWORD=replace-with-a-strong-password
|
||||
PODCASTS_DIR=./data/podcasts
|
||||
DATABASE_DIR=./data/db
|
||||
@@ -0,0 +1,170 @@
|
||||
additionalProperties:
|
||||
formFields:
|
||||
- default: 0.0.0.0
|
||||
edit: true
|
||||
envKey: PANEL_APP_BIND_ADDRESS
|
||||
labelEn: Bind Address
|
||||
labelZh: 绑定地址
|
||||
label:
|
||||
en: Bind Address
|
||||
zh: 绑定地址
|
||||
zh-Hant: 綁定位址
|
||||
ja: バインドアドレス
|
||||
ko: 바인드 주소
|
||||
ru: Адрес привязки
|
||||
ms: Alamat ikatan
|
||||
pt-br: Endereco de vinculacao
|
||||
required: true
|
||||
type: text
|
||||
- default: 40100
|
||||
edit: true
|
||||
envKey: PANEL_APP_PORT_HTTP
|
||||
labelEn: HTTP Port
|
||||
labelZh: HTTP 端口
|
||||
label:
|
||||
en: HTTP Port
|
||||
zh: HTTP 端口
|
||||
zh-Hant: HTTP 連接埠
|
||||
ja: HTTP ポート
|
||||
ko: HTTP 포트
|
||||
ru: HTTP-порт
|
||||
ms: Port HTTP
|
||||
pt-br: Porta HTTP
|
||||
required: true
|
||||
rule: paramPort
|
||||
type: number
|
||||
- default: 1000
|
||||
edit: true
|
||||
envKey: PUID
|
||||
labelEn: User ID
|
||||
labelZh: 用户 ID
|
||||
label:
|
||||
en: User ID
|
||||
zh: 用户 ID
|
||||
zh-Hant: 使用者 ID
|
||||
ja: ユーザー ID
|
||||
ko: 사용자 ID
|
||||
ru: Идентификатор пользователя
|
||||
ms: ID pengguna
|
||||
pt-br: ID do usuario
|
||||
required: true
|
||||
type: number
|
||||
- default: 1000
|
||||
edit: true
|
||||
envKey: PGID
|
||||
labelEn: Group ID
|
||||
labelZh: 用户组 ID
|
||||
label:
|
||||
en: Group ID
|
||||
zh: 用户组 ID
|
||||
zh-Hant: 使用者群組 ID
|
||||
ja: グループ ID
|
||||
ko: 그룹 ID
|
||||
ru: Идентификатор группы
|
||||
ms: ID kumpulan
|
||||
pt-br: ID do grupo
|
||||
required: true
|
||||
type: number
|
||||
- default: 60
|
||||
edit: true
|
||||
envKey: POLLING_INTERVAL
|
||||
labelEn: Polling Interval
|
||||
labelZh: 检查间隔
|
||||
label:
|
||||
en: Polling Interval
|
||||
zh: 检查间隔
|
||||
zh-Hant: 檢查間隔
|
||||
ja: 確認間隔
|
||||
ko: 확인 간격
|
||||
ru: Интервал проверки
|
||||
ms: Selang semakan
|
||||
pt-br: Intervalo de verificacao
|
||||
required: true
|
||||
type: number
|
||||
- default: "true"
|
||||
edit: true
|
||||
envKey: BASIC_AUTH
|
||||
labelEn: Enable Basic Authentication
|
||||
labelZh: 启用基本认证
|
||||
label:
|
||||
en: Enable Basic Authentication
|
||||
zh: 启用基本认证
|
||||
zh-Hant: 啟用基本驗證
|
||||
ja: Basic 認証を有効化
|
||||
ko: 기본 인증 사용
|
||||
ru: Включить базовую аутентификацию
|
||||
ms: Dayakan pengesahan asas
|
||||
pt-br: Ativar autenticacao basica
|
||||
required: true
|
||||
type: select
|
||||
values:
|
||||
- label: "true"
|
||||
value: "true"
|
||||
- label: "false"
|
||||
value: "false"
|
||||
- default: admin
|
||||
edit: true
|
||||
envKey: PODFETCH_USERNAME
|
||||
labelEn: Administrator Username
|
||||
labelZh: 管理员用户名
|
||||
label:
|
||||
en: Administrator Username
|
||||
zh: 管理员用户名
|
||||
zh-Hant: 管理員使用者名稱
|
||||
ja: 管理者ユーザー名
|
||||
ko: 관리자 사용자 이름
|
||||
ru: Имя администратора
|
||||
ms: Nama pengguna pentadbir
|
||||
pt-br: Nome do administrador
|
||||
required: true
|
||||
type: text
|
||||
- default: ""
|
||||
edit: true
|
||||
envKey: PODFETCH_PASSWORD
|
||||
labelEn: Administrator Password
|
||||
labelZh: 管理员密码
|
||||
label:
|
||||
en: Administrator Password
|
||||
zh: 管理员密码
|
||||
zh-Hant: 管理員密碼
|
||||
ja: 管理者パスワード
|
||||
ko: 관리자 비밀번호
|
||||
ru: Пароль администратора
|
||||
ms: Kata laluan pentadbir
|
||||
pt-br: Senha do administrador
|
||||
random: true
|
||||
required: true
|
||||
rule: paramComplexity
|
||||
type: password
|
||||
- default: ./data/podcasts
|
||||
edit: true
|
||||
envKey: PODCASTS_DIR
|
||||
labelEn: Podcast Directory
|
||||
labelZh: 播客目录
|
||||
label:
|
||||
en: Podcast Directory
|
||||
zh: 播客目录
|
||||
zh-Hant: Podcast 目錄
|
||||
ja: ポッドキャストディレクトリ
|
||||
ko: 팟캐스트 디렉터리
|
||||
ru: Каталог подкастов
|
||||
ms: Direktori podcast
|
||||
pt-br: Diretorio de podcasts
|
||||
required: true
|
||||
type: text
|
||||
- default: ./data/db
|
||||
edit: true
|
||||
envKey: DATABASE_DIR
|
||||
labelEn: Database Directory
|
||||
labelZh: 数据库目录
|
||||
label:
|
||||
en: Database Directory
|
||||
zh: 数据库目录
|
||||
zh-Hant: 資料庫目錄
|
||||
ja: データベースディレクトリ
|
||||
ko: 데이터베이스 디렉터리
|
||||
ru: Каталог базы данных
|
||||
ms: Direktori pangkalan data
|
||||
pt-br: Diretorio do banco de dados
|
||||
required: true
|
||||
type: text
|
||||
@@ -0,0 +1,27 @@
|
||||
services:
|
||||
podfetch:
|
||||
image: "docker.io/samuel19982/podfetch:v5.2.2@sha256:d8b8e546d3ae40c6e7821343c3d0f0a238b47cb772295e95c7f8683ca419663f"
|
||||
container_name: ${CONTAINER_NAME}
|
||||
restart: unless-stopped
|
||||
user: "${PUID}:${PGID}"
|
||||
networks:
|
||||
- 1panel-network
|
||||
ports:
|
||||
- "${PANEL_APP_BIND_ADDRESS}:${PANEL_APP_PORT_HTTP}:8000"
|
||||
environment:
|
||||
- PORT=8000
|
||||
- POLLING_INTERVAL=${POLLING_INTERVAL}
|
||||
- DATABASE_URL=sqlite:///app/db/podcast.db
|
||||
- PODFETCH_FOLDER=/app/podcasts
|
||||
- BASIC_AUTH=${BASIC_AUTH}
|
||||
- USERNAME=${PODFETCH_USERNAME}
|
||||
- PASSWORD=${PODFETCH_PASSWORD}
|
||||
volumes:
|
||||
- "${PODCASTS_DIR}:/app/podcasts"
|
||||
- "${DATABASE_DIR}:/app/db"
|
||||
labels:
|
||||
createdBy: Apps
|
||||
|
||||
networks:
|
||||
1panel-network:
|
||||
external: true
|
||||
Executable
+64
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)"
|
||||
ENV_FILE="${ENV_FILE:-${ROOT_DIR}/.env}"
|
||||
|
||||
fail() {
|
||||
printf '%s\n' "$1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
read_env_value() {
|
||||
local key="$1"
|
||||
local value=""
|
||||
|
||||
value="$(grep -E "^${key}=" "$ENV_FILE" | tail -n 1 | cut -d '=' -f 2-)"
|
||||
case "$value" in
|
||||
\"*\" | \'*\') value="${value:1:${#value}-2}" ;;
|
||||
esac
|
||||
printf '%s\n' "$value"
|
||||
}
|
||||
|
||||
prepare_directory() {
|
||||
local key="$1"
|
||||
local raw="$2"
|
||||
local absolute=""
|
||||
|
||||
[[ -n "$raw" ]] || fail "${key} must not be empty"
|
||||
case "$raw" in
|
||||
*$'\n'* | *$'\r'* | *\\* | *'$'* | *'#'* | *'"'* | *"'"*) fail "${key} contains unsupported dotenv characters" ;;
|
||||
esac
|
||||
if [[ "$raw" = /* ]]; then
|
||||
[[ ! -L "$raw" ]] || fail "${key} must not be a symbolic link"
|
||||
absolute="$(realpath -m -- "$raw")"
|
||||
[[ "$absolute" != "/" ]] || fail "${key} must not be the filesystem root"
|
||||
if [[ -e "$absolute" ]]; then
|
||||
[[ -d "$absolute" ]] || fail "${key} must be a directory"
|
||||
[[ "$(stat -c '%u:%g' "$absolute")" == "${PUID}:${PGID}" ]] || fail "Existing ${key} must be owned by ${PUID}:${PGID}"
|
||||
else
|
||||
install -d -m 0750 -- "$absolute"
|
||||
chown "${PUID}:${PGID}" -- "$absolute"
|
||||
fi
|
||||
else
|
||||
absolute="$(realpath -m -- "${ROOT_DIR}/${raw#./}")"
|
||||
case "$absolute" in
|
||||
"${ROOT_DIR}"/*) ;;
|
||||
*) fail "Relative ${key} must remain inside the application version directory" ;;
|
||||
esac
|
||||
[[ ! -L "$absolute" ]] || fail "${key} must not be a symbolic link"
|
||||
install -d -m 0750 -- "$absolute"
|
||||
chown "${PUID}:${PGID}" -- "$absolute"
|
||||
fi
|
||||
}
|
||||
|
||||
[[ "$(id -u)" -eq 0 ]] || fail "PodFetch init must run as root"
|
||||
[[ -f "$ENV_FILE" ]] || fail "Environment file not found: ${ENV_FILE}"
|
||||
[[ ! -L "$ENV_FILE" ]] || fail "Environment file must not be a symbolic link"
|
||||
|
||||
PUID="${PUID:-$(read_env_value PUID)}"
|
||||
PGID="${PGID:-$(read_env_value PGID)}"
|
||||
[[ "$PUID" =~ ^[0-9]+$ && "$PGID" =~ ^[0-9]+$ ]] || fail "PUID and PGID must be numeric"
|
||||
|
||||
prepare_directory PODCASTS_DIR "${PODCASTS_DIR:-$(read_env_value PODCASTS_DIR)}"
|
||||
prepare_directory DATABASE_DIR "${DATABASE_DIR:-$(read_env_value DATABASE_DIR)}"
|
||||
Executable
+5
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Podcast media and the SQLite database are retained for recovery.
|
||||
exit 0
|
||||
Executable
+5
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# PodFetch applies its database migrations when the new container starts.
|
||||
exit 0
|
||||
Reference in New Issue
Block a user