Personal docker image setups for Knot/Spindle

Initial commit, basic knot & spindle image setup

Changed files
+196
rootfs
etc
s6-overlay
s6-rc.d
create-sshd-host-keys
knotserver
dependencies.d
run
sshd
user
contents.d
scripts
ssh
+70
Dockerfile
···
···
+
FROM golang:1.25-alpine AS builder
+
ENV KNOT_REPO_SCAN_PATH=/home/git/repositories
+
ENV CGO_ENABLED=1
+
+
ARG TAG='v1.11.0-alpha'
+
+
WORKDIR /app
+
RUN apk add git gcc musl-dev
+
RUN git clone -b ${TAG} https://tangled.org/tangled.org/core .
+
+
FROM builder AS build-knot
+
RUN go build -o /usr/bin/knot -ldflags '-s -w -extldflags "-static"' ./cmd/knot
+
+
FROM builder AS build-spindle
+
RUN go build -o /usr/bin/spindle -ldflags '-s -w -extldflags "-static"' ./cmd/spindle
+
+
FROM alpine:edge AS knot
+
EXPOSE 5555
+
EXPOSE 22
+
+
LABEL org.opencontainers.image.title='knot'
+
LABEL org.opencontainers.image.description='data server for tangled'
+
LABEL org.opencontainers.image.source='https://tangled.org/sachy.dev/knot-spindle-docker'
+
LABEL org.opencontainers.image.url='https://tangled.org'
+
LABEL org.opencontainers.image.vendor='tangled.org'
+
LABEL org.opencontainers.image.licenses='MIT'
+
+
ARG UID=1000
+
ARG GID=1000
+
+
COPY rootfs .
+
RUN chmod 755 /etc
+
RUN chmod -R 755 /etc/s6-overlay
+
RUN apk add shadow s6-overlay execline openssl openssh git curl bash
+
RUN groupadd -g $GID -f git
+
RUN useradd -u $UID -g $GID -d /home/git git
+
RUN openssl rand -hex 16 | passwd --stdin git
+
RUN mkdir -p /home/git/repositories && chown -R git:git /home/git
+
COPY --from=build-knot /usr/bin/knot /usr/bin
+
RUN mkdir /app && chown -R git:git /app
+
+
HEALTHCHECK --interval=60s --timeout=30s --start-period=5s --retries=3 \
+
CMD curl -f http://localhost:5555 || exit 1
+
+
ENTRYPOINT ["/init"]
+
+
FROM alpine:edge AS spindle
+
+
EXPOSE 6555
+
+
LABEL org.opencontainers.image.title="spindle"
+
LABEL org.opencontainers.image.description="ci server for tangled"
+
LABEL org.opencontainers.image.source="https://tangled.org/sachy.dev/knot-spindle-docker"
+
LABEL org.opencontainers.image.url="https://tangled.org"
+
LABEL org.opencontainers.image.vendor="tangled.org"
+
LABEL org.opencontainers.image.licenses="MIT"
+
+
ARG UID=1000
+
ARG GID=1000
+
+
RUN adduser --system --uid $UID spindle
+
RUN addgroup --system --gid $UID spindle
+
RUN mkdir -p /app && chown -R spindle:spindle /app
+
COPY --from=build-spindle /usr/bin/spindle /usr/bin
+
+
WORKDIR /app
+
CMD ["spindle"]
+
VOLUME ["/app"]
+
HEALTHCHECK --interval=60s --timeout=30s --start-period=5s --retries=3 \
+
CMD curl -f http://localhost:6555 || exit 1
+21
LICENSE-MIT
···
···
+
MIT License
+
+
Copyright (c) 2025 Sachy.dev
+
+
Permission is hereby granted, free of charge, to any person obtaining a copy
+
of this software and associated documentation files (the "Software"), to deal
+
in the Software without restriction, including without limitation the rights
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+
copies of the Software, and to permit persons to whom the Software is
+
furnished to do so, subject to the following conditions:
+
+
The above copyright notice and this permission notice shall be included in all
+
copies or substantial portions of the Software.
+
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+
SOFTWARE.
+5
README.md
···
···
+
# Sachy's Knot/Spindle Docker images
+
+
More info TBA
+
+
Licensed under MIT
+49
docker-bake.hcl
···
···
+
variable "UID" {
+
default = "1000"
+
}
+
+
variable "GID" {
+
default = "1000"
+
}
+
+
group "edge" {
+
targets = ["knot-edge", "spindle-edge"]
+
}
+
+
target "knot-edge" {
+
context = "."
+
target = "knot"
+
args = {
+
TAG = "master"
+
UID = UID
+
GID = GID
+
}
+
tags = ["sachymetsu/knot:edge"]
+
}
+
+
target "spindle-edge" {
+
context = "."
+
target = "spindle"
+
args = {
+
TAG = "master"
+
UID = UID
+
GID = GID
+
}
+
tags = ["sachymetsu/spindle:edge"]
+
}
+
+
target "latest" {
+
name = "${APP}-${replace(TAG, ".", "-")}"
+
context = "."
+
matrix = {
+
APP = ["knot", "spindle"]
+
TAG = ["v1.11.0-alpha"]
+
}
+
target = "${APP}"
+
args = {
+
TAG = "${TAG}"
+
UID = UID
+
GID = GID
+
}
+
tags = ["sachymetsu/${APP}:${TAG}"]
+
}
+1
rootfs/etc/s6-overlay/s6-rc.d/create-sshd-host-keys/type
···
···
+
oneshot
+1
rootfs/etc/s6-overlay/s6-rc.d/create-sshd-host-keys/up
···
···
+
/etc/s6-overlay/scripts/create-sshd-host-keys
rootfs/etc/s6-overlay/s6-rc.d/knotserver/dependencies.d/base

This is a binary file and will not be displayed.

+3
rootfs/etc/s6-overlay/s6-rc.d/knotserver/run
···
···
+
#!/command/with-contenv ash
+
+
exec s6-setuidgid git /usr/bin/knot server
+1
rootfs/etc/s6-overlay/s6-rc.d/knotserver/type
···
···
+
longrun
rootfs/etc/s6-overlay/s6-rc.d/sshd/dependencies.d/base

This is a binary file and will not be displayed.

rootfs/etc/s6-overlay/s6-rc.d/sshd/dependencies.d/create-sshd-host-keys

This is a binary file and will not be displayed.

+3
rootfs/etc/s6-overlay/s6-rc.d/sshd/run
···
···
+
#!/usr/bin/execlineb -P
+
+
/usr/sbin/sshd -e -D
+1
rootfs/etc/s6-overlay/s6-rc.d/sshd/type
···
···
+
longrun
rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/knotserver

This is a binary file and will not be displayed.

rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/sshd

This is a binary file and will not be displayed.

+21
rootfs/etc/s6-overlay/scripts/create-sshd-host-keys
···
···
+
#!/usr/bin/execlineb -P
+
+
foreground {
+
if -n { test -d /etc/ssh/keys }
+
mkdir /etc/ssh/keys
+
}
+
+
foreground {
+
if -n { test -f /etc/ssh/keys/ssh_host_rsa_key }
+
ssh-keygen -t rsa -f /etc/ssh/keys/ssh_host_rsa_key -q -N ""
+
}
+
+
foreground {
+
if -n { test -f /etc/ssh/keys/ssh_host_ecdsa_key }
+
ssh-keygen -t rsa -f /etc/ssh/keys/ssh_host_ecdsa_key -q -N ""
+
}
+
+
foreground {
+
if -n { test -f /etc/ssh/keys/ssh_host_ed25519_key }
+
ssh-keygen -t rsa -f /etc/ssh/keys/ssh_host_ed25519_key -q -N ""
+
}
+8
rootfs/etc/s6-overlay/scripts/keys-wrapper
···
···
+
#!/bin/sh
+
+
# Execute the knot keys command with proper shell context
+
exec /bin/sh -c '/usr/bin/knot keys -output authorized-keys \
+
-internal-api "http://${KNOT_SERVER_INTERNAL_LISTEN_ADDR:-localhost:5444}" \
+
-git-dir "${KNOT_REPO_SCAN_PATH:-/home/git/repositories}" \
+
-log-path "/tmp/knotguard.log"'
+
+3
rootfs/etc/ssh/sshd_config.d/authorized_keys_command.conf
···
···
+
Match User git
+
AuthorizedKeysCommand /usr/bin/knot keys -o authorized-keys -git-dir /home/git/repositories
+
AuthorizedKeysCommandUser nobody
+9
rootfs/etc/ssh/sshd_config.d/tangled_sshd.conf
···
···
+
HostKey /etc/ssh/keys/ssh_host_rsa_key
+
HostKey /etc/ssh/keys/ssh_host_ecdsa_key
+
HostKey /etc/ssh/keys/ssh_host_ed25519_key
+
+
PasswordAuthentication no
+
+
Match User git
+
AuthorizedKeysCommand /etc/s6-overlay/scripts/keys-wrapper
+
AuthorizedKeysCommandUser nobody