From b2b8b14310f37a3a66111b1989b299cd2047d4f0 Mon Sep 17 00:00:00 2001 From: troyeguo <13820674+troyeguo@users.noreply.github.com> Date: Fri, 13 Jun 2025 16:28:28 +0800 Subject: [PATCH] feat: add support for Docker Secrets to manage server credentials securely --- Dockerfile | 12 ++++++++++++ docker-compose.yml | 1 + httpServer.js | 32 ++++++++++++++++++++++++++++---- 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 48035add..4eeaba23 100644 --- a/Dockerfile +++ b/Dockerfile @@ -47,9 +47,21 @@ RUN echo '#!/bin/sh' > /start.sh && \ # Set default environment variables (can be overridden at runtime) ENV SERVER_USERNAME=admin ENV SERVER_PASSWORD=securePass123 +ENV SERVER_PASSWORD_FILE=my_secret ENV PORT=8080 # Define volume for uploads directory VOLUME ["/app/uploads"] CMD ["/start.sh"] + +# docker run -d \ +# --name koodo-reader \ +# -p 80:80 \ +# -p 8080:8080 \ +# -e ENABLE_HTTP_SERVER=false \ +# -e SERVER_USERNAME=admin \ +# -e SERVER_PASSWORD=securePass123 \ +# -e SERVER_PASSWORD_FILE=my_secret \ +# -v /path/to/host/uploads:/app/uploads \ +# ghcr.io/koodo-reader/koodo-reader:master diff --git a/docker-compose.yml b/docker-compose.yml index 61330546..fb965d5a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,6 +11,7 @@ services: environment: - SERVER_USERNAME=${SERVER_USERNAME:-admin} - SERVER_PASSWORD=${SERVER_PASSWORD:-securePass123} + - SERVER_PASSWORD_FILE=${SERVER_PASSWORD_FILE:-my_secret} - PORT=8080 - ENABLE_HTTP_SERVER=false volumes: diff --git a/httpServer.js b/httpServer.js index e49f9b35..bd8a16d6 100644 --- a/httpServer.js +++ b/httpServer.js @@ -3,18 +3,42 @@ const fs = require('fs'); const path = require('path'); const url = require('url'); +// 从 Docker Secrets 读取密码的函数 +function getDockerSecret(secretName) { + try { + const secretPath = `/run/secrets/${secretName}`; + if (fs.existsSync(secretPath)) { + return fs.readFileSync(secretPath, 'utf8').trim(); + } + } catch (err) { + console.warn(`Failed to read Docker secret '${secretName}':`, err.message); + } + return null; +} + // 配置信息 const UPLOAD_DIR = path.resolve('./uploads'); // 使用绝对路径 const PORT = process.env.PORT || 8080; const SERVER_ENABLED = process.env.ENABLE_HTTP_SERVER === 'true'; // 新增:控制服务器是否启用 +// 优先从 Docker Secrets 读取密码,如果没有则回退到环境变量 +const SERVER_PASSWORD_FILE = process.env.SERVER_PASSWORD_FILE || 'my_secret'; +const SERVER_PASSWORD = getDockerSecret(SERVER_PASSWORD_FILE) || process.env.SERVER_PASSWORD || 'securePass123'; const VALID_CREDENTIALS = { username: process.env.SERVER_USERNAME || 'admin', - password: process.env.SERVER_PASSWORD || 'securePass123' + password: SERVER_PASSWORD }; -// 验证必要的环境变量 -if (!process.env.SERVER_USERNAME || !process.env.SERVER_PASSWORD) { - console.warn('Warning: Using default credentials. Set SERVER_USERNAME and SERVER_PASSWORD environment variables for production.'); +// 验证密码来源 +if (getDockerSecret(SERVER_PASSWORD_FILE)) { + console.log('Using password from Docker Secret'); +} else if (process.env.SERVER_PASSWORD) { + console.warn('Using password from environment variable (less secure)'); +} else { + console.warn('Warning: Using default password. Set Docker Secret or SERVER_PASSWORD environment variable for production.'); +} + +if (!process.env.SERVER_USERNAME) { + console.warn('Warning: Using default username. Set SERVER_USERNAME environment variable for production.'); } // 检查服务器是否启用