# Alpine dev container with dropbear SSH access and this dotfiles repo
# pre-cloned and installed.
#
# Build:
#   docker build -t dev-container \
#     --build-arg USERNAME=dafu \
#     --build-arg GITHUB_USER=dafu \
#     devcontainer
#
# Run:
#   docker run -d -p 2222:22 --name dev-container dev-container
#   ssh -p 2222 dafu@localhost

FROM alpine:latest

ARG USERNAME=dafu
# public keys are pulled from https://github.com/<GITHUB_USER>.keys at build time
ARG GITHUB_USER=dafu
ARG REPO_URL=https://git.dafu.dev/dafu/dot.config.git
# gid of the docker group on the host, so it lines up with the mounted
# /var/run/docker.sock (check with: stat -c '%g' /var/run/docker.sock)
ARG DOCKER_GID=104

# edge repos, aliased so packages stay on the stable branch by default;
# pull a specific package from edge with `apk add <pkg>@edge`
RUN cat <<'EOF' > /etc/apk/repositories
https://dl-cdn.alpinelinux.org/alpine/edge/main
https://dl-cdn.alpinelinux.org/alpine/edge/community
https://dl-cdn.alpinelinux.org/alpine/edge/testing
EOF
RUN apk update

RUN apk add --no-cache \
        dropbear htop fd fzf fzf-tmux gnupg age go-task gopass ripgrep lnav lazygit mysql-client \
        nmap p7zip restic rsync shellcheck tree-sitter tree-sitter-cli tree-sitter-go tree-sitter-markdown \
        tzdata zk \
        git go \
        neovim \
        tmux \
        mksh \
        curl \
        foot-extra-terminfo \
        doas \
        docker-cli \
        tini

RUN ln -sf /usr/share/zoneinfo/Europe/Berlin /etc/localtime && \
    echo "Europe/Berlin" > /etc/timezone
ENV TZ=Europe/Berlin

# make mksh a valid login shell
RUN echo "/bin/mksh" >> /etc/shells

# create the user with mksh as its shell, no password (pubkey-only login)
RUN adduser -D -s /bin/mksh "$USERNAME"

# let the user talk to the docker socket mounted in at runtime without doas:
# reuse whatever group already owns DOCKER_GID, or create "docker" if free
RUN addgroup -g "$DOCKER_GID" docker 2>/dev/null; \
    docker_group="$(getent group "$DOCKER_GID" | cut -d: -f1)" && \
    addgroup "$USERNAME" "$docker_group"

# passwordless doas for package installs etc. (no password auth is set up
# for the user at all, so this must be nopass)
RUN echo "permit nopass $USERNAME as root" > /etc/doas.conf && \
    chown root:root /etc/doas.conf && \
    chmod 0400 /etc/doas.conf

# ssh access: authorized_keys sourced from GitHub, pubkey auth only
RUN mkdir -p "/home/$USERNAME/.ssh" && \
    curl -fsSL "https://github.com/${GITHUB_USER}.keys" -o "/home/$USERNAME/.ssh/authorized_keys" && \
    test -s "/home/$USERNAME/.ssh/authorized_keys" && \
    chown -R "$USERNAME:$USERNAME" "/home/$USERNAME/.ssh" && \
    chmod 700 "/home/$USERNAME/.ssh" && \
    chmod 600 "/home/$USERNAME/.ssh/authorized_keys"

# clone the dotfiles repo and run its installer as the login user
USER $USERNAME
RUN git clone "$REPO_URL" "/home/$USERNAME/.config" && \
    "/home/$USERNAME/.config/install.sh"
USER root

RUN mkdir -p /etc/dropbear

# crontab spool lives on the home-data volume so it survives rebuilds; the
# standard /var/spool/cron/crontabs path is symlinked to it so crond and
# `crontab -e` keep working with no extra flags
RUN mkdir -p "/home/$USERNAME/.crontabs" && \
    touch "/home/$USERNAME/.crontabs/$USERNAME" && \
    chown -R "$USERNAME:$USERNAME" "/home/$USERNAME/.crontabs" && \
    chmod 700 "/home/$USERNAME/.crontabs" && \
    chmod 600 "/home/$USERNAME/.crontabs/$USERNAME" && \
    mkdir -p /var/spool/cron && \
    ln -s "/home/$USERNAME/.crontabs" /var/spool/cron/crontabs

RUN <<'EOF' cat > /usr/local/bin/entrypoint.sh
#!/bin/sh
set -e

# host keys are generated on first start rather than at build time, so a
# shared private key never ends up baked into the image.
for t in rsa ed25519; do
    key="/etc/dropbear/dropbear_${t}_host_key"
    [ -f "$key" ] || dropbearkey -t "$t" -f "$key"
done

# busybox crond daemonizes itself by default (no -f), so this returns
# immediately; tini (real PID 1) reaps it and any of its orphaned children
crond -L /dev/stdout

# -F: foreground, -E: log to stderr, -w: no root login, -s: no password auth
exec dropbear -F -E -w -s -p 22
EOF
RUN chmod +x /usr/local/bin/entrypoint.sh

EXPOSE 22
ENTRYPOINT ["/sbin/tini", "--", "/usr/local/bin/entrypoint.sh"]
