CreaRack-SL

Setting SITE_URL — URL base pública para emails y enlaces

Ubicación

Archivo: config/settings/base.py
Definición:

SITE_URL = os.getenv("SITE_URL") or "https://crearack.com"

Tipo: Django setting, string con URL base (scheme + host, sin trailing slash)

Propósito

Inyectar la URL base pública del SaaS en:

  1. Email de bienvenida: el campo login_url y la base del enlace “Set password”
  2. Otros emails futuros que generen enlaces internos (password reset, confirmaciones)

Caso de uso principal: Permitir que STAGE y PROD usen la misma codebase (mismo settings.py) pero generen enlaces hacia hosts distintos.

Configuración por entorno

EntornoValor env varResultado SITE_URLEmails apuntan a
PRODNo definidahttps://crearack.comcrearack.com
STAGEhttps://stage.example.nethttps://stage.example.netstage.example.net
DEV localNo definidahttps://crearack.comcrearack.com (fallback OK para links que no se usan)

Patrón getenv-or

SITE_URL = os.getenv("SITE_URL") or "https://crearack.com"

Usa or en lugar de .get(..., default=...) para evitar el footgun de Dokploy: si Dokploy declara la env var como vacía (string ""), os.getenv("SITE_URL") retorna "" (falseo en Python), y el or pasa al default. Sin esto, SITE_URL sería "" y los emails apuntarían a rutas relativas inválidas.

Consumidores

core.email_service._generate_set_password_url(user)

return f"{settings.SITE_URL}/accounts/password/reset/key/{uidb36}-{token}/"

El enlace “Crea tu contraseña” del email de bienvenida sale con este SITE_URL.

core.email_service.send_welcome_email(user)

context = {
    # ...
    "login_url": settings.SITE_URL,
    "set_password_url": _generate_set_password_url(user),
}

El template welcome.html usa {{ login_url }} para el botón de login y {{ set_password_url }} para el enlace de creación de contraseña.

Histórico de cambios

Pre-v1.65.3

Los URLs de email estaban hardcodeados:

login_url = "https://crearack.com"
return f"https://crearack.com/accounts/password/reset/key/..."

Problema: STAGE generaba emails con enlaces a PROD, confundiendo a testers.

v1.65.3 (commit 1d2876c)

  • Introducida SITE_URL en config/settings/base.py
  • compose.prod.yml declara la env var en los servicios (default vacío para PROD)
  • STAGE fija su propio valor en Dokploy
  • core/email_service.py reemplazó hardcodes por settings.SITE_URL

Ejemplo: Variable en compose.prod.yml

environment:
  # Base pública para links en emails. PROD: sin valor (default crearack.com).
  # STAGE la fija en su Dokploy — sin esto sus emails apuntan a PROD (F1 PR-0).
  - SITE_URL=${SITE_URL:-}

El patrón ${VAR_NAME:-} en docker-compose pasará el valor de SITE_URL si existe, o una cadena vacía si no. El Python getenv-or luego aplica el default.

Testing

File: tests/api/test_signup_activation.py

Test: test_email_links_respect_site_url

@override_settings(SITE_URL="https://stage.example.net", ...)
def test_email_links_respect_site_url(client, django_capture_on_commit_callbacks):
    response = _signup(client, django_capture_on_commit_callbacks, ...)
    body = mail.outbox[0].body
    assert "https://stage.example.net/accounts/password/reset/key/" in body
    assert "https://crearack.com/accounts/password/reset" not in body

Verifica que el override en tests funciona y que no hay hardcodes residuales.

Contexto (F1 PR-0)

  • Task: #137 (Preparación de alta de cuentas)
  • Iniciativa: Fase 1 (F1)
  • Commit: v1.65.3 (1d2876c)
  • Cazado en plan-review: 2026-08-04

Véase también

  • [[entity—core—service—send-welcome-email]]
  • [[entity—core—service—signup-activation]]
  • [[feature—auth—email-welcome-activation-link]]
  • [[concept—saas—multi-environment-configuration]]
  • [[entity—core—model—user]]