|
4ce269c…
|
ragelink
|
1 |
# fossilrepo backend — Django + HTMX + Fossil binary |
|
4ce269c…
|
ragelink
|
2 |
# |
|
4ce269c…
|
ragelink
|
3 |
# Omnibus: bundles Fossil from source for repo init/management. |
|
4ce269c…
|
ragelink
|
4 |
|
|
4ce269c…
|
ragelink
|
5 |
# ── Stage 1: Build Fossil from source ────────────────────────────────────── |
|
4ce269c…
|
ragelink
|
6 |
|
|
4ce269c…
|
ragelink
|
7 |
FROM debian:bookworm-slim AS fossil-builder |
|
4ce269c…
|
ragelink
|
8 |
|
|
4ce269c…
|
ragelink
|
9 |
ARG FOSSIL_VERSION=2.24 |
|
4ce269c…
|
ragelink
|
10 |
|
|
4ce269c…
|
ragelink
|
11 |
RUN apt-get update && apt-get install -y --no-install-recommends \ |
|
4ce269c…
|
ragelink
|
12 |
build-essential curl ca-certificates zlib1g-dev libssl-dev tcl \ |
|
4ce269c…
|
ragelink
|
13 |
&& rm -rf /var/lib/apt/lists/* |
|
4ce269c…
|
ragelink
|
14 |
|
|
4ce269c…
|
ragelink
|
15 |
WORKDIR /build |
|
4ce269c…
|
ragelink
|
16 |
RUN curl -sSL "https://fossil-scm.org/home/tarball/version-${FOSSIL_VERSION}/fossil-src-${FOSSIL_VERSION}.tar.gz" \ |
|
4ce269c…
|
ragelink
|
17 |
-o fossil.tar.gz \ |
|
4ce269c…
|
ragelink
|
18 |
&& tar xzf fossil.tar.gz \ |
|
4ce269c…
|
ragelink
|
19 |
&& cd fossil-src-${FOSSIL_VERSION} \ |
|
4ce269c…
|
ragelink
|
20 |
&& ./configure --prefix=/usr/local --with-openssl=auto --json \ |
|
4ce269c…
|
ragelink
|
21 |
&& make -j$(nproc) \ |
|
4ce269c…
|
ragelink
|
22 |
&& make install |
|
4ce269c…
|
ragelink
|
23 |
|
|
4ce269c…
|
ragelink
|
24 |
# ── Stage 2: Runtime image ───────────────────────────────────────────────── |
|
4ce269c…
|
ragelink
|
25 |
|
|
4ce269c…
|
ragelink
|
26 |
FROM python:3.12-slim-bookworm |
|
4ce269c…
|
ragelink
|
27 |
|
|
4ce269c…
|
ragelink
|
28 |
RUN apt-get update && apt-get install -y --no-install-recommends \ |
|
c588255…
|
ragelink
|
29 |
postgresql-client ca-certificates zlib1g libssl3 openssh-server git \ |
|
4ce269c…
|
ragelink
|
30 |
&& rm -rf /var/lib/apt/lists/* |
|
4ce269c…
|
ragelink
|
31 |
|
|
4ce269c…
|
ragelink
|
32 |
# Copy Fossil binary from builder |
|
4ce269c…
|
ragelink
|
33 |
COPY --from=fossil-builder /usr/local/bin/fossil /usr/local/bin/fossil |
|
4ce269c…
|
ragelink
|
34 |
RUN fossil version |
|
4ce269c…
|
ragelink
|
35 |
|
|
4ce269c…
|
ragelink
|
36 |
RUN pip install --no-cache-dir uv |
|
4ce269c…
|
ragelink
|
37 |
|
|
4ce269c…
|
ragelink
|
38 |
WORKDIR /app |
|
4ce269c…
|
ragelink
|
39 |
|
|
4ce269c…
|
ragelink
|
40 |
COPY pyproject.toml ./ |
|
4ce269c…
|
ragelink
|
41 |
RUN uv pip install --system --no-cache -r pyproject.toml |
|
4ce269c…
|
ragelink
|
42 |
|
|
4ce269c…
|
ragelink
|
43 |
COPY . . |
|
4ce269c…
|
ragelink
|
44 |
|
|
c588255…
|
ragelink
|
45 |
RUN DJANGO_SECRET_KEY=build-placeholder DJANGO_DEBUG=true python manage.py collectstatic --noinput |
|
c588255…
|
ragelink
|
46 |
|
|
c588255…
|
ragelink
|
47 |
# Create data directories |
|
c588255…
|
ragelink
|
48 |
RUN mkdir -p /data/repos /data/trash /data/ssh |
|
c588255…
|
ragelink
|
49 |
|
|
c588255…
|
ragelink
|
50 |
# SSH setup — restricted fossil user + sshd for clone/push |
|
c588255…
|
ragelink
|
51 |
RUN useradd -r -m -d /home/fossil -s /usr/sbin/nologin fossil \ |
|
c588255…
|
ragelink
|
52 |
&& mkdir -p /run/sshd /home/fossil/.ssh \ |
|
c588255…
|
ragelink
|
53 |
&& chown fossil:fossil /home/fossil/.ssh \ |
|
c588255…
|
ragelink
|
54 |
&& chmod 700 /home/fossil/.ssh |
|
c588255…
|
ragelink
|
55 |
|
|
c588255…
|
ragelink
|
56 |
COPY docker/sshd_config /etc/ssh/sshd_config |
|
c588255…
|
ragelink
|
57 |
COPY docker/fossil-shell /usr/local/bin/fossil-shell |
|
c588255…
|
ragelink
|
58 |
RUN chmod +x /usr/local/bin/fossil-shell |
|
c588255…
|
ragelink
|
59 |
|
|
c588255…
|
ragelink
|
60 |
# Generate host keys if they don't exist (entrypoint will handle persistent keys) |
|
c588255…
|
ragelink
|
61 |
RUN ssh-keygen -A |
|
4ce269c…
|
ragelink
|
62 |
|
|
c588255…
|
ragelink
|
63 |
# Create non-root app user for running gunicorn |
|
c588255…
|
ragelink
|
64 |
RUN useradd -r -m -d /home/app -s /bin/false app \ |
|
c588255…
|
ragelink
|
65 |
&& chown -R app:app /app /data |
|
4ce269c…
|
ragelink
|
66 |
|
|
4ce269c…
|
ragelink
|
67 |
ENV PYTHONUNBUFFERED=1 |
|
4ce269c…
|
ragelink
|
68 |
ENV PYTHONDONTWRITEBYTECODE=1 |
|
4ce269c…
|
ragelink
|
69 |
ENV DJANGO_SETTINGS_MODULE=config.settings |
|
4ce269c…
|
ragelink
|
70 |
|
|
c588255…
|
ragelink
|
71 |
EXPOSE 8000 2222 |
|
c588255…
|
ragelink
|
72 |
|
|
c588255…
|
ragelink
|
73 |
COPY docker/entrypoint.sh /usr/local/bin/entrypoint.sh |
|
c588255…
|
ragelink
|
74 |
RUN chmod +x /usr/local/bin/entrypoint.sh |
|
c588255…
|
ragelink
|
75 |
|
|
c588255…
|
ragelink
|
76 |
# Install gosu for privilege dropping in entrypoint |
|
c588255…
|
ragelink
|
77 |
RUN apt-get update && apt-get install -y --no-install-recommends gosu && rm -rf /var/lib/apt/lists/* |
|
4ce269c…
|
ragelink
|
78 |
|
|
c588255…
|
ragelink
|
79 |
# Entrypoint runs as root (to start sshd), then drops to app user for gunicorn |
|
c588255…
|
ragelink
|
80 |
CMD ["/usr/local/bin/entrypoint.sh"] |