Fix docker build error and SSL regeneration

This commit is contained in:
LukeGus
2025-09-28 01:42:50 -05:00
parent e2146cdfbf
commit cfa7c26c49
6 changed files with 76 additions and 43 deletions

View File

@@ -9,6 +9,7 @@ COPY package*.json ./
ENV npm_config_target_platform=linux ENV npm_config_target_platform=linux
ENV npm_config_target_arch=x64 ENV npm_config_target_arch=x64
ENV npm_config_target_libc=glibc ENV npm_config_target_libc=glibc
ENV NODE_OPTIONS="--max-old-space-size=4096"
RUN npm ci --force --ignore-scripts && \ RUN npm ci --force --ignore-scripts && \
npm cache clean --force npm cache clean --force
@@ -19,7 +20,11 @@ WORKDIR /app
COPY . . COPY . .
ENV NODE_OPTIONS="--max-old-space-size=4096"
ENV NODE_ENV=production
RUN npm run build RUN npm run build
RUN npm run build:types
# Stage 3: Build backend TypeScript # Stage 3: Build backend TypeScript
FROM deps AS backend-builder FROM deps AS backend-builder
@@ -30,6 +35,8 @@ COPY . .
ENV npm_config_target_platform=linux ENV npm_config_target_platform=linux
ENV npm_config_target_arch=x64 ENV npm_config_target_arch=x64
ENV npm_config_target_libc=glibc ENV npm_config_target_libc=glibc
ENV NODE_OPTIONS="--max-old-space-size=4096"
ENV NODE_ENV=production
RUN npm rebuild better-sqlite3 --force RUN npm rebuild better-sqlite3 --force
@@ -46,6 +53,7 @@ COPY package*.json ./
ENV npm_config_target_platform=linux ENV npm_config_target_platform=linux
ENV npm_config_target_arch=x64 ENV npm_config_target_arch=x64
ENV npm_config_target_libc=glibc ENV npm_config_target_libc=glibc
ENV NODE_OPTIONS="--max-old-space-size=4096"
RUN npm ci --only=production --ignore-scripts --force && \ RUN npm ci --only=production --ignore-scripts --force && \
npm rebuild better-sqlite3 bcryptjs --force && \ npm rebuild better-sqlite3 bcryptjs --force && \

View File

@@ -25,15 +25,33 @@ chown -R node:node /app/data
chmod 755 /app/data chmod 755 /app/data
if [ "$ENABLE_SSL" = "true" ]; then if [ "$ENABLE_SSL" = "true" ]; then
echo "Generating SSL certificates..." echo "Checking SSL certificate configuration..."
mkdir -p /app/data/ssl mkdir -p /app/data/ssl
chown -R node:node /app/data/ssl chown -R node:node /app/data/ssl
chmod 755 /app/data/ssl chmod 755 /app/data/ssl
DOMAIN=${SSL_DOMAIN:-localhost} DOMAIN=${SSL_DOMAIN:-localhost}
echo "Generating certificate for domain: $DOMAIN"
# Check if certificates already exist and are valid
if [ -f "/app/data/ssl/termix.crt" ] && [ -f "/app/data/ssl/termix.key" ]; then
echo "SSL certificates found, checking validity..."
# Check if certificate is still valid (not expired within 30 days)
if openssl x509 -in /app/data/ssl/termix.crt -checkend 2592000 -noout >/dev/null 2>&1; then
echo "SSL certificates are valid and will be reused for domain: $DOMAIN"
else
echo "SSL certificate is expired or expiring soon, regenerating..."
rm -f /app/data/ssl/termix.crt /app/data/ssl/termix.key
fi
else
echo "SSL certificates not found, will generate new ones..."
fi
# Generate certificates only if they don't exist or are invalid
if [ ! -f "/app/data/ssl/termix.crt" ] || [ ! -f "/app/data/ssl/termix.key" ]; then
echo "Generating SSL certificates for domain: $DOMAIN"
cat > /app/data/ssl/openssl.conf << EOF cat > /app/data/ssl/openssl.conf << EOF
[req] [req]
default_bits = 2048 default_bits = 2048
prompt = no prompt = no
@@ -62,17 +80,18 @@ IP.1 = 127.0.0.1
IP.2 = ::1 IP.2 = ::1
EOF EOF
openssl genrsa -out /app/data/ssl/termix.key 2048 openssl genrsa -out /app/data/ssl/termix.key 2048
openssl req -new -x509 -key /app/data/ssl/termix.key -out /app/data/ssl/termix.crt -days 365 -config /app/data/ssl/openssl.conf -extensions v3_req openssl req -new -x509 -key /app/data/ssl/termix.key -out /app/data/ssl/termix.crt -days 365 -config /app/data/ssl/openssl.conf -extensions v3_req
chmod 600 /app/data/ssl/termix.key chmod 600 /app/data/ssl/termix.key
chmod 644 /app/data/ssl/termix.crt chmod 644 /app/data/ssl/termix.crt
chown node:node /app/data/ssl/termix.key /app/data/ssl/termix.crt chown node:node /app/data/ssl/termix.key /app/data/ssl/termix.crt
rm -f /app/data/ssl/openssl.conf rm -f /app/data/ssl/openssl.conf
echo "SSL certificates generated successfully for domain: $DOMAIN" echo "SSL certificates generated successfully for domain: $DOMAIN"
fi
fi fi
echo "Starting nginx..." echo "Starting nginx..."

