# ============================================================================ # STAGE 1: Build Java I2P from source # ============================================================================ FROM alpine:3.17 AS i2p-builder ENV I2P_VERSION=2.13.0 ENV APP_HOME="/opt/i2p" # Install build dependencies RUN echo "https://dl-cdn.alpinelinux.org/alpine/v3.17/community" >> /etc/apk/repositories && \ apk update && \ apk add --no-cache \ openjdk17 \ apache-ant \ gettext \ tar \ bzip2 \ curl \ git \ && rm -rf /var/cache/apk/* WORKDIR /tmp/build # Download and extract I2P source RUN curl -L -o i2psource.tar.bz2 "https://files.i2p.net/${I2P_VERSION}/i2psource_${I2P_VERSION}.tar.bz2" \ && tar -xjf i2psource.tar.bz2 \ && mv i2p-${I2P_VERSION}/* . \ && rm -rf i2psource.tar.bz2 i2p-${I2P_VERSION} # Build Core I2P Suite RUN echo "build.built-by=Docker" >> override.properties \ && ant preppkg-linux-only \ && rm -rf pkg-temp/osid pkg-temp/lib/wrapper pkg-temp/lib/wrapper.* # ============================================================================ # STAGE 2: Compile xmrig-proxy from source # ============================================================================ FROM alpine:3.17 AS xmrig-builder RUN echo "https://dl-cdn.alpinelinux.org/alpine/v3.17/community" >> /etc/apk/repositories && \ apk update && \ apk add --no-cache \ git \ make \ cmake \ gcc \ g++ \ musl-dev \ libuv-dev \ openssl-dev \ util-linux-dev RUN git clone https://github.com/xmrig/xmrig-proxy.git /tmp/xmrig-proxy && \ mkdir /tmp/xmrig-proxy/build && \ cd /tmp/xmrig-proxy/build && \ cmake .. -DCMAKE_BUILD_TYPE=Release && \ make -j$(nproc) # ============================================================================ # STAGE 3: Final Runtime # ============================================================================ FROM alpine:3.17 ENV APP_HOME="/opt/i2p" ENV I2P_DATA="/var/lib/i2p" ENV I2P_CONFIG_DIR="/var/lib/i2p/i2p-config" ENV JAVA_HOME="/usr/lib/jvm/java-17-openjdk" ENV PATH="${JAVA_HOME}/bin:${PATH}" # Enable Alpine repositories RUN echo "https://dl-cdn.alpinelinux.org/alpine/v3.17/main" >> /etc/apk/repositories && \ echo "https://dl-cdn.alpinelinux.org/alpine/v3.17/community" >> /etc/apk/repositories && \ apk update # Install runtime dependencies including Java RUN apk add --no-cache \ openjdk17-jre \ ttf-dejavu \ monero \ i2pd \ tor \ python3 py3-pip py3-websockets py3-httpx \ curl procps iptables cryptsetup kmod \ tini strace lsof net-tools iproute2 \ sudo ca-certificates e2fsprogs wget \ gpgv dirmngr gnupg \ libevent libuv libssl3 \ device-mapper \ gcc musl-dev python3-dev libffi-dev \ bash \ findutils \ && rm -rf /var/cache/apk/* # Copy built binaries from builder stages COPY --from=i2p-builder /tmp/build/pkg-temp ${APP_HOME} COPY --from=xmrig-builder /tmp/xmrig-proxy/build/xmrig-proxy /usr/local/bin/xmrig-proxy # ============================================================================ # DEBUG: Verify all binaries # ============================================================================ RUN echo "=== DEBUG: CHECKING BINARIES ===" && \ echo "=== JAVA ===" && \ java -version 2>&1 || echo "java version check failed" && \ echo "=== I2P ===" && \ ls -la ${APP_HOME}/lib/ 2>/dev/null | head -20 && \ echo "=== MONERO ===" && \ monerod --version 2>&1 | head -1 || echo "monerod version check failed" && \ echo "=== TOR ===" && \ tor --version 2>&1 | head -1 || echo "tor version check failed" && \ echo "=== XMRIG-PROXY ===" && \ xmrig-proxy --version 2>&1 | head -1 || echo "xmrig-proxy version check failed" # Install Python dependencies RUN pip3 install \ websockets \ httpx[socks] \ python-socks[asyncio] \ stem \ structlog \ psutil # Create users RUN adduser -D -s /bin/bash toruser && \ adduser -D -s /bin/bash monerouser && \ adduser -D -s /bin/bash i2puser && \ echo "root ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers && \ echo "toruser ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers && \ echo "monerouser ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers && \ echo "i2puser ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers # Setup directories - ALL DATA IN /dev/shm (RAM) RUN rm -rf /tmp /run /var/run && \ ln -s /dev/shm /tmp && \ ln -s /dev/shm /run # Setup I2P directories RUN mkdir -p /dev/shm/i2pd /dev/shm/i2pd/netDb \ /dev/shm/i2pd/addressbook /dev/shm/i2pd/certificates \ /dev/shm/i2pd/destinations /dev/shm/i2pd/run && \ chown -R i2puser:i2puser /dev/shm/i2pd && \ chmod -R 755 /dev/shm/i2pd # Setup I2P config directory - THIS IS CRITICAL RUN mkdir -p ${I2P_CONFIG_DIR} && \ mkdir -p ${I2P_CONFIG_DIR}/clients.config.d && \ mkdir -p ${I2P_CONFIG_DIR}/destinations && \ mkdir -p ${I2P_CONFIG_DIR}/private && \ chown -R i2puser:i2puser ${I2P_CONFIG_DIR} && \ chmod -R 755 ${I2P_CONFIG_DIR} # Setup I2P data directory RUN mkdir -p ${I2P_DATA} && \ mkdir -p ${I2P_DATA}/destinations && \ mkdir -p ${I2P_DATA}/private && \ chown -R i2puser:i2puser ${I2P_DATA} && \ chmod -R 755 ${I2P_DATA} # Setup tor directory RUN mkdir -p /dev/shm/tor /dev/shm/tor/hs && \ chown -R toruser:toruser /dev/shm/tor && \ chmod 700 /dev/shm/tor # Setup shared ringdb RUN mkdir -p /dev/shm/shared-ringdb && \ chown -R monerouser:monerouser /dev/shm/shared-ringdb && \ chmod 700 /dev/shm/shared-ringdb # ============================================================================ # Configure I2P (Java) with proper config in I2P_CONFIG_DIR # ============================================================================ RUN echo "=== Creating I2P configurations in ${I2P_CONFIG_DIR} ===" && \ # Router Config - Core settings echo "router.consolePort=7657" >> ${I2P_CONFIG_DIR}/router.config && \ echo "router.consoleHost=127.0.0.1" >> ${I2P_CONFIG_DIR}/router.config && \ echo "router.samPort=7656" >> ${I2P_CONFIG_DIR}/router.config && \ echo "router.sam.enabled=true" >> ${I2P_CONFIG_DIR}/router.config && \ echo "i2np.ntcp.enabled=true" >> ${I2P_CONFIG_DIR}/router.config && \ echo "i2np.ntcp2.enabled=true" >> ${I2P_CONFIG_DIR}/router.config && \ echo "i2np.ssu.enabled=true" >> ${I2P_CONFIG_DIR}/router.config && \ echo "i2np.ssu2.enabled=true" >> ${I2P_CONFIG_DIR}/router.config && \ echo "i2np.ipv4=true" >> ${I2P_CONFIG_DIR}/router.config && \ echo "i2np.ipv6=false" >> ${I2P_CONFIG_DIR}/router.config && \ # Clients Config - App 0: RouterConsole echo "clientApp.0.main=net.i2p.router.web.RouterConsoleRunner" >> ${I2P_CONFIG_DIR}/clients.config && \ echo "clientApp.0.name=RouterConsole" >> ${I2P_CONFIG_DIR}/clients.config && \ echo "clientApp.0.args=-p 7657 -h 127.0.0.1 ./webapps/" >> ${I2P_CONFIG_DIR}/clients.config && \ echo "clientApp.0.delay=5" >> ${I2P_CONFIG_DIR}/clients.config && \ echo "clientApp.0.startOnLoad=true" >> ${I2P_CONFIG_DIR}/clients.config && \ # Clients Config - App 1: SAM Bridge echo "clientApp.1.main=net.i2p.sam.SAMBridge" >> ${I2P_CONFIG_DIR}/clients.config && \ echo "clientApp.1.name=SAMBridge" >> ${I2P_CONFIG_DIR}/clients.config && \ echo "clientApp.1.args=sam.keys 127.0.0.1 7656" >> ${I2P_CONFIG_DIR}/clients.config && \ echo "clientApp.1.delay=10" >> ${I2P_CONFIG_DIR}/clients.config && \ echo "clientApp.1.startOnLoad=true" >> ${I2P_CONFIG_DIR}/clients.config && \ # Set permissions chown -R i2puser:i2puser ${I2P_CONFIG_DIR} && \ chmod -R 755 ${I2P_CONFIG_DIR} && \ echo "✓ I2P configurations created" # ============================================================================ # Create Java I2P start script with proper classpath # ============================================================================ RUN echo '#!/bin/sh\n\ echo "=== Starting Java I2P ==="\n\ echo "APP_HOME: ${APP_HOME}"\n\ echo "I2P_CONFIG_DIR: ${I2P_CONFIG_DIR}"\n\ echo "I2P_DATA: ${I2P_DATA}"\n\ echo "=== I2P lib directory contents ==="\n\ ls -la ${APP_HOME}/lib/ | grep -E "(i2p|router)" || echo "No matching JARs found"\n\ echo "=== Starting I2P Router ==="\n\ cd ${APP_HOME}\n\ exec java -cp "${APP_HOME}/lib/*" \ -Di2p.config.dir=${I2P_CONFIG_DIR} \ -Di2p.data.dir=${I2P_DATA} \ net.i2p.router.RouterLaunch' > /start-i2p.sh && \ chmod +x /start-i2p.sh # ============================================================================ # Copy orchestrator # ============================================================================ COPY orchestrator.py /orchestrator.py RUN chmod +x /orchestrator.py # ============================================================================ # Expose I2P ports # ============================================================================ EXPOSE 7654 7656 7657 7658 4444 6668 7659 7660 4445 12345 7650 7655 # ============================================================================ # Health check # ============================================================================ HEALTHCHECK --interval=30s --timeout=10s --start-period=180s --retries=3 \ CMD pgrep -f "monerod" > /dev/null 2>&1 || exit 1 WORKDIR /root ENTRYPOINT ["/sbin/tini", "--", "python3", "-u", "/orchestrator.py"]