Problema

En entornos de self‑hosted backup es frecuente montar un Kopia server dentro de un contenedor Docker y exponerlo mediante un reverse proxy con TLS. El cliente gráfico, Kopia UI, se conecta a esa URL para crear o abrir repositorios remotos. Un error típico que aparece en la UI es:

Connect Error: INTERNAL: internal server error: connect error: error opening repository:
error connecting to API server: unable to establish session for purpose=:
error establishing session: unable to initialize session: rpc error:
code = Unauthenticated desc = unexpected HTTP status code received from server: 401 (Unauthorized);
transport: received unexpected content-type "text/plain; charset=utf-8": EOF

En otras palabras, la petición HTTP llega al servidor, pero la capa de autenticación de la API rechaza al usuario. El síntoma se repite tanto en Windows como en cualquier otro cliente que use el mismo endpoint.

Causa

Los errores 401 Unauthorized en este contexto pueden deberse a varios factores que suelen coincidir en instalaciones “DIY”:

  1. Cabeceras de autorización ausentes o mal formateadas
    Kopia UI envía la credencial mediante HTTP Basic Auth (usuario:contraseña codificados en base64). Si el reverse proxy no pasa esa cabecera al contenedor, el servidor la interpreta como ausencia de credenciales.

  2. Terminación TLS en el proxy sin proxy_set_header adecuado
    Cuando Nginx/Traefik termina TLS, la petición interna al contenedor es HTTP. Si el proxy no re‑escribe la cabecera Authorization, el contenedor nunca la recibe.

  3. Endpoint de la API mal configurado
    El cliente debe apuntar a https://host:port/kopia/ (o el path que haya configurado el servidor). Un path distinto hace que la petición llegue a la raíz del contenedor, que devuelve 401 por defecto.

  4. Usuario creado en el servidor con permisos insuficientes
    En Kopia, los usuarios pueden estar limitados a ciertos repositories o a ciertos roles. Un usuario que solo tiene permiso de admin pero sin acceso a la ruta solicitada provocará 401.

  5. Desincronización entre la versión del cliente y la del servidor
    Cambios menores en la API (p.ej. en la versión 0.14) pueden romper la negociación de autenticación si una parte está actualizada y la otra no.

Solución

1. Verificar que el proxy reenvíe la cabecera Authorization

En Nginx, la configuración mínima para que la autenticación básica llegue al contenedor es:

server {
    listen 443 ssl;
    server_name backup.example.fake;

    ssl_certificate /etc/letsencrypt/live/backup.example.fake/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/backup.example.fake/privkey.pem;

    location / {
        proxy_pass http://kopia_server:51515;
        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;
        # <‑‑ clave
        proxy_set_header Authorization $http_authorization;
    }
}

La línea proxy_set_header Authorization $http_authorization; asegura que la credencial codificada enviada por Kopia UI no se pierda en la capa de TLS.

2. Confirmar el path de la API

Kopia server expone su API bajo /kopia. Si el contenedor se lanzó con la opción --listen=0.0.0.0:51515, el proxy debe reenviar a esa ruta:

proxy_pass http://kopia_server:51515/kopia/;

En la UI, la URL de conexión debe terminar en /kopia/ (p.ej. https://backup.example.fake/kopia/). O, si se prefiere eliminar el path del proxy, ajustar el location a location /kopia/ { ... }.

3. Revisar los usuarios y sus permisos

Dentro del contenedor, lista los usuarios y verifica los roles:

docker exec -it kopia_server kopia server user list

Si el usuario kopia aparece sin permisos de RepositoryWrite, añádelo:

docker exec -it kopia_server kopia server user add --username=kopia --password=MiClaveSegura --role=admin

Para limitar a un repositorio específico, usa --repo=repo-id. Asegúrate de que la contraseña sea la misma que ingresas en la UI.

4. Alinear versiones

Comprueba la versión del binario dentro del contenedor:

docker exec -it kopia_server kopia version

Y la versión de Kopia UI (se muestra en la barra de título). Si difieren en más de una versión menor, actualiza la que esté desfasada. En la mayoría de los casos, la versión más reciente de ambos componentes elimina incompatibilidades de autenticación.

5. Probar la API directamente

Antes de abrir la UI, usa curl para confirmar que la autenticación funciona:

curl -u kopia:MiClaveSegura -k https://backup.example.fake/kopia/v1/info

El flag -k ignora la verificación del certificado (solo para pruebas). La respuesta JSON con {"version":"...","mode":"server"} indica que la cabecera se está enviando correctamente. Si recibes 401, vuelve a la configuración del proxy.

Cuándo aplicar esta solución

  • Síntomas: la UI muestra “401 Unauthorized”, los logs del contenedor indican “rpc error: code = Unauthenticated”.
  • Entorno: Kopia server en Docker, acceso a través de un reverse proxy con TLS (Nginx, Traefik, Caddy, etc.).
  • No aplica: si el cliente se conecta directamente al contenedor (sin proxy) y la autenticación falla; en ese caso el problema suele estar en la creación del usuario o en la contraseña.

Código

# 1. Crear usuario con permisos admin (ejecución dentro del host)
docker exec -it kopia_server kopia server user add \
    --username=kopia \
    --password=MiClaveSegura \
    --role=admin

# 2. Verificar que el usuario exista
docker exec -it kopia_server kopia server user list

# 3. Probar la API con curl
curl -u kopia:MiClaveSegura -k https://backup.example.fake/kopia/v1/info

Verificación

  1. Reinicia Nginx (o el proxy que uses) para cargar la nueva configuración.
    sudo nginx -s reload
    
  2. Abre Kopia UI y crea/abre un repositorio remoto apuntando a https://backup.example.fake/kopia/.
  3. La UI debe cargar la lista de repositorios sin mostrar el mensaje de error.
  4. En los logs del contenedor (docker logs kopia_server) no debe aparecer Unauthenticated después de la conexión.

Notas adicionales

  • Certificados autofirmados: si decides no usar LetsEncrypt, agrega la CA al almacén de confianza de Windows o usa la opción -k en curl solo para pruebas. En producción, un certificado válido evita errores de “certificate verification failed” que a veces se confunden con 401.
  • Header stripping en Cloudflare: si el proxy está detrás de Cloudflare o similar, verifica que la opción “Disable HTTP Header Rewrite” esté activada; de lo contrario Cloudflare puede eliminar la cabecera Authorization.
  • Logs de Kopia: habilita KOPIA_LOGGING=debug al lanzar el contenedor para obtener trazas más detalladas de la negociación de sesión.
  • Persistencia de datos: siempre monta un volumen para /app/kopia-repo (o el directorio que uses) para evitar perder la configuración de usuarios al recrear el contenedor.

Con estos ajustes la comunicación entre Kopia UI en Windows y el servidor Kopia en Docker debería ser estable, segura y, lo más importante, libre de errores 401.