ARG VERSION=4.5.0 ARG ALPINE_VERSION=3.22 ARG NODE_VERSION=20.19 # FRONTEND BUILD FROM node:${NODE_VERSION}-trixie AS frontend-build ARG VERSION WORKDIR /front RUN wget "https://github.com/rommapp/romm/archive/refs/tags/${VERSION}.tar.gz" && \ tar xfz ${VERSION}.tar.gz --strip-components=2 -C /front romm-${VERSION}/frontend && rm ${VERSION}.tar.gz RUN npm ci --ignore-scripts --no-audit --no-fund RUN npm run build # FETCH EMULATORJS AND RUFFLE FROM alpine:${ALPINE_VERSION} AS emulator-stage RUN apk add --no-cache \ 7zip \ wget \ ca-certificates ARG EMULATORJS_VERSION=4.2.3 ARG EMULATORJS_SHA256=07d451bc06fa3ad04ab30d9b94eb63ac34ad0babee52d60357b002bde8f3850b RUN wget "https://github.com/EmulatorJS/EmulatorJS/releases/download/v${EMULATORJS_VERSION}/${EMULATORJS_VERSION}.7z" && \ echo "${EMULATORJS_SHA256} ${EMULATORJS_VERSION}.7z" | sha256sum -c - && \ 7z x -y "${EMULATORJS_VERSION}.7z" -o/emulatorjs && \ rm -f "${EMULATORJS_VERSION}.7z" ARG RUFFLE_VERSION=nightly-2025-08-14 ARG RUFFLE_FILE=ruffle-nightly-2025_08_14-web-selfhosted.zip ARG RUFFLE_SHA256=178870c5e7dd825a8df35920dfc5328d83e53f3c4d5d95f70b1ea9cd13494151 RUN wget "https://github.com/ruffle-rs/ruffle/releases/download/${RUFFLE_VERSION}/${RUFFLE_FILE}" && \ echo "${RUFFLE_SHA256} ${RUFFLE_FILE}" | sha256sum -c - && \ unzip -o "${RUFFLE_FILE}" -d /ruffle && \ rm -f "${RUFFLE_FILE}" FROM cloudron/base:5.0.0@sha256:04fd70dbd8ad6149c19de39e35718e024417c3e01dc9c6637eaf4a41ec4e596c as cloudron-builder ARG NJS_VERSION=0.9.4 ARG MODZIP_VERSION=1.3.0 # Prevent interactive prompts during installation ENV DEBIAN_FRONTEND=noninteractive # Install system dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ git \ make \ gcc \ g++ \ libmariadb3 \ libmariadb-dev \ libpq-dev \ libffi-dev \ musl-dev \ curl \ ca-certificates \ libmagic-dev \ 7zip \ tzdata \ libbz2-dev \ libssl-dev \ libreadline-dev \ libsqlite3-dev \ zlib1g-dev \ liblzma-dev \ libncurses5-dev \ libncursesw5-dev \ nginx \ nginx-dev \ libpcre3-dev \ libssl-dev \ libxml2-dev \ libxslt-dev WORKDIR / RUN git clone -b ${NJS_VERSION} https://github.com/nginx/njs.git RUN git clone -b ${MODZIP_VERSION} https://github.com/evanmiller/mod_zip.git WORKDIR /usr/share/nginx/src RUN ./configure --add-dynamic-module=/njs/nginx --add-dynamic-module=/mod_zip --with-compat --builddir=. && make modules # Build and install RAHasher (optional for RA hashes) RUN git clone --recursive --branch 1.8.1 --depth 1 https://github.com/RetroAchievements/RALibretro.git /tmp/RALibretro WORKDIR /tmp/RALibretro RUN sed -i '22a #include ' ./src/Util.h \ && sed -i '6a #include ' \ ./src/libchdr/deps/zlib-1.3.1/gzlib.c \ ./src/libchdr/deps/zlib-1.3.1/gzread.c \ ./src/libchdr/deps/zlib-1.3.1/gzwrite.c \ && make HAVE_CHD=1 -f ./Makefile.RAHasher # Main image starts here FROM cloudron/base:5.0.0@sha256:04fd70dbd8ad6149c19de39e35718e024417c3e01dc9c6637eaf4a41ec4e596c RUN mkdir -p /app/code WORKDIR /app/code ARG WEBSERVER_FOLDER=/app/code/frontend ARG UV_VERSION=0.8.24 ARG VERSION # Prevent interactive prompts during installation ENV DEBIAN_FRONTEND=noninteractive # Install system dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ git \ libpq-dev \ libmariadb-dev \ curl \ ca-certificates \ 7zip \ tzdata \ nginx \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* # Clone release backend code RUN wget "https://github.com/rommapp/romm/archive/refs/tags/${VERSION}.tar.gz" && \ tar xfz ${VERSION}.tar.gz --strip-components=1 -C /app/code romm-${VERSION}/backend romm-${VERSION}/pyproject.toml romm-${VERSION}/uv.lock && rm ${VERSION}.tar.gz # Install RAHasher into image COPY --from=cloudron-builder /tmp/RALibretro/bin64/RAHasher /usr/bin/RAHasher # Install frontend into image WORKDIR ${WEBSERVER_FOLDER} COPY --from=frontend-build /front/dist ${WEBSERVER_FOLDER} COPY --from=frontend-build /front/assets ${WEBSERVER_FOLDER}/assets COPY ./decode.js /etc/nginx/js/decode.js COPY ./nginx.conf /etc/nginx/nginx.conf COPY ./default.conf /etc/nginx/conf.d/default.conf COPY --from=cloudron-builder /usr/share/nginx/src/ngx_http_js_module.so /usr/lib/nginx/modules/ COPY --from=cloudron-builder /usr/share/nginx/src/ngx_http_zip_module.so /usr/lib/nginx/modules/ RUN mkdir -p assets/romm && ln -s /app/data/assets ${WEBSERVER_FOLDER}/assets/romm/assets && ln -s /app/data/resources ${WEBSERVER_FOLDER}/assets/romm/resources # Copy emulator to web folder COPY --from=emulator-stage /emulatorjs ${WEBSERVER_FOLDER}/assets/emulatorjs COPY --from=emulator-stage /ruffle ${WEBSERVER_FOLDER}/assets/ruffle WORKDIR /app/code/ # Install uv for the non-root user COPY --from=ghcr.io/astral-sh/uv:$UV_VERSION /uv /uvx /usr/local/bin/ # Install Python RUN mkdir /app/code/uv && uv python install -i /app/code/uv 3.13 # Install Python dependencies ENV UV_PYTHON_INSTALL_DIR=/app/code/uv RUN uv sync --all-extras # add supervisor configs ADD supervisor/* /etc/supervisor/conf.d/ RUN ln -sf /run/supervisord.log /var/log/supervisor/supervisord.log ENV PATH="/app/code/.venv/bin:${PATH}" COPY start.sh /app/pkg/ COPY env.sh.template /app/pkg/ COPY config.yml.template /app/pkg/ CMD [ "/app/pkg/start.sh" ]