feat: implement basic auth using nginx and bcrypt password hashing
This commit is contained in:
parent
bbd9c44259
commit
b43cd62ca9
@ -31,10 +31,11 @@ COPY data-api.js /usr/share/nginx/api/
|
|||||||
COPY backup-s3.js /usr/share/nginx/api/
|
COPY backup-s3.js /usr/share/nginx/api/
|
||||||
COPY auth-middleware.js /usr/share/nginx/api/
|
COPY auth-middleware.js /usr/share/nginx/api/
|
||||||
COPY login.html /usr/share/nginx/api/
|
COPY login.html /usr/share/nginx/api/
|
||||||
COPY inject-password-hash.js /usr/share/nginx/api/
|
COPY generate-htpasswd.js /usr/share/nginx/api/
|
||||||
|
|
||||||
# Copy a custom Nginx configuration that includes the data API proxy
|
# Copy a custom Nginx configuration that includes the data API proxy
|
||||||
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
COPY nginx-auth.conf /etc/nginx/auth.conf
|
||||||
|
|
||||||
# Copy supervisor configuration
|
# Copy supervisor configuration
|
||||||
COPY supervisord.conf /etc/supervisord.conf
|
COPY supervisord.conf /etc/supervisord.conf
|
||||||
|
|||||||
33
generate-htpasswd.js
Normal file
33
generate-htpasswd.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* Generate .htpasswd file for Nginx basic authentication
|
||||||
|
*
|
||||||
|
* This script creates a .htpasswd file from the bcrypt hash provided in the
|
||||||
|
* PASSWORD_HASH environment variable.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
// Default username
|
||||||
|
const USERNAME = 'user';
|
||||||
|
|
||||||
|
// Get password hash from environment variable
|
||||||
|
const passwordHash = process.env.PASSWORD_HASH || '$2a$10$EgxHKjDDFcZKtQY9hl/N4.QvEQHCXVnQXw9dzFYlUDVKOcLMGp9eq';
|
||||||
|
|
||||||
|
// Format for .htpasswd: username:$2y$...hash...
|
||||||
|
// Note: Nginx requires $2y$ format instead of bcrypt's $2a$ format
|
||||||
|
const htpasswdContent = `${USERNAME}:${passwordHash.replace('$2a$', '$2y$')}`;
|
||||||
|
|
||||||
|
// Path to the .htpasswd file
|
||||||
|
const htpasswdPath = '/etc/nginx/.htpasswd';
|
||||||
|
|
||||||
|
// Write the .htpasswd file
|
||||||
|
try {
|
||||||
|
fs.writeFileSync(htpasswdPath, htpasswdContent);
|
||||||
|
console.log(`Generated .htpasswd file at ${htpasswdPath}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error generating .htpasswd file: ${error.message}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Basic authentication setup complete');
|
||||||
42
generate-password.js
Normal file
42
generate-password.js
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/**
|
||||||
|
* Password Hash Generator for Weight Tracker
|
||||||
|
*
|
||||||
|
* This script generates a bcrypt hash for a given password that can be used
|
||||||
|
* with the Weight Tracker application's authentication system.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* node generate-password.js <your-password>
|
||||||
|
*/
|
||||||
|
|
||||||
|
const bcrypt = require('bcryptjs');
|
||||||
|
|
||||||
|
// Get password from command line arguments
|
||||||
|
const password = process.argv[2];
|
||||||
|
|
||||||
|
if (!password) {
|
||||||
|
console.error('Error: Password is required');
|
||||||
|
console.log('Usage: node generate-password.js <your-password>');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate salt and hash
|
||||||
|
const saltRounds = 10;
|
||||||
|
bcrypt.genSalt(saltRounds, (err, salt) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('Error generating salt:', err);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bcrypt.hash(password, salt, (err, hash) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('Error generating hash:', err);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('\nPassword Hash for Nginx Basic Authentication:');
|
||||||
|
console.log(hash);
|
||||||
|
console.log('\nUse this hash in your PASSWORD_HASH environment variable in Coolify.');
|
||||||
|
console.log('Example:');
|
||||||
|
console.log(`PASSWORD_HASH=${hash}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
13
nginx-auth.conf
Normal file
13
nginx-auth.conf
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Authentication configuration for Nginx
|
||||||
|
# This file will be included in the main Nginx configuration
|
||||||
|
|
||||||
|
# Define the authentication realm
|
||||||
|
auth_basic "Weight Tracker";
|
||||||
|
|
||||||
|
# Path to the .htpasswd file containing user credentials
|
||||||
|
auth_basic_user_file /etc/nginx/.htpasswd;
|
||||||
|
|
||||||
|
# CORS headers
|
||||||
|
add_header 'Access-Control-Allow-Origin' '*' always;
|
||||||
|
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
|
||||||
|
add_header 'Access-Control-Allow-Headers' 'Origin, X-Requested-With, Content-Type, Accept, Authorization' always;
|
||||||
41
nginx.conf
41
nginx.conf
@ -1,29 +1,19 @@
|
|||||||
server {
|
server {
|
||||||
listen 80;
|
listen 80;
|
||||||
server_name _;
|
server_name localhost;
|
||||||
root /usr/share/nginx/html;
|
|
||||||
index index.html;
|
# Enable gzip compression
|
||||||
|
|
||||||
# Enable compression
|
|
||||||
gzip on;
|
gzip on;
|
||||||
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
|
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
|
||||||
|
|
||||||
# Authentication check - redirect to login if not authenticated
|
# Protect all routes with basic authentication
|
||||||
location = / {
|
location / {
|
||||||
# First try to use the API to check authentication
|
# Include authentication configuration
|
||||||
auth_request /auth/check;
|
include /etc/nginx/auth.conf;
|
||||||
|
|
||||||
# If auth passes, serve the main page
|
# Serve static files
|
||||||
try_files $uri $uri/ /index.html;
|
try_files $uri $uri/ /index.html;
|
||||||
|
|
||||||
# CORS headers
|
|
||||||
add_header 'Access-Control-Allow-Origin' '*' always;
|
|
||||||
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
|
|
||||||
add_header 'Access-Control-Allow-Headers' 'Origin, X-Requested-With, Content-Type, Accept, Authorization' always;
|
|
||||||
|
|
||||||
# Error indicates not authenticated, redirect to login
|
|
||||||
error_page 401 = @error401;
|
|
||||||
|
|
||||||
# Handle preflight requests
|
# Handle preflight requests
|
||||||
if ($request_method = 'OPTIONS') {
|
if ($request_method = 'OPTIONS') {
|
||||||
add_header 'Access-Control-Allow-Origin' '*';
|
add_header 'Access-Control-Allow-Origin' '*';
|
||||||
@ -35,21 +25,6 @@ server {
|
|||||||
return 204;
|
return 204;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Serve static files directly
|
|
||||||
location / {
|
|
||||||
try_files $uri $uri/ /index.html;
|
|
||||||
|
|
||||||
# CORS headers
|
|
||||||
add_header 'Access-Control-Allow-Origin' '*' always;
|
|
||||||
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
|
|
||||||
add_header 'Access-Control-Allow-Headers' 'Origin, X-Requested-With, Content-Type, Accept, Authorization' always;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Handle 401 unauthorized by redirecting to login
|
|
||||||
location @error401 {
|
|
||||||
return 302 /login;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Proxy requests to the data API
|
# Proxy requests to the data API
|
||||||
location /data/ {
|
location /data/ {
|
||||||
|
|||||||
@ -5,8 +5,8 @@ logfile=/dev/stdout
|
|||||||
logfile_maxbytes=0
|
logfile_maxbytes=0
|
||||||
pidfile=/var/run/supervisord.pid
|
pidfile=/var/run/supervisord.pid
|
||||||
|
|
||||||
[program:inject-password-hash]
|
[program:generate-htpasswd]
|
||||||
command=node /usr/share/nginx/api/inject-password-hash.js
|
command=node /usr/share/nginx/api/generate-htpasswd.js
|
||||||
directory=/usr/share/nginx/api
|
directory=/usr/share/nginx/api
|
||||||
environment=PASSWORD_HASH="%(ENV_PASSWORD_HASH)s"
|
environment=PASSWORD_HASH="%(ENV_PASSWORD_HASH)s"
|
||||||
autostart=true
|
autostart=true
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user