How hostgator-setup-kit/install.sh Validates Environment Variables One at a Time
The script validates every environment variable individually using dedicated v_* validator functions wrapped in a recursive ask_one helper that repeats prompts until inputs pass strict format checks, API health tests, or database connectivity verification.
The hostgator-setup-kit/install.sh script in the melgarafael/DeskcommCRM repository implements a sequential, fail-fast validation pipeline for CRM configuration values. Rather than bulk-validating a .env file, it interrogates each variable—from domain names to Supabase credentials—through specialized Bash functions that enforce business rules and verify external connectivity before writing values to disk.
The Validation Architecture
Dedicated Validator Functions
Each configuration category defines a v_* function in hostgator-setup-kit/install.sh that receives raw user input, outputs localized Portuguese error messages on failure, and returns a non-zero exit code when validation fails. These functions act as atomic guards for specific data types:
v_domain(lines 73‑79) — Rejects URLs containing protocols or paths, accepting only bare hostnames (e.g.,crm.suaempresa.com.br).v_email(lines 82‑86) — Requires both an "@" symbol and a dot-separated domain.v_hex(lines 2‑4) — Accepts empty strings or hash-prefixed six-digit hexadecimal codes for brand colors.v_locale(lines 18‑24) — Restricts input topt-BR,es, or their numeric aliases1and2.v_supabase_url(lines 27‑44) — Verifies thehttps://scheme and performs a live HTTP request to the/auth/v1/healthendpoint.v_sb_key(lines 48‑65) — Parses JWT claims or the newersb_*format, ensuring the key’s role matches expectations and belongs to the specified Supabase project.v_db_url(lines 90‑41) — Validates the connection string scheme, removes placeholder passwords, confirms the host belongs to the same Supabase project, and executes a realpsqlcheck inside a temporary container.v_anthropic(lines 43‑54) — Enforces thesk-ant-prefix and makes a test request to the Anthropic API.v_openrouter(lines 56‑73) — Requires thesk-or-prefix and pings the OpenRouter endpoint.v_openai(lines 76‑88) — Optional validation requiring thesk-prefix and live API verification.v_password(lines 90‑94) — Enforces a minimum length of eight characters.
The ask_one Control Loop
The core interaction logic resides in the ask_one function (lines 96‑100). This helper accepts a prompt string and a validator function name, then implements a repeat-until-valid loop:
- Displays the prompt and captures user input.
- Invokes the specified
v_*validator with the raw value. - If the validator returns non-zero, prints the error message and recurses.
- If the user types
voltar(Portuguese for "back"), returns exit code2to signal navigation to a previous step. - On success, returns
0and stores the cleaned value.
Validator Implementation Details
Domain and Format Validators
Simple format validators perform pattern matching without external network calls. For example, v_domain explicitly rejects strings containing http or forward slashes, printing:
"Dige só o domínio, sem https:// — ex.: crm.suaempresa.com.br"
Similarly, v_hex uses regex to ensure color codes match ^#[0-9a-fA-F]{6}$ or are empty, preventing invalid CSS values from entering the configuration.
Supabase Ecosystem Validation
The script performs deep validation on Supabase credentials to prevent runtime connection failures:
v_supabase_url validates the URL format and performs a synchronous HTTP health check:
# Conceptual implementation based on lines 27-44
v_supabase_url() {
local url="$1"
[[ "$url" =~ ^https:// ]] || { echo "URL deve começar com https://"; return 1; }
curl -sf "${url}/auth/v1/health" >/dev/null || { echo "Supabase não responde"; return 1; }
}
v_sb_key (lines 48‑65) goes further by decoding the JWT payload to verify the role claim (e.g., anon or service_role) matches the expected key type, ensuring the user pasted the correct key for the intended permission level.
Database and Third-Party API Checks
High-risk variables like database URLs and paid API keys undergo live verification:
v_db_url (lines 90‑41) parses the PostgreSQL connection string, extracts the host, validates it belongs to the same Supabase project referenced earlier, and spawns a temporary container to execute psql -c "SELECT 1". This confirms both network reachability and credential validity before the installer proceeds.
API key validators follow a consistent pattern: prefix validation followed by authenticated ping. For instance, v_anthropic (lines 43‑54) checks for the sk-ant- prefix, then submits a minimal request to the Anthropic API to verify quota and key validity.
Interactive vs Non-Interactive Modes
When executed with the --yes flag, the script enters non-interactive mode and reads an existing .env file. Rather than prompting, it iterates over the same v_* validators automatically:
# Non-interactive validation pattern from the source
for var in DOMAIN EMAIL SUPABASE_URL ANON_KEY DB_URL; do
validator="v_${var,,}"
value="${!var}"
if ! "$validator" "$value"; then
die "Valor inválido para $var – corrija o .env e rode novamente."
fi
done
If any validator fails, the script aborts immediately with a clear error message, forcing the operator to correct the .env file before retrying. This guarantees that the same strict validation applies in both interactive and automated deployments.
Practical Usage Examples
Interactive Setup
During normal installation, each variable is collected individually:
# From hostgator-setup-kit/install.sh
ask_one "Qual domínio (ex.: crm.suaempresa.com.br)?" v_domain
ask_one "E-mail do admin?" v_email
ask_one "Cor da marca (ex.: #7a5cd6)?" v_hex
ask_one "URL do Supabase (ex.: https://abcd.supabase.co)?" v_supabase_url
ask_one "Chave anon do Supabase?" v_anon
ask_one "Chave service_role do Supabase?" v_service
ask_one "Connection string do Postgres?" v_db_url
ask_one "Chave Anthropic?" v_anthropic
ask_one "Chave OpenRouter?" v_openrouter
ask_one "Chave OpenAI (opcional)?" v_openai
ask_one "Senha do admin (mínimo 8 caracteres)?" v_password
If a user enters https://example.com for the domain, v_domain returns 1, prints the protocol error, and ask_one repeats the prompt until a bare hostname is provided.
Extending Validation
To add a validator for a new variable, define a v_* function returning 0 for success or 1 for failure, then invoke it via ask_one:
v_slack_webhook() {
local url="$1"
[[ "$url" =~ ^https://hooks.slack.com/ ]] || { echo "URL do Slack inválida"; return 1; }
curl -sf "$url" -X POST -d '{"text":"test"}' >/dev/null || { echo "Webhook não responde"; return 1; }
}
ask_one "Webhook do Slack?" v_slack_webhook
Summary
- Atomic validators: Each environment variable has a dedicated
v_*function inhostgator-setup-kit/install.sh(lines 2‑94) enforcing type-specific rules, from regex patterns to live API health checks. - Recursive prompting: The
ask_onehelper (lines 96‑100) isolates validation logic from user interaction, looping until inputs pass or the user triggers the back navigation (voltar). - Dual-mode operation: The same validation suite runs in both interactive mode (prompting) and non-interactive mode (
--yesflag reading existing.envfiles), ensuring consistency across manual and automated deployments. - External verification: High-value credentials (Supabase URLs, database connections, Anthropic/OpenAI keys) undergo real network validation to catch typos and permission errors before deployment.
Frequently Asked Questions
How does the script handle invalid input during interactive setup?
When a v_* validator returns a non-zero exit code, ask_one prints the validator’s Portuguese error message and recursively calls itself with the same prompt. This loop continues indefinitely until the user provides a valid value or types voltar to return to the previous question.
Can I run the installer without interactive prompts?
Yes. Executing install.sh --yes enables non-interactive mode, where the script reads an existing .env file and validates each value against the same v_* functions. If any validation fails, the script aborts with a descriptive error, requiring you to fix the .env before re-running.
What happens if I enter a valid-looking Supabase URL that is unreachable?
The v_supabase_url function (lines 27‑44) performs a live curl request to the /auth/v1/health endpoint. If the host is down, returns a non-200 status, or the SSL handshake fails, the validator prints an error and ask_one repeats the prompt, preventing you from proceeding with a broken configuration.
How do the validators distinguish between the anon and service_role Supabase keys?
The v_sb_key function (lines 48‑65) decodes the JWT payload to inspect the role claim. It validates that the key’s embedded role matches the expected type (e.g., anon vs service_role) and verifies the project identifier within the key matches the previously validated SUPABASE_URL, ensuring cryptographic isolation between environments.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →