Antes de empezar

Preparar tu equipo

El curso funciona en Windows (con o sin WSL), macOS y Linux. Necesitas lo mismo en todos: Go, Docker y un navegador. Aquí tienes cómo instalarlo en cada sistema y qué cambia al seguir las lecciones.

Qué necesitas

HerramientaVersiónPara qué
Go1.26 o superiorTodo el código del curso. Las versiones actuales de go-oidc y x/oauth2 exigen 1.26.
Docker con Compose v2Docker Desktop, OrbStack o Docker EngineKeycloak y PostgreSQL (docker compose, con espacio). La lección 11 añade un Active Directory de prueba (Samba, unos 300 MB); la 16, Caddy y una imagen de Keycloak construida por ti.
curlcualquieraProbar endpoints a mano. Viene con macOS, Linux y Windows 10/11 (curl.exe).
Navegadorcualquiera modernoEl login. Una ventana privada viene bien para probar con otro usuario.
Editorel que prefierasVS Code con la extensión de Go es una buena opción en los tres sistemas.

Dónde se ha probado

EntornoEstado
Windows 11 + WSL 2 (Ubuntu, Docker Desktop con integración WSL)✔ Todo el curso, lección por lección, y la verificación automática completa (tools/ci con act): los 15 pasos de punta a punta, sus tests y la infraestructura de producción.
Windows 11 sin WSL (Go para Windows, Docker Desktop, PowerShell 5.1 y 7, Git Bash)✔ Comprobado: Keycloak, login de tienda-web, back-channel logout, api-pedidos, la CLI de tokens, la exportación del realm y los comandos de esta página. La verificación con act funciona desde Git Bash (tools/ci/README.md).
macOS (Intel o Apple Silicon)Sin probar directamente. Las imágenes de Keycloak 26.8.0, PostgreSQL 17 y Samba (lección 11) tienen versión arm64 (comprobado), y Docker Desktop para Mac funciona igual que en Windows en lo que importa aquí (host.docker.internal, puertos en localhost).
Linux (Docker Engine)Sin probar directamente. Los docker-compose.yml incluyen lo necesario para Linux (extra_hosts, ver más abajo).

macOS

  1. Go: el instalador .pkg de go.dev/dl (elige darwin-arm64 para Apple Silicon, darwin-amd64 para Intel) o brew install go.
  2. Docker: Docker Desktop para Mac (con el chip correcto) u OrbStack. Arráncalo antes de seguir.
  3. Terminal: la de macOS (zsh). Los comandos del curso funcionan tal cual.
go version                 # go version go1.26… darwin/arm64
docker compose version     # Docker Compose version v2…
docker run --rm hello-world
Particularidades de macOS
  • Si tienes activado el cortafuegos de macOS, la primera vez que un programa Go escuche en un puerto puede preguntarte si aceptas conexiones entrantes. Acepta (o arranca la app con ADDR=localhost:3000, ver abajo).
  • Docker Desktop y OrbStack definen host.docker.internal. Si usas otro motor (Colima, Podman…), comprueba que resuelve con docker run --rm alpine getent hosts host.docker.internal; solo afecta al back-channel logout (lección 4).
  • En la exportación del realm (lección 2), con Docker Desktop normalmente no hace falta el chmod 777. Si ves AccessDeniedException, aplícalo.

Windows sin WSL

  1. Go: el instalador .msi de go.dev/dl o winget install GoLang.Go. Abre una terminal nueva después.
  2. Docker: Docker Desktop para Windows. Por dentro usa WSL 2, pero tú no necesitas trabajar dentro de una distribución Linux.
  3. Terminal: PowerShell (mejor la 7, winget install Microsoft.PowerShell) o Git Bash (viene con Git para Windows). Con Git Bash los comandos del curso funcionan casi tal cual; con PowerShell, mira la tabla de equivalencias.
go version                 # go version go1.26… windows/amd64
docker compose version
docker run --rm hello-world
Particularidades de Windows
  • Rutas: los cd tienda/pasos/paso-02/infra del curso funcionan en PowerShell y en Git Bash; las barras / valen.
  • Cortafuegos: la primera vez que go run ./cmd/web escuche en :3000, Windows puede pedir permiso. Para no verlo, arranca con $env:ADDR="localhost:3000": el curso funciona igual, incluido el back-channel logout. Lo hemos comprobado: Docker Desktop entrega a la app las conexiones de los contenedores como si vinieran de 127.0.0.1.
  • Exportar el realm (lección 2): sin chmod; y en Git Bash, con MSYS_NO_PATHCONV=1 (ver la tabla).

Windows con WSL 2

  1. Instala Go dentro de tu distribución (el tarball de go.dev/dl para linux-amd64). El paquete de la distribución suele ser demasiado antiguo.
  2. Docker Desktop en Windows, con Settings → Resources → WSL integration activado para tu distribución.
  3. Si docker ps dice permission denied … docker.sock: tu usuario está en el grupo docker, pero la terminal se abrió antes. Cierra la terminal (o wsl --shutdown desde PowerShell) y abre otra.
El caso especial de WSL

Con la red NAT de WSL (la predeterminada), los contenedores no llegan a tus programas de WSL por host.docker.internal, que apunta a Windows. Para el back-channel logout (lección 4) usa la IP de WSL (hostname -I), que cambia al reiniciar. Es lo único del curso que cambia en WSL.

