diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index 9671042..adfcc1b 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -44,109 +44,47 @@ jobs: docker tag nfoguard:latest nfoguard:${{ github.sha }} echo "Docker image built and tagged successfully" - - name: Find local Gitea IP + - name: Login and Push to Gitea registry (local network) run: | - echo "Using known local Gitea IP: 192.168.253.221" - GITEA_LOCAL_IP="192.168.253.221" - - # Test connectivity to local IP - echo "Testing local connectivity..." - if timeout 3 curl -s "http://$GITEA_LOCAL_IP:3000" >/dev/null 2>&1; then - echo "✅ Local Gitea accessible at $GITEA_LOCAL_IP:3000" - else - echo "❌ Cannot reach local Gitea at $GITEA_LOCAL_IP:3000" - fi - - # Test registry endpoint - if timeout 3 curl -s "http://$GITEA_LOCAL_IP:3000/v2/" >/dev/null 2>&1; then - echo "✅ Registry endpoint accessible" - else - echo "❌ Registry endpoint not accessible" - fi - - # Export for other steps - echo "GITEA_LOCAL_IP=$GITEA_LOCAL_IP" >> $GITHUB_ENV - echo "Using Gitea at: $GITEA_LOCAL_IP" - - - name: Login to Gitea registry - run: | - echo "Logging into Gitea container registry..." + echo "Using local network connection to avoid Cloudflare tunnel timeouts..." export DOCKER_CONFIG=/tmp/docker-config mkdir -p $DOCKER_CONFIG - # Test local IP connectivity first - REGISTRY="$GITEA_LOCAL_IP:3000" - echo "Testing registry connectivity to: $REGISTRY" + # Use local IP directly - no tunnel overhead + LOCAL_REGISTRY="192.168.253.221:3000" + echo "Registry: $LOCAL_REGISTRY" - # Test if we can reach the registry endpoint - if curl -s -f "http://$REGISTRY/v2/" >/dev/null 2>&1; then - echo "✅ Registry endpoint accessible via HTTP" - # Try login with local IP - echo "${{ secrets.token }}" | docker --config $DOCKER_CONFIG login "$REGISTRY" -u "${{ secrets.username }}" --password-stdin && { - echo "REGISTRY_URL=$REGISTRY" >> $GITHUB_ENV - echo "✅ Local registry login successful" - } || { - echo "❌ Local registry login failed, using domain fallback" - echo "${{ secrets.token }}" | docker --config $DOCKER_CONFIG login gitea.skalas.org -u "${{ secrets.username }}" --password-stdin - echo "REGISTRY_URL=gitea.skalas.org" >> $GITHUB_ENV - } - else - echo "❌ Local registry not accessible, using domain" - echo "${{ secrets.token }}" | docker --config $DOCKER_CONFIG login gitea.skalas.org -u "${{ secrets.username }}" --password-stdin - echo "REGISTRY_URL=gitea.skalas.org" >> $GITHUB_ENV - fi + # Login to local registry + echo "${{ secrets.token }}" | docker --config $DOCKER_CONFIG login "$LOCAL_REGISTRY" -u "${{ secrets.username }}" --password-stdin - echo "Using registry: ${REGISTRY_URL:-gitea.skalas.org}" - - - name: Push to Gitea registry - run: | - echo "Pushing to Gitea container registry at: ${REGISTRY_URL:-gitea.skalas.org}" - export DOCKER_CONFIG=/tmp/docker-config + # Tag images for local registry + docker tag nfoguard:latest "$LOCAL_REGISTRY/jskala/nfoguard:latest" + docker tag nfoguard:latest "$LOCAL_REGISTRY/jskala/nfoguard:${{ github.sha }}" - # Use the discovered registry URL or fallback to domain name - REGISTRY=${REGISTRY_URL:-gitea.skalas.org} + echo "Pushing to local registry (much faster!)..." - # Retag images for the correct registry - docker tag nfoguard:latest "$REGISTRY/jskala/nfoguard:latest" - docker tag nfoguard:latest "$REGISTRY/jskala/nfoguard:${{ github.sha }}" - - echo "Pushing to $REGISTRY..." - echo "Image 1: $REGISTRY/jskala/nfoguard:latest" - echo "Image 2: $REGISTRY/jskala/nfoguard:${{ github.sha }}" - - # Push first image with detailed output + # Push to local network - should be very fast echo "=== Pushing latest tag ===" - timeout 600 docker --config $DOCKER_CONFIG push "$REGISTRY/jskala/nfoguard:latest" 2>&1 | tee /tmp/push1.log && { - echo "✅ First image pushed successfully" - FIRST_SUCCESS=true - } || { - echo "❌ First push failed" - cat /tmp/push1.log - FIRST_SUCCESS=false - } - - # Push second image - echo "=== Pushing SHA tag ===" - timeout 600 docker --config $DOCKER_CONFIG push "$REGISTRY/jskala/nfoguard:${{ github.sha }}" 2>&1 | tee /tmp/push2.log && { - echo "✅ Second image pushed successfully" - SECOND_SUCCESS=true - } || { - echo "❌ Second push failed" - cat /tmp/push2.log - SECOND_SUCCESS=false - } - - # Verify what actually made it - echo "=== Verifying push results ===" - curl -s "$REGISTRY/v2/jskala/nfoguard/tags/list" || echo "Could not verify tags" - - if [ "$FIRST_SUCCESS" = "true" ]; then - echo "🎉 At least one image pushed successfully!" - exit 0 + if docker --config $DOCKER_CONFIG push "$LOCAL_REGISTRY/jskala/nfoguard:latest"; then + echo "✅ Latest tag pushed successfully" + + echo "=== Pushing SHA tag ===" + if docker --config $DOCKER_CONFIG push "$LOCAL_REGISTRY/jskala/nfoguard:${{ github.sha }}"; then + echo "✅ SHA tag pushed successfully" + else + echo "⚠️ SHA tag push failed but latest succeeded" + fi else - echo "💥 Push failed" + echo "❌ Local registry push failed" + docker images | grep nfoguard exit 1 fi + + # Verify the push worked + echo "=== Verifying push ===" + curl -s "http://$LOCAL_REGISTRY/v2/jskala/nfoguard/tags/list" || echo "Could not verify (but push likely succeeded)" + + echo "🎉 Local registry push completed!" deploy: needs: build diff --git a/Dockerfile b/Dockerfile index b0f42a6..5df2762 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,25 +1,60 @@ FROM python:3.11-slim + +# Set working directory WORKDIR /app -# deps (curl for healthcheck; gosu only needed when running as root) +# Install system dependencies in a single layer and clean up RUN apt-get update && apt-get install -y --no-install-recommends \ sqlite3 curl gosu \ - && rm -rf /var/lib/apt/lists/* + && rm -rf /var/lib/apt/lists/* \ + && apt-get clean -# Create a default appuser (will be ignored if process isn’t root) +# Create user early RUN groupadd -g 1000 appuser && useradd -u 1000 -g appuser -m appuser +# Copy and install Python dependencies first (for better caching) COPY requirements.txt . -RUN pip install --no-cache-dir -r requirements.txt +RUN pip install --no-cache-dir -r requirements.txt \ + && pip cache purge -# Copy new modular structure +# Copy application files COPY nfoguard.py . COPY core/ ./core/ COPY clients/ ./clients/ COPY VERSION . +# Set permissions RUN mkdir -p /app/data && chown -R appuser:appuser /app +# Root-aware entrypoint +RUN echo '#!/bin/bash' > /entrypoint.sh && \ + echo 'set -euo pipefail' >> /entrypoint.sh && \ + echo '' >> /entrypoint.sh && \ + echo 'PUID=${PUID:-1000}' >> /entrypoint.sh && \ + echo 'PGID=${PGID:-1000}' >> /entrypoint.sh && \ + echo '' >> /entrypoint.sh && \ + echo 'if [ "$(id -u)" -eq 0 ]; then' >> /entrypoint.sh && \ + echo ' # running as root: we can adjust IDs and drop privileges' >> /entrypoint.sh && \ + echo ' groupmod -o -g "$PGID" appuser 2>/dev/null || groupadd -o -g "$PGID" appuser' >> /entrypoint.sh && \ + echo ' id appuser &>/dev/null || useradd -o -u "$PUID" -g "$PGID" -m appuser' >> /entrypoint.sh && \ + echo ' usermod -o -u "$PUID" -g "$PGID" appuser 2>/dev/null || true' >> /entrypoint.sh && \ + echo ' chown -R "$PUID:$PGID" /app || true' >> /entrypoint.sh && \ + echo ' exec gosu appuser "$@"' >> /entrypoint.sh && \ + echo 'else' >> /entrypoint.sh && \ + echo ' # not root (e.g., compose set user: 1000:1000) — just run' >> /entrypoint.sh && \ + echo ' exec "$@"' >> /entrypoint.sh && \ + echo 'fi' >> /entrypoint.sh + +RUN chmod +x /entrypoint.sh + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ + CMD curl -f http://localhost:8080/health || exit 1 + +EXPOSE 8080 +ENTRYPOINT ["/entrypoint.sh"] +CMD ["python", "nfoguard.py"] + # Root-aware entrypoint RUN echo '#!/bin/bash' > /entrypoint.sh && \ echo 'set -euo pipefail' >> /entrypoint.sh && \ diff --git a/Dockerfile.optimized b/Dockerfile.optimized new file mode 100644 index 0000000..801c83f --- /dev/null +++ b/Dockerfile.optimized @@ -0,0 +1,33 @@ +# Test image size optimization + +FROM python:3.11-slim + +WORKDIR /app + +# Single layer for all dependencies to reduce image size +RUN apt-get update && apt-get install -y --no-install-recommends \ + sqlite3 curl gosu \ + && rm -rf /var/lib/apt/lists/* \ + && apt-get clean \ + && groupadd -g 1000 appuser \ + && useradd -u 1000 -g appuser -m appuser + +# Install Python deps with cleanup +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt && pip cache purge + +# Copy app files +COPY nfoguard.py core/ clients/ VERSION ./ + +# Set permissions and create entrypoint in single layer +RUN mkdir -p /app/data \ + && chown -R appuser:appuser /app \ + && echo '#!/bin/bash\nset -euo pipefail\nPUID=${PUID:-1000}\nPGID=${PGID:-1000}\nif [ "$(id -u)" -eq 0 ]; then\n groupmod -o -g "$PGID" appuser 2>/dev/null || groupadd -o -g "$PGID" appuser\n id appuser &>/dev/null || useradd -o -u "$PUID" -g "$PGID" -m appuser\n usermod -o -u "$PUID" -g "$PGID" appuser 2>/dev/null || true\n chown -R "$PUID:$PGID" /app || true\n exec gosu appuser "$@"\nelse\n exec "$@"\nfi' > /entrypoint.sh \ + && chmod +x /entrypoint.sh + +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ + CMD curl -f http://localhost:8080/health || exit 1 + +EXPOSE 8080 +ENTRYPOINT ["/entrypoint.sh"] +CMD ["python", "nfoguard.py"] \ No newline at end of file diff --git a/VERSION b/VERSION index a918a2a..769ed6a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.6.0 +0.2.14 diff --git a/fix-gitea-packages.md b/fix-gitea-packages.md index ff61ad1..5c80295 100644 --- a/fix-gitea-packages.md +++ b/fix-gitea-packages.md @@ -40,4 +40,17 @@ docker tag hello-world gitea.skalas.org/jskala/test:latest docker push gitea.skalas.org/jskala/test:latest ``` -After enabling packages, your workflow should work! \ No newline at end of file +After enabling packages, your workflow should work! + +## 5. Performance tip: Use local network for same-host setups + +If your runner and Gitea are on the same host, use the local IP to avoid Cloudflare tunnel overhead: + +```bash +# Much faster for same-host setups +docker login 192.168.253.221:3000 +docker tag hello-world 192.168.253.221:3000/jskala/test:latest +docker push 192.168.253.221:3000/jskala/test:latest +``` + +This bypasses the tunnel completely and should be very fast! \ No newline at end of file