mirror of
https://github.com/migatu/conjurer.git
synced 2026-07-21 09:12:09 +00:00
33ec1c0e35
The Python half of the short-lived share links lived in the repo; the Apache config and the cron entries that make it work were hand-placed on the host, so the feature could not be rebuilt from a checkout. This adds the missing half. Scripts (defaults unchanged, so existing bare-metal cron keeps working): * scan_shares.py / revoke_shares.py take their paths from CONJURER_SHARE_* instead of hardcoding the Pi layout, and create their parent dirs; * the revoke TTL is now CONJURER_SHARE_TTL_SECONDS. Its --help claimed "2min" while the code used a hardcoded 3600 - the help text now reports the real, configured value. New share service: * docker/Dockerfile.share - Apache + the two jobs, reusing the same scripts rather than forking copies; * docker/share-vhost.conf.tpl - the previously undocumented Apache half. Three settings are load-bearing and commented as such: +FollowSymLinks (the shares ARE symlinks), -Indexes (a listing would expose every live token), and a deny rule for dotfiles (revoke_shares.py keeps .downloads.json - a map of every live token - inside the served directory); * docker/entrypoint.share.sh - renders the vhost, seeds the index on first run, then runs scanner/revoker in sleep loops beside Apache (no cron, so their output shows up in docker logs); * compose + env example, incl. the two volumes that MUST be shared with the musician (it creates the links and reads the index). docs/deployment/FILE_SHARING.md documents the mechanism, both deployment routes (docker and existing host Apache), the Discord command, why each Apache setting matters, verification commands, and the known limitations - notably that a link nobody ever downloads is never revoked, since the TTL starts at first download. Verified: scanner and revoker exercised end-to-end against temp dirs (index built; token recorded from a combined-format log line and the symlink unlinked). Compose file not validated - no docker on this machine. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
68 lines
2.7 KiB
Bash
Executable File
68 lines
2.7 KiB
Bash
Executable File
#!/bin/sh
|
|
# Entrypoint for the Conjurer share container: renders the vhost, seeds the
|
|
# share index, then runs the two periodic jobs alongside Apache.
|
|
#
|
|
# Cron is deliberately not used. Both scripts are already written to be safe to
|
|
# re-run (the scanner writes atomically, the revoker persists its log position),
|
|
# so plain sleep loops give the same result with one less moving part and with
|
|
# their output on the container's stdout where `docker logs` can see it.
|
|
set -eu
|
|
|
|
: "${CONJURER_SHARE_SERVER_NAME:=localhost}"
|
|
: "${CONJURER_SHARE_SCAN_PATH:=/mnt/shares}"
|
|
: "${CONJURER_SHARE_DB:=/srv/share/db/share_scan.json}"
|
|
: "${CONJURER_SHARE_DIR:=/var/www/html/share}"
|
|
: "${CONJURER_APACHE_LOG:=/var/log/apache2/share_access.log}"
|
|
: "${CONJURER_SHARE_SCAN_INTERVAL:=3600}"
|
|
: "${CONJURER_SHARE_REVOKE_INTERVAL:=60}"
|
|
: "${CONJURER_SHARE_TTL_SECONDS:=3600}"
|
|
export CONJURER_SHARE_SCAN_PATH CONJURER_SHARE_DB CONJURER_SHARE_DIR \
|
|
CONJURER_APACHE_LOG CONJURER_SHARE_TTL_SECONDS
|
|
|
|
# Render the vhost (same placeholder pattern as icecast.xml.tpl).
|
|
sed "s|__SERVER_NAME__|${CONJURER_SHARE_SERVER_NAME}|g" \
|
|
/app/share-vhost.conf.tpl > /etc/apache2/sites-available/000-default.conf
|
|
|
|
mkdir -p "$CONJURER_SHARE_DIR" \
|
|
"$(dirname "$CONJURER_SHARE_DB")" \
|
|
"$(dirname "$CONJURER_APACHE_LOG")" \
|
|
/var/run/apache2
|
|
chown -R www-data:www-data "$CONJURER_SHARE_DIR"
|
|
|
|
# revoke_shares.py seeks to a stored byte offset, so the log must exist before
|
|
# the first pass or it starts by reporting an error.
|
|
touch "$CONJURER_APACHE_LOG"
|
|
|
|
# Seed the index immediately when absent - otherwise /get_share_list returns
|
|
# nothing until the first scheduled scan, which looks like a broken feature.
|
|
if [ ! -f "$CONJURER_SHARE_DB" ]; then
|
|
echo "[share] no index at $CONJURER_SHARE_DB - running initial scan of $CONJURER_SHARE_SCAN_PATH"
|
|
python3 /app/scan_shares.py || echo "[share] initial scan failed, continuing"
|
|
fi
|
|
|
|
# Periodic index rebuild.
|
|
(
|
|
while true; do
|
|
sleep "$CONJURER_SHARE_SCAN_INTERVAL"
|
|
echo "[share] rescanning $CONJURER_SHARE_SCAN_PATH"
|
|
python3 /app/scan_shares.py || echo "[share] scan failed"
|
|
done
|
|
) &
|
|
SCAN_PID=$!
|
|
|
|
# Periodic revocation of links whose TTL expired after first download.
|
|
(
|
|
while true; do
|
|
sleep "$CONJURER_SHARE_REVOKE_INTERVAL"
|
|
python3 /app/revoke_shares.py || echo "[share] revoke failed"
|
|
done
|
|
) &
|
|
REVOKE_PID=$!
|
|
|
|
trap 'kill "$SCAN_PID" "$REVOKE_PID" 2>/dev/null || true' INT TERM
|
|
|
|
echo "[share] serving $CONJURER_SHARE_DIR as ${CONJURER_SHARE_SERVER_NAME}/share"
|
|
echo "[share] scan every ${CONJURER_SHARE_SCAN_INTERVAL}s, revoke sweep every ${CONJURER_SHARE_REVOKE_INTERVAL}s, TTL ${CONJURER_SHARE_TTL_SECONDS}s after first download"
|
|
|
|
exec apache2ctl -D FOREGROUND
|