Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 71a8823b35 |
+260
-4
@@ -12,6 +12,250 @@ fi
|
||||
# Resolve script directory so config paths are deterministic even when called via sudo
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
CONFIG_FILE="$SCRIPT_DIR/config.json"
|
||||
NGINX_DOMAIN_BASE="${INVENTAR_TENANT_DOMAIN_BASE:-invario-software.de}"
|
||||
NGINX_PROXY_HOST="${INVENTAR_NGINX_PROXY_HOST:-172.17.0.1}"
|
||||
NGINX_SITES_AVAILABLE="${INVENTAR_NGINX_SITES_AVAILABLE:-/etc/nginx/sites-available}"
|
||||
NGINX_SITES_ENABLED="${INVENTAR_NGINX_SITES_ENABLED:-/etc/nginx/sites-enabled}"
|
||||
NGINX_SITE_PREFIX="${INVENTAR_NGINX_SITE_PREFIX:-inventarsystem}"
|
||||
CERTBOT_EMAIL="${INVENTAR_CERTBOT_EMAIL:-}"
|
||||
|
||||
tenant_domain() {
|
||||
printf '%s.%s' "$1" "$NGINX_DOMAIN_BASE"
|
||||
}
|
||||
|
||||
tenant_nginx_site_path() {
|
||||
printf '%s/%s-%s.conf' "$NGINX_SITES_AVAILABLE" "$NGINX_SITE_PREFIX" "$1"
|
||||
}
|
||||
|
||||
tenant_nginx_enabled_path() {
|
||||
printf '%s/%s-%s.conf' "$NGINX_SITES_ENABLED" "$NGINX_SITE_PREFIX" "$1"
|
||||
}
|
||||
|
||||
run_host_command() {
|
||||
if [ "$(id -u)" -eq 0 ]; then
|
||||
"$@"
|
||||
elif command -v sudo >/dev/null 2>&1; then
|
||||
sudo "$@"
|
||||
else
|
||||
return 127
|
||||
fi
|
||||
}
|
||||
|
||||
reload_host_nginx() {
|
||||
if command -v nginx >/dev/null 2>&1 || command -v sudo >/dev/null 2>&1; then
|
||||
if ! run_host_command nginx -t; then
|
||||
echo "Warning: nginx configuration test failed; skipping reload."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if command -v systemctl >/dev/null 2>&1; then
|
||||
if ! run_host_command systemctl reload nginx; then
|
||||
echo "Warning: systemctl reload nginx failed."
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
if ! run_host_command nginx -s reload; then
|
||||
echo "Warning: nginx reload failed."
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
write_tenant_nginx_config() {
|
||||
local tenant_id="$1"
|
||||
local port="$2"
|
||||
local domain site_path enabled_path
|
||||
|
||||
domain="$(tenant_domain "$tenant_id")"
|
||||
site_path="$(tenant_nginx_site_path "$tenant_id")"
|
||||
enabled_path="$(tenant_nginx_enabled_path "$tenant_id")"
|
||||
|
||||
if [ -z "$port" ]; then
|
||||
echo "Warning: No port configured for tenant '$tenant_id'; skipping nginx vhost creation."
|
||||
return 0
|
||||
fi
|
||||
|
||||
if ! run_host_command mkdir -p "$NGINX_SITES_AVAILABLE" "$NGINX_SITES_ENABLED"; then
|
||||
echo "Warning: Unable to prepare nginx site directories; skipping reverse-proxy setup."
|
||||
return 0
|
||||
fi
|
||||
|
||||
local have_cert=false
|
||||
|
||||
if [ -f "/etc/letsencrypt/live/$domain/fullchain.pem" ] && [ -f "/etc/letsencrypt/live/$domain/privkey.pem" ]; then
|
||||
have_cert=true
|
||||
else
|
||||
if [ "$(id -u)" -eq 0 ]; then
|
||||
cat > "$site_path" <<EOF
|
||||
# ==========================================
|
||||
# INVENTARSYSTEM ($tenant_id)
|
||||
# ==========================================
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name $domain;
|
||||
client_max_body_size 100M;
|
||||
|
||||
location / {
|
||||
proxy_pass http://$NGINX_PROXY_HOST:$port;
|
||||
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;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
else
|
||||
sudo tee "$site_path" >/dev/null <<EOF
|
||||
# ==========================================
|
||||
# INVENTARSYSTEM ($tenant_id)
|
||||
# ==========================================
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name $domain;
|
||||
client_max_body_size 100M;
|
||||
|
||||
location / {
|
||||
proxy_pass http://$NGINX_PROXY_HOST:$port;
|
||||
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;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
|
||||
if ! run_host_command ln -sfn "$site_path" "$enabled_path"; then
|
||||
echo "Warning: Could not enable nginx site for tenant '$tenant_id'."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! reload_host_nginx; then
|
||||
echo "Warning: Initial nginx reload failed for tenant '$tenant_id'."
|
||||
fi
|
||||
|
||||
if command -v certbot >/dev/null 2>&1 || command -v sudo >/dev/null 2>&1; then
|
||||
local certbot_args=(certbot --nginx --non-interactive --agree-tos -d "$domain")
|
||||
if [ -n "$CERTBOT_EMAIL" ]; then
|
||||
certbot_args+=(--email "$CERTBOT_EMAIL")
|
||||
else
|
||||
certbot_args+=(--register-unsafely-without-email)
|
||||
fi
|
||||
|
||||
if ! run_host_command "${certbot_args[@]}"; then
|
||||
echo "Warning: certbot failed for tenant '$tenant_id'; keeping HTTP-only vhost for now."
|
||||
return 1
|
||||
fi
|
||||
|
||||
have_cert=true
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$have_cert" != true ]; then
|
||||
echo "Warning: No TLS certificate available for tenant '$tenant_id'; leaving HTTP-only nginx config in place."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "$(id -u)" -eq 0 ]; then
|
||||
cat > "$site_path" <<EOF
|
||||
# ==========================================
|
||||
# INVENTARSYSTEM ($tenant_id)
|
||||
# ==========================================
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
server_name $domain;
|
||||
client_max_body_size 100M;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/$domain/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/$domain/privkey.pem;
|
||||
|
||||
location / {
|
||||
proxy_pass http://$NGINX_PROXY_HOST:$port;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
# Gezielte HTTP zu HTTPS Weiterleitung für $tenant_id
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name $domain;
|
||||
return 301 https://$domain\$request_uri;
|
||||
}
|
||||
EOF
|
||||
else
|
||||
sudo tee "$site_path" >/dev/null <<EOF
|
||||
# ==========================================
|
||||
# INVENTARSYSTEM ($tenant_id)
|
||||
# ==========================================
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
server_name $domain;
|
||||
client_max_body_size 100M;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/$domain/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/$domain/privkey.pem;
|
||||
|
||||
location / {
|
||||
proxy_pass http://$NGINX_PROXY_HOST:$port;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
# Gezielte HTTP zu HTTPS Weiterleitung für $tenant_id
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name $domain;
|
||||
return 301 https://$domain\$request_uri;
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
|
||||
if ! run_host_command ln -sfn "$site_path" "$enabled_path"; then
|
||||
echo "Warning: Could not enable nginx site for tenant '$tenant_id'."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! reload_host_nginx; then
|
||||
echo "Warning: nginx reload after tenant '$tenant_id' configuration update failed."
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
remove_tenant_nginx_config() {
|
||||
local tenant_id="$1"
|
||||
local domain site_path enabled_path
|
||||
|
||||
domain="$(tenant_domain "$tenant_id")"
|
||||
site_path="$(tenant_nginx_site_path "$tenant_id")"
|
||||
enabled_path="$(tenant_nginx_enabled_path "$tenant_id")"
|
||||
|
||||
if [ -f "$enabled_path" ] || [ -L "$enabled_path" ]; then
|
||||
run_host_command rm -f "$enabled_path" || true
|
||||
fi
|
||||
|
||||
if [ -f "$site_path" ]; then
|
||||
run_host_command rm -f "$site_path" || true
|
||||
fi
|
||||
|
||||
if command -v certbot >/dev/null 2>&1 || command -v sudo >/dev/null 2>&1; then
|
||||
run_host_command certbot delete --cert-name "$domain" --non-interactive >/dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
reload_host_nginx || true
|
||||
}
|
||||
|
||||
ensure_runtime_config_json() {
|
||||
local config_path backup_path
|
||||
@@ -505,15 +749,18 @@ ${YELLOW}Nutzung:${RESET} $0 <befehl> [tenant_id] [optionen]
|
||||
|
||||
${BLUE}${BOLD}VERFÜGBARE BEFEHLE:${RESET}
|
||||
${GREEN}add${RESET} <tenant_id> [port]
|
||||
Legt einen neuen Tenant an, registriert den Port und initialisiert
|
||||
die MongoDB-Datenbank mit einem Standard-Admin (${YELLOW}admin / admin123${RESET}).
|
||||
Legt einen neuen Tenant an, registriert den Port, richtet den nginx-Host
|
||||
für ${YELLOW}<tenant_id>.invario-software.de${RESET} ein und initialisiert
|
||||
die MongoDB-Datenbank mit einem Standard-Admin (${YELLOW}admin / admin123${RESET}).
|
||||
|
||||
${GREEN}trial${RESET} <tenant_id> [port] [tage]
|
||||
Erstellt einen temporären Test-Tenant. Standardlaufzeit: 7 Tage.
|
||||
Läuft automatisch ab und löscht sich selbst.
|
||||
Läuft automatisch ab, löscht sich selbst und bekommt die gleiche nginx/
|
||||
Certbot-Anbindung wie ein normaler Tenant.
|
||||
|
||||
${GREEN}remove${RESET} [-y|--yes] <tenant_id>
|
||||
Löscht einen Tenant, seine Konfiguration, Ports und die Datenbank.
|
||||
Löscht einen Tenant, seine Konfiguration, Ports, nginx-VHost und das
|
||||
zugehörige Let's-Encrypt-Zertifikat sowie die Datenbank.
|
||||
Nutze ${RED}-y${RESET}, um die Bestätigungsabfrage zu überspringen.
|
||||
|
||||
${GREEN}restart-tenant${RESET} <tenant_id>
|
||||
@@ -574,11 +821,16 @@ case "$COMMAND" in
|
||||
register_tenant_port "$TENANT_ID" "$PORT_ARG"
|
||||
update_runtime_ports "$PORT_ARG"
|
||||
sync_tenant_port_map
|
||||
if ! write_tenant_nginx_config "$TENANT_ID" "$PORT_ARG"; then
|
||||
echo "Warning: nginx/certbot provisioning for '$TENANT_ID' could not be completed automatically."
|
||||
fi
|
||||
if [ -n "$(docker ps -qf 'name=app' | head -n 1)" ]; then
|
||||
restart_app_container
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
|
||||
echo "Adding new tenant '$TENANT_ID'..."
|
||||
echo "Initializing database for $TENANT_ID..."
|
||||
initialize_tenant_database "$TENANT_ID" "standard"
|
||||
@@ -603,6 +855,9 @@ case "$COMMAND" in
|
||||
register_tenant_port "$TENANT_ID" "$PORT_ARG"
|
||||
update_runtime_ports "$PORT_ARG"
|
||||
sync_tenant_port_map
|
||||
if ! write_tenant_nginx_config "$TENANT_ID" "$PORT_ARG"; then
|
||||
echo "Warning: nginx/certbot provisioning for trial tenant '$TENANT_ID' could not be completed automatically."
|
||||
fi
|
||||
fi
|
||||
|
||||
write_trial_tenant_config "$TENANT_ID" "$PORT_ARG" "$DAYS_ARG"
|
||||
@@ -682,6 +937,7 @@ case "$COMMAND" in
|
||||
if [ -n "$port_to_remove" ]; then
|
||||
remove_runtime_port "$port_to_remove"
|
||||
fi
|
||||
remove_tenant_nginx_config "$TENANT_ID"
|
||||
sync_tenant_port_map
|
||||
if [ -n "$(docker ps -qf 'name=app' | head -n 1)" ]; then
|
||||
restart_app_container
|
||||
|
||||
Reference in New Issue
Block a user