-
-
Save aacater/6086b51732dfdd9a6ef0db6fa7d316d4 to your computer and use it in GitHub Desktop.
FROM node:18-slim | |
ARG USERNAME=borgwarehouse | |
ARG USER_UID=1001 | |
ARG USER_GID=$USER_UID | |
ARG SUDO_LINE="$USERNAME ALL=(ALL) NOPASSWD: /usr/sbin/useradd,/bin/mkdir,/usr/bin/touch,/bin/chmod,/bin/chown,/bin/bash,/usr/bin/jc,/usr/bin/jq,/bin/sed,/bin/grep,/usr/bin/stat,/usr/bin/borg,/bin/echo,/usr/sbin/userdel,/usr/sbin/service" | |
ENV DEBIAN_FRONTEND=noninteractive | |
RUN apt update && apt install -y --no-install-recommends \ | |
jc jq sudo borgbackup openssh-server openssl \ | |
&& rm -rf /var/lib/apt/lists/* /var/cache/apt | |
RUN addgroup --gid $USER_GID $USERNAME \ | |
&& adduser --disabled-login --disabled-password --uid $USER_UID --ingroup $USERNAME --gecos BorgWarehouse $USERNAME \ | |
&& echo $SUDO_LINE > /etc/sudoers.d/10-$USERNAME \ | |
&& chmod 0440 /etc/sudoers.d/10-$USERNAME | |
RUN echo -e "* * * * * root curl --request POST --url '$NEXTAUTH_URL/api/cronjob/checkStatus' --header 'Authorization: Bearer $CRONJOB_KEY' \n\ | |
* * * * * root curl --request POST --url '$NEXTAUTH_URL/api/cronjob/getStorageUsed' --header 'Authorization: Bearer $CRONJOB_KEY' \ | |
" > /etc/cron.d/borgwarehouse | |
USER $USERNAME | |
WORKDIR /app | |
COPY --chown=$USER_UID:$USER_GID package*.json . | |
RUN npm ci --only=production | |
COPY --chown=$USER_UID:$USER_GID . . | |
RUN chmod 700 /app/helpers/shells/* | |
RUN npm run build | |
EXPOSE 22 3000 | |
VOLUME /app/config | |
VOLUME /var/borgwarehouse | |
COPY entrypoint.sh /entrypoint.sh | |
ENTRYPOINT ["/entrypoint.sh"] | |
CMD ["init"] |
#!/bin/bash | |
CONFIG_DIR="/app/config" | |
sudo service ssh start &> /dev/null | |
if [ ! -f "$CONFIG_DIR/users.json" ];then | |
echo '[{"id":0,"email":"[email protected]","username":"admin","password":"$2a$12$20yqRnuaDBH6AE0EvIUcEOzqkuBtn1wDzJdw2Beg8w9S.vEqdso0a","roles":["admin"]}]' > "$CONFIG_DIR/users.json" | |
fi | |
if [ ! -f "$CONFIG_DIR/repo.json" ];then | |
echo '[]' > "$CONFIG_DIR/repo.json" | |
fi | |
if [ "$1" == "init" ] ; then | |
npm run start | |
exit | |
fi | |
exec "$@" |
@aacater I confirm that some commands are not placed in the same place on the docker version of debian, so the sudo file must be adapted 😕
When I build the docker image with the dockerfile, I'm stuck at the "npm ci" step because the user can't create anything in the /app folder which belongs to root.
I can build with this version :
FROM node:18-slim
ARG USERNAME=borgwarehouse
ARG USER_UID=1001
ARG USER_GID=$USER_UID
ARG SUDO_LINE="$USERNAME ALL=(ALL) NOPASSWD: /usr/sbin/useradd,/bin/mkdir,/usr/bin/touch,/bin/chmod,/bin/chown,/bin/bash,/usr/bin/jc,/usr/bin/jq,/bin/sed,/bin/grep,/usr/bin/stat,/usr/bin/borg,/bin/echo,/usr/sbin/userdel,/usr/sbin/service"
ENV DEBIAN_FRONTEND=noninteractive
RUN apt update && apt install -y --no-install-recommends \
jc jq sudo borgbackup openssh-server openssl \
&& rm -rf /var/lib/apt/lists/* /var/cache/apt
RUN addgroup --gid $USER_GID $USERNAME \
&& adduser --disabled-login --disabled-password --uid $USER_UID --ingroup $USERNAME --gecos BorgWarehouse $USERNAME \
&& echo $SUDO_LINE > /etc/sudoers.d/10-$USERNAME \
&& chmod 0440 /etc/sudoers.d/10-$USERNAME
RUN echo -e "* * * * * root curl --request POST --url '$NEXTAUTH_URL/api/cronjob/checkStatus' --header 'Authorization: Bearer $CRONJOB_KEY' \n\
* * * * * root curl --request POST --url '$NEXTAUTH_URL/api/cronjob/getStorageUsed' --header 'Authorization: Bearer $CRONJOB_KEY' \
" > /etc/cron.d/borgwarehouse
WORKDIR /app
RUN chown $USER_UID:$USER_GID /app
USER $USERNAME
COPY --chown=$USER_UID:$USER_GID package*.json ./
RUN npm ci --only=production
COPY --chown=$USER_UID:$USER_GID . .
RUN chmod 700 /app/helpers/shells/*
RUN npm run build
EXPOSE 22 3000
VOLUME /app/config
VOLUME /var/borgwarehouse
COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["init"]
WORKDIR is always execute with "root" if the folder exist. Don't you have any problem with your dockerfile version ? In my case, I need to chown /app
Everything works for me now. If your datas are not persistent, you have a problem with the rights on the locally mounted volumes. The environment variables are well read and it's working for me.
On the other hand I have another problem... the created UNIX users are not persistent... so when the container is restarted the data is there, but you can't edit it anymore, because the shell returns "the user doesn't exist" errors.
I continue in this way...
I think we need to make /etc/passwd and /etc/shadow persistent. What do you think ?
I've been looking at this after trying to get borgwarehouse working in docker, and I think trying to persist the passwd and shadow will be fraught with problems.
Instead I've been testing a "recreateRepo" script which can be called during entrypoint to create the users based off of the data in repos.json. Now when the docker is reset, we effectively recreate the users and update their authorized keys from the json to make sure it's all intact.
First I have the overall recreateRepos (note that jq is already being added in the dockerfile to the node-18:slim image being used):
#!/bin/bash
mapfile -t newValue < <(
jq -c -r '.[]' /app/config/repo.json
)
for item in "${newValue[@]}"; do
unixUser=$( echo ${item} | jq -c -r '.unixUser')
sshPublicKey=$( echo ${item} | jq -c -r '.sshPublicKey')
echo "user $unixUser / $sshPublicKey"
/app/recreateRepo.sh $unixUser "$sshPublicKey"
done
which then calls recreateRepo.sh (a trimmed down version of createRepo):
set -e
if [ "$1" == "" ] || [ "$2" == "" ];then
echo "This shell takes 2 arguments : Reponame, SSH Public Key"
exit 1
fi
pattern='(ssh-ed25519 AAAAC3NzaC1lZDI1NTE5|[email protected] AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29t|ssh-rsa AAAAB3NzaC1yc2)[0-9A-Za-z+/]+[=]{0,3}(\s.*)?'
if [[ ! "$2" =~ $pattern ]]
then
echo "Invalid public SSH KEY format. Provide a key in OpenSSH format (rsa, ed25519, ed25519-sk)"
exit 2
fi
user=$1
group="${user}"
home="/var/borgwarehouse/${user}"
pool="${home}/repos"
authorized_keys="${home}/.ssh/authorized_keys"
sudo useradd -d ${home} -s "/bin/bash" -m --badname ${user}
sudo mkdir -p ${home}/.ssh
sudo touch ${authorized_keys}
sudo chmod 777 ${authorized_keys}
sudo echo $2 > ${authorized_keys}
sudo mkdir -p "${pool}/$1"
sudo chmod -R 750 ${home}
sudo chmod 600 ${authorized_keys}
sudo chown -R ${user}:borgwarehouse ${home}
if [ ! -f "${authorized_keys}" ];then
echo "${authorized_keys} must be present"
exit 4
fi
echo ${user}
Then the modifed entrypoint.sh (this is already a mess anyway and the hardcoded user defaults should be moved to another helper script):
#!/bin/bash
CONFIG_DIR="/app/config"
sudo service ssh start &> /dev/null
if [ ! -f "$CONFIG_DIR/users.json" ];then
echo '[{"id":0,"email":"[email protected]","username":"admin","password":"$2a$12$20yqRnuaDBH6AE0EvIUcEOzqkuBtn1wDzJdw2Beg8w9S.vEqdso0a","roles":["admin"]}]' > "$CONFIG_DIR/users.json"
fi
if [ ! -f "$CONFIG_DIR/repo.json" ];then
echo '[]' > "$CONFIG_DIR/repo.json"
fi
/app/recreateRepos.sh
if [ "$1" == "init" ] ; then
npm run start
exit
fi
exec "$@"
and finally the Dockerfile (added adduser as well as one or two others that were causing sudo hangs during testing):
FROM node:18-slim
ARG USERNAME=borgwarehouse
ARG USER_UID=1900
ARG USER_GID=$USER_UID
ARG SUDO_LINE="$USERNAME ALL=(ALL) NOPASSWD: /usr/sbin/adduser,/usr/sbin/useradd,/bin/mkdir,/usr/bin/touch,/bin/chmod,/bin/chown,/bin/bash,/usr/bin/jc,/usr/bin/jq,/bin/sed,/bin/grep,/usr/bin/stat,/usr/bin/tee,/usr/bin/borg,/bin/echo,/usr/sbin/userdel,/usr/sbin/service"
ENV DEBIAN_FRONTEND=noninteractive
RUN apt update && apt install -y --no-install-recommends \
jc jq sudo borgbackup openssh-server openssl \
&& rm -rf /var/lib/apt/lists/* /var/cache/apt
RUN addgroup --gid $USER_GID $USERNAME \
&& adduser --disabled-login --disabled-password --uid $USER_UID --ingroup $USERNAME --gecos BorgWarehouse $USERNAME \
&& echo $SUDO_LINE > /etc/sudoers.d/10-$USERNAME \
&& chmod 0440 /etc/sudoers.d/10-$USERNAME
RUN echo -e "* * * * * root curl --request POST --url '$NEXTAUTH_URL/api/cronjob/checkStatus' --header 'Authorization: Bearer $CRONJOB_KEY' \n\
* * * * * root curl --request POST --url '$NEXTAUTH_URL/api/cronjob/getStorageUsed' --header 'Authorization: Bearer $CRONJOB_KEY' \
" > /etc/cron.d/borgwarehouse
WORKDIR /app
RUN chown $USER_UID:$USER_GID /app
USER $USERNAME
COPY --chown=$USER_UID:$USER_GID package*.json ./
RUN npm ci --only=production
COPY --chown=$USER_UID:$USER_GID . .
RUN chmod 700 /app/helpers/shells/*
RUN npm run build
EXPOSE 22 3000
VOLUME /app/config
VOLUME /var/borgwarehouse
COPY --chown=$USER_UID:$USER_GID docker/entrypoint.sh /app/entrypoint.sh
COPY --chown=$USER_UID:$USER_GID docker/recreateRepo.sh /app/recreateRepo.sh
COPY --chown=$USER_UID:$USER_GID docker/recreateRepos.sh /app/recreateRepos.sh
RUN chmod +x /app/entrypoint.sh
RUN chmod +x /app/recreateRepo.sh
RUN chmod +x /app/recreateRepos.sh
ENTRYPOINT ["/app/entrypoint.sh"]
CMD ["init"]
I've been digging the question and indeed the main problem that prevents me for the moment to propose a dockerfile is the persistence of unix users...
It is impossible to use a persistent mount on /etc/passwd or /etc/shadow files, UNIX does not support that, certainly for obvious security reasons.
I have not yet taken the time to think about how to overcome this problem. I have one or two ideas but it's not easy to do it without breaking changes.
cat /etc/os-release