dotfiles/dev.Dockerfile

118 lines
4.6 KiB
Docker

FROM debian:trixie-slim
ENV TZ=America/New_York
ARG DEBIAN_FRONTEND=noninteractive
# Build-time args -> baked into the image as env vars for later use
ARG DOTFILES_USER=cobertos
ARG DOTFILES_EMAIL=me+git@cobertos.com
ARG DOTFILES_GIT_DEFAULT_BRANCH=owo
ARG DOTFILES_ENVIRONMENT=bare
ARG DOTFILES_ARCHITECTURE=x86_64-linux
ENV DOTFILES_USER=${DOTFILES_USER}
ENV DOTFILES_ENVIRONMENT=${DOTFILES_ENVIRONMENT}
ENV DOTFILES_ARCHITECTURE=${DOTFILES_ARCHITECTURE}
ENV DOTFILES_LOG_SHELL_TO_DOCKER=1
# Nix installer args
# Look up at https://github.com/NixOS/nix-installer/releases
# Version corresponds to nix version at https://releases.nixos.org
ARG NIX_INSTALLER_VERSION=2.34.6
ARG NIX_INSTALLER_ARCHITECTURE=${DOTFILES_ARCHITECTURE}
# Deps before we start doing things
RUN apt-get update \
&& apt-get install -y ca-certificates sudo xz-utils curl \
&& rm -rf /var/lib/apt/lists/*
# Install nix multi-user (must be root)
# The install process is pretty involved for multi-user install so unfortunately
# we will use a script for this and not do it ourselves :(
# In general I have to configure nix through this instead of with directly writing
# nix.conf as this installer will clobber any changes we make
# https://github.com/NixOS/nix-installer/blob/main/README.md#in-a-container
RUN curl -sSfL https://github.com/NixOS/nix-installer/releases/download/${NIX_INSTALLER_VERSION}/nix-installer-${NIX_INSTALLER_ARCHITECTURE} -o nix-installer \
&& chmod +x nix-installer \
&& ./nix-installer install linux --extra-conf "sandbox = false" --enable-flakes --no-confirm --init none
ENV PATH="${PATH}:/nix/var/nix/profiles/default/bin"
# Setup nix entrypoint. Needs to run as root so we can write to /usr/local/bin.
# (quoted heredoc 'EOF' does no variable expansion)
# I'm actually really surprised && part of this works, but it does. This is because
# heredoc follows the command. I hate shell :3
USER root
RUN cat > /usr/local/bin/entrypoint.sh <<'EOF' \
&& chmod +x /usr/local/bin/entrypoint.sh
#!/usr/bin/env bash
set -e
# Start the nix-daemon (needs root) if its socket isn't already present
if [ ! -S /nix/var/nix/daemon-socket/socket ]; then
sudo sh -c 'nohup /nix/var/nix/profiles/default/bin/nix-daemon >/var/log/nix-daemon.log 2>&1 &'
# wait for the socket to appear
for i in $(seq 1 30); do
[ -S /nix/var/nix/daemon-socket/socket ] && break
sleep 0.2
done
fi
# Make sure nix itself is on PATH (daemon profile, not the user's broken one)
. /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
# If we persist the users home directory as a docker volume, updating the
# underlying image will break the old persisted home directory. This will
# check if the symlink at ~/.nix-profile is broken and rebuild it
HM_LINK="$HOME/.nix-profile"
if [ ! -e "$HM_LINK" ] || { [ -L "$HM_LINK" ] && [ ! -e "$HM_LINK" ]; }; then
echo "[entrypoint] home-manager profile broken/missing — re-running switch..."
nix run home-manager/master -- switch --flake "/dotfiles#${DOTFILES_ENVIRONMENT}"
fi
# Run whatever the user passed into the container after we started the daemon
# (defaults to sleep infinity but might be something else)
exec "$@"
EOF
# Setup user
RUN groupadd -g 1000 ${DOTFILES_USER} && \
useradd -m -u 1000 -g 1000 -s /bin/bash ${DOTFILES_USER} && \
echo "${DOTFILES_USER} ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
USER ${DOTFILES_USER}
WORKDIR /home/${DOTFILES_USER}
ENV USER=${DOTFILES_USER}
ENV HOME=/home/${DOTFILES_USER}
# Copy the dotfiles repo, filling in any defaults from our environment variables
COPY --chown=1000:1000 . /dotfiles
RUN test ! -f /dotfiles/secrets.sh || (echo "Failsafe: secrets.sh should not have been copied into the build!" && exit 1)
# Add config.nix with Dockerfile configuration
RUN cat > /dotfiles/config.nix <<EOF
{
identity = {
username = "${DOTFILES_USER}";
git = {
name = "${DOTFILES_USER}";
email = "${DOTFILES_EMAIL}";
defaultBranch = "${DOTFILES_GIT_DEFAULT_BRANCH}";
};
};
dotfilesPath = "/dotfiles";
}
EOF
# Finally run home-manager to the expected DOTFILES_ENVIRONMENT
# Remove any files first that would get overwritten (so we dont need to make backups)
RUN rm -f /home/${DOTFILES_USER}/.bashrc /home/${DOTFILES_USER}/.profile /home/${DOTFILES_USER}/.bash_profile
# We run the nix daemon first so multi user install can actually use it
RUN sudo sh -c 'nohup /nix/var/nix/profiles/default/bin/nix-daemon >/tmp/nix-daemon.log 2>&1 &' \
&& sleep 2 \
&& nix run home-manager/master -- switch --flake "/dotfiles#${DOTFILES_ENVIRONMENT}" \
&& nix-collect-garbage -d \
&& nix store optimise
WORKDIR /home/${DOTFILES_USER}
CMD ["sleep", "infinity"]
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]