---
title: Protección con contraseña
description: Protege todo tu sitio de documentación o solo algunas páginas con una contraseña compartida. Los visitantes ven una pantalla de acceso; el resto de tu documentación permanece abierta.
---

A veces quieres que tu documentación esté en línea, sea descubrible, versionada en Git, pero no visible para todo el mundo. Runbooks, guías de prelanzamiento, documentos solo para socios, funciones de acceso anticipado. La protección con contraseña te proporciona una frase de contraseña compartida que controla el acceso a todo tu sitio o a un conjunto específico de páginas, sin mover nada de tu repositorio existente.

Las capturas de pantalla muestran la interfaz en inglés.

<Note>
  Necesitarás un proyecto de Jamdesk [conectado a un repositorio de Git](/es/setup/connecting-github) antes de poder activar la protección con contraseña. La configuración reside en `docs.json`, por lo que la protección con contraseña se integra en tu flujo normal de build y despliegue.
</Note>

## ¿Qué modo debo elegir?

Jamdesk tiene dos modos de protección con contraseña. Elige uno según lo que sea público y lo que no.

| | **Modo para todo el sitio** | **Modo para páginas específicas** |
|---|---|---|
| **Úsalo cuando** | Todo es privado: documentación interna de ingeniería, una copia de staging de tu sitio público, un producto sin lanzar. | La mayoría de la documentación es pública. Solo necesitas ocultar algunas páginas (un runbook, una función beta, una referencia de API interna). |
| **Cómo activarlo** | Establece `auth.password.enabled: true` en `docs.json`. | Marca las páginas como privadas con `private: true` en el frontmatter, o lista las rutas en `auth.password.private[]`. |
| **Excepciones públicas** | Sí: marca páginas individuales, grupos de navegación o patrones glob como públicos. | N/A. Cada página es pública a menos que la marques como privada. |

Ambos modos comparten la misma tarjeta en el dashboard, la misma pantalla de acceso y los mismos controles de rotación y revocación. Puedes cambiar entre ellos en cualquier momento editando `docs.json` y haciendo push.

## Proteger todo el sitio

<Steps>
  <Step title="Agrega auth.password.enabled a docs.json">
    Abre tu `docs.json` y declara la protección para todo el sitio. El campo `hint` es opcional pero muy recomendado, ya que es la única pista visible en pantalla que tus lectores tienen sobre cómo obtener la contraseña.

    ```json docs.json
    {
      "$schema": "https://jamdesk.com/docs.json",
      "name": "Acme Docs",
      "theme": "jam",
      "auth": {
        "password": {
          "enabled": true,
          "hint": "Ask #docs-access on Slack"
        }
      }
    }
    ```

    Los hints son texto plano, máximo 200 caracteres, sin HTML.

    <Tip>
      No pongas la contraseña en `docs.json`. La contraseña se establece en el dashboard después del build. Tu repositorio solo contiene el indicador de activación y un hint opcional.
    </Tip>
  </Step>

  <Step title="Haz commit y push">
    Sube el cambio a tu rama configurada. Jamdesk ejecuta un build y, durante el proceso, activa la protección con contraseña en modo para todo el sitio.

    ```bash
    git add docs.json
    git commit -m "Turn on password protection"
    git push
    ```

    Mientras escribías, la tarjeta del dashboard cambió de **Off** a **Password not set**, y tu sitio empezó a devolver `401` en todas las páginas. Hasta que establezcas una contraseña, todas las solicitudes serán rechazadas. La puerta está cerrada y aún no tiene llave.

    ![Tarjeta de Password Protection mostrando el estado 'Password not set' con alerta de advertencia y botón Set password](/images/password-protection/dashboard-pp-notset.webp)
  </Step>

  <Step title="Establece la contraseña en el dashboard">
    Abre **Project Settings** en el dashboard y desplázate hasta la tarjeta **Password Protection**. Escribe una frase de contraseña segura (mínimo 8 caracteres) y haz clic en **Set password**.

    La tarjeta cambia al estado **On**. Todos los que tengan la contraseña podrán navegar por el sitio; los demás verán la pantalla de acceso.

    ![Tarjeta de Password Protection en estado On mostrando el formulario de rotación, el botón Revoke all sessions e instrucciones para desactivar](/images/password-protection/dashboard-pp-on.webp)

    <Warning>
      Jamdesk nunca almacena tu contraseña en texto plano. Se hashea con scrypt en la base de datos del dashboard y nunca se escribe en tu repositorio ni en `docs.json`. Eso también significa que Jamdesk no puede enviártela por correo si la olvidas. Usa la rotación en su lugar.
    </Warning>
  </Step>

  <Step title="Verifica el acceso">
    Abre tu sitio de documentación en una ventana de navegador privada (o con `curl`) y confirma que ves la pantalla de acceso. Prueba con una contraseña incorrecta para comprobar el estado de error, y luego con la real para acceder.

    ```bash
    # Should respond with HTTP/1.1 401 and the unlock HTML
    curl -I https://acme.jamdesk.app/

    # Submit the password. On success, sets the jd_auth_<slug> cookie.
    curl -i -X POST https://acme.jamdesk.app/jd/unlock \
      -d "password=your-passphrase&from=/"
    ```

    Un acceso exitoso devuelve una redirección `303` con un encabezado `Set-Cookie: jd_auth_acme=...; HttpOnly; Secure; SameSite=Lax; Max-Age=2592000`. Guarda esa cookie para la siguiente solicitud y habrás accedido.
  </Step>
