Activar certificados locales autofirmados
Introducción
Dende que comecei co proxecto de servizos autoaloxados, todo funciona con HTTP. A fin de contas estou a correr todo na miña rede local.
Pero comecei a pensar que en certas ocasións estaría ben ter a opción de acceder dende fora aos meus arquivos. A ver, o noventa e cinco por cento do tempo,
é suficiente. Sen embargo, en ocasións teño que viaxar por traballo. Nestes casos cando estou no hotel, ou na oficina, podo precisar acceder a algún contido
que teño na casa. Entón comecei a pensar en facer accesibles os servizos dende internet e claro, que vaian sen cifrar xa non me parece ben.
Sei que hai opcións, como montar unha VPN con Wireguard, utilizar Tailscale, etc. Isto faría que dende fora fosen cifrados, a todos aqueles que non estean
conectados á VPN. Pero ter unha capa extra de seguridade como HTTPS non me parece mal. Ademais, tamén está a cuestión lúdica de probar un proxecto co que
ter certificados autoasinados e autorenovables. Algo como Letsencrypt, pero local.
No principio pensei en Letsencrypt, pero require ter un dominio asociado e ao ser un proxecto local, non teño. De momento tamén descarto contratar un VPS.
Así que a través dun grupo de Telegram, publicaron un proxecto que facía o que precisaba. O usuario estribiyo creou un proxecto que aunaba Traefik con Step-ca. O proxecto ten outras cousas que a min non me interesan, tamén engade algunhas dependencias ou tecnoloxías, que non vexo necesarias no meu sistema. Dito isto, baseime neste proxecto para chegar a onde quería.
Step-ca
Smallstep son os creadores de Step-ca un proxecto que nos permite xerar os nosos propios certificados, de xeito local. Para isto podemos crear a nosa propia autoridade de certificación. Esta será a que asine os nosos certificados, polo que ao incluíla entre as entidades de confianza no sistema, ou no navegador, evitaremos os avisos de risco cando accedamos ás páxinas. Avisos de que estamos a recibir un certificado autoasinado.
Descartando Rust
Como podemos ver no proxecto de estribiyo, el utiliza un justfile o cal engade a dependencia de
Rust. Quero poder desplegar os meus servizos de xeito sinxelo, cas mínimas dependencias posibles. Así que no meu caso creei un Makefile que fai o mesmo.
Así cando despregue na Raspberry non teño que instalar Rust, nin Cargo. E no caso de precisar formatear o despregue sería igual.
Si que hai un par de dependencias que mantiven como jq, pero son ferramentas que de cando en cando utilizo. Así que estas non as vexo mal.
Activando certificados locais
Step-ca: configuración
O primeiro foi activar un novo servizo en docker, o de Step-ca. Como é unha dependencia de Traefik, púxeno no mesmo docker-compose. Non é unha dependencia directa, ata hoxe non o tiña. Pero si que preciso que este servizo arranque antes que Traefik, para que este poida pedir os certificados. A configuración deste servizo é bastante pequena. As dores de cabeza están mais do lado de Traefik. Esta foi a configuración a engadir no docker-compose.
step-ca: # Service to generate certificates
image: smallstep/step-ca:latest
container_name: step-ca
restart: on-failure
user: root # Run as root to avoid permission issues
extra_hosts:
- "${STEP_CA_URL}:127.0.0.1"
ports:
- "9000:9000"
volumes:
- ${STEP_DIR}:/home/step
environment:
- STEPPATH=/home/step
networks:
proxy:
aliases:
- ${STEP_CA_URL}
Con extra_hosts o que estou a facer é indicarlle onde debe resolver o dominio no que estará o servizo. Por exemplo raspberry.local, apuntará á IP de loopback. As outras variables son para montar a carpeta do host, enlazándoa co home do contenedor. De xeito que aí se xerarán os ficheiros de configuración e os certificados.
Traefik: configuración
Isto trouxo cambios na configuración de Traefik, xa que tiven que indicarlle que a partir de agora vai usar un servizo para xerar certificados. Pero imos ir de máis simple a máis complexo. Primeiro, o arquivo traefik.yml ca configuracion pasou a ser traefik.template.yml. Isto foi así porque requería ter algunhas variables de configuración para que collese o dominio e o email. Como non se cambian directamente faise mediante un script que lanzará envsubst xerando o arquivo final.
Este é o script que fai esa operación, ademáis de crear o ficheiro que almacenará os certificados e mover o da entidade certificadora a onde toca.
#!/bin/sh
set -e
# Replace environment variables in traefik.yml
envsubst < /etc/traefik/traefik.template.yml > /etc/traefik/traefik.yml
# Create acme.json if it doesn't exist
if [ ! -f /certs/acme.json ]; then
touch /certs/acme.json
chmod 600 /certs/acme.json
fi
# Copy CA certificate
if [ -f /certs/root_ca.crt ]; then
cp /certs/root_ca.crt /usr/local/share/ca-certificates/
update-ca-certificates
fi
# Start Traefik
exec "$@"
Esta é a configuración de traefik.
api:
dashboard: true
insecure: true
entryPoints:
http:
address: ":80"
http:
redirections:
entryPoint:
to: https
scheme: https
permanent: true
https:
address: ":443"
serversTransport:
insecureSkipVerify: false
rootCAs:
- /certs/root_ca.crt
providers:
docker:
network: proxy
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
certificatesResolvers:
step:
acme:
email: ${STEP_CA_ADMIN_EMAIL}
storage: /certs/acme.json
caServer: https://${STEP_CA_DNS}${STEP_CA_ADDRESS}/acme/acme-provisioner/directory
httpChallenge:
entryPoint: http
Aquí quedan cousas por cambiar no futuro, por exemplo activar seguridade no dashboard. Agora mesmo calquera pode acceder, polo que a futuro activarei o login.
Outros detalles a destacar serían a redirección de HTTP a HTTPS de xeito permanente, co cal desactivamos a posibilidade de acceder de xeito non cifrado. Tamén vemos como establecemos a entidade certificadora que se xerará en Step-ca. E por último vemos a configuración do xerador de certificados. O valor de STEP_CA_DNS debe coíncidir co dominio que indiquemos no noso root_ca.crt ou darános erro por ser distintos e non se considerarán válidos os certificados.
Por último, nas labels de Traefik, no docker-compose.yml engadiremos as necesarias para utilizar Step-ca. Así é como quedan:
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.rule=Host(`${DOMAIN:-localhost}`)"
- "traefik.http.routers.traefik.entrypoints=https"
- "traefik.http.routers.traefik.service=api@internal"
- "traefik.http.routers.traefik.tls=true"
- "traefik.http.routers.traefik.tls.certresolver=step"
- "traefik.http.routers.traefik.tls.domains[0].main=${DOMAIN}"
- "traefik.http.routers.traefik.tls.domains[0].sans=www.${DOMAIN}"
Con respecto ao que tiña antes, mudei o entrypoint a https que coíncide co nome no traefik.template.yml anterior. Por iso vai en minúsculas. Activamos tls, indicando cal é o encargado de resolver os certificados. E por ultimo indicamos cal é o dominio principal.
Este sería o docker-compose.yaml compreto.
services:
step-ca: # Service to generate certificates
image: smallstep/step-ca:latest
container_name: step-ca
restart: on-failure
user: root # Run as root to avoid permission issues
extra_hosts:
- "${STEP_CA_URL}:127.0.0.1"
ports:
- "9000:9000"
volumes:
- ${STEP_DIR}:/home/step
environment:
- STEPPATH=/home/step
networks:
proxy:
aliases:
- ${STEP_CA_URL}
traefik:
build:
context: .
dockerfile: Dockerfile.traefik
container_name: traefik
init: true
restart: on-failure
depends_on:
- step-ca
networks:
- proxy
ports:
- "80:80"
- "8080:8080"
- "443:443"
extra_hosts:
- "${DOMAIN}:${HOST_IP}"
environment:
- STEP_DIR=${STEP_DIR}
- TZ=Europe/Madrid
- STEP_CA_ADMIN_EMAIL=${STEP_CA_ADMIN_EMAIL}
- STEP_CA_DNS=${STEP_CA_DNS}
- STEP_CA_ADDRESS=${STEP_CA_ADDRESS}
entrypoint: /custom-entrypoint.sh
command: ["traefik", "--configFile=/etc/traefik/traefik.yml"]
volumes:
- $XDG_RUNTIME_DIR/docker.sock:/var/run/docker.sock:ro
- ${STEP_DIR}:/certs
- ./traefik.template.yml:/etc/traefik/traefik.template.yml
- ./scripts/entrypoint.sh:/custom-entrypoint.sh
- ${STEP_DIR}/certs/root_ca.crt:/usr/local/share/ca-certificates/root_ca.crt:ro
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.rule=Host(`${DOMAIN:-localhost}`)"
- "traefik.http.routers.traefik.entrypoints=https"
- "traefik.http.routers.traefik.service=api@internal"
- "traefik.http.routers.traefik.tls=true"
- "traefik.http.routers.traefik.tls.certresolver=step"
- "traefik.http.routers.traefik.tls.domains[0].main=${DOMAIN}"
- "traefik.http.routers.traefik.tls.domains[0].sans=www.${DOMAIN}"
networks:
proxy:
name: proxy
driver: bridge
Nos volumes podemos ver como apuntamos ao directorio de certificados, ao template que usaremos para a configuración de Traefik, ao script de entrypoint e ao certificado da entidade.
Configurando servizos
Para mudar servizos de xeito que utilicen o HTTPS, simplemente llo indicaremos nas etiquetas.
labels:
- "traefik.enable=true"
- "traefik.http.routers.calibre.entrypoints=https"
- "traefik.http.routers.calibre.rule=Host(`${URL:-localhost}`)"
- "traefik.http.services.calibre.loadbalancer.server.port=${CALIBRE_HTTP_PORT:-8083}"
- "traefik.http.routers.calibre.tls.certresolver=step"
Ao igual que en traefik mudamos o entrypoint para utilizar https e engadimos o certresolver. O resto do ficheiro permanece igual. Noutros servizos a configuración é a mesma.
Jellyfin: configuración
No caso de Jellyfin, tiven que facer algún axuste a maiores. Por exemplo, cando a transimisión non vai securizada o porto que utiliza é o 8096, que o propio docker de Jellyfin xa ten exposto. Pero houben de engadir o 8920. A maiores engadin algunha variable de entorno a maiores, as seguintes:
services:
jellyfin:
# resto da configuración
environment:
- JELLYFIN_PublishedServerUrl=$URL
- JELLYFIN_EnableHttps=true
- JELLYFIN_HttpsPortNumber=${PORT}
- JELLYFIN_EnableRemoteAccess=true
root_ca.crt
Con isto temos certificados autoasinados. Pero para que os poidamos utilizar quedan algúns pasos. Por exemplo, para que as webs non nos pregunten continuamente, deberemos engadir o certificado ao navegador. Mentres que outras aplicacións de escritorio, requerirán que se engada ao sistema. Isto último tamén é así en Android. Para poder sincronizar aplicacións cos servizos o sistema ten que recoñecer a nosa entidade coma unha entidade válida.
Se temos un sistema con entorno gráfico, xeralmente o abrir o root_ca.crt xa nos preguntará se o queremos instalar. No caso de facelo por terminal deberemos copialo no directorio adecuado e actualizar os certificados. A continuación reiniciar calquer aplicación que tivésemos aberta e que teña que utilizar o certificado.
Por exemplo, no caso de Raspberry Pi OS, copiei o certificado a /usr/local/share/ca-certificates/ e despois executei sudo update-ca-certificates. Isto foi preciso, para que Kodi aceptase os certificados autoasinados como válidos. En caso contrario mesmo se no addon de Jellycon inicaba que non se comprobasen, daba erro.
Este era o erro en cuestión
error <general>: CCurlFile::Stat - <https://jellyfin.trast3b.local/Items/09bd6adadd4c56dce17a08ed16cae376/Images/Primary/0?Format=original&Tag=45d187c36e4dd2cd2dbf7484291322b1> Failed: SSL peer certificate or SSH remote key was not OK(60)
Conclusión
Agora teño os servizos que se transmiten pola rede local securizados, o que me permitirá facer probas e decidir como quero abrir os servizos no futuro. Deste xeito se accedo a través do móbil dende fora da casa, ou dende outra rede o datos non serán tan facilmente recoñecibles. Isto non quere dicir que vaia conectar dende unha Wifi descoñecida sen VPN, pero mesmo se o fago dende a oficina ou o que fose. A miña información estará máis protexida.
Fontes
- Jellyfin: documentación
- Github Estribiyo: traefik-stepca-base
Artigos Relacionados:
- Xestión de versións de Python con Pyenv
- Executando modelos de IA en local con Jan.ai
- Instalar Displaylink openSuse Tumbleweed
- Crear un PNG animado con FFMPEG
- Presenterm
- Cómo instalar Traefik con docker
- Configurar sshfs para acceder al sistema de ficheros de forma segura
- Sincronizar Merkuro calendar con Nextcloud
- Recuperar ficheiros dun backup con Borgbackup
- Actualizar Invidious despois de que me dese erro bastante tempo
- Instalación de News en Nextcloud
- Instalación de GPodder Sync en Nextcloud
- Actualizar Nextcloud en Docker
- Configuración de Calibre web auto aloxado con Traefik
- Configuración de Jellyfin auto aloxado con Traefik
- Copias de seguridade con Borgbackup
- Controlar la temperatura del equipo con bash y telegram
- Instalación de Nextcloud
- Instalación de Pi-hole
- Configuración de Invidious auto aloxado con Traefik
- Configuración de SearXNG auto aloxado con Traefik
- Cómo instalar Traefik con docker
- Instalando docker en modo rootless en Debian
- Instalando Jekyll con Docker
- Recuperar ficheiros dun backup con Borgbackup
- Instalar Fedora con BTRFS, cifrado e Snapshots activos
- Ciberseguridad de tú a tú
- Copias de seguridade con Borgbackup
- Crear un usuario con permisos restrinxidos para backups
- error: gpg failed to sign the data
- Instalación de Pi-hole