Monorepo for Tangled
tangled.org
1# Development only. Not for production use.
2
3FROM golang:1.25-alpine AS builder
4
5RUN apk add --no-cache git build-base sqlite-dev
6
7ENV CGO_ENABLED=1
8ENV GOCACHE=/go/cache
9ENV GOMODCACHE=/go/mod
10
11WORKDIR /src
12
13COPY go.mod go.sum ./
14RUN --mount=type=cache,target=/go/cache \
15 --mount=type=cache,target=/go/mod \
16 go mod download
17
18COPY . .
19RUN --mount=type=cache,target=/go/cache \
20 --mount=type=cache,target=/go/mod \
21 go build -tags libsqlite3 -o /out/knot ./cmd/knot
22
23FROM alpine:3.20
24
25RUN apk add --no-cache git openssh-server tini sqlite-libs su-exec ca-certificates shadow openssl bash
26
27RUN groupadd -g 1000 -f git && \
28 useradd -u 1000 -g 1000 -d /home/git -s /bin/sh -m git && \
29 echo "git:$(openssl rand -hex 16)" | chpasswd
30
31COPY --from=builder /out/knot /usr/local/bin/knot
32RUN chmod 0755 /usr/local/bin/knot
33
34COPY <<'EOF' /usr/local/bin/knot-keys-wrapper
35#!/bin/sh
36exec /usr/local/bin/knot keys -output authorized-keys \
37 -internal-api "http://${KNOT_SERVER_INTERNAL_LISTEN_ADDR:-127.0.0.1:5444}" \
38 -git-dir "${KNOT_REPO_SCAN_PATH:-/home/git/repositories}" \
39 -log-path "/tmp/knotguard.log"
40EOF
41RUN chmod +x /usr/local/bin/knot-keys-wrapper
42
43# sshd config
44COPY <<'EOF' /etc/ssh/sshd_config.d/knot.conf
45PermitRootLogin no
46PasswordAuthentication no
47ChallengeResponseAuthentication no
48
49Match User git
50 AuthorizedKeysCommand /usr/local/bin/knot-keys-wrapper
51 AuthorizedKeysCommandUser nobody
52EOF
53
54RUN echo 'Include /etc/ssh/sshd_config.d/*.conf' >> /etc/ssh/sshd_config
55
56COPY <<'EOF' /etc/ssh/sshd_config.d/host-keys.conf
57HostKey /etc/ssh/keys/ssh_host_rsa_key
58HostKey /etc/ssh/keys/ssh_host_ecdsa_key
59HostKey /etc/ssh/keys/ssh_host_ed25519_key
60EOF
61
62RUN mkdir -p /home/git/.config/git
63COPY <<'EOF' /home/git/.config/git/config
64[user]
65 name = Tangled
66 email = noreply@tangled.org
67[receive]
68 advertisePushOptions = true
69[uploadpack]
70 allowFilter = true
71 allowReachableSHA1InWant = true
72EOF
73RUN mkdir -p /home/git/repositories && chown -R git:git /home/git
74
75COPY <<'EOF' /usr/local/bin/knot-entrypoint.sh
76#!/bin/sh
77set -eu
78[ -z "${KNOT_SERVER_OWNER:-}" ] && [ -r /shared/owner-did ] && \
79 export KNOT_SERVER_OWNER="$(cat /shared/owner-did)"
80: "${KNOT_SERVER_OWNER:?set via env or /shared/owner-did}"
81
82mkdir -p /etc/ssh/keys
83[ -f /etc/ssh/keys/ssh_host_rsa_key ] || ssh-keygen -t rsa -f /etc/ssh/keys/ssh_host_rsa_key -q -N ""
84[ -f /etc/ssh/keys/ssh_host_ecdsa_key ] || ssh-keygen -t ecdsa -f /etc/ssh/keys/ssh_host_ecdsa_key -q -N ""
85[ -f /etc/ssh/keys/ssh_host_ed25519_key ] || ssh-keygen -t ed25519 -f /etc/ssh/keys/ssh_host_ed25519_key -q -N ""
86
87/usr/sbin/sshd -D -e &
88exec su-exec git /usr/local/bin/knot server
89EOF
90RUN chmod +x /usr/local/bin/knot-entrypoint.sh
91
92VOLUME /home/git
93EXPOSE 22 5555
94
95ENTRYPOINT ["/sbin/tini", "--"]
96CMD ["/usr/local/bin/knot-entrypoint.sh"]