</Steps>

### Excepciones públicas

El modo para todo el sitio tiene una válvula de escape: puedes mantener páginas específicas públicas aunque el resto del sitio esté protegido. Así es como publicas una página de marketing o un formulario de registro junto a documentación privada.

Tienes tres formas de marcar una página como pública, y todas se fusionan en la misma lista de permitidos en cada build.

**Frontmatter** es la opción más granular. Agrega `public: true` a cualquier archivo `.mdx` y solo esa página escapa al control de acceso:

```yaml
---
title: Get started
public: true
---
```

**Los grupos de navegación** cubren toda una sección a la vez. Establece `public: true` en un `group` o `tab` en la navegación de tu `docs.json`, y todas las páginas bajo él serán públicas. Útil para una pestaña de "Marketing" junto a documentación privada de ingeniería:

```json docs.json
{
  "navigation": {
    "tabs": [
      {
        "tab": "Marketing",
        "public": true,
        "groups": [
          {
            "group": "Overview",
            "pages": ["landing", "pricing", "changelog"]
          }
        ]
      },
      {
        "tab": "Internal",
        "groups": [
          { "group": "Runbooks", "pages": ["deploys", "oncall"] }
        ]
      }
    ]
  }
}
```

**Los globs explícitos** en `auth.password.public[]` manejan lo que el frontmatter y la navegación no pueden: páginas de inicio de nivel superior, rutas generadas dinámicamente o un subárbol completo que prefieres no reescribir.

```json docs.json
{
  "auth": {
    "password": {
      "enabled": true,
      "hint": "Ask #docs-access on Slack",
      "public": [
        "/landing",
        "/pricing",
        "/marketing/**",
        "/blog/*"
      ]
    }
  }
}
```

Los globs admiten `*` (un segmento de ruta) y `**` (cualquier profundidad). Un `/` simple es rechazado en la validación: si Jamdesk lo aceptara, un solo error tipográfico podría desbloquear silenciosamente todo tu sitio. Después de cada build, la tarjeta del dashboard muestra la lista de permitidos resuelta, para que puedas verificar lo que el build realmente capturó.

## Proteger solo algunas páginas

El modo para páginas específicas es el flujo opuesto: todo es público por defecto y tú decides qué páginas individuales quedan protegidas.

<Steps>
  <Step title="Marca una página como privada">
    Agrega `private: true` al frontmatter de la página. Esta es la opción más sencilla cuando la decisión recae en quien es responsable de la página.

    ```yaml
    ---
    title: Incident Runbook
    description: What to do when the deploys dashboard is on fire.
    private: true
    ---
    ```

    O, si prefieres mantener la lista de rutas protegidas en un solo archivo, agrégalas en `auth.password.private[]` en `docs.json`. Ambos enfoques son aditivos, por lo que puedes combinarlos.

    ```json docs.json
    {
      "auth": {
        "password": {
          "hint": "Ask the on-call engineer",
          "private": ["/admin/runbook", "/internal/api-keys"]
        }
      }
    }
    ```

    Observa que no hay `enabled: true`. Establecer `auth.password.private[]` sin `enabled` es lo que activa el modo para páginas específicas automáticamente.
  </Step>

  <Step title="Haz commit y push">
    Sube tus cambios. El siguiente build detecta las páginas privadas, activa la protección en modo para páginas específicas y muestra en el dashboard el aviso para establecer una contraseña, exactamente igual que en el modo para todo el sitio.

    ```bash
    git add content/runbook.mdx docs.json
    git commit -m "Gate the incident runbook"
    git push
    ```
  </Step>

  <Step title="Establece la contraseña">
    Abre **Project Settings**, busca la tarjeta **Password Protection** y establece una frase de contraseña. El encabezado de la tarjeta ahora muestra **On** con **Specific pages** en lugar de **Whole site**, y muestra la lista de páginas privadas que el build resolvió para que puedas auditarla de un vistazo.

    ![Tarjeta de Password Protection en modo de páginas específicas con tres rutas privadas listadas e instrucciones de desactivación actualizadas](/images/password-protection/dashboard-pp-specific.webp)
  </Step>

  <Step title="Verifica el acceso">
    Navega por tu sitio de documentación normalmente. Las páginas públicas deben cargarse como antes; las páginas privadas deben redirigirte a la pantalla de acceso. Una vez que ingreses la contraseña, quedarás autenticado durante 30 días en ese dispositivo y podrás leer cualquier página privada sin volver a escribirla.
  </Step>
