vpn 2, ahora con GUI
De vez en cuando entro a las listas ‘Awesome’, sobre self-hosting, privacy o como es el caso, en la de awesome-sysadmin.
Aqui empiezo a investigar a ver si hay alguna forma mejor para montar la VPN que tengo para mis cositas, y ahi encuentro a Tailscale y Headscale. El resumen es que ambos se pueden self-hostear pero Tailscale sigue siendo una solucion demasiado completa (aunque si te fias, tienen un plan personal por 0€). Asi que tenemos la opcion DIY: Headscale
No tengo nada en contra de usar Wireguard sin aditivos, pero bueno, por probar?.
El proceso para montarlo:
En mi caso voy a usar un servidor VPS con un dominio determinado que a partir de ahora sera el imaginario “dns.com”, y sus respectivos subdominios “vpn.dns.com” y “web.dns.com”
Dentro del servidor, dentro de una carpeta para agrupar todo, como ’/home/user/Headscale/’, y dentro de la misma, todas estas:
mkdir config headplane-config headplane-data lib run
En esta misma carpeta, el docker-compose.yaml magico que se encargara de casi todo:
services:
headscale:
image: docker.io/headscale/headscale:0.26.1
restart: unless-stopped
container_name: headscale
ports:
- 8080
- 9090
volumes:
- ./config:/etc/headscale
- ./lib:/var/lib/headscale
- ./run:/var/run/headscale
command: serve
networks:
- "traefik_net"
labels:
- traefik.enable=true
- traefik.http.middlewares.headscale-cors.headers.accessControlAllowOriginList=https://web.dns.com
- traefik.http.middlewares.headscale-cors.headers.accessControlAllowMethods=GET,POST,PUT
- traefik.http.middlewares.headscale-cors.headers.accessControlAllowHeaders=*
- traefik.http.middlewares.headscale-cors.headers.accessControlMaxAge=100
- traefik.http.middlewares.headscale-cors.headers.addVaryHeader=true
- traefik.http.routers.headscale-http.rule=Host("vpn.dns.com")
- traefik.http.routers.headscale-http.entrypoints=web
- traefik.http.routers.headscale-http.middlewares=redirect-to-https
- traefik.http.routers.headscale-secure.rule=Host("vpn.dns.com")
- traefik.http.routers.headscale-secure.entrypoints=websecure
- traefik.http.routers.headscale-secure.tls=true
- traefik.http.routers.headscale-secure.tls.certresolver=myresolver
- traefik.http.routers.headscale-secure.middlewares=headscale-cors@docker
- traefik.http.services.headscale-service.loadbalancer.server.port=8080
headplane:
image: ghcr.io/tale/headplane:0.6.0
container_name: headplane
restart: unless-stopped
ports:
- 3000
volumes:
- ./headplane-config/config.yaml:/etc/headplane/config.yaml
- ./config/config.yaml:/etc/headscale/config.yaml
- ./headplane-data:/var/lib/headplane
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- "traefik_net"
labels:
- traefik.enable=true
- traefik.http.routers.headplane-http.rule=Host("web.dns.com")
- traefik.http.routers.headplane-http.entrypoints=web
- traefik.http.routers.headplane-http.middlewares=redirect-to-https
- traefik.http.routers.headplane-secure.rule=Host("web.dns.com")
- traefik.http.routers.headplane-secure.entrypoints=websecure
- traefik.http.routers.headplane-secure.tls=true
- traefik.http.routers.headplane-secure.tls.certresolver=myresolver
- traefik.http.services.headplane-service.loadbalancer.server.port=3000
networks:
traefik_net:
external: true
Los archivos de configuracion de cada cosa, parten de los ejemplo que hay en:
Como se puede ver en las 10000 labels del docker-compose, voy a usar Traefik para gestiona todo como proxy inverso, lo estoy intentando cambiar por nginx ya que creo que se adapta mejor a mi forma de hacer las cosas.
Este traefik ira en una carpeta a parte (por claridad), dentro de, por ejemplo: ’/home/user/Traefik/’, y dentro de este docker-compose.yaml:
services:
traefik:
image: traefik:v3.5
container_name: traefik
command:
- --api.dashboard=false
- --providers.docker=true
- --log.level=DEBUG
- --providers.docker.exposedbydefault=false
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --certificatesresolvers.myresolver.acme.email=correo@yahooooo.com # <- Esto se cambia
- --certificatesresolvers.myresolver.acme.storage=/acme.json
- --certificatesresolvers.myresolver.acme.tlschallenge=true
ports:
- 80:80
- 443:443
networks:
- "traefik_net"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./acme.json:/acme.json
labels:
- traefik.enable=true
- traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https
networks:
traefik_net:
external: true
Headscale como tal esta pensado para usarse via CLI, pero la verdad es que, pudiendo poner una interfaz grafica, mejora la cosa. A mi me ha gustado [Headplane]https://github.com/tale/headplane)
Asi todo, ejemplo de como usaria via cli:
Para acceder a la utilidad de headscale es a traves de docker asi que el comando completo queda asi
docker exec -it headscale headscale
Creo un alias para evitar el flato de escribir:
alias headscake='docker exec -it headscale headscale'
Y a funcionar:
Algunos ejemplos de comandos
# Crear un apikey, este es el unico que es necesario ejecutar, para despues usar la web
headscake apikeys create
# Crear un usuario chulo
headscake user create usuario_chulo
# Comprobar que existe
headscake users list # -> apuntar el id del usuario para el siguiente comando
# O sabiendo el nombre del usuario se puede hacer como:
# $(headscake users list | grep "usuario_chulo" | grep -o '^[0-9]\+')
# Crear una key para que el usuario pueda aceder a la VPN:
headscake preauthkeys create --user 123 --reusable --expiration 24h
# Destruir el usuario :(
headscake user destroy --name usuario_chulo
Ahora si, con todo esto creado, se puede pasar a levantar, primero el docker compose de traefik, y despues el docker compose de headscale. Si todo esta ok, deberiamos de poder acceder a la web UI de Headplane en ‘https://web.dns.com/admin'. Aqui hay que meter la api key de antes.