fetch_ml/build/docker/secure-prod.Dockerfile
Jeremie Fraeys ea15af1833 Fix multi-user authentication and clean up debug code
- Fix YAML tags in auth config struct (json -> yaml)
- Update CLI configs to use pre-hashed API keys
- Remove double hashing in WebSocket client
- Fix port mapping (9102 -> 9103) in CLI commands
- Update permission keys to use jobs:read, jobs:create, etc.
- Clean up all debug logging from CLI and server
- All user roles now authenticate correctly:
  * Admin: Can queue jobs and see all jobs
  * Researcher: Can queue jobs and see own jobs
  * Analyst: Can see status (read-only access)

Multi-user authentication is now fully functional.
2025-12-06 12:35:32 -05:00

102 lines
3.7 KiB
Docker

# Secure Production Dockerfile with proper SSH setup
FROM golang:1.25-alpine AS builder
# Install dependencies
RUN apk add --no-cache git make gcc musl-dev
# Set working directory
WORKDIR /app
# Copy go mod files
COPY go.mod go.sum ./
# Download dependencies
RUN go mod download
# Copy source code
COPY . .
# Build Go binaries with CGO enabled for SQLite
RUN CGO_ENABLED=1 go build -o bin/api-server cmd/api-server/main.go && \
CGO_ENABLED=1 go build -o bin/worker cmd/worker/worker_server.go cmd/worker/worker_config.go
# Final stage with Podman and secure SSH
FROM alpine:3.19
# Install runtime dependencies including Podman and SSH
RUN apk add --no-cache ca-certificates redis openssl curl podman openssh sudo gcc musl-dev
# Create app user and worker user
RUN addgroup -g 1001 -S appgroup && \
adduser -u 1001 -S appuser -G appgroup && \
addgroup -g 1002 -S workergroup && \
adduser -u 1002 -S worker -G workergroup -s /bin/sh && \
echo "worker:SecureWorkerPass2024!" | chpasswd && \
mkdir -p /home/worker/.ssh && \
chown -R worker:workergroup /home/worker
# Set working directory
WORKDIR /app
# Copy binaries from builder
COPY --from=builder /app/bin/ /usr/local/bin/
# Copy configs
COPY --from=builder /app/configs/ /app/configs/
# Create necessary directories
RUN mkdir -p /app/data/experiments /app/logs /app/ssl /tmp/fetchml-jobs && \
chown -R appuser:appgroup /app
# Generate SSL certificates
RUN openssl req -x509 -newkey rsa:2048 -keyout /app/ssl/key.pem -out /app/ssl/cert.pem -days 365 -nodes \
-subj "/C=US/ST=Homelab/L=Local/O=ML/OU=Experiments/CN=localhost" && \
chmod 644 /app/ssl/cert.pem /app/ssl/key.pem
# Generate SSH keys for worker user
RUN ssh-keygen -t rsa -b 4096 -f /home/worker/.ssh/id_rsa -N "" && \
cp /home/worker/.ssh/id_rsa.pub /home/worker/.ssh/authorized_keys && \
chmod 700 /home/worker/.ssh && \
chmod 600 /home/worker/.ssh/id_rsa && \
chmod 644 /home/worker/.ssh/id_rsa.pub /home/worker/.ssh/authorized_keys && \
chown -R worker:workergroup /home/worker/.ssh
# Configure SSH daemon securely
RUN echo "Port 2222" >> /etc/ssh/sshd_config && \
echo "PermitRootLogin no" >> /etc/ssh/sshd_config && \
echo "PasswordAuthentication yes" >> /etc/ssh/sshd_config && \
echo "PubkeyAuthentication yes" >> /etc/ssh/sshd_config && \
echo "AuthorizedKeysFile %h/.ssh/authorized_keys" >> /etc/ssh/sshd_config && \
echo "AllowUsers worker" >> /etc/ssh/sshd_config && \
echo "MaxAuthTries 3" >> /etc/ssh/sshd_config && \
echo "ClientAliveInterval 300" >> /etc/ssh/sshd_config && \
echo "ClientAliveCountMax 2" >> /etc/ssh/sshd_config && \
echo "X11Forwarding no" >> /etc/ssh/sshd_config && \
echo "AllowTcpForwarding no" >> /etc/ssh/sshd_config && \
echo "Banner /etc/ssh/banner" >> /etc/ssh/sshd_config
# Create SSH banner
RUN echo "=================================================" > /etc/ssh/banner && \
echo " ML Experiments Production Server" >> /etc/ssh/banner && \
echo " Unauthorized access is prohibited" >> /etc/ssh/banner && \
echo "=================================================" >> /etc/ssh/banner
# Generate SSH host keys
RUN ssh-keygen -A
# Give appuser sudo permissions for SSH and worker user for Podman
RUN echo "appuser ALL=(ALL) NOPASSWD: /usr/sbin/sshd" >> /etc/sudoers && \
echo "worker ALL=(ALL) NOPASSWD: /usr/bin/podman" >> /etc/sudoers
# Switch to app user for application
USER appuser
# Expose ports
EXPOSE 9101 2222
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
CMD curl -k -f https://localhost:9101/health || exit 1
# Default command for API server
CMD ["/usr/local/bin/api-server", "-config", "/app/configs/config.yaml"]