</Steps>

## Lo que ven los visitantes

Cuando alguien accede a una página protegida, ve una tarjeta de acceso centrada sin barra lateral, sin elementos de navegación y sin indicación de qué hay detrás, salvo el nombre del sitio y un hint opcional.

![Pantalla de acceso de ACME con el nombre del sitio, icono de candado, campo de contraseña y texto de pista debajo](/images/password-protection/unlock-screen.webp)

La tarjeta lleva la marca de tu sitio con el logo y el color primario de `docs.json`. El campo de contraseña tiene un botón para mostrar u ocultar el texto y recibe el foco automáticamente.

Las contraseñas incorrectas muestran la misma tarjeta con un mensaje de error, un campo nuevo y un pequeño retraso entre intentos. Una contraseña incorrecta y una solicitud sin contraseña muestran la misma pantalla, por lo que nada en la página distingue "contraseña incorrecta" de "aún no se ha ingresado ninguna contraseña".

![Pantalla de acceso tras un intento fallido, con 'Incorrect password. Please try again.' en rojo](/images/password-protection/unlock-screen-error.webp)

Una vez que el visitante ingresa la contraseña correcta, recibe una cookie firmada y puede navegar con normalidad hasta que la sesión expire o la revoques.

## Rotación y revocación de sesiones

Las contraseñas se comparten. Las personas se van. Querrás cambiarla tarde o temprano.

Abre la tarjeta **Password Protection**, escribe una nueva frase de contraseña en el campo **Rotate password** y haz clic en **Save new password**. Todos los que tenían la contraseña anterior quedan bloqueados en su siguiente solicitud; todos los que tienen la nueva contraseña pueden acceder. La rotación tiene efecto inmediato y no requiere un rebuild.

Si solo quieres forzar el cierre de sesión de todas las sesiones activas sin cambiar la frase de contraseña (por ejemplo, si el portátil de alguien desapareció), haz clic en **Revoke all sessions**. Esto incrementa un contador de versión del lado del servidor, lo que invalida todas las cookies emitidas antes del incremento. Los visitantes vuelven a ingresar la contraseña actual y recuperan el acceso.

## Desactivar la protección

La protección está controlada por `docs.json`, por lo que desactivarla implica editar el archivo y hacer push.

- **Todo el sitio:** elimina `auth.password.enabled` (o establécelo en `false`).
- **Páginas específicas:** elimina todos los marcadores `private: true` y vacía `auth.password.private`.

En el siguiente build, Jamdesk elimina el hash de contraseña almacenado y vuelve a mostrar la tarjeta en estado **Off**. No queda ningún estado "inactivo". Si vuelves a activar la protección más adelante, necesitarás elegir una nueva contraseña.

<Warning>
  Tu repositorio fuente no está protegido con contraseña. La protección con contraseña controla el acceso al sitio de documentación alojado en `*.jamdesk.app` (o tu dominio personalizado). Si tu repositorio de GitHub es público, el contenido MDX sigue siendo legible allí. Haz el repositorio privado si necesitas protección total del contenido.
</Warning>

## Reglas de precedencia

Una sola página puede estar afectada por varias señales a la vez. El orden de resolución, de más a menos específico:

- Si `auth.password.enabled` es `true`, todo el sitio está protegido. `private: true` en páginas individuales se vuelve redundante.
- Si una página está marcada como `public: true` y `private: true` al mismo tiempo, **public gana**. El valor predeterminado más seguro es el que no filtra accidentalmente una página.
- El frontmatter `public: true`, el `public: true` de grupos de navegación y los globs de `auth.password.public[]` se fusionan en una sola lista de permitidos. No existe una regla de "más específico gana". Si cualquier señal indica que una página es pública, es pública.
- Si `auth.password.private[]` está configurado pero `auth.password.enabled` no lo está, Jamdesk activa el modo para páginas específicas automáticamente. No necesitas hacer nada más.

## Cómo funcionan las sesiones y la limitación de solicitudes

Surgen tres preguntas con cualquier nuevo sistema de autenticación.

