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
| Herramienta | Versión | Para qué |
|---|---|---|
| Go | 1.26 o superior | Todo el código del curso. Las versiones actuales de go-oidc y x/oauth2 exigen 1.26. |
| Docker con Compose v2 | Docker Desktop, OrbStack o Docker Engine | Keycloak 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. |
| curl | cualquiera | Probar endpoints a mano. Viene con macOS, Linux y Windows 10/11 (curl.exe). |
| Navegador | cualquiera moderno | El login. Una ventana privada viene bien para probar con otro usuario. |
| Editor | el que prefieras | VS Code con la extensión de Go es una buena opción en los tres sistemas. |
Dónde se ha probado
| Entorno | Estado |
|---|---|
| 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
- Go: el instalador
.pkgde go.dev/dl (eligedarwin-arm64para Apple Silicon,darwin-amd64para Intel) obrew install go. - Docker: Docker Desktop para Mac (con el chip correcto) u OrbStack. Arráncalo antes de seguir.
- 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
- 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 condocker 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 vesAccessDeniedException, aplícalo.
Windows sin WSL
- Go: el instalador
.mside go.dev/dl owinget install GoLang.Go. Abre una terminal nueva después. - Docker: Docker Desktop para Windows. Por dentro usa WSL 2, pero tú no necesitas trabajar dentro de una distribución Linux.
- 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
- Rutas: los
cd tienda/pasos/paso-02/infradel curso funcionan en PowerShell y en Git Bash; las barras/valen. - Cortafuegos: la primera vez que
go run ./cmd/webescuche 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 de127.0.0.1. - Exportar el realm (lección 2): sin
chmod; y en Git Bash, conMSYS_NO_PATHCONV=1(ver la tabla).
Windows con WSL 2
- 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. - Docker Desktop en Windows, con Settings → Resources → WSL integration activado para tu distribución.
- Si
docker psdicepermission denied … docker.sock: tu usuario está en el grupodocker, pero la terminal se abrió antes. Cierra la terminal (owsl --shutdowndesde PowerShell) y abre otra.
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
- Go: el tarball de go.dev/dl (
sudo tar -C /usr/local -xzf go1.26…linux-amd64.tar.gzy añade/usr/local/go/binalPATH). Los paquetes de las distribuciones suelen ir por detrás. - Docker: Docker Engine con el plugin de Compose (
docker-compose-plugin), siguiendo la guía oficial de tu distribución. - Permisos:
sudo usermod -aG docker $USERy abre una sesión nueva. Sin eso veráspermission denied … /var/run/docker.sock.
host.docker.internalno existe por defecto con Docker Engine. Losdocker-compose.ymldel curso lo definen conextra_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 777de 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 / zsh | PowerShell |
|---|---|---|
| Variable de entorno para un comando | OIDC_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 comando | TOKEN=$(go run ./cmd/token) | $TOKEN = go run ./cmd/token ✔ probado |
| Usar la variable | -H "Authorization: Bearer $TOKEN" | igual ✔ |
| curl | curl | curl.exe(en PowerShell 5.1, curl es otro comando: Invoke-WebRequest) |
| Partir una línea larga | \ al final | ` (acento grave) al final |
| Crear una carpeta | mkdir -p export | mkdir 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:
| Forma | PowerShell 5.1 | PowerShell 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:
| Entorno | Backchannel 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 NAT | http://<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).