Switched from Dockmon to Beszel

This commit is contained in:
2025-10-31 17:13:00 +01:00
parent cc6454cef9
commit f4a4142799
75 changed files with 24313 additions and 122 deletions

111
dockmon/docker/Dockerfile Normal file
View File

@@ -0,0 +1,111 @@
# DockMon All-in-One Container
# Multi-stage build: Go stats service + Python backend + Nginx frontend
# Stage 1: Build Go stats service
FROM golang:1.23-alpine AS go-builder
WORKDIR /build
# Copy go mod files
COPY stats-service/go.mod stats-service/go.sum* ./
# Download dependencies
RUN go mod download
# Copy source code
COPY stats-service/*.go ./
# Build binary (static linking for alpine)
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o stats-service .
# Stage 2: Final image with Python + Go binary
FROM python:3.11.10-slim
# Install system dependencies
RUN apt-get update && apt-get install -y \
nginx \
supervisor \
curl \
gcc \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*
# Create app directory
WORKDIR /app
# Copy Go stats service binary from builder
COPY --from=go-builder /build/stats-service /usr/local/bin/stats-service
RUN chmod +x /usr/local/bin/stats-service
# Copy and install Python dependencies
COPY backend/requirements.txt /app/backend/
RUN pip install --no-cache-dir -r /app/backend/requirements.txt
# Copy backend code
COPY backend/ /app/backend/
# Copy frontend files
COPY src/index.html /usr/share/nginx/html/index.html
COPY src/login.html /usr/share/nginx/html/login.html
COPY src/favicon.ico /usr/share/nginx/html/favicon.ico
COPY src/lucide.min.js /usr/share/nginx/html/lucide.min.js
COPY src/images/ /usr/share/nginx/html/images/
COPY src/css/ /usr/share/nginx/html/css/
COPY src/js/ /usr/share/nginx/html/js/
RUN chmod 644 /usr/share/nginx/html/*.html /usr/share/nginx/html/*.ico /usr/share/nginx/html/*.js
RUN chmod -R 644 /usr/share/nginx/html/css/ /usr/share/nginx/html/js/
RUN find /usr/share/nginx/html/css /usr/share/nginx/html/js -type d -exec chmod 755 {} \;
# Create certs directory (certificates will be generated at runtime if not present)
RUN mkdir -p /etc/nginx/certs
# Copy nginx configuration
COPY docker/nginx.conf /etc/nginx/conf.d/default.conf
RUN rm -f /etc/nginx/sites-enabled/default /etc/nginx/sites-available/default
# Add WebSocket upgrade mapping to main nginx.conf (must be in http block)
RUN sed -i '/^http {/a \ # WebSocket upgrade mapping\n map $http_upgrade $connection_upgrade {\n default upgrade;\n '"''"' close;\n }\n' /etc/nginx/nginx.conf
# Copy supervisor configuration
COPY docker/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
# Create data directory with correct permissions
RUN mkdir -p /app/data && \
chmod 700 /app/data
# Create startup script
RUN echo '#!/bin/bash' > /startup.sh && \
echo 'set -e' >> /startup.sh && \
echo '' >> /startup.sh && \
echo '# Ensure certificates exist (generate if missing)' >> /startup.sh && \
echo 'if [ ! -f /etc/nginx/certs/dockmon.crt ]; then' >> /startup.sh && \
echo ' mkdir -p /etc/nginx/certs' >> /startup.sh && \
echo ' echo "Generating SSL certificates..."' >> /startup.sh && \
echo ' openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \' >> /startup.sh && \
echo ' -keyout /etc/nginx/certs/dockmon.key \' >> /startup.sh && \
echo ' -out /etc/nginx/certs/dockmon.crt \' >> /startup.sh && \
echo ' -subj "/C=US/ST=State/L=City/O=DockMon/CN=localhost" > /dev/null 2>&1' >> /startup.sh && \
echo ' echo "SSL certificates generated successfully"' >> /startup.sh && \
echo ' chmod 600 /etc/nginx/certs/dockmon.key' >> /startup.sh && \
echo ' chmod 644 /etc/nginx/certs/dockmon.crt' >> /startup.sh && \
echo 'fi' >> /startup.sh && \
echo '' >> /startup.sh && \
echo '# Wait for backend to be ready' >> /startup.sh && \
echo 'sleep 2' >> /startup.sh && \
echo '' >> /startup.sh && \
echo '# Start supervisor' >> /startup.sh && \
echo 'exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf' >> /startup.sh && \
chmod +x /startup.sh
# Expose ports (8081 is internal for stats service)
EXPOSE 443 8080
# Health check - checks both backend and stats service
HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
CMD curl -f http://localhost:8080/health && curl -f http://localhost:8081/health || exit 1
# Volume for persistent data
VOLUME ["/app/data"]
# Start supervisor
CMD ["/startup.sh"]

View File

@@ -0,0 +1,40 @@
#!/bin/bash
# Generate self-signed SSL certificates for DockMon
# These certificates are for development/internal use only
CERT_DIR="./docker/certs"
CERT_DAYS=3650 # 10 years
# Create certificate directory
mkdir -p "$CERT_DIR"
# Generate private key
openssl genrsa -out "$CERT_DIR/dockmon.key" 2048
# Generate certificate signing request
openssl req -new -key "$CERT_DIR/dockmon.key" \
-out "$CERT_DIR/dockmon.csr" \
-subj "/C=US/ST=State/L=City/O=DockMon/CN=localhost"
# Generate self-signed certificate
openssl x509 -req -days $CERT_DAYS \
-in "$CERT_DIR/dockmon.csr" \
-signkey "$CERT_DIR/dockmon.key" \
-out "$CERT_DIR/dockmon.crt"
# Create a combined certificate file for nginx
cat "$CERT_DIR/dockmon.crt" "$CERT_DIR/dockmon.key" > "$CERT_DIR/dockmon.pem"
# Set appropriate permissions
chmod 600 "$CERT_DIR/dockmon.key"
chmod 644 "$CERT_DIR/dockmon.crt"
chmod 600 "$CERT_DIR/dockmon.pem"
# Clean up CSR
rm "$CERT_DIR/dockmon.csr"
echo "✅ SSL certificates generated successfully in $CERT_DIR"
echo " - Certificate: $CERT_DIR/dockmon.crt"
echo " - Private Key: $CERT_DIR/dockmon.key"
echo " - Combined PEM: $CERT_DIR/dockmon.pem"

116
dockmon/docker/nginx.conf Normal file
View File

@@ -0,0 +1,116 @@
# HTTPS server only - no HTTP redirect
server {
listen 443 ssl default_server;
server_name _;
# SSL Configuration
ssl_certificate /etc/nginx/certs/dockmon.crt;
ssl_certificate_key /etc/nginx/certs/dockmon.key;
# Modern SSL configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# SSL session caching
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
root /usr/share/nginx/html;
index index.html;
# Enable gzip compression
gzip on;
gzip_types text/plain text/css text/javascript application/javascript application/json;
gzip_min_length 1000;
# Proxy API requests to local backend (same container)
location /api/ {
proxy_pass http://127.0.0.1:8080/api/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $server_name;
# Timeouts for long-running requests
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# Proxy WebSocket connections
location /ws/ {
proxy_pass http://127.0.0.1:8080/ws/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Disable buffering for WebSocket
proxy_buffering off;
proxy_cache off;
proxy_redirect off;
# WebSocket timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 3600s;
}
# Main WebSocket for events
location = /ws {
proxy_pass http://127.0.0.1:8080/ws;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Disable buffering for WebSocket
proxy_buffering off;
proxy_cache off;
proxy_redirect off;
# WebSocket timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 3600s;
}
# Direct backend health check
location /api/health {
proxy_pass http://127.0.0.1:8080/health;
access_log off;
}
# Serve static files
location / {
try_files $uri $uri/ /index.html;
# Don't cache HTML files - always fetch fresh
location ~* \.html$ {
expires -1;
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0";
}
# Cache static assets (images, fonts, etc)
location ~* \.(jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
}
}

View File

@@ -0,0 +1,45 @@
[supervisord]
nodaemon=true
user=root
logfile=/var/log/supervisor/supervisord.log
pidfile=/var/run/supervisord.pid
[program:stats-service]
command=/usr/local/bin/stats-service
directory=/app
autostart=true
autorestart=true
startsecs=5
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
priority=100
[program:backend]
command=uvicorn main:app --host 127.0.0.1 --port 8080 --log-level info
directory=/app/backend
autostart=true
autorestart=true
startsecs=10
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
environment=PYTHONPATH="/app/backend",PYTHONUNBUFFERED="1"
priority=200
[program:nginx]
command=nginx -g "daemon off;"
autostart=true
autorestart=true
startsecs=5
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
# Wait for backend to be ready
priority=999
[group:dockmon]
programs=stats-service,backend,nginx