**La cookie de sesión.** Al desbloquear correctamente, Jamdesk establece una cookie llamada `jd_auth_<slug>` (por ejemplo, `jd_auth_acme`). Es `HttpOnly`, `Secure`, `SameSite=Lax`, con alcance al host y firmada con HMAC-SHA256. El payload incluye el slug del proyecto, el contador de versión actual y una marca de tiempo de expiración, por lo que cualquier manipulación falla la validación. La duración predeterminada es de **30 días**, renovada en cada acceso exitoso.

**Limitación de solicitudes.** El endpoint de acceso aplica dos contadores por hora: **10 intentos por IP** y **100 intentos por proyecto**. Ambos se aplican antes de la verificación del hash scrypt para que un intento de fuerza bruta no pueda consumir CPU ni filtrar información de tiempo. Superar cualquiera de los límites devuelve `429 Too Many Requests` con un encabezado `Retry-After`.

**Almacenamiento.** Tu contraseña se hashea con scrypt y se almacena en el Firestore del dashboard. Nunca llega a tu repositorio, a tu `docs.json` ni a un artefacto del build. Si la pierdes, rótala. No existe ninguna ruta de recuperación.

## Pruebas durante el desarrollo local

`jamdesk dev` ejecuta tu documentación contra el contenido R2 en vivo y la configuración en vivo. La protección con contraseña **no se aplica** en el servidor de desarrollo local, por lo que puedes hacer preview de las páginas protegidas sin conocer la contraseña. Esto es deliberado: eres el autor, ya tienes acceso al repositorio, y bloquear el preview local con una contraseña sería fricción sin ningún beneficio de seguridad.

Si quieres verificar el acceso real, accede al sitio desplegado en `<slug>.jamdesk.app` (o tu dominio personalizado) desde una ventana del navegador que aún no tenga la cookie.

## Solución de problemas

<Accordion title="Mi build ha terminado pero la pantalla de acceso nunca aparece">
  El dashboard probablemente muestra **Password not set**. La protección no se activa hasta que hayas (1) subido la configuración a `docs.json` y (2) establecido una contraseña en **Project Settings**. Hasta que se complete el segundo paso, cada solicitud devuelve `401` con la pantalla de acceso como cuerpo, lo que puede parecer que la pantalla "no aparece" si esperabas un destino específico.
</Accordion>

<Accordion title="Establecí la contraseña pero mi compañero sigue viendo la pantalla de acceso">
  Su navegador tiene una cookie `jd_auth_<slug>` antigua de antes de que roticaras. Puede esperar 30 días a que expire la cookie, hacer clic en **Revoke all sessions** en el dashboard o borrar las cookies del dominio de la documentación. Se le pedirá la contraseña actual en su próxima visita.
</Accordion>

<Accordion title="¿Puedo compartir contraseñas diferentes con distintos grupos?">
  No directamente. Jamdesk usa una única contraseña compartida por sitio. Si necesitas acceso por grupos, divide tu documentación en múltiples proyectos (cada uno con su propia contraseña) o usa el modo para páginas específicas con límites separados de público/privado por audiencia.
</Accordion>

<Accordion title="¿La protección con contraseña funciona con dominios personalizados?">
  Sí. La cookie de acceso está vinculada al host, por lo que cada host (el subdominio `*.jamdesk.app` y tu dominio personalizado) se autentica de forma independiente. Los lectores que desbloqueen un host no estarán preautenticados en el otro.
</Accordion>

<Accordion title="¿Un sitio protegido sigue apareciendo en los motores de búsqueda?">
  No. Los sitios protegidos establecen `noindex, nofollow` en la pantalla de acceso y devuelven `401` para cada página protegida, por lo que los rastreadores de búsqueda no pueden indexar nada detrás del control de acceso. Las páginas públicas dentro de un sitio protegido siguen siendo indexables con normalidad.
</Accordion>

## ¿Qué sigue?

<Columns cols={2}>
  <Card title="Descripción general de Control de acceso" icon="shield" href="/es/setup/access-control">
    Compara la protección con contraseña con SSO y el patrón de múltiples proyectos.
  </Card>
  <Card title="SSO (Enterprise)" icon="key" href="/es/setup/sso">
    Reemplaza las frases de contraseña compartidas con inicio de sesión por usuario a través de tu proveedor de identidad.
  </Card>
  <Card title="Dominios personalizados" icon="globe" href="/es/deploy/custom-domains">
    Pon tu documentación en tu propio dominio antes de compartir el enlace.
  </Card>
  <Card title="Esquema de auth.password" icon="book" href="/es/config/docs-json-reference#auth-password">
    Referencia completa de campos para `enabled`, `hint`, `public` y `private`.
  </Card>
</Columns>
