From fb64e70d74cfec92b10bc9dcd4c867bff36ebfb6 Mon Sep 17 00:00:00 2001 From: okxlin <61420215+okxlin@users.noreply.github.com> Date: Tue, 28 Jul 2026 20:44:27 +0800 Subject: [PATCH] feat(app): add Wayback --- apps/wayback/0.21.1/.env.sample | 7 ++ apps/wayback/0.21.1/data.yml | 99 +++++++++++++++++++++++ apps/wayback/0.21.1/data/.gitkeep | 1 + apps/wayback/0.21.1/docker-compose.yml | 39 +++++++++ apps/wayback/0.21.1/scripts/init.sh | 66 +++++++++++++++ apps/wayback/0.21.1/scripts/uninstall.sh | 8 ++ apps/wayback/0.21.1/scripts/upgrade.sh | 5 ++ apps/wayback/README.md | 44 ++++++++++ apps/wayback/data.yml | 33 ++++++++ apps/wayback/latest/.env.sample | 7 ++ apps/wayback/latest/data.yml | 99 +++++++++++++++++++++++ apps/wayback/latest/data/.gitkeep | 1 + apps/wayback/latest/docker-compose.yml | 39 +++++++++ apps/wayback/latest/scripts/init.sh | 66 +++++++++++++++ apps/wayback/latest/scripts/uninstall.sh | 8 ++ apps/wayback/latest/scripts/upgrade.sh | 5 ++ apps/wayback/logo.png | Bin 0 -> 9415 bytes apps/wayback/source-evidence.json | 5 ++ 18 files changed, 532 insertions(+) create mode 100644 apps/wayback/0.21.1/.env.sample create mode 100644 apps/wayback/0.21.1/data.yml create mode 100644 apps/wayback/0.21.1/data/.gitkeep create mode 100644 apps/wayback/0.21.1/docker-compose.yml create mode 100755 apps/wayback/0.21.1/scripts/init.sh create mode 100755 apps/wayback/0.21.1/scripts/uninstall.sh create mode 100755 apps/wayback/0.21.1/scripts/upgrade.sh create mode 100644 apps/wayback/README.md create mode 100644 apps/wayback/data.yml create mode 100644 apps/wayback/latest/.env.sample create mode 100644 apps/wayback/latest/data.yml create mode 100644 apps/wayback/latest/data/.gitkeep create mode 100644 apps/wayback/latest/docker-compose.yml create mode 100755 apps/wayback/latest/scripts/init.sh create mode 100755 apps/wayback/latest/scripts/uninstall.sh create mode 100755 apps/wayback/latest/scripts/upgrade.sh create mode 100644 apps/wayback/logo.png create mode 100644 apps/wayback/source-evidence.json diff --git a/apps/wayback/0.21.1/.env.sample b/apps/wayback/0.21.1/.env.sample new file mode 100644 index 000000000..93175a301 --- /dev/null +++ b/apps/wayback/0.21.1/.env.sample @@ -0,0 +1,7 @@ +CONTAINER_NAME="wayback" +PANEL_APP_BIND_ADDRESS="127.0.0.1" +PANEL_APP_PORT_HTTP="8964" +DATA_PATH="./data" +WAYBACK_POOLING_SIZE="3" +WAYBACK_TIMEOUT="300" +WAYBACK_MAX_MEDIA_SIZE="512MB" diff --git a/apps/wayback/0.21.1/data.yml b/apps/wayback/0.21.1/data.yml new file mode 100644 index 000000000..79bfee3c7 --- /dev/null +++ b/apps/wayback/0.21.1/data.yml @@ -0,0 +1,99 @@ +additionalProperties: + formFields: + - default: 127.0.0.1 + 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: 8964 + 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: ./data + edit: true + envKey: DATA_PATH + labelEn: Data Folder Path + labelZh: 数据文件夹路径 + label: + en: Data Folder Path + zh: 数据文件夹路径 + zh-Hant: 資料夾路徑 + ja: データフォルダのパス + ko: 데이터 폴더 경로 + ru: Путь к папке данных + ms: Laluan folder data + pt-br: Caminho da pasta de dados + required: true + type: text + - default: 3 + edit: true + envKey: WAYBACK_POOLING_SIZE + labelEn: Concurrent Jobs + labelZh: 并发任务数 + label: + en: Concurrent Jobs + zh: 并发任务数 + zh-Hant: 並行工作數 + ja: 同時実行ジョブ数 + ko: 동시 작업 수 + ru: Параллельные задания + ms: Kerja serentak + pt-br: Tarefas simultaneas + required: true + type: number + - default: 300 + edit: true + envKey: WAYBACK_TIMEOUT + labelEn: Archive Timeout Seconds + labelZh: 归档超时秒数 + label: + en: Archive Timeout Seconds + zh: 归档超时秒数 + zh-Hant: 封存逾時秒數 + ja: アーカイブのタイムアウト秒数 + ko: 아카이브 제한 시간(초) + ru: Тайм-аут архивации в секундах + ms: Tamat masa arkib dalam saat + pt-br: Tempo limite de arquivamento em segundos + required: true + type: number + - default: 512MB + edit: true + envKey: WAYBACK_MAX_MEDIA_SIZE + labelEn: Maximum Media Size + labelZh: 最大媒体大小 + label: + en: Maximum Media Size + zh: 最大媒体大小 + zh-Hant: 最大媒體大小 + ja: 最大メディアサイズ + ko: 최대 미디어 크기 + ru: Максимальный размер медиафайла + ms: Saiz media maksimum + pt-br: Tamanho maximo de midia + required: true + type: text diff --git a/apps/wayback/0.21.1/data/.gitkeep b/apps/wayback/0.21.1/data/.gitkeep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/apps/wayback/0.21.1/data/.gitkeep @@ -0,0 +1 @@ + diff --git a/apps/wayback/0.21.1/docker-compose.yml b/apps/wayback/0.21.1/docker-compose.yml new file mode 100644 index 000000000..45c85039a --- /dev/null +++ b/apps/wayback/0.21.1/docker-compose.yml @@ -0,0 +1,39 @@ +services: + wayback: + image: "wabarc/wayback:0.21.1@sha256:60cc26d4678462a866d34866d2f1d07c0419d4b87940640bdf2e3030e3b77a06" + container_name: ${CONTAINER_NAME} + restart: unless-stopped + command: ["wayback", "--ia", "--is", "--ga", "-d", "web"] + networks: + - 1panel-network + ports: + - "${PANEL_APP_BIND_ADDRESS}:${PANEL_APP_PORT_HTTP}:8964" + user: "100:101" + read_only: true + cap_drop: + - ALL + security_opt: + - no-new-privileges:true + environment: + - WAYBACK_LISTEN_ADDR=0.0.0.0:8964 + - WAYBACK_BOLT_PATH=/data/wayback.db + - WAYBACK_POOLING_SIZE=${WAYBACK_POOLING_SIZE} + - WAYBACK_TIMEOUT=${WAYBACK_TIMEOUT} + - WAYBACK_MAX_MEDIA_SIZE=${WAYBACK_MAX_MEDIA_SIZE} + - WAYBACK_ONION_DISABLED=true + volumes: + - "${DATA_PATH}:/data" + tmpfs: + - /tmp:rw,noexec,nosuid,size=256m + healthcheck: + test: ["CMD-SHELL", "wget -q -O - http://127.0.0.1:8964/healthcheck | grep -qx OK"] + interval: 10s + timeout: 5s + start_period: 20s + retries: 12 + labels: + createdBy: "Apps" + +networks: + 1panel-network: + external: true diff --git a/apps/wayback/0.21.1/scripts/init.sh b/apps/wayback/0.21.1/scripts/init.sh new file mode 100755 index 000000000..c78f96639 --- /dev/null +++ b/apps/wayback/0.21.1/scripts/init.sh @@ -0,0 +1,66 @@ +#!/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="$(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" +} + +validate_ipv4() { + local value="$1" + local part + local -a parts + IFS='.' read -r -a parts <<< "$value" + [[ ${#parts[@]} -eq 4 ]] || return 1 + for part in "${parts[@]}"; do + [[ "$part" =~ ^[0-9]{1,3}$ ]] || return 1 + (( 10#$part <= 255 )) || return 1 + done +} + +[[ -f "$ENV_FILE" ]] || fail "$ENV_FILE not found" +[[ ! -L "$ENV_FILE" ]] || fail "$ENV_FILE must not be a symbolic link" + +bind_address="$(read_env_value PANEL_APP_BIND_ADDRESS)" +validate_ipv4 "$bind_address" || fail "PANEL_APP_BIND_ADDRESS must be an IPv4 address" + +pooling_size="$(read_env_value WAYBACK_POOLING_SIZE)" +[[ "$pooling_size" =~ ^[0-9]+$ ]] || fail "WAYBACK_POOLING_SIZE must be an integer" +(( pooling_size >= 1 && pooling_size <= 32 )) || fail "WAYBACK_POOLING_SIZE must be between 1 and 32" + +timeout="$(read_env_value WAYBACK_TIMEOUT)" +[[ "$timeout" =~ ^[0-9]+$ ]] || fail "WAYBACK_TIMEOUT must be an integer" +(( timeout >= 10 && timeout <= 3600 )) || fail "WAYBACK_TIMEOUT must be between 10 and 3600" + +media_size="$(read_env_value WAYBACK_MAX_MEDIA_SIZE)" +[[ "$media_size" =~ ^[1-9][0-9]{0,4}(MB|GB)$ ]] || fail "WAYBACK_MAX_MEDIA_SIZE must use MB or GB, for example 512MB" + +data_path="$(read_env_value DATA_PATH)" +[[ "$data_path" =~ ^\./[A-Za-z0-9._-]+(/[A-Za-z0-9._-]+)*$ ]] || fail "DATA_PATH must be a relative path inside the app directory" +[[ "/$data_path/" != *"/../"* ]] || fail "DATA_PATH must not contain parent traversal" + +data_dir="${ROOT_DIR}/${data_path#./}" +canonical_root="$(realpath -m -- "$ROOT_DIR")" +canonical_data="$(realpath -m -- "$data_dir")" +[[ "$canonical_data" == "$canonical_root"/* ]] || fail "DATA_PATH resolves outside the app directory" +[[ ! -L "$data_dir" ]] || fail "DATA_PATH must not be a symbolic link" + +umask 077 +mkdir -p "$data_dir" +chown -R 100:101 "$data_dir" +chmod 750 "$data_dir" +chmod 600 "$ENV_FILE" diff --git a/apps/wayback/0.21.1/scripts/uninstall.sh b/apps/wayback/0.21.1/scripts/uninstall.sh new file mode 100755 index 000000000..5c199242b --- /dev/null +++ b/apps/wayback/0.21.1/scripts/uninstall.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -euo pipefail + +if command -v docker-compose >/dev/null 2>&1; then + docker-compose down --remove-orphans +else + docker compose down --remove-orphans +fi diff --git a/apps/wayback/0.21.1/scripts/upgrade.sh b/apps/wayback/0.21.1/scripts/upgrade.sh new file mode 100755 index 000000000..593b31667 --- /dev/null +++ b/apps/wayback/0.21.1/scripts/upgrade.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" +exec bash "${SCRIPT_DIR}/init.sh" diff --git a/apps/wayback/README.md b/apps/wayback/README.md new file mode 100644 index 000000000..5b7e374a0 --- /dev/null +++ b/apps/wayback/README.md @@ -0,0 +1,44 @@ +# Wayback + +## 产品介绍 + +Wayback 是开源的网页归档与回放工具。它提供 Web 界面,可将网页提交到 Internet Archive、archive.today 和 Ghostarchive,并聚合多个公共归档服务的回放结果。 + +## 主要功能 + +- 从 Web 界面提交一个或多个网页地址 +- 聚合多个公共归档服务的结果 +- 使用本地 Bolt 数据库保存应用状态 + +## 访问说明 + +- 默认仅监听 `127.0.0.1:8964`,实际地址和端口以安装表单为准。远程访问建议使用 HTTPS 反向代理,不要直接暴露到公网。 +- Wayback Web 界面没有内置用户认证。能够访问该界面的用户可以让服务器请求外部 URL,并可能访问服务器可达的内部地址。请使用反向代理认证、网络访问控制和出站防火墙限制不受信任用户。 +- 默认禁用 Wayback 的 Tor、Telegraph 和 IPFS 集成。官方 Compose 中的无头浏览器不能绕过当前应用对本地 Chromium 的前置检查,同时其当前镜像存在 Critical 漏洞,因此本包不包含该可选依赖。 +- Meilisearch 是可选的归档索引与回放增强服务,不属于本包的默认拓扑。 +- 当前官方 Wayback 镜像的安全扫描结果为 0 个 Critical、7 个 High。源码与运行路径复核未发现这些 High 在本包默认配置下的可达路径,但相关上游组件仍保留在镜像中;上游发布修复镜像后应及时更新。 + +## 数据与备份 + +应用数据保存在 `DATA_PATH`,其中 `wayback.db` 是 Bolt 数据库。升级或卸载前请备份整个目录。 + +## Introduction + +Wayback is an open-source web archiving and playback tool. This package runs the official single image in Web mode with Internet Archive, archive.today, and Ghostarchive enabled. Optional browser, Telegraph, IPFS, Tor, and Meilisearch integrations are not enabled by default. + +The Web interface has no built-in authentication and can make outbound requests to user-supplied URLs. Keep the default loopback binding or place it behind an authenticated HTTPS reverse proxy with appropriate egress controls. Back up the complete data directory before upgrades or uninstalling. + +The current official Wayback image scans at 0 Critical and 7 High findings. Source and runtime-path review found no demonstrated reachability in this package's default configuration, but the affected upstream components remain present and the package should be updated when upstream publishes a fixed image. + +## Features + +- Submit one or more URLs from the Web interface +- Collect results from multiple public archive services +- Persist application state in a local Bolt database + +## References + +- Website: +- Source: +- Documentation: +- License: GPL-3.0 diff --git a/apps/wayback/data.yml b/apps/wayback/data.yml new file mode 100644 index 000000000..fe9b30bc0 --- /dev/null +++ b/apps/wayback/data.yml @@ -0,0 +1,33 @@ +name: Wayback +tags: + - 工具 + - 网络工具 +title: 网页归档与回放工具 +description: 网页归档与回放工具 +additionalProperties: + key: wayback + name: Wayback + tags: + - Tool + - Network + shortDescZh: 网页归档与回放工具 + shortDescEn: Web archiving and playback tool + description: + en: Web archiving and playback tool + zh: 网页归档与回放工具 + zh-Hant: 網頁封存與回放工具 + ja: Webアーカイブおよび再生ツール + ko: 웹 아카이빙 및 재생 도구 + ru: Инструмент архивирования и воспроизведения веб-страниц + ms: Alat pengarkiban dan main balik web + pt-br: Ferramenta de arquivamento e reproducao da Web + type: tool + crossVersionUpdate: true + limit: 0 + recommend: 0 + website: https://wabarc.eu.org/ + github: https://github.com/wabarc/wayback + document: https://docs.wabarc.eu.org/ + architectures: + - amd64 + - arm64 diff --git a/apps/wayback/latest/.env.sample b/apps/wayback/latest/.env.sample new file mode 100644 index 000000000..93175a301 --- /dev/null +++ b/apps/wayback/latest/.env.sample @@ -0,0 +1,7 @@ +CONTAINER_NAME="wayback" +PANEL_APP_BIND_ADDRESS="127.0.0.1" +PANEL_APP_PORT_HTTP="8964" +DATA_PATH="./data" +WAYBACK_POOLING_SIZE="3" +WAYBACK_TIMEOUT="300" +WAYBACK_MAX_MEDIA_SIZE="512MB" diff --git a/apps/wayback/latest/data.yml b/apps/wayback/latest/data.yml new file mode 100644 index 000000000..79bfee3c7 --- /dev/null +++ b/apps/wayback/latest/data.yml @@ -0,0 +1,99 @@ +additionalProperties: + formFields: + - default: 127.0.0.1 + 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: 8964 + 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: ./data + edit: true + envKey: DATA_PATH + labelEn: Data Folder Path + labelZh: 数据文件夹路径 + label: + en: Data Folder Path + zh: 数据文件夹路径 + zh-Hant: 資料夾路徑 + ja: データフォルダのパス + ko: 데이터 폴더 경로 + ru: Путь к папке данных + ms: Laluan folder data + pt-br: Caminho da pasta de dados + required: true + type: text + - default: 3 + edit: true + envKey: WAYBACK_POOLING_SIZE + labelEn: Concurrent Jobs + labelZh: 并发任务数 + label: + en: Concurrent Jobs + zh: 并发任务数 + zh-Hant: 並行工作數 + ja: 同時実行ジョブ数 + ko: 동시 작업 수 + ru: Параллельные задания + ms: Kerja serentak + pt-br: Tarefas simultaneas + required: true + type: number + - default: 300 + edit: true + envKey: WAYBACK_TIMEOUT + labelEn: Archive Timeout Seconds + labelZh: 归档超时秒数 + label: + en: Archive Timeout Seconds + zh: 归档超时秒数 + zh-Hant: 封存逾時秒數 + ja: アーカイブのタイムアウト秒数 + ko: 아카이브 제한 시간(초) + ru: Тайм-аут архивации в секундах + ms: Tamat masa arkib dalam saat + pt-br: Tempo limite de arquivamento em segundos + required: true + type: number + - default: 512MB + edit: true + envKey: WAYBACK_MAX_MEDIA_SIZE + labelEn: Maximum Media Size + labelZh: 最大媒体大小 + label: + en: Maximum Media Size + zh: 最大媒体大小 + zh-Hant: 最大媒體大小 + ja: 最大メディアサイズ + ko: 최대 미디어 크기 + ru: Максимальный размер медиафайла + ms: Saiz media maksimum + pt-br: Tamanho maximo de midia + required: true + type: text diff --git a/apps/wayback/latest/data/.gitkeep b/apps/wayback/latest/data/.gitkeep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/apps/wayback/latest/data/.gitkeep @@ -0,0 +1 @@ + diff --git a/apps/wayback/latest/docker-compose.yml b/apps/wayback/latest/docker-compose.yml new file mode 100644 index 000000000..52c789878 --- /dev/null +++ b/apps/wayback/latest/docker-compose.yml @@ -0,0 +1,39 @@ +services: + wayback: + image: "wabarc/wayback:latest@sha256:60cc26d4678462a866d34866d2f1d07c0419d4b87940640bdf2e3030e3b77a06" + container_name: ${CONTAINER_NAME} + restart: unless-stopped + command: ["wayback", "--ia", "--is", "--ga", "-d", "web"] + networks: + - 1panel-network + ports: + - "${PANEL_APP_BIND_ADDRESS}:${PANEL_APP_PORT_HTTP}:8964" + user: "100:101" + read_only: true + cap_drop: + - ALL + security_opt: + - no-new-privileges:true + environment: + - WAYBACK_LISTEN_ADDR=0.0.0.0:8964 + - WAYBACK_BOLT_PATH=/data/wayback.db + - WAYBACK_POOLING_SIZE=${WAYBACK_POOLING_SIZE} + - WAYBACK_TIMEOUT=${WAYBACK_TIMEOUT} + - WAYBACK_MAX_MEDIA_SIZE=${WAYBACK_MAX_MEDIA_SIZE} + - WAYBACK_ONION_DISABLED=true + volumes: + - "${DATA_PATH}:/data" + tmpfs: + - /tmp:rw,noexec,nosuid,size=256m + healthcheck: + test: ["CMD-SHELL", "wget -q -O - http://127.0.0.1:8964/healthcheck | grep -qx OK"] + interval: 10s + timeout: 5s + start_period: 20s + retries: 12 + labels: + createdBy: "Apps" + +networks: + 1panel-network: + external: true diff --git a/apps/wayback/latest/scripts/init.sh b/apps/wayback/latest/scripts/init.sh new file mode 100755 index 000000000..c78f96639 --- /dev/null +++ b/apps/wayback/latest/scripts/init.sh @@ -0,0 +1,66 @@ +#!/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="$(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" +} + +validate_ipv4() { + local value="$1" + local part + local -a parts + IFS='.' read -r -a parts <<< "$value" + [[ ${#parts[@]} -eq 4 ]] || return 1 + for part in "${parts[@]}"; do + [[ "$part" =~ ^[0-9]{1,3}$ ]] || return 1 + (( 10#$part <= 255 )) || return 1 + done +} + +[[ -f "$ENV_FILE" ]] || fail "$ENV_FILE not found" +[[ ! -L "$ENV_FILE" ]] || fail "$ENV_FILE must not be a symbolic link" + +bind_address="$(read_env_value PANEL_APP_BIND_ADDRESS)" +validate_ipv4 "$bind_address" || fail "PANEL_APP_BIND_ADDRESS must be an IPv4 address" + +pooling_size="$(read_env_value WAYBACK_POOLING_SIZE)" +[[ "$pooling_size" =~ ^[0-9]+$ ]] || fail "WAYBACK_POOLING_SIZE must be an integer" +(( pooling_size >= 1 && pooling_size <= 32 )) || fail "WAYBACK_POOLING_SIZE must be between 1 and 32" + +timeout="$(read_env_value WAYBACK_TIMEOUT)" +[[ "$timeout" =~ ^[0-9]+$ ]] || fail "WAYBACK_TIMEOUT must be an integer" +(( timeout >= 10 && timeout <= 3600 )) || fail "WAYBACK_TIMEOUT must be between 10 and 3600" + +media_size="$(read_env_value WAYBACK_MAX_MEDIA_SIZE)" +[[ "$media_size" =~ ^[1-9][0-9]{0,4}(MB|GB)$ ]] || fail "WAYBACK_MAX_MEDIA_SIZE must use MB or GB, for example 512MB" + +data_path="$(read_env_value DATA_PATH)" +[[ "$data_path" =~ ^\./[A-Za-z0-9._-]+(/[A-Za-z0-9._-]+)*$ ]] || fail "DATA_PATH must be a relative path inside the app directory" +[[ "/$data_path/" != *"/../"* ]] || fail "DATA_PATH must not contain parent traversal" + +data_dir="${ROOT_DIR}/${data_path#./}" +canonical_root="$(realpath -m -- "$ROOT_DIR")" +canonical_data="$(realpath -m -- "$data_dir")" +[[ "$canonical_data" == "$canonical_root"/* ]] || fail "DATA_PATH resolves outside the app directory" +[[ ! -L "$data_dir" ]] || fail "DATA_PATH must not be a symbolic link" + +umask 077 +mkdir -p "$data_dir" +chown -R 100:101 "$data_dir" +chmod 750 "$data_dir" +chmod 600 "$ENV_FILE" diff --git a/apps/wayback/latest/scripts/uninstall.sh b/apps/wayback/latest/scripts/uninstall.sh new file mode 100755 index 000000000..5c199242b --- /dev/null +++ b/apps/wayback/latest/scripts/uninstall.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -euo pipefail + +if command -v docker-compose >/dev/null 2>&1; then + docker-compose down --remove-orphans +else + docker compose down --remove-orphans +fi diff --git a/apps/wayback/latest/scripts/upgrade.sh b/apps/wayback/latest/scripts/upgrade.sh new file mode 100755 index 000000000..593b31667 --- /dev/null +++ b/apps/wayback/latest/scripts/upgrade.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" +exec bash "${SCRIPT_DIR}/init.sh" diff --git a/apps/wayback/logo.png b/apps/wayback/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..8b8255da962450a43fa1fa2233b6d39d1ecf09ad GIT binary patch literal 9415 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 o{GLZ{p8S9EXED2xcmQyHop2<8N()UI1qA|>