From 455c6dfd01d665c35e0d5dc6a8ba2c66ca6e84dd Mon Sep 17 00:00:00 2001 From: "Aaron D. Lee" Date: Wed, 7 Jan 2026 23:45:44 -0500 Subject: [PATCH] Docker HTTPS by default, smoke test improvements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Docker: - HTTPS enabled by default (generates self-signed cert) - Added docker-entrypoint.sh for SSL cert generation - Gunicorn now starts with --certfile/--keyfile when HTTPS enabled - Install curl/openssl in web container for healthcheck and certs - Updated docs to reflect HTTPS default Smoke Test: - Moved from rpi/ to scripts/ (works for Pi, Docker, and dev) - Updated header and examples - Added to .gitignore exceptions 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .gitignore | 3 +- DOCKER.md | 9 +++-- Dockerfile | 20 ++++++++--- README.md | 7 ++-- docker-compose.yml | 4 ++- frontends/web/docker-entrypoint.sh | 55 ++++++++++++++++++++++++++++++ {rpi => scripts}/smoke-test.sh | 11 ++++-- 7 files changed, 95 insertions(+), 14 deletions(-) create mode 100644 frontends/web/docker-entrypoint.sh rename {rpi => scripts}/smoke-test.sh (96%) diff --git a/.gitignore b/.gitignore index b151eb1..bb5d1d5 100644 --- a/.gitignore +++ b/.gitignore @@ -64,9 +64,10 @@ htmlcov/ # Output test files. test_data/*.png -# Dev scripts (local convenience scripts - except validate-release.sh) +# Dev scripts (local convenience scripts - except these) scripts/* !scripts/validate-release.sh +!scripts/smoke-test.sh # Web UI auth database and SSL certs instance/ diff --git a/DOCKER.md b/DOCKER.md index b886f89..b886413 100644 --- a/DOCKER.md +++ b/DOCKER.md @@ -13,7 +13,7 @@ docker-compose ps ``` Access: -- **Web UI**: http://localhost:5000 +- **Web UI**: https://localhost:5000 (HTTPS with self-signed cert) - **REST API**: http://localhost:8000 ## Services @@ -36,9 +36,12 @@ STEGASOO_CHANNEL_KEY=XXXX-XXXX-XXXX-XXXX-XXXX-XXXX-XXXX-XXXX # Web UI authentication (default: enabled) STEGASOO_AUTH_ENABLED=true -# HTTPS support (default: disabled) -STEGASOO_HTTPS_ENABLED=false +# HTTPS support (default: enabled, generates self-signed cert) +STEGASOO_HTTPS_ENABLED=true STEGASOO_HOSTNAME=localhost + +# To disable HTTPS: +# STEGASOO_HTTPS_ENABLED=false ``` ### Volume Mounts diff --git a/Dockerfile b/Dockerfile index 22c325a..b5d3047 100644 --- a/Dockerfile +++ b/Dockerfile @@ -35,6 +35,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libzbar0 \ libjpeg-dev \ zlib1g-dev \ + curl \ + openssl \ && rm -rf /var/lib/apt/lists/* # Install ALL dependencies (slow path) @@ -57,6 +59,12 @@ FROM base AS web WORKDIR /app +# Install runtime dependencies (curl for healthcheck, openssl for cert generation) +USER root +RUN apt-get update && apt-get install -y --no-install-recommends \ + curl openssl \ + && rm -rf /var/lib/apt/lists/* + # Copy application files (this is all that rebuilds normally!) COPY src/ src/ COPY data/ data/ @@ -66,6 +74,10 @@ COPY frontends/web/ frontends/web/ # temp_files is for multi-worker temp file sharing RUN mkdir -p /tmp/stego_uploads /app/frontends/web/instance /app/frontends/web/certs /app/frontends/web/temp_files +# Copy and set up entrypoint (before switching to non-root user) +COPY frontends/web/docker-entrypoint.sh /app/frontends/web/ +RUN chmod +x /app/frontends/web/docker-entrypoint.sh + # Create non-root user RUN useradd -m -u 1000 stego && chown -R stego:stego /app /tmp/stego_uploads USER stego @@ -77,12 +89,12 @@ ENV PYTHONPATH=/app/src EXPOSE 5000 # Health check -HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ - CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:5000/')" || exit 1 +HEALTHCHECK --interval=30s --timeout=10s --start-period=10s --retries=3 \ + CMD curl -fsk https://localhost:5000/ || curl -fs http://localhost:5000/ || exit 1 -# Run with gunicorn +# Run with entrypoint (handles HTTPS/HTTP mode) WORKDIR /app/frontends/web -CMD ["gunicorn", "--bind", "0.0.0.0:5000", "--workers", "2", "--threads", "4", "--timeout", "120", "app:app"] +ENTRYPOINT ["/app/frontends/web/docker-entrypoint.sh"] # ============================================================================ # API stage - REST API diff --git a/README.md b/README.md index a961100..bf489af 100644 --- a/README.md +++ b/README.md @@ -105,12 +105,15 @@ ruff check src/ tests/ frontends/ ## Docker ```bash -# Quick start +# Quick start (HTTPS enabled by default) docker-compose up -d # Access -# Web UI: http://localhost:5000 +# Web UI: https://localhost:5000 (self-signed cert) # REST API: http://localhost:8000 + +# Disable HTTPS if needed: +STEGASOO_HTTPS_ENABLED=false docker-compose up -d ``` See [DOCKER.md](DOCKER.md) for full documentation. diff --git a/docker-compose.yml b/docker-compose.yml index d88b54c..14234f6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -18,7 +18,9 @@ services: FLASK_ENV: production # Authentication (v4.0.2) STEGASOO_AUTH_ENABLED: ${STEGASOO_AUTH_ENABLED:-true} - STEGASOO_HTTPS_ENABLED: ${STEGASOO_HTTPS_ENABLED:-false} + # HTTPS enabled by default - generates self-signed cert if none provided + # To disable: STEGASOO_HTTPS_ENABLED=false docker-compose up + STEGASOO_HTTPS_ENABLED: ${STEGASOO_HTTPS_ENABLED:-true} STEGASOO_HOSTNAME: ${STEGASOO_HOSTNAME:-localhost} volumes: # Persist auth database and SSL certs (v4.0.2) diff --git a/frontends/web/docker-entrypoint.sh b/frontends/web/docker-entrypoint.sh new file mode 100644 index 0000000..460109a --- /dev/null +++ b/frontends/web/docker-entrypoint.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# +# Docker entrypoint for Stegasoo Web UI +# Handles SSL certificate generation and gunicorn startup +# + +set -e + +CERT_DIR="/app/frontends/web/certs" +CERT_FILE="$CERT_DIR/cert.pem" +KEY_FILE="$CERT_DIR/key.pem" +HOSTNAME="${STEGASOO_HOSTNAME:-localhost}" + +# Generate self-signed SSL certificate if HTTPS enabled and certs don't exist +generate_certs() { + if [ ! -f "$CERT_FILE" ] || [ ! -f "$KEY_FILE" ]; then + echo "Generating self-signed SSL certificate for $HOSTNAME..." + mkdir -p "$CERT_DIR" + + openssl req -x509 -newkey rsa:2048 \ + -keyout "$KEY_FILE" \ + -out "$CERT_FILE" \ + -sha256 -days 365 -nodes \ + -subj "/CN=$HOSTNAME" \ + -addext "subjectAltName=DNS:$HOSTNAME,DNS:localhost,IP:127.0.0.1" \ + 2>/dev/null + + echo "SSL certificate generated." + else + echo "Using existing SSL certificates." + fi +} + +# Start gunicorn with appropriate settings +if [ "${STEGASOO_HTTPS_ENABLED:-false}" = "true" ]; then + echo "HTTPS mode enabled" + generate_certs + + exec gunicorn \ + --bind 0.0.0.0:5000 \ + --workers 2 \ + --threads 4 \ + --timeout 120 \ + --certfile "$CERT_FILE" \ + --keyfile "$KEY_FILE" \ + app:app +else + echo "HTTP mode (HTTPS disabled)" + exec gunicorn \ + --bind 0.0.0.0:5000 \ + --workers 2 \ + --threads 4 \ + --timeout 120 \ + app:app +fi diff --git a/rpi/smoke-test.sh b/scripts/smoke-test.sh similarity index 96% rename from rpi/smoke-test.sh rename to scripts/smoke-test.sh index e9f68e1..64e908f 100755 --- a/rpi/smoke-test.sh +++ b/scripts/smoke-test.sh @@ -1,10 +1,15 @@ #!/bin/bash # -# Stegasoo Pi Smoke Test -# Tests all core functionality against a running Pi instance +# Stegasoo Smoke Test +# Tests all core functionality against a running instance (Pi, Docker, or dev) # # Usage: ./smoke-test.sh [host] [port] [user] [pass] # +# Examples: +# ./smoke-test.sh # Pi default (stegasoo.local:443) +# ./smoke-test.sh localhost 5000 # Docker default +# ./smoke-test.sh 192.168.1.100 5000 # Custom host +# set -e @@ -296,7 +301,7 @@ test_tools() { echo "" echo -e "${CYAN}╔═══════════════════════════════════════════════════════════════╗${NC}" -echo -e "${CYAN}║ Stegasoo Pi Smoke Test ║${NC}" +echo -e "${CYAN}║ Stegasoo Smoke Test ║${NC}" echo -e "${CYAN}╚═══════════════════════════════════════════════════════════════╝${NC}" echo "" echo -e "Target: ${YELLOW}$BASE_URL${NC}"