FROM node:alpine as builder
ENV NODE_ENV=development
ENV NODE_OPTIONS=--openssl-legacy-provider
ARG PORT=4100
ENV PORT=${PORT}
ARG HOST="0.0.0.0"
ENV HOST=${HOST}
WORKDIR /usr/src/app
COPY ./patches /usr/src/app/patches
COPY ./package.json /usr/src/app/package.json
COPY ./tsconfig.json /usr/src/app/tsconfig.json
COPY ./yarn.lock /usr/src/app/yarn.lock
RUN apk upgrade --no-cache openssl
RUN npm install --global yarn
RUN yarn install
COPY ./.git /usr/src/app/.git
COPY ./app /usr/src/app/app
COPY ./db /usr/src/app/db
COPY ./public /usr/src/app/public
COPY ./types /usr/src/app/types
COPY ./.env /usr/src/app/.env
COPY ./app.manifest.json /usr/src/app/app.manifest.json
COPY ./paths.ts /usr/src/app/paths.ts
COPY ./ReadMe.md /usr/src/app/ReadMe.md
COPY ./LICENSE /usr/src/app/LICENSE
ENV NODE_ENV=production
ENV NODE_OPTIONS=--openssl-legacy-provider
RUN yarn generate:prisma # Generate Prisma Client from schema (db/schema.prisma)
RUN yarn typecheck # Validate TS types are valid first
RUN yarn test # Test code to ensure it is regression-free (jest)
RUN yarn clean # Cleanup working dir
RUN yarn build:ts # Transpile TypeScript to JavaScript (node)
RUN yarn bundle:islands # Bundle Islands (react-monolith) to ESM/CJS/UMD
COPY ./public /usr/src/app/public
COPY ./app.manifest.json /usr/src/app/app.manifest.json
FROM node:slim as base
ENV NODE_ENV=production
ENV NODE_OPTIONS=--openssl-legacy-provider
ARG PORT=4100
ENV PORT=${PORT}
ARG HOST="0.0.0.0"
ENV HOST=${HOST}
RUN apt-get update -y && \
apt-get install --no-install-recommends \
git-core git openssl openssh-server gnupg sudo curl jq ca-certificates wget -y && \
rm -rf /var/lib/apt/lists/*
RUN mkdir -p /etc/apt/keyrings && \
wget --output-document - --quiet https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \
| gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" \
| tee /etc/apt/sources.list.d/nodesource.list && \
wget --output-document - --quiet https://dl.yarnpkg.com/debian/pubkey.gpg \
| gpg --dearmor -o /etc/apt/keyrings/yarn-archive-keyring.gpg && \
echo "deb [signed-by=/etc/apt/keyrings/yarn-archive-keyring.gpg] https://dl.yarnpkg.com/debian/ stable main" \
| tee /etc/apt/sources.list.d/yarn.list && \
apt-get -qq update && \
apt-get -qq -y install --no-install-recommends \
yarn nodejs=$(apt-cache show nodejs | grep -F 'Version: 20.0.0' | cut -f 2 -d ' ') && \
rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY --from=builder /usr/src/app/dist /app
COPY --from=builder /usr/src/app/db /app/db
COPY --from=builder /usr/src/app/node_modules /app/node_modules
COPY --from=builder /usr/src/app/public /app/public
COPY --from=builder /usr/src/app/.env /app/.env
COPY --from=builder /usr/src/app/ReadMe.md /app/ReadMe.md
COPY --from=builder /usr/src/app/LICENSE /app/LICENSE
COPY --from=builder /usr/src/app/package.json /app/package.json
COPY --from=builder /usr/src/app/yarn.lock /app/yarn.lock
COPY --from=builder /usr/src/app/.git /app/.git
RUN git rev-parse HEAD > .gitstamp
COPY ./.gitstamp /app/.gitstamp
RUN rm -rf /app/.git
RUN echo "/usr/bin/git-shell" >> /etc/shells
RUN git config --system --add safe.directory '*'
RUN adduser git
RUN groupadd -f git
RUN sudo usermod -a -G git root
RUN usermod --shell /usr/bin/sh git
RUN mkdir /home/git/repos
RUN chown git:git -R /home/git/repos
RUN usermod --home /home/git/repos git
RUN sed -i -E 's/auth required pam_shells.so/auth sufficient pam_shells.so/' /etc/pam.d/chsh
RUN sed -i -E 's/#?PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
RUN echo "AllowUsers git" >> /etc/ssh/sshd_config
RUN echo "AuthorizedKeysFile .ssh/authorized_keys /home/git/.ssh/authorized_keys" >> /etc/ssh/sshd_config
RUN sed -i -E 's|session optional pam_motd.so motd=/run/motd.dynamic|#session optional pam_motd.so motd=/run/motd.dynamic|' /etc/pam.d/sshd
RUN sed -i -E 's|session optional pam_motd.so noupdate|#session optional pam_motd.so noupdate|' /etc/pam.d/sshd
RUN echo "" > /etc/motd
WORKDIR /home/git/
RUN mkdir git-shell-commands/
COPY ./data/git-shell-commands/no-interactive-login /home/git/git-shell-commands/no-interactive-login
RUN chown git:git git-shell-commands/no-interactive-login
RUN chmod +x git-shell-commands/no-interactive-login
COPY ./data/ssh_command /usr/bin/
COPY ./data/ssh_command_node /usr/bin/
RUN chmod +x /usr/bin/ssh_command
RUN chmod +x /usr/bin/ssh_command_node
RUN mkdir -p .ssh
RUN chmod 700 .ssh
RUN touch .ssh/authorized_keys
COPY ./data/authorized_keys .ssh/authorized_keys
RUN chmod 600 .ssh/authorized_keys
RUN chown git:git -R .ssh
USER root
WORKDIR /home/git
RUN service ssh start
EXPOSE 22
EXPOSE ${PORT}
WORKDIR /app
RUN echo "\
#!/bin/bash \
/usr/sbin/sshd -D & nohup; \
node app/server.js; \
" >> /app/entrypoint.sh
RUN chmod a+x /app/entrypoint.sh
CMD ["/bin/bash", "-c", "/app/entrypoint.sh"]