Linux

  1. Go: el tarball de go.dev/dl (sudo tar -C /usr/local -xzf go1.26…linux-amd64.tar.gz y añade /usr/local/go/bin al PATH). Los paquetes de las distribuciones suelen ir por detrás.
  2. Docker: Docker Engine con el plugin de Compose (docker-compose-plugin), siguiendo la guía oficial de tu distribución.
  3. Permisos: sudo usermod -aG docker $USER y abre una sesión nueva. Sin eso verás permission denied … /var/run/docker.sock.
Particularidades de Linux
  • host.docker.internal no existe por defecto con Docker Engine. Los docker-compose.yml del curso lo definen con extra_hosts: ["host.docker.internal:host-gateway"]. Con eso, el back-channel logout funciona como en Windows y macOS, siempre que la app escuche en todas las interfaces (:3000, lo predeterminado).
  • La exportación del realm (lección 2) sí necesita el chmod 777 de la carpeta, porque el contenedor escribe como el usuario 1000.

Los comandos del curso en PowerShell

Las lecciones usan sintaxis de bash (macOS, Linux, WSL, Git Bash). En PowerShell cambian unas pocas cosas:

Québash / zshPowerShell
Variable de entorno para un comandoOIDC_CLIENT_SECRET=otro go run ./cmd/web$env:OIDC_CLIENT_SECRET="otro"; go run ./cmd/web
(queda definida en esa terminal; se quita con Remove-Item Env:OIDC_CLIENT_SECRET)
Guardar la salida de un comandoTOKEN=$(go run ./cmd/token)$TOKEN = go run ./cmd/token ✔ probado
Usar la variable-H "Authorization: Bearer $TOKEN"igual ✔
curlcurlcurl.exe
(en PowerShell 5.1, curl es otro comando: Invoke-WebRequest)
Partir una línea larga\ al final` (acento grave) al final
Crear una carpetamkdir -p exportmkdir export
Carpeta actual en una ruta"$PWD/export:/tmp/export""${PWD}\export:/tmp/export" ✔ probado con docker compose run

Enviar JSON con curl en Windows

Es el único punto delicado, porque PowerShell 5.1 y 7 pasan las comillas a curl.exe de forma distinta. Resultados reales contra api-pedidos:

FormaPowerShell 5.1PowerShell 7
-d '{"producto":"taza","cantidad":1}'❌ «JSON inválido»✔
-d '{\"producto\":\"taza\",\"cantidad\":1}'✔❌ «JSON inválido»
--data "@pedido.json" (el JSON en un archivo)✔✔

Lo más sencillo: guarda el cuerpo en un archivo y envíalo con @. Funciona en todas las terminales.

Set-Content -Path pedido.json -Value '{"producto":"taza","cantidad":1}'
curl.exe -s -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" `
  --data "@pedido.json" http://localhost:8081/pedidos

Git Bash

En Git Bash los comandos de bash funcionan tal cual, con una excepción comprobada: Git Bash convierte las rutas que empiezan por / en rutas de Windows, y eso rompe los volúmenes de Docker. En la exportación de la lección 2, /tmp/export se convirtió en C:/Users/…/Temp/export y Keycloak falló. Se arregla así:

MSYS_NO_PATHCONV=1 docker compose run --rm -v "$PWD/export:/tmp/export" keycloak \
  export --dir /tmp/export --realm tienda --users realm_file

Tu app vista desde Keycloak

Solo una lección (la 4, back-channel logout) necesita que Keycloak, desde su contenedor, llame a un programa tuyo. La URL depende del entorno:

EntornoBackchannel logout URL
Windows sin WSL (Docker Desktop)http://host.docker.internal:3000/backchannel-logout ✔ probado, también con la app en localhost:3000
macOS (Docker Desktop, OrbStack)http://host.docker.internal:3000/backchannel-logout
Linux (Docker Engine)http://host.docker.internal:3000/backchannel-logout (gracias al extra_hosts del compose; la app debe escuchar en :3000)
WSL 2 con red NAThttp://<IP de WSL>:3000/backchannel-logout (hostname -I) ✔ probado

Problemas típicos por sistema

permission denied …/var/run/docker.sock (Linux, WSL)

Tu usuario no está en el grupo docker, o lo está pero la sesión es anterior. sudo usermod -aG docker $USER y abre una sesión nueva (en WSL: cierra todas las terminales o wsl --shutdown).

docker: command not found / error during connect

Docker Desktop no está arrancado (Windows, macOS), no está instalado (Linux) o falta la integración con tu distribución (WSL).

go.mod requires go >= 1.26

Tu Go es más antiguo. Instálalo desde go.dev/dl, no desde el gestor de paquetes de la distribución.

JSON inválido al hacer un POST desde PowerShell

Comillas. Usa un archivo con --data "@archivo.json" (ver arriba).

token is expired con tokens recién emitidos

El reloj de tu máquina va mal. En Windows y macOS activa la hora automática; en WSL, tras suspender el portátil, sudo hwclock -s; en Linux, timedatectl set-ntp true.

address already in use en 8080, 3000, 8081 u 8082

Otro programa usa el puerto. Cambia el de la app con ADDR, o el de Keycloak en el compose (y entonces el issuer pasa a ser http://localhost:<puerto>/realms/tienda en todas partes).