FossilRepo

fossilrepo / docker / fossil-shell
Blame History Raw 66 lines
1
#!/bin/bash
2
# fossil-shell — Forced command for SSH-based Fossil clone/push/pull.
3
#
4
# Each authorized_keys entry uses:
5
# command="/usr/local/bin/fossil-shell <username>",no-port-forwarding,...
6
#
7
# When a Fossil client connects via SSH, it sends a command like:
8
# fossil http /path/to/repo.fossil
9
# which arrives in $SSH_ORIGINAL_COMMAND.
10
#
11
# This script:
12
# 1. Extracts the repo name from the SSH command
13
# 2. Maps it to the on-disk .fossil file
14
# 3. Runs fossil http in CGI mode with --localauth
15
#
16
# Auth is already handled by the SSH key → user mapping in authorized_keys.
17
18
set -euo pipefail
19
20
FOSSIL_USER="${1:-anonymous}"
21
REPO_DIR="${FOSSIL_DATA_DIR:-/data/repos}"
22
23
# Validate SSH_ORIGINAL_COMMAND
24
if [ -z "${SSH_ORIGINAL_COMMAND:-}" ]; then
25
echo "Error: Interactive SSH sessions are not supported." >&2
26
echo "Use: fossil clone ssh://fossil@<host>/<project-slug> local.fossil" >&2
27
exit 1
28
fi
29
30
# Fossil SSH sends: fossil http <repo-path> --args...
31
# We only allow "fossil http" commands.
32
if ! echo "$SSH_ORIGINAL_COMMAND" | grep -qE '^fossil\s+http\s+'; then
33
echo "Error: Only fossil http commands are allowed." >&2
34
exit 1
35
fi
36
37
# Extract the repo identifier (second argument after "fossil http")
38
REPO_ARG=$(echo "$SSH_ORIGINAL_COMMAND" | awk '{print $3}')
39
40
if [ -z "$REPO_ARG" ]; then
41
echo "Error: No repository specified." >&2
42
exit 1
43
fi
44
45
# Strip any path components — only allow bare slugs or slug.fossil
46
REPO_NAME=$(basename "$REPO_ARG" .fossil)
47
48
# Sanitize: only allow alphanumeric, hyphens, underscores
49
if ! echo "$REPO_NAME" | grep -qE '^[a-zA-Z0-9_-]+$'; then
50
echo "Error: Invalid repository name." >&2
51
exit 1
52
fi
53
54
REPO_PATH="${REPO_DIR}/${REPO_NAME}.fossil"
55
56
if [ ! -f "$REPO_PATH" ]; then
57
echo "Error: Repository '${REPO_NAME}' not found." >&2
58
exit 1
59
fi
60
61
# Log the access
62
logger -t fossil-shell "user=${FOSSIL_USER} repo=${REPO_NAME} action=ssh-sync"
63
64
# Run fossil http in CGI mode
65
exec fossil http "$REPO_PATH" --localauth
66

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button