Instalación y configuración de un servidor VSCode y expuesto con Traefik en docker-compose en una Raspberry Pi
En esta entrada se instalará y se configurará Code Server en una Raspberry Pi. Se utilizará la versión dockerizada linuxserver/code-server, se instalará mediante docker-compose y el balanceo de carga se realizará con traefik.
¿Qué es Code Server?
Code-server es VS Code corriendo en un servidor remoto, accesible a través del navegador.
Requisitos
Instalar:
-
Docker
-
Docker-compose
-
Actualizar el sistema
Redomendaciones
-
Obtener un dominio (No aseguramos que funcione sin un dominio)
-
Configurar una Raspberry Pi para hacerla accesible desde internet
-
Utilizar un gestor de contraseñas como KeePassXC y la consola zsh
Actualizar el sistema
Lo primero siempre es actualizar el sistema con:
sudo apt update -y && sudp apt upgrade -y
Configurar cortafuegos ufw
Para instalar el cortafuegos ufw ejecutar:
sudo apt-get install ufw
Permitimos las conexiones por el puerto 80 (HTTP), 443(HTTPS) y 2251(SSH configurado).
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 4443/tcp
sudo ufw allow 2251/tcp
Para activarlo:
sudo ufw enable
Para ver las reglas por defecto:
sudo ufw show raw
También se puede ver con un formato más legible:
sudo ufw status verbose
Apagar la Raspberry Pi de forma correcta
Para apagar la Raspberry Pi evitando que se corrompa la tarjeta SD se ejecuta el siguiente comando:
sudo shutdown -h now
Esperar a que la luz verde deje de parpadear para desenchufar el cable de alimentación.
Obtener dominio (Opcional)
Se requiere un dominio en caso de querer acceder desde el exterior de la red local, en otras palabras, desde Internet. Para ello existen varias páginas donde obtener dominios gratuitos o por menos de 1€ al año. Lo más importante es que el resgistrador de nombres de dominio tenga protección de Whois (WhoisGuard) para prevenir ataques de spam o de suplantación de indentidad a través de los datos personales que tienen que ser públicos al registrar un dominio en el ICANN.
En caso de usar un dominio de freenom, es necesario cambiar el DNS a un de Cloudflare siguiendo los pasos de este tutorial.
Desplegar VSCode Server con Docker
Para levantar el contenedor docker de code-server, simplemente se necesitan los siguientes pasos:
- Añadir la variable de entorno con el nombre del dominio:
export $DOMINIO=dominioejemplo.org
- Levantar el contenedor desde el repositorio de Docker Hub:
docker run -d \
--name=code-server \
-e PUID=1000 \
-e PGID=1000 \
-e TZ=Europe/London \
-e PASSWORD=password `#optional` \
-e HASHED_PASSWORD= `#optional` \
-e SUDO_PASSWORD=password `#optional` \
-e SUDO_PASSWORD_HASH= `#optional` \
-e PROXY_DOMAIN=code-server.my.domain `#optional` \
-e DEFAULT_WORKSPACE=/config/workspace `#optional` \
-p 8443:8443 \
-v /path/to/appdata/config:/config \
--restart unless-stopped \
lscr.io/linuxserver/code-server:latest
Escribir en el navegador la dirección http://<IP-Raspberry-Pi>:8443 y escribir la contraseña elegida.
Configuración en producción de code-server en una Raspberry Pi
Nota importante: no funciona sin un dominio.
Creamos una carpeta raiz que contendrá una carpeta con el nombre de cada autoalojemos, por ejemplo la llamaremos servicios-autoalojados:
mkdir servicios-autoalojados
Variables de entorno de Traefik
Una vez creado nos dirigidos al directorio y creamos otra carpeta llamada traefik. Además, añadimos un nuevo archivo .env en la carpeta traefik con el siguiente contenido. Es la variable de entorno necesaria para traefik. También se pueden incluir en cada carpeta raiz y tenerlas centralizadas en dicha carpeta, el inconveniene es que todos los contenedores tendrían acceso a todas las variables de entorno y eso podría dar lugar a problemas de seguridad. Por esa razón, recomendamos tener un archivo de variables de entorno separado por cada servicio que despleguemos.Para que funcione correctamente, es importante borrar el comentario que se ha añadido en el siguiente ejemplo.
DOMAIN=dominioejemplo.org # Cambiar por un dominio propio
Docker-compose de producción de Traefik
Después, creamos un archivo docker-compose.yml con la siguiente configuración:
version: "3.3"
services:
traefik:
image: "traefik:v2.6"
container_name: "traefik"
command:
- "--log.level=DEBUG"
# - "--api.insecure=false"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.web.address=:80"
- "--entrypoints.web.http.redirections.entryPoint.to=websecure"
- "--entrypoints.web.http.redirections.entryPoint.scheme=https"
- "--entrypoints.web.http.redirections.entrypoint.permanent=true"
- "--certificatesresolvers.myresolver.acme.tlschallenge=true"
- "--certificatesresolvers.myresolver.acme.caserver=https://acme-v02.api.letsencrypt.org/directory"
- "--certificatesresolvers.myresolver.acme.email=admin@${DOMAIN}" # Email de ejemplo, cambiarlo para recibir correos de la renovación de los certificados
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
ports:
- "443:443"
- "8080:8080"
volumes:
- "./letsencrypt:/letsencrypt"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
env_file:
- .env
networks:
- traefik-external-network
- vscode-network
restart: unless-stopped
networks:
traefik-external-network:
driver: bridge
external: true
vscode-network:
driver: bridge
En el hemos creado una red de docker llamada traefik-external-network donde se expodrán los servicios al exterior y es obligatorio que sea de tipo external, mientras que code-server-network servirá para conectar la base de datos postgres con netxcloud.
Desplegamos el docker-compose con:
docker-compose up --build --force-recreate
Variables de entorno de Code Server
A continuación, creamos una carpeta llamada code-server. Una vez creada nos dirigidos al directorio y añadimos un nuevo archivo .env en la carpeta code-server con el siguiente contenido. Son las variables de entorno necesarias para el servidor de código.
Primero, creamos un archivo .env donde guardaremos las variables de entorno. Es importante borrar los comentarios que se han añadido en el siguiente ejemplo para que funcione correctamente.
DOMAIN=dominioejemplo.org
SUBDOMAIN_CODE_SERVER=code-server
PUID=1000
PGID=1000
TZ=Europe/London
PASSWORD= #optional
HASHED_PASSWORD= #optional
SUDO_PASSWORD= #optional
SUDO_PASSWORD_HASH= #optional
PROXY_DOMAIN=code-server.dominioejemplo.org #optional
DEFAULT_WORKSPACE=/config/workspace #optional
En segundo lugar, creamos un archivo docker-compose.yml con el siguiente contenido:
version: "3.3"
services:
# Visual Studio code server
code-server:
image: lscr.io/linuxserver/code-server:latest
container_name: code-server
env_file:
- .env
volumes:
- ./code-server-config:/home/coder/.config
- ./code-server-data:/home/coder/projects
# command: code-server --auth password --disable-telemetry /home/coder/project
ports:
- 8443:8443
networks:
- traefik-external-network
restart: unless-stopped
labels:
- "traefik.enable=true"
# Code-server URL
- "traefik.http.routers.code-server.rule=Host(`${SUBDOMAIN_CODE_SERVER}.${DOMAIN}`)"
- "traefik.http.routers.code-server.service=code-server"
- "traefik.http.routers.code-server.entrypoints=websecure"
- "traefik.http.services.code-server.loadbalancer.server.port=8443"
- "traefik.http.routers.code-server.tls=true"
- "traefik.http.routers.code-server.tls.certresolver=myresolver"
- "traefik.http.services.code-server.loadbalancer.passhostheader=true"
volumes:
code-server-config:
code-server-data:
networks:
traefik-external-network:
driver: bridge
external: true
Desplegamos el docker-compose con:
docker-compose up --build --force-recreate
El certificado de Let’s Encrypt puede tardar unos minutos en obtenerse, por lo tanto, espere y si obtiene algún warning en los logs de Traefik, no es preocupante. Una forma para probar si se ha generado correctamente es leer el archivo acme.json de la carpeta letsencrypt creada en el directorio code-server. También se pueden recrear los servicios hasta que funcione todo correctamente.
Por último, ya podemos buscar en el navegador nuestro dominio https://code-server.dominiodeejemplo.org