Skip to content

Instantly share code, notes, and snippets.

@Tardo
Last active May 22, 2023 11:23
Show Gist options
  • Save Tardo/f5a88534cbe93e9de0df808efd3a6855 to your computer and use it in GitHub Desktop.
Save Tardo/f5a88534cbe93e9de0df808efd3a6855 to your computer and use it in GitHub Desktop.
Raspberry Pi 4B #RPI

En pro de fomentar el opensource, siempre que sea posible todos los extras referentes a apps de Android serán de los repositorios de F-Droid. En muchos casos se puede encontrar la misma app en los repositorios oficiales de google.

Índice

RaspiOS (64 bits)

Ver incidencias reportadas: https://github.com/raspberrypi/Raspberry-Pi-OS-64bit/issues

Grabar la imagén a una SD Card

  1. Descargar rpi-imager
  2. Selecciona el sistema operativo Raspberry Pi OS Lite (64-bit)
  3. Graba la imagen en la SD Card

Completar instalación

  1. Poner la SD Card en la rpi e iniciarla.
  2. Cambia la contraseña por defecto (raspberry) del usuario 'pi': passwd

Habilitando SSH

En este paso se habilitará el servicio SSH en la rpi y se configurará para conectar únicamente mediante llave pública. ** Se puede omitir esto si no se va a usar. La conexión SSH sirve para gestionar la rpi sin necesidad de conectar una pantalla, teclado y ratón directamente al cacharro.

En la RPI (1/2)

  1. Lo primero es activar el servicio SSH, para ello abrir el programa de configuración y en servicios marca la casilla para SSH
    1. Ejecutar: sudo rpi-config
      1. Ir a la opcion 5 (la opción que pone Interfacing Options)
      2. Activar P2 (la opción que pone SSH)
    2. Activar el servicio: sudo systemctl enable ssh
    3. Arrancar el servicio: sudo systemctl start ssh

En nuestro equipo

  1. Se deben crear un par de claves ssh si es que no se dispone de ellas ya: ssh-keygen
    1. No cambiar la ruta de guardado, también es aconsejable poner un 'passphrase' para asegurar el uso de las claves.
  2. Copiar la clave en la rpi: ssh-copy-id pi@rpi_ip
    1. Si todo va bien nos pedirá tanto la 'passphrase' como la contraseña del usuario 'pi'

En la RPI (2/2)

  1. Editar el archivo /etc/ssh/sshd_config
    1. Descomentar PasswordAuthentication dejando la opción en no.
    2. Descomentar PermitRootLogin dejando la opción en no.
  2. Reiniciar SSH: sudo systemctl restart ssh

  • INFO 1: Llegados a este punto se pueden desconectar los periféricos de la rpi (teclado, ratón, pantalla) y trabajar desde SSH por red.
  • INFO 2: No olvidar obtener la ip local del cacharro! para ello ejecutar ip address show y fijate en el inet de eth0 si está por cable, o wlan0 si está por wifi. Es muy recomendable tenerlo conectado por cable.
  • INFO 3: Un consejo, configura el router para que asigne siempre la misma ip a la raspberry.

Desactivar WiFi & BT

Editar el archivo /boot/config y añadir:

dtoverlay=disable-wifi
dtoverlay=disable-bt

Formateando discos externos

  1. Identificar el nombre del disco: sudo lsblk
  2. Seleccionar el tipo de particiones del disco:
    1. GPT (El más moderno): sudo parted /dev/NOMBRE_DISCO mklabel gpt
    2. MBR: sudo parted /dev/NOMBRE_DISCO mklabel msdos
  3. Crear partición:
    1. EXT4: sudo parted -a opt /dev/NOMBRE_DISCO mkpart primary ext4 0% 100%
  4. Comprobar que se ha creado correctamente la partición e identificar su nombre: sudo lsblk -f
  5. Crear el sistema de archivos en la nueva partición:
    1. EXT4: sudo mkfs -t ext4 /dev/NOMBRE_PARTICION
  6. Opcional: Poner una etiqueta a la partición: sudo e2label /dev/NOMBRE_PARTICION NUEVA_ETIQUETA

Montando discos externos

  1. Crear la carpeta donde se montara el disco: sudo mkdir /media/mydisk
    1. Seguramente se quiera cambiar el dueño al usuario 'pi' sobre esa carpeta: sudo chown pi:pi /media/mydisk
  2. Obtener el PARTUUID: sudo blkid
  3. Añadir al archivo 'fstab': sudo nano /etc/fstab
    1. Ejemplo linea: PARTUUID=0203-12D /media/mydisk ext4 defaults 0 0
    2. Aplicar cambios: sudo mount -a

Auto-Reiniciar cada 15 días a las 09:00

  1. Abrir el editor para CRON: sudo crontab -e
  2. Añadir la tarea programada: 0 9 */15 * * reboot

** Puedes usar https://crontab.guru para definir otros intervalos

Cambiando la shell a Zsh

Con está shell tendremos funciones como autocompletar, resaltado, colores, ...

  1. Básicamente seguir los pasos: https://github.com/ohmyzsh/ohmyzsh/wiki/Installing-ZSH
    1. Instalar zsh: sudo apt install zsh
    2. Ponerla como shell por defecto: chsh -s $(which zsh)
  2. Cerrar la sesión y volver a logear
    1. La primera vez nos pedirá configurar ciertos parámetros. Podremos omitirlo si usamos OhMyZSH
  3. Verificar que todo está correcto ejecutando echo $SHELL y ver que devuelve /usr/bin/zsh

Vitaminando nuestra nueva shell con 'Oh My Zsh'

Este es un framework para zsh que nos permite instalar temas y añadir plugins facilmente.

Instalando

  1. Ejecutar: sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"

Configuración mínima + Instalar plugins

La configuración se hace desde el archivo '.zshrc' que está en el directorio home del usuario 'pi' (~/.zshrc).

  1. Para tener un tema es la opción ZSH_THEME, se pueden ver los disponibles aquí: https://github.com/ohmyzsh/ohmyzsh/wiki/Themes
    1. En mi caso para terminales remotas uso amuse (para local blinks)
  2. Para habilitar complementos es la opción plugins. Recomiendo los siguientes:
    • git -> Obtener información de repositorios (viene habilitado por defecto)
    • zsh-dircolors-solarized -> Esquema de colores usado por varios temas: git clone --recursive git://github.com/joel-porquet/zsh-dircolors-solarized $ZSH_CUSTOM/plugins/zsh-dircolors-solarized
    • zsh-syntax-highlighting -> Resaltar la sintaxis al estilo de la shell 'fish': git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting
    • zsh-autosuggestions -> Auto-sugestiones al estilo de la shell 'fish': git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions
    • zsh-history-substring-search -> Permite buscar comandos en el historico por subcadenas: git clone https://github.com/zsh-users/zsh-history-substring-search ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-history-substring-search
    1. Con todo la linea de configuración nos quedará así: plugins=(git zsh-dircolors-solarized zsh-syntax-highlighting zsh-autosuggestions zsh-history-substring-search)
  3. Cerrar la sesión y volver a logear

Byobu

Byobu es un gestor de ventanas en modo texto y un multiplexador de terminal. Esto nos permitira trabajar en varias sesiones al mismo tiempo.

Instalando

  1. Ejecutar: apt install byobu
  2. Ejecutar: byobu-enable
  3. Cerrar la sesión: exit
  4. Volver a conectar

Uso básico

  1. Para crear una nueva ventana pulsa F2
  2. Para moverte entre ventanas pulsa ALT + <tecla de dirección> ** Más atajos: https://manpages.ubuntu.com/manpages/jammy/en/man1/byobu.1.html#keybindings

Instalando docker

Docker es un gestor de contenedores.

  1. Usamos el método "Install using the convenience script": https://docs.docker.com/engine/install/debian/#install-using-the-convenience-script
    1. Nos traemos el script: curl -fsSL https://get.docker.com -o get-docker.sh
    2. Lo ejecutamos: sudo sh get-docker.sh
    3. Añadimos el usurio 'pi' al grupo de docker: sudo usermod -aG docker pi

Instalando docker-compose

  1. Método pip: pip3 install docker-compose
    1. A mi me hizo falta instalar 'libffi-dev': sudo apt install libffi-dev
  2. Añade la carpeta .local/bin a $PATH
    1. Edita el archivo .zshrc (si te has puesto Zsh) o .bashrc y añade: export PATH=/home/pi/.local/bin:$PATH
    2. Para aplicar los cambios deslogearse y volver a logear

Traefik

Traefik hará de proxy inverso. Un proxy inverso nos ayuda a controlar el flujo de las peticiones al cacharro.

Levantar contenedor

  1. Crear los archivos necesarios a bindear (lo hacemos como root, pero no es necesario) ** Esto se hace para asegurarnos de que docker bindea correctamente, ya que si no encuentra en el host el archivo lo bindeará como una carpeta.
    1. mkdir data
    2. touch data/access.log
    3. touch data/acme.json
    4. chmod 600 data/acme.json
  2. Crear la carpeta donde se meterá el archivo docker-compose.yaml. Yo, por ejemplo, lo meto en un disco externo.
  3. El archivo docker-compose.yaml será muy parecido a este:

docker-compose.yaml

version: "3"

services:
  traefik:
    image: traefik:latest
    container_name: traefik
    # Descomentar si se usa Let's Encrypt
    #environment:
    #  - OVH_ENDPOINT=ovh-eu (or ovh-ca)
    #  - OVH_APPLICATION_KEY=<tu_application_key>
    #  - OVH_APPLICATION_SECRET=<tu_application_secret>
    #  - OVH_CONSUMER_KEY=<tu_application_consumer_key>
    ports:
      - "8080:8080"
      - "80:80"
      - "443:443"
      # Pi-Hole
      #- "67:67/udp" (no DHCP)
      #- "853:853" (no DoT)
      - "9010:9010"
      # Deluge
      - "8112:8112"
      - "58846:58846"
      - "58946:58946"
      - "58946:58946/udp"
      # Portainer
      - "8000:8000"
      - "9000:9000"
      # Postgres
      - "5432:5432"
      # Nextcloud
      - "9020:9020"
      # Syncthing
      - "8384:8384"
      - "22000:22000"
      - "22000:22000/udp"
      # Jellyfin
      - "8096:8096"
      - "7359:7359/udp"
      - "1900:1900/udp"
      # Gotify
      - "9050:9050"
    networks:
      - rpipub
    dns:
      - 127.0.0.1
      - 1.1.1.1
    volumes:
      - ./data/traefik.yaml:/etc/traefik/traefik.yaml
      - ./data/access.log:/etc/traefik/access.log
      - ./data/acme.json:/etc/traefik/acme.json
      - ./data/conf/:/etc/traefik/conf/
      - /var/run/docker.sock:/var/run/docker.sock
    restart: unless-stopped
    hostname: "rpi-traefik"

networks:
  rpipub:
    name: "rpi-net-public"
  1. Crear el archivo de configuración en la carpeta donde se metió el docker-compose.yaml: mkdir data && nano data\traefik.yaml
    1. Editar el archivo y añadir:

traefik.yaml

log:
  level: Info

providers:
  docker:
    exposedByDefault: false
  file:
    directory: "/etc/traefik/conf"
    watch: true

accessLog:
  filePath: "/etc/traefik/access.log"
  bufferingSize: 100

# API and dashboard configuration
api:
  insecure: true

entryPoints:
  websecure:
   address: ":443"
  web:
   address: ":80"
   # Descomentar si se usa Let's Encrypt
   #http:
   #  redirections:
   #    entryPoint:
   #      to: websecure
   #      scheme: https
  #dnstls:
  # address: ":853"
  pihole_interface:
   address: ":9010"
  deluge_interface:
   address: ":8112"
  deluge_daemon:
   address: ":58846"
  deluge_torrent:
   address: ":58946"
  udpdeluge_torrent:
   address: ":58946/udp"
  portainer_interface:
   address: ":9000"
  portainer_daemon:
   address: ":8000"
  postgres_daemon:
   address: ":5432"
  nextcloud_interface:
   address: ":9020"
  syncthing_interface:
   address: ":8384"
  syncthing_daemon:
   address: ":22000"
  udpsyncthing_daemon:
   address: ":22000/udp"
  jellyfin_interface:
   address: ":8096"
  udpjellyfin_discovery:
   address: ":7359/udp"
  udpjellyfin_dlna:
   address: ":1900/udp"
  gotify:
   address: ":9050"

# Descomentar si se usa Let's Encrypt
#certificatesResolvers:
#  letsencrypt:
#    acme:
#      email: tu@correo.com 
#      storage: /etc/traefik/acme.json
#      dnsChallenge:  
#        provider: ovh
#        delayBeforeCheck: 10
  1. Crear los archivos de configuración en ./data/conf

    1. Aquí se definen unos middleware para rateLimit que tendrás que ajustar los valores a lo que busques, o incluso no quieras usar el middleware, en ese caso comenta/borra la label en los archivos docker-compose.yaml. Este middleware nos ayudará a prevenir posibles abusos y aliviando la carga de nuestra rpi. En este caso los valores son bajos, pero es que, en mi caso, el acceso web a la rpi se va usar por muy pocos usuarios.

      low_ratelimit.yaml

      http:
        middlewares:
          low-ratelimit:
            ratelimit:
              average: 50
              burst: 45

      medium_ratelimit.yaml

      http:
        middlewares:
          medium-ratelimit:
            ratelimit:
              average: 100
              burst: 95
    2. Aquí se define un middleware para headers que sirve para habilitar HSTS y otras políticas de seguridad como SAMEORIGIN

      secure_headers.yaml

      http:
        middlewares:
          secure-headers:
            headers:
              contentTypeNosniff: true
              browserxssfilter: true
              frameDeny: true
              # Descomentar si se usa Let's Encrypt
              # Esto habilita HSTS, puede resultar peligroso si en algún momento tenemos problemas con los certificados
              # ya que el navegador solo tratará de conectar mediante HTTPS y tardará todos los segundos
              # definidos en 'stsSeconds' en olvidar esta configuración y volver a intentar conectar por HTTP
              # stsSeconds: 31536000
              # stsIncludeSubdomains: true
              # stsPreload: true
              # forceSTSHeader: true
              customResponseHeaders:
                X-Frame-Options: "SAMEORIGIN"
      # Descomentar si se usa Let's Encrypt (Esto deshabilita tls 1.0 y 1.1)
      #tls:
      # options:
      #   default:
      #     minVersion: VersionTLS12
      #     cipherSuites:
      #       - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
      #       - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
      #       - TLS_AES_256_GCM_SHA384
      #       - TLS_CHACHA20_POLY1305_SHA256
      
    3. Aquí se define un middleware para headers que sirve para denegar el indexado

      norobots_headers.yaml

      http:
        middlewares:
          norobots-headers:
            headers:
              customResponseHeaders:
                X-Robots-Tag: "none"
  2. Levantar el contenedor en modo 'detached': docker-compose up -d

    1. Lanzando docker ls se debera ver el contenedor de traefik levantado

Extras

  1. Con está configuración se tiene acceso a un panel en: http://rpi_ip:8080

Portainer (Community Edition)

Frontend para docker.

Levantar contenedor

  1. Crear una carpeta donde se meterá el archivo docker-compose.yaml. Yo, por ejemplo, lo meto en un disco externo.
  2. El archivo docker-compose.yaml será muy parecido a este:

docker-compose.yaml

version: "3"

services:
  portainer:
    image: portainer/portainer-ce
    container_name: portainer
    environment:
      - TZ=Europe/Madrid
    networks:
      - rpipub
    dns:
      - 127.0.0.1
      - 1.1.1.1
    labels:
      - traefik.enable=true
  
      # CORS (Solo es útil en caso de usar DynHost)
      - traefik.http.middlewares.portainer-cors-headers.headers.accesscontrolallowmethods=GET,OPTIONS,PUT
      - traefik.http.middlewares.portainer-cors-headers.headers.accesscontrolalloworiginlist=https://subdomain.domain.tld  # Cambiar a http si es necesario
      - traefik.http.middlewares.portainer-cors-headers.headers.accesscontrolmaxage=100
      - traefik.http.middlewares.portainer-cors-headers.headers.addvaryheader=true

      # Direct Web UI (Comentar si se va a conectar siempre mediante dominio)
      - traefik.http.routers.portainer.rule=PathPrefix(`/`)
      - traefik.http.routers.portainer.entrypoints=portainer_interface
      - traefik.http.routers.portainer.service=portainer-direct-service
      - traefik.http.services.portainer-direct-service.loadbalancer.server.port=9000
  
      # Web UI (Descomentar si no se usa HTTPS)
      #- traefik.http.routers.portainer-http.rule=Host(`subdomain.domain.tld`) && PathPrefix(`/`)
      #- traefik.http.routers.portainer-http.entrypoints=web
      #- traefik.http.routers.portainer-http.middlewares=low-ratelimit@file
      #- traefik.http.routers.portainer-http.service=portainer-http-service
      #- traefik.http.services.portainer-http-service.loadbalancer.server.port=9000
  
      # Secure Web UI (Descomentar si se usa HTTPS)
      #- traefik.http.routers.portainer-https.rule=Host(`subdomain.domain.tld`) && PathPrefix(`/`)
      #- traefik.http.routers.portainer-https.entrypoints=websecure
      #- traefik.http.routers.portainer-https.middlewares=low-ratelimit@file,secure-headers@file,norobots-headers@file,portainer-cors-headers@docker
      #- traefik.http.routers.portainer-https.tls=true
      #- traefik.http.routers.portainer-https.tls.certresolver=letsencrypt
      #- traefik.http.routers.portainer-https.tls.domains[0].main=domain.tld
      #- traefik.http.routers.portainer-https.tls.domains[0].sans=*.domain.tld
      #- traefik.http.routers.portainer-https.service=portainer-https-service
      #- traefik.http.services.portainer-https-service.loadbalancer.server.port=9000
  
      # 8000 TCP
      - traefik.tcp.services.portainer.loadbalancer.server.port=8000
      - traefik.tcp.routers.portainer_daemon.rule=HostSNI(`*`)
      - traefik.tcp.routers.portainer_daemon.entrypoints=portainer_daemon
      - traefik.tcp.routers.portainer_daemon.service=portainer
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./data:/data
    restart: unless-stopped
    hostname: "rpi-portainer"
networks:
  rpipub:
    name: "rpi-net-public"
  • /!\ Cambiar 'domain.tld' y 'subdomain.domain.tld' por el dominio que vayas a usar
  1. Levantar el contenedor en modo 'detached': docker-compose up -d
    1. Lanzando docker ls se debe ver el contenedor de portainer levantado

Configuración mínima

Para acceder al panel será una URL como http://rpi_ip:9000.

  1. La primera vez que arranca pedirá que crear un usuario (por defecto admin).
  2. Una vez dentro lo primero que se tendrá que hacer es crear un 'endpoint' desde el menú "Endpoints".
    1. Seleccionar el tipo "Docker"
    2. Poner el nombre que queramos
    3. Activar el check "Connect via socket"
    4. Pulsar "+ Add Endpoint"
    5. Ahora en a la sección "Containers" se debe ver que está levantado el propio contenedor de portainer.

Pi-Hole

Pihole es un programa con varios propósitos, pero el que nos atañe es el de hacer de Servidor DNS para cachear y filtrar. Nos proporciona una primera barrera contra trackers en cualquier dispositivo del hogar que tire de DHCP. Se debe tener en cuenta que con esta configuración si cae la rpi (cae el servidor DNS), quedaremos sin poder resolver dominios y no se podra navegar con normalidad.

Levantar contenedor

  1. Crear una carpeta donde se meterá el archivo docker-compose.yaml. Yo, por ejemplo, lo meto en un disco externo.
  2. El archivo docker-compose.yaml será muy parecido a este:

docker-compose.yaml

version: "3"

# More info at https://github.com/pi-hole/docker-pi-hole/ and https://docs.pi-hole.net/
services:
  pihole:
    container_name: pihole
    image: pihole/pihole:latest
    networks:
      - rpipub
    dns:
      - 127.0.0.1
      - 1.1.1.1
    ports:
      - "53:53"
      - "53:53/udp"
    environment:
      TZ: 'Europe/Madrid'
      #WEBPASSWORD: 'establece una contraseña segura aquí o sino se generará una aleatoria'
    # Volumes store your data between container upgrades
    volumes:
      - './data/etc-pihole/:/etc/pihole/'
      - './data/etc-dnsmasq.d/:/etc/dnsmasq.d/'
    # Recommended but not required (DHCP needs NET_ADMIN)
    #   https://github.com/pi-hole/docker-pi-hole#note-on-capabilities
    #cap_add:
    #  - NET_ADMIN
    labels:
      - traefik.enable=true
  
      # CORS (Solo es útil en caso de usar DynHost)
      - traefik.http.middlewares.pihole-cors-headers.headers.accesscontrolallowmethods=GET,OPTIONS,PUT
      - traefik.http.middlewares.pihole-cors-headers.headers.accesscontrolalloworiginlist=https://subdomain.domain.tld  # Cambiar a http si es necesario
      - traefik.http.middlewares.pihole-cors-headers.headers.accesscontrolmaxage=100
      - traefik.http.middlewares.pihole-cors-headers.headers.addvaryheader=true
  
      # Direct Web UI (Comentar si se va a conectar siempre mediante dominio)
      - traefik.http.routers.pihole.rule=PathPrefix(`/`)
      - traefik.http.routers.pihole.entrypoints=pihole_interface
      - traefik.http.routers.pihole.service=pihole-direct-service
      - traefik.http.services.pihole-direct-service.loadbalancer.server.port=80
  
      # Web UI (Descomentar si no se usa HTTPS)
      #- traefik.http.routers.pihole-http.rule=Host(`subdomain.domain.tld`) && PathPrefix(`/`)
      #- traefik.http.routers.pihole-http.entrypoints=web
      #- traefik.http.routers.pihole-http.middlewares=low-ratelimit@file
      #- traefik.http.routers.pihole-http.service=pihole-http-service
      #- traefik.http.services.pihole-http-service.loadbalancer.server.port=80
  
      # Secure Web UI (Descomentar si se usa HTTPS)
      #- traefik.http.routers.pihole-https.rule=Host(`subdomain.domain.tld`) && PathPrefix(`/`)
      #- traefik.http.routers.pihole-https.entrypoints=websecure
      #- traefik.http.routers.pihole-https.middlewares=low-ratelimit@file,secure-headers@file,norobots-headers@file,pihole-cors-headers@docker
      #- traefik.http.routers.pihole-https.tls=true
      #- traefik.http.routers.pihole-https.tls.certresolver=letsencrypt
      #- traefik.http.routers.pihole-https.tls.domains[0].main=domain.tld
      #- traefik.http.routers.pihole-https.tls.domains[0].sans=*.domain.tld
      #- traefik.http.routers.pihole-https.service=pihole-https-service
      #- traefik.http.services.pihole-https-service.loadbalancer.server.port=80
  
      # DNS-over-TLS (No configurado, dejar comentado)
      #- traefik.tcp.routers.dnstls.rule=HostSNI(`*`)
      #- traefik.tcp.routers.dnstls.entrypoints=dnstls
      #- traefik.tcp.routers.dnstls.tls.certresolver=mytlschallenge
      #- traefik.tcp.routers.dnstls.service=pihole
  
      # Normal DNS coming in on 53 TCP, no TLS
      - traefik.tcp.routers.dns.rule=HostSNI(`*`)
      - traefik.tcp.routers.dns.entrypoints=dns
      - traefik.tcp.routers.dns.service=pihole
  
      # recieves traffic from both the TLS and non-TLS traefik routers
      - traefik.tcp.services.pihole.loadbalancer.server.port=53
  
      # Normal DNS coming in on 53 UDP
      - traefik.udp.routers.udpdns.entrypoints=udpdns
      - traefik.udp.routers.udpdns.service=pihole
      - traefik.udp.services.pihole.loadbalancer.server.port=53
    restart: unless-stopped
    hostname: 'rpi-pihole'
networks:
    rpipub:
      name: 'rpi-net-public'
  • /!\ Revisar la variable "WEBPASSWORD"!!
  • /!\ Cambiar 'domain.tld' y 'subdomain.domain.tld' por el dominio que vayamos a usar

Aquí no inventamos nada, el archivo anterior lo ofrecen en la propia documentación (ver https://hub.docker.com/r/pihole/pihole). Lo que si, ampliamos/cambiamos alguna cosa:

  • El tema de puertos se maneja por traefik
  • Establecido el 'hostname'. Así podemos referenciar desde otros contenedores fácilmente dentro de la misma red.
  • Establecida una red por defecto a 'rpi-net', para la configuración que usamos no es realmente necesario pero me gusta que este organizado y seguir un estándar en la nomenclatura.
  • Establecidas unas DNS para que apunten al sitio correcto (fallback a 1.1.1.1)
  1. Levantar el contenedor en modo 'detached': docker-compose up -d
    1. Tanto en portainer como lanzando docker ls se debe ver el contenedor de pi-hole levantado

Configuración

Para acceder al panel será una URL como http://rpi_ip:9010.

Aquí existen varios caminos, aquí comentaremos uno apoyándonos en el router:

  1. Vamos al apartado "Settings", allí a la sección "DNS"
    1. Desmarcar todos los check del bloque de la izquierda llamado "Upstream DNS Servers"
    2. Habilitar "Custom 1 (IPv4)" del bloque de la derecha llamado "Upstream DNS Servers"
      1. Introducir la ip del router (por lo general 192.168.1.1)
  2. Guardar los cambios
  3. Ir al apartado "Group Management", a la sección "Adlists"
    1. Añadir las listas que consideres oportunas... En esta web se pueden consultar listas: https://firebog.net/
    2. Ir a al apartado "Tools", a la sección "Update Gravity" y actualizar.

Configurando el router

  1. Abrir la configuración del router y cambiar el DHCP para que los servidores DNS apunten a la rpi
  2. Quizás se necesite habilitar el "DNS Proxy" para que se puedan procesar las peticiones desde la rpi.
  3. Este punto es opcional, pero recuerda que siempre podrás cambiar los servidores DNS del router para usar, por ejemplo, los de Cloudflare (1.1.1.1) o Quad9 (9.9.9.9)
    1. ¿Pero no dijimos de poner las DNS apuntando a la rpi? Si, pero en este caso no me refiero a la configuración DHCP, sino a la que usará el router (son diferentes apartados).
  4. Resetear las conexiones de nuestros dispositivos para que obtengan la nueva dirección del servidor DNS.

Deluge

Cliente bittorrent

Levantar contenedor

  1. Crear una carpeta donde se meterá el archivo docker-compose.yaml. Yo, por ejemplo, lo meto en un disco externo.
  2. El archivo docker-compose.yaml será muy parecido a este:

docker-compose.yaml

version: "3"

services:
  deluge:
    image: ghcr.io/linuxserver/deluge
    container_name: deluge
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Europe/Madrid
      - DELUGE_LOGLEVEL=error #optional
    networks:
      - rpipub
    dns:
      - 127.0.0.1
      - 1.1.1.1
    labels:
      - traefik.enable=true
  
      # CORS (Solo es útil en caso de usar DynHost)
      - traefik.http.middlewares.deluge-cors-headers.headers.accesscontrolallowmethods=GET,OPTIONS,PUT
      - traefik.http.middlewares.deluge-cors-headers.headers.accesscontrolalloworiginlist=https://subdomain.domain.tld  # Cambiar a http si es necesario
      - traefik.http.middlewares.deluge-cors-headers.headers.accesscontrolmaxage=100
      - traefik.http.middlewares.deluge-cors-headers.headers.addvaryheader=true
  
      # Direct Web UI (Comentar si se va a conectar siempre mediante dominio)
      - traefik.http.routers.deluge.rule=PathPrefix(`/`)
      - traefik.http.routers.deluge.entrypoints=deluge_interface
      - traefik.http.routers.deluge.service=deluge-direct-service
      - traefik.http.services.deluge-direct-service.loadbalancer.server.port=8112
  
      # Web UI (Descomentar si no se usa HTTPS)
      #- traefik.http.routers.deluge-http.rule=Host(`subdomain.domain.tld`) && PathPrefix(`/`)
      #- traefik.http.routers.deluge-http.entrypoints=web
      #- traefik.http.routers.deluge-http.middlewares=low-ratelimit@file
      #- traefik.http.routers.deluge-http.service=deluge-http-service
      #- traefik.http.services.deluge-http-service.loadbalancer.server.port=8112
  
      # Secure Web UI (Descomentar si se usa HTTPS)
      #- traefik.http.routers.deluge-https.rule=Host(`subdomain.domain.tld`) && PathPrefix(`/`)
      #- traefik.http.routers.deluge-https.entrypoints=websecure
      #- traefik.http.routers.deluge-https.middlewares=low-ratelimit@file,secure-headers@file,norobots-headers@file,deluge-cors-headers@docker
      #- traefik.http.routers.deluge-https.tls=true
      #- traefik.http.routers.deluge-https.tls.certresolver=letsencrypt
      #- traefik.http.routers.deluge-https.tls.domains[0].main=domain.tld
      #- traefik.http.routers.deluge-https.tls.domains[0].sans=*.domain.tld
      #- traefik.http.routers.deluge-https.service=deluge-https-service
      #- traefik.http.services.deluge-https-service.loadbalancer.server.port=8112
  
      # 58846 TCP
      - traefik.tcp.services.deluge.loadbalancer.server.port=58846
      - traefik.tcp.routers.deluge_daemon.rule=HostSNI(`*`)
      - traefik.tcp.routers.deluge_daemon.entrypoints=deluge_daemon
      - traefik.tcp.routers.deluge_daemon.service=deluge
  
      # 58946 TCP
      - traefik.tcp.services.deluge_torrent.loadbalancer.server.port=58946
      - traefik.tcp.routers.deluge_torrent.rule=HostSNI(`*`)
      - traefik.tcp.routers.deluge_torrent.entrypoints=deluge_torrent
      - traefik.tcp.routers.deluge_torrent.service=deluge_torrent
  
      # 58946 UDP
      - traefik.udp.routers.udpdeluge_torrent.entrypoints=udpdeluge_torrent
      - traefik.udp.routers.udpdeluge_torrent.service=deluge_torrent
      - traefik.udp.services.deluge_torrent.loadbalancer.server.port=58946
    volumes:
      - ./data/config:/config
      - ./data/downloads:/downloads
      - ./data/downloaded:/downloaded
    restart: unless-stopped
    hostname: "rpi-deluge"
networks:
  rpipub:
    name: "rpi-net-public"
  • /!\ Cambiar 'domain.tld' y 'subdomain.domain.tld' por el dominio que vayas a usar
  1. Este paso es opcional, se enlaza simbólicamente la carpeta ./data/downloaded a una carpeta que está en un disco externo. Las rutas aquí usadas dependerán de donde se hayan montado los discos y como se han nombrado las carpetas. Por ejemplo, un disco montado en /media/e2rpi y una carpeta llamada torrents se queda en /media/e2rpi/torrents.

    1. Para hacer el enlace simbólico: ln -s /media/e2rpi/torrents ./data/downloaded
  2. Levantar el contenedor en modo 'detached': docker-compose up -d

    1. Tanto en portainer como lanzando docker ls se debe ver el contenedor de deluge levantado

Configuración

Para acceder al panel será una URL como http://rpi_ip:8112. La contraseña por defecto es deluge.

  1. Desde la barra de herramientas ir la opción "Preferences", allí se puede cambiar el idioma, limites de velocidad, etc...
    1. Sección 'plugins':
      1. Habilitar blocklist para bloquear ip's
        1. Ir a la configuración de 'blocklist' y usar, por ejemplo, https://github.com/Naunter/BT_BlockLists/raw/master/bt_blocklists.gz
        2. Pulsar el botón Check Download and Import
      2. Habilitar label
      3. Habilitar execute
    2. Sección 'Deamon'
      1. Habilitar Allow Remote Connections (Esto es útil si instalamos el plugin indicado en 'extras')

Configuración (Custom)

Para mi servidor he creado un shell script para tratar los torrents; si están comprimidos en rar o zip se descomprimen y luego se revisa todo y se cataloga en las carpetas video, audio, image.

  1. Copiar el siguiente script en la carpeta ./data/config/:

catalog.sh

  1. Darle permisos de ejecución amplios (para todo el mundo): chmod 755 ./data/catalog.sh
  2. Ir a la configuración de deluge, a la sección Execute
    1. Añadir una nueva regla para Torrent Complete con el comando /config/catalog.sh

Extras

  1. delugesiphon: https://chrome.google.com/webstore/detail/delugesiphon/gabdloknkpdefdpkkibplcfnkngbidim

PostgreSQL

Motor de base de datos

Levantar contenedor

  1. Crear una carpeta donde se meterá el archivo docker-compose.yaml. Yo, por ejemplo, lo meto en un disco externo.
  2. El archivo docker-compose.yaml será muy parecido a este:

docker-compose.yaml

version: "3"

services:
  postgres:
    image: postgres
    container_name: postgres
    environment:
      - TZ=Europe/Madrid
      #- POSTGRES_USER=TU_USUARIO
      - POSTGRES_PASSWORD=TU_CONTRASEÑA
      - PGDATA=/var/lib/postgresql/data/pgdata
    networks:
      - rpipub
    dns:
      - 127.0.0.1
      - 1.1.1.1
    labels:
      - traefik.enable=true
  
      # 5432 TCP
      - traefik.tcp.services.postgres.loadbalancer.server.port=5432
      - traefik.tcp.routers.postgres_daemon.rule=HostSNI(`*`)
      - traefik.tcp.routers.postgres_daemon.entrypoints=postgres_daemon
      - traefik.tcp.routers.posgres_daemon.service=postgres
    volumes:
      - ./data:/var/lib/postgresql/data
    restart: unless-stopped
    hostname: "rpi-postgres"
networks:
  rpipub:
    name: "rpi-net-public"
  • /!\ Revisar la variable "POSTGRES_PASSWORD"!!
  • /!\ Revisar la variable "POSTGRES_USER", si se deja comentado el usuario será 'postgres'
  • /!\ SE RECOMIENDA FIJAR LA VERSION DE LA IMAGEN Y ES NECESARIO SI USAS WATCHTOWER
  1. Levantar el contenedor en modo 'detached': docker-compose up -d
    1. Tanto en portainer como lanzando docker ls se debe ver el contenedor de postgres levantado o esperando a ser reiniciado.

Configuración

El login a la base de datos dependerá de lo que se haya puesto en POSTGRES_USER y POSTGRES_PASSWORD.

Gotify

Gotify es un servidor de notificaciones en tiempo real.

Levantar contenedor

  1. Se usará 'PostgreSQL' para almacenar las notificaciones.
  2. Crear una carpeta donde se meterá el archivo docker-compose.yaml. Yo, por ejemplo, lo meto en un disco externo.
  3. El archivo docker-compose.yaml será muy parecido a este:

docker-compose.yaml

version: "3"

services:
  gotify:
    image: gotify/server-arm64
    container_name: gotify
    environment:
      - TZ=Europe/Madrid
      - GOTIFY_DEFAULTUSER_PASS=CLAVE_PARA_USUARIO_POR_DEFECTO
      - GOTIFY_DATABASE_DIALECT=postgres
      - GOTIFY_DATABASE_CONNECTION=host=rpi-postgres port=5432 user=gotify dbname=gotify password=CLAVE_USUARIO_GOTIFY_POSTGRES sslmode=disable
    networks:
      - rpipub
    dns:
      - 127.0.0.1
      - 1.1.1.1
    volumes:
      - ./data:/app/data
    labels:
      - traefik.enable=true

      # CORS
      - traefik.http.middlewares.gotify-cors-headers.headers.accesscontrolallowmethods=GET,OPTIONS,PUT
      - traefik.http.middlewares.gotify-cors-headers.headers.accesscontrolalloworiginlist=https://subdomain.domain.tld
      - traefik.http.middlewares.gotify-cors-headers.headers.accesscontrolmaxage=100
      - traefik.http.middlewares.gotify-cors-headers.headers.addvaryheader=true

      # Direct Web UI (Comentar si se va a conectar siempre mediante dominio)
      - traefik.http.routers.gotify.rule=PathPrefix(`/`)
      - traefik.http.routers.gotify.entrypoints=gotify
      - traefik.http.routers.gotify.service=gotify-direct-service
      - traefik.http.services.gotify-direct-service.loadbalancer.server.port=80

      # Web UI (Descomentar si no se usa HTTPS)
      #- traefik.http.routers.gotify-http.rule=Host(`subdomain.domain.tld`) && PathPrefix(`/`)
      #- traefik.http.routers.gotify-http.entrypoints=web
      #- traefik.http.routers.gotify-http.middlewares=low-ratelimit@file
      #- traefik.http.routers.gotify-http.service=gotify-http-service
      #- traefik.http.services.gotify-http-service.loadbalancer.server.port=80

      # Secure Web UI (Descomentar si se usa HTTPS)
      #- traefik.http.routers.gotify-https.rule=Host(`subdomain.domain.tld`) && PathPrefix(`/`)
      #- traefik.http.routers.gotify-https.entrypoints=websecure
      #- traefik.http.routers.gotify-https.middlewares=low-ratelimit@file,secure-headers@file,norobots-headers@file,gotify-cors-headers@docker
      #- traefik.http.routers.gotify-https.tls=true
      #- traefik.http.routers.gotify-https.tls.certresolver=letsencrypt
      #- traefik.http.routers.gotify-https.tls.domains[0].main=domain.tld
      #- traefik.http.routers.gotify-https.tls.domains[0].sans=*.domain.tld
      #- traefik.http.routers.gotify-https.service=gotify-https-service
      #- traefik.http.services.gotify-https-service.loadbalancer.server.port=80

    restart: unless-stopped
    hostname: "rpi-gotify"
networks:
    rpipub:
      name: 'rpi-net-public'
  • /!\ Revisar la variable 'GOTIFY_DEFAULTUSER_PASS'
  • /!\ Revisar la variable 'GOTIFY_DATABASE_CONNECTION'
  • /!\ Cambiar 'domain.tld' y 'subdomain.domain.tld' por el dominio que vayas a usar
  1. Levantar el contenedor en modo 'detached': docker-compose up -d
    1. Tanto en portainer como lanzando docker ls se debe ver el contenedor de gotify levantado

Configuración

Para acceder al panel será una URL como http://rpi_ip:9050.

Como se está usando "postgres" debemos asegurar que tenemos creado el usuario "gotify" y la base de datos "gotify". Para empezar a trabajar se necesita crear, al menos, una app:

  1. Ir a la seccion "APPS" y pulsar en "Create Application"
    1. Poner un nombre y descripción

Extras

  1. App para Android: https://f-droid.org/es/packages/com.github.gotify/

Notas

Si vas a conectarte a gotify desde fuera de la red local es imperativo el uso de https!!

Watchtower

Watchtower nos ayuda a tener nuestras imagenes actualizadas. Esto no es recomendable en entornos de producción, pero para nuestro servidor casero donde no nos importa que pueda romperse algo por alguna incompatibilidad pues es un gran aliado.

Levantar contenedor

  1. Se usará 'Gotify' como medio para recibir las notificaciones.
  2. Crear una carpeta donde se meterá el archivo docker-compose.yaml. Yo, por ejemplo, lo meto en un disco externo.
  3. El archivo docker-compose.yaml será muy parecido a este:

docker-compose.yaml

version: "3"

services:
  watchtower:
    image: containrrr/watchtower
    container_name: watchtower
    environment:
      - TZ=Europe/Madrid
      - WATCHTOWER_NOTIFICATIONS=gotify
      - WATCHTOWER_NOTIFICATION_GOTIFY_URL=http://rpi-gotify
      - WATCHTOWER_NOTIFICATION_GOTIFY_TOKEN=EL_TOKEN_SECRETO_CREADO_PARA_LA_APP
    networks:
      - rpipub
    dns:
      - 127.0.0.1
      - 1.1.1.1
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    command: --cleanup
    restart: unless-stopped
    hostname: "rpi-watchtower"
networks:
    rpipub:
      name: 'rpi-net-public'
  • /!\ Revisar la variable 'WATCHTOWER_NOTIFICATION_GOTIFY_TOKEN' ** Como se puede apreciar, usamos "http" para conectar con el servidor de notificaciones. Esto es así porque la conexión va a ser local (no sale a internet).
  1. Levantar el contenedor en modo 'detached': docker-compose up -d
    1. Tanto en portainer como lanzando docker ls se debe ver el contenedor de watchtower levantado

Jellyfin

Jellyfin es una servidor media con capacidades de streaming. Clasifca el contenido, catalogalo usando servicios de internet: Carataluas, fechas, actores, etc... Usamos la imagen de "linuxserver" en vez de la oficial porque es la que recomiendan en la propia documentación de jellyfin (https://jellyfin.org/docs/general/administration/hardware-acceleration.html#raspberry-pi-3-and-4)

Levantar contenedor

  1. Crear una carpeta donde se meterá el archivo docker-compose.yaml. Yo, por ejemplo, lo meto en un disco externo.
  2. El archivo docker-compose.yaml será muy parecido a este:

docker-compose.yaml

version: "2.1"
services:
  jellyfin:
    image: ghcr.io/linuxserver/jellyfin
    container_name: jellyfin
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Europe/Madrid
      - JELLYFIN_PublishedServerUrl=subdomain.domain.tld # <---- QUE NO SE OLVIDETE ESTE
    networks:
      - rpipub
    #network_mode: host
    dns:
      - 127.0.0.1
      - 1.1.1.1
    volumes:
      - ./data/downloads/video/peliculas:/data/movies
      - ./data/downloads/video/series:/data/tvshows
      - ./data/config:/config
      - /opt/vc/lib:/opt/vc/lib # OpenMAX libs
      - /dev/shm:/config/data/transcoding-temp/transcodes
    devices:
      - /dev/dri:/dev/dri # VAAPI enconding
      - /dev/vcsm-cma:/dev/vcsm-cma # MMAL (OpenMAX H264 decode)
      - /dev/vchiq:/dev/vchiq # OpenMAX encoding
      - /dev/video10:/dev/video10 # V4L2 encoding
      - /dev/video11:/dev/video11 # V4L2 encoding
      - /dev/video12:/dev/video12 # V4L2 encoding
    labels:
      - traefik.enable=true

      # CORS (Solo es útil en caso de usar DynHost)
      - traefik.http.middlewares.jellyfin-cors-headers.headers.accesscontrolallowmethods=GET,OPTIONS,PUT
      - traefik.http.middlewares.jellyfin-cors-headers.headers.accesscontrolalloworiginlist=https://subdomain.domain.tld
      - traefik.http.middlewares.jellyfin-cors-headers.headers.accesscontrolmaxage=100
      - traefik.http.middlewares.jellyfin-cors-headers.headers.addvaryheader=true

      # Direct Web UI (Comentar si se va a conectar siempre mediante dominio)
      - traefik.http.routers.jellyfin.rule=PathPrefix(`/`)
      - traefik.http.routers.jellyfin.entrypoints=jellyfin_interface
      - traefik.http.routers.jellyfin.service=jellyfin-direct-service
      - traefik.http.services.jellyfin-direct-service.loadbalancer.server.port=8096

      # Web UI (Descomentar si no se usa HTTPS)
      #- traefik.http.routers.jellyfin-http.rule=Host(`subdomain.domain.tld`) && PathPrefix(`/`)
      #- traefik.http.routers.jellyfin-http.entrypoints=web
      #- traefik.http.routers.jellyfin-http.middlewares=low-ratelimit@file
      #- traefik.http.routers.jellyfin-http.service=jellyfin-http-service
      #- traefik.http.services.jellyfin-http-service.loadbalancer.server.port=8096

      # Secure Web UI (Descomentar si se usa HTTPS)
      #- traefik.http.routers.jellyfin-https.rule=Host(`subdomain.domain.tld`) && PathPrefix(`/`)
      #- traefik.http.routers.jellyfin-https.entrypoints=websecure
      #- traefik.http.routers.jellyfin-https.middlewares=low-ratelimit@file,secure-headers@file,norobots-headers@file,jellyfin-cors-headers@docker
      #- traefik.http.routers.jellyfin-https.tls=true
      #- traefik.http.routers.jellyfin-https.tls.certresolver=letsencrypt
      #- traefik.http.routers.jellyfin-https.tls.domains[0].main=domain.tld
      #- traefik.http.routers.jellyfin-https.tls.domains[0].sans=*.domain.tld
      #- traefik.http.routers.jellyfin-https.service=jellyfin-https-service
      #- traefik.http.services.jellyfin-https-service.loadbalancer.server.port=8096

      # 7359 UDP
      - traefik.udp.routers.udpjellyfin_discovery.entrypoints=udpjellyfin_discovery
      - traefik.udp.routers.udpjellyfin_discovery.service=jellyfin_discovery
      - traefik.udp.services.jellyfin_discovery.loadbalancer.server.port=7359

      # 1900 UDP
      - traefik.udp.routers.udpjellyfin_dlna.entrypoints=udpjellyfin_dlna
      - traefik.udp.routers.udpjellyfin_dlna.service=jellyfin_dlna
      - traefik.udp.services.jellyfin_dlna.loadbalancer.server.port=1900
    restart: unless-stopped
    hostname: "rpi-jellyfin"
    
networks:
  rpipub:
    name: "rpi-net-public"
  • /!\ Cambiar 'domain.tld' por el dominio que vayas a usar
  • */!\ Los volumenes '/media/movies' y '/media/tvshows' son meros ejemplos, usa los nombres y puntos de montaje que quieras

Requisitos

  1. Según la documentación se debe aumentar la memoria reservada para la gpu (https://jellyfin.org/docs/general/administration/hardware-acceleration.html#raspberry-pi-3-and-4 y https://www.raspberrypi.org/documentation/configuration/config-txt/memory.md)
    1. Editar el archivo /boot/config.txt
      1. Añadir: gpu_mem=320
      2. Reiniciar: sudo reboot

Configuración

  1. Habilitar la aceleración por hardware. (Es importante tener la rpi con ventilación activa!!)
    1. En Panel de control > Reproducción dejar la aceleración por hardware en Video Aceleration API (VAAPI).
    2. Grabar los cambios

Extras

  1. App para Android: https://f-droid.org/es/packages/org.jellyfin.mobile/
  2. Reproductor de música para Android: https://f-droid.org/es/packages/com.dkanada.gramophone/ ** Más en: https://jellyfin.org/clients/
  3. Canales IPTV (M3U8) + EPG: https://tdtchannels.com/listas

Notas

No he sido capaz de hacer funcionar el descubrimiento del servidor DLNA, pero se puede obtener la url de streaming y usar programas como VLC para reprucidr las películas.

NextCloud

Levantar contenedor

  1. Se usará 'PostgreSQL' para almacenar los datos.
  2. Crear una carpeta donde se meterá el archivo docker-compose.yaml. Yo, por ejemplo, lo meto en un disco externo.
  3. El archivo docker-compose.yaml será muy parecido a este:

docker-compose.yaml

version: "3"

services:
  nextcloud:
    image: nextcloud
    container_name: nextcloud
    environment:
      - TZ=Europe/Madrid
      - NEXTCLOUD_ADMIN_USER=USUARIO_ADMIN
      - NEXTCLOUD_PASSWORD=CONTRASEÑA_ADMIN
      - NEXTCLOUD_DATA_DIR=/nextcloud_data
      - POSTGRES_DB=NOMBRE_BASE_DE_DATOS
      - POSTGRES_USER=USUARIO_BASE_DE_DATOS
      - POSTGRES_PASSWORD=CONTRASEÑA_USUARIO_BASE_DE_DATOS
      - POSTGRES_HOST=rpi-postgres
    networks:
      - rpipub
    dns:
      - 127.0.0.1
      - 1.1.1.1
    labels:
      - traefik.enable=true
  
      # CORS (Solo es útil en caso de usar DynHost)
      - traefik.http.middlewares.nextcloud-cors-headers.headers.accesscontrolallowmethods=GET,OPTIONS,PUT
      - traefik.http.middlewares.nextcloud-cors-headers.headers.accesscontrolalloworiginlist=https://subdomain.domain.tld  # Cambiar a http si es necesario
      - traefik.http.middlewares.nextcloud-cors-headers.headers.accesscontrolmaxage=100
      - traefik.http.middlewares.nextcloud-cors-headers.headers.addvaryheader=true
  
      # Web DAV
      - traefik.http.middlewares.nextcloud-dav-redirect.redirectregex.permanent=true
      - traefik.http.middlewares.nextcloud-dav-redirect.redirectregex.regex=https://(.*)/.well-known/(card|cal)dav
      - traefik.http.middlewares.nextcloud-dav-redirect.redirectregex.replacement=https://$$1/remote.php/dav/

      # Direct Web UI (Comentar si se va a conectar siempre mediante dominio)
      - traefik.http.routers.nextcloud.rule=PathPrefix(`/`)
      - traefik.http.routers.nextcloud.entrypoints=nextcloud_interface
      - traefik.http.routers.nextcloud.service=nextcloud-direct-service
      - traefik.http.services.nextcloud-direct-service.loadbalancer.server.port=80
  
      # Web UI (Descomentar si no se usa HTTPS)
      #- traefik.http.routers.nextcloud-http.rule=Host(`subdomain.domain.tld`) && PathPrefix(`/`)
      #- traefik.http.routers.nextcloud-http.entrypoints=web
      #- traefik.http.routers.nextcloud-http.middlewares=low-ratelimit@file
      #- traefik.http.routers.nextcloud-http.service=nextcloud-http-service
      #- traefik.http.services.nextcloud-http-service.loadbalancer.server.port=80
  
      # Secure Web UI (Descomentar si se usa HTTPS)
      #- traefik.http.routers.nextcloud-https.rule=Host(`subdomain.domain.tld`) && PathPrefix(`/`)
      #- traefik.http.routers.nextcloud-https.entrypoints=websecure
      #- traefik.http.routers.nextcloud-https.middlewares=medium-ratelimit@file,secure-headers@file,norobots-headers@file,nextcloud-cors-headers@docker,nextcloud-dav-redirect@docker
      #- traefik.http.routers.nextcloud-https.tls=true
      #- traefik.http.routers.nextcloud-https.tls.certresolver=letsencrypt
      #- traefik.http.routers.nextcloud-https.tls.domains[0].main=domain.tld
      #- traefik.http.routers.nextcloud-https.tls.domains[0].sans=*.domain.tld
      #- traefik.http.routers.nextcloud-https.service=nextcloud-https-service
      #- traefik.http.services.nextcloud-https-service.loadbalancer.server.port=80
    volumes:
      - ./data/html:/var/www/html
      - ./data/data:/nextcloud_data
      - ./data/config/nextcloud.ini:/usr/local/etc/php/conf.d/nextcloud.ini
    restart: unless-stopped
    hostname: "rpi-nextcloud"
  
  cron:
    image: rcdailey/nextcloud-cronjob
    restart: always
    container_name: nextcloud-cron
    network_mode: none
    depends_on:
    - nextcloud
    volumes:
    - /var/run/docker.sock:/var/run/docker.sock:ro
    - /etc/localtime:/etc/localtime:ro
    environment:
    - NEXTCLOUD_CONTAINER_NAME=nextcloud
  
networks:
  rpipub:
    name: "rpi-net-public"
  • /!\ Revisar la variable "NEXTCLOUD_ADMIN_USER"
  • /!\ Revisar la variable "NEXTCLOUD_PASSWORD"!!
  • /!\ Revisar la variable "POSTGRES_DB"
  • /!\ Revisar la variable "POSTGRES_USER"
  • /!\ Revisar la variable "POSTGRES_PASSWORD"!!
  • /!\ Cambiar 'domain.tld' y 'subdomain.domain.tld' por el dominio que vayas a usar
  1. Este paso es opcional, enlazar simbólicamente la carpeta ./data/data a una carpeta que está en otro disco externo. Las rutas aquí usadas dependerán de donde se hayan montado los discos y como se han nombrado las carpetas. Por ejemplo, un disco montado en /media/e2rpi y una carpeta llamada nextcloud_data queda en /media/e2rpi/nextcloud_data.
    1. Para hacer el enlace simbólico: ln -s /media/e2rpi/nextcloud_data ./data/data
  2. Aplicar permisos a la carpeta ./data/data
    1. Asignar grupo: sudo chown -R www-data: data/data
    2. Asignar permisos: sudo chmod 0770 data/data
  3. Crear el archivo de configuracion de PHP para nextcloud
    1. Crear la carpeta: sudo mkdir data/config
    2. Crear el archivo, ajustar los valores a lo que consideres oportuno: sudo nano data/config/nextcloud.ini nextcloud.ini
[PHP]
memory_limit = 1G
upload_max_filesize= 15G
post_max_size = 16G
max_execution_time = 3600
max_input_time = 3600
  1. Levantar el contenedor en modo 'detached': docker-compose up -d
    1. Tanto en portainer como lanzando docker ls se debe ver el contenedor de nextcloud levantado

Configuración

La primera vez que arrancamos nos pedirá iniciar la instalación, como ya hemos puesto todo lo necesario en las variables de entorno del contenedor solo tendremos que pulsar en el bóton de instalar.

  1. Asegurarse de tener los permisos correctos en la carpeta data (desde la carpeta donde está el archivo docker-compose.yaml):
chown -R www-data:www-data data/
find data/ -type d -exec chmod 750 {} \;
find data/ -type f -exec chmod 640 {} \;
  1. Cambiar los trabajos en segundo plano a cron (Se usa una imagen de apoyo para ejecutar la tarea ya que la imagen de docker no puede ejecutar el cron si no es con permisos de root)
    1. Para ello deberemos ir a la configuración al apartado Ajustes básicos.
  2. Es aconsejable darse una vuelta por la configuración para dejarlo a nuestro gusto
  3. Es aconsejable darse una vuelta por las aplicaciones para instalar/desinstalar lo que queramos
    1. Por ejemplo, si usamos certificado igual nos interese instalar la autentificación en dos pasos.
  4. Se pueden montar carpetas alojadas en otros discos o rutas fuera de la indicada para nextcloud.
    1. Para ello se debe montar la carpeta en el contenedor ampliando docker-compose.yaml.
    2. Se tiene que instalar la aplicación de nextcloud para almacenamiento externo (External Storage) que saldrá como recomendada.
    3. Una vez instalada se debe configurar el nuevo almacenamiento (en nuestro caso de tipo Local) desde la configuración.

Configuracion Extra

Los cambios se hacen en la configuración de nextcloud data/html/config/config.php añadiendo las lineas necesarias.

  1. Si se va a usar por HTTPS se tiene que habilitar el forzado de protocolo
    1. 'overwriteprotocol' => 'https'
  2. Si se usa DynHost (ver siguiente tema)
    1. 'overwritehost' => 'subdomain.domain.tld'
      1. Cambiar subdomain.domain.tld por el que hayas puesto en el archivo docker-compose.yaml
    2. 'trusted_domains' => array ( 0 => 'subdomain.domain.tld' )
      1. Cambiar subdomain.domain.tld por el que hayas puesto en el archivo docker-compose.yaml
    3. 'trusted_proxies' => array ( 0 => 'subdomain.domain.tld' )
      1. Cambiar subdomain.domain.tld por el dominio que uses en DynHost
  3. Si se va a usar el listin telefónico
    1. 'default_phone_region' => 'ES'

Notas

  • Si se activa TOTP (se requiere HTTPS para ello) y se quiere conectar con una aplicación externa, seguramente se necesite crear una contraseña de aplicación desde Configuración > Personal > Seguridad > Dispositivos y sesiones

Extras

  1. App para Android, permite auto-sincronizar archivos: https://f-droid.org/es/packages/com.nextcloud.client/
  2. Extensión de navegador para sincronizar marcadores: https://floccus.org/

Syncthing

Syncthing sirve para replicar archivos entre servidores. Para funcionar con syncthing se debe tener una instancia funcionando en todos los equipos que estén involucrados. En nuestro caso tendremos un syncthing ejecutándose en el equipo de sobremesa y otro syncthing ejecutándose en la raspberry pi.

En este apartado se verá como configurar syncthing para tener: [ PC ] (Solo envía) --> [ RPI ] (Solo recibe y versionado de cambios)

Preparando syncthing en el equipo de sobremesa

Aquí se puede optar por usar docker o instalarlo mediante repositorios de tu distro. Lo más sencillo es usar los repositorios de tu distro. Una vez instalado se tiene acceso al panel en: http://127.0.0.1:8384/

Configuración

  1. Añadir la carpeta que queremos tener replicada
    1. Pulsar en Agregar Carpeta
    2. En la pestaña General
      1. Poner la Etiqueta de la Carpeta que se quiera para identificarla
      2. Poner la Ruta de la carpeta que se quiera replicar, en nuestro ejemplo: /home/test/mi_carpeta_sincronizada
    3. En la pestaña Avanzado cambiar el Tipo de carpeta a Solo Enviar
  2. Añadir un dispositivo nuevo
    1. Pulsar en Añadir un dispositivo
    2. En la pestaña General poner el ID del Dispositivo de la rpi
      1. Para saber este ID ir al panel de syncthing en la rpi (mirar el siguiente apartado para desplegar) y en el menú superior pulsar en Acciones > Mostrar ID
    3. Ir a la pestaña Avanzado y cambiar Direcciones a algo como tcp://IP_RPI:22000 (cambiar IP_RPI por la ip de la raspberry)
    4. Guardar

Preparando syncthing en la rpi

Levantar contenedor

  1. Crear una carpeta donde se meterá el archivo docker-compose.yaml. Yo, por ejemplo, lo meto en un disco externo.
  2. El archivo docker-compose.yaml será muy parecido a este:

docker-compose.yaml

version: "3"

services:
  syncthing:
    image: syncthing/syncthing
    container_name: syncthing
    environment:
      - TZ=Europe/Madrid
    networks:
      - rpipub
    dns:
      - 127.0.0.1
      - 1.1.1.1
    labels:
      - traefik.enable=true

      # CORS (Solo es útil en caso de usar DynHost)
      - traefik.http.middlewares.syncthing-cors-headers.headers.accesscontrolallowmethods=GET,OPTIONS,PUT
      - traefik.http.middlewares.syncthing-cors-headers.headers.accesscontrolalloworiginlist=https://subdomain.domain.tld
      - traefik.http.middlewares.syncthing-cors-headers.headers.accesscontrolmaxage=100
      - traefik.http.middlewares.syncthing-cors-headers.headers.addvaryheader=true

      # Direct Web UI
      - traefik.http.routers.syncthing.rule=PathPrefix(`/`)
      - traefik.http.routers.syncthing.entrypoints=syncthing_interface
      - traefik.http.routers.syncthing.service=syncthing-direct-service
      - traefik.http.services.syncthing-direct-service.loadbalancer.server.port=8384

      # Web UI (Descomentar si no se usa HTTPS)
      #- traefik.http.routers.syncthing-http.rule=Host(`subdomain.domain.tld`) && PathPrefix(`/`)
      #- traefik.http.routers.syncthing-http.entrypoints=web
      #- traefik.http.routers.syncthing-http.middlewares=low-ratelimit@file
      #- traefik.http.routers.syncthing-http.service=syncthing-http-service
      #- traefik.http.services.syncthing-http-service.loadbalancer.server.port=8384

      # Secure Web UI (Descomentar si se usa HTTPS)
      #- traefik.http.routers.syncthing-https.rule=Host(`subdomain.domain.tld`) && PathPrefix(`/`)
      #- traefik.http.routers.syncthing-https.entrypoints=websecure
      #- traefik.http.routers.syncthing-https.middlewares=medium-ratelimit@file,secure-headers@file,norobots-headers@file,syncthing-cors-headers@docker
      #- traefik.http.routers.syncthing-https.tls=true
      #- traefik.http.routers.syncthing-https.tls.certresolver=letsencrypt
      #- traefik.http.routers.syncthing-https.tls.domains[0].main=domain.tld
      #- traefik.http.routers.syncthing-https.tls.domains[0].sans=*.domain.tld
      #- traefik.http.routers.syncthing-https.service=syncthing-https-service
      #- traefik.http.services.syncthing-https-service.loadbalancer.server.port=8384

      # 22000 TCP
      - traefik.tcp.services.syncthing_daemon.loadbalancer.server.port=22000
      - traefik.tcp.routers.syncthing_daemon.rule=HostSNI(`*`)
      - traefik.tcp.routers.syncthing_daemon.entrypoints=syncthing_daemon
      - traefik.tcp.routers.syncthing_daemon.service=syncthing_daemon

      # 22000 UDP
      - traefik.udp.routers.udpsyncthing_daemon.entrypoints=udpsyncthing_daemon
      - traefik.udp.routers.udpsyncthing_daemon.service=syncthing_daemon
      - traefik.udp.services.syncthing_daemon.loadbalancer.server.port=22000
    volumes:
      - ./data:/var/syncthing
    restart: unless-stopped
    hostname: "rpi-syncthing"

networks:
  rpipub:
    name: "rpi-net-public"
  • /!\ Cambiar 'domain.tld' y 'subdomain.domain.tld' por el dominio que vayas a usar

Configuración mínima

  1. Añadir un dispositivo nuevo

    1. Pulsar en Añadir un dispositivo
    2. En la pestaña General poner el ID del Dispositivo del equipo de sobremesa
      1. Para saber este ID ir al panel de syncthing en el equipo de sobremesa y en el menú superior pulsar en Acciones > Mostrar ID
    3. Ir a la pestaña Avanzado y cambiar Direcciones a algo como tcp://IP_RPI:22000 (cambiar IP_RPI por la ip de la raspberry)
    4. Guardar
  2. Añadir la carpeta donde queremos tener la replica

    1. Pulsar en Agregar Carpeta
    2. En la pestaña General
      1. Poner la Etiqueta de la Carpeta, en nuestro ejemplo: replica_sobremesa
      2. Poner el ID de carpeta que se va a replicar
        1. Para saber este ID vamos al panel de syncthing en el equipo de sobremesa y el apartado Carpetas desplegar la información de la carpeta que se quiere replicar y el primer apartado es el ID de carpeta
    3. En la pestaña Compartiendo seleccionar el equipo de sobremesa (debería ser la única opción disponible)
    4. En la pestaña Versionado de ficheros
      1. Cambiar el Versionado de ficheros a Versionado escalonado de fichero
      2. Puedes cambiar la Edad máxima a lo que quieras, por ejemplo, 60 días
    5. En la pestaña Avanzado cambiar el Tipo de carpeta a Solo Recibir
  3. Poner una contraseña al panel

    1. En el menú superior pulsar en Acciones > Ajustes
      1. Cambiar el Password de la Interfaz Gráfica de Usuario (GUI)
      2. Guardar

DynHost (OVH)

Una DNS dinámica nos sirve para tener un dominio apuntando a un host que puede ir variando de ip. Teniendo un DynHost podremos tener un dominio como rpi.mysuperdominio.com que usar para conectar a nuestra RPI sin miedo a que se nos reinicie el router.

En este caso la imagen que se usará lanzará una actualización cada 5 minutos.

  1. Lo primero será configurar el DynHost en OVH: https://docs.ovh.com/es/domains/web_hosting_dynhost/

Levantar contenedor

  1. Crear una carpeta donde se meterá el archivo docker-compose.yaml. Yo, por ejemplo, lo meto en un disco externo.
  2. El archivo docker-compose.yaml será muy parecido a este:

docker-compose.yaml

version: "3"

services:
  dynhost:
    image: webhainaut/ovh-dyndns
    container_name: dynhost
    environment:
      - TZ=Europe/Madrid
      - HOST=DOMINIO_DYNHOST
      - LOGIN=USUARIO_DOMINIO_DYNHOST
      - PASSWORD=CONTRASEÑA_USUARIO_DOMINIO_DYNHOST
    networks:
      - rpipub
    dns:
      - 127.0.0.1
      - 1.1.1.1
    restart: unless-stopped
    hostname: "rpi-dynhost"
networks:
  rpipub:
    name: "rpi-net-public"
  • /!\ Revisar las variables 'HOST', 'LOGIN' y 'PASSWORD'!!
  1. Levantar el contenedor en modo 'detached': docker-compose up -d
    1. Tanto en portainer como lanzando docker ls se debe ver el contenedor de dynhost levantado o esperando a ser reiniciado.

Un extra sobre la gestión de dominios y DynHost

Vale, ahora que ya está DynHost funcionando seguramente se quiera usar más subdominios... en contra de registrar más DynHost, lo aconsejable es crear DNS de tipo CNAME apuntando al actual registro de DynHost ... así solo se tiene que actualizar un DNS y el resto se fían. Por ejemplo tener: rpi.ejemplo.com y después como CNAME: vault.ejemplo.com, cloud.ejemplo.com, ....

Let's Encrypt (OVH)

Háganse los certificados!

Configurando OVH para trabajar con traefik

Información sobre reglas de acceso necesarias: https://certbot-dns-ovh.readthedocs.io/en/stable/#credentials

  1. Lo primero es crear una clave de applicación: https://eu.api.ovh.com/createApp/
  2. Luego se debe darle permisos a dicha applicacion: curl -XPOST -H "X-Ovh-Application: APPLICATION_KEY" -H "Content-type: application/json" https://eu.api.ovh.com/1.0/auth/credential -d '{"accessRules":[{"method":"GET","path":"/domain/zone/*"},{"method": "POST","path":"/domain/zone/*"},{"method":"PUT","path":"/domain/zone/*"},{"method":"DELETE","path":"/domain/zone/*"}], "redirection": "https://www.domain.tld"}' ** Por ejemplo: curl -XPOST -H "X-Ovh-Application: R3uJWoCPyDki9rHCmBES" -H "Content-type: application/json" https://eu.api.ovh.com/1.0/auth/credential -d '{"accessRules":[{"method":"GET","path":"/domain/zone/*"},{"method": "POST","path":"/domain/zone/*"},{"method":"PUT","path":"/domain/zone/*"},{"method":"DELETE","path":"/domain/zone/*"}], "redirection": "https://www.ejemplo.com"}'
    1. Esto devolverá el dato consumerKey que debemos guardar
    2. RECUERDAR que se debe validar las nuevas credenciales siguiendo el enlace que indican en la respuesta validationUrl

Verificar que todo está correcto

  1. Acceder al panel de OVH y logearse: https://eu.api.ovh.com/console
  2. Ir a /me/api/application y ejecutar para ver el ID de la aplicación
  3. Ir a /me/api/application/{applicationId} (GET) y ver que se puede consultar la "applicationKey".
  4. Ir a /me/api/credential y usando el "applicationId" que se ha obtenido antes se comprueba que devuelve un id de credenciales
  5. Ir a /me/api/credential/{credentialId} (GET) y se comprueba que los permisos de esas credenciales son los que se han indicado antes y que está con status: "validated" *** Se puede borrar la aplicación desde /me/api/application/{applicationId} (DELETE)

Actualizar la configuración de traefik y resto de contenedores

Ahora que ya está habilitado todo en OVH es turno de modificar la configuración de traefik para hacer uso de ello. Revisar el tema de traefik y fijarse en las partes comentadas tanto en traefik.yaml como en docker-compose.yaml. No olvidar habilitar también las rutas para que las app sean accesibles usando el certificado generado por let's encrypt. En este caso estarán comentadas a modo de plantilla en los respectivos docker-compose.yaml.

DNS CAA (OVH)

CAA es un tipo de registro de DNS para indicar que autoridades están autorizadas a emitir el certificado SSL/TLS.

Crear registro CAA

  1. Acceder a la zona DNS de tu dominio: https://www.ovh.com/manager/web/#/domain
  2. Pulsa en Añadir un registro
    1. Pulsa en CAA
    2. En indicador pon 0
    3. En etiqueta selecciona issue (Esto es para indicar quien puede emitir para el dominio indicado)
    4. En destino pon letsencrypt.org
    5. Finalia pulsando Siguiente
  3. Añade otro registro CAA pero está vez en etiqueta selecciona issuewild (Esto es para indicar quien puede emitir para los subdominios)
  4. Añade un tercer registro CAA pero está vez en etiqueta selecciona ideof (Esto es para indicar a que correo se enviará una notificación en caso de que alguien intente generar un certificado por vías no autorizadas)
    1. En destino pon mailto:tu@correo

Extras

Si todo ha salido bien hasta este punto, si usas https://www.ssllabs.com/ssltest/ debería darte como resultado un A+

Vaultwarden (Solo si usas certificado)

Con vaultwarden tendremos un baúl donde almacenar nuestros secretos más preciados como claves de acceso, tarjetas de crédito, etc... Se trata de una implementación alternativa (no oficial) en Rust del servidor de bitwarden. Para poder usar vaultwarden se necesita si o si usar HTTPS!

Levantar contenedor (1/2)

  1. Crear una carpeta donde se meterá el archivo docker-compose.yaml. Yo, por ejemplo, lo meto en un disco externo.
  2. El archivo docker-compose.yaml será muy parecido a este:

docker-compose.yaml

version: "3"

services:
  vaultwarden:
    image: vaultwarden/server
    container_name: vaultwarden
    environment:
      - TZ=Europe/Madrid
      - ADMIN_TOKEN=PON_AQUI_UNA_PASS_SEGURA
    networks:
      - rpipub
    dns:
      - 127.0.0.1
      - 1.1.1.1
    labels:
      - traefik.enable=true
  
      # CORS
      - traefik.http.middlewares.vaultwarden-cors-headers.headers.accesscontrolallowmethods=GET,OPTIONS,PUT
      - traefik.http.middlewares.vaultwarden-cors-headers.headers.accesscontrolalloworiginlist=https://subdomain.domain.tld  # Cambiar a http si es necesario
      - traefik.http.middlewares.vaultwarden-cors-headers.headers.accesscontrolmaxage=100
      - traefik.http.middlewares.vaultwarden-cors-headers.headers.addvaryheader=true
   
      # Secure Web UI
      - traefik.http.routers.vaultwarden-https.rule=Host(`subdomain.domain.tld`) && PathPrefix(`/`)
      - traefik.http.routers.vaultwarden-https.entrypoints=websecure
      - traefik.http.routers.vaultwarden-https.middlewares=low-ratelimit@file,secure-headers@file,norobots-headers@file,vaultwarden-cors-headers@docker
      - traefik.http.routers.vaultwarden-https.tls=true
      - traefik.http.routers.vaultwarden-https.tls.certresolver=letsencrypt
      - traefik.http.routers.vaultwarden-https.tls.domains[0].main=domain.tld
      - traefik.http.routers.vaultwarden-https.tls.domains[0].sans=*.domain.tld
      - traefik.http.routers.vaultwarden-https.service=vaultwarden-https-service
      - traefik.http.services.vaultwarden-https-service.loadbalancer.server.port=80

    volumes:
      - ./data/:/data/
    restart: unless-stopped
    hostname: "rpi-vaultwarden"
networks:
  rpipub:
    name: "rpi-net-public"
  • /!\ Revisar la variable "ADMIN_TOKEN"!!
  • /!\ Cambiar 'domain.tld' y 'subdomain.domain.tld' por el dominio que vayas a usar
  1. Levantr el contenedor en modo 'detached': docker-compose up -d
    1. Tanto en portainer como lanzando docker ls se debe ver el contenedor de vaultwarden levantado o esperando a ser reiniciado.

Configuración básica

Con la configuración de este hilo tendremos acceso a vaultwarden desde https://subdomain.domain.tld

  1. Crear una cuenta de usuario

Levantar contenedor (2/2)

Este paso no es necesario, esto es para que no se puedan crear más usuarios.

  1. Para el contenedor: docker-compose down
  2. Ampliar docker-compose.yaml añadiendo dos nuevas variables de entorno (SIGNUPS_ALLOWED y INVITATIONS_ALLOWED):

docker-compose.yaml

version: "3"

services:
  vaultwarden:
    image: vaultwarden/server
    container_name: vaultwarden
    environment:
      - TZ=Europe/Madrid
      - ADMIN_TOKEN=PON_AQUI_UNA_PASS_SEGURA
      - SIGNUPS_ALLOWED=false
      - INVITATIONS_ALLOWED=false
    networks:
      - rpipub
    dns:
      - 127.0.0.1
      - 1.1.1.1
    labels:
      - traefik.enable=true
  
      # CORS
      - traefik.http.middlewares.vaultwarden-cors-headers.headers.accesscontrolallowmethods=GET,OPTIONS,PUT
      - traefik.http.middlewares.vaultwarden-cors-headers.headers.accesscontrolalloworiginlist=https://subdomain.domain.tld  # Cambiar a http si es necesario
      - traefik.http.middlewares.vaultwarden-cors-headers.headers.accesscontrolmaxage=100
      - traefik.http.middlewares.vaultwarden-cors-headers.headers.addvaryheader=true
  
      # Secure Web UI
      - traefik.http.routers.vaultwarden-https.rule=Host(`subdomain.domain.tld`) && PathPrefix(`/`)
      - traefik.http.routers.vaultwarden-https.entrypoints=websecure
      - traefik.http.routers.vaultwarden-https.middlewares=low-ratelimit@file,secure-headers@file,norobots-headers@file,vaultwarden-cors-headers@docker
      - traefik.http.routers.vaultwarden-https.tls=true
      - traefik.http.routers.vaultwarden-https.tls.certresolver=letsencrypt
      - traefik.http.routers.vaultwarden-https.tls.domains[0].main=domain.tld
      - traefik.http.routers.vaultwarden-https.tls.domains[0].sans=*.domain.tld
      - traefik.http.routers.vaultwarden-https.service=vaultwarden-https-service
      - traefik.http.services.vaultwarden-https-service.loadbalancer.server.port=80
    volumes:
      - ./data/:/data/
    restart: unless-stopped
    hostname: "rpi-vaultwarden"
networks:
  rpipub:
    name: "rpi-net-public"
  • /!\ Revisar la variable "ADMIN_TOKEN"!!
  • /!\ Cambiar 'domain.tld' y 'subdomain.domain.tld' por el dominio que vayas a usar
  1. Levantar el contenedor en modo 'detached': docker-compose up -d
    1. Tanto en portainer como lanzando docker ls se debe ver el contenedor de vaultwarden levantado o esperando a ser reiniciado.

Extras

  1. Extensión para Chrome: https://chrome.google.com/webstore/detail/bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb/related
  2. App para Android: https://play.google.com/store/apps/details?id=com.x8bit.bitwarden&hl=en_US&gl=US

** Se tiene que configurar las aplicaciones para que ataquen contra el servidor casero (En la pantalla de login el icono de engranaje en la esquina superior izquierda).

Exponer la RPI a internet

Depende de cada router... mirar información sobre como abrir los puertos 80 y 443 (no se necesitan abrir más) apuntando a la rpi.

Incrementar tamaño archivo SWAP

Por defecto se emplean 100MiB para el archivo swap. Se aumentará a 2GiB (el máximo habilitado, aunque se puede llegar a cambiar):

  1. Parar el uso del archivo swap: sudo dphys-swapfile swapoff
  2. Modificar el tamaño: sudo nano /etc/dphys-swapfile
    1. CONF_SWAPSIZE=2048
  3. Aplicar los cambios: sudo dphys-swapfile setup
  4. Iniciar el uso del archivo swap: sudo dphys-swapfile swapon
  5. Reiniciar: sudo reboot

ZRAM SWAP

ZRAM SWAP habilita un espacio comprimido (por defecto usando LZ4) de swap en la memoria. Esto nos provee una partición swap de acceso más rápido.

  1. Clonar el repositorio: git clone https://github.com/foundObjects/zram-swap
  2. Instalar: sudo ./install.sh
    1. Verificar Instalación: sudo cat /proc/swaps

Ajustar parámetros del kernel

Ya que usamos ZRam, vamos a indicarle al kernel que trabaje un poco más intensamente con la swap.

  1. Editar el archivo sysctl: sudo nano /etc/sysctl.conf
  2. Añadir:
vm.vfs_cache_pressure=500
vm.swappiness=100
vm.dirty_background_ratio=1
vm.dirty_ratio=50
  1. Aplicar cambios: sudo sysctl --system

Overclocking

En este apartado se verá como hacer que la rpi rinda más. Para ello es necesario asegurarse de que la rpi está bien ventilada! y que la fuente de alimentación pueda ofrecer toda la energia que requiere tanto la rpi como lo que tengáis conectado a ella.

  • Si la rpi supera los 80º empezará con el 'thermal throttling'
  • Si te pasas de hercios (no llega el voltaje), el procesador entrará a trabajar a 700MHz
  • Lo máximo que aconsejan poner la rpi es a 2.0GHz - 1.3V
  • Con los valores por defecto la rpi funciona a 1.5GHz - 1.2V

Explicando parámetros usados para overclocking

gpu_freq -> Indica la frecuencia de la GPU en MHz (No aconsejan jugar con este valor, las ventajas son residuales) arm_freq -> Indica la frecuencia de la CPU en MHz over_voltage -> Indica el voltaje:

  • Los valores posibles son de -16 a 8 (0.8V a 1.4V)
  • Cada paso es 0.025V

Poniendola a 1.75GHz - 1.25V

  1. Editar el archivo sudo nano /boot/config.txt
    1. Buscar la linea comentada #arm_freq=800
    2. Descomentar y dejarla a arm_freq=1750
    3. Añadir la linea over_voltage=2
  2. Reiniciar: sudo reboot

Comprobando que está como queremos

  1. Para ver a que frecuencia está configurado ejecuta vcgencmd measure_clock arm, debería de empezar por 1750...
  2. Para comprobar a que frecuencia está trabajando: cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq

Costes

Vamos a ver a cuanto nos sale tener la rpi conectada 24/7. Voy hacer el caso de máximo consumo... pero ten en cuenta que el consumo real de tu rpi dependerá de varios factores, como por ejemplo, la temperatura ambiente.

Datos de la RPI4 (B)

Info: https://www.raspberrypi.org/documentation/hardware/raspberrypi/power/README.md

  • Voltaje: 5.1V
  • Amperios máximo: 3.0A
  • Amperios máximo placa: 1.8A
  • Amperios máximo periféricos: 1.2A
  • Voltaje mínimo: 4.63V (+/- 5%)

Coste energético

En este ejemplo usaré un precio medio de 0.28€/kWh (https://tarifaluzhora.es/info/precio-kwh) y un consumo de 15.3W (el tope que da el adaptador de corriente oficial).

  • Consumo mes: 3.13€
  • Consumo año: 37.53€

Ahora le vamos a añadir un DAS (Terramaster D5-300C), pondré un consumo de 45.6W (el que dice el fabricante que se consume bajo carga):

  • Consumo mes: 9.32€
  • Consumo año: 111.85€

Nos quedan los siguientes totales máximos:

  • Consumo mes: 12.45€
  • Consumo año: 149.38€

Calculadora online: https://www.calculat.org/es/energia/consumo-de-electricidad.html

Observaciones

La gestión de la energía es importante, como hemos visto en el tema de 'Costes' la energía que reserva la rpi4b para los perifericos puede resultar un tanto escasa. Por poner un ejemplo, tener dos dicos duros alimentados por usb escribiendo/leyendo puede resultar en que algún disco no reciba todo lo que necesita y se desconecte. Para solucinar este tipo de "problemas" es mejor usar perifericos auto-alimentados, en el caso de los discos duros sería una buena opción usar un DAS.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment