Skip to content

Commit 743d2a0

Browse files
authored
feat: Implement Per-Machine Nginx Configuration Distribution [DOCKER-COMPOSE] [closes #36] (#45)
1 parent 30a8ec0 commit 743d2a0

3 files changed

Lines changed: 637 additions & 9 deletions

File tree

scripts/translate_homelab_to_compose.sh

Lines changed: 121 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -297,8 +297,8 @@ events {
297297
}
298298
299299
http {
300-
include /etc/nginx/mime.types;
301-
default_type application/octet-stream;
300+
include mime.types;
301+
default_type application/octet-stream;
302302
303303
# Logging
304304
log_format main '\$remote_addr - \$remote_user [\$time_local] "\$request" '
@@ -315,27 +315,53 @@ http {
315315
keepalive_timeout 65;
316316
types_hash_max_size 2048;
317317
318+
# Health check endpoint
319+
server {
320+
listen 80 default_server;
321+
server_name _;
322+
323+
location /health {
324+
access_log off;
325+
return 200 "healthy\n";
326+
add_header Content-Type text/plain;
327+
}
328+
}
329+
318330
# Include service configurations
319-
include /etc/nginx/conf.d/*.conf;
331+
include conf.d/*.conf;
320332
}
321333
EOF
322334

335+
# Get base domain for service URLs
336+
local base_domain
337+
base_domain=$(get_base_domain "$HOMELAB_CONFIG")
338+
323339
# Generate configuration for each service that needs reverse proxy
324340
while IFS= read -r service; do
325341
[[ -z "$service" ]] && continue
326342

327-
local port
328-
port=$(yq ".services[\"$service\"].port" "$HOMELAB_CONFIG" 2>/dev/null)
343+
# Check if this is a web service that needs nginx proxy
344+
if is_web_service "$service" "$HOMELAB_CONFIG"; then
345+
local port
346+
port=$(yq ".services[\"$service\"].port" "$HOMELAB_CONFIG" 2>/dev/null | tr -d '"')
329347

330-
# Only create proxy config for services on ports 80/443 (web services)
331-
if [[ "$port" == "80" || "$port" == "443" ]]; then
332-
log_info " Creating nginx config for: $service"
348+
# Skip if no port (can't proxy without knowing the port)
349+
if [[ -z "$port" || "$port" == "null" ]]; then
350+
log_info " Skipping nginx config for $service: no port specified"
351+
continue
352+
fi
353+
354+
# Get custom domain or use default pattern
355+
local service_domain
356+
service_domain=$(yq ".services[\"$service\"].domain // \"${service}.${base_domain}\"" "$HOMELAB_CONFIG" 2>/dev/null | tr -d '"')
357+
358+
log_info " Creating nginx config for: $service (${service_domain})"
333359

334360
cat > "$nginx_dir/conf.d/${service}.conf" <<EOF
335361
# Service: $service
336362
server {
337363
listen 80;
338-
server_name ${service}.local;
364+
server_name ${service_domain};
339365
340366
location / {
341367
proxy_pass http://$service:$port;
@@ -566,6 +592,11 @@ main() {
566592
OUTPUT_DIR="$2"
567593
shift 2
568594
;;
595+
generate-nginx-bundles)
596+
# Special command to only generate nginx bundles
597+
generate_nginx_bundles "$HOMELAB_CONFIG"
598+
exit $?
599+
;;
569600
-h|--help)
570601
usage
571602
exit 0
@@ -582,6 +613,87 @@ main() {
582613
translate_homelab_to_compose
583614
}
584615

616+
# Function: is_web_service
617+
# Description: Determines if a service should be exposed via nginx proxy
618+
# Arguments: $1 - service name, $2 - config file path
619+
# Returns: 0 if service should be exposed, 1 if not
620+
is_web_service() {
621+
local service="$1"
622+
local config_file="${2:-$HOMELAB_CONFIG}"
623+
624+
# Check if service has a custom domain configured
625+
local custom_domain
626+
custom_domain=$(yq ".services[\"$service\"].domain" "$config_file" 2>/dev/null | tr -d '"')
627+
628+
if [[ -n "$custom_domain" && "$custom_domain" != "null" ]]; then
629+
return 0 # Has explicit domain configuration
630+
fi
631+
632+
# Check if service has a port (indicating it's a service that could be exposed)
633+
# and doesn't explicitly disable web exposure
634+
local port
635+
port=$(yq ".services[\"$service\"].port" "$config_file" 2>/dev/null | tr -d '"')
636+
637+
local web_enabled
638+
web_enabled=$(yq ".services[\"$service\"].web" "$config_file" 2>/dev/null | tr -d '"')
639+
640+
# Default web to true if not specified
641+
if [[ -z "$web_enabled" || "$web_enabled" == "null" ]]; then
642+
web_enabled="true"
643+
fi
644+
645+
# Service is a web service if:
646+
# 1. It has a port AND
647+
# 2. web is not explicitly set to false
648+
if [[ -n "$port" && "$port" != "null" && "$web_enabled" != "false" ]]; then
649+
return 0 # Service should be exposed
650+
fi
651+
652+
return 1 # Service should not be exposed via nginx
653+
}
654+
655+
# Function: get_base_domain
656+
# Description: Gets the base domain from environment or config
657+
# Arguments: $1 - config file path
658+
# Returns: Base domain string
659+
get_base_domain() {
660+
local config_file="${1:-$HOMELAB_CONFIG}"
661+
662+
# Try environment first, then config, then default
663+
local base_domain="${BASE_DOMAIN:-}"
664+
665+
if [[ -z "$base_domain" ]]; then
666+
base_domain=$(yq ".environment.BASE_DOMAIN // \"homelab.local\"" "$config_file" 2>/dev/null | tr -d '"')
667+
fi
668+
669+
echo "$base_domain"
670+
}
671+
672+
# Function: generate_nginx_bundles
673+
# Description: Generates nginx bundles for all machines
674+
# Arguments: $1 - config file path
675+
# Returns: 0 on success, 1 on failure
676+
generate_nginx_bundles() {
677+
local config_file="${1:-$HOMELAB_CONFIG}"
678+
679+
log_info "Generating nginx bundles for all machines..."
680+
681+
# Get all machines
682+
local machines
683+
machines=$(get_machine_list "$config_file") || return 1
684+
685+
# Generate nginx config for each machine
686+
while IFS= read -r machine; do
687+
[[ -z "$machine" ]] && continue
688+
689+
log_info "Generating nginx bundle for: $machine"
690+
generate_nginx_config_for_machine "$machine" "$config_file" || return 1
691+
done <<< "$machines"
692+
693+
log_success "Generated nginx bundles for all machines"
694+
return 0
695+
}
696+
585697
# Only run main if script is executed directly (not sourced)
586698
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
587699
main "$@"

selfhosted.sh

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,27 @@ case "$1" in
752752
;;
753753
esac
754754
;;
755+
generate-nginx)
756+
# Generate nginx bundles for Docker Compose deployment
757+
case "$2" in
758+
bundles)
759+
"$PROJECT_ROOT/scripts/translate_homelab_to_compose.sh" generate-nginx-bundles "${3:-homelab.yaml}"
760+
;;
761+
help|"")
762+
echo "💡 Generate-Nginx Commands:"
763+
echo " bundles [config] - Generate nginx bundles for all machines"
764+
echo ""
765+
echo "💡 Examples:"
766+
echo " $0 generate-nginx bundles homelab.yaml # Generate nginx bundles"
767+
echo " $0 generate-nginx bundles # Use default homelab.yaml"
768+
;;
769+
*)
770+
echo "❌ Unknown generate-nginx command: $2"
771+
echo "💡 Run '$0 generate-nginx help' for available commands"
772+
exit 1
773+
;;
774+
esac
775+
;;
755776
config)
756777
case "$2" in
757778
init) config_init ;;
@@ -794,6 +815,7 @@ case "$1" in
794815
echo " service - Manage service configurations"
795816
echo " deploy - Deploy services to infrastructure"
796817
echo " deploy-compose - Multi-machine Docker Compose deployment coordination"
818+
echo " generate-nginx - Generate nginx bundles for Docker Compose"
797819
echo " config - Manage environment and configuration"
798820
echo " help - Show detailed help"
799821
echo ""

0 commit comments

Comments
 (0)