View File

@@ -10,7 +10,9 @@
"clean": "npx prettier . --write", "clean": "npx prettier . --write",
"dev": "vite", "dev": "vite",
"dev:https": "cross-env VITE_HTTPS=true vite", "dev:https": "cross-env VITE_HTTPS=true vite",
"build": "vite build && tsc -p tsconfig.node.json", "build": "vite build",
"build:types": "tsc -p tsconfig.node.json",
"build:full": "npm run build && npm run build:types",
"build:backend": "tsc -p tsconfig.node.json", "build:backend": "tsc -p tsconfig.node.json",
"dev:backend": "tsc -p tsconfig.node.json && node ./dist/backend/backend/starter.js", "dev:backend": "tsc -p tsconfig.node.json && node ./dist/backend/backend/starter.js",
"start": "npm run build:backend && node ./dist/backend/backend/starter.js", "start": "npm run build:backend && node ./dist/backend/backend/starter.js",

View File

@@ -30,12 +30,30 @@ export class AutoSSLSetup {
try { try {
if (await this.isSSLConfigured()) { if (await this.isSSLConfigured()) {
await this.logCertificateInfo(); await this.logCertificateInfo();
await this.setupEnvironmentVariables();
return; return;
} }
await this.generateSSLCertificates(); // In Docker, certificates might be generated by entrypoint script
// Check if they exist but weren't detected by isSSLConfigured
await this.setupEnvironmentVariables(); try {
await fs.access(this.CERT_FILE);
await fs.access(this.KEY_FILE);
systemLogger.info("SSL certificates found from entrypoint script", {
operation: "ssl_cert_found_entrypoint",
cert_path: this.CERT_FILE,
key_path: this.KEY_FILE,
});
await this.logCertificateInfo();
await this.setupEnvironmentVariables();
return;
} catch {
// Certificates don't exist, generate them
await this.generateSSLCertificates();
await this.setupEnvironmentVariables();
}
} catch (error) { } catch (error) {
systemLogger.error("Failed to initialize SSL configuration", error, { systemLogger.error("Failed to initialize SSL configuration", error, {
operation: "ssl_auto_init_failed", operation: "ssl_auto_init_failed",

View File

@@ -222,9 +222,8 @@ export function HomepageAuth({
setTotpCode(""); setTotpCode("");
setTotpTempToken(""); setTotpTempToken("");
} catch (err: any) { } catch (err: any) {
toast.error( const errorMessage = err?.response?.data?.error || err?.message || t("errors.unknownError");
err?.response?.data?.error || err?.message || t("errors.unknownError"), toast.error(errorMessage);
);
setInternalLoggedIn(false); setInternalLoggedIn(false);
setLoggedIn(false); setLoggedIn(false);
setIsAdmin(false); setIsAdmin(false);
@@ -371,11 +370,8 @@ export function HomepageAuth({
setTotpTempToken(""); setTotpTempToken("");
toast.success(t("messages.loginSuccess")); toast.success(t("messages.loginSuccess"));
} catch (err: any) { } catch (err: any) {
toast.error( const errorMessage = err?.response?.data?.error || err?.message || t("errors.invalidTotpCode");
err?.response?.data?.error || toast.error(errorMessage);
err?.message ||
t("errors.invalidTotpCode"),
);
} finally { } finally {
setTotpLoading(false); setTotpLoading(false);
} }
@@ -394,11 +390,8 @@ export function HomepageAuth({
window.location.replace(authUrl); window.location.replace(authUrl);
} catch (err: any) { } catch (err: any) {
toast.error( const errorMessage = err?.response?.data?.error || err?.message || t("errors.failedOidcLogin");
err?.response?.data?.error || toast.error(errorMessage);
err?.message ||
t("errors.failedOidcLogin"),
);
setOidcLoading(false); setOidcLoading(false);
} }
} }

View File

@@ -204,9 +204,8 @@ export function HomepageAuth({
setTotpCode(""); setTotpCode("");
setTotpTempToken(""); setTotpTempToken("");
} catch (err: any) { } catch (err: any) {
toast.error( const errorMessage = err?.response?.data?.error || err?.message || t("errors.unknownError");
err?.response?.data?.error || err?.message || t("errors.unknownError"), toast.error(errorMessage);
);
setInternalLoggedIn(false); setInternalLoggedIn(false);
setLoggedIn(false); setLoggedIn(false);
setIsAdmin(false); setIsAdmin(false);
@@ -347,11 +346,8 @@ export function HomepageAuth({
setTotpTempToken(""); setTotpTempToken("");
toast.success(t("messages.loginSuccess")); toast.success(t("messages.loginSuccess"));
} catch (err: any) { } catch (err: any) {
toast.error( const errorMessage = err?.response?.data?.error || err?.message || t("errors.invalidTotpCode");
err?.response?.data?.error || toast.error(errorMessage);
err?.message ||
t("errors.invalidTotpCode"),
);
} finally { } finally {
setTotpLoading(false); setTotpLoading(false);
} }
@@ -370,11 +366,8 @@ export function HomepageAuth({
window.location.replace(authUrl); window.location.replace(authUrl);
} catch (err: any) { } catch (err: any) {
toast.error( const errorMessage = err?.response?.data?.error || err?.message || t("errors.failedOidcLogin");
err?.response?.data?.error || toast.error(errorMessage);
err?.message ||
t("errors.failedOidcLogin"),
);
setOidcLoading(false); setOidcLoading(false);
} }
} }
@@ -402,12 +395,12 @@ export function HomepageAuth({
setLoggedIn(true); setLoggedIn(true);
setIsAdmin(!!meRes.is_admin); setIsAdmin(!!meRes.is_admin);
setUsername(meRes.username || null); setUsername(meRes.username || null);
setUserId(meRes.id || null); setUserId(meRes.userId || null);
setDbError(null); setDbError(null);
onAuthSuccess({ onAuthSuccess({
isAdmin: !!meRes.is_admin, isAdmin: !!meRes.is_admin,
username: meRes.username || null, username: meRes.username || null,
userId: meRes.id || null, userId: meRes.userId || null,
}); });
setInternalLoggedIn(true); setInternalLoggedIn(true);
window.history.replaceState( window.history.replaceState(