[{"content":"Configuración de clientes en Authelia Ya tenemos configurado nuestro sistema de autenticación a través de Authelia que dejamos bastante detallado en el post de Owncloud oCIS.\nAñadir cliente nuevo en Authelia Vamos a añadir otro cliente para Immich.\nSiguiendo la documentación oficial de Authelia creamos un nuevo cliente modificando nuestro fichero configuration.yml:\nidentity_providers: oidc: ## The other portions of the mandatory OpenID Connect 1.0 configuration go here. ## See: https://www.authelia.com/c/oidc clients: - client_id: \u0026#39;immich\u0026#39; client_name: \u0026#39;immich\u0026#39; client_secret: \u0026#39;$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng\u0026#39; # The digest of \u0026#39;insecure_secret\u0026#39;. public: false authorization_policy: \u0026#39;two_factor\u0026#39; require_pkce: false pkce_challenge_method: \u0026#39;\u0026#39; redirect_uris: - \u0026#39;https://immich.midominio.com/auth/login\u0026#39; - \u0026#39;https://immich.midominio.com/user-settings\u0026#39; - \u0026#39;app.immich:///oauth-callback\u0026#39; scopes: - \u0026#39;openid\u0026#39; - \u0026#39;profile\u0026#39; - \u0026#39;email\u0026#39; response_types: - \u0026#39;code\u0026#39; grant_types: - \u0026#39;authorization_code\u0026#39; access_token_signed_response_alg: \u0026#39;none\u0026#39; userinfo_signed_response_alg: \u0026#39;none\u0026#39; token_endpoint_auth_method: \u0026#39;client_secret_post\u0026#39; En este punto, la única parte complicada es el client_secret. Vamos a generarlo:\n# Generamos una cadena aleatoria openssl rand -base64 48 #Resultado (lo añadimos en web de Immich) h9JrBOoitgYvBjDEmGH7gx10e6bEnawGedXOv7+rdfbEqgqfRr56hH+eacu977Mf # Hasheamos la cadena que hemos generado docker exec authelia authelia crypto hash generate pbkdf2 --variant sha512 --password \u0026#39;h9JrBOoitgYvBjDEmGH7gx10e6bEnawGedXOv7+rdfbEqgqfRr56hH+eacu977Mf\u0026#39; #Resultado (lo añadimos en fichero configuration.yml) Digest: $pbkdf2-sha512$310000$GHkth/w7Mv2nuZ/Wyp5.6Q$Z9r9wGFaubza/kqmyChgkzsBwyhvtT/blW633ytwJuJPdt4w8gqszDLAIGj8k4qnx5O05SuuGhokTU0tRFrEgA El Digest es el que añadimos en nuestro fichero configuration.yml:\noidc: clients: - client_id: \u0026#39;immich\u0026#39; client_name: \u0026#39;immich\u0026#39; client_secret: \u0026#39;$pbkdf2-sha512$310000$GHkth/w7Mv2nuZ/Wyp5.6Q$Z9r9wGFaubza/kqmyChgkzsBwyhvtT/blW633ytwJuJPdt4w8gqszDLAIGj8k4qnx5O05SuuGhokTU0tRFrEgA\u0026#39; Y la cadena en texto claro va en el apartado client_secret dentro de immich:\nWeb Immich \u0026mdash;\u0026gt; Administración \u0026mdash;\u0026gt; OAuth\nUna vez configurado, es IMPORTANTE reiniciar nuestro contenedor de Authelia para que detecte el nuevo cliente y probamos el acceso:\ndocker restart authelia MUY MUY IMPORTANTE - He desactivado el inicio de sesión por Usuario y Contraseña en Immich. Antes de desactivarlo es totalmente imprescindible problar el acceso a través de Authelia para no llevarnos sorpresas.\nDe todas formas, si hubiera algún problema con el acceso a través de Authelia podemos reactivar el acceso por Usuario y Contraseña con el siguiente comando:\ndocker exec -it immich_server immich-admin enable-password-login La verdad es que la documentación de Immich es de lo mejorcito que he visto y está todo muy detallado.\nFuentes:\nDocumentación Immich\nDocumentación Authelia\n","permalink":"https://blog.lasnotasdenoah.com/posts/authelia/","summary":"\u003ch3 id=\"configuración-de-clientes-en-authelia\"\u003eConfiguración de clientes en Authelia\u003c/h3\u003e\n\u003cp\u003eYa tenemos configurado nuestro \u003ca href=\"https://blog.lasnotasdenoah.com/posts/owncloud/\"\u003esistema de autenticación a través de Authelia\u003c/a\u003e que dejamos bastante detallado en el post de Owncloud oCIS.\u003c/p\u003e\n\u003ch3 id=\"añadir-cliente-nuevo-en-authelia\"\u003eAñadir cliente nuevo en Authelia\u003c/h3\u003e\n\u003cp\u003eVamos a añadir otro cliente para \u003ca href=\"https://immich.app/\"\u003eImmich\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eSiguiendo la \u003ca href=\"https://www.authelia.com/integration/openid-connect/clients/immich/\"\u003edocumentación oficial de Authelia\u003c/a\u003e creamos un nuevo cliente modificando nuestro fichero configuration.yml:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eidentity_providers:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  oidc:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e## The other portions of the mandatory OpenID Connect 1.0 configuration go here.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e## See: https://www.authelia.com/c/oidc\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    clients:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      - client_id: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;immich\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        client_name: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;immich\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        client_secret: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng\u0026#39;\u003c/span\u003e  \u003cspan style=\"color:#75715e\"\u003e# The digest of \u0026#39;insecure_secret\u0026#39;.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        public: false\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        authorization_policy: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;two_factor\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        require_pkce: false\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        pkce_challenge_method: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        redirect_uris:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          - \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;https://immich.midominio.com/auth/login\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          - \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;https://immich.midominio.com/user-settings\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          - \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;app.immich:///oauth-callback\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        scopes:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          - \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;openid\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          - \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;profile\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          - \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;email\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        response_types:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          - \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;code\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        grant_types:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          - \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;authorization_code\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        access_token_signed_response_alg: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;none\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        userinfo_signed_response_alg: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;none\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        token_endpoint_auth_method: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;client_secret_post\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eEn este punto, la única parte complicada es el client_secret. Vamos a generarlo:\u003c/p\u003e","title":"Authelia"},{"content":"Owncloud oCIS oCIS está escrito en Go, lo que lo hace extremadamente rápido y ligero, funcionando como un binario único. Nextcloud utiliza PHP, lo que facilita su personalización pero requiere más recursos y optimización del servidor para grandes volúmenes.\nMientras que oCIS se centra en ser un especialista en almacenamiento y sincronización a gran escala, Nextcloud se posiciona como una \u0026ldquo;Content Collaboration Platform\u0026rdquo; completa, incluyendo chat, videollamadas y oficina en línea de forma nativa.\nLlevo varios años usando Nextcloud y nunca he usado ninguna de sus aplicaciones. Tengo la sensación que es lento y por eso vamos a probar Owncloud.\nEsquema inicial Petición a cloud.midominio.com \u0026mdash;\u0026gt; VPS con traefik + lldap + authelia \u0026mdash;\u0026gt; NAS con Owncloud\nDocker-compose Si dejamos que docker cree las carpetas nos dará errores de permisos, por tanto las creamos de forma manual:\n# Ficheros de configuración en appdata como siempre mkdir -p /mnt/user/appdata/ocis/config # Almacenamiento de datos # Creamos el recurso compartido en Unraid y después los directorios necesarios mkdir -p /mnt/user/Ocis-Files/ocis-data mkdir -p /mnt/user/Ocis-Files/thumbnails # Cambiamos el usuario de los directorios porque sino Ocis nos dará problemas de permisos. chown -Rfv 1000:1000 /mnt/user/appdata/ocis chown -Rfv 1000:1000 /mnt/user/Ocis-Files # Como unraid deja permisos 777 vamos a cambiarlos tambien chmod -R 755 /mnt/user/Ocis-Files chmod -R 755 /mnt/user/appdata/ocis Docker-compose:\nservices: ocis: image: owncloud/ocis:latest container_name: ocis restart: unless-stopped user: \u0026#34;1000:1000\u0026#34; entrypoint: - /bin/sh command: [\u0026#34;-c\u0026#34;, \u0026#34;ocis init || true; ocis server\u0026#34;] environment: # --- Dominio público (el que Traefik expone en el VPS) --- OCIS_URL: https://cloud.midominio.com OCIS_LOG_LEVEL: info # Cambiar a debug si hay problemas OCIS_LOG_COLOR: true OCIS_LOG_PRETTY: true # --- Deshabilita TLS interno (Traefik termina TLS) --- PROXY_TLS: \u0026#34;false\u0026#34; OCIS_INSECURE: \u0026#34;true\u0026#34; # Configuración para que no se cierre sesión tan a menudo OCIS_ACCESS_TOKEN_LIFETIME: 24h OCIS_REFRESH_TOKEN_LIFETIME: 2160h volumes: - /mnt/user/appdata/ocis/config:/etc/ocis - /mnt/user/Ocis-Files/ocis-data:/var/lib/ocis - /mnt/user/Ocis-Files/thumbnails:/var/lib/ocis-thumbnails ports: # Solo escucha en la IP de Tailscale, no expone al exterior - \u0026#34;100.105.100.10:9200:9200\u0026#34; healthcheck: test: [\u0026#34;CMD\u0026#34;, \u0026#34;curl\u0026#34;, \u0026#34;-f\u0026#34;, \u0026#34;http://localhost:9200/health\u0026#34;] interval: 30s timeout: 10s retries: 3 networks: default: name: cloud external: true Después de configurar Authelia añadiremos las siguientes variables al compose:\nenvironment: # --- OIDC / Authelia --- OCIS_EXCLUDE_RUN_SERVICES: \u0026#34;idp\u0026#34; WEB_OIDC_CLIENT_ID: \u0026#39;ocis\u0026#39; PROXY_OIDC_ISSUER: \u0026#39;https://auth.midominio.com\u0026#39; PROXY_OIDC_REWRITE_WELLKNOWN: \u0026#39;true\u0026#39; PROXY_OIDC_ACCESS_TOKEN_VERIFY_METHOD: \u0026#39;jwt\u0026#39; PROXY_AUTOPROVISION_ACCOUNTS: \u0026#39;true\u0026#39; PROXY_AUTOPROVISION_CLAIM_USERNAME: \u0026#39;preferred_username\u0026#39; PROXY_AUTOPROVISION_CLAIM_EMAIL: \u0026#39;email\u0026#39; PROXY_AUTOPROVISION_CLAIM_DISPLAYNAME: \u0026#39;name\u0026#39; PROXY_AUTOPROVISION_CLAIM_GROUPS: \u0026#39;groups\u0026#39; Si queremos usar notificaciones por mail:\n# Email SMTP NOTIFICATIONS_SMTP_HOST: \u0026#34;${SMTP_HOST}\u0026#34; NOTIFICATIONS_SMTP_PORT: \u0026#34;${SMTP_PORT}\u0026#34; NOTIFICATIONS_SMTP_SENDER: \u0026#34;${SMTP_SENDER}\u0026#34; NOTIFICATIONS_SMTP_USERNAME: \u0026#34;${SMTP_USERNAME}\u0026#34; NOTIFICATIONS_SMTP_PASSWORD: \u0026#34;${SMTP_PASSWORD}\u0026#34; NOTIFICATIONS_SMTP_AUTHENTICATION: \u0026#34;${SMTP_AUTHENTICATION}\u0026#34; NOTIFICATIONS_SMTP_ENCRYPTION: \u0026#34;${SMTP_ENCRYPTION}\u0026#34; NOTIFICATIONS_SMTP_INSECURE: \u0026#34;${SMTP_INSECURE}\u0026#34; Después de añadir nuestras variables, modificamos el fichero .env:\n# Datos SMTP de Gmail SMTP_HOST=smtp.gmail.com SMTP_PORT=587 #SMTP_SENDER=oCIS notifications \u0026lt;mi_correo@gmail.com\u0026gt; SMTP_SENDER=mi_correo@gmail.com SMTP_USERNAME=mi_correo@gmail.com SMTP_PASSWORD=xxxx xxxx xxxx xxxx SMTP_AUTHENTICATION=login SMTP_ENCRYPTION=starttls SMTP_INSECURE=false Traefik Por último, creamos nuestro fichero estático de traefik para nuestro dominio:\nImportante: Durante subidas grandes, Traeﬁk puede cerrar la conexión por timeout. En tu ocis.yml hay que tenerlo en cuenta:\nserversTransport: ocis-transport responseHeaderTimeout: 0s # 0 = sin límite # cat ocis.yml http: routers: cloud: rule: \u0026#34;Host(`cloud.midominio.com`)\u0026#34; service: cloud entryPoints: - websecure tls: {} # o simplemente ‘tls: true’ en v3 middlewares: - geoblock-es - crowdsec-bouncer-noappsec - ocis-headers - ocis-upload-buffer # ← AÑADIR services: cloud: loadBalancer: servers: - url: \u0026#34;http://100.105.100.10:9200\u0026#34; passHostHeader: true responseForwarding: flushInterval: 100ms # ← AÑADIR para streaming middlewares: ocis-upload-buffer: buffering: maxRequestBodyBytes: 0 # sin límite en subidas memRequestBodyBytes: 2097152 retryExpression: \u0026#34;IsNetworkError() \u0026amp;\u0026amp; Attempts() \u0026lt; 3\u0026#34; ocis-headers: headers: customRequestHeaders: X-Forwarded-Proto: \u0026#34;https\u0026#34; X-Real-IP: \u0026#34;\u0026#34; customResponseHeaders: X-Frame-Options: \u0026#34;SAMEORIGIN\u0026#34; Content-Security-Policy: \u0026#34;default-src \u0026#39;self\u0026#39; https://auth.midominio.com; script-src \u0026#39;self\u0026#39; \u0026#39;unsafe-inline\u0026#39; \u0026#39;unsafe-eval\u0026#39;; style-src \u0026#39;self\u0026#39; \u0026#39;unsafe-inline\u0026#39;; img-src \u0026#39;self\u0026#39; data: blob:; connect-src \u0026#39;self\u0026#39; https://auth.midominio.com; frame-ancestors \u0026#39;self\u0026#39;\u0026#34; Primer arranque Arrancamos nuestro compose desde Unraid y verificamos los logs para ver nuestra pass de administrador:\ndocker logs owncloud ========================================= generated OCIS Config ========================================= configpath : /etc/ocis/ocis.yaml user : admin password : #XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXxx 2026-05-09T07:07:41Z WRN starting service nats line=github.com/owncloud/ocis/v2/services/nats/pkg/command/server.go:97 service=nats 2026-05-09T07:07:41Z INF Starting nats-server line=github.com/owncloud/ocis/v2/services/nats/pkg/logging/nats.go:21 service=nats Usuarios Tenemos dos opciones. Accedemos como administrador y vamos creando los usuarios: O bien, usamos un sistema centralizado de usuarios Ldap y nos logueamos a través de Authelia. Si el usuario está en Ldap y no está en Owncloud oCIS se genera automáticamente. Optaremos por la opción 2.\nConfiguración de LLDAP Docker compose:\nservices: lldap: container_name: lldap hostname: lldap image: lldap/lldap:stable restart: unless-stopped expose: - 3890 # LDAP - 17170 # Web UI environment: LLDAP_LDAP_BASE_DN: \u0026#34;${LLDAP_LDAP_BASE_DN}\u0026#34; LLDAP_JWT_SECRET: \u0026#34;${JWT_SECRET}\u0026#34; LLDAP_LDAP_USER_PASS: \u0026#34;${LDAP_USER_PASS}\u0026#34; volumes: - ./data:/data networks: - infra_network networks: infra_network: external: true Generamos las llaves aleatorias:\n# JWT_SECRET tr -cd \u0026#39;[:alnum:]\u0026#39; \u0026lt; /dev/urandom | fold -w \u0026#34;64\u0026#34; | head -n 1 #mIyud6Bz6TKGPDxV3b1SlixrRdIdemNu3LmgvdZ3f9bKyNCyMvyyQ7hlXCfyoYq6 # LDAP_USER_PASS tr -cd \u0026#39;[:alnum:]\u0026#39; \u0026lt; /dev/urandom | fold -w \u0026#34;20\u0026#34; | head -n 1 #TE7z8T3Ii1rm4u5NUkRC Y las pasamos a nuestro fichero .env:\nLLDAP_LDAP_BASE_DN=dc=midominio,dc=com JWT_SECRET=mIyud6Bz6TKGPDxV3b1SlixrRdIdemNu3LmgvdZ3f9bKyNCyMvyyQ7hlXCfyoYq6 LDAP_USER_PASS=TE7z8T3Ii1rm4u5NUkRC Arrancamos nuestro contenedor:\ndocker compose up -d # verificamos logs docker logs lldap Ahora podremos acceder a nuestro ldap desde https://lldap.midominio.com.\nEn mi caso he creado los usuarios necesarios y un grupo llamado ocis.\nConfiguración de Authelia-redis Vamos a configurar un contenedor Redis.\nRedis es un sistema de almacenamiento de datos en memoria que Authelia puede utilizar como proveedor de almacenamiento de sesiones. Al usar un servicio externo para los datos de sesión, Authelia se puede reiniciar sin que los usuarios tengan que volver a autenticarse y lo que más importante, no se cerrarán nuestras sesiones al poco tiempo o pocos días de iniciar (por ejemplo en aplicación de escritorio o de Android).\nDocker compose:\nservices: redis: container_name: authelia-redis hostname: authelia-redis image: redis:latest restart: unless-stopped command: redis-server --save 60 1 --appendonly yes # ← persiste en disco expose: - 6379 volumes: - ./data:/data networks: - infra_network networks: infra_network: external: true Arrancamos el contenedor y debe funcionar sin problemas.\ndocker compose up -d Configuración de Authelia Este es el más complejo de configurar y el corazón de nuestro sistema de login.\nOcis redirige la autenticación hacia Authelia, que a su vez se conecta con ldap y verifica que el usuario esté activo tenga los permisos necesarios.\nDocker-compose:\nservices: authelia: image: authelia/authelia:latest container_name: authelia restart: unless-stopped volumes: - ./config:/config environment: - TZ=Europe/Madrid - AUTHELIA_IDENTITY_VALIDATION_RESET_PASSWORD_JWT_SECRET=${AUTHELIA_JWT_SECRET} - AUTHELIA_SESSION_SECRET=${AUTHELIA_SESSION_SECRET} - AUTHELIA_STORAGE_ENCRYPTION_KEY=${AUTHELIA_STORAGE_ENCRYPTION_KEY} - AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PASSWORD=${LLDAP_ADMIN_PASSWORD} networks: - infra_network networks: infra_network: external: true Vamos a generar los secretos.\nEjecutamos cada línea y copiamos el resultado al fichero .env:\n# Ejecuta cada línea y copia el resultado: echo \u0026#34;AUTHELIA_JWT_SECRET=$(openssl rand -hex 32)\u0026#34; echo \u0026#34;AUTHELIA_SESSION_SECRET=$(openssl rand -hex 32)\u0026#34; echo \u0026#34;AUTHELIA_STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)\u0026#34; echo \u0026#34;AUTHELIA_OIDC_HMAC_SECRET=$(openssl rand -base64 48)\u0026#34; # LLDAP_ADMIN_PASSWORD echo \u0026#34;LLDAP_ADMIN_PASSWORD=Pass_generada_en_la_conf_de_lldap\u0026#34; Y los añadimos a nuestro fichero .env:\n# cat .env: AUTHELIA_JWT_SECRET=c8207bb043e77a53ba096497877cc13a9af82d7e229454cd2a4dd04c956653b0 AUTHELIA_SESSION_SECRET=904c93860b0e66e43124d0ad62c52ec990c099177dfbfd3c29d681b7888c0709 AUTHELIA_STORAGE_ENCRYPTION_KEY=05990b793ee23f896d151121645c2f57cf0f594e881f96c5cc1936fbec7e4546 LLDAP_ADMIN_PASSWORD=6LbWYgj9sn3EZyIP6KTC AUTHELIA_OIDC_HMAC_SECRET=zjGQ1ZGejeRJghaEqcQA2iykIE9et6INn6ZNLrWTigl3ORNBYczgXZomETXTFXrY Docker-compose de oCIS. Añadimos las siguientes variables de entorno:\nenvironment: # --- OIDC / Authelia --- OCIS_EXCLUDE_RUN_SERVICES: \u0026#34;idp\u0026#34; WEB_OIDC_CLIENT_ID: \u0026#39;ocis\u0026#39; PROXY_OIDC_ISSUER: \u0026#39;https://auth.midominio.com\u0026#39; PROXY_OIDC_REWRITE_WELLKNOWN: \u0026#39;true\u0026#39; PROXY_OIDC_ACCESS_TOKEN_VERIFY_METHOD: \u0026#39;jwt\u0026#39; PROXY_AUTOPROVISION_ACCOUNTS: \u0026#39;true\u0026#39; PROXY_AUTOPROVISION_CLAIM_USERNAME: \u0026#39;preferred_username\u0026#39; PROXY_AUTOPROVISION_CLAIM_EMAIL: \u0026#39;email\u0026#39; PROXY_AUTOPROVISION_CLAIM_DISPLAYNAME: \u0026#39;name\u0026#39; PROXY_AUTOPROVISION_CLAIM_GROUPS: \u0026#39;groups\u0026#39; Al principio tenía configurado PROXY_OIDC_ACCESS_TOKEN_VERIFY_METHOD mal, lo que provocaba que con cada fichero que se subia, se hacía una llamada al endpoint userinfo de Authelia. Para solucionarlo tenemos que hacer el siguiente cambio:\n# Debemos cambiar en el docker-compose de oCIS: PROXY_OIDC_ACCESS_TOKEN_VERIFY_METHOD: \u0026#39;none\u0026#39; # por PROXY_OIDC_ACCESS_TOKEN_VERIFY_METHOD: \u0026#39;jwt\u0026#39; # y añadir a cada cliente de Authelia en configuration.yml lo siguiente: clients: - client_id: ocis # ...resto igual... access_token_signed_response_alg: \u0026#39;RS256\u0026#39; # ← AÑADIR Fichero de configuración de Authelia Aquí añadimos la configuración base y los clientes necesarios:\n╰─ cat config/configuration.yml --- ############################################################################### # AUTHELIA - CONFIGURACIÓN PRINCIPAL (compatible 4.38+) # LLDAP + SQLite + TOTP + Traefik (ficheros) ############################################################################### theme: dark server: address: tcp://0.0.0.0:9091/ log: level: debug # level: debug # Descomenta para depurar totp: issuer: midominio.com period: 30 skew: 1 ############################################################################### # AUTENTICACIÓN - LLDAP ############################################################################### authentication_backend: password_reset: disable: false refresh_interval: 1m ldap: implementation: custom address: ldap://lldap:3890 timeout: 5s start_tls: false base_dn: dc=midominio,dc=com additional_users_dn: ou=people users_filter: (\u0026amp;({username_attribute}={input})(objectClass=person)) additional_groups_dn: ou=groups groups_filter: (member={dn}) user: uid=admin,ou=people,dc=midominio,dc=com password: ${LLDAP_ADMIN_PASSWORD} attributes: username: uid group_name: cn mail: mail display_name: displayName ############################################################################### # CONTROL DE ACCESO ############################################################################### access_control: default_policy: deny rules: - domain: auth.midominio.com policy: bypass - domain: cloud.midominio.com policy: two_factor # - domain: blog.midominio.com # policy: one_factor # - domain: outline.midominio.com # policy: two_factor # subject: # - \u0026#34;group:admins\u0026#34; ############################################################################### # SESIONES ############################################################################### session: secret: ${AUTHELIA_SESSION_SECRET} cookies: - name: authelia_session domain: midominio.com authelia_url: https://auth.midominio.com expiration: 1y # sesión dura 1 año inactivity: 6M # se cierra solo si no usas nada en 6 meses remember_me: 1y # cookie remember_me dura 1 año redis: host: authelia-redis port: 6379 ############################################################################### # ALMACENAMIENTO - SQLite ############################################################################### storage: encryption_key: ${AUTHELIA_STORAGE_ENCRYPTION_KEY} local: path: /config/db.sqlite3 ############################################################################### # NOTIFICADOR - Solo uno activo a la vez # Opción A: filesystem (para pruebas, sin SMTP) \u0026lt;- ACTIVO AHORA # Opción B: SMTP (descomenta cuando tengas SMTP listo) ############################################################################### notifier: disable_startup_check: false filesystem: filename: /config/notifications.txt # --- Opción B: SMTP (comenta el filesystem de arriba si activas esto) --- # notifier: # smtp: # username: tu@email.com # password: ${AUTHELIA_SMTP_PASSWORD} # host: smtp.gmail.com # port: 587 # sender: \u0026#34;Authelia \u0026lt;authelia@midominio.com\u0026gt;\u0026#34; # subject: \u0026#34;[Authelia] {title}\u0026#34; # startup_check_address: tu@email.com ############################################################################### # JWT ############################################################################### identity_validation: reset_password: jwt_secret: ${AUTHELIA_JWT_SECRET} ############################################################################### # OIDC - Provider para oCIS ############################################################################### identity_providers: oidc: lifespans: access_token: 24h refresh_token: 90d authorize_code: 1m id_token: 24h hmac_secret: ${AUTHELIA_OIDC_HMAC_SECRET} cors: endpoints: - authorization - token - revocation - introspection - userinfo jwks: - key: | -----BEGIN PRIVATE KEY----- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDOI9Y/nQssjJSD /sYc3/agPGpyPWKoFAJw3iGQc8+cxpGS6QELAGASYBPbq11xQOMbMe5YEe2U3zJy n/b8heXqRqik79FC3YiO4YaUDz1OWzUnpEcBWeDmEqKSTGPoR0EEiu9u7orM0kX8 j3uLGz4uHPWSrrTZtoipGADm4yrHk3/GSH9ubC2s8zQVJ47l/0VX7pzNDakCBMDJ RlNTGb9Y5b1/aMej6LGkZXAzchdnj3ZnzcVgC2kKQg21fG5xx3SPIZ56BMXW8On0 FeHi/OPPSYhhbaMVav6uWckcCgab469tjcitk3eLFfyWSRxV29KlH5gKu2yvI6Ia 4R0ynbb/AgMBAAECggEAFDxlYFpIygdE3w5IIXaE7ebwZiWLhUdtk+nibp1H0LKX gM35ybwwMi2XVXWllyQRB07oAGJGKdqdR65XXyO/1bc4//QA3WkE6k3OWcODN6lx duJEDChoEP3cUrNIDXnNMqZ26bNmEcRElY36SUYT3Q//tXYMD+FA2iSelgvP28Z8 PzxxJJ0KJ2Ay9muenR+6rJjT7eaE2Y4oiASTrHjG1A04WHHKQ4ip3VznRaqRMzO6 HsjdeCwu2WCsuQjwSkbUd3YfjSm4Fyky8abUNUbGyyVJXMJ9hp8A9u7dR6l5YsJ1 AG1Kd/SNgp9H7lf+cyGplMFHZBnRruMfWygHx9j2DQKBgQD5km3p8wFu9kUk7h8/ ATchPvWAnv10YZDiXtKdSl7FVdDx+yW0c+adc8Ujomfu+C0H/os8lFGCwDvdN33D ngZTlcnGZUJeXNbCT/aXqzA/TIt+8PnHjmRwSmNPxaUbf6+otEqM6Fspgz4kAn1s WFPMQGCwnEoJFLP2z938aKYB5QKBgQDTcwka8PltbCfoaRVcxsj8EvHOqBYvLB8H iJcEwpRd4E0k5vXAWSLAfK1ns6UcucIT54ocCyXpzu10crUZcIdrz4S6hjwOqqgM RTVHyVaT67CWQqNlsyIwKozWoMtrgjxFzFTEES51LcDI2sl8u8+U+HVIlnH0asDq A3iisaAXEwKBgQDPquWk5x0JPQkaCr6bSaKbGm1kYmeaYNkTVD3CvjCP2bGsuQON 3WdHGx8uYKRFN+MYpNktRmlw+A6YK+WNUcAH6zrjyDxqkqvtMmaJm9vgwAvPTCs7 vyOaQHvU1Cxn7l63bZYfG/VHXLrncd71uaW47tTGALamScDaHeukbVu9dQKBgDFR pZAJIMRq86v7xqXLH9nbuVbQUcxS6DHjpAXSNLToulWfITbqE3b+HZwQhLR8h04J NWdxGji8sRn2H1N9sbhtwLGY2a06FNQ32EOULIN398o0ZNQ1wgWmBw+QlaHP0Ksf C65nq4RdVZgDn/dd/v7qLMDvhkjSFYj/okWgVIzNAoGBAPh+DsV/Lo9JDsFhUiHq KEEhOS5GaljhqTLhRt8QA56vIXsWc74t+leP9/pZHWa3p06kbeqzKCV2Xa+3wLUH AyCavZboq2NLQZVvE3D6TlST3gSY6bRp9pzRe/GC89VgTjQWU2/PcICgtKxbD8wS AnlBZr6T5/VrSs8oOOBtSGE6 -----END PRIVATE KEY----- clients: - client_id: ocis client_name: ownCloud Infinite Scale public: true authorization_policy: two_factor redirect_uris: - https://cloud.midominio.com/oidc-callback.html - https://cloud.midominio.com/ scopes: - \u0026#39;openid\u0026#39; - \u0026#39;profile\u0026#39; - \u0026#39;email\u0026#39; - \u0026#39;groups\u0026#39; - \u0026#39;offline_access\u0026#39; response_types: - code grant_types: - \u0026#39;authorization_code\u0026#39; - \u0026#39;refresh_token\u0026#39; access_token_signed_response_alg: \u0026#39;RS256\u0026#39; userinfo_signed_response_alg: none Clave JWKS\nopenssl genrsa -out /tmp/oidc_private.pem 2048 cat /tmp/oidc_private.pem Y la añadimos a nuestro fichero configuration.yml:\njwks: - key: | -----BEGIN PRIVATE KEY----- MIIEvgIBADA... (clave generada) -----END PRIVATE KEY----- Es muy importante pegar la clave JWKS con exactamente 10 espacios de indentación en cada línea del PEM.\nConfiguración de usuario de Authelia Accedemos a nuestro authelia desde https://auth.midominio.com con nuestro usuario de ldap. Según nuestro fichero de configuración de authelia, la política de acceso a cloud.midominio.com es de doble factor, por lo que debemos configurar uno.\n- domain: cloud.midominio.com policy: two_factor En mi caso, he elegido passkey como doble factor, porque me resulta mucho más sencillo a la hora de acceder desde mi app móvil. En Credenciales WebAuthn se crean las passkeys, aunque podemos usar OTP si queremos una aplicación tipo Google Authenticator o Aegis.\nMUY IMPORTANTE - MUY IMPORTANTE - MUY IMPORTANTE Definir una política adecuada de backups de la base de Authelia para no perder acceso a nuestras aplicaciones.\nClientes de escritorio y Android para oCIS Clientes para aplicación de escritorio y Android. Estas aplicaciones llevan el client_id fijo, por lo que debemos añadirlo con los datos necesarios, siguiendo las instrucciones de la web de Authelia:\n- client_id: \u0026#39;xdXOt13JKxym1B1QcEncf2XDkLAexMBFwiT9j6EfhhHFJhs2KM9jbjTmf8JBXE69\u0026#39; client_name: \u0026#39;ownCloud Infinite Scale (Desktop Client)\u0026#39; # client_secret: \u0026#39;UBntmLjC2yYCeHwsyj73Uwo9TAaecAetRwMw0xYcvNL9yRdLSUi0hUAHfvCHFeFh\u0026#39; client_secret: \u0026#39;$argon2id$v=19$m=65536,t=3,p=4$OVq2YVWmLGibRRqH98qtwA$tITLZACNq2j1f43vPH6fxkdP06rYhR3bLRXCG0mvm0U\u0026#39; public: false authorization_policy: \u0026#39;two_factor\u0026#39; require_pkce: true pkce_challenge_method: \u0026#39;S256\u0026#39; scopes: - \u0026#39;openid\u0026#39; - \u0026#39;offline_access\u0026#39; - \u0026#39;groups\u0026#39; - \u0026#39;profile\u0026#39; - \u0026#39;email\u0026#39; redirect_uris: - \u0026#39;http://127.0.0.1\u0026#39; - \u0026#39;http://localhost\u0026#39; response_types: - \u0026#39;code\u0026#39; grant_types: - \u0026#39;authorization_code\u0026#39; - \u0026#39;refresh_token\u0026#39; access_token_signed_response_alg: \u0026#39;RS256\u0026#39; # ← AÑADIR userinfo_signed_response_alg: \u0026#39;none\u0026#39; token_endpoint_auth_method: \u0026#39;client_secret_basic\u0026#39; - client_id: \u0026#39;e4rAsNUSIUs0lF4nbv9FmCeUkTlV9GdgTLDH1b5uie7syb90SzEVrbN7HIpmWJeD\u0026#39; client_name: \u0026#39;ownCloud Infinite Scale (Android)\u0026#39; # client_secret: \u0026#39;dInFYGV33xKzhbRmpqQltYNdfLdJIfJ9L5ISoKhNoT9qZftpdWSP71VrpGR9pmoD\u0026#39; client_secret: \u0026#39;$argon2id$v=19$m=65536,t=3,p=4$sEHOFVA6UqdIq+3l8e7TtQ$sY7mai6PoZTV44l3DaBUdGyn4+YL8M7dIu1Um32FQyw\u0026#39; public: false authorization_policy: \u0026#39;two_factor\u0026#39; require_pkce: true pkce_challenge_method: \u0026#39;S256\u0026#39; redirect_uris: - \u0026#39;oc://android.owncloud.com\u0026#39; scopes: - \u0026#39;openid\u0026#39; - \u0026#39;offline_access\u0026#39; - \u0026#39;groups\u0026#39; - \u0026#39;profile\u0026#39; - \u0026#39;email\u0026#39; response_types: - \u0026#39;code\u0026#39; grant_types: - \u0026#39;authorization_code\u0026#39; - \u0026#39;refresh_token\u0026#39; # access_token_signed_response_alg: \u0026#39;none\u0026#39; access_token_signed_response_alg: \u0026#39;RS256\u0026#39; # ← AÑADIR userinfo_signed_response_alg: \u0026#39;none\u0026#39; token_endpoint_auth_method: \u0026#39;client_secret_post\u0026#39; Al arrancar Authelia muestra warning por los client_secret de la aplicación de escritorio y de Android. No pasa nada por estar en texto plano porque así está definido pero podemos hashearlos para no recibir el warning:\nComando para hacer el hash:\ndocker exec authelia authelia crypto hash generate argon2 \\ --password \u0026#39;dInFYGV33xKzhbRmpqQltYNdfLdJIfJ9L5ISoKhNoT9qZftpdWSP71VrpGR9pmoD\u0026#39; # Salida Digest: $argon2id$v=19$m=65536,t=3,p=4$ZWAI68YRTbHNGjUWnLv/gA$eAltG2ylbCp+n1LTJpb4knPbcjMVwwVHBfBOUKYr01U Este comando nos sirve para hacer el hash de cualquier secret.\nInicio de oCIS Volvemos a Unraid y verificamos que las nuevas variables de entorno de Authelia de oCIS estén correctamente:\nenvironment: # --- OIDC / Authelia --- OCIS_EXCLUDE_RUN_SERVICES: \u0026#34;idp\u0026#34; WEB_OIDC_CLIENT_ID: \u0026#39;ocis\u0026#39; PROXY_OIDC_ISSUER: \u0026#39;https://auth.midominio.com\u0026#39; PROXY_OIDC_REWRITE_WELLKNOWN: \u0026#39;true\u0026#39; PROXY_OIDC_ACCESS_TOKEN_VERIFY_METHOD: \u0026#39;jwt\u0026#39; PROXY_AUTOPROVISION_ACCOUNTS: \u0026#39;true\u0026#39; PROXY_AUTOPROVISION_CLAIM_USERNAME: \u0026#39;preferred_username\u0026#39; PROXY_AUTOPROVISION_CLAIM_EMAIL: \u0026#39;email\u0026#39; PROXY_AUTOPROVISION_CLAIM_DISPLAYNAME: \u0026#39;name\u0026#39; PROXY_AUTOPROVISION_CLAIM_GROUPS: \u0026#39;groups\u0026#39; Arrancamos nuestro contenedor oCIS y hacemos el primer inicio de sesión con mi usuario.\nDespués de aceptar vemos que nos crea nuestro primer usuario y ya podemos trabajar con nuestro nuevo Owncloud oCIS.\nComandos útliles para verificar funcionamiento Para que estos comandos funcionen, es importante que en el docker-compose modifiquemos el loglevel:\n# Logs OCIS_LOG_LEVEL: error / debug / info DEBUG:\tDetalle granular. Muestra cada paso interno, variables y eventos técnicos.\tSe usa en Desarrollo y diagnóstico de errores complejos.\tImpacto en rendimiento Alto: Genera archivos muy grandes rápidamente. INFO\tConfirmación de que las cosas funcionan. Reporta eventos normales (inicio de servicios, conexiones).\tSe usa en Producción (por defecto en la mayoría de sistemas).\tImpacto en rendimiento Moderado: Es el equilibrio estándar. ERROR\tNotificación de fallos críticos. Solo registra eventos que impiden una operación.\tSistemas estables donde solo te interesa saber si algo se rompió.\tImpacto en rendimiento Bajo: Solo escribe cuando algo sale mal. Revisar notificaciones:\ndocker inspect owncloud | grep NOTIFICATIONS_SMTP Revisar logs docker:\ndocker logs ocis --tail=50 Verificar si oCIS está escuchando en el puerto:\ndocker exec ocis netstat -tlnp 2\u0026gt;/dev/null || docker exec ocis ss -tlnp Prueba de conexión directa:\ncurl -k https://100.105.100.10:9200 Listado de servicios oCIS en ejecución:\ndocker exec owncloud ocis list Verificaciones de notificaciones:\ndocker logs -f owncloud 2\u0026gt;\u0026amp;1 | grep -i -E \u0026#34;notification|smtp|email|mail|send\u0026#34; Variables de entorno que carga oCIS:\ndocker exec owncloud env Borrar las claves de redis:\n# Borrar todas docker exec authelia-redis redis-cli FLUSHALL # Borrar solo las sesiones de Authelia: docker exec authelia-redis redis-cli --scan --pattern \u0026#34;authelia:*\u0026#34; | xargs docker # Despues reiniciamos Authelia para arranque limpio: docker restart authelia Configuración de Tailscale Como uso Tailscale para conectar traefik con oCIS tengo el problema que la conexión se hace por un servidor intermedio de tailscale.\nEso se notaba mogollón al hacer la carga de datos, que era superlenta.\nPara garantizar que tenemos conexión directa vamos a abrir el puerto 41641 de tailscale.\nImportante: antes de configurar ufw tenemos que asegurarnos que el puerto 41641 está abierto en el firewall de nuestro vps:\nsudo ufw allow 41641/udp sudo ufw reload sudo ufw status numbered # Verificamos que el puerto está abierto ss -ulnp | grep 41641 ➜ ~ tailscale status 100.105.100.20 envy noecubi@ linux active; direct 192.168.10.220:41641, tx 695908 rx 783636 100.105.100.14 my-vps noecubi@ linux active; direct xx.xx.xx.xx:41641, tx 8194354248 rx 28761750016 Con esto la carga de nuestros datos aumenta de forma espectacular.\nSolución de errores Después de toda la subida de datos veo que tengo un problema importante. El contenedor ocis tiene una carga muy elevada de procesamiento.\nEso es debido a que la cola NATS estaba corrupta.\nNATS es el bus de mensajes interno de OCIS — es el sistema que usan todos los microservicios de OCIS para comunicarse entre sí.\nCuando subes un archivo, OCIS no procesa todo de golpe — publica un evento en NATS (\u0026ldquo;archivo subido\u0026rdquo;) y los distintos servicios internos (búsqueda, miniaturas, actividad, etc.) van consumiendo esos eventos a su ritmo.\nLos datos de NATS que borraste eran solo esa cola de eventos pendientes — básicamente una lista de tareas pendientes. No contenían tus archivos ni tus metadatos, por eso borrarlos fue seguro.\nEl problema fue que al subir mucha información de golpe, la cola se llenó tanto que algunos archivos de bloque (.blk) se corrompieron o eliminaron antes de ser procesados, dejando referencias rotas que hacían que OCIS entrara en bucle intentando procesar eventos que ya no existían.\nLa consecuencia práctica de haberla borrado es que algunos archivos que subimos a oCIS puede que no aparezcan en los resultados de búsqueda.\nSolución:\ndu -sh /mnt/user/Ocis-Files # Salida du: cannot access \u0026#39;/mnt/user/Ocis-Files/ocis-data/nats/jetstream/$G/streams/KV_activitylog/msgs/152413.blk\u0026#39;: No such file or directory du: cannot access \u0026#39;/mnt/user/Ocis-Files/ocis-data/nats/jetstream/$G/streams/KV_activitylog/msgs/151988.blk\u0026#39;: No such file or directory du: cannot access \u0026#39;/mnt/user/Ocis-Files/ocis-data/nats/jetstream/$G/streams/KV_activitylog/msgs/151987.blk\u0026#39;: No such file or directory du: cannot access \u0026#39;/mnt/user/Ocis-Files/ocis-data/nats/jetstream/$G/streams/KV_activitylog/msgs/151990.blk\u0026#39;: No such file or directory 33G\t/mnt/user/Ocis-Files Los errores No such file or directory en los archivos .blk de NATS JetStream indican que la cola de NATS está corrupta — hay referencias a bloques que ya no existen físicamente. Eso explica el bucle infinito y el 146% de CPU.\ndocker stop ocis # 2. Limpia SOLO los datos de NATS (no toca tus archivos). Los archivos de usuario están en otra ruta dentro de ocis-data (storages, metadata, etc.) — la carpeta nats/ solo contiene la cola de eventos, no datos de usuario. Borrarla es seguro. rm -rf /mnt/user/Ocis-Files/ocis-data/nats/ # 3. Reinicia OCIS — reconstruirá NATS desde cero docker start ocis Tras el reinicio comprobamos:\n# Que la CPU baje docker stats ocis --no-stream # Que NATS se reconstruya sin errores docker logs ocis --tail 50 | grep -i nats Podemos forzar el reindexado para garantizar que las busquedas incluyen todo:\ndocker exec ocis ocis search index --all HACER REFERENCIA A LA IMPORTANCIA DE HACER BACKUPS PARA BASE AUTHELIA\nVitaminar nuestro Owncloud Instalación de tika.\nPor defecto oCIS solo indexa nombres de archivo y contenido de texto plano. Con Apache Tika puedes activar búsqueda en PDFs usando OCR.\nAñadimos esto a nuestro compose:\n# Añadir estas variables a ocis \u0026gt; environment: # SEARCH_EXTRACTOR_TYPE: tika # SEARCH_EXTRACTOR_TIKA_TIKA_URL: http://tika:9998 # FRONTEND_FULL_TEXT_SEARCH_ENABLED: \u0026#34;true\u0026#34; tika: image: apache/tika:latest-full container_name: tika restart: always logging: driver: local Antivirus con ClamAV.\nAñadimos al compose:\n# Añadir a ocis \u0026gt; environment: # ANTIVIRUS_SCANNER_TYPE: clamav # ANTIVIRUS_INFECTED_FILE_HANDLING: delete # ANTIVIRUS_CLAMAV_SOCKET: \u0026#34;/var/run/clamav/clamd.sock\u0026#34; # OCIS_ADD_RUN_SERVICES: \u0026#34;antivirus\u0026#34; # POSTPROCESSING_STEPS: \u0026#34;virusscan\u0026#34; # Y añadir volumen: clamav-socket:/var/run/clamav clamav: image: clamav/clamav:latest container_name: clamav volumes: - /mnt/user/appdata/ocis/clamav:/var/lib/clamav - clamav-socket:/tmp volumes: clamav-socket: Fuentes:\nDocumentación Owncloud\nOwncloud oCIS en docker\nAuthelia y oCIS\nAuthelia y ldap\nOwncloud con OpenID\n","permalink":"https://blog.lasnotasdenoah.com/posts/owncloud/","summary":"\u003ch3 id=\"owncloud-ocis\"\u003eOwncloud oCIS\u003c/h3\u003e\n\u003cp\u003eoCIS está escrito en Go, lo que lo hace extremadamente rápido y ligero, funcionando como un binario único. Nextcloud utiliza PHP, lo que facilita su personalización pero requiere más recursos y optimización del servidor para grandes volúmenes.\u003c/p\u003e\n\u003cp\u003eMientras que oCIS se centra en ser un especialista en almacenamiento y sincronización a gran escala, Nextcloud se posiciona como una \u0026ldquo;Content Collaboration Platform\u0026rdquo; completa, incluyendo chat, videollamadas y oficina en línea de forma nativa.\u003c/p\u003e","title":"Instalación de Owncloud oCIS en Unraid"},{"content":"Adguard Home Según su web, Adguard Home es el primer bloqueador de anuncios para Linux a nivel de sistema en el mundo. Bloquea anuncios y rastreadores en el dispositivo, selecciona de los filtros preinstalados o añade los tuyos propios, todo a través de la interfaz de línea de comandos.\nCaracterísticas:\n1.- Bloqueo de anuncios: El bloqueador de anuncios AdGuard elimina los molestos banners, ventanas emergentes y anuncios de vídeo.\n2.- Protección de privacidad: El bloqueador de anuncios AdGuard protege tus datos de web analytics y los rastreadores online.\n3.- Seguridad de navegación: El bloqueador de anuncios AdGuard protege contra el phishing y los sitios maliciosos.\n4.- Control parental: El bloqueador de anuncios AdGuard protege a los niños del contenido adulto e inapropiado.\nInstalación en el VPS Usaremos docker como es habitual.\nservices: adguardhome: image: adguard/adguardhome:latest container_name: adguardhome restart: unless-stopped ports: # DNS (imprescindible) - \u0026#34;53:53/tcp\u0026#34; - \u0026#34;53:53/udp\u0026#34; # Web UI - Solo para el primer arranque del contenedor - Luego lo comentamos # - \u0026#34;3000:3000/tcp\u0026#34; # DoT (DNS over TLS) nosotros vamos a usarlo - \u0026#34;853:853/tcp\u0026#34; volumes: - ./conf:/opt/adguardhome/conf - ./data:/opt/adguardhome/work - ./certs:/opt/adguardhome/certs:ro networks: - infra_network # \u0026lt;--- Nuestra red de traefik certs-extractor: image: ldez/traefik-certs-dumper:v2.8.1 container_name: certs-extractor entrypoint: sh -c \u0026#34; traefik-certs-dumper file --watch --version v2 --source /data/acme.json --dest /output --domain-subdir \u0026amp;\u0026amp; chmod -R 600 /output/*\u0026#34; volumes: - /home/noe/traefik-crowdsec/traefik/ssl/acme.json:/data/acme.json:ro # Ruta a TU archivo acme.json - ./certs:/output # Donde se guardarán los .pem networks: - infra_network # \u0026lt;--- Nuestra red de traefik networks: infra_network: external: true Nuestro stack consta de dos contenedores. 1.- Adguardhome. Configuración sencilla. Solo es destacable que para el primer arranque mapeamos el puerto 3000 y una vez hecha la configuración inicial podemos comentarlo, ya que accederemos al panel a través de adguard.midominio.com. Aunque miestras escribo igual vuelvo a mapearlo para que solo sea accesible desde tailscale.\n2.- Certs-extractor. Este contenedor se encarga de extraer los certificados de traefik para usar el DNS over TLS. Esta parte es muy importante porque traefik guarda los certificados juntos en el mismo fichero acme.json. Este docker se encarga de extraer los certificados que contiene acme.json en dos ficheros: certificate.crt y privatekey.key\nEn la configuración inicial se dejan todos los valores por defecto. Lo único que tenemos que modificar es el usuario y la contraseña.\nConfiguraciones en traefik Nos vamos a traefik para adaptarlo a nuestro Adguard Home.\nEditamos nuestro fichero traefik.yml y añadimos un nuevo entrypoint para los DNS over TLS:\nentryPoints: web: address: \u0026#34;:80\u0026#34; http: redirections: entryPoint: to: websecure scheme: https websecure: address: \u0026#34;:443\u0026#34; http: tls: certResolver: letsencrypt # certResolver: letsencrypt_staging # Primer dominio domains: - main: \u0026#34;midominio.com\u0026#34; sans: - \u0026#34;*.midominio.com\u0026#34; # Segundo dominio - main: \u0026#34;lasnotasdenoah.com\u0026#34; sans: - \u0026#34;*.lasnotasdenoah.com\u0026#34; # Entrypoint para dns adguard-home dot: address: \u0026#34;:853\u0026#34; En nuestro directorio conf.d creamos el fichero dns.yml:\n# Esta primera parte de http simplemente es el acceso al panel de adguard como cualquier otro servicio. http: routers: adguard-ui: rule: \u0026#34;Host(`adguard.midominio.com`)\u0026#34; service: adguard-ui entryPoints: - websecure tls: {} # o simplemente ‘tls: true’ en v3 # Protegemos nuestro panel con los middleware middlewares: - geoblock-es - crowdsec-bouncer - security-headers services: adguard-ui: loadBalancer: servers: # Como estamos en la misma red docker, no hace falta poner dirección IP. Usamos el nombre del contenedor y traefik lo entiene perfectamente. - url: \u0026#34;http://adguardhome:80\u0026#34; # Aquí configuramos la conexión DNS tcp: routers: adguard-dot: rule: \u0026#34;HostSNI(`dns.midomnio.com`)\u0026#34; service: adguard-dot # Usamos el nuevo entryPoint que configuramos en traefik.yml por el puerto 853 que es el que usa DNS over TLS entryPoints: - dot # IMPORTANTÍSIMO: Tenemos que forzar a ACME a generar este dominio. MOTIVO: identificar de forma individual los equipos que se pueden conectar y de rebote vemos las estadísticas de uso de cada uno tls: certResolver: letsencrypt domains: # ← Esto fuerza ACME para este dominio específico - main: \u0026#34;dns.midominio.com\u0026#34; sans: - \u0026#34;*.dns.midominio.com\u0026#34; services: adguard-dot: loadBalancer: servers: - address: \u0026#34;adguardhome:853\u0026#34; # Reiniciamos traefik docker compose restart traefik # Verificamos los logs: docker logs traefik | grep -i acme Y vemos la respuesta de traefik:\n[...] 2026-04-03T16:32:09+02:00 ERR Unable to obtain ACME certificate for domains error=\u0026#34;unable to generate a certificate for the domains [*.dns.midominio.com]: error: one or more domains had a problem:\\n[dns.midominio.com] [dns.midominio.com] acme: error presenting token: cloudflare: failed to create TXT record: An identical record already exists. (81058)\\n\u0026#34; ACME CA=https://acme-v02.api.letsencrypt.org/directory acmeCA=https://acme-v02.api.letsencrypt.org/directory domains=[\u0026#34;dns.midominio.com\u0026#34;,\u0026#34;*.dns.midominio.com\u0026#34;] providerName=letsencrypt.acme routerName=adguard-certs-helper@file rule=Host(`dns.midominio.com`) ERROR: CrowdsecBouncerTraefikPlugin: 2026/04/04 11:02:04 ServeHTTP:Get ip:88.58.78.148 cache:unreachable [...] Pasos para solucionar el error:\nSegún Perplexity el error \u0026ldquo;An identical record already exists. (81058)\u0026rdquo; de Cloudflare DNS-01 es inofensivo (cert se genera igual), pero ensucia logs. Se soluciona borrando el TXT challenge persistente en Cloudflare.\n1.- Entramos en nuestro panel de administración de cloudflare y borramos los txt de los registros DNS 2.- Limpieza de logs de traefik:\ndocker exec traefik truncate -s 0 /var/log/traefik/access.log docker exec traefik truncate -s 0 /var/log/traefik/traefik.log 3.- Añadimos a certificatesResolvers.letsencrypt.acme.dnsChallenge de traefik.yml:\ndnsChallenge: provider: cloudflare delayBeforeCheck: 60 # Espera propagación resolvers: - \u0026#34;1.1.1.1:53\u0026#34; - \u0026#34;8.8.8.8:53\u0026#34; 4.- Verificamos con:\ndocker logs traefik | grep acme # Debería dar un resultado sin errores acme En la parte 1 de configurar el VPS tenía comentados los resolvers de traefik.yml:\nprovider: cloudflare # resolvers: # - \u0026#34;1.1.1.1:53\u0026#34; # - \u0026#34;1.0.0.1:53\u0026#34; Consulté nuevamente a Perplexity sobre ese comentario y su respuesta fue que es MUY importante descomentarlo para DNS-01 con Cloudflare. Esos resolvers le dicen a Traefik qué DNS públicos consultar para verificar que el TXT challenge se propagó antes de pedir el certificado.\nBeneficios inmediatos:\n1.- Renovaciones ACME 2x más rápidas\n2.- Cero errores \u0026ldquo;propagation timeout\u0026rdquo;\n3.- Logs de Traefik impecables\n4.- Rate limits Let’s Encrypt respetados\nAsí que toca descomentarlo para mejorar la estabilidad con certificados wildcards:\nprovider: cloudflare resolvers: - \u0026#34;1.1.1.1:53\u0026#34; - \u0026#34;1.0.0.1:53\u0026#34; Configuración panel Adguard Home En la siguiente imagen vemos el panel funcionando. Configuración de cifrado:\n1.- Marcamos el Check de Habilitar cifrado (DNS over TLS)\n2.- Nombre del servidor: dns.midominio.com\nEstablecemos la ruta de los certificados. En mi caso:\n# Archivo del certificado /opt/adguardhome//certs/*.dns.midominio.com/certificate.crt # Archivo de clave privada /opt/adguardhome//certs/*.dns.midominio.com/privatekey.key Nos saldrá una confirmación en verde para decir que se han cargado correctamente: Configuración de clientes en Adguard Home En esta parte vamos a configurar los clientes que pueden realizar consultas DNS por nuestro servicio.\nEsta es mi configuración Importante:\n1.- Nombre del cliente: nombre que nos guste para ver las estadísticas.\n2.- Etiqueta: se puede seleccionar la que sea mas acorde al dispositivo.\n3.- Identificador: esta es la parte mas importante. Identificador único por ejemplo: S24-XXXXXXXXXXX\nUna vez configurados los clientes, tenemos que autorizarles el uso del DNS en Configuración DNS. IMPORTANTE: En clientes permitidos ponemos el Identificador del cliente (NO el nombre) Configuración de clientes en Linux sudo nano /etc/systemd/resolved.conf # Añadimos lo siguiente: [Resolve] DNS=IP_PUBLICA_VPS#debian13-XXXXXXXXXXXX.dns.midominio.com FallbackDNS=9.9.9.9#dns.quad9.net Domains=~. DNSOverTLS=yes # Reiniciamos systemd-resolved sudo systemctl restart systemd-resolved.service Configuración de clientes en Android Vamos a Ajustes -\u0026gt; Conexiones -\u0026gt; Mas ajustes de conexión -\u0026gt; DNS privado:\ns24-XXXXXXXXX.dns.midominio.com Modificación para VPS en NetCUP Al cambiar mi VPS a NetCUP he tenido un problema con el firewall del propio netcup. Por motivos desconocidos el firewall bloqueaba los proveedores de DNS y no había manera de hacerlo funcionar. Daba igual las reglas que pusiera que netcup siempre bloqueaba cualquier comunicación a través del puerto DNS 53. La única forma de hacerlo funcionar era desactivando el firewall.\nPreguntando a Claude encontré la solución para dejar activado el firewall de netcup y que funciona adguardhome sin problemas. Por cierto, era bastante sencilla y Gemini me estuvo volviendo loco con configuraciones muy extranñas. Y yo venga a decirle que el problema no era de mi debian 13, que era de netcup y erre que erre.\n# Simplemente tenemos que liberar a adguardhome de tener que hacer una consulta DNS para resolver dns.quad9.net. # Le damos la IP directamente y ya no tiene que hacer esa consulta. # Sustituimos: https://dns.quad9.net/dns-query # por: # Proveedores DNS https://9.9.9.10/dns-query https://149.112.112.10/dns-query tls://9.9.9.9 tls://1.1.1.1 # Servidores DNS de arranque 9.9.9.9 1.1.1.1 Quedando en mi caso de esta forma: y los DNS de arranque: Fuentes:\nDebo decir que en esta guía he tirado mucho de IA.\nAdguard Home\nConfigurar VPS parte 1\nConfigurar VPS parte 2\n","permalink":"https://blog.lasnotasdenoah.com/posts/adguard-home-dns/","summary":"\u003ch2 id=\"adguard-home\"\u003eAdguard Home\u003c/h2\u003e\n\u003cp\u003eSegún su web, \u003ca href=\"https://adguard.com/es/welcome.html\"\u003eAdguard Home\u003c/a\u003e es el primer bloqueador de anuncios para Linux a nivel de sistema en el mundo. Bloquea anuncios y rastreadores en el dispositivo, selecciona de los filtros preinstalados o añade los tuyos propios, todo a través de la interfaz de línea de comandos.\u003c/p\u003e\n\u003cp\u003eCaracterísticas:\u003cbr\u003e\n1.- Bloqueo de anuncios: El bloqueador de anuncios AdGuard elimina los molestos banners, ventanas emergentes y anuncios de vídeo.\u003cbr\u003e\n2.- Protección de privacidad: El bloqueador de anuncios AdGuard protege tus datos de web analytics y los rastreadores online.\u003cbr\u003e\n3.- Seguridad de navegación: El bloqueador de anuncios AdGuard protege contra el phishing y los sitios maliciosos.\u003cbr\u003e\n4.- Control parental: El bloqueador de anuncios AdGuard protege a los niños del contenido adulto e inapropiado.\u003c/p\u003e","title":"AdguardHome como servidor DNS"},{"content":"Instalación y configuración de Wireguard Vamos a instalar un servidor Wireguard en nuestro VPS.\n# Instalamos wireguard y generador de qr para escanear desde app movil sudo apt install wireguard qrencode -y # Cambiamos a nuestro directorio de wireguard sudo su cd /etc/wireguard/ umask 077 # Generamos claves de servidor wg genkey | tee /etc/wireguard/server.key | wg pubkey \u0026gt; /etc/wireguard/server.pub Creamos nuestro fichero wg0.conf:\nnano wg0.conf [Interface] # IP que tendrá el VPS dentro de la VPN Address = 10.8.0.1/24 # Puerto de escucha (OJO - abrir el puerto en ufw y panel de nuestro vps si es necesario) ListenPort = 51820 # Clave privada del servidor PrivateKey = # GENERADA EN EL APARTADO ANTERIOR - FICHERO server.key # Reglas para permitir que el tráfico fluya y salga a internet #PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o ens6 -j MASQUERADE #PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o ens6 -j MASQUERADE # Reglas combinadas: Acceso a Internet (ens6) + Acceso a Tailscale (tailscale0) PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o ens6 -j MASQUERADE; iptables -A FORWARD -i %i -o tailscale0 -j ACCEPT; iptables -A FORWARD -i tailscale0 -o %i -m state --state RELATED,ESTABLISHED -j ACCEPT; iptables -t nat -A POSTROUTING -o tailscale0 -j MASQUERADE PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o ens6 -j MASQUERADE; iptables -D FORWARD -i %i -o tailscale0 -j ACCEPT; iptables -D FORWARD -i tailscale0 -o %i -m state --state RELATED,ESTABLISHED -j ACCEPT; iptables -t nat -D POSTROUTING -o tailscale0 -j MASQUERADE # CLIENTES # s24 [Peer] PublicKey = # CLAVE PUBLICA DE NUESTRO CLIENTE S24 AllowedIPs = 10.8.0.2/32 # envy [Peer] PublicKey = # CLAVE PUBLICA DE NUESTRO CLIENTE ENVY AllowedIPs = 10.8.0.3/32 Generamos las claves de nuestro primer cliente:\nwg genkey | tee /etc/wireguard/s24.key | wg pubkey \u0026gt; /etc/wireguard/s24.pub Fichero de configuracion del cliente:\nnano s24.conf [Interface] # Clave privada del cliente s24 PrivateKey = # CLAVE PRIVADA DE s24 GENERADA EN EL PASO ANTERIOR FICHERO s24.key Address = 10.8.0.2/24 #### OJO CON ESTO ###### # DNS = 1.1.1.1 # NETCUP es muy exigente con su firewall externo y no permite las consultas DNS. Un problema parecido he tenido en la configuración de AdguardHome # Para hacer funcionar esta configuración de wireguard en mi vps de NetCUP tengo que comentar la línea de DNS, cuando estaba en piensasolutions no me hacía falta comentar la línea. [Peer] # Public key del servidor PublicKey = # CLAVE PUBLICA DEL SERVIDOR FICHERO server.pub Endpoint = IP_PUBLICA_VPS:51820 AllowedIPs = 0.0.0.0/0 Generamos el codigo qr para escanear con el movil:\nqrencode -t ansiutf8 \u0026lt; s24.conf Y listo. Con esto ya está configurado nuestro servidor y nuestro.\nArrancamos el servicio y lo habilitamos:\nsystemctl start wg-quick@wg0 systemctl enable wg-quick@wg0 #Vemos el estado del servidor wg show Cuando actualicemos algún peer reiniciamos el servidor wireguard:\nsystemctl restart wg-quick@wg0 IMPORTANTE: Fichero wg0.conf no se puede borrar. Los ficheros .conf de los clientes no es necesarios conservarlos.Simplemente los creamos para generar luego el qr o para importarlos desde nuestro gestor de red de Gnome. RECORDAR actualizar nuestro fichero wg0.conf con cada cliente que añadimos.\nAmpliar la capacidad de RAM de nuestro VPS con swap Nuestro VPS está muy escaso de RAM. Vamos a darle algo de margen aprovechando nuestro nvme y creando una swap de 1GB de tamaño.\nCreación de nuestro fichero swap:\nsudo fallocate -l 1G /swapfile ls -la / sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile echo \u0026#39;/swapfile none swap sw 0 0\u0026#39; | sudo tee -a /etc/fstab cat /etc/fstab free -h sudo sysctl vm.swappiness=20 htop Backups remotos con Borgmatic En este mismo blog, tengo una entrada con la configuración de borgmatic en mi NAS secundario de backups.\nVamos a hacer una mejora en la programación de los backups.\nDebian 13 ya no usa cron para las tareas. Ahora usa systemd.\nInstalación de borgmatic\n# Instalación sudo apt install borgmatic # Generamos fichero de configuración sudo generate-borgmatic-config Editamos nuestro fichero de borgmatic:\nsudo nano /etc/borgmatic/config.yaml # Añadimos lo siguiente: source_directories: - /home/usuario repositories: # USAMOS NUESTRA IP DE TAILSCALE - path: ssh://borg@100.105.100.10:2222/./piensa label: piensa exclude_caches: true exclude_patterns: - \u0026#39;*.pyc\u0026#39; - /home/*/.cache compression: auto,zstd encryption_passphrase: PASS_SUPER_SECRETA archive_name_format: \u0026#34;{hostname}-{now}\u0026#34; # Usamos root porque hay directorios que solo tienen permisos de root (pe. en crowdsec) ssh_command: ssh -i /root/.ssh/piensa retries: 5 retry_wait: 5 keep_daily: 3 keep_weekly: 4 keep_monthly: 12 checks: - name: repository frequency: 4 weeks - name: archives frequency: 8 weeks check_last: 3 apprise: states: - start - finish - fail services: - url: mailtos://smtp.gmail.com:587?user=SUPERUSUARIO@gmail.com\u0026amp;pass=SUPERSECRETA_PASS\u0026amp;from=SUPERUSUARIO@gmail.com\u0026amp;to=DESTINATARIO@gmail.com label: mail - url: tgram://BOT_TOKEN:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/-ID_GRUPO_TELEGRAM/ label: telegram start: title: ⚙️ Starrted Backup Piensa body: Starting backup process finish: title: ✅ SUCCESS Backup Piensa body: Backup Piensa success fail: title: ❌ FAILED Backup Piensa body: Backups Piensa failed Con esto ya está configurado el backup de nuestros datos.\nAhora tenemos que verificar que la configuración sea correcta, iniciamos el repositorio de borg en el servidor remoto y hacemos el primer backup:\n# Verificamos configuración sudo env \u0026#34;PATH=$PATH\u0026#34; borgmatic config validate # Iniciamos el repositorio sudo env \u0026#34;PATH=$PATH\u0026#34; borgmatic init --encryption repokey-blake2 # Primer backup sudo borgmatic create --list --stats Vamos a programar los backups. En la web de borgmatic nos explica como hacerlo con tareas de systemd.\nwget https://projects.torsion.org/borgmatic-collective/borgmatic/raw/branch/main/sample/systemd/borgmatic.service wget https://projects.torsion.org/borgmatic-collective/borgmatic/raw/branch/main/sample/systemd/borgmatic.timer sudo mv borgmatic.service borgmatic.timer /etc/systemd/system/ # Connfiguración de horario: cd /etc/systemd/system sudo nano borgmatic.timer # Añadimos lo siguiente: [Unit] Description=Run borgmatic backup every day at 23:25:00 [Timer] #OnCalendar=daily OnCalendar=*-*-* 23:25:00 Persistent=true RandomizedDelaySec=10m [Install] WantedBy=timers.target Retocamos un par de cosas en nuestro fichero borgmatic.service\n# Connfiguración de horario: cd /etc/systemd/system sudo nano borgmatic.service [Unit] Description=borgmatic backup Wants=network-online.target After=network-online.target # Prevent borgmatic from running unless the machine is plugged into power. Remove this line if you # want to allow borgmatic to run anytime. #ConditionACPower=true Documentation=https://torsion.org/borgmatic/ [Service] Type=oneshot RuntimeDirectory=borgmatic StateDirectory=borgmatic # Comentamos para que borgmatic no vaya al fichero borgmatic.pw a buscar las contraseñas # Load single encrypted credential. # LoadCredentialEncrypted=borgmatic.pw LockPersonality=true MemoryDenyWriteExecute=no NoNewPrivileges=yes PrivateDevices=yes PrivateTmp=yes ProtectClock=yes ProtectControlGroups=yes ProtectHostname=yes ProtectKernelLogs=yes ProtectKernelModules=yes ProtectKernelTunables=yes RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 AF_NETLINK RestrictNamespaces=yes RestrictRealtime=yes RestrictSUIDSGID=yes SystemCallArchitectures=native SystemCallFilter=@system-service @mount SystemCallErrorNumber=EPERM ProtectSystem=full CapabilityBoundingSet=CAP_DAC_READ_SEARCH CAP_NET_RAW # Lower CPU and I/O priority. Nice=19 CPUSchedulingPolicy=batch IOSchedulingClass=best-effort IOSchedulingPriority=7 IOWeight=100 Restart=no LogRateLimitIntervalSec=0 # Delay start to prevent backups running during boot. Note that systemd-inhibit requires dbus and # dbus-user-session to be installed. ExecStartPre=sleep 1m # En esta linea es importante indicar la ruta de nuestro borgmatic # which borgmatic ExecStart=systemd-inhibit --who=\u0026#34;borgmatic\u0026#34; --what=\u0026#34;sleep:shutdown\u0026#34; --why=\u0026#34;Prevent interrupting scheduled backup\u0026#34; /usr/bin/borgmatic --verbosity -2 --syslog-verbosity 1 Por último, solo queda habilitar el nuevo servicio:\nsudo systemctl enable --now borgmatic.timer Verificamos la proxima ejecución:\nsystemctl list-timers borgmatic.timer NEXT LEFT LAST PASSED UNIT ACTIVATES Fri 2026-03-06 23:30:33 UTC 7h Fri 2026-03-06 07:18:33 UTC 8h ago borgmatic.timer borgmatic.service 1 timers listed. Pass --all to see loaded but inactive timers, too. Con esto debería estar correctamente configurados los backus a nuestro servidor borg a través del cliente borgmatic.\nPara verificar nuestros backups:\nsudo borgmatic list piensa: Listing archives my-vps-2026-02-23T12:23:46 Mon, 2026-02-23 12:23:46 [f6508163e6c277ea7cbaf33db275ba2052d430d4538e4ca12161a9fec5ee5a06] my-vps-2026-02-28T08:10:03 Sat, 2026-02-28 08:10:04 [c0fe77d566cc1db569e05c5ff9d7fc5d845e93b667373de24d86445891645945] my-vps-2026-03-01T08:10:04 Sun, 2026-03-01 08:10:05 [87a15d7677e28c62fe143e28117652dc8ca9f08b230083a01047147eb0cea948] my-vps-2026-03-02T23:25:04 Mon, 2026-03-02 23:25:05 [e4209a633f6a2f67cba38e3f4d6c481e6212cbcf76d0d2f79d22cc2c52d754e6] my-vps-2026-03-03T00:51:39 Tue, 2026-03-03 00:51:40 [f1c31249f7c8ded0e7d289a593c78e146606934cd5a913fec9959e7268e88cea] Restaurar el backup Esta la parte más importante de los backups. He realizado varias pruebas y todo ha funcionado correctamente. Para restaurar el backup primero hacemos un listado de los que tenemos y después montamos el backup en la ubicación deseada para restaurar los ficheros:\nPrimero listamos los ficheros creados con borgmatic:\nsudo borgmatic list Una vez sabemos el fichero que nos interesa podemos ver el contenido:\nsudo borgmatic list --archive server-2020-04-01 Extracción completa de ficheros:\nsudo borgmatic extract --archive my_server-2025-07-30T04:24:04 --destination /mnt/new-directory Extracción de una parte solamente:\nsudo borgmatic extract --archive my_server-2020-04-01 --path mnt/catpics --destination /mnt/new-directory Actualizaciones de seguridad automaticas Instalamos paquetes necesarios:\nsudo apt update \u0026amp;\u0026amp; sudo apt upgrade sudo apt install unattended-upgrades apt-listchanges -y Configuración:\nsudo nano /etc/apt/apt.conf.d/50unattended-upgrades # Nos aseguramos que las lineas siguientes están descomentadas: Unattended-Upgrade::Origins-Pattern { // Codename based matching: // This will follow the migration of a release through different // archives (e.g. from testing to stable and later oldstable). // Software will be the latest available for the named release, // but the Debian release itself will not be automatically upgraded. // \u0026#34;origin=Debian,codename=${distro_codename}-updates\u0026#34;; // \u0026#34;origin=Debian,codename=${distro_codename}-proposed-updates\u0026#34;; \u0026#34;origin=Debian,codename=${distro_codename},label=Debian\u0026#34;; \u0026#34;origin=Debian,codename=${distro_codename},label=Debian-Security\u0026#34;; \u0026#34;origin=Debian,codename=${distro_codename}-security,label=Debian-Security\u0026#34;; // \u0026#34;o=Debian Backports,n=${distro_codename}-backports,l=Debian Backports\u0026#34;; # Limpieza de dependencias no usadas // Do automatic removal of unused packages after the upgrade // (equivalent to apt-get autoremove) Unattended-Upgrade::Remove-Unused-Dependencies \u0026#34;true\u0026#34;; # Podríamos configurar reinicio automático, pero prefiero hacerlo después tras una notificación: # Descomentaríamos esto: // Unattended-Upgrade::Automatic-Reboot \u0026#34;true\u0026#34;; // Automatically reboot even if there are users currently logged in // when Unattended-Upgrade::Automatic-Reboot is set to true //Unattended-Upgrade::Automatic-Reboot-WithUsers \u0026#34;true\u0026#34;; // If automatic reboot is enabled and needed, reboot at the specific // time instead of immediately // Default: \u0026#34;now\u0026#34; # Aquí configuraríamos la hora del reinicio: // Unattended-Upgrade::Automatic-Reboot-Time \u0026#34;02:00\u0026#34;; Configuramos el lanzador:\nsudo nano /etc/apt/apt.conf.d/20auto-upgrades # Añadimos lo siguiente: APT::Periodic::Update-Package-Lists \u0026#34;1\u0026#34;; APT::Periodic::Download-Upgradeable-Packages \u0026#34;1\u0026#34;; APT::Periodic::AutocleanInterval \u0026#34;7\u0026#34;; APT::Periodic::Unattended-Upgrade \u0026#34;1\u0026#34;; Verificamos el correcto funcionamiento:\nsudo unattended-upgrade --dry-run --debug sudo cat /var/log/unattended-upgrades/unattended-upgrades.log systemctl status unattended-upgrades Notificaciones de actualizaciones Notificaciones con las actualizaciones automáticas. Creamos los scripts de notificación.\nComo unattended-upgrades envía correos electrónicos de forma nativa, pero no notificaciones Webhook/Push directamente, usaremos un script de \u0026ldquo;Post-Invoke\u0026rdquo;.\nsudo nano /usr/local/bin/notify-updates.sh # Añadimos lo siguiente: #!/bin/bash # Configuración APPRISE_URL=\u0026#34;tgram://11111111111111:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/-5002897396/\u0026#34; HOSTNAME=$(hostname) REBOOT_FILE=\u0026#34;/var/run/reboot-required\u0026#34; REBOOT_PKGS=\u0026#34;/var/run/reboot-required.pkgs\u0026#34; # 1. Obtener paquetes (usamos una variable limpia) LAST_UPGRADES=$(grep \u0026#34;Packages that were upgraded:\u0026#34; /var/log/unattended-upgrades/unattended-upgrades.log | tail -n 1 | cut -d: -f2) [ -z \u0026#34;$LAST_UPGRADES\u0026#34; ] \u0026amp;\u0026amp; LAST_UPGRADES=\u0026#34;Ninguno (solo ajustes de seguridad)\u0026#34; # 2. Lógica de reinicio if [ -f \u0026#34;$REBOOT_FILE\u0026#34; ]; then ICON=\u0026#34;⚠️\u0026#34; SUBJECT=\u0026#34;REINICIO REQUERIDO - Piensa: $HOSTNAME\u0026#34; MSG_REBOOT=\u0026#34;ATENCIÓN: Se requiere reiniciar el sistema.\u0026#34; else ICON=\u0026#34;✅\u0026#34; SUBJECT=\u0026#34;Actualización Exitosa - Piensa: $HOSTNAME\u0026#34; MSG_REBOOT=\u0026#34;No es necesario reiniciar.\u0026#34; fi # 3. Construir el cuerpo CON SALTOS DE LÍNEA REALES # Importante: Las líneas vacías entre el texto mantienen el formato en Telegram FINAL_BODY=\u0026#34;$ICON Actualizaciones completadas en Piensa: $HOSTNAME. Paquetes: $LAST_UPGRADES $MSG_REBOOT\u0026#34; # 4. Enviar (Apprise detectará los saltos de línea del shell) apprise --title \u0026#34;$SUBJECT\u0026#34; --body \u0026#34;$FINAL_BODY\u0026#34; \u0026#34;$APPRISE_URL\u0026#34; Como vemos en nuestro script el sistema nos avisa si es necesario reiniciar. En Debian, cuando apt instala un nuevo kernel, crea dos archivos temporales. El script simplemente mira si están ahí:\n/var/run/reboot-required\t#Su presencia indica que el sistema debe reiniciarse. /var/run/reboot-required.pkgs\t#Contiene la lista de paquetes que forzaron el reinicio (ej. linux-image-6.1...). Hacemos el script ejecutable:\nsudo chmod +x /usr/local/bin/notify-updates.sh Creamos un nuevo archivo de configuración en APT para que ejecute el script justo después de que unattended-upgrades termine su tarea:\nsudo nano /etc/apt/apt.conf.d/99apprise-notifications # Añadimos lo siguiente: Unattended-Upgrade::Post-Invoke { \u0026#34;/usr/local/bin/notify-updates.sh\u0026#34;; }; Pruebas:\nsudo touch /var/run/reboot-required /usr/local/bin/notify-updates.sh sudo rm /var/run/reboot-required En este punto nuestro sistema hace lo siguiente: 1.- Actualización diaria: unattended-upgrades hace el trabajo sucio.\n2.- Post-Update: Recibimos un mensaje con los paquetes instalados y un aviso si hace falta reiniciar.\nAhora ya es decisión nuestra realizar el reinicio del sistema\nNotificaciones de Servidor Online y espacio de almacenamiento Ya que nos hemos puesto con las notificaciones, vamos a configurar las notificaciones para que una vez reiniciemos el sistema no informe que está operativo y otra para informar de poco espacio de almacenamiento. Mi VPS es muy modesto y esta última me vendrá muy bien en caso de problemas con el llenado del disco.\nCreamos nuestro script:\nsudo nano /usr/local/bin/notify-boot.sh # Contenido: #!/bin/bash # Configuración APPRISE_URL=\u0026#34;tgram://2222222222:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/-5002897396/\u0026#34; HOSTNAME=$(hostname) UPTIME=$(uptime -p) # Mensaje de sistema iniciado SUBJECT=\u0026#34;🚀 Servidor Online - Piensa: $HOSTNAME\u0026#34; BODY=\u0026#34;El sistema se ha iniciado correctamente. Estado: $UPTIME Fecha: $(date \u0026#39;+%Y-%m-%d %H:%M:%S\u0026#39;)\u0026#34; # Enviar notificación /usr/bin/apprise --title \u0026#34;$SUBJECT\u0026#34; --body \u0026#34;$BODY\u0026#34; \u0026#34;$APPRISE_URL\u0026#34; Permisos de ejecución:\nsudo chmod +x notify-boot.sh sudo nano /etc/systemd/system/notify-boot.service # Contenido: [Unit] Description=Notificación de inicio por Apprise After=network-online.target Wants=network-online.target [Service] Type=oneshot ExecStart=/usr/local/bin/notify-boot.sh RemainAfterExit=yes [Install] WantedBy=multi-user.target Cargamos el nuevo servicio y lo habilitamos:\nsudo systemctl daemon-reload sudo systemctl enable notify-boot.service Prueba:\nsudo systemctl start notify-boot.service Vamos con la notificación de disco muy lleno:\nsudo nano /usr/local/bin/check-disk.sh # Contenido: #!/bin/bash # Configuración APPRISE_URL=\u0026#34;tgram://2222222222:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/-5002897396/\u0026#34; THRESHOLD=10 # Porcentaje mínimo de espacio libre antes de avisar HOSTNAME=$(hostname) # Obtener el uso actual de la partición raíz (/) CURRENT_FREE=$(df / --output=pcent | tail -1 | tr -dc \u0026#39;0-9\u0026#39;) FREE_SPACE_PERCENT=$((100 - CURRENT_FREE)) if [ \u0026#34;$FREE_SPACE_PERCENT\u0026#34; -le \u0026#34;$THRESHOLD\u0026#34; ]; then ICON=\u0026#34;🚨\u0026#34; SUBJECT=\u0026#34;ALERTA DE DISCO - $HOSTNAME\u0026#34; BODY=\u0026#34;¡Poco espacio en disco detectado! Espacio libre: $FREE_SPACE_PERCENT% Uso actual: $CURRENT_FREE% Se recomienda limpiar logs o paquetes antiguos antes de la próxima actualización.\u0026#34; # Enviar notificación /usr/bin/apprise --title \u0026#34;$SUBJECT\u0026#34; --body \u0026#34;$BODY\u0026#34; \u0026#34;$APPRISE_URL\u0026#34; fi Permisos de ejecución:\nsudo chmod +x check-disk.sh Programación diaria con systemd timers:\nsudo nano /etc/systemd/system/check-disk.service # Contenido: [Unit] Description=Chequeo de espacio en disco para alertas Apprise After=network-online.target [Service] Type=oneshot ExecStart=/usr/local/bin/check-disk.sh [Install] WantedBy=multi-user.target Creamos la Unidad de timer. Este archivo le dice a systemd cuando ejecutarlo:\nsudo nano /etc/systemd/system/check-disk.timer # Contenido: [Unit] Description=Ejecutar chequeo de disco diariamente [Timer] # Se ejecuta todos los días a las 08:30 AM OnCalendar=*-*-* 08:30:00 # Añade un margen aleatorio de 5 min para no saturar si tienes muchos VPS RandomizedDelaySec=300 Persistent=true # Si el VPS estaba apagado a las 08:30, el script se ejecutará inmediatamente en cuanto se encienda [Install] WantedBy=timers.target Activamos el nuevo timer:\nsudo systemctl daemon-reload sudo systemctl enable --now check-disk.timer Listado de timers activos en el sistema:\nsudo systemctl list-timers Logs de la última vez que se ejecutó el checkeo del disco:\nsudo journalctl -u check-disk.service Prueba para que nos avise por Telegram:\nsudo nano /usr/local/bin/check-disk.sh # Editamos nuestro script y modificamos la siguiente linea: # Si nuestro disco está mas de un 10% lleno que nos avise: THRESHOLD=90 # Porcentaje mínimo de espacio libre antes de avisar # Y lanzamos nuestro script. /usr/local/bin/check-disk.sh Nos debería llegar una notificación a Telegram con el aviso.\nEjecución manual del checkeo del disco:\nsudo systemctl start check-disk.service Con todo esto, nuestro VPS nos notificará de los siguientes eventos:\nActualizaciones: Te avisa qué instaló.\nMantenimiento: Te avisa si el kernel cambió y toca reiniciar.\nSupervivencia: Te avisa si el VPS arrancó tras un corte o reboot.\nPrevención: Te avisa si se está quedando sin espacio en disco.\nFuentes y enlaces de interés que ayudaran a complementar esta guía:\nDebo decir que en esta guía he tirado mucho de IA.\nhttps://blog.lasnotasdenoah.com/posts/vps-proxy/\nInstalación de traefik sin etiquetas Crowdsec WAF - Appsec\nWeb oficial de borgmatic\n","permalink":"https://blog.lasnotasdenoah.com/posts/vps-proxy-parte2/","summary":"\u003ch3 id=\"instalación-y-configuración-de-wireguard\"\u003eInstalación y configuración de Wireguard\u003c/h3\u003e\n\u003cp\u003eVamos a instalar un servidor Wireguard en nuestro VPS.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Instalamos wireguard y generador de qr para escanear desde app movil\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo apt install wireguard qrencode -y\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Cambiamos a nuestro directorio de wireguard\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo su\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd /etc/wireguard/\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eumask \u003cspan style=\"color:#ae81ff\"\u003e077\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Generamos claves de servidor\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ewg genkey | tee /etc/wireguard/server.key | wg pubkey \u0026gt; /etc/wireguard/server.pub\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eCreamos nuestro fichero wg0.conf:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enano wg0.conf\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003eInterface\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# IP que tendrá el VPS dentro de la VPN\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eAddress \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e 10.8.0.1/24\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Puerto de escucha (OJO - abrir el puerto en ufw y panel de nuestro vps si es necesario)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eListenPort \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e51820\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Clave privada del servidor\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePrivateKey \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e# GENERADA EN EL APARTADO ANTERIOR - FICHERO server.key\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Reglas para permitir que el tráfico fluya y salga a internet\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o ens6 -j MASQUERADE\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o ens6 -j MASQUERADE\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Reglas combinadas: Acceso a Internet (ens6) + Acceso a Tailscale (tailscale0)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePostUp \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o ens6 -j MASQUERADE; iptables -A FORWARD -i %i -o tailscale0 -j ACCEPT; iptables -A FORWARD -i tailscale0 -o %i -m state --state RELATED,ESTABLISHED -j ACCEPT; iptables -t nat -A POSTROUTING -o tailscale0 -j MASQUERADE\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePostDown \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o ens6 -j MASQUERADE; iptables -D FORWARD -i %i -o tailscale0 -j ACCEPT; iptables -D FORWARD -i tailscale0 -o %i -m state --state RELATED,ESTABLISHED -j ACCEPT; iptables -t nat -D POSTROUTING -o tailscale0 -j MASQUERADE\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# CLIENTES\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# s24\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ePeer\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePublicKey \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e# CLAVE PUBLICA DE NUESTRO CLIENTE S24\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eAllowedIPs \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e 10.8.0.2/32\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# envy\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ePeer\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePublicKey \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e# CLAVE PUBLICA DE NUESTRO CLIENTE ENVY\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eAllowedIPs \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e 10.8.0.3/32\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eGeneramos las claves de nuestro primer cliente:\u003c/p\u003e","title":"Proxy Inverso en VPS (parte 2)"},{"content":"Traefik y crowdsec Estoy hasta el gorro de la liga y sus puñeteros bloqueos. Este blog y mis servicios estaban configurados en el NAS con un traefik como proxy inverso. Para proteger mi IP pública uso el Proxied de cloudflare, que además aporta un WAF muy potente, geolocalización, etc. PROBLEMA: cada vez que hay futbol pierdo la conexión a homeassistant y otros servicios que para mi son muy importantes.\nHoy vamos a configurar traefik en un VPS y desde allí enrutamos todo el tráfico a nuestro NAS local a través de Tailscale. Desactivaremos el proxied de cloudflare y de esta forma no está expuesta mi IP pública, sólo está expuesta la IP del VPS.\nHe contratado el VPS más económico que tiene Piensasolutions. En mi caso pago 0,75€ al mes durante 12 meses y después el coste pasa a ser 1€ al mes.\nEl VPS tiene 1 GB de RAM, 1 vCPU, 10GB SSD NVMe y conexión de 1Gbps.\nAl principio intenté instalar Pangolín, que ya lo tuve operativo en un VPS de prueba más potente. Pero creo que en este servidor es muy exigente y no puede para nada con él. Solo Pangolín consume 300 Mb de RAM más el sistema, crowdsec, etc. IMPOSIBLE !!!!!\nPreparación del entorno Como sistema operativo tengo Debian 13. Una maravilla que consume pocos recursos. Instalamos y actualizamos:\nsudo apt update \u0026amp;\u0026amp; sudo apt upgrade -y Instalamos Tailscale:\ncurl -fsSL https://tailscale.com/install.sh | sh sudo tailscale up -d Configuración del Firewall. Instalamos ufw:\nsudo apt install ufw # Reglas iniciales sudo ufw default deny incoming # Ojo con esta regla estamos bloqueando hasta el ssh, que luego permitimos a través de tailscale. sudo ufw default allow outgoing #Permitimos todo el tráfico a través de tailscale0 sudo ufw allow in on tailscale0 # Puertos 80 y 443 para traefik sudo ufw allow 80/tcp sudo ufw allow 443/tcp # Activamos el firewall sudo ufw enable # Verificamos reglas sudo ufw status numbered Status: active To Action From -- ------ ---- [ 1] Anywhere on tailscale0 ALLOW IN Anywhere [ 2] 80/tcp ALLOW IN Anywhere [ 3] 443/tcp ALLOW IN Anywhere [ 5] Anywhere (v6) on tailscale0 ALLOW IN Anywhere (v6) [ 6] 80/tcp (v6) ALLOW IN Anywhere (v6) [ 7] 443/tcp (v6) ALLOW IN Anywhere (v6) # Nota para borrar alguna regla: sudo ufw delete 8 # Antes de cerrar esta sesión abrimos otra terminal y probamos a conectar por ssh. Si hubiera algún fallo siempre tenemos la opción de acceder a través de la web de nuestro VPS. En nuestro panel de control del VPS verificamos que los puertos que vamos a usar estén abiertos. En este caso necesitamos los puertos 80 y 443: Mi dominio está registrado en cloudflare. Tenemos que apuntar los registros DNS a la IP pública de nuestro VPS. Desactivamos el Proxied y nos quedamos sin protección para evitar que la dichosa liga y sus esbirros nos jodan a los pobres de a pie. Dejamos la nube de color gris para que cloudflare dirija el tráfico de forma transparente al VPS. CLoudflare nos muestra el siguiente aviso, pero da igual, nos jodemos porques estamos compartiendo la misma IP que alguna web ilegal. Cortamos medio internet y encima no se dan cuenta que no están consiguiendo nada, casi están animando a todo lo contrario. En fin que me caliento.\nEs necesario redirigir mediante proxy para la mayoría de las funciones de seguridad y rendimiento Para configurar sus registros DNS estableciendo la opción redirigido mediante proxy haga clic en \u0026#34;Editar\u0026#34; en la tabla siguiente y se beneficiará de la protección DDoS, las reglas de seguridad, el almacenamiento en caché y mucho más. Por último necesitamos una API Key de cloudflare para los certificados.\nInstalamos docker:\nsudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker version docker compose version # Damos permisos a nuestro usuario para ejecutar docker sin sudo sudo usermod -aG docker $USER Docker compose de traefik y crowdsec Creamos directorios:\nmkdir -p /home/noah/traefik-crowdsec mkdir -p /home/noah/traefik-crowdsec/traefik/{conf.d,logs,ssl} mkdir -p /home/noah/traefik-crowdsec/crowdsec/{config,data} mkdir -p /home/noah/traefik-crowdsec/redis-data Dentro de /home/noah/traefik-crowdsec creamos nuestro docker-compose.yml:\nservices: traefik: image: traefik:v3.5.0 container_name: traefik hostname: traefik restart: unless-stopped security_opt: - no-new-privileges:true environment: TZ: ${TZ:-Europe/Madrid} CF_DNS_API_TOKEN: ${CF_DNS_API_TOKEN} ports: - \u0026#34;80:80\u0026#34; - \u0026#34;443:443\u0026#34; volumes: - /usr/share/zoneinfo/${TZ:-Europe/Madrid}:/etc/localtime:ro - ./traefik/traefik.yml:/traefik.yml:ro - ./traefik/conf.d:/conf.d:ro - ./traefik/ssl:/ssl - ./traefik/logs:/var/log/traefik networks: - infra_network crowdsec: image: crowdsecurity/crowdsec:latest container_name: crowdsec restart: unless-stopped environment: - COLLECTIONS=crowdsecurity/traefik crowdsecurity/http-cve # ESTAS COLECCIONES LAS AÑADIREMOS LUEGO crowdsecurity/appsec-virtual-patching crowdsecurity/appsec-generic-rules - DISABLE_CAPI=true # Ignora CAPI completamente. Esto es para iniciar el contenedor sin avisos de error. Posteriormente habilitamos CAPI. volumes: - ./traefik/logs:/var/log/traefik:ro # comparte los logs - ./crowdsec/data:/var/lib/crowdsec/data - ./crowdsec/config:/etc/crowdsec networks: - infra_network # Usaremos redis como caché para quitar trabajo a nuestro crowdsec redis: image: redis:alpine container_name: crowdsec-redis restart: unless-stopped volumes: - ./redis-data:/data networks: - infra_network networks: infra_network: name: infra_network IMPORTANTE: Las colecciones de crowdsec que he incluido son las siguientes:\n- COLLECTIONS=crowdsecurity/traefik crowdsecurity/http-cve crowdsecurity/appsec-virtual-patching crowdsecurity/appsec-generic-rules # La coleccion appsec es para usar el WAF integrado que tiene crowdsec Creamos nuestro fichero .env:\nTZ=Europe/Madrid CF_DNS_API_TOKEN=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX Ficheros de configuración de traefik NOTA: Esta configuración es para emitir certificados individuales por cada servicio. Unas líneas más abajo modificamos nuestro traefik.yml para usar certificados Wildcard.\nFichero traefik.yml:\n# Global configuration global: checknewversion: false sendanonymoususage: false # API and dashboard configuration api: insecure: false dashboard: true debug: false # Load dynamic configuration from .yaml files in a directory - Routers providers: file: directory: /conf.d watch: true # Certificate Resolvers certificatesResolvers: letsencrypt: acme: email: micorreo@gmail.com storage: /ssl/acme.json caServer: https://acme-v02.api.letsencrypt.org/directory dnsChallenge: provider: cloudflare # resolvers: # - \u0026#34;1.1.1.1:53\u0026#34; # - \u0026#34;1.0.0.1:53\u0026#34; letsencrypt_staging: acme: email: micorreo@gmail.com storage: /ssl/acme.json caServer: https://acme-staging-v02.api.letsencrypt.org/directory dnsChallenge: provider: cloudflare # resolvers: # - \u0026#34;1.1.1.1:53\u0026#34; # - \u0026#34;1.0.0.1:53\u0026#34; # EntryPoints configuration entryPoints: web: address: \u0026#34;:80\u0026#34; http: redirections: entryPoint: to: websecure scheme: https websecure: address: \u0026#34;:443\u0026#34; http: tls: certResolver: letsencrypt # certResolver: letsencrypt_staging # Aquí podemos añadir los middleware que queramos de forma general. En mi caso no tengo ninguno porque prefiero añadirlos de forma manual a cada fichero en conf.d: # middlewares: # - crowdsec-bouncer # - security-headers accessLog: filePath: \u0026#34;/var/log/traefik/access.log\u0026#34; format: json bufferingSize: 100 fields: headers: defaultMode: keep # Mantiene headers para que CrowdSec vea IPs reales # PLUGINS (CrowdSec Bouncer para Traefik v3) experimental: plugins: crowdsec-bouncer: moduleName: github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin version: v1.5.1 # Ultima versión en el momento de la configuración. IMPORTANTE VERIFICAR geoblock: moduleName: github.com/PascalMinder/geoblock version: v0.3.6 IMPORTANTE: Para hacer pruebas usaremos el certResolver: letsencrypt_staging. Una vez esté todo configurado cambiamos a certResolver: letsencrypt. En el blog de manelrodero explica muy bien el motivo.\nDentro de ssl creamos nuestro fichero acme.json para los certificados:\ntouch acme.json chmod 600 acme.json NOTA: Con esta configuración de traefik.yml se genera un certificado para cada servicio.\nVamos a modificarla para generar un solo certificado por dominio, lo que se llama Certificados Wildcard y de esta forma me facilitará un poco otra parte de la configuración que será hacer una servidor DNS privado con Adguard Home.\n# Modificaciones en fichero traefik.yml [.......] # EntryPoints configuration entryPoints: web: address: \u0026#34;:80\u0026#34; http: redirections: entryPoint: to: websecure scheme: https websecure: address: \u0026#34;:443\u0026#34; http: tls: certResolver: letsencrypt # certResolver: letsencrypt_staging domains: - main: \u0026#34;midominio1.com\u0026#34; sans: - \u0026#34;*.midominio1.com\u0026#34; - main: \u0026#34;midominio2.com\u0026#34; sans: - \u0026#34;*.midominio2.com\u0026#34; accessLog: filePath: \u0026#34;/var/log/traefik/access.log\u0026#34; [.......] Ahora tenemos que hacer una pequeña modificación en cada fichero de traefik/conf.d. Ahora vemos un ejemplo con certificado individual y otro con certificado Wildcard.\nDentro de conf.d crearemos nuestros ficheros para dashboard, middlewares y distintos servicios.\nFichero dashboard.yml con certificado individual:\nhttp: routers: dashboard: rule: \u0026#34;Host(`traefik.midominio.com`)\u0026#34; service: api@internal entryPoints: - websecure tls: certResolver: letsencrypt middlewares: - auth Fichero dashboard.yml con certificado Wildcard:\nhttp: routers: dashboard: rule: \u0026#34;Host(`traefik.midominio.com`)\u0026#34; service: api@internal entryPoints: - websecure tls: {} # o simplemente ‘tls: true’ en v3 middlewares: - geoblock-es - crowdsec-bouncer - security-headers - auth Fichero middelwares.yml:\nhttp: middlewares: auth: basicAuth: # Generar con: echo $(htpasswd -nB usuario) | sed -e s/\\\\$/\\\\$\\\\$/g users: - \u0026#34;noah:$XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\u0026#34; security-headers: headers: stsSeconds: 15552000 stsIncludeSubdomains: true stsPreload: true forceSTSHeader: true frameDeny: true # Previene Clickjacking contentTypeNosniff: true # Previene sniffing de MIME browserXssFilter: true referrerPolicy: \u0026#34;same-origin\u0026#34; # Ajuste para Nextcloud: customFrameOptionsValue: \u0026#34;SAMEORIGIN\u0026#34; crowdsec-bouncer: plugin: crowdsec-bouncer: Enabled: true CrowdsecMode: stream # live o stream # Identidad fija para evitar los \u0026#34;bouncers fantasmas\u0026#34; # No funciona bien. De vez en cuando tengo un bouncer traefik-bouncer@172.18.0.X bouncerName: \u0026#34;traefik-bouncer\u0026#34; # Conexión a la LAPI (Local API) #CrowdsecLapiUrl: \u0026#34;http://crowdsec:8080\u0026#34; Nomenclatura antigua CrowdsecLapiScheme: \u0026#34;http\u0026#34; CrowdsecLapiHost: \u0026#34;crowdsec:8080\u0026#34; CrowdsecLapiKey: \u0026#34;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\u0026#34; # Cache Redis RedisCacheEnabled: true RedisCacheHost: \u0026#34;crowdsec-redis:6379\u0026#34; # LogLevel: \u0026#34;DEBUG\u0026#34; # Configuración del WAF se añade luego junto con las colecciones (AppSec) CrowdsecAppsecEnabled: true CrowdsecAppsecHost: \u0026#34;crowdsec:7422\u0026#34; # Puerto por defecto del WAF en el contenedor crowdsec CrowdsecAppsecFailureBlock: true CrowdsecAppsecUnreachableBlock: true # Trusted IPs ForwardedHeadersCustomName: \u0026#34;X-Forwarded-For\u0026#34; ForwardedHeadersTrustedIps: - \u0026#34;103.21.244.0/22\u0026#34; - \u0026#34;103.22.200.0/22\u0026#34; - \u0026#34;103.31.4.0/22\u0026#34; - \u0026#34;104.16.0.0/13\u0026#34; - \u0026#34;104.24.0.0/14\u0026#34; - \u0026#34;108.162.192.0/18\u0026#34; - \u0026#34;131.0.72.0/22\u0026#34; - \u0026#34;141.101.64.0/18\u0026#34; - \u0026#34;162.158.0.0/15\u0026#34; - \u0026#34;172.64.0.0/13\u0026#34; - \u0026#34;173.245.48.0/20\u0026#34; - \u0026#34;188.114.96.0/20\u0026#34; - \u0026#34;190.93.240.0/20\u0026#34; - \u0026#34;197.234.240.0/22\u0026#34; - \u0026#34;198.41.128.0/17\u0026#34; geoblock-es: plugin: geoblock: httpStatusCodeDeniedRequest: 404 api: \u0026#34;https://get.geojs.io/v1/ip/country/{ip}\u0026#34; # ← OBLIGATORIO ipGeolocationHttpHeaderField: \u0026#34;CF-IPCountry\u0026#34; # ← Prioriza este header! ipHeaders: [\u0026#34;X-Forwarded-For\u0026#34;, \u0026#34;CF-Connecting-IP\u0026#34;] # Backup ipHeaderStrategy: \u0026#34;CheckFirst\u0026#34; countries: # Permitir SOLO estos (ISO 3166-1 alpha-2) - ES allowLocalRequests: true # VPS/local/Tailscale allowUnknownCountries: false # Bloquea IPs sin país apiTimeoutMs: 200 # Rápido cacheSize: 100 # Para tu tráfico forwardedHeadersTrustedIps: # Cloudflare + Tailscale - \u0026#34;103.21.244.0/22\u0026#34; - \u0026#34;103.22.200.0/22\u0026#34; - \u0026#34;103.31.4.0/22\u0026#34; - \u0026#34;104.16.0.0/13\u0026#34; - \u0026#34;104.24.0.0/14\u0026#34; - \u0026#34;108.162.192.0/18\u0026#34; - \u0026#34;131.0.72.0/22\u0026#34; - \u0026#34;141.101.64.0/18\u0026#34; - \u0026#34;162.158.0.0/15\u0026#34; - \u0026#34;172.64.0.0/13\u0026#34; - \u0026#34;173.245.48.0/20\u0026#34; - \u0026#34;188.114.96.0/20\u0026#34; - \u0026#34;190.93.240.0/20\u0026#34; - \u0026#34;197.234.240.0/22\u0026#34; - \u0026#34;198.41.128.0/17\u0026#34; Cuando arranquemos por primera vez el stack crowdsec no funcionará porque no hemos creado el bouncer de traefik:\ndocker exec -it crowdsec cscli bouncers add traefik-bouncer Este comando nos genera una API Key que tenemos que copiar en el fichero middlewares.yml:\ncrowdsec-bouncer: plugin: crowdsec-bouncer: Enabled: true CrowdsecMode: strem # live o stream # Identidad fija para evitar los \u0026#34;bouncers fantasmas\u0026#34; bouncerName: \u0026#34;traefik-bouncer\u0026#34; # Conexión a la LAPI (Local API) CrowdsecLapiUrl: \u0026#34;http://crowdsec:8080\u0026#34; CrowdsecLapiKey: \u0026#34;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\u0026#34; \u0026lt;\u0026lt;--COPIAR AQUI EL API KEY # Configuración del WAF (AppSec) appsecEnabled: true Reiniciamos nuestro compose:\ndocker compose restart Fichero de ejemplo de un servicio con certificado individual: karakeep.yml:\nhttp: routers: karakeep: rule: \u0026#34;Host(`karakeep.midominio.com`)\u0026#34; service: karakeep entryPoints: - websecure tls: certResolver: letsencrypt services: karakeep: loadBalancer: servers: - url: \u0026#34;http://100.105.100.10:3333\u0026#34; Fichero de ejemplo de un servicio con certificado Wildcard: karakeep.yml:\nhttp: routers: karakeep: rule: \u0026#34;Host(`karakeep.midominio.com`)\u0026#34; service: karakeep entryPoints: - websecure tls: {} # o simplemente ‘tls: true’ en v3 middlewares: - geoblock-es - crowdsec-bouncer - security-headers services: karakeep: loadBalancer: servers: - url: \u0026#34;http://100.105.100.10:3333\u0026#34; Script para creación de servicios:\nservice=\u0026#34;my_servicio\u0026#34; url=\u0026#34;http://100.105.100.10:3333\u0026#34; cat \u0026lt;\u0026lt; EOF \u0026gt; \u0026#34;./data/conf.d/${service}.yml\u0026#34; http: routers: ${service}: rule: \u0026#34;Host(\\`${service}.midominio.com\\`)\u0026#34; service: ${service} entryPoints: - websecure # Opción para certificado individual #tls: # certResolver: letsencrypt # Opción para certificado Wildcard tls: {} # middlewares: # - crowdsec-bouncer # - security-headers # - geoblock-es services: ${service}: loadBalancer: servers: - url: \u0026#34;${url}\u0026#34; EOF NOTA: En el fichero traefik.yml le podemos indicar a traefik que todo el tráfico que entre por 443 pase por los siguientes middlewares:\nwebsecure: address: \u0026#34;:443\u0026#34; http: tls: certResolver: letsencrypt # certResolver: letsencrypt_staging middlewares: - geoblock-es - crowdsec-bouncer - security-headers En nuestro script de creación de servicios hemos comentado los middleware para añadir cado uno según nuestras necesidades.\nFicheros de configuración de crowdsec Fichero obtención datos /traefik-crowdsec/crowdsec/config/acquis.yaml:\n--- filenames: - /var/log/traefik/access.log poll_without_inotify: true labels: type: traefik Fichero definir baneos y tipo de notificaciones /traefik-crowdsec/crowdsec/config/profiles.yaml:\n# 1. PERFIL PARA REINCIDENTES (Primero en la lista) name: reincident_remediation filters: # Usamos la función correcta para contar decisiones previas de esa IP - Alert.Remediation == true \u0026amp;\u0026amp; Alert.GetScope() == \u0026#34;Ip\u0026#34; \u0026amp;\u0026amp; GetDecisionsCount(Alert.GetValue()) \u0026gt; 0 decisions: - type: ban duration: 168h # 1 semana de \u0026#34;nevera\u0026#34; VAMOS A SER MUY EXTRICTOS CON LOS REINCIDENTES notifications: - telegram on_success: break # Si entra aquí, no sigue leyendo hacia abajo --- # 2. PERFIL POR DEFECTO PARA IPs name: default_ip_remediation #debug: true filters: - Alert.Remediation == true \u0026amp;\u0026amp; Alert.GetScope() == \u0026#34;Ip\u0026#34; decisions: - type: ban duration: 48h notifications: - telegram #duration_expr: Sprintf(\u0026#39;%dh\u0026#39;, (GetDecisionsCount(Alert.GetValue()) + 1) * 4) # notifications: # - slack_default # Set the webhook in /etc/crowdsec/notifications/slack.y\u0026gt; # - splunk_default # Set the splunk url and token in /etc/crowdsec/notifica\u0026gt; # - http_default # Set the required http parameters in /etc/crowdsec/noti\u0026gt; # - email_default # Set the required email parameters in /etc/crowdsec/not\u0026gt; on_success: break --- # 3. PERFIL PARA RANGOS name: default_range_remediation #debug: true filters: - Alert.Remediation == true \u0026amp;\u0026amp; Alert.GetScope() == \u0026#34;Range\u0026#34; decisions: - type: ban duration: 48h #duration_expr: Sprintf(\u0026#39;%dh\u0026#39;, (GetDecisionsCount(Alert.GetValue()) + 1) * 4) # notifications: # - slack_default # Set the webhook in /etc/crowdsec/notifications/slack.y\u0026gt; # - splunk_default # Set the splunk url and token in /etc/crowdsec/notifica\u0026gt; # - http_default # Set the required http parameters in /etc/crowdsec/noti\u0026gt; # - email_default # Set the required email parameters in /etc/crowdsec/not\u0026gt; on_success: break Fichero notificaciones traefik-crowdsec/crowdsec/config/notifications/http.yaml:\ntype: http # Don\u0026#39;t change name: telegram # Must match the registered plugin in the profile # One of \u0026#34;trace\u0026#34;, \u0026#34;debug\u0026#34;, \u0026#34;info\u0026#34;, \u0026#34;warn\u0026#34;, \u0026#34;error\u0026#34;, \u0026#34;off\u0026#34; log_level: info format: | { \u0026#34;chat_id\u0026#34;: \u0026#34;-XXXXXXXXXXXXXXXX\u0026#34;, \u0026#34;text\u0026#34;: \u0026#34; {{range . -}} {{$alert := . -}} {{range .Decisions -}} 🚨 CrowdSec Alert on Piensa! 🚨 🆔 IP: {{.Value}} ⚠️ Scenario: {{ .Scenario }} 🚧 Decision: {{.Type}} for next {{.Duration}} {{end -}} {{end -}} \u0026#34;, \u0026#34;reply_markup\u0026#34;: { \u0026#34;inline_keyboard\u0026#34;: [ {{ $arrLength := len . -}} {{ range $i, $value := . -}} {{ $V := $value.Source.Value -}} [ { \u0026#34;text\u0026#34;: \u0026#34;See {{ $V }} on shodan.io\u0026#34;, \u0026#34;url\u0026#34;: \u0026#34;https://www.shodan.io/host/{{ $V -}}\u0026#34; }, { \u0026#34;text\u0026#34;: \u0026#34;See {{ $V }} on crowdsec.net\u0026#34;, \u0026#34;url\u0026#34;: \u0026#34;https://app.crowdsec.net/cti/{{ $V -}}\u0026#34; } ]{{if lt $i ( sub $arrLength 1) }},{{end }} {{end -}} ] } url: https://api.telegram.org/bot111111111111:XXXXXXXXXx-XXXXXXXXXXXXXXXXXXXXXXXXX/sendMessage method: POST headers: Content-Type: \u0026#34;application/json\u0026#34; En este momento podemos arrancar nuestro compose y debería funcionar todo correctamente.\nAPPSEC para Crowdsec Según la web de Crowdsec, Appsec es un WAF que ofrece las siguientes características:\n1.- Aplicación de parches virtuales con bajo esfuerzo. 2.- Compatibilidad con reglas heredadas de ModSecurity. 3.- Protección WAF clásica más funciones de CrowdSec para detección avanzada de comportamiento. 4.- Integración completa con la pila CrowdSec, incluidos la consola y los componentes de remediación.\nPara integrarlo realizamos los siguientes pasos:\n# Detenemos nuestro stack docker compose down Añadimos a nuestro docker-compose las colecciones:\n- COLLECTIONS=crowdsecurity/traefik crowdsecurity/http-cve crowdsecurity/appsec-virtual-patching crowdsecurity/appsec-generic-rules # Arrancamos nuevamente la pila docker compose up -d Tenemos que crear un fichero de adquisiciones para Appsec. Antes de eso debemos descargar las reglas de appsec porque sino el contenedor de crowdsec no arrancará (me dió este problema y estuvo volviendome loco hasta encontrar una solución por la red).\nDescargamos las reglas:\ndocker exec crowdsec cscli collections install crowdsecurity/appsec-virtual-patching docker exec crowdsec cscli collections install crowdsecurity/appsec-generic-rules Reiniciamos crowdsec:\ndocker compose restart crowdsec Ahora podemos verificar que ha arrancado correctamente sin reinicios con\ndocker stats Creamos el fichero de adquisiciones:\nsudo nano /crowdsec/config/acquis.d/appsec.yaml #Añadimos esto al fichero: appsec_config: crowdsecurity/appsec-default labels: type: appsec listen_addr: 0.0.0.0:7422 source: appsec Añadimos la nueva configuración a nuestro middleware de crowdsec:\ncrowdsec-bouncer: plugin: crowdsec-bouncer: Enabled: true # CrowdsecMode: stream # live o stream crowdsecMode: stream # live o stream # Identidad fija para evitar los \u0026#34;bouncers fantasmas\u0026#34; bouncerName: \u0026#34;traefik-bouncer\u0026#34; # Conexión a la LAPI (Local API) CrowdsecLapiUrl: \u0026#34;http://crowdsec:8080\u0026#34; # crowdsecLapiHost: \u0026#34;crowdsec:8080\u0026#34; CrowdsecLapiKey: \u0026#34;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\u0026#34; # Configuración del WAF (AppSec) crowdsecAppsecEnabled: true crowdsecAppsecHost: \u0026#34;crowdsec:7422\u0026#34; # Puerto por defecto del WAF en\u0026gt; crowdsecAppsecFailureBlock: true crowdsecAppsecUnreachableBlock: true #appsecFailureAction: \u0026#34;passthrough\u0026#34; # Si el WAF falla, deja pasar (\u0026gt; ForwardedHeadersCustomName: \u0026#34;X-Forwarded-For\u0026#34; [.................] Y reiniciamos nuevamente crowdsec:\ndocker compose restart crowdsec Verificaciones a realizar para comprobar que funciona correctamente:\ndocker exec crowdsec cscli appsec-rules list # Genera un listado de las reglas que están activas: ------------------------------------------------------------------------------------------------------------------------------------------ APPSEC-RULES ------------------------------------------------------------------------------------------------------------------------------------------ Name 📦 Status Version Local Path ------------------------------------------------------------------------------------------------------------------------------------------ crowdsecurity/appsec-generic-test ✔️ enabled 0.3 /etc/crowdsec/appsec-rules/appsec-generic-test.yaml crowdsecurity/base-config ✔️ enabled 0.1 /etc/crowdsec/appsec-rules/base-config.yaml crowdsecurity/experimental-no-user-agent ✔️ enabled 0.1 /etc/crowdsec/appsec-rules/experimental-no-user-agent.yaml crowdsecurity/generic-freemarker-ssti ✔️ enabled 0.3 /etc/crowdsec/appsec-rules/generic-freemarker-ssti.yaml docker exec crowdsec cscli metrics show appsec #Metricas de Appsec +-------------------------------------+ | Appsec Metrics | +---------------+-----------+---------+ | Appsec Engine | Processed | Blocked | +---------------+-----------+---------+ | 0.0.0.0:7422/ | 361 | - | +---------------+-----------+---------+ ╰─ docker exec crowdsec cscli appsec-configs list ---------------------------------------------------------------------------------------------------------- APPSEC-CONFIGS ---------------------------------------------------------------------------------------------------------- Name 📦 Status Version Local Path ---------------------------------------------------------------------------------------------------------- crowdsecurity/appsec-default ✔️ enabled 0.4 /etc/crowdsec/appsec-configs/appsec-default.yaml crowdsecurity/generic-rules ✔️ enabled 0.4 /etc/crowdsec/appsec-configs/generic-rules.yaml crowdsecurity/virtual-patching ✔️ enabled 0.4 /etc/crowdsec/appsec-configs/virtual-patching.yaml ---------------------------------------------------------------------------------------------------------- En teoría, siguiendo las instrucciones de crowdsec deberíamos mapear el fichero en el contenedor de docker, pero yo no lo he hecho y funciona igual:\ncrowdsec: image: crowdsecurity/crowdsec:latest container_name: crowdsec restart: unless-stopped environment: - COLLECTIONS=crowdsecurity/traefik crowdsecurity/http-cve crowdsecurity/appsec-virtual-patching crowdsecurity/appsec-generic-rules - DISABLE_CAPI=true # Ignora CAPI completamente volumes: # - ./crowdsec/config/acquis.d/appsec.yaml:/etc/crowdsec/acquis.d/appsec.yaml [......] NOTA IMPORTANTE: Por último, me he dado cuenta que si ya teníamos funcionando el stack con configuraciones anteriores, cuando añadimos Appsec por lo que sea el Appsec engine se queda en blanco:\n╰─ docker exec crowdsec cscli metrics show appsec +-------------------------------------+ | Appsec Metrics | +---------------+-----------+---------+ | Appsec Engine | Processed | Blocked | +---------------+-----------+---------+ | | | - | +---------------+-----------+---------+ y tengo que borrar toda la configuración de crowdsec y volver a empezar. Con eso ya funciona correctamente. Supongo que algo se queda en caché.\n╰─ docker exec crowdsec cscli metrics show appsec +-------------------------------------+ | Appsec Metrics | +---------------+-----------+---------+ | Appsec Engine | Processed | Blocked | +---------------+-----------+---------+ | 0.0.0.0:7422/ | 4 | - | +---------------+-----------+---------+ Llegados a este punto, parece que Appsec funciona correctamente, pero no es cierto. Con el tiempo veremos que procesa muchas peticiones pero no bloquea ninguna. Vamos a ponerle remedio.\nMejoras en la configuración de Appsec Verificamos las colecciones de Appsec:\ndocker exec crowdsec cscli collections list -a | grep appsec Salida:\ncrowdsecurity/appsec-crs ✔️ enabled 0.8 /etc/crowdsec/collections/appsec-crs.yaml crowdsecurity/appsec-crs-exclusion-plugin-cpanel 🚫 disabled,update-available crowdsecurity/appsec-crs-exclusion-plugin-dokuwiki 🚫 disabled,update-available crowdsecurity/appsec-crs-exclusion-plugin-drupal 🚫 disabled,update-available crowdsecurity/appsec-crs-exclusion-plugin-nextcloud 🚫 disabled,update-available crowdsecurity/appsec-crs-exclusion-plugin-phpbb 🚫 disabled,update-available crowdsecurity/appsec-crs-exclusion-plugin-phpmyadmin 🚫 disabled,update-available crowdsecurity/appsec-crs-exclusion-plugin-wordpress 🚫 disabled,update-available crowdsecurity/appsec-crs-exclusion-plugin-xenforo 🚫 disabled,update-available crowdsecurity/appsec-crs-inband 🚫 disabled,update-available crowdsecurity/appsec-generic-rules ✔️ enabled 1.1 /etc/crowdsec/collections/appsec-generic-rules.yaml crowdsecurity/appsec-virtual-patching ✔️ enabled 14.7 /etc/crowdsec/collections/appsec-virtual-patching.yaml crowdsecurity/appsec-wordpress 🚫 disabled,update-available openappsec/openappsec 🚫 disabled,update-available Modificamos nuestro fichero appsec-default.yaml\nsudo nano ~/traefik-crowdsec/crowdsec/config/hub/appsec-configs/crowdsecurity/appsec-default.yaml # Contenido: name: crowdsecurity/appsec-default default_remediation: ban inband_rules: - crowdsecurity/base-config - crowdsecurity/vpatch-* - crowdsecurity/generic-* - crowdsecurity/crs # \u0026lt;---- AÑADIMOS ESTO outofband_rules: - crowdsecurity/experimental-* - crowdsecurity/appsec-generic-test Reiniciamos crowdsec. Es posible que en el reinicio nos cree un nuevo bouncer. Ya sabemos lo que hay que hacer.\ndocker restart crowdsec Prueba de funcionamiento:\nprueba: # Terminal 1 en VPS Dejamos los logs visualizando docker logs crowdsec -f 2\u0026gt;\u0026amp;1 # Terminal 2 en mi pc - SIMULAMOS UNA PETICIÓN QUE APPSEC DEBERÍA BLOQUEAR curl -v \u0026#34;https://lasnotasdenoah.com/?id=1+UNION+SELECT+1,2,3--\u0026#34; Esta vez deberías recibir un 403.\n⚠️ Aviso importante: este archivo es del hub y cscli hub update podría sobreescribirlo en el futuro. Para hacerlo permanente sin que se pierda, lo ideal sería crear un appsec-config personalizado en /etc/crowdsec/appsec-configs/ con otro nombre que no gestione el hub.\nVamos a hacer permanente el cambio:\nsudo cp ~/traefik-crowdsec/crowdsec/config/hub/appsec-configs/crowdsecurity/appsec-default.yaml \\ ~/traefik-crowdsec/crowdsec/config/appsec-configs/myconfig-appsec-default.yaml Editamos nuestro fichero acquis.d/appsec.yaml:\nappsec_config: myconfig-appsec-default labels: type: appsec listen_addr: 0.0.0.0:7422 source: appsec Reiniciamos crowdsec\ndocker compose restart crowdsec Y vemos que no arranca.\nEl motivo es el siguiente: El problema es que cuando usas appsec_config: myconfig-appsec-default CrowdSec busca ese nombre dentro del hub, no por nombre de archivo. El nombre que registra CrowdSec es el campo name: dentro del yaml, no el nombre del fichero.\nVamos a editar nuevamente nuestro fichero myconfig-appsec-default.yaml:\nsudo nano ~/traefik-crowdsec/crowdsec/config/appsec-configs/myconfig-appsec-default.yaml # Contenido: name: custom/appsec-default # \u0026lt;--- MODIFICAMOS EL NOMBRE default_remediation: ban inband_rules: - crowdsecurity/base-config - crowdsecurity/vpatch-* - crowdsecurity/generic-* - crowdsecurity/crs outofband_rules: - crowdsecurity/experimental-* - crowdsecurity/appsec-generic-test sudo nano ~/traefik-crowdsec/crowdsec/config/acquis.d/appsec.yaml # Contenido: appsec_configs: - custom/appsec-default labels: type: appsec listen_addr: 0.0.0.0:7422 source: appsec Verificamos que funciona:\ndocker restart crowdsec docker logs crowdsec 2\u0026gt;\u0026amp;1 | grep -E \u0026#34;fatal|error|inband\u0026#34; | head -10 Llegados a este punto, todos mis servicios deberían funcionar correctamente excepto Nextcloud. Nos vamos al siguiente punto del tutorial.\nCorrecciones de Nextcloud para funcionar con Appsec Las reglas crowdsecurity/crs (Core Rule Set de OWASP) son muy agresivas y bloquean muchas peticiones legítimas de Nextcloud, especialmente las subidas de archivos, WebDAV, y las llamadas a la API.\nTenemos varias opciones:\nOPCION 1.- Configuración reglas acceso de Appsec para Nextcloud\nsudo nano ~/traefik-crowdsec/crowdsec/config/appsec-configs/myconfig-appsec-default.yaml # Contenido: name: custom/appsec-default default_remediation: ban inband_rules: - crowdsecurity/base-config - crowdsecurity/vpatch-* - crowdsecurity/generic-* - crowdsecurity/crs # OPCION 1 inband_options: request_exclusions: - rules_ids: - crowdsecurity/crs zone: URI zone_filter: \u0026#34;^/(remote\\\\.php|ocs|index\\\\.php|apps|core|status\\\\.php|login|logout|cron\\\\.php|public\\\\.php|dav|caldav|carddav|webdav)\u0026#34; outofband_rules: - crowdsecurity/experimental-* - crowdsecurity/appsec-generic-test # OPCION 2 inband_options: request_exclusions: - rules_ids: - crowdsecurity/crs zone: URI zone_filter: \u0026#34;^/(remote\\\\.php|ocs|index\\\\.php|apps|core|status\\\\.php|login|logout|cron\\\\.php|public\\\\.php|dav)\u0026#34; # Buscando información: Request_exclusions no existe en esta versión de CrowdSec. La estructura inband_options solo acepta disable_rules. La solución correcta para esta versión es usar on_match con un filtro de URI: # OPCION 3 on_match: - filter: \u0026#34;match(req.URI, \u0026#39;^/(remote\\\\.php|ocs|index\\\\.php|apps|core|status\\\\.php|login|logout|cron\\\\.php|public\\\\.php|dav)\u0026#39;) \u0026amp;\u0026amp; evt.Rules_matched contains \u0026#39;crowdsecurity/crs\u0026#39;\u0026#34; apply: - SetRemediation(\u0026#34;allow\u0026#34;) # OPCION 4 on_match: - filter: \u0026#34;evt.Rules_matched contains \u0026#39;crowdsecurity/crs\u0026#39; \u0026amp;\u0026amp; (contains(req.URI, \u0026#39;/remote.php\u0026#39;) || contains(req.URI, \u0026#39;/ocs/\u0026#39;) || contains(req.URI, \u0026#39;/index.php\u0026#39;) || contains(req.URI, \u0026#39;/apps/\u0026#39;) || contains(req.URI, \u0026#39;/dav\u0026#39;) || contains(req.URI, \u0026#39;/status.php\u0026#39;) || contains(req.URI, \u0026#39;/cron.php\u0026#39;) || contains(req.URI, \u0026#39;/public.php\u0026#39;))\u0026#34; apply: - SetRemediation(\u0026#34;allow\u0026#34;) # OPCION 5 on_match: - filter: \u0026#34;\u0026#39;crowdsecurity/crs\u0026#39; in evt.Rules_matched \u0026amp;\u0026amp; (req.URI startsWith \u0026#39;/remote.php\u0026#39; || req.URI startsWith \u0026#39;/ocs/\u0026#39; || req.URI startsWith \u0026#39;/index.php\u0026#39; || req.URI startsWith \u0026#39;/apps/\u0026#39; || req.URI startsWith \u0026#39;/dav\u0026#39; || req.URI startsWith \u0026#39;/status.php\u0026#39; || req.URI startsWith \u0026#39;/cron.php\u0026#39; || req.URI startsWith \u0026#39;/public.php\u0026#39;)\u0026#34; apply: - SetRemediation(\u0026#34;allow\u0026#34;) FALLAN TODAS LAS OPCIONES DE MODIFICAR NUESTRO FICHERO myconfig-appsec-default.yaml. No conseguí hacerlo funcionar\nOPCION 2.- Configurar un middleware de crowdsec sin Appsec para Nextcloud\nVamos a actuar sobre traefik. El plan es sencillo y a la vez potente. Añadiremos un nuevo middleware llamado crowdsec-bouncer-noappsec en middlewares.yml y lo usaremos en el router de Nextcloud.\nNuestro Nextcloud no tendrá la protección del WAF Appsec pero nos protege igualmente Crowdsec.\nnano ~/traefik-crowdsec/traefik/conf.d/middlewares.yml # Añadimos el siguiente middleware después del middleware crowdsec-bouncer: crowdsec-bouncer-noappsec: plugin: crowdsec-bouncer: Enabled: true CrowdsecMode: stream bouncerName: \u0026#34;traefik-bouncer\u0026#34; CrowdsecLapiScheme: \u0026#34;http\u0026#34; CrowdsecLapiHost: \u0026#34;crowdsec:8080\u0026#34; CrowdsecLapiKey: \u0026#34;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\u0026#34; RedisCacheEnabled: true RedisCacheHost: \u0026#34;crowdsec-redis:6379\u0026#34; CrowdsecAppsecEnabled: false ForwardedHeadersCustomName: \u0026#34;X-Forwarded-For\u0026#34; ForwardedHeadersTrustedIps: - \u0026#34;103.21.244.0/22\u0026#34; - \u0026#34;103.22.200.0/22\u0026#34; - \u0026#34;103.31.4.0/22\u0026#34; - \u0026#34;104.16.0.0/13\u0026#34; - \u0026#34;104.24.0.0/14\u0026#34; - \u0026#34;108.162.192.0/18\u0026#34; - \u0026#34;131.0.72.0/22\u0026#34; - \u0026#34;141.101.64.0/18\u0026#34; - \u0026#34;162.158.0.0/15\u0026#34; - \u0026#34;172.64.0.0/13\u0026#34; - \u0026#34;173.245.48.0/20\u0026#34; - \u0026#34;188.114.96.0/20\u0026#34; - \u0026#34;190.93.240.0/20\u0026#34; - \u0026#34;197.234.240.0/22\u0026#34; - \u0026#34;198.41.128.0/17\u0026#34; NOTAS IMPORTANTES: Podemos usar el mismo CrowdsecLapiKey para los dos middleware\nModificamos nuestro fichero estático de Nextcloud:\nnano ~/traefik-crowdsec/traefik/conf.d/nextcloud.yml # Contenido: http: routers: nextcloud: rule: \u0026#34;Host(`nextcloud.lafinquina.com`)\u0026#34; service: nextcloud entryPoints: - websecure tls: {} # o simplemente ‘tls: true’ en v3 middlewares: - geoblock-es - crowdsec-bouncer-noappsec # \u0026lt;----- Este es el nuevo middleware - security-headers services: nextcloud: loadBalancer: servers: - url: \u0026#34;http://100.105.100.10:8666\u0026#34; En este caso no es necesario reiniciar, ya que traefik cargará la nueva configuración de forma automática. Esperamos unos segundos y ya debería estar cargada la nueva configuración: Actualización de escenarios Crowdsec Mantener los escenarios y parsers actualizados es vital, ya que los atacantes cambian sus tácticas constantemente. En Docker, esto es sencillo de verificar.\ndocker exec -it crowdsec cscli hub update # Este comando te mostrará una tabla con todo tu software de seguridad (escenarios, parsers, colecciones). Fíjate en la columna que indica si hay versiones nuevas: docker exec -it crowdsec cscli hub list # Si tenemos actualizaciones disponibles: docker exec -it crowdsec cscli hub upgrade Para que los cambios surtan efecto, reiniciamos el motor de Crowdsec:\ndocker exec -it crowdsec kill -SIGHUP 1 # o simplemente reiniciamos el contenedor con: docker restart crowdsec Vamos a automatizarlo con timers de systemd.\nScript de actualización:\nsudo nano /usr/local/bin/crowdsec-update.sh # Contenido: #!/bin/bash set -e COMPOSE_DIR=\u0026#34;/home/noe/traefik-crowdsec\u0026#34; echo \u0026#34;Actualizando CrowdSec hub...\u0026#34; docker exec crowdsec cscli hub update docker exec crowdsec cscli hub upgrade --force echo \u0026#34;Reiniciando CrowdSec...\u0026#34; cd \u0026#34;$COMPOSE_DIR\u0026#34; \u0026amp;\u0026amp; docker compose restart crowdsec echo \u0026#34;Actualización completada.\u0026#34; Lo hacemos ejecutable:\nsudo chmod +x /usr/local/bin/crowdsec-update.sh Creamos el servicio systemd:\nsudo nano /etc/systemd/system/crowdsec-update.service # Contenido: [Unit] Description=CrowdSec hub update Requires=docker.service After=docker.service [Service] Type=oneshot ExecStart=/usr/local/bin/crowdsec-update.sh StandardOutput=journal StandardError=journal Timer Unit:\nsudo nano /etc/systemd/system/crowdsec-update.timer # Contenido: [Unit] Description=CrowdSec hub update semanal [Timer] OnCalendar=Sun *-*-* 03:00:00 Persistent=true # El Persistent=true garantiza que si el servidor estaba apagado el domingo a las 3:00, ejecuta la actualización en el próximo arranque. RandomizedDelaySec=10min [Install] WantedBy=timers.target Y activamos\nsudo systemctl daemon-reload sudo systemctl enable --now crowdsec-update.timer Verificaciones:\n# Estado del timer systemctl status crowdsec-update.timer # Cuándo ejecutará la próxima vez systemctl list-timers crowdsec-update.timer # Probar manualmente sudo systemctl start crowdsec-update.service journalctl -u crowdsec-update.service -f Configuración de CAPI en Crowdsec CAPI significa Central API. Es la red de inteligencia colectiva de CrowdSec.\nCon CAPI activado: El servidor recibe una lista de miles de IPs que ya han sido reportadas como maliciosas por otros usuarios de CrowdSec en el mundo. Las bloqueas antes de que toquen nuestro servidor.\nCon CAPI desactivado: El servidor está en modo \u0026ldquo;isla\u0026rdquo;. Solo bloquea lo que él mismo detecta. Es mucho menos eficiente.\nModificamos el docker-compose:\nservices: crowdsec: # ... environment: - DISABLE_CAPI=false # Permitir inteligencia colectiva y Consola A veces se desactiva por privacidad extrema (para no enviar señales de ataque a los servidores de CrowdSec) o para ahorrar un mínimo de ancho de banda. Pero para un VPS estándar con Traefik, tenerlo en false es lo recomendado para estar protegido por la \u0026ldquo;inmunidad de grupo\u0026rdquo;.\nReiniciamos docker compose:\ndocker compose restart Accedemos a nuestra consola de crowdsec app.crowdsec.net y vamos a Engines y Enroll y nos dará la key para hacer el enrolado:\ndocker exec crowdsec cscli console enroll XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX Verificamos:\ndocker exec crowdsec cscli console status +--------------------+-----------+------------------------------------------------------+ | Option Name | Activated | Description | +--------------------+-----------+------------------------------------------------------+ | custom | ✅ | Forward alerts from custom scenarios to the console | | manual | ✅ | Forward manual decisions to the console | | tainted | ✅ | Forward alerts from tainted scenarios to the console | | context | ✅ | Forward context with alerts to the console | | console_management | ❌ | Receive decisions from console | +--------------------+-----------+------------------------------------------------------+ Ahora mismo la comunicación es unidireccional: el VPS le cuenta cosas a la consola. Si activamos la última opción, la comunicación será bidireccional:\n1.- Bloqueo remoto: Si ves una IP atacándote desde el móvil en la web de la consola, podrás darle a \u0026ldquo;Ban\u0026rdquo; y la consola le dirá a tu VPS que la bloquee inmediatamente.\n2.- Suscripción a listas: Podrás suscribirte a listas de bloqueo de terceros (por ejemplo, \u0026ldquo;IPs de nodos de salida Tor\u0026rdquo; o \u0026ldquo;Bad Bots\u0026rdquo;) desde la web y se aplicarán solas en tu Traefik.\nVamos a activarla:\ndocker exec crowdsec cscli console enable console_management docker compose restart crowdsec docker exec crowdsec cscli console status # Salida: +--------------------+-----------+------------------------------------------------------+ | Option Name | Activated | Description | +--------------------+-----------+------------------------------------------------------+ | custom | ✅ | Forward alerts from custom scenarios to the console | | manual | ✅ | Forward manual decisions to the console | | tainted | ✅ | Forward alerts from tainted scenarios to the console | | context | ✅ | Forward context with alerts to the console | | console_management | ✅ | Receive decisions from console | +--------------------+-----------+------------------------------------------------------+ Verificamos el estado:\ndocker exec crowdsec cscli capi status # Salida: Loaded credentials from /etc/crowdsec//online_api_credentials.yaml You can successfully interact with Central API (CAPI) Your instance is enrolled in the console Subscription type: COMMUNITY Sharing signals is enabled Pulling community blocklist is enabled Pulling blocklists from the console is enabled Con esto, obtenemos una protección muy superior a la que ya teníamos.\nPara ver los ataques accedemos a app.crowdsec.net y en la sección Alerts tenemos los datos por IP, paises, tipo ataque, motivo baneo, etc.\nLimpieza de logs de traefik Hay que tener cuidado con los logs de traefik. Revisando un par de dias después de la configuración vi que tenía casi 100MB de logs. Vamos a configurar la limpieza.\nEl trabajo de limpieza lo hacemos en el host ya que tenemos un volumen donde montamos los logs según nuestro docker compose.\nInstalación de logrotate:\n# En caso de no estar instalado: sudo apt install logrotate Archivo de configuración:\nsudo nano /etc/logrotate.d/traefik #Pegamos lo siguiente: /home/MI_USUARIO/traefik-crowdsec/traefik/logs/*.log { daily rotate 7 size 50M compress delaycompress missingok notifempty copytruncate } #Explicación: daily: rota los logs cada día. rotate 7: conserva 7 días de logs antes de eliminarlos. size 50M: si superamos los 50M se hace la rotación compress / delaycompress: comprime los logs antiguos (en .gz) al siguiente ciclo. missingok: ignora si el archivo no existe. notifempty: no rota si está vacío. copytruncate: copia el log y limpia el original sin interrumpir Traefik (importante para contenedores). Prueba de funcionamiento:\nsudo logrotate -f /etc/logrotate.d/traefik error: skipping \u0026#34;/home/noe/traefik-crowdsec/traefik/logs/access.log\u0026#34; because parent directory has insecure permissions (It\u0026#39;s world writable or writable by group which is not \u0026#34;root\u0026#34;) Set \u0026#34;su\u0026#34; directive in config file to tell logrotate which user/group should be used for rotation. Este error se produce porque logrotate es muy tiquismikis con los permisos. Yo lo he solucionado de la siguiente forma:\n# Dentro del directorio traefik ejecutamos sudo chown root:root logs Y ya funciona correctamente.\nMejoras en sistema de actualizaciones de crowdsec Vamos a mejorar nuestro sistema, poniendo las actualizaciones de Telegram más chulas y añadiendo un pulsador de unban para IPs que se baneen por error.\nModificamos nuestro docker compose:\nEste servicio es el encargado de interaccionar con crowdsec para desbanear IPs\n# Añadimos un nuevo servicio: crowdsec-decisions-bot: image: lluisd/crowdsec-decisions-bot:latest container_name: crowdsec-decisions-bot restart: unless-stopped ports: - \u0026#34;3005:3000\u0026#34; environment: - TELEGRAM_TOKEN=${TELEGRAM_TOKEN} # Token de BotFather - LAPI_URL=http://crowdsec:8080 # URL de tu contenedor CrowdSec - LAPI_LOGIN=${LAPI_LOGIN} - LAPI_PASSWORD=${LAPI_PASSWORD} networks: - infra_network Nuestro fichero .env:\nTZ=Europe/Madrid # Cloudflare API_TOKEN CF_DNS_API_TOKEN=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX # Telegram_TOKEN TELEGRAM_TOKEN=555555555555:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX # LAPI Credentials LAPI_LOGIN=bot-watcher LAPI_PASSWORD=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX TELEGRAM_TOKEN es el token de nuestro bot telegram.\nPara obtener los datos LAPI tenemos que crear una nueva machine en crowdsec:\ndocker exec crowdsec cscli machines add bot-watcher --force -a # Si no usamos la opción --force nos dirá crowdsec que ya existe un fichero crowdsec/config/local_api_credentials.yaml y no hará nada. # La opción -a es para que cree el password de forma automática sudo cat crowdsec/config/local_api_credentials.yaml # Aquí ya tenemos los datos que necesitamos, los copiamos a nuestro fichero .env: url: http://0.0.0.0:8080 login: bot-watcher password: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX Verificamos las machines que tenemos:\ndocker exec crowdsec cscli machines list ---------------------------------------------------------------------------------------------------------------------------------- Name IP Address Last Update Status Version OS Auth Type Last Heartbeat ---------------------------------------------------------------------------------------------------------------------------------- localhost 127.0.0.1 2026-04-07T21:55:13Z ✔️ v1.7.6-eacc8192-docker alpine (docker)/3.21.5 password 27s bot-watcher 127.0.0.1 2026-04-07T21:42:11Z ✔️ v1.7.6-eacc8192-docker ? password ⚠️ - ---------------------------------------------------------------------------------------------------------------------------------- Arrancamos el servicio y verificamos que esté operativo:\n# Levantamos el servicio: docker compose up -d crowdsec-decisions-bot # Verificamos los logs: docker logs -f crowdsec-decisions-bot \u0026gt; crowdsec-decisions-bot@1.0.0 start \u0026gt; node ./app.js Listening on port 3000 Telegram bot on Polling mode [....] Ahora vamos a crear un nuevo modelo de notificaciones en crowdsec.\nCreamos nuestro fichero crowdsec/config/notifications/telegram_default.yaml\n# CUMPLIMENTAR LOS SIGUIENTES DATOS: # chat_id # apiKey de geoapify.com # url de Telegram con datos de nuestro bot type: http name: telegram log_level: info format: | { \u0026#34;chat_id\u0026#34;: \u0026#34;XXXXXXXXX\u0026#34;, \u0026#34;photo\u0026#34;: \u0026#34;https://maps.geoapify.com/v1/staticmap?style=osm-bright-grey\u0026amp;width=600\u0026amp;height=400\u0026amp;center=lonlat:{{(index . 0).Source.Longitude}},{{(index . 0).Source.Latitude}}\u0026amp;zoom=8\u0026amp;marker=lonlat:{{(index . 0).Source.Longitude}},{{(index . 0).Source.Latitude}};type:material;color:%23ff3421;size:large\u0026amp;scaleFactor=2\u0026amp;apiKey=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\u0026#34;, \u0026#34;caption\u0026#34;: \u0026#34;{{range . -}}{{$alert := . -}}{{range .Decisions -}}{{- $cti := $alert.Source.Value | CrowdsecCTI -}}{{- $flags := dict \u0026#34;US\u0026#34; \u0026#34;🇺🇸\u0026#34; \u0026#34;FR\u0026#34; \u0026#34;🇫🇷\u0026#34; \u0026#34;DE\u0026#34; \u0026#34;🇩🇪\u0026#34; \u0026#34;MX\u0026#34; \u0026#34;🇲🇽\u0026#34; \u0026#34;GB\u0026#34; \u0026#34;🇬🇧\u0026#34; \u0026#34;HK\u0026#34; \u0026#34;🇭🇰\u0026#34; \u0026#34;ES\u0026#34; \u0026#34;🇪🇸\u0026#34; \u0026#34;NL\u0026#34; \u0026#34;🇳🇱\u0026#34; \u0026#34;JP\u0026#34; \u0026#34;🇯🇵\u0026#34; \u0026#34;AR\u0026#34; \u0026#34;🇦🇷\u0026#34; \u0026#34;BR\u0026#34; \u0026#34;🇧🇷\u0026#34; \u0026#34;CA\u0026#34; \u0026#34;🇨🇦\u0026#34; \u0026#34;AU\u0026#34; \u0026#34;🇦🇺\u0026#34; \u0026#34;IN\u0026#34; \u0026#34;🇮🇳\u0026#34; \u0026#34;IT\u0026#34; \u0026#34;🇮🇹\u0026#34; \u0026#34;RU\u0026#34; \u0026#34;🇷🇺\u0026#34; \u0026#34;CN\u0026#34; \u0026#34;🇨🇳\u0026#34; \u0026#34;SA\u0026#34; \u0026#34;🇸🇦\u0026#34; \u0026#34;ZA\u0026#34; \u0026#34;🇿🇦\u0026#34; \u0026#34;KR\u0026#34; \u0026#34;🇰🇷\u0026#34; \u0026#34;ID\u0026#34; \u0026#34;🇮🇩\u0026#34; \u0026#34;NG\u0026#34; \u0026#34;🇳🇬\u0026#34; \u0026#34;EG\u0026#34; \u0026#34;🇪🇬\u0026#34; \u0026#34;TR\u0026#34; \u0026#34;🇹🇷\u0026#34; \u0026#34;SE\u0026#34; \u0026#34;🇸🇪\u0026#34; \u0026#34;NO\u0026#34; \u0026#34;🇳🇴\u0026#34; \u0026#34;DK\u0026#34; \u0026#34;🇩🇰\u0026#34; \u0026#34;FI\u0026#34; \u0026#34;🇫🇮\u0026#34; \u0026#34;PL\u0026#34; \u0026#34;🇵🇱\u0026#34; \u0026#34;PT\u0026#34; \u0026#34;🇵🇹\u0026#34; \u0026#34;CH\u0026#34; \u0026#34;🇨🇭\u0026#34; \u0026#34;BE\u0026#34; \u0026#34;🇧🇪\u0026#34; \u0026#34;AT\u0026#34; \u0026#34;🇦🇹\u0026#34; \u0026#34;SG\u0026#34; \u0026#34;🇸🇬\u0026#34; \u0026#34;MY\u0026#34; \u0026#34;🇲🇾\u0026#34; \u0026#34;TH\u0026#34; \u0026#34;🇹🇭\u0026#34; \u0026#34;PH\u0026#34; \u0026#34;🇵🇭\u0026#34; \u0026#34;VN\u0026#34; \u0026#34;🇻🇳\u0026#34; \u0026#34;PK\u0026#34; \u0026#34;🇵🇰\u0026#34; \u0026#34;BD\u0026#34; \u0026#34;🇧🇩\u0026#34; \u0026#34;UA\u0026#34; \u0026#34;🇺🇦\u0026#34; \u0026#34;RO\u0026#34; \u0026#34;🇷🇴\u0026#34; \u0026#34;HU\u0026#34; \u0026#34;🇭🇺\u0026#34; \u0026#34;BG\u0026#34; \u0026#34;🇧🇬\u0026#34; \u0026#34;SK\u0026#34; \u0026#34;🇸🇰\u0026#34; \u0026#34;HR\u0026#34; \u0026#34;🇭🇷\u0026#34; \u0026#34;SI\u0026#34; \u0026#34;🇸🇮\u0026#34; \u0026#34;EE\u0026#34; \u0026#34;🇪🇪\u0026#34; \u0026#34;LV\u0026#34; \u0026#34;🇱🇻\u0026#34; \u0026#34;LT\u0026#34; \u0026#34;🇱🇹\u0026#34; \u0026#34;CZ\u0026#34; \u0026#34;🇨🇿\u0026#34; \u0026#34;IS\u0026#34; \u0026#34;🇮🇸\u0026#34; \u0026#34;GR\u0026#34; \u0026#34;🇬🇷\u0026#34; \u0026#34;AE\u0026#34; \u0026#34;🇦🇪\u0026#34; \u0026#34;KW\u0026#34; \u0026#34;🇰🇼\u0026#34; \u0026#34;OM\u0026#34; \u0026#34;🇴🇲\u0026#34; \u0026#34;QA\u0026#34; \u0026#34;🇶🇦\u0026#34; \u0026#34;BH\u0026#34; \u0026#34;🇧🇭\u0026#34; \u0026#34;MA\u0026#34; \u0026#34;🇲🇦\u0026#34; \u0026#34;TN\u0026#34; \u0026#34;🇹🇳\u0026#34; \u0026#34;DZ\u0026#34; \u0026#34;🇩🇿\u0026#34; \u0026#34;LY\u0026#34; \u0026#34;🇱🇾\u0026#34; \u0026#34;JO\u0026#34; \u0026#34;🇯🇴\u0026#34; \u0026#34;LB\u0026#34; \u0026#34;🇱🇧\u0026#34; \u0026#34;SY\u0026#34; \u0026#34;🇸🇾\u0026#34; \u0026#34;IQ\u0026#34; \u0026#34;🇮🇶\u0026#34; \u0026#34;YE\u0026#34; \u0026#34;🇾🇪\u0026#34; \u0026#34;IR\u0026#34; \u0026#34;🇮🇷\u0026#34; \u0026#34;MN\u0026#34; \u0026#34;🇲🇳\u0026#34; \u0026#34;KP\u0026#34; \u0026#34;🇰🇵\u0026#34; \u0026#34;TW\u0026#34; \u0026#34;🇹🇼\u0026#34; \u0026#34;MO\u0026#34; \u0026#34;🇲🇴\u0026#34; \u0026#34;LC\u0026#34; \u0026#34;🇱🇨\u0026#34; \u0026#34;TT\u0026#34; \u0026#34;🇹🇹\u0026#34; \u0026#34;VC\u0026#34; \u0026#34;🇻🇨\u0026#34; \u0026#34;BB\u0026#34; \u0026#34;🇧🇧\u0026#34; \u0026#34;JM\u0026#34; \u0026#34;JJAM\u0026#34; \u0026#34;BS\u0026#34; \u0026#34;🇧🇸\u0026#34; \u0026#34;GD\u0026#34; \u0026#34;🇬🇩\u0026#34; \u0026#34;HT\u0026#34; \u0026#34;🇭🇹\u0026#34; \u0026#34;DO\u0026#34; \u0026#34;🇩🇴\u0026#34; \u0026#34;CR\u0026#34; \u0026#34;🇨🇷\u0026#34; \u0026#34;PY\u0026#34; \u0026#34;🇵🇾\u0026#34; \u0026#34;PE\u0026#34; \u0026#34;🇵🇪\u0026#34; \u0026#34;EC\u0026#34; \u0026#34;🇪🇨\u0026#34; \u0026#34;CO\u0026#34; \u0026#34;🇨🇴\u0026#34; \u0026#34;VE\u0026#34; \u0026#34;🇻🇪\u0026#34; \u0026#34;CL\u0026#34; \u0026#34;🇨🇱\u0026#34; \u0026#34;BO\u0026#34; \u0026#34;🇧🇴\u0026#34; \u0026#34;GT\u0026#34; \u0026#34;🇬🇹\u0026#34; \u0026#34;HN\u0026#34; \u0026#34;🇭🇳\u0026#34; \u0026#34;SV\u0026#34; \u0026#34;🇸🇻\u0026#34; \u0026#34;NI\u0026#34; \u0026#34;🇳🇮\u0026#34; \u0026#34;PA\u0026#34; \u0026#34;🇵🇦\u0026#34; \u0026#34;CU\u0026#34; \u0026#34;🇨🇺\u0026#34; -}}{{- $countryCode := upper $alert.Source.Cn -}}{{- $flag := index $flags $countryCode | default $countryCode -}}🚨 *Alerta CrowdSec* \\n\\n🔴 *IP:* [{{.Value}}](https://www.whois.com/whois/{{.Value}}) \\n⚠️ *Escenario:* `{{.Scenario}}` \\n⏱️ *Ban:* `{{.Duration}}` \\n🌍 *Ubicación:* {{ $flag }} {{ $alert.Source.Cn }} {{if $cti.Location.City}}- {{ $cti.Location.City | replace \u0026#34;\\\u0026#34;\u0026#34; \u0026#34;\u0026#34; }}{{end}} \\n💀 *Malicia:* {{mulf $cti.GetMaliciousnessScore 100 | floor}}% \\n🔊 *Ruido:* {{ $cti.GetBackgroundNoiseScore }}/10 \\n\\n{{range $alert.Meta -}}{{if not (or (eq .Key \u0026#34;source_ip\u0026#34;) (eq .Key \u0026#34;remediation\u0026#34;) (eq .Key \u0026#34;scenario\u0026#34;)) -}}🔹 *{{.Key}}*: `{{ (splitList \u0026#34;,\u0026#34; (.Value | replace \u0026#34;\\\u0026#34;\u0026#34; \u0026#34;\u0026#34; | replace \u0026#34;[\u0026#34; \u0026#34;\u0026#34; | replace \u0026#34;]\u0026#34; \u0026#34;\u0026#34;)) | join \u0026#34; \u0026#34; }}` \\n{{end}}{{end}}{{- end -}}{{- end -}}\u0026#34;, \u0026#34;parse_mode\u0026#34;: \u0026#34;Markdown\u0026#34;, \u0026#34;reply_markup\u0026#34;: { \u0026#34;inline_keyboard\u0026#34;: [ {{- $arrLength := len . -}} {{- range $i, $value := . -}} {{- $V := (index $value.Decisions 0).Value -}} [ { \u0026#34;text\u0026#34;: \u0026#34;🛡️ Ver en CrowdSec CTI\u0026#34;, \u0026#34;url\u0026#34;: \u0026#34;https://app.crowdsec.net/cti/{{ $V }}\u0026#34; } ], [ { \u0026#34;text\u0026#34;: \u0026#34;🔎 Shodan\u0026#34;, \u0026#34;url\u0026#34;: \u0026#34;https://www.shodan.io/host/{{ $V }}\u0026#34; } ], [ { \u0026#34;text\u0026#34;: \u0026#34;🔓 UNBAN IP\u0026#34;, \u0026#34;callback_data\u0026#34;: \u0026#34;deleteDecisions~{{ $V }}\u0026#34; } ]{{if lt $i (sub $arrLength 1)}},{{end}} {{- end -}} ] } } url: https://api.telegram.org/bot111111111:XXXXXXXXXXXXXXXXXXXXXXXXXXXXX/sendPhoto method: POST headers: Content-Type: \u0026#34;application/json\u0026#34; Para configurar correctamente nuestro fichero tenemos que abrir una cuenta en Geoapify. Una vez lo tenemos creamos un nuevo proyecto: Y creamos una nueva API Key de tipo Map Tiles: Y copiamos la APIKey al fichero de notificaciones:\n\u0026#34;photo\u0026#34;: \u0026#34;https://maps.geoapify.com/v1/staticmap?style=osm-bright-grey\u0026amp;width=600\u0026amp;height=400\u0026amp;center=lonlat:{{(index . 0).Source.Longitude}},{{(index . 0).Source.Latitude}}\u0026amp;zoom=8\u0026amp;marker=lonlat:{{(index . 0).Source.Longitude}},{{(index . 0).Source.Latitude}};type:material;color:%23ff3421;size:large\u0026amp;scaleFactor=2\u0026amp;apiKey=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\u0026#34;, Por último, solo nos queda modificar nuestro fichero crowdsec/config/profiles.yaml:\n# 0. PERFIL PARA MEGA-REINCIDENTES (Primero en la lista) name: mega_reincident_remediation filters: # Usamos la función correcta para contar decisiones previas de esa IP - Alert.Remediation == true \u0026amp;\u0026amp; Alert.GetScope() == \u0026#34;Ip\u0026#34; \u0026amp;\u0026amp; GetDecisionsCount(Alert.GetValue()) \u0026gt; 1 decisions: - type: ban duration: 720h # 1 mes de \u0026#34;nevera\u0026#34; #notifications: # - telegram_default on_success: break # Si entra aquí, no sigue leyendo hacia abajo --- # 1. PERFIL PARA REINCIDENTES (Primero en la lista) name: reincident_remediation filters: # Usamos la función correcta para contar decisiones previas de esa IP - Alert.Remediation == true \u0026amp;\u0026amp; Alert.GetScope() == \u0026#34;Ip\u0026#34; \u0026amp;\u0026amp; GetDecisionsCount(Alert.GetValue()) == 1 decisions: - type: ban duration: 168h # 1 semana de \u0026#34;nevera\u0026#34; notifications: - telegram_default on_success: break # Si entra aquí, no sigue leyendo hacia abajo --- # 2. PERFIL POR DEFECTO PARA IPs name: default_ip_remediation #debug: true filters: - Alert.Remediation == true \u0026amp;\u0026amp; Alert.GetScope() == \u0026#34;Ip\u0026#34; decisions: - type: ban duration: 48h notifications: - telegram_default #duration_expr: Sprintf(\u0026#39;%dh\u0026#39;, (GetDecisionsCount(Alert.GetValue()) + 1) * 4) # notifications: # - slack_default # Set the webhook in /etc/crowdsec/notifications/slack.y\u0026gt; # - splunk_default # Set the splunk url and token in /etc/crowdsec/notifica\u0026gt; # - http_default # Set the required http parameters in /etc/crowdsec/noti\u0026gt; # - email_default # Set the required email parameters in /etc/crowdsec/not\u0026gt; on_success: break --- # 3. PERFIL PARA RANGOS name: default_range_remediation #debug: true filters: - Alert.Remediation == true \u0026amp;\u0026amp; Alert.GetScope() == \u0026#34;Range\u0026#34; decisions: - type: ban duration: 48h #duration_expr: Sprintf(\u0026#39;%dh\u0026#39;, (GetDecisionsCount(Alert.GetValue()) + 1) * 4) # notifications: # - slack_default # Set the webhook in /etc/crowdsec/notifications/slack.y\u0026gt; # - splunk_default # Set the splunk url and token in /etc/crowdsec/notifica\u0026gt; # - http_default # Set the required http parameters in /etc/crowdsec/noti\u0026gt; # - email_default # Set the required email parameters in /etc/crowdsec/not\u0026gt; on_success: break Esta nueva versión hace lo siguiente:\n# 2. PERFIL POR DEFECTO PARA IPs - Alert.Remediation == true \u0026amp;\u0026amp; Alert.GetScope() == \u0026#34;Ip\u0026#34; # Si detecta una IP la banea 48 horas y envía notificación # 1. PERFIL PARA REINCIDENTES (Primero en la lista) - Alert.Remediation == true \u0026amp;\u0026amp; Alert.GetScope() == \u0026#34;Ip\u0026#34; \u0026amp;\u0026amp; GetDecisionsCount(Alert.GetValue()) == 1 # Si detecta un reincidente lo banea 1 semana y envía notificación # 0. PERFIL PARA MEGA-REINCIDENTES (Primero en la lista) - Alert.Remediation == true \u0026amp;\u0026amp; Alert.GetScope() == \u0026#34;Ip\u0026#34; \u0026amp;\u0026amp; GetDecisionsCount(Alert.GetValue()) \u0026gt; 1 # Si detecta un super-reincidente lo banea 1 mes y NO envía notificación # NO QUIERO EL GRUPO DE TELEGRAM LLENO DE MENSAJES # El perfil para rangos no lo he tocado. Prueba. Baneamos una IP\ndocker exec crowdsec cscli decisions add --ip 1.2.3.4 --reason \u0026#34;Prueba de Bot\u0026#34; # Verificamos en la lista docker exec crowdsec cscli decisions list # Arrancamos los logs de nuestro crowdsec-decisions-bot: docker logs -f crowdsec-decisions-bot Ejemplo notificación: # Pulsamos en unban de Telegram y deberíamos ver lo siguiente: docker logs -f crowdsec-decisions-bot \u0026gt; crowdsec-decisions-bot@1.0.0 start \u0026gt; node ./app.js Listening on port 3000 Telegram bot on Polling mode Calling /v1/decisions?ip=1.2.3.4 Calling /v1/watchers/login 1 decision deleted for IP: 1.2.3.4 # Verificamos en la lista nuevamente que ya no esté la IP docker exec crowdsec cscli decisions list Fuentes y enlaces de interés que ayudaran a complementar esta guía:\nDebo decir que en esta guía he tirado mucho de IA.\nInstalación de traefik sin etiquetas Crowdsec WAF - Appsec\nWeb oficial de borgmatic\nAgradecimientos en Telegram para @joled y @lluis2k del Grupo Detras del mostraddor que me ayudaron en las mejoras del sistema de actualizaciones de Crowdsec.\n","permalink":"https://blog.lasnotasdenoah.com/posts/vps-proxy/","summary":"\u003ch2 id=\"traefik-y-crowdsec\"\u003eTraefik y crowdsec\u003c/h2\u003e\n\u003cp\u003eEstoy hasta el gorro de la liga y sus puñeteros bloqueos.  Este blog y mis servicios estaban configurados en el NAS con un traefik como proxy inverso. Para proteger mi IP pública uso el Proxied de cloudflare, que además aporta un WAF muy potente, geolocalización, etc. \u003cstrong\u003ePROBLEMA\u003c/strong\u003e: cada vez que hay futbol pierdo la conexión a homeassistant y otros servicios que para mi son muy importantes.\u003c/p\u003e\n\u003cp\u003eHoy vamos a configurar traefik en un VPS y desde allí enrutamos todo el tráfico a nuestro NAS local a través de Tailscale.  Desactivaremos el proxied de cloudflare y de esta forma no está expuesta mi IP pública, sólo está expuesta la IP del VPS.\u003cbr\u003e\nHe contratado el VPS más económico que tiene \u003ca href=\"https://www.piensasolutions.com/\"\u003ePiensasolutions\u003c/a\u003e. En mi caso pago 0,75€ al mes durante 12 meses y después el coste pasa a ser 1€ al mes.\u003cbr\u003e\nEl VPS tiene 1 GB de RAM, 1 vCPU, 10GB SSD NVMe y conexión de 1Gbps.\u003cbr\u003e\nAl principio intenté instalar Pangolín, que ya lo tuve operativo en un VPS de prueba más potente. Pero creo que en este servidor es muy exigente y no puede para nada con él. Solo Pangolín consume 300 Mb de RAM más el sistema, crowdsec, etc. IMPOSIBLE !!!!!\u003c/p\u003e","title":"Proxy Inverso en VPS"},{"content":"Traefik y crowdsec Hasta hace poco tenía en funcionamiento traefik con crowdsec usando las plantillas de unraid. Hice varios manuales sobre la instalación pero por motivos que desconozco crowdsec no parseaba las líneas de logs de traefik y por tanto no hacía absolutamente nada.\nHe decicido hacer una instalación limpia desde 0 y aquí va.\nGran parte de este manual se ha hecho usando Perplexity. Debo decir que tiene mucho que mejorar, pero nos marca unas bases buenas para empezar.\nPreparación del entorno Lo primero que vamos a hacer es preparar nuestro entorno de directorios:\nDirectorios de traefik y crowdsec:\nmkdir -p /mnt/user/appdata/traefik/{letsencrypt,log} mkdir -p /mnt/user/appdata/crowdsec/data Ficheros de configuración y logs de traefik:\ntouch /mnt/user/appdata/traefik/letsencrypt/acme.json chmod 600 /mnt/user/appdata/traefik/letsencrypt/acme.json touch /mnt/user/appdata/traefik/traefik.yml touch /mnt/user/appdata/traefik/dynamic_conf.yml touch /mnt/user/appdata/traefik/log/access.log chmod 644 /mnt/user/appdata/traefik/log/access.log Fichero de configuración de crowdsec. Dentro de la carpeta de configuración de crowdsec creamos el fichero acquis.yaml:\ntouch /mnt/user/appdata/crowdsec/config/acquis.yaml Docker-compose Sigo usando Unraid. Nos vamos a la pestaña compose y creamos nuestro stack de docker:\ndocker-compose.yml\nservices: traefik: image: traefik:v3.0 container_name: traefik restart: unless-stopped security_opt: - no-new-privileges:true ports: - \u0026#34;1880:80\u0026#34; - \u0026#34;18443:443\u0026#34; environment: - CF_DNS_API_TOKEN=${CF_DNS_API_TOKEN} # API TOKEN DE CLOUDFLARE volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - /mnt/user/appdata/traefik/letsencrypt/acme.json:/letsencrypt/acme.json - /mnt/user/appdata/traefik/traefik.yml:/etc/traefik/traefik.yml:ro - /mnt/user/appdata/traefik/dynamic_conf.yml:/etc/traefik/dynamic_conf.yml:ro - /mnt/user/appdata/traefik/log:/var/log/traefik # Volumen para persistencia de logs networks: - cloud crowdsec: image: crowdsecurity/crowdsec container_name: crowdsec restart: unless-stopped environment: - COLLECTIONS=crowdsecurity/traefik crowdsecurity/http-cve volumes: - /mnt/user/appdata/traefik/log:/var/log/traefik:ro # comparte los logs - /mnt/user/appdata/crowdsec/data:/var/lib/crowdsec/data - /mnt/user/appdata/crowdsec/config:/etc/crowdsec networks: - cloud networks: cloud: external: true Fichero .env\nCF_DNS_API_TOKEN=MI_API_KEY_CLOUDFLARE. # Se obtiene en el panel de cloudflare CROWDSEC_BOUNCER_API_KEY= xxxxxxxx # Con la última versión del docker-compose se puede borrar DOMAIN_NAME=mi_dominio.com # Con la última versión del docker-compose se puede borrar EMAIL=mi_correo@hotmail.com # Con la última versión del docker-compose se puede borrar Nota Importante: ES IMPRESCINDIBLE QUE LOS SERVICIOS QUE USEMOS CON TRAEFIK ESTÉN EN LA MISMA RED DOCKER. En mi caso se llama cloud\nFicheros de configuración Traefik - traefik.yml\napi: dashboard: false # Cuando necesito revisar el dashboard lo cambio a true y reinicio el contenedor. Mientras no sea necesario lo dejo en false. providers: docker: exposedByDefault: false network: cloud # Debe coincidir con el nombre de tu red externa en docker-compose file: fileName: /etc/traefik/dynamic_conf.yml watch: true entryPoints: web: address: \u0026#34;:80\u0026#34; http: redirections: entryPoint: to: websecure scheme: https websecure: address: \u0026#34;:443\u0026#34; transport: respondingTimeouts: idleTimeout: 3600 # 1. HABILITAR LOGS (Vital para que CrowdSec detecte ataques) accessLog: filePath: \u0026#34;/var/log/traefik/access.log\u0026#34; format: json bufferingSize: 100 fields: headers: defaultMode: keep # Mantiene headers para que CrowdSec vea IPs reales # 2. PLUGINS (CrowdSec Bouncer para Traefik v3) # # AQUI AÑADIREMOS EL PLUGIN DE CROWDSEC # # 3. CONFIGURACIÓN DE CERTIFICADOS (Cloudflare DNS Challenge) certificatesResolvers: cloudflare: acme: email: mi_correo@hotmail.com storage: /letsencrypt/acme.json dnsChallenge: provider: cloudflare resolvers: - \u0026#34;1.1.1.1:53\u0026#34; - \u0026#34;8.8.8.8:53\u0026#34; Traefik - dynamic_conf.yml\nhttp: routers: dashboard: rule: \u0026#34;Host(`traefik.mi_dominio.com`)\u0026#34; service: api@internal entryPoints: - websecure tls: certResolver: cloudflare middlewares: - auth - security-headers middlewares: auth: basicAuth: # Generar con: echo $(htpasswd -nB usuario) | sed -e s/\\\\$/\\\\$\\\\$/g users: - \u0026#34;noah:$mi_pass_hasheada\u0026#34; security-headers: headers: stsSeconds: 15552000 stsIncludeSubdomains: true stsPreload: true forceSTSHeader: true frameDeny: true # Previene Clickjacking contentTypeNosniff: true # Previene sniffing de MIME browserXssFilter: true referrerPolicy: \u0026#34;same-origin\u0026#34; # Ajuste para Nextcloud: customFrameOptionsValue: \u0026#34;SAMEORIGIN\u0026#34; # # AQUI AÑADIREMOS EL MIDDLEWARE DE CROWDSEC # Crowdsec - acquis.yaml\n--- filenames: - /var/log/traefik/access.log poll_without_inotify: true labels: type: traefik Integración del bouncer en traefik Iniciamos nuestro compose y no debería lanzar errores.\nEs momento de crear nuestra API key del bouncer crowdsec:\n--- docker exec -it crowdsec cscli bouncers add traefik-bouncer # te devolverá una API key, guárdala Verificamos que nuestras colecciones estén actualizadas:\ndocker exec -it crowdsec cscli hub update docker exec -it crowdsec cscli hub upgrade docker restart crowdsec Modificamos nuestros ficheros traefik.yml y dynamic_conf.yml para añadir lo siguente:\nTraefik - traefik.yml\nexperimental: plugins: crowdsec-bouncer: moduleName: github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin version: v1.3.5 Traefik - dynamic_conf.yml\nmiddlewares: [...AQUI TENEMOS NUESTROS OTROS MIDDLEWARES......] crowdsec-bouncer: plugin: crowdsec-bouncer: Enabled: true CrowdsecMode: live # o streaming si prefieres CrowdsecLapiUrl: \u0026#34;http://crowdsec:8080\u0026#34; CrowdsecLapiKey: \u0026#34;ESTA KEY SE GENERA MAS ADELANTE\u0026#34; ForwardedHeadersCustomName: \u0026#34;X-Forwarded-For\u0026#34; # Obtenemos la lista oficial de IPs con el siguiente comando: # curl https://www.cloudflare.com/ips-v4 -o cloudflare-ips-v4.txt ForwardedHeadersTrustedIps: - \u0026#34;103.21.244.0/22\u0026#34; - \u0026#34;103.22.200.0/22\u0026#34; - \u0026#34;103.31.4.0/22\u0026#34; - \u0026#34;104.16.0.0/13\u0026#34; - \u0026#34;104.24.0.0/14\u0026#34; - \u0026#34;108.162.192.0/18\u0026#34; - \u0026#34;131.0.72.0/22\u0026#34; - \u0026#34;141.101.64.0/18\u0026#34; - \u0026#34;162.158.0.0/15\u0026#34; - \u0026#34;172.64.0.0/13\u0026#34; - \u0026#34;173.245.48.0/20\u0026#34; - \u0026#34;188.114.96.0/20\u0026#34; - \u0026#34;190.93.240.0/20\u0026#34; - \u0026#34;197.234.240.0/22\u0026#34; - \u0026#34;198.41.128.0/17\u0026#34; Ficheros completos:\nTraefik - traefik.yml\napi: dashboard: false # Cuando necesito revisar el dashboard lo cambio a true y reinicio el contenedor. Mientras no sea necesario lo dejo en false. providers: docker: exposedByDefault: false network: cloud # Debe coincidir con el nombre de tu red externa en docker-compose file: fileName: /etc/traefik/dynamic_conf.yml watch: true entryPoints: web: address: \u0026#34;:80\u0026#34; http: redirections: entryPoint: to: websecure scheme: https websecure: address: \u0026#34;:443\u0026#34; transport: respondingTimeouts: idleTimeout: 3600 # 1. HABILITAR LOGS (Vital para que CrowdSec detecte ataques) accessLog: filePath: \u0026#34;/var/log/traefik/access.log\u0026#34; format: json bufferingSize: 100 fields: headers: defaultMode: keep # Mantiene headers para que CrowdSec vea IPs reales # 2. PLUGINS (CrowdSec Bouncer para Traefik v3) experimental: plugins: crowdsec-bouncer: moduleName: github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin version: v1.3.5 # 3. CONFIGURACIÓN DE CERTIFICADOS (Cloudflare DNS Challenge) certificatesResolvers: cloudflare: acme: email: mi_correo@hotmail.com storage: /letsencrypt/acme.json dnsChallenge: provider: cloudflare resolvers: - \u0026#34;1.1.1.1:53\u0026#34; - \u0026#34;8.8.8.8:53\u0026#34; Traefik - dynamic_conf.yml\nhttp: routers: dashboard: rule: \u0026#34;Host(`traefik.mi_dominio.com`)\u0026#34; service: api@internal entryPoints: - websecure tls: certResolver: cloudflare middlewares: - auth - security-headers - crowdsec-bouncer # Protegemos el dashboard con crowdsec middlewares: auth: basicAuth: # Generar con: echo $(htpasswd -nB usuario) | sed -e s/\\\\$/\\\\$\\\\$/g users: - \u0026#34;noah:$mi_pass_hasheada\u0026#34; security-headers: headers: stsSeconds: 15552000 stsIncludeSubdomains: true stsPreload: true forceSTSHeader: true frameDeny: true # Previene Clickjacking contentTypeNosniff: true # Previene sniffing de MIME browserXssFilter: true referrerPolicy: \u0026#34;same-origin\u0026#34; # Ajuste para Nextcloud: customFrameOptionsValue: \u0026#34;SAMEORIGIN\u0026#34; crowdsec-bouncer: plugin: crowdsec-bouncer: Enabled: true CrowdsecMode: live # o streaming si prefieres CrowdsecLapiUrl: \u0026#34;http://crowdsec:8080\u0026#34; CrowdsecLapiKey: \u0026#34;zEtyY2gJsQgQca03vEvWWwcowSG8f9yJz84nF95qZq4\u0026#34; ForwardedHeadersCustomName: \u0026#34;X-Forwarded-For\u0026#34; ForwardedHeadersTrustedIps: - \u0026#34;103.21.244.0/22\u0026#34; - \u0026#34;103.22.200.0/22\u0026#34; - \u0026#34;103.31.4.0/22\u0026#34; - \u0026#34;104.16.0.0/13\u0026#34; - \u0026#34;104.24.0.0/14\u0026#34; - \u0026#34;108.162.192.0/18\u0026#34; - \u0026#34;131.0.72.0/22\u0026#34; - \u0026#34;141.101.64.0/18\u0026#34; - \u0026#34;162.158.0.0/15\u0026#34; - \u0026#34;172.64.0.0/13\u0026#34; - \u0026#34;173.245.48.0/20\u0026#34; - \u0026#34;188.114.96.0/20\u0026#34; - \u0026#34;190.93.240.0/20\u0026#34; - \u0026#34;197.234.240.0/22\u0026#34; - \u0026#34;198.41.128.0/17\u0026#34; Obtener las IPs confiables de cloudflare Para configurar ForwardedHeadersTrustedIps con precisión en el middleware de CrowdSec, se usan las IPs de Cloudflare. Esto evita que IPs falsas se usen para evadir bloqueos.\n​ Lista oficial de IPs de Cloudflare.\nCloudflare publica sus rangos IPv4/IPv6 en dos archivos JSON. Los podemos obetner así\n# Desde la terminal de Unraid (donde corre Docker) curl https://www.cloudflare.com/ips-v4 -o cloudflare-ips-v4.txt curl https://www.cloudflare.com/ips-v6 -o cloudflare-ips-v6.txt Las IPs que obtenemos las añadimos al fichero dynamic_conf.yml, apartado ForwardedHeadersTrustedIps del middleware crowdsec-bouncer.\nPuesta en marcha y comprobación Con todo esto reiniciamos el stack de docker y debería arrancar funcionando sin errores. Revisaremos los logs para verificar fallos.\ndocker compose down docker compose up -d # En Unraid lo hacemos de forma gráfica docker logs traefik | grep -i crowdsec docker logs crowdsec docker exec crowdsec cscli decisions list Comandos intersantes de crowdsec:\n# Listado de decisiones tomadas docker exec -it crowdsec cscli decisions list # Métricas completas de crowdsec docker exec -it crowdsec cscli metrics # Unban IP docker exec -it crowdsec cscli decisions delete -i x.x.x.x # Banear una IP docker exec -it crowdsec cscli decisions add --ip xx.xx.xx.xx --duration 1h Enrutar servicios a través de traefik Las etiquetas básicas que debe llevar cualquier servicio para que traefik lo enrute son las siguientes:\n# Ejemplo para nuestro karakeep traefik.enable=true traefik.http.routers.karakeep.rule=Host(`karakeep.mi_dominio.com`) traefik.http.routers.karakeep.entrypoints=websecure traefik.http.routers.karakeep.tls.certresolver=cloudflare traefik.http.services.karakeep.loadbalancer.server.port=3000 # middelware que vamos a aplicar a este servcio traefik.http.routers.karakeep.middlewares=crowdsec-bouncer@file,security-headers@file IMPORTANTE: La etiqueta traefik.http.services.karakeep.loadbalancer.server.port debe indicar el puerto interno del contenedor, ya que tenemos que recordar que nuestros servicios siempre deben estar en la misma red que traefik para que funcionen.\nEn mi caso, el docker-compose de karakeep lleva la siguiente configuración de puertos porque el puerto 3000 lo estoy usando para otro servicio:\n[....] ports: - 3333:3000 [....] Entonces, el acceso a karakeep a través de la red local es:\nhttp://192.168.10.55:3333\nPero traefik sólo entiende de la red docker, por lo que el puerto para traefik es 3000.\nProtección de servicios con crowdsec Hemos configurado crowdsec como un middleware, por tanto, la solicitud de conexión al servicio debe pasar antes por crowdsec que dirá si permite esa conexión o no.\nPara proteger servicios tenemos dos opciones:\n1.- Configuración estática en dynamic_conf.yml\n2.- Etiquetas traefik en el servicio en cuestión.\nPor facilidad vamos a hacer la segunda opción, a través de etiquetas, así mantenemos más limpio el dynamic_conf.yml y traefik hace una carga en vivo sin reiniciar el proxy.\nEtiqueta:\n# Ejemplo para Nextcloud. El resto de servicios sería exactamente igual traefik.http.routers.nextcloud.middlewares=rowdsec-bouncer@file,security-headers@file Protección de Nextcloud Crowdsec tiene una colección específica para Nextcloud. Vamos a proteger nuestra instancia.\nModificamos el docker-compose añadiendo la colección de crowdsecurity/nextcloud y montando la carpeta donde almacenamos los logs de Nextcloud.\ncrowdsec: image: crowdsecurity/crowdsec container_name: crowdsec restart: unless-stopped environment: - COLLECTIONS=crowdsecurity/traefik crowdsecurity/http-cve crowdsecurity/nextcloud volumes: - /mnt/user/appdata/traefik/log:/var/log/traefik:ro # comparte los logs - /mnt/user/appdata/nextcloud/config/nextcloud-logs:/var/log/nextcloud:ro # comparte los logs Reiniciamos crowdsec y podemos actualizar las colletions:\ndocker exec -it crowdsec cscli hub update Revisamos nuestro config.php de Nextcloud para verificar que los logs se guardan en el lugar correcto:\n\u0026#39;mail_smtpport\u0026#39; =\u0026gt; \u0026#39;465\u0026#39;, \u0026#39;bulkupload.enabled\u0026#39; =\u0026gt; false, \u0026#39;loglevel\u0026#39; =\u0026gt; 2, \u0026#39;logfile\u0026#39; =\u0026gt; \u0026#39;/var/www/html/config/nextcloud-logs/nextcloud.log\u0026#39;, \u0026#39;log_rotate_size = 0\u0026#39;, Modificamos nuestro fichero acquis.yaml de crowdsec, quedano así:\n# Logs de Traefik (para todo lo que pasa por el proxy) --- filenames: - /var/log/traefik/access.log poll_without_inotify: true labels: type: traefik # Logs de Nextcloud (brute-force y eventos específicos NC) --- filenames: - /var/log/nextcloud/nextcloud.log labels: type: nextcloud Reiniciamos y verificamos si se están parseando los dos ficheros de logs que tenemos:\ndocker restart crowdsec docker exec crowdsec cscli metrics # Verifica parsing Con esta configuración Nextcloud registraba la dirección IP de Cloudflare, no la IP real del usuario que accede a Nextcloud. Vamos a arreglarlo.\nProblema clásico Cloudflare + Traefik + Nextcloud: Nextcloud ve IP de Cloudflare porque no confía en Traefik como proxy ni lee el header CF-Connecting-IP (IP real que pasa Cloudflare).\nEditamos nuestro fichero config.php de Nextcloud:\n[.......] \u0026#39;dbtype\u0026#39; =\u0026gt; \u0026#39;mysql\u0026#39;, \u0026#39;version\u0026#39; =\u0026gt; \u0026#39;32.0.5.0\u0026#39;, \u0026#39;trusted_proxies\u0026#39; =\u0026gt; array ( 0 =\u0026gt; \u0026#39;192.168.10.55\u0026#39;, // añadida rango IP de nuestra red \u0026#34;cloud\u0026#34; de docker: 1 =\u0026gt; \u0026#39;172.21.0.0/16\u0026#39;, // añadidas IPs de clouflare para que Nextcloud confíe en ellas: 2 =\u0026gt; \u0026#39;103.21.244.0/22\u0026#39;, 3 =\u0026gt; \u0026#39;103.22.200.0/22\u0026#39;, 4 =\u0026gt; \u0026#39;103.31.4.0/22\u0026#39;, 5 =\u0026gt; \u0026#39;104.16.0.0/13\u0026#39;, 6 =\u0026gt; \u0026#39;104.24.0.0/14\u0026#39;, 7 =\u0026gt; \u0026#39;108.162.192.0/18\u0026#39;, 8 =\u0026gt; \u0026#39;131.0.72.0/22\u0026#39;, 9 =\u0026gt; \u0026#39;141.101.64.0/18\u0026#39;, 10 =\u0026gt; \u0026#39;162.158.0.0/15\u0026#39;, 11 =\u0026gt; \u0026#39;172.64.0.0/13\u0026#39;, 12 =\u0026gt; \u0026#39;173.245.48.0/20\u0026#39;, 13 =\u0026gt; \u0026#39;188.114.96.0/20\u0026#39;, 14 =\u0026gt; \u0026#39;190.93.240.0/20\u0026#39;, 15 =\u0026gt; \u0026#39;197.234.240.0/22\u0026#39;, 16 =\u0026gt; \u0026#39;198.41.128.0/17\u0026#39;, ), // añadida según info de perplexity para que crowdsec funcione bien. \u0026#39;forwarded_for_headers\u0026#39; =\u0026gt; array ( \u0026#39;HTTP_CF_CONNECTING_IP\u0026#39;, // ← IP real de Cloudflare \u0026#39;HTTP_X_FORWARDED_FOR\u0026#39;, \u0026#39;HTTP_X_FORWARDED\u0026#39;, \u0026#39;HTTP_X_CLUSTER_CLIENT_IP\u0026#39;, \u0026#39;HTTP_FORWARDED_FOR\u0026#39;, \u0026#39;HTTP_FORWARDED\u0026#39;, \u0026#39;REMOTE_ADDR\u0026#39;, ), \u0026#39;overwrite.cli.url\u0026#39; =\u0026gt; \u0026#39;https://nextcloud.mi_dominio.com\u0026#39;, \u0026#39;overwritehost\u0026#39; =\u0026gt; \u0026#39;nextcloud.mi_dominio.com\u0026#39;, [......] Y añadimos las siguientes etiquetas al docker-compose de Nextcloud:\n# Esta primera la editamos como sigue: traefik.http.routers.nextcloud.middlewares=crowdsec-bouncer@file,security-headers@file,nextcloud-headers@docker # Estas se añaden nuevas: traefik.http.middlewares.nextcloud-headers.headers.customrequestheaders.X-Forwarded-Proto=https traefik.http.middlewares.nextcloud-headers.headers.customrequestheaders.X-Forwarded-For=true traefik.http.middlewares.nextcloud-headers.headers.customrequestheaders.X-Forwarded-Port=443 traefik.http.middlewares.nextcloud-headers.headers.customrequestheaders.X-Real-IP={{.ClientIP }} Y con esto nuestro Nextcloud ya detecta la IP verdadera para, si procede, banearla.\nConexión de nuestro contenedor a Crowdsec.net Accedemos a nuestra cuenta en https://app.crowdsec.net/.\nEn el dashboard → Security Engines → Add Instance (o \u0026ldquo;Engines\u0026rdquo;)\nCopia el Enrollment Token que genera (algo como cscli console enroll abc123\u0026hellip;def456)\n# Registrar con el token docker exec -it crowdsec cscli console enroll TU_ENROLLMENT_TOKEN_AQUI Esto creará /etc/crowdsec/online_api_credentials.yaml con login y password válidos.\nReiniciamos nuestro contenedor:\ndocker restart crowdsec docker logs crowdsec | grep -i capi Volvemos al dashboard de crowdsec.net y aceptamos el enrolado del equipo. Podemos cambiar el nombre para ser más visual al acceder. En mi caso le puse Unraid.\nVentajas de conectar a Console:\n1.- Dashboard web con alertas en tiempo real\n2.- Blocklist comunitaria (millones de IPs malas)\n3.- Métricas globales y threat intel\n**En mi caso, al final no hice el enrolado del equipo por los siguientes motivos:\nNotificaciones en Telegram de Crowdsec Para añadir notificaciones realizamos la siguiente configuración:\nIMPORTANTE: DETENEMOS EL COMPOSE\nFichero /mnt/user/appdata/crowdsec/config/notifications/http.yaml\ntype: http # No cambiar name: telegram # Nombre que usaremos en el perfil log_level: info # URL de la API de Telegram con tu TOKEN # Mucho OJO en la url - Está bien escrita url: https://api.telegram.org/botXXXXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXX_XXXXXXXXXXXXXXXX/sendMessage method: POST headers: Content-Type: application/json # Formato del mensaje (JSON) # Formato del mensaje (JSON) format: | { \u0026#34;chat_id\u0026#34;: \u0026#34;-5002897396\u0026#34;, \u0026#34;text\u0026#34;: \u0026#34;{{range .}}{{$alert := .}}{{range .Decisions}}IP {{.Value}} baneada {{.Duration}} por {{.Scenario}}{{end}}{{end}}\u0026#34;, \u0026#34;parse_mode\u0026#34;: \u0026#34;HTML\u0026#34; } Fichero /mnt/user/appdata/crowdsec/config/profiles.yaml\nname: default_ip_remediation #debug: true filters: - Alert.Remediation == true \u0026amp;\u0026amp; Alert.GetScope() == \u0026#34;Ip\u0026#34; decisions: - type: ban duration: 4h notifications: - telegram Probamos a enviar una notificación de prueba:\ndocker exec -it crowdsec cscli notifications test telegram Versión tuneada de notificaciones en Telegram. Tomando como ejemplo el modelo de la documentación de crowdsec.net:\ntype: http # Don\u0026#39;t change name: telegram # Must match the registered plugin in the profile # One of \u0026#34;trace\u0026#34;, \u0026#34;debug\u0026#34;, \u0026#34;info\u0026#34;, \u0026#34;warn\u0026#34;, \u0026#34;error\u0026#34;, \u0026#34;off\u0026#34; log_level: info format: | { \u0026#34;chat_id\u0026#34;: \u0026#34;-5002897396\u0026#34;, \u0026#34;text\u0026#34;: \u0026#34; {{range . -}} {{$alert := . -}} {{range .Decisions -}} 🚨 CrowdSec Alert on MyServer! 🚨 🆔 IP: {{.Value}} ⚠️ Scenario: {{ .Scenario }} 🚧 Decision: {{.Type}} for next {{.Duration}} {{end -}} {{end -}} \u0026#34;, \u0026#34;reply_markup\u0026#34;: { \u0026#34;inline_keyboard\u0026#34;: [ {{ $arrLength := len . -}} {{ range $i, $value := . -}} {{ $V := $value.Source.Value -}} [ { \u0026#34;text\u0026#34;: \u0026#34;See {{ $V }} on shodan.io\u0026#34;, \u0026#34;url\u0026#34;: \u0026#34;https://www.shodan.io/host/{{ $V -}}\u0026#34; }, { \u0026#34;text\u0026#34;: \u0026#34;See {{ $V }} on crowdsec.net\u0026#34;, \u0026#34;url\u0026#34;: \u0026#34;https://app.crowdsec.net/cti/{{ $V -}}\u0026#34; } ]{{if lt $i ( sub $arrLength 1) }},{{end }} {{end -}} ] } url: https://api.telegram.org/botXXXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/sendMessage method: POST headers: Content-Type: \u0026#34;application/json\u0026#34; Fuentes y enlaces de interés que ayudaran a complementar esta guía:\nTraefik Crowdsec\n","permalink":"https://blog.lasnotasdenoah.com/posts/traefik/","summary":"\u003ch2 id=\"traefik-y-crowdsec\"\u003eTraefik y crowdsec\u003c/h2\u003e\n\u003cp\u003eHasta hace poco tenía en funcionamiento traefik con crowdsec usando las plantillas de unraid. Hice varios manuales sobre la instalación pero por motivos que desconozco crowdsec no parseaba las líneas de logs de traefik y por tanto no hacía absolutamente nada.\u003cbr\u003e\nHe decicido hacer una instalación limpia desde 0 y aquí va.\u003cbr\u003e\nGran parte de este manual se ha hecho usando \u003ca href=\"https://www.perplexity.ai/\"\u003ePerplexity\u003c/a\u003e. Debo decir que tiene mucho que mejorar, pero nos marca unas bases buenas para empezar.\u003c/p\u003e","title":"Traefik v3 y Crowdsec"},{"content":"Configuración de Backups con Borg Nuestro servidor de Unraid va a servir para guardar los backups de nuestras máquinas. En concreto vamos a guardar los backups de los equipos (portátiles y móviles) a través de Vorta, del VPS y del servidor Debian sanMi.\nEsta necesidad ha surgido por dos temas distintos:\nEl primero es la necesidad de hacer backup de nuestros servidores secundarios. Podría instalar Duplicacy, que es el sistema que uso para hacer backup de unRaid en la cuenta de GoogleDrive pero visto lo bien que habla todo el mundo de borg vamos a probarlo una temporada.\nSegundo, los equipos de oficina estaban configurados con Gnome y usando la herramienta Deja-dup hacía los backups. El problema es que Deja-dup no funciona con KDE y me he visto obligado a emplear otra aplicación. Kbackup es una buena opción, pero no acaba de convencerme. Vorta me parece que es una opción excelente así que vamos a ello.\nInstalación de borgserver Buscamos en aplicaciones Unraid el servidor borg:\nRepository: nold360/borgserver:latest Network Type: Bridge SSH: 2222 # Ubicación de las claves ssh sshkeys:/mnt/user/appdata/borg/sshkeys/ # Ubicación de los backups backup: /mnt/user/Backups/borg Pulsamos en aplicar y no arranca el contenedor. El motivo es que si no hemos añadido alguna clave ssh antes no arrancará.\nEn la web del proyecto de hub.docker.com lo explica: !IMPORTANT!: The container wouldn\u0026rsquo;t start the SSH-Deamon until there is at least one ssh-keyfile in this directory!\nCopiamos nuestra clave pública a la siguiente ruta: /mnt/user/appdata/borg/sshkeys/clients En el momento de hacer este manual tengo dos claves públicas, la del pc portátil y la del servidor sanmi:\n➜ clients pwd /mnt/user/appdata/borg/sshkeys/clients ➜ clients ls envy_kde.pub sanmi.pub Ahora si reiniciamos el contenedor debería arrancar sin problemas\nInstalación de Vorta Backup en Fedora En mi caso he instalado Vorta a través de Discover en formato flatpak.\nIniciamos Vorta y comenzamos el procedimiento:\nPrimero creamos nuestra clave ssh:\nUna vez creada la clave ssh tenemos que copiarla a nuestro servidor borg a la siguiente ruta:\n/mnt/user/appdata/borg/sshkeys/clients Añadimos nuestro repositorio de Borg:\nEs importante verificar correctamente los datos del repositorio. En mi caso:\nPESTAÑA GENERAL: Repository URL: ssh://borg@DIRECCION_IP_TAILSCALE:2222/./envy Repository name: envy Enter passphrase: XXXXXXXXX PESTAÑA ADVANCED: SSH Key: seleccionamos la clave ssh que hemos creado anteriormente Encryption: Repokey-Blake2 El resto de opciones las dejamos por defecto.\nPlanificamos la programación tanto de backups como de prune:\nIMPORTANTE: En los Settings de Vorta debemos marcar \u0026ldquo;Automatically start Vorta at login\u0026rdquo; para que arranque al inicio.\nCon esto debería funcionar ya nuestro primer backup. Para restaurar es muy sencillo a través de Vorta. Procedemos a montar el backup que nos interese y realizamos la copia a nuestro sistema.\nConfiguración del cliente borgmatic en los servidores (modo consola) Esta parte es un poco más compleja porque se hace todo en modo consola, pero una vez configurada resulta todo muy sencillo.\nLa configuración consiste en varios pasos (Nota: las claves empleadas en este manual son ficticias):\nInstalación de borgmatic. Borgmatic nos permite realizar backups con borg a través de un sencillo fichero de configuración. Instalación de gpg y pass que nos harán falta para encriptar los backups en destino. Creamos nuestra contraseña gpg para almacenar el password de encriptado de la copia de seguridad. Creamos nueva clave ssh para logearse en nuestro servidor destino de los backups. Configuramos nuestro fichero config.yaml para borgmatic. Creamos nuestra pass para encriptar la copia de seguridad Añadimos una entrada a crontab para programar los backups y las limpiezas. Instalación de borgmatic sudo apt install borgmatic Instalación de gpg y pass sudo apt install pass gpg Creación clave gpg Configuramos nuestra clave gpg:\nsudo gpg --full-generate-key Tipo de clave: predeterminada Validez: sin caducidad Rellenamos nuestros datos personales y de correo: Nuestra contraseña para proteger la clave: Por último nos muestra un resumen de la clave creada: Si queremos ver nuevamente la clave ejecutamos el siguiente comando:\nsudo gpg --list-secret-keys --keyid-format LONG Nos genera la siguiente salida:\n[sudo] password for XXXXXXXXXXXXX: /root/.gnupg/pubring.kbx ------------------------ sec XXXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXXX 2025-07-30 [SC] XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX uid [ultimate] xxxxxx XXXXXXXXXXXXXXX \u0026lt;XXXXXXXXXXXXXXX@XXXXXXXXXXXXXXX.com\u0026gt; ssb XXXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXXX 2025-07-30 [E] Creación de claves ssh sudo ssh-keygen -o -a 100 -t ed25519 Ponemos el nombre de fichero que vamos a usar para almacenar la clave y el resto lo dejamos sin contraseña. Una vez tenemos nuestra clave ssh la pasamos al servidor borgserver de Unraid (tenemos varias opciones con scp, ssh-cp-id, o creando el fichero a mano y añadiendo el contenido):\n# Servidor Unraid cd /mnt/user/appdata/borg/sshkeys/clients nano my_server.pub # y pegamos el contenido de la clave ssh.pub Posteriormente reiniciamos el servidor borg:\ndocker restart borgserver ### docker logs borgserver #### ######################################################## * Testing Volume BORG_DATA_DIR: /backup * Testing Volume SSH_KEY_DIR: /sshkeys * Checking / Preparing SSH Host-Keys... ######################################################## * Starting SSH-Key import... ** Adding client envy_kde.pub with repo path /backup/envy_kde.pub ** Adding client my_server.pub with repo path /backup/my_server.pub En la salida vemos que ya se ha añadido la nueva clave ssh a nuestro servidor borg.\nConfiguramos nuestro fichero config.yaml para borgmatic Generamos el fichero por defecto para borgmatic\nsudo generate-borgmatic-config # Hacemos una copia por seguridad sudo cp /etc/borgmatic/config.yaml /etc/borgmatic/config.yaml.bak # Editamos el fichero Editamos el fichero:\nsudo nano /etc/borgmatic/config.yaml Contenido definitivo del fichero de configuración de borgmatic:\n# /etc/borgmatic/config.yaml location: source_directories: - /home/mi_usuario repositories: - ssh://borg@MY_SERVER_IP_TAILSCALE:2222/./mi_nombre_del_repositorio exclude_caches: true exclude_patterns: - \u0026#39;*.pyc\u0026#39; - /home/*/.cache storage: compression: auto,zstd encryption_passphrase: pass /super_admin@mi_compañía.com/borg-repokey archive_name_format: \u0026#34;{hostname}-{now}\u0026#34; ssh_command: ssh -i /root/.ssh/my_server_ssh_key # Number of times to retry a failing backup # Needs recent Borgmatic version retries: 5 retry_wait: 5 retention: keep_daily: 3 keep_weekly: 4 keep_monthly: 12 consistency: checks: - disabled # Uncomment to regularly read all repo data # Needs recent Borgmatic version # - name: repository # frequency: 4 weeks # - name: archives # frequency: 8 weeks check_last: 3 Llegado a este punto ya está casi todo hecho, pero debemos prestar atención a esta parte del fichero:\nencryption_passphrase: pass /super_admin@mi_compañía.com/borg-repokey\nTenemos que generar nuestra pass para encritar la copia de seguridad. Vamos a ello.\nCreamos nuestra pass para encriptar la copia de seguridad sudo pass generate /super_admin@mi_compañía.com/borg-repokey 16 Nos pedirá la contraseña de nuestro gpg para encriptarla y nos la crea.\nPara ver lista de contraseñas:\nsudo pass list Si queremos ver la contraseña:\nsudo pass list /super_admin@mi_compañía.com/borg-repokey 16 Si queremos editar la contraseña:\nsudo pass edit /super_admin@mi_compañía.com/borg-repokey 16 Y con esto ya está creada y lista para se usada en nuestro fichero config.yaml de borgmatic.\nVerificamos que nuestro fichero config.yaml no contenga errores:\nsudo validate-borgmatic-config -c /etc/borgmatic/config.yaml Primer backup El manejo de borgmatic en modo consola está muy bien explicado en la web docs.borgbase.com.\nsudo env \u0026#34;PATH=$PATH\u0026#34; validate-borgmatic-config sudo env \u0026#34;PATH=$PATH\u0026#34; borgmatic init --encryption repokey-blake2 sudo borgmatic create --list --stats Verificamos que lo ha creado:\nsudo borgmatic list ssh://borg@IP_My_server:2222/./my_repo: Listing archives my_server-2025-07-30T04:22:14 Wed, 2025-07-30 04:22:17 [f920bbec8c5f1ff80cfb794b801f1a3d55b3a90a52047f37bf8035e57902fb51] Añadimos una entrada a crontab para programar los backups y las limpiezas. Vamos a programar nuestros backups y limpiezas a las 08.00 horas todos los días:\nsudo crontab -e # For more information see the manual pages of crontab(5) and cron(8) # # m h dom mon dow command 0 8 * * * /usr/bin/borgmatic --stats -v 0 2\u0026gt;\u0026amp;1 INFORMACIÓN IMPORTANTE SOBRE EL COMANDO BORGMATIC\nEn el repositorio de github borgmatic-collective nos dice lo siguiente:\nIf you omit create and other actions, borgmatic runs through a set of default actions: prune any old backups as per the configured retention policy, compact segments to free up space (with Borg 1.2+, borgmatic 1.5.23+), create a backup, and check backups for consistency problems due to things like file damage. For instance:\nsudo borgmatic --verbosity 1 --list --stats En resumen, cuando no añadimos otras opciones a borgmatica, éste ejecuta de forma automática por defecto las siguientes operaciones: Prune, Compact, Backups y Check de backup, lo que me parece ideal para añadir el comando en cron.\nRestaurar el backup Esta la segunda parte más importante. He realizado varias pruebas y todo ha funcionado correctamente. Para restaurar el backup primero hacemos un listado de los que tenemos y después montamos el backup en la ubicación deseada para restaurar los ficheros:\nPrimero listamos los ficheros creados con borgmatic:\nsudo borgmatic list Una vez sabemos el fichero que nos interesa podemos ver el contenido:\nsudo borgmatic list --archive server-2020-04-01 Extracción completa de ficheros:\nsudo borgmatic extract --archive my_server-2025-07-30T04:24:04 --destination /mnt/new-directory Extracción de una parte solamente:\nsudo borgmatic extract --archive my_server-2020-04-01 --path mnt/catpics --destination /mnt/new-directory Notificaciones del Backup usando apprise Instalamos el software necesario. Según su github Apprise permite enviar una notificación a casi todos los servicios de notificación más populares disponibles en la actualidad, como: Telegram, Discord, Slack, Amazon SNS, Gotify, etc.\nInstalación es sencilla:\nsudo apt install apprise Configuración de nuestro fichero borgmatic conf:\nsudo nano /etc/borgmatic/config.yaml #### AÑADIMOS ESTO AL FINAL de nuestro fichero de configuración hooks: before_backup: - echo \u0026#34;Starting a backup job.\u0026#34; after_backup: - echo \u0026#34;Backup created.\u0026#34; - apprise -vv -t \u0026#34;✅ SUCCESS Backup My_Server\u0026#34; -b \u0026#34;$(cat /tmp/backup_run.log)\u0026#34; \u0026#34;mailtos://smtp.gmail.com:587?user=super_admin@gmail.com\u0026amp;pass=superpasssecreta\u0026amp;from=superadmin@gmail.com\u0026amp;to=superadmin@hotmail.com,tgram://bot_token:de_telegram/chat_id_telegram/\u0026#34; on_error: - echo \u0026#34;Error while creating a backup.\u0026#34; - apprise -vv -t \u0026#34;❌ FAILED Backup My_Server\u0026#34; -b \u0026#34;$(cat /tmp/backup_run.log)\u0026#34; \u0026#34;mailtos://smtp.gmail.com:587?user=super_admin@gmail.com\u0026amp;pass=superpasssecreta\u0026amp;from=superadmin@gmail.com\u0026amp;to=superadmin@hotmail.com,tgram://bot_token:de_telegram/chat_id_telegram/\u0026#34; En mi caso he configurado para que nos envíe dos notificaciones. La primera por correo electrónico y la segunda a Telegram.\nEn la versión de borgmatic 1.8.4+ Apprise se integra de forma nativa con borgmatic, lo que permite una configuración mucho más limpia, tal y como se muestra en la siguiente ejemplo. Esta configuración yo no puedo usarla porque mi sistema tiene la versión borgmatic 1.7.7:\napprise: states: - start - finish - fail services: - url: mailtos://smtp.example.com:587?user=server@example.com\u0026amp;pass=YourSecurePassword\u0026amp;from=server@example.com\u0026amp;to=receiver@example.com label: mail - url: slack://token@Txxxx/Bxxxx/Cxxxx label: slack start: title: ⚙️ Started body: Starting backup process. finish: title: ✅ SUCCESS body: Backups successfully made. fail: title: ❌ FAILED body: Your backups have failed. En la versión 1.8.9+, los logs de borgmatic son añadidos automaticamenta al cuerpo de las notificaciones de apprise. Me parece una colaboración impresionante. Que ganas tengo de que actualice Debian a la nueva versión de borgmatic.\nPor último, modificamos nuestro crontab para que al ejecutarse guarde la salida de las estadísticas en el fichero /tmp/backup_run.log.\nsudo crontab -e # # # 30 8 * * * /usr/bin/borgmatic --stats -v 0 \u0026gt; /tmp/backup_run.log Con esto, nuestro borgmatica ya debería notificarnos:\nCorreo:\nTelegram:\nNotas finales a tener en cuenta En mi servidor sanmi tengo instalado Fedora Server. En este caso, la versión de borgmatic que nos acompaña es la versión 2.0.6 por lo que ya disponemos de las nuevas características para notificaciones y de un nuevo formato en el fichero config.yaml.\nRespecto a la configuración de encryption_passcommand en borgmatic, se me presenta un problema.\nSi programamos el backup con cron, no se ejecuta. El motivo es que cada vez que se va a ejecutar, el comando pass nos solicita nuestra contraseña de la clave gpg y si no la introducimos el resto no continúa. Entonces, para que los backups se realicen de forma automática sin intervención del usuario, la única forma que he conseguido hacerlo es poniendo la contraseña directamente en el fichero config.yaml.\nConfiguración de mi fichero config.yaml en Fedora Server:\nsource_directories: - /home/AppData - /home/super_admin repositories: - path: ssh://borg@100.100.100.100:2222/./sanMi label: sanMi exclude_caches: true exclude_patterns: - \u0026#39;*.pyc\u0026#39; - /home/*/.cache compression: auto,zstd encryption_passphrase: My_super_password #encryption_passcommand: pass /super_admin@gmail.com/borg-repokey archive_name_format: \u0026#34;{hostname}-{now}\u0026#34; ssh_command: ssh -i /root/.ssh/sanmi retries: 5 retry_wait: 5 keep_daily: 3 keep_weekly: 4 keep_monthly: 12 checks: - name: repository frequency: 4 weeks - name: archives frequency: 8 weeks check_last: 3 apprise: states: - start - finish - fail services: - url: mailtos://smtp.gmail.com:587?user=super_admin_@gmail.com\u0026amp;pass=super_password\u0026amp;from=super_admin@gmail.com\u0026amp;to=destino@hotmail.com label: mail - url: tgram://123456789:AAE39Q5XXXXXXXXXXXXXXX_XXXXXXXXXXXXXXXXXXXxPGrI/XXXXXXXXXXXX/ label: telegram start: title: ⚙️ Starrted Backup body: Starting backup process finish: title: ✅ SUCCESS Backup SanMi body: Backup SanMi success fail: title: ❌ FAILED Backup SanMi body: Backups SanMi failed Fuentes y enlaces de interés que ayudaran a complementar esta guía:\nBorgserver en hub.docker.com Guía muy completa, base de casi todo el manual\nGuía en español con detalle de uso contraseña cifrado\nTutorial bilito para configurar borg en Unraid\nGuía en español configuración pass y claves gpg para almacenar esas pass\nConfiguración de pass como password-manager en consola\nDocumentación Borgbase.com\nGithub de borgmatic-collective con ejemplos varios\nNotificaciones con apprise\nGithub de borgmatic-collective notificaciones apprise\nDoc notificaciones apprise Telegram\n","permalink":"https://blog.lasnotasdenoah.com/posts/borg-backups/","summary":"\u003ch2 id=\"configuración-de-backups-con-borg\"\u003eConfiguración de Backups con Borg\u003c/h2\u003e\n\u003cp\u003eNuestro servidor de Unraid va a servir para guardar los backups de nuestras máquinas. En concreto vamos a guardar los backups de los equipos (portátiles y móviles) a través de Vorta, del VPS y del servidor Debian sanMi.\u003cbr\u003e\nEsta necesidad ha surgido por dos temas distintos:\u003cbr\u003e\nEl primero es la necesidad de hacer backup de nuestros servidores secundarios. Podría instalar Duplicacy, que es el sistema que uso para hacer backup de unRaid en la cuenta de GoogleDrive pero visto lo bien que habla todo el mundo de borg vamos a probarlo una temporada.\u003cbr\u003e\nSegundo, los equipos de oficina estaban configurados con Gnome y usando la herramienta Deja-dup hacía los backups. El problema es que Deja-dup no funciona con KDE y me he visto obligado a emplear otra aplicación. Kbackup es una buena opción, pero no acaba de convencerme. Vorta me parece que es una opción excelente así que vamos a ello.\u003c/p\u003e","title":"Borg Backups"},{"content":"Instalar Debian en particiones LVM encriptadas ya existentes conservando datos Arrancamos con el médio de instalación de Debian y seleccionamos Opciones avanzadas - Instalación experta\nAvanzamos en el proceso de instalación normalmente y en Load Installer components from CD cargamos los siguientes:\ncrypto-dm-modules and rescue-mode\nContinuamos con la instalación y nos detenemos antes de Detect disks:\nAccedemos a una consola con ctrl+alt+f2 y realizamos la carga de nuestro LVM:\nCargamos los módulos necesarios (por motivo que desconozco este comando no funciona pero no es relevante para la instalación)\ndepmod -a Listamos las particiones del sistema:\nblkid Desbloqueamos nuestro volumen LVM con cryptsetup:\ncryptsetup luksOpen /dev/vda3 debian-encriptado Enter passphrase for /dev/vda3: Abrimos nuestro VG volume group y verificamos que esté disponible en dev/mapper/debian-encriptado:\nvgchange -ay ls /dev/mapper Presionamos ctrl+alt+f1 y continuamos con la instalación normalmente:\nAhora ya tenemos disponibles nuestros volúmenes para instalar nuevamente el sistema:\nEn mi caso, formateo todas las particiones excepto el volumen /home que es donde estan mis datos de usuario y efi que está compartido con Windows:\nComo se ve tengo el siguiente particionado:\nvda1 - uefi - 100MB /boot/efi\nvda2 - boot - 1GB /boot\nvda3 - luks - 20GB\nVG debian - LV home - 5GB /home\nVG debian - LV root - 15GB\t/root\nContinuamos con la instalación del sistema normal y nos detenemos antes de Install the GRUB bootloader to a hard disk.\nAccedemos nuevamente a la consola con ctrl+alt+f2 para configurar initramfs:\nNos interesa la partición TYPE=\u0026ldquo;crypto_LUKS\u0026rdquo;, que en mi caso es /dev/vda3:\nListamos las particiones del sistema:\nblkid cryptsetup luksDump /dev/vda3 |grep -F UUID Tenemos que modificar el fichero /target/etc/crypttab.\ncryptsetup luksDump /dev/vda3 |grep -F UUID \u0026gt;\u0026gt; /target/etc/crypttab Modificamos crypttab dejandolo así:\n# \u0026lt;target name\u0026gt; \u0026lt;source device\u0026gt;\t\u0026lt;key file\u0026gt;\t\u0026lt;options\u0026gt; debian-encriptado UUID=3dfb977c-8368-4146-b7b9-5a2426aa4347 none luks,discard Volvemos a la instalación con ctrl+alt+f1 y procedemos a instalar Grub bootloader.\nSi algo ha ido mal en la generación de initramfs podemos iniciar nuevamente desde nuestro usb de debian y ejecutar un Rescue mode, seguimos los pasos de carga de nuestros volúmnes LUKS, etc y a la hora de generamos initramfs manualmente con el siguiente comando:\nupdate-initramfs -u -k all Si hay algún error nos lo dirá el comando y podemos corregir lo que sea neceario.\nInstalar Debian en particiones LVM NO encriptadas ya existentes conservando datos En este caso es todo muy sencillo. Seleccionamos particionado manual y el instalador de Debian nos detectará la estructura de particiones que tiene el disco y simplemente tenemos que indicar que volumenes queremos que se formateen y cuales no.\nDebemos dejar el sistema configurado como se muestra en la imangen y en ningún momento es preciso salir del instalador a una consola. (NOTA: esta imagen está aprovechada del apartado donde se hacía con encriptado, pero es exactamente lo mismo).\nFuentes:\nhttps://www.blakecarpenter.dev/installing-debian-on-existing-encrypted-lvm/\nhttps://consolematt.wordpress.com/2013/06/19/reinstalling-debian-on-existing-lukslvm-partition/\nhttps://www.reddit.com/r/debian/comments/1599rkt/how_to_reinstall_debian_12_with_existing/\n","permalink":"https://blog.lasnotasdenoah.com/posts/debian-luks-recovery/","summary":"\u003ch2 id=\"instalar-debian-en-particiones-lvm-encriptadas-ya-existentes-conservando-datos\"\u003eInstalar Debian en particiones LVM encriptadas ya existentes conservando datos\u003c/h2\u003e\n\u003cp\u003eArrancamos con el médio de instalación de Debian y seleccionamos Opciones avanzadas - Instalación experta\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"debian.png\" loading=\"lazy\" src=\"/posts/debian-luks-recovery/debian.png\"\u003e\u003cbr\u003e\n\u003cimg alt=\"debian2.png\" loading=\"lazy\" src=\"/posts/debian-luks-recovery/debian2.png\"\u003e\u003c/p\u003e\n\u003cp\u003eAvanzamos en el proceso de instalación normalmente y en Load Installer components from CD cargamos los siguientes:\u003cbr\u003e\n\u003cstrong\u003ecrypto-dm-modules and rescue-mode\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"debian3.png\" loading=\"lazy\" src=\"/posts/debian-luks-recovery/debian3.png\"\u003e\u003c/p\u003e\n\u003cp\u003eContinuamos con la instalación y nos detenemos antes de Detect disks:\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"debian4.png\" loading=\"lazy\" src=\"/posts/debian-luks-recovery/debian4.png\"\u003e\u003c/p\u003e\n\u003cp\u003eAccedemos a una consola con \u003cstrong\u003ectrl+alt+f2\u003c/strong\u003e y realizamos la carga de nuestro LVM:\u003c/p\u003e","title":"Reinstalar Debian con LVM"},{"content":"Integrar Telegram en Home Assistant Resulta muy sencillo la integración de Telegram. Modificamos el fichero configuration.yaml y añadimos lo siguiente:\nTenemos que crear nuestro bot a través de @BotFather. Una vez finalizado nos dará el api_key que necesitamos.\nPara obtener el id del chat usamos @GetIDs bot\ntelegram_bot: - platform: polling api_key: xxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx allowed_chat_ids: - 123456789 - 123456789-dos notify: - platform: telegram name: \u0026#34;telegram\u0026#34; chat_id: 123456789 - platform: telegram name: \u0026#34;telegram_dos\u0026#34; chat_id: 123456789-dos En name: \u0026ldquo;telegram\u0026rdquo; podemos poner el nombre que queramos, teniendo en cuenta que cuando llamemos a nuestro servicio debemos usar: notify.telegram, notify.my_home, etc\u0026hellip;\nComo vemos en el ejemplo, se puede hacer varias notificaciones distintas a distintos grupos o chats.\nReiniciamos Home Assistant y ya lo tenemos disponible. Nos vamos a Herramientas de desarrolladores -\u0026gt; Servicios para probarlo:\nMensaje sencillo:\nservice: notify.telegram data: message: \u0026#34;Yay! A message from Home Assistant.\u0026#34; Mensaje enviando una foto:\nservice: notify.telegram data: title: Send an images message: That\u0026#39;s an example that sends an image. data: photo: - file: /media/CCTV/2024/02/02/Tapia XXXXXX_00_20240202184131.jpg Fuentes y enlaces de interés que ayudaran a complementar esta guía:\nhttps://www.home-assistant.io/integrations/telegram/\n","permalink":"https://blog.lasnotasdenoah.com/posts/home-assistant/","summary":"\u003ch3 id=\"integrar-telegram-en-home-assistant\"\u003eIntegrar Telegram en Home Assistant\u003c/h3\u003e\n\u003cp\u003eResulta muy sencillo la integración de Telegram.\nModificamos el fichero configuration.yaml y añadimos lo siguiente:\u003c/p\u003e\n\u003cp\u003eTenemos que crear nuestro bot a través de \u003ca href=\"https://t.me/BotFather\"\u003e@BotFather\u003c/a\u003e. Una vez finalizado nos dará el api_key que necesitamos.\u003c/p\u003e\n\u003cp\u003ePara obtener el id del chat usamos \u003ca href=\"https://t.me/getidsbot\"\u003e@GetIDs bot\u003c/a\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003etelegram_bot\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  - \u003cspan style=\"color:#f92672\"\u003eplatform\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003epolling\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003eapi_key\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003exxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003eallowed_chat_ids\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      - \u003cspan style=\"color:#ae81ff\"\u003e123456789\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      - \u003cspan style=\"color:#ae81ff\"\u003e123456789\u003c/span\u003e-\u003cspan style=\"color:#ae81ff\"\u003edos\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003enotify\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  - \u003cspan style=\"color:#f92672\"\u003eplatform\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003etelegram\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;telegram\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003echat_id\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e123456789\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  - \u003cspan style=\"color:#f92672\"\u003eplatform\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003etelegram\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;telegram_dos\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003echat_id\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e123456789\u003c/span\u003e-\u003cspan style=\"color:#ae81ff\"\u003edos\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eEn name: \u0026ldquo;telegram\u0026rdquo; podemos poner el nombre que queramos, teniendo en cuenta que cuando llamemos a nuestro servicio debemos usar: notify.telegram, notify.my_home, etc\u0026hellip;\u003c/p\u003e","title":"Home Assistant y Telegram"},{"content":"Script de backup con rsync Con este pequeño script hacemos el backup del USB del trabajo a nuestro disco duro:\nOrigen: /ruta origen\nDestino: /ruta destino\nOJO - cuando tenemos espacios en los nombres hay que usar \u0026lsquo;' para que el script sepa que es un espacio\n#!/bin/bash \u0026lt;\u0026lt; \u0026#39;Comment\u0026#39; Opciones rsync: --delete: borrar los archivos que fueron borrados de la carpeta origen en la carpeta destino -a: mantiene el usuario, grupo, permisos, fecha y hora, así como los enlaces simbólicos -v: la información imprimida durante la ejecución del programa será mucho más detallada, -h: nos da las tasas de transferencia y el tamaño de los archivos en unidades razonables -u: evitar copiar archivos que ya tenemos en la carpeta de destino que no has sido modificados en la carpeta de origen Comment rsync --progress --stats --delete -avhiu /media/user/Nuevo\\ vol/Origen /home/user/Destino Configuración con reglas UDEV Primero debemos obtener el idProduct y el idVendor del nuestro usb\nlsusb Bus 002 Device 003: ID 0781:5581 SanDisk Corp. Ultra Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub idVendor = 0781\nidProduct = 5581\nCon estos datos creamos un fichero .rules:\nsudo nano /etc/udev/rules.d/10.backup_usb.rules SUBSYSTEM==\u0026#34;block\u0026#34;, ACTION==\u0026#34;add\u0026#34;, ATTRS{idVendor}==\u0026#34;0781\u0026#34;, ATTRS{idProduct}==\u0026#34;5581\u0026#34;, SYMLINK+=\u0026#34;external\u0026#34;, RUN+=\u0026#34;/home/user/backup_usb.sh\u0026#34; Por último, recargamos las reglas udev para que el sistema ejecute el script al enchufar nuestro pendrive:\nudevadm control --reload Este método funcionaria de maravilla para usb normales. El problema es que mi usb del trabajo está encritado con bitlocker y cuando se ejecuta la regla udev todavía no está montada la partción del usb porque antes tenemos que introducir la contraseña de bitlocker, por lo que no funciona mi backup automático.\nConfiguración con systemd La solución al problema anterior es crear un servicio systemd que ejecute mi script de backup cuando se monta la partición que nos interesa.\nCreamos nuestro backup_usb.service en /home/user/.config/systemd/user:\ncat backup_usb.service [Unit] Description=Backup pendrive trabajo Requires=media-label-user.mount After=media-label-user.mount [Service] ExecStart=/home/user/Apps/backup_usb.sh [Install] WantedBy=media-label-user.mount Para buscar las media label:\nsudo systemctl list-units -t mount Aqui aparecerá una etiqueta similar a esta entre otras muchas:\nmedia-user-Work.mount Por último habilitamos nuestro servicio:\nsystemctl --user enable backup_usb.service Al crear el enlace simbólico nos dirá el sistema que estamos creando un servicio con una dependencia que no existe:\nUnit /home/user/.config/systemd/user/backup_usb.service is added as a dependency to a non-existent unit media-user-Work.mount. No importa porque cuando se ejecute el servicio al insertar el pendrive debería funcionar correctamente ya que la unidad se crea en ese momento.\nFuentes:\nSystemd\nhttps://askubuntu.com/questions/25071/how-to-run-a-script-when-a-specific-flash-drive-is-mounted\n","permalink":"https://blog.lasnotasdenoah.com/posts/backup-usb/","summary":"\u003ch3 id=\"script-de-backup-con-rsync\"\u003eScript de backup con rsync\u003c/h3\u003e\n\u003cp\u003eCon este pequeño script  hacemos el backup del USB del trabajo a nuestro disco duro:\u003cbr\u003e\nOrigen:  /ruta origen\u003cbr\u003e\nDestino: /ruta destino\u003cbr\u003e\nOJO - cuando tenemos espacios en los nombres hay que usar \u0026lsquo;' para que el script sepa que es un espacio\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#!/bin/bash\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026lt;\u0026lt; \u0026#39;Comment\u0026#39;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\tOpciones rsync: \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\t--delete: borrar los archivos que fueron borrados de la carpeta origen en la carpeta destino\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\t-a: mantiene el usuario, grupo, permisos, fecha y hora, así como los enlaces simbólicos\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\t-v: la información imprimida durante la ejecución del programa será mucho más detallada,\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\t-h: nos da las tasas de transferencia y el tamaño de los archivos en unidades razonables\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\t-u: evitar copiar archivos que ya tenemos en la carpeta de destino que no has sido modificados en la carpeta de origen\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003eComment\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ersync --progress --stats --delete  -avhiu /media/user/Nuevo\u003cspan style=\"color:#ae81ff\"\u003e\\ \u003c/span\u003evol/Origen /home/user/Destino\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"configuración-con-reglas-udev\"\u003eConfiguración con reglas UDEV\u003c/h3\u003e\n\u003cp\u003ePrimero debemos obtener el idProduct y el idVendor del nuestro usb\u003c/p\u003e","title":"Backups a USB automático"},{"content":"GSconnect Instalación y configuración de GSconnect\nGSConnect es una implementación completa de KDE Connect especialmente para GNOME Shell con integración de Nautilus, Chrome y Firefox. No depende de la aplicación de escritorio KDE Connect y no funcionará si está instalada.\nKDE Connect permite que los dispositivos compartan contenido de forma segura, como notificaciones o archivos, y otras funciones como mensajería SMS y control remoto. El equipo de KDE Connect cuenta con aplicaciones para Linux, BSD, Android, Sailfish, iOS, macOS y Windows.\nEsp preciso seguir estos pasos en Debian para que nos conecte correctamente, ya que por experiencia propia de otra forma no funciona en algunas ocasiones:\nSi ha estado instalado y nos ha dado problemas, eliminar todo rastro de la aplicación en el ordenador y en el móvil.\nsudo apt autoremove --purge gnome-shell-extension-gsconnect Revisamos las carpetas ~/.config y ~/.cache y borramos cualquier resto de gsconnect.\nInstalar el paquete .deb con apt\nsudo apt install gnome-shell-extension-gsconnect Instalamos la extensión desde el gestor de extensiones de gnome:\nVerificar que ha sido todo correcto.\nReiniciar el ordenador.\nInstalar en el móvil kde connect\nEn el móvil refrescar para ver dispositivos y debería aparecer el ordenador para enlazar.\nAceptar y dar permisos en el móvil a la aplicación.\nPor último, tenemos que dar permisos en firewalld al servicio de GSconnect, no olvidando crear la regla de forma permanente.\nfirewall-cmd --permanent --zone=public --add-service=gsconnect Fuentes:\nhttps://userbase.kde.org/KDEConnect#Troubleshooting\n","permalink":"https://blog.lasnotasdenoah.com/posts/gsconnect/","summary":"\u003ch2 id=\"gsconnect\"\u003eGSconnect\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eInstalación y configuración de GSconnect\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eGSConnect es una implementación completa de KDE Connect especialmente para GNOME Shell con integración de Nautilus, Chrome y Firefox.  No depende de la aplicación de escritorio KDE Connect y no funcionará si está instalada.\u003c/p\u003e\n\u003cp\u003eKDE Connect permite que los dispositivos compartan contenido de forma segura, como notificaciones o archivos, y otras funciones como mensajería SMS y control remoto.  El equipo de KDE Connect cuenta con aplicaciones para Linux, BSD, Android, Sailfish, iOS, macOS y Windows.\u003c/p\u003e","title":"Gsconnect (kdeconnect para Gnome)"},{"content":"Notas sobre configuraciones para uso de Python Instalación de Pip\nPip es un sistema de gestión de paquetes utilizado para instalar y administrar paquetes de software escritos en Python.\nAdemás de instalar pip aprovechamos para instalar software de desarrollo de python muy util.\nsudo apt install python3-pip python-dev build-essential python3-venv El módulo venv proporciona soporte para crear «entornos virtuales» ligeros con sus propios directorios de ubicación, aislados opcionalmente de los directorios de ubicación del sistema.\nCada entorno virtual tiene su propio binario Python (que coincide con la versión del binario que se utilizó para crear este entorno) y puede tener su propio conjunto independiente de paquetes Python instalados en sus directorios de ubicación.\nEn resumen, los entornos virtuales nos permiten tener un entorno de desarrollo en cada proyecto sin llenar el sistema de dependencias y paquetes instalados.\nPara crear un entorno virtual dentro del proyecto que estemos:\npython3 -m venv entorno_virtual De esta forma creamos una carpeta llamada entorno_virtual dentro del proyecto donde se almacenaran todos los archivos de python para ese entorno.\nAl abrir un proyecto con un entorno virtual, VSCode nos lo detecta automáticamente lo activa directamente.\nSi no se activa directamente, o vamos a trabajar fuera de VSCode lo activamos nosotros:\nsource ruta/al/entorno/virtual/bin/activate Para desactivarlo:\ndeactivate Si queremos eliminar un entorno virtual:\nrm -rf ruta/al/entorno/virtual Nota SUPERIMPORTANTE\nSi vamos a usar el entorno virtual dentro de un proyecto en github tenemos que excluir esa carpeta de git. Para ello creamos un fichero .gitignore dentro de la carpeta entorno_virtual y excluimos todo con \u0026lsquo;*\u0026rsquo;:\nnano .gitignore * Una vez tengamos pip instalado podemos instalar los paquetes que necesitemos para nuestros proyectos:\npip install jupyter pandas request numpy etc..... Para actulizar pip:\npip install --upgrade pip Fuentes:\n[]https://code.tutsplus.com/es/tutorials/understanding-virtual-environments-in-python\u0026ndash;cms-28272](https://code.tutsplus.com/es/tutorials/understanding-virtual-environments-in-python--cms-28272)\nhttps://gee.es/2023/05/17/como-creo-un-entorno-de-desarrollo-con-env-en-vscode/\n","permalink":"https://blog.lasnotasdenoah.com/posts/python/","summary":"\u003ch2 id=\"notas-sobre-configuraciones-para-uso-de-python\"\u003eNotas sobre configuraciones para uso de Python\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eInstalación de Pip\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003ePip es un sistema de gestión de paquetes utilizado para instalar y administrar paquetes de software escritos en Python.\u003cbr\u003e\nAdemás de instalar pip aprovechamos para instalar software de desarrollo de python muy util.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo apt install python3-pip python-dev build-essential python3-venv\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eEl módulo venv proporciona soporte para crear «entornos virtuales» ligeros con sus propios directorios de ubicación, aislados opcionalmente de los directorios de ubicación del sistema.\u003cbr\u003e\nCada entorno virtual tiene su propio binario Python (que coincide con la versión del binario que se utilizó para crear este entorno) y puede tener su propio conjunto independiente de paquetes Python instalados en sus directorios de ubicación.\u003cbr\u003e\nEn resumen, los entornos virtuales nos permiten tener un entorno de desarrollo en cada proyecto sin llenar el sistema de dependencias y paquetes instalados.\u003cbr\u003e\nPara crear un entorno virtual dentro del proyecto que estemos:\u003c/p\u003e","title":"Python"},{"content":"Uso de FirewallD NOTA: En Joplin tengo un manual más completo\nManual de ayuda:\nfirewall-cmd --help FirewallD funciona con systemd, por lo que se emplean todos los comandos de systemd:\nsystemctl enable firewalld systemctl start firewalld systemctl restart firewalld systemctl status firewalld Zonas de firewall Zonas de Firewalld.\nDe modo predeterminado Firewalld tiene diferentes tipos de zonas. Cada una tiene un distinto nivel de seguridad.\ndrop Descripción: Para redes públicas. Se descartan los paquetes de red entrantes no solicitados. Los paquetes entrantes que están relacionados con las conexiones de red salientes son aceptados. Se permite el tráfico de salida. Ésta sería la zona más segura. Ideal para paranoicos. Servicios habilitados: ninguno. Política predeterminada: DROP.\nblock Descripción: Para redes públicas. Se rechazan los paquetes de red entrantes no solicitados. Los paquetes entrantes que están relacionados con las conexiones de red salientes son aceptados. Se permite el tráfico de salida. Servicios habilitados: ninguno. Política predeterminada: REJECT.\npublic Descripción: Es la zona predeterminada. Para redes públicas. Sólo se aceptan algunas conexiones entrantes selectas y el resto son rechazadas. Es ideal para áreas públicas. Servicios habilitados: ssh y dhcpv6-client. Política predeterminada: REJECT.\nexternal Descripción: Para redes externas.Sólo se aceptan algunas conexiones entrantes selectas y el resto son rechazadas. Es ideal para redes externas con enmascaramiento habilitado especialmente para ruteadores. Servicios habilitados: ssh. Política predeterminada: REJECT.\ndmz Descripción: Para en sistemas zona desmilitarizada con acceso limitado a la red interna. Sólo se aceptan algunas conexiones entrantes selectas y el resto son rechazadas. Servicios habilitados: ssh. Política predeterminada: REJECT.\nwork Descripción: Para trabajo u oficina. Se confía en los sistemas que coexisten en la misma red pero sólo se aceptan algunas conexiones entrantes selectas y el resto son rechazadas. Servicios habilitados: ssh, ipp-client y dhcpv6-client. Política predeterminada: REJECT.\nhome Descripción: Para el hogar. Se confía en los sistemas que coexisten en la misma red pero sólo se aceptan algunas conexiones entrantes selectas y el resto son rechazadas. Básicamente igual que work. Servicios habilitados: ssh, ipp-client, mdns, samba-client y dhcpv6-client. Política predeterminada: REJECT.\ninternal Descripción: Para redes internas. Se confía en los sistemas que coexisten en la misma red pero sólo se aceptan algunas conexiones entrantes selectas y el resto son rechazadas. Servicios habilitados: ssh, ipp-client, mdns, samba-client y dhcpv6-client. Política predeterminada: REJECT.\ntrusted Descripción: Todas las conexiones son aceptadas. Servicios habilitados: todos. Política predeterminada: ACCEPT.\nPrimeros comandos\nSi solo queremos recargar la configuración:\nfirewall-cmd --reload El firewall dispone de diferentes zonas, cada una con sus particularidades, para verlas:\nfirewall-cmd --get-zones Para ver la que tenemos por defecto:\nfirewall-cmd --get-default-zone Servicios habilitados en la zona activa:\nfirewall-cmd --list-services Cambios temporales y permanentes\nLos cambios realizados con firewall-cmd sin la opción \u0026ndash;permanent se aplicarán de inmediato sin guardarse en la configuración.\nLos cambios realizados con firewall-cmd con la opción \u0026ndash;permanent se guardan de inmediato en la configuración pero sólo aplicarán después de ejecutar firewall-cmd con la opción \u0026ndash;reload o systemctl restart firewalld.\nCambios de zona por defecto\nfirewall-cmd --set-default-zone=public Añadir un servicio a una zona:\nfirewall-cmd --permanent --zone=public --add-service=gsconnect Si nos surge un problema tipo ransomware o similar que esté sincronizando nuestros ficheros con el NAS o la nube podemos tomar medidas extremas:\nActivar el módo pánico:\nfirewall-cmd --panic-on Desactivar:\nfirewall-cmd --panic-off Verificar estado:\nfirewall-cmd --query-panic Y un largo etc. de opciones\u0026hellip;.\nFuentes:\nhttps://blog.alcancelibre.org/staticpages/index.php/como-firewalld\nhttps://www.redhat.com/sysadmin/how-to-configure-firewalld\n","permalink":"https://blog.lasnotasdenoah.com/posts/firewalld-config/","summary":"\u003ch2 id=\"uso-de-firewalld\"\u003eUso de FirewallD\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eNOTA: En Joplin tengo un manual más completo\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eManual de ayuda:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003efirewall-cmd --help\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eFirewallD funciona con systemd, por lo que se emplean todos los comandos de systemd:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esystemctl enable firewalld\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esystemctl start firewalld\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esystemctl restart firewalld\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esystemctl status firewalld\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cem\u003e\u003cstrong\u003eZonas de firewall\u003c/strong\u003e\u003c/em\u003e\nZonas de Firewalld.\u003c/p\u003e\n\u003cp\u003eDe modo predeterminado Firewalld tiene diferentes tipos de zonas. Cada una tiene un distinto nivel de seguridad.\u003c/p\u003e\n\u003cp\u003e\u003cem\u003e\u003cstrong\u003edrop\u003c/strong\u003e\u003c/em\u003e\nDescripción: Para redes públicas. Se descartan los paquetes de red entrantes no solicitados. Los paquetes entrantes que están relacionados con las conexiones de red salientes son aceptados. Se permite el tráfico de salida. Ésta sería la zona más segura. Ideal para paranoicos.\nServicios habilitados: ninguno.\nPolítica predeterminada: DROP.\u003c/p\u003e","title":"Firewalld configuración"},{"content":" title: Configuración NextDNS en router Asus con firmware Merlin y en equipos Debian con NetworkManager date: 2023-10-20 09:00:00 +0100 categories: [Network] tags: [config, network] # TAG names should always be lowercase img_path: /assets/pictures/ author: Instalación de Nextdns firmware Merlin router ASUS En el github de Nextdns tenemos toda la información para la instalación del NextDNS CLI Client en nuestro router. Este cliente emplea DNS-over-HTTPS.\nInstalación\nNos conectamos por ssh al router y ejecutamos el script de instalación:\nsh -c \u0026#39;sh -c \u0026#34;$(curl -sL https://nextdns.io/install)\u0026#34;\u0026#39; Tenemos otra opción para realizar la configuración de NextDNS en nuestro router, esta vez empleando DNS-over-TLS:\nEN el reddit de nextdns se explica perfectamente.\nSi queremos saber la diferencia entre DNS-over-HTTPS y DNS-over-TLS en el siguiente enlace se explica muy bien.\nInstalación de Nextdns en Debian Según la web de NextDNS se recomienda la siguiente instalación:\nEditar el fichero /etc/systemd/resolved.conf:\n[Resolve] DNS=45.90.28.0#user_id.dns.nextdns.io DNS=2a07:a8c0::#user_id.dns.nextdns.io DNS=45.90.30.0#user_id.dns.nextdns.io DNS=2a07:a8c1::#user_id.dns.nextdns.io DNSOverTLS=yes En Debian no venía preinstalado el servicio systemd-resolved y tuve que instalarlo. Pero surgió un problema: NextDNS no se lleva bien con NetworkManager cuando activamos alguna de las VPN de pago que tengo configuradas a través del protocolo OpenVPN. En esta entrada del blog NextDNS explican el mismo problema que yo tengo y con la solución que aportan a mi no me ha funcionado.\nEn mi caso he optado por instalar NextDNS a través del cliente en línea de comando y cuando activo la VPN tengo que tener la precaución de parar NextDNS.\nRevisamos que esté correctamente configurado el fichero /etc/resolv.conf:\nDebería tener líneas similares a esta:\nnameserver 9.9.9.9 nameserver 8.8.8.8 nameserver 1.1.1.1 nameserver 192.168.1.1 Es importante revisar esto si hemos tenido instalado systemd-resolved o si viene instalado por defecto. En ese caso es importante desinstalarlo si vamos a trabajar con VPN hasta que se resuelva el bug.\nGuía de desintalación de systemd-resolved.\nInstalación de cliente NextDNS\nsh -c \u0026#39;sh -c \u0026#34;$(curl -sL https://nextdns.io/install)\u0026#34;\u0026#39; Seguimos las instrucciones y ya debería funcionar.\nComandos básicos:\nnextdns start nextdns stop nextdns restart nextdns status nextdns log nextdns help Desinstalar\nEjecutamos el mismo comando y elegimos la opción Uninstall en el menú.\nsh -c \u0026#39;sh -c \u0026#34;$(curl -sL https://nextdns.io/install)\u0026#34;\u0026#39; Uso de la VPN a través de NetworkManager\nMi operativa ahora es sencilla, NextDNS se inicia al arrancar el sistema.\nSi tengo que hacer uso de la VPN los pasos son los siguientes:\nsudo nextdns stop 2.- Activo la VPN a través del NetworkManager de Gnome\n3.- Hago el trabajo que sea.\n4.- Activo la VPN a través del NetworkManager de Gnome\nsudo nextdns start Fuentes:\nAsus\nhttps://github.com/nextdns/nextdns/wiki/AsusWRT-Merlin\nhttps://www.reddit.com/r/nextdns/comments/x2k8f3/asus_merlin_noncli_configuration_guide/\nhttps://www.cloudflare.com/es-es/learning/dns/dns-over-tls/.\nDebian\nhttps://help.nextdns.io/t/h7yhxk1/setting-up-nextdns-on-ubuntu-in-resolved-conf-doesnt-work-with-vpns-dns\nhttps://github.com/nextdns/nextdns/wiki\nhttps://gist.github.com/zoilomora/f7d264cefbb589f3f1b1fc2cea2c844c\n","permalink":"https://blog.lasnotasdenoah.com/posts/nextdns/","summary":"\u003chr\u003e\n\u003ch2 id=\"author\"\u003etitle: Configuración NextDNS en router Asus con firmware Merlin y en equipos Debian con NetworkManager\ndate: 2023-10-20 09:00:00 +0100\ncategories: [Network]\ntags: [config, network]     # TAG names should always be lowercase\nimg_path: /assets/pictures/\nauthor: \u003c!-- raw HTML omitted --\u003e\u003c/h2\u003e\n\u003ch2 id=\"instalación-de-nextdns-firmware-merlin-router-asus\"\u003eInstalación de Nextdns firmware Merlin router ASUS\u003c/h2\u003e\n\u003cp\u003eEn el \u003ca href=\"https://github.com/nextdns/nextdns\"\u003egithub de Nextdns\u003c/a\u003e tenemos toda la información para la instalación del NextDNS CLI Client en nuestro router. Este cliente emplea DNS-over-HTTPS.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eInstalación\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eNos conectamos por ssh al router y ejecutamos el script de instalación:\u003c/p\u003e","title":"Nextdns"},{"content":"Habilitar el safetynet en el móvil con ROM personalizada ROM personalizada LINEAGEOS\nCuando nuestro teléfono ha llegado al fin de su vida útil en lo que se refiere a actualizaciones de seguridad, he decidido emplear una ROM personalizada que nos permite tener nuestro sistema actualizado y operativo. Entre las que he probado están Pixel Experience y LineageOS entre otras.\nAl final me he decido por LineageOS ya que me da mucha confianza.\nAl usar estas ROM se genera un problema secundario, mi aplicación de pagos a través de NFC dice que el sistema tiene una ROM personalizada y por seguridad no permite realizar el pago.\nTenemos varias soluciones:\n1.- Instalar MAGISK con un módulo de safetynet. Tal vez, si probara hoy me funcione, pero la segunda opción han sido 5 minutos y me ha funcionado a la primera.\n2.- Modificar el fichero /system/build.prop del teléfono móvil.\nHe optado por esta segunda opción porque en su día lo intenté con MAGISK y no lo hice funcionar, desconociendo el por qué.\nLa esencia consiste en modificar las siguientes líneas del fichero /system/build.prop y cambiar el valor:\nro.secure=0 sustituirlos por ro.secure=1 ro.debuggable=1 sustituirlos por ro.debuggable=0 Para hacer este cambio tenemos que acceder al móvil por adb, que debe estar correctamente instalado en nuestro ordenador.\nHabilitamos las opciones de desarrollador en el móvil:\nAccedemos a Información del teléfono \u0026mdash;\u0026gt; Número de compilación (pulsamos 5 veces)\nDespués:\nSistema \u0026mdash;\u0026gt; Opciones de desarrollador\nActivamos Depuración por USB y Depuración como Superusuario.\nConectamos el teléfono al ordenador y activamos Transferencia de Archivos en lugar de Solo carga.\nAhora nos vamos a la terminal de nuestro ordenador y testeamos que detecta el teléfono:\n[noah@envy ~]$ ╰─ adb devices * daemon not running; starting now at tcp:5037 * daemon started successfully List of devices attached 967fd02\tdevice Vemos que detectamos el teléfono, procedemos con el cambio:\n[noah@envy ~]$ ╰─ adb root restarting adbd as root [noah@envy ~]$ ╰─ adb remount remount succeeded [noah@envy ~]$ ╰─ adb pull /system/build.prop . /system/build.prop: 1 file pulled, 0 skipped. 0.9 MB/s (7671 bytes in 0.008s) [noah@envy ~]$ ╰─ Ya tenemos el fichero build.prop y ahora vamos a modificar las dos líneas que nos interesan. El comando sed nos permite sustituir una cadena de texto por otra:\nsed -i \u0026#34;s/ro.secure=0/ro.secure=1/\u0026#34; build.prop sed -i \u0026#34;s/ro.debuggable=1/ro.debuggable=0/\u0026#34; build.prop Volvemos a subir el fichero al teléfono móvil:\nadb push build.prop /system/build.prop Y listo, reiniciamos el teléfono móvil y ya podemos instalar nuestra aplicación de pagos a través del NFC y debería funcionar.\nPara simplificar el trabajo podemos hacer un pequeño script que lo haga todo a la primera:\n#!/bin/bash adb root adb remount adb pull /system/build.prop . sed -i \u0026#34;s/ro.secure=0/ro.secure=1/\u0026#34; build.prop sed -i \u0026#34;s/ro.debuggable=1/ro.debuggable=0/\u0026#34; build.prop adb push build.prop /system/build.prop rm build.prop LineageOS hace actualizaciones semanales de la ROM. Cada vez que actualicemos tenemos que ejecutar nuestro pequeño script, activando las opciones de desarrollador, etc. por eso he decidido hacer actualizaciones mensuales mas o menos para no tener que estar pendiente de esto.\nFuentes:\nModificar fichero build.prop\nhttps://github.com/OmarAhmed-A/MakeLineageOSSecure\nhttps://forum.xda-developers.com/t/safetynet-on-lineageos-20-microg.4558065/\nMagisk\nhttps://topjohnwu.github.io/Magisk/install.html\nhttps://community.fxtec.com/topic/2537-magisk-install-step-by-step-root/\nhttps://telegra.ph/Instalar-Magisk-v24-en-nuestra-ROM\u0026ndash;Install-Magisk-on-our-ROM-03-11\n","permalink":"https://blog.lasnotasdenoah.com/posts/lineageos/","summary":"\u003ch2 id=\"habilitar-el-safetynet-en-el-móvil-con-rom-personalizada\"\u003eHabilitar el safetynet en el móvil con ROM personalizada\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eROM personalizada LINEAGEOS\u003c/strong\u003e\u003cbr\u003e\nCuando nuestro teléfono ha llegado al fin de su vida útil en lo que se refiere a actualizaciones de seguridad, he decidido emplear una ROM personalizada que nos permite tener nuestro sistema actualizado y operativo.\nEntre las que he probado están \u003ca href=\"https://get.pixelexperience.org/\"\u003ePixel Experience\u003c/a\u003e y \u003ca href=\"https://lineageos.org/\"\u003eLineageOS\u003c/a\u003e entre otras.\u003c/p\u003e\n\u003cp\u003eAl final me he decido por LineageOS ya que me da mucha confianza.\u003c/p\u003e","title":"LineageOS y SafetyNet"},{"content":"Instalación de Entware en firmware Merlin Fedora con Gnome trae instalado por defecto Gnome-Boxes. La verdad es que está genial pero tiene algunas carencias, como por ejemplo la conectividad de red.\nCon Gnome Boxes solo podemos acceder a nuestra máquina virtual desde el host pero no podemos acceder desde la red local o contactar con la red local desde la máquina virtual. Para eso vamos a instalar y configurar KVM Y Virt Manger.\nRequisitos\nVerificamos si tenemos la virtualización activa. Si no lo estuviera debemos acceder a la UEFI (BIOS) y activarla. grep -E --color \u0026#39;(vmx|svm)\u0026#39; /proc/cpuinfo Verificamos que el módulo KVM del kernel esté cargado:\nlsmod | grep -i kvm Instalación de los paquetes:\nsudo dnf install -y qemu-kvm libvirt virt-install bridge-utils Instalamos Virt-manager que es un gestor gráfico que facilita mucho el trabajo:\nsudo dnf install -y virt-manager Módulos de virtualización adicionales:\nsudo dnf install -y libvirt-devel virt-top libguestfs-tools guestfs-tools Iniciamos y habilitamos el daemon de virtualización:\nsudo systemctl start libvirtd sudo systemctl enable libvirtd sudo systemctl status libvirtd Ahora crearemos una red puente a nuestro sistema para poder acceder a la red local:\nAccedemos a la configuración de redes de QEMU/KVM:\nY configuramos el nombre. Forward to: Physical device\u0026hellip; Device: En mi caso he puesto la interfaz wifi: wlo1\nEl resto se configura según gustos del usuario:\nSi tenemos máquinas virtuales creadas con Gnome Boxes podemos usarlas a través de Virt Manager y adaptar las conexiones de red a nuestras necesidades. Gnome Boxes guarda sus máquinas en: ~/.local/share/gnome-boxes/images\nPodemos importar el disco de almacenamiento de estas máquinas a Virt Manager Y configuramos la red eligiendo el bridge network que hemos creado:\ny ya deberíamos poder acceder con nuestra máquina virtual a los equipos de la red local o viceversa.\nFuentes:\nhttps://www.linuxtechi.com/how-to-install-kvm-on-fedora-step-by-step/\nhttps://computingforgeeks.com/how-to-create-and-configure-bridge-networking-for-kvm-in-linux/?expand_article=1\n","permalink":"https://blog.lasnotasdenoah.com/posts/kvm-virtmanager/","summary":"\u003ch2 id=\"instalación-de-entware-en-firmware-merlin\"\u003eInstalación de Entware en firmware Merlin\u003c/h2\u003e\n\u003cp\u003eFedora con Gnome trae instalado por defecto Gnome-Boxes. La verdad es que está genial pero tiene algunas carencias, como por ejemplo la conectividad de red.\u003cbr\u003e\nCon Gnome Boxes solo podemos acceder a nuestra máquina virtual desde el host pero no podemos acceder desde la red local o contactar con la red local desde la máquina virtual. Para eso vamos a instalar y configurar KVM Y Virt Manger.\u003c/p\u003e","title":"KVM y VirtManager"},{"content":" title: Instalación de IDE IntelliJ date: 2023-06-16 22:00:00 +0100 categories: [Programming] tags: [software, programming] # TAG names should always be lowercase img_path: /pictures/ author: Instalación del IDE de programación IntelliJ Instalación mediante Flatpak\nEs una buena opción a través del centro de software de Gnome pero a mi me dio problemas de bloqueos por lo que he decidido realizar la instalación desde la web de jetbrains.\nDescargamos la versión Comunity de la web\nhttps://www.jetbrains.com/idea/download/#section=linux\nDescomprimimos el paquete en /opt:\nsudo tar -xzf ideaIU-*.tar.gz -C /opt Accedemos al directorio descomprimido:\ncd /opt/idea-IC-231.9011.34/bin ejecutamos ./idea.sh Por último podemos crear un enlace simbolico al path del sistema:\nsudo ln -s /opt/idea-IC-231.9011.34/bin/idea.sh /usr/bin/ideaC Para crear un enlace en el escritorio tenemos dos opciones:\nPrimera opción y más complicada\nCopiamos el icono al directorio de iconos:\nsudo cp IntelliJ.svg /usr/share/icons/ y generamos el fichero IntelliJ.desktop en /usr/share/applications con el siguiente contenido:\n[Desktop Entry] Version=1.0 Type=Application Name=IntelliJ Comunity GenericName=IntelliJ Comment=Launch IntelliJ Icon=IntelliJ Categories=Development; Exec=ideaC TryExec=ideaC Terminal=false Segunda opción y más sencilla\nAbrimos la aplicación idea.sh y en el menú principal:\nTools | Create Desktop Entry Fuentes:\nhttps://www.jetbrains.com/help/idea/installation-guide.html#standalone\n","permalink":"https://blog.lasnotasdenoah.com/posts/intellij/","summary":"\u003chr\u003e\n\u003ch2 id=\"author\"\u003etitle: Instalación de IDE IntelliJ\ndate: 2023-06-16 22:00:00 +0100\ncategories: [Programming]\ntags: [software, programming]     # TAG names should always be lowercase\nimg_path: /pictures/\nauthor: \u003c!-- raw HTML omitted --\u003e\u003c/h2\u003e\n\u003ch2 id=\"instalación-del-ide-de-programación-intellij\"\u003eInstalación del IDE de programación IntelliJ\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eInstalación mediante Flatpak\u003c/strong\u003e\u003cbr\u003e\nEs una buena opción a través del centro de software de Gnome pero a mi me dio problemas de bloqueos por lo que he decidido realizar la instalación desde la web de jetbrains.\u003c/p\u003e","title":"IntelliJ IDE"},{"content":"Crear un servicio con systemd Crear un script Antes que nada necesitamos crear un script que no es más que un simple archivo, que debe contener algo muy importante para arrancar y es #!/bin/bash, así que usamos un editor, en mi caso nano para crearlo:\nnano /usr/local/sbin/servicios Dentro vamos a colocar lo que necesitamos quedando con la siguiente estructura:\n#!/bin/bash contenido del script Una vez que lo guardamos con F2, le damos permisos de ejecución.\nchmod +x /usr/local/sbin/servicios Crear el servicio con systemd Es importante que el nombre al final termine con .service, dado que así lo entenderá systemd. Recordá que también debe tener permisos (otra forma es # chmod 777 servicio.service)\nnano /etc/systemd/system/servicios.service El contenido será el siguiente, teniendo en cuenta que la primera de las instrucciones especifica que se debe iniciar tras sección syslog.target.\nExecStart=/usr/local/sbin/servicio.service se da la ruta en dónde realmente está el script a ejecutar.\nDespués viene el tipo de servicio que hay varios, pero para este caso será:\n[Service] Type=forking\nPor último, la sección [Install] nos dice en qué runlevel se ejecutará. En el modo multiusuario o en el clásico sysv, que sería el runlevel 3.\nEl contenido entonces deberá ser algo como:\n[Unit] Description=Lanza servicios varios After=syslog.target [Service] Type=forking ExecStart=/usr/local/sbin/servicios [Install] WantedBy=multi-user.target Una vez este todo configurado debemos recargar.\nsudo systemctl daemon-reload Para lanzar el servicio simplemente hacemos:\nsudo systemctl start servicios.service Para habilitarlo al inicio y que se lance automáticamente:\nsudo systemctl enable servicios.service Y finalmente para ver el estado podemos hacer:\nsudo systemctl status servicios.service ","permalink":"https://blog.lasnotasdenoah.com/posts/systemd/","summary":"\u003ch2 id=\"crear-un-servicio-con-systemd\"\u003eCrear un servicio con systemd\u003c/h2\u003e\n\u003ch3 id=\"crear-un-script\"\u003eCrear un script\u003c/h3\u003e\n\u003cp\u003eAntes que nada necesitamos crear un script que no es más que un simple archivo, que debe contener algo muy importante para arrancar y es #!/bin/bash, así que usamos un editor, en mi caso nano para crearlo:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enano /usr/local/sbin/servicios\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eDentro vamos a colocar lo que necesitamos quedando con la siguiente estructura:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#!/bin/bash\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003econtenido del script\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eUna vez que lo guardamos con F2, le damos permisos de ejecución.\u003c/p\u003e","title":"Systemd"},{"content":"Añadir accesos directos de Office Online a Gnome Hay que reconocer que Microsoft Office es muy superior a alternativas libres. En alguna ocasión podemos necesitar su uso. Para que resulte más cómodo creamos estos accesos en el escritorio de Gnome:\nCopiar los ficheros de acceso en:\n~/.local/share/applications Copiar los iconos en:\n~/.local/share/icons Ficheros:\nIconos de Office\nFicheros .desktop\n","permalink":"https://blog.lasnotasdenoah.com/posts/office/","summary":"\u003ch2 id=\"añadir-accesos-directos-de-office-online-a-gnome\"\u003eAñadir accesos directos de Office Online a Gnome\u003c/h2\u003e\n\u003cp\u003eHay que reconocer que Microsoft Office es muy superior a alternativas libres. En alguna ocasión podemos necesitar su uso. Para que resulte más cómodo creamos estos accesos en el escritorio de Gnome:\u003cbr\u003e\nCopiar los ficheros de acceso en:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e~/.local/share/applications\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eCopiar los iconos en:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e~/.local/share/icons\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eFicheros:\u003cbr\u003e\n\u003ca href=\"/assets/files/icons.zip\"\u003eIconos de Office\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"/assets/files/links.zip\"\u003eFicheros .desktop\u003c/a\u003e\u003c/p\u003e","title":"Microsoft Office Online"},{"content":"Problemas al ejecutar algunos programas con renderizado gpu Algunos programas generan errores de visualización debido al renderizado de GPU con drivers Nvidia. En la mayoría lo podemos deshabilitar:\nVISUAL STUDIO CODE\nPrimera opción\nDentro de Visual Studio abrimos la paleta (Ctrl+Shift+P). Ejecutamos: Preferences: Configure Runtime Arguments Este comando abre el fichero de configuración \u0026ldquo;argv.json\u0026rdquo; y añadimos el siguiente texto \u0026#34;disable-hardware-acceleration\u0026#34;: true y reiniciamos Visual Studio Code\nSegunda Opción\nModificar el fichero \u0026ldquo;argv.json\u0026rdquo; de Visual Studio desde la terminal: nano ~/.vscode/argv.json Añadimos el mismo texto que decíamos antes\n\u0026#34;disable-hardware-acceleration\u0026#34;: true Tercera Opción\nModificar el lanzador de la aplicación de escritorio en Gnome: Editamos el fichero /usr/share/applications/code.desktop. Cambiamos\n`Exec=/usr/share/code/code --unity-launch %F` por `Exec=/usr/share/code/code --disable-gpu --unity-launch %F` TEAMS\nModificar el fichero\n~/.config/Microsoft/Microsoft Teams/desktop-config.json\nCambiamos\n\u0026#34;disableGpu\u0026#34;:false (por defecto la opción es FALSE) por \u0026#34;disableGpu\u0026#34;:true THUNDERBIRD\nEn la configuración hay que deshabilitar la aceleración por hardware:\nFuentes:\n","permalink":"https://blog.lasnotasdenoah.com/posts/gpu-render/","summary":"\u003ch2 id=\"problemas-al-ejecutar-algunos-programas-con-renderizado-gpu\"\u003eProblemas al ejecutar algunos programas con renderizado gpu\u003c/h2\u003e\n\u003cp\u003eAlgunos programas generan errores de visualización debido al renderizado de GPU con drivers Nvidia. En la mayoría lo podemos deshabilitar:\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eVISUAL STUDIO CODE\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003ePrimera opción\u003cbr\u003e\nDentro de Visual Studio abrimos la paleta (Ctrl+Shift+P).\nEjecutamos:\n\u003ccode\u003ePreferences: Configure Runtime Arguments\u003c/code\u003e\nEste comando abre el fichero de configuración \u0026ldquo;argv.json\u0026rdquo; y añadimos el siguiente texto\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;disable-hardware-acceleration\u0026#34;\u003c/span\u003e: true \n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003ey reiniciamos Visual Studio Code\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eSegunda Opción\u003cbr\u003e\nModificar el fichero \u0026ldquo;argv.json\u0026rdquo; de Visual Studio desde la terminal:\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enano ~/.vscode/argv.json\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eAñadimos el mismo texto que decíamos antes\u003c/p\u003e","title":"Problemas con Nvidia"},{"content":"Qué es y cómo funciona el comando Screen en Linux Hablamos del programa Screen, que permite en los sistemas GNU/Linux, abrir múltiples instancias de terminal dentro de una sola sesión. De esta manera, si salimos de una de las instancias de terminal, el proceso que se ejecute en dicha terminal no se interrumpirá y continuará en segundo plano.\n¿En qué consiste el comando Screen? Screen, según indica su página de man, es un administrador de ventanas en pantalla completa, que multiplexa un terminal en varios procesos, cada proceso asociado a una nueva terminal.\nCuando se utiliza el comando Screen, este crea una única ventana con una terminal en ella (o un comando especificado) de forma independiente. Por lo que, en cualquier momento, podemos crear nuevas ventanas con otros programas.\nPermite también obtener una lista de las ventanas activas, activar o desactivar el registro de salida, copiar y pegar texto en las ventanas, mostrar el historial, cambiar entre ventanas, etcétera.\nPara usuarlo sólo hemos de escribir “screen”\nscreen Existe la posibilidad de asignar un nombre a una nueva sesión, como se muestra en el ejemplo, utilizando el parámetro “-S”\nscreen -S nombre-de-sesión Si nos queremos desvincular de una sesión hemos de utilizar la siguiente combinación de teclas:\nCtrl+a d Para volver a una sesión ya existente debemos utilizar el parámetro “-r”\nscreen -r Fuentes:\n","permalink":"https://blog.lasnotasdenoah.com/posts/screen-command/","summary":"\u003ch2 id=\"qué-es-y-cómo-funciona-el-comando-screen-en-linux\"\u003eQué es y cómo funciona el comando Screen en Linux\u003c/h2\u003e\n\u003cp\u003eHablamos del programa \u003cstrong\u003eScreen\u003c/strong\u003e, que permite en los sistemas \u003cstrong\u003eGNU\u003c/strong\u003e/\u003cstrong\u003eLinux\u003c/strong\u003e, abrir múltiples instancias de terminal dentro de una sola sesión. De esta manera, si salimos de una de las instancias de terminal, el proceso que se ejecute en dicha terminal no se interrumpirá y continuará en segundo plano.\u003c/p\u003e\n\u003ch3 id=\"en-qué-consiste-el-comando-screen\"\u003e¿En qué consiste el comando Screen?\u003c/h3\u003e\n\u003cp\u003e\u003cstrong\u003eScreen\u003c/strong\u003e, según indica su página de \u003ca href=\"https://linux.die.net/man/1/screen\"\u003e\u003cstrong\u003eman\u003c/strong\u003e\u003c/a\u003e, es un administrador de ventanas en pantalla completa, que multiplexa un terminal en varios procesos, cada proceso asociado a una nueva terminal.\u003c/p\u003e","title":"Comando \"screen\""},{"content":"Qué es y cómo funciona el comando find en Linux La sintáxis básica del comando “find” es:\nfind directorio criterio acción\nDirectorio.- define la ubicación desde la que se quiere empezar la búsqueda. Por ejemplo: /home/ Criterio.- se usa para seleccionar los archivos. Se pueden usar comodines. Por ejemplo: *.tmp Acción.- se especifica aquí qué debe hacer el comando con los archivos que cumplan con el criterio indicado. Para eliminar múltiples archivos del tipo que queramos:\nfind . -name \u0026#34;archivo\u0026#34; -exec rm -rf {} \\\\; o\nfind . -type f -name \u0026#34;archivo\u0026#34; -exec rm -rf {} \\\\; La diferencia entre ambos comandos indicados arriba es que el primero localiza y borra archivos y directorios, y el segundo sólo archivos.\n-name “archivo”.- se indica aquí qué estamos buscando. Se pueden usar comodines. -exec rm -rf.- Ejecuta el comando indicado a continuación, es decir, tras el “-exec” insertamos el comando que se ejecutará con cada archivo encontrado. En este caso es “rm” con el modificador “-rf”, que significa borrar de forma recursiva sin preguntar. -type f: Permite filtrar para incluir sólo f(icheros) o d(irectorios). Ejemplos: Mucho mucho ojo al usar estos comandos como root:\nBuscar y borrar todos los archivos con extensión *.bak en el directorio en el que estás:\nfind . -type f -name \u0026#34;*.bak\u0026#34; -exec rm -f {} \\\\; Buscar todos los nombres de archivo que contengan la palabra “core” desde la raíz y eliminarlos:\nfind / -name core -exec rm -f {} \\\\; Buscar y eliminar los archivos *.bak desde el directorio actual pero pidiendo confirmación por cada archivo encontrado:\nfind . -type f -name \u0026#34;*.bak\u0026#34; -exec rm -i {} \\\\; Buscar y eliminar archivos ocultos en el directorio que estamos:\nfind -type f -name \u0026#34;.*\u0026#34; -exec rm -f {} \\; Fuentes:\n","permalink":"https://blog.lasnotasdenoah.com/posts/find-command/","summary":"\u003ch2 id=\"qué-es-y-cómo-funciona-el-comando-find-en-linux\"\u003eQué es y cómo funciona el comando find en Linux\u003c/h2\u003e\n\u003cp\u003eLa sintáxis básica del comando “find” es:\u003c/p\u003e\n\u003cp\u003efind directorio criterio acción\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eDirectorio\u003c/strong\u003e.- define la ubicación desde la que se quiere empezar la búsqueda. Por ejemplo: /home/\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eCriterio\u003c/strong\u003e.- se usa para seleccionar los archivos. Se pueden usar comodines. Por ejemplo: *.tmp\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAcción\u003c/strong\u003e.- se especifica aquí qué debe hacer el comando con los archivos que cumplan con el criterio indicado.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003ePara eliminar múltiples archivos del tipo que queramos:\u003c/p\u003e","title":"Comando \"find\""},{"content":"Instalación de Entware en firmware Merlin Entware es un repositorio de software que nos va a permitir la instalación de diferentes programas en nuestro router. Software disponible en Entware\nRequisitos\nEs necesario tener conectado un disco USB en el router formateado con ext2 o ext3 Si está instalado Download Manager, se debe desinstalar y reiniciar el router Instalación\nDescargar el script y añadirlo al usb. Nos conectamos por ssh al router. Ejecutar el script:\nusuario@RT-AC86U-3EB8:/tmp/home/root# entware-setup.sh Info: This script will guide you through the Entware installation. Info: Script modifies \u0026#34;entware\u0026#34; folder only on the chosen drive, Info: no other data will be changed. Existing installation will be Info: replaced with this one. Also some start scripts will be installed, Info: the old ones will be saved on Entware partition with name Info: like /tmp/mnt/sda1/jffs_scripts_backup.tgz Entware se instalará en el USB. Si tenemos varios nos preguntará donde instalarlo.\nUso\nopkg list - lista todos los paquetes disponibles para instalar opkg install nombre_software - instala el paquete nombre_software opkg remove software_name - borra el paquete nombre_software A partir de aquí podemos instalar software como Tailscale.\nFuentes:\nhttps://elblogdelazaro.org/posts/2019-01-02-instalacion-de-entware-en-firmware-merlin/\nhttps://github.com/RMerl/asuswrt-merlin/wiki/Entware\n","permalink":"https://blog.lasnotasdenoah.com/posts/asus-merlin/","summary":"\u003ch2 id=\"instalación-de-entware-en-firmware-merlin\"\u003eInstalación de Entware en firmware Merlin\u003c/h2\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/RMerl/asuswrt-merlin/wiki/Entware\"\u003eEntware\u003c/a\u003e es un repositorio de software que nos va a permitir la instalación de diferentes programas en nuestro router. \u003ca href=\"http://bin.entware.net/armv7sf-k3.2/Packages.html\"\u003eSoftware disponible en Entware\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eRequisitos\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eEs necesario tener conectado un disco USB en el router formateado con ext2 o ext3\u003c/li\u003e\n\u003cli\u003eSi está instalado Download Manager, se debe desinstalar y reiniciar el router\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eInstalación\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eDescargar el script y añadirlo al usb.\nNos conectamos por ssh al router.\nEjecutar el script:\u003c/p\u003e","title":"Entware"},{"content":"Configuración sistema para ejecutar web estática en local antes de subir a github Instalación de rubygems\nInstalamos el software necesario a través de DNF:\nsudo dnf install ruby rubygems ruby-devel gcc gcc-c++ rpm-build Para Debian 12:\nsudo apt install ruby ruby-dev build-essential Le decimos al administrador de gemas donde queremos que se instalen las gemas: Editamos .zshrc y añadimos esto al final:\n# Install Ruby Gems to ~/gems export GEM_HOME=\u0026#34;$HOME/gems\u0026#34; export PATH=\u0026#34;$PATH:~/bin\u0026#34; export PATH=\u0026#34;$HOME/gems/bin:$PATH\u0026#34; Recargamos el entorno de Zsh:\nsource .zshrc Ahora ya podemos instalar las gemas. Instalamos las gemas de jekyll y bundler:\ngem install jekyll bundler Como estamos usando la plantilla de just-the-docs ya vienen preparada con un Gemfile que es el que indica las gemas necesarias para ejecutar en local con jekyll.\nEjecutamos dentro del directorio de nuestro proyecto:\nbundle install Después:\nbundle exec jekyll serve Se arrancará el servidor en:\nlocalhost:4000 Es posible que el sistema lance un error similar a este:\nzsh: jekyll: command not found... Install package \u0026#39;rubygem-jekyll\u0026#39; to provide command \u0026#39;jekyll\u0026#39;? [N/y] nnn Eso significa que no encuentra jekyll como comando. En mi sistema los ejecutables de las gemas se instalaban en el siguiente path: ~/bin\nHaciendo un ls aparecen los siguientes ejecutables:\nbundle jekyll kramdown rake safe_yaml bundler just-the-docs listen rougify En stacoverflow aportan una posible solución. Todo se limita a añdir al PATH el directorio donde se encuentran los ejecutables:\nnano .zshrc copy and past these two lines of code at the end of the .zshrc export GEM_HOME=\u0026#34;$(ruby -e \u0026#39;puts Gem.user_dir\u0026#39;)\u0026#34; export PATH=\u0026#34;$PATH:$GEM_HOME/bin\u0026#34; En ~/.local/share/gem/ruby se copia la carpeta ~/bin o bien se añade directamente esta última al path.\nY si queremos eliminar todas las gemas instaladas de Ruby:\nfor i in \u0026#39;gem list --no-versions\u0026#39;; do gem uninstall -aIx $i; done Para eliminar sólo una:\ngem uninstall gemaaaaaa --version 1.1.9 Fuentes:\nhttps://docs.github.com/es/pages/setting-up-a-github-pages-site-with-jekyll/creating-a-github-pages-site-with-jekyll\nhttps://docs.github.com/es/pages/setting-up-a-github-pages-site-with-jekyll/testing-your-github-pages-site-locally-with-jekyll\nhttps://github.com/just-the-docs/just-the-docs-template/blob/main/README.md\nhttp://brionescl.blogspot.com/2014/02/eliminar-todas-las-gemas-de-ruby.html\n","permalink":"https://blog.lasnotasdenoah.com/posts/jekyll/","summary":"\u003ch2 id=\"configuración-sistema-para-ejecutar-web-estática-en-local-antes-de-subir-a-github\"\u003eConfiguración sistema para ejecutar web estática en local antes de subir a github\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eInstalación de rubygems\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eInstalamos el software necesario a través de DNF:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo dnf install ruby rubygems ruby-devel gcc gcc-c++ rpm-build\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003ePara Debian 12:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo apt install ruby ruby-dev build-essential\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eLe decimos al administrador de gemas donde queremos que se instalen las gemas:\nEditamos .zshrc y añadimos esto al final:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Install Ruby Gems to ~/gems\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eexport GEM_HOME\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e$HOME\u003cspan style=\"color:#e6db74\"\u003e/gems\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eexport PATH\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e$PATH\u003cspan style=\"color:#e6db74\"\u003e:~/bin\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eexport PATH\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e$HOME\u003cspan style=\"color:#e6db74\"\u003e/gems/bin:\u003c/span\u003e$PATH\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eRecargamos el entorno de Zsh:\u003c/p\u003e","title":"Web estática con Jekyll"},{"content":"Instalación de drivers NVIDIA en Fedora Verificamos si en el administrador de software de Gnome aparecen los drivers Nvidia:\nEn caso afirmativo podemos saltarnos el siguiente paso. Si no aparecen los drivers de Nvidia quiere decir que tenemos que actualizar el repositorio RPMFusion\nInstalación de forma gráfica desde administrador de software\nInstalamos el software necesario a través de DNF: Instalamos primeramente el repositorio free:\nsudo dnf install https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm Y después instalamos el non-free que es donde se alojan los drivers de Nvidia:\nsudo dnf install https://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm sudo dnf upgrade -y Si hacemos la instalación de forma gráfica instalamos “Nvidia Linux Graphics Driver” y “Nvidia X Server Settings”.\nLos demás no. Como se ve en la captura anterior.\nInstalación desde la terminal\nsudo dnf -y install kmod-nvidia sudo dnf install xorg-x11-drv-nvidia-cuda Puedes ejecutarlos juntos o uno y después el otro. El primero instala los drivers generales y el segundo comando el oporte para CUDA(cuda son los núcleos de Nvidia, una gráfica tiene miles normalmente a día de hoy, sería el equivalente a los núcleos de las CPU).\nDe hecho, puedes instalar solo los drivers y prescindir del segundo programa, pero es mejor ambos.\nProblemas al ejecutar algunos programas\nAlgunos programas dan problemas al ejecutarse con el renderizado de la GPU activada. Pasos para desactivarlo:\nVISUAL STUDIO CODE\nPrimera opción\nDentro de Visual Studio abrimos la paleta (Ctrl+Shift+P). Ejecutamos: Preferences: Configure Runtime Arguments Este comando abre el fichero de configuración \u0026ldquo;argv.json\u0026rdquo; y añadimos el siguiente texto \u0026#34;disable-hardware-acceleration\u0026#34;: true y reiniciamos Visual Studio Code\nSegunda Opción\nModificar el fichero \u0026ldquo;argv.json\u0026rdquo; de Visual Studio desde la terminal: nano ~/.vscode/argv.json Añadimos el mismo texto que decíamos antes\n\u0026#34;disable-hardware-acceleration\u0026#34;: true Tercera Opción\nModificar el lanzador de la aplicación de escritorio en Gnome: Editamos el fichero /usr/share/applications/code.desktop. Cambiamos\n`Exec=/usr/share/code/code --unity-launch %F` por `Exec=/usr/share/code/code --disable-gpu --unity-launch %F` TEAMS\nModificar el fichero\n~/.config/Microsoft/Microsoft Teams/desktop-config.json\nCambiamos\n\u0026#34;disableGpu\u0026#34;:false por \u0026#34;disableGpu\u0026#34;:false THUNDERBIRD\nEn la configuración hay que deshabilitar la aceleración por hardware:\nFuentes:\nhttps://yourgeekweb.com/es/2022/06/18/como-instalar-los-drivers-de-nvidia-en-linux-fedora/\n","permalink":"https://blog.lasnotasdenoah.com/posts/nvidia-fedora/","summary":"\u003ch2 id=\"instalación-de-drivers-nvidia-en-fedora\"\u003eInstalación de drivers NVIDIA en Fedora\u003c/h2\u003e\n\u003cp\u003eVerificamos si en el administrador de software de Gnome aparecen los drivers Nvidia:\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Foto.png\" loading=\"lazy\" src=\"/posts/nvidia-fedora/gnome-software-driver-nvidia-1024x666.png\"\u003e\nEn caso afirmativo podemos saltarnos el siguiente paso.\nSi no aparecen los drivers de Nvidia quiere decir que tenemos que actualizar el repositorio RPMFusion\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eInstalación de forma gráfica desde administrador de software\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eInstalamos el software necesario a través de DNF:\nInstalamos primeramente el repositorio free:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo dnf install https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-\u003cspan style=\"color:#66d9ef\"\u003e$(\u003c/span\u003erpm -E %fedora\u003cspan style=\"color:#66d9ef\"\u003e)\u003c/span\u003e.noarch.rpm\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eY después instalamos el non-free que es donde se alojan los drivers de Nvidia:\u003c/p\u003e","title":"Drivers Nvidia"},{"content":"FirewallD Instalación y configuración del firewallD\nSi queremos tener el applet en la barra de tareas de gnome añadimos lo siguiente:\nsudo dnf install firewall-config firewall-applet -y FirewalID debería estar ya habilitado por defecto, lo comprobamos: La mejor práctica es habilitar automáticamente el software de firewall al iniciar el sistema e iniciarlo de inmediato. Esto se puede lograr con un comando todo en uno de la siguiente manera.\nsudo systemctl enable firewalld --now A continuación, verificamos el estado de FirewallD para asegurarse de que todo funcione y no haya errores.\nsystemctl status firewalld Después añadimos a los programas de inicio el firewall-applet de la siguiente forma:\ncd ~/.config/autostart touch firewall-applet.desktop nano firewall-applet.desktop Añadimos el siguiente texto:\n[Desktop Entry] Name=Firewall Applet Comment=Firewall Applet Icon=firewall-config Categories=System;Settings;Security; #Translators: These are searchable keywords for the firewall configuration tool Keywords=firewall;network;security;iptables;netfilter; Exec=/usr/bin/firewall-applet Type=Application StartupNotify=true Terminal=false X-Desktop-File-Install-Version=0.26 Las reglas del firewall para aplicaciones y demás ya es configurar a gusto del usuario.\nFuentes:\nhttps://fedoraproject.org/wiki/FirewallD/es\n","permalink":"https://blog.lasnotasdenoah.com/posts/firewalld/","summary":"\u003ch2 id=\"firewalld\"\u003eFirewallD\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eInstalación y configuración del firewallD\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eSi queremos tener el applet en la barra de tareas de gnome añadimos lo siguiente:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo dnf install firewall-config firewall-applet -y\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eFirewalID debería estar ya habilitado por defecto, lo comprobamos:\nLa mejor práctica es habilitar automáticamente el software de firewall al iniciar el sistema e iniciarlo de inmediato.\nEsto se puede lograr con un comando todo en uno de la siguiente manera.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo systemctl enable firewalld --now\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eA continuación, verificamos el estado de FirewallD para asegurarse de que todo funcione y no haya errores.\u003c/p\u003e","title":"Firewalld Instalación"},{"content":"Primeros pasos después de instalar Fedora o Debian NOTA: Aunque la mayor parte de este post se centra en Fedora, debo decir que Debian para mí siempre será la mejor, por ese motivo he añadido unas notas sobre instalación en Debian. Configurar DNF para descargas más rápidas:\nsudo nano /etc/dnf/dnf.conf y añadimos la siguiente línea:\nmax_parallel_downloads=10 Realizamos una acutalización completa del sistema:\nsudo dnf upgrade -y Habilitamos los respostorios de RPM Fusion:\nsudo dnf install https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm sudo dnf install https://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm Compatibilidad con ciertos formatos comprimidos, así como OpenSSL para usar la extensión GSConnect:\nsudo dnf install openssl unrar p7zip p7zip-plugins Principales codecs multimedia:\nsudo dnf install gstreamer1-plugins-bad-free-extras gstreamer1-plugin-openh264 gstreamer1-plugins-good-extras mozilla-openh264 gstreamer1-plugins-bad-free-fluidsynth gstreamer1-plugins-bad-free-wildmidi gstreamer1-svt-av1 sudo dnf install vlc ACTUALIZACIÓN 28/07/2025 He tenido problemas de reproducción de videos H.265 del sistema CCTV. Para solucionarlo he tenido que instalar los siguientes paquetes según este hilo de los foros de Fedora:\nEsto creo que no es necesario porque los repositorios rpmfusion ya deberían estar instalados de los pasos anteriores:\nsudo dnf install https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm sudo dnf install https://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm sudo dnf install libavcodec-freeworld --allowerasing sudo dnf install intel-media-driver --allowerasing Por defecto Fedora ofrece la versión libre para el códec de vídeo H264, que resulta insuficiente. Con la anterior orden ampliamos el soporte, pero si usamos Firefox debemos efectuar un pequeño cambio: Menú \u0026gt; Complementos y temas \u0026gt; Plugins, y allí activaremos el códec Open H264 de Cisco. Esta información ha sido obtenida de la web thecheis.com.\nAñadimos el repositorio de Flathub:\nflatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo Solo para Debian Si queremos tener disponible el software de faltpak en el administrador de software de gnome debemos instalar el siguiente paquete:\nsudo apt install gnome-software-plugin-flatpak En la instalación Fedora no pregunta por el nombre del host. Ahora podemos modificarlo:\nsudo hostnamectl set-hostname \u0026#34;New_Custom_Name\u0026#34; Instalamos las aplicaciones esenciales para personalizar Gnome:\nsudo dnf install gnome-tweaks gnome-extensions-app Instalamos también Extension Manager desde el administrador de Software de Gnome (es una aplicación Flatpak).\nInstalamos Flatseal y Warehouse, que son aplicaciones de Flatpak para gestionar permisos y almacenamientos de estas aplicaciones. Extensiones instaladas: Habilitamos Maximizar y Minimizar en las ventanas:\nHabilitar/deshabilitar los informes de errores: Configuraciones de energía: Habilitamos luz nocturna para reducir la fatiga visual: Ordenación de directorios antes de los ficheros: Configuraciones de papelera de reciclaje: Nota: Lista de flatpak que he instalado a mayores de lo que había:\nWarp app.drey.Warp 0.6.1 stable flathub system teams-for-linux com.github.IsmaelMartinez.teams_for_linux 1.3.19 stable flathub system Flatseal com.github.tchx84.Flatseal 2.1.0 stable flathub system IntelliJ IDEA Community com.jetbrains.IntelliJ-IDEA-Community 2023.2.5 stable flathub system Extension Manager com.mattjakeman.ExtensionManager 0.4.3 stable flathub system Warehouse io.github.flattool.Warehouse 1.3.0 stable flathub system Kooha io.github.seadve.Kooha 2.2.4 stable flathub system SaveDesktop io.github.vikdevelop.SaveDesktop 2.9 stable flathub system Photoflare io.photoflare.photoflare 1.6.13 stable flathub system Joplin net.cozic.joplin_desktop 2.12.19 stable flathub system Geary org.gnome.Geary 44.1 stable fedora system Kasts org.kde.kasts 23.08.1 stable fedora system Nota: Lista de paquetes instalados por dnf:\n8 sudo dnf install vlc conky zsh 14 sudo dnf install teams 17 sudo dnf install gnome-tweaks gnome-extensions-app 19 sudo dnf install timeshift 20 sudo dnf install firewall-config firewall-applet 28 sudo dnf install translate-shell 31 sudo dnf install nvme-cli 38 sudo dnf install etherwake 39 sudo dnf install ether-wake 40 sudo dnf install net-tools 43 sudo dnf install thunderbird # Ya no lo uso, ahora uso Geary 55 sudo dnf install wireguard-tools 72 sudo dnf install code 149 sudo dnf install util-linux-user 456 sudo dnf install codium 794 sudo dnf install nextcloud-client-nautilus nextcloud-client 1013 sudo dnf install brave-browser 1016 sudo dnf install photoflare 1295 sudo dnf install telegram-desktop 1965 sudo dnf install steam 2291 sudo dnf install dconf-editor 2348 sudo dnf install htop 2351 sudo dnf install gstreamer1-plugins-bad-free-extras gstreamer1-plugin-openh264 gstreamer1-plugins-good-extras mozilla-openh264 gstreamer1-plugins-bad-free-fluidsynth gstreamer1-plugins-bad-free-wildmidi gstreamer1-svt-av1 2352 sudo dnf install openssl unrar p7zip p7zip-plugins Nota: Lista de paquetes instalados por apt:\nsudo apt install zram-tools sudo apt install flatpak sudo apt install gnome-software-plugin-flatpak sudo apt autoremove gnome-games sudo apt install nextcloud-desktop nautilus-nextcloud Fuentes:\nhttps://itsfoss.com/things-to-do-after-installing-fedora/\nhttps://thecheis.com/2023/08/09/puesta-a-punto-intel-nuc-fedora/\n","permalink":"https://blog.lasnotasdenoah.com/posts/primeros-pasos/","summary":"\u003ch2 id=\"primeros-pasos-después-de-instalar-fedora-o-debian\"\u003ePrimeros pasos después de instalar Fedora o Debian\u003c/h2\u003e\n\u003cp\u003eNOTA: Aunque la mayor parte de este post se centra en Fedora, debo decir que Debian para mí siempre será la mejor, por ese motivo he añadido unas notas sobre instalación en Debian.\nConfigurar DNF para descargas más rápidas:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo nano /etc/dnf/dnf.conf\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003ey añadimos la siguiente línea:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emax_parallel_downloads\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eRealizamos una acutalización completa del sistema:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo dnf upgrade -y\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eHabilitamos los respostorios de RPM Fusion:\u003c/p\u003e","title":"Primeros pasos con Fedora Gnome"},{"content":"System quitar entradas antiguas de UEFI Instalarción Zsh Alias .zshrc (fichero .zshrc) firewall-config y firewall-applet (ojo añadir firewall-applet al arranque del sistema) Instalación conky (fichero .conkyrc) Traductor de consola (sudo apt install translate-shell) Apps Configuración Flatpak Timeshift Deja-dup Insync Nextcloud Joplin (Flatpak) Thunderbird o Geary (Actualmente estoy con Geary) Idioma thunderbird Libreoffice Idioma en Libreoffice - OK Kooha (Flatpak) Teams Telegram Boxes de Gnome Virtual box Network Configurar claves ssh con NAS principal Configurar claves ssh con NAS secundario Configurar accesos smb al NAS principal Configurar accesos smb al NAS secundario a través de Zerotier o Tailscale Con tailscale el recurso compartido en smb es: smb://xxx.xxx.xxx.xxx/Recurso_compartido Configurar claves ssh con ROUTERS Configurar el cliente Wireguard de nuestra VPN al NAS (para debian): sudo apt install wireguard Copiamos el fichero wg0.conf generado por el servidor a la carpeta /etc/wireguard sudo wg-quick up wg0 - Conexión a la VPN sudo wg-quick down wg0 - Desconexión a la VPN Configurar VPN de pago en Gnome Instalar antes el paquete network-manager-openvpn-gnome Configuración ZeroTier (ultima versión da fallo en Debian testing) Configuración Tailscale Configuración NextDNS curl -fsSL https://tailscale.com/install.sh | sh (en la web de Tailscale se detalla) Instalar extensión Gnome: Tailscale Status Desktop Primeros pasos con Gnome (https://itsfoss.com/things-to-do-after-installing-fedora/) Tweeks Gnome extensions Extension manager (está como paquete en Flathub) Minimizar y Maximizar Night-light settings Cambiar primer dia calendario (Generar locales Debian) Añadir accesos directos Office Online Nuevo documento en plantillas de nautilus SaveDesktop - Backup de la configuración de escritorio Programming visual studio code Python entornos virtuales ","permalink":"https://blog.lasnotasdenoah.com/posts/mis-imprescindibles/","summary":"\u003ch2 id=\"system\"\u003eSystem\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e quitar entradas antiguas de UEFI\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ca href=\"/posts/zsh/index.html\"\u003eInstalarción Zsh\u003c/a\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Alias .zshrc \u003ca href=\"/assets/files/zshrc\"\u003e(fichero .zshrc)\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e firewall-config y firewall-applet (ojo añadir firewall-applet al arranque del sistema)\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Instalación conky \u003ca href=\"/assets/files/conkyrc\"\u003e(fichero .conkyrc)\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Traductor de consola (sudo apt install translate-shell)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"apps\"\u003eApps\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ca href=\"/posts/Flatpak/index.html\"\u003eConfiguración Flatpak\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Timeshift\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Deja-dup\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Insync\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Nextcloud\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Joplin (Flatpak)\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Thunderbird o Geary (Actualmente estoy con Geary)\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Idioma thunderbird\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Libreoffice\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Idioma en Libreoffice - OK\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Kooha (Flatpak)\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Teams\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Telegram\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Boxes de Gnome\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Virtual box\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"network\"\u003eNetwork\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Configurar claves ssh con NAS principal\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Configurar claves ssh con NAS secundario\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Configurar accesos smb al NAS principal\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Configurar accesos smb al NAS secundario a través de Zerotier o Tailscale\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Con tailscale el recurso compartido en smb es:\nsmb://xxx.xxx.xxx.xxx/Recurso_compartido\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Configurar claves ssh con ROUTERS\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Configurar el cliente Wireguard de nuestra VPN al NAS (para debian):\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e sudo apt install wireguard\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Copiamos el fichero wg0.conf generado por el servidor a la carpeta /etc/wireguard\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e sudo wg-quick up wg0 - Conexión a la VPN\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e sudo wg-quick down wg0 - Desconexión a la VPN\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Configurar VPN de pago en Gnome\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Instalar antes el paquete network-manager-openvpn-gnome\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Configuración ZeroTier (ultima versión da fallo en Debian testing)\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Configuración Tailscale\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Configuración NextDNS\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e curl -fsSL \u003ca href=\"https://tailscale.com/install.sh\"\u003ehttps://tailscale.com/install.sh\u003c/a\u003e | sh (en la web de Tailscale se detalla)\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Instalar extensión Gnome: Tailscale Status\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"desktop\"\u003eDesktop\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Primeros pasos con Gnome (\u003ca href=\"https://itsfoss.com/things-to-do-after-installing-fedora/\"\u003ehttps://itsfoss.com/things-to-do-after-installing-fedora/\u003c/a\u003e)\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Tweeks\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Gnome extensions\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Extension manager (está como paquete en Flathub)\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Minimizar y Maximizar\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Night-light settings\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Cambiar primer dia calendario (\u003ca href=\"/posts/locales/index.html\"\u003eGenerar locales Debian\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Añadir accesos directos Office Online\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Nuevo documento en plantillas de nautilus\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e SaveDesktop - Backup de la configuración de escritorio\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"programming\"\u003eProgramming\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e visual studio code\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Python entornos virtuales\u003c/li\u003e\n\u003c/ul\u003e","title":"Software imprescindible"},{"content":"Instalación nuevos locales en Debian Revisamos los locales que tenemos generados en el sistema:\nlocale -a Podemos generar más editando /etc/locale.gen y descomentando la línea que nos interesa:\nes_ES.UTF-8 UTF-8 Generamos nuevamente los locales con:\nlocale-gen Hacemos el cambio en \u0026ldquo;Region \u0026amp; Language\u0026rdquo;\n","permalink":"https://blog.lasnotasdenoah.com/posts/locales-debian/","summary":"\u003ch2 id=\"instalación-nuevos-locales-en-debian\"\u003eInstalación nuevos locales en Debian\u003c/h2\u003e\n\u003cp\u003eRevisamos los locales que tenemos generados en el sistema:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003elocale -a\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003ePodemos generar más editando /etc/locale.gen y descomentando la línea que nos interesa:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ees_ES.UTF-8 UTF-8\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eGeneramos nuevamente los locales con:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003elocale-gen\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eHacemos el cambio en \u0026ldquo;Region \u0026amp; Language\u0026rdquo;\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Region\" loading=\"lazy\" src=\"/posts/locales-debian/1.png\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"vista\" loading=\"lazy\" src=\"/posts/locales-debian/2.png\"\u003e\u003c/p\u003e","title":"Locales Debian"},{"content":"Soporte Flatpak en Debian 11 Bullseye Información en la web oficial de Flatpak.\nAunque, a mi modo de ver, es importante instalar el software con la paquetería .deb, en ocasiones es necesario usar flatpak porque el software no está disponible en otro formato.\nInstalamos el paquete flatpak\nDependiendo nuestro sistema operativo, el comando será el siguiente:\n# Debian apt install flatpak # Fedora dnf install flatpak Instalamos el plugin para la tienda de software. En este caso la tienda de Gnome.\napt install gnome-software-plugin-flatpak Agregamos el repositorio de Flathub\nflatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo Para buscar una aplicación en Flathub:\nflatpak search firefox Listado de aplicaciones flatpak instaladas\nflatpak list Listado limpio que solo enumera las aplicaciones\nflatpak list --app Para eliminar un flatpak, primero debemos obtener el ID de la aplicación y ejecutar el siguiente comando\nflatpak uninstall --delete-data org.mozilla.firefox Para eliminar un flatpak, primero debemos obtener el ID de la aplicación y ejecutar el siguiente comando\nflatpak uninstall --delete-data org.mozilla.firefox Elimina todas la librerías que no están en uso por ninguna app instalada, o las versiones antiguas residuales que ya han sido actualizadas\nflatpak uninstall --unused Para eliminar completamente Flatpak del sistema ejecutamos:\nsudo flatpak repair Después podemos seguir con los comandos:\nsudo apt autoremove flatpak sudo apt purge flatpak ","permalink":"https://blog.lasnotasdenoah.com/posts/flatpak/","summary":"\u003ch2 id=\"soporte-flatpak-en-debian-11bullseye\"\u003eSoporte Flatpak en Debian 11 Bullseye\u003c/h2\u003e\n\u003cp\u003eInformación en la \u003ca href=\"https://flatpak.org/setup/Debian/\"\u003eweb oficial de Flatpak\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eAunque, a mi modo de ver, es importante instalar el software con la paquetería .deb, en ocasiones es necesario usar flatpak porque el software no está disponible en otro formato.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eInstalamos el paquete flatpak\u003c/strong\u003e\u003cbr\u003e\nDependiendo nuestro sistema operativo, el comando será el siguiente:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Debian\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eapt install flatpak\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Fedora\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ednf install flatpak\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eInstalamos el plugin para la tienda de software. En este caso la tienda de Gnome.\u003c/strong\u003e\u003c/p\u003e","title":"Flatpak"},{"content":"Según su web, NextDNS ofrece un firewall para la Internet moderna. NextDNS protege de todo tipo de amenazas a la seguridad, bloquea anuncios y rastreadores en sitios web y aplicaciones, y brinda una Internet segura y supervisada para niños, en todos los dispositivos y en todas las redes.\nMe parece un servicio genial por 20€ al año que ofrece mucha seguridad a la hora de navegar por internet.\nConfiguración de DNS privado en Fedora En nuestro sistema Fedora, estarán conviviendo NetworkMananger con systemd-resolved, por tanto, el primer paso que debemos hacer es indicarle a NetworkManager que la resolución de DNS se va a realizar con systemd-resolved.\nEditamos el fichero /etc/NetworkManager/conf.d/dns.conf y añadimos el siguiente contenido:\n[main] dns=systemd-resolved En versiones actuales del servicio systemd-resolved el fichero de configuración resolved.conf se encuentra en /etc/systemd/resolved.conf.d/, anteriormente se encontraba en /etc/systemd/\nCreamos el fichero resolved.conf en la ruta /etc/systemd/resolved.conf.d:\nTenemos como ejemplo los DNS de quad9, que funcionan muy bien:\n[Resolve] DNS=9.9.9.9#dns.quad9.net DNSOverTLS=yes En nuestro caso vamos a usar los DNS de NetxDNS, para ello accedemos a nuestro panel de usuario de NextDNS y copiamos la configuración:\n[Resolve] DNS=xx.xx.xx.xx#AAAAAAAA.dns.nextdns.io DNS=xx.xx.xx.xx#AAAAAAAA.dns.nextdns.io DNS=xx.xx.xx.xx#AAAAAAAA.dns.nextdns.io DNS=xx.xx.xx.xx#AAAAAAAA.dns.nextdns.io DNSOverTLS=yes En Fedora ya debería estar el enlace simbólico de /etc/resolv.conf. Lo comprobamos y sino procedemos a crearlo:\nsudo ln -sf ../run/systemd/resolve/stub-resolv.conf /etc/resolv.conf El servicio systemd-resolved debería estar habilitado, sino lo habilitamos:\nsudo systemctl status systemd-resolved.service sudo systemctl enable systemd-resolved.service Podemos habilitar el registro de logs para detectar errores en la resolución de DNS:\nsudo resolvectl log-level debug journalctl -u systemd-resolved -f Como en nuestro sistema tenemos conviviendo systemd-resolved con NetworkManager, debemos reiniciar ambos para que todo funcione correctamente:\nsudo systemctl restart systemd-resolved.service \u0026amp;\u0026amp; sudo service NetworkManager restart Verificamos si está bien configurada la resolución de nombres:\nresolvectl status Por último, si accedemos a nuestro panel de NextDNS veremos que ya estamos trabajando con sus servidores.\nNota importante: En mi caso tuve problemas con la resolución de nombres porque tengo configuradas varias redes en mi equipo. La red que me generó problemas era la que crea TailScale, la red tailscale0.\nEn el panel de control de Tailscale tenía configurada la resolución de nombres a través de un perfil diferente de NextDNS, entonces al acceder al panel de control de NextDNS, por motivos que desconozco mi portátil Fedora hacía la resolución de nombres a través del perfil configurado en Tailscale en lugar del perfil configurado en el equipo.\nNo he descubierto porque lo hace así, la solución fue sencilla, a través de la extensión de Tailscale Status de Gnome habilito la red de Tailscale cuando es necesario para conectarme a mis NAS de forma remota.\nACTUALIZACIÓN 26/07/2025 En mi última configuración de Fedora 42 con KDE he tenido que seguir al pie de la letra la siguiente guia para que funcione.\nPor el motivo que sea el fichero /etc/systemd/resolved.conf.d/resolved.conf no se lee por systemd-resolved y no se aplica la configuración.\nSi configuramos los datos de NEXTDNS en el fichero /etc/systemd/resolved.conf, todo comenzó a funcionar a la primera.\nFuentes:\nhttps://nextdns.io/\nhttps://www.adityathebe.com/systemd-resolved-dns-over-tls/\nhttps://dev.to/archerallstars/using-dns-over-tls-on-opensuse-linux-in-4-easy-steps-enable-cloud-firewall-for-free-today-2job\nhttps://docs.quad9.net/Setup_Guides/Linux_and_BSD/Ubuntu_22.04_%28Encrypted%29/#instructions\n","permalink":"https://blog.lasnotasdenoah.com/posts/dns-over-tls/","summary":"\u003cp\u003eSegún su \u003ca href=\"https://nextdns.io/\"\u003eweb\u003c/a\u003e, NextDNS ofrece un firewall para la Internet moderna. NextDNS protege de todo tipo de amenazas a la seguridad, bloquea anuncios y rastreadores en sitios web y aplicaciones, y brinda una Internet segura y supervisada para niños, en todos los dispositivos y en todas las redes.\u003cbr\u003e\nMe parece un servicio genial por 20€ al año que ofrece mucha seguridad a la hora de navegar por internet.\u003c/p\u003e\n\u003ch2 id=\"configuración-de-dns-privado-en-fedora\"\u003eConfiguración de DNS privado en Fedora\u003c/h2\u003e\n\u003cp\u003eEn nuestro sistema Fedora, estarán conviviendo NetworkMananger con systemd-resolved, por tanto, el primer paso que debemos hacer es indicarle a NetworkManager que la resolución de DNS se va a realizar con systemd-resolved.\u003cbr\u003e\nEditamos el fichero \u003cstrong\u003e/etc/NetworkManager/conf.d/dns.conf\u003c/strong\u003e y añadimos el siguiente contenido:\u003c/p\u003e","title":"DNS Over TLS"},{"content":"Configuración WOL desde Internet en router Asus Instalación y configuración del firewallD\nEl primer paso es hacer una redirección de puertos en el router: Elegimos un puerto aleatorio externo (que sea alto) y redireccionamos al puerto 9 a la IP 192.168.1.254:\nAccedemos al router por ssh y creamos una nueva entrada en la tabla arp del router para reenviar el paquete WOL al broadcast de la red FF:FF:FF:FF:FF:FF (a todas las direcciones MAC):\narp -s 192.168.1.254 ff:ff:ff:ff:ff:ff Verificamos que se ha creado la nueva entrada:\nadmin@(none):/jffs/scripts# arp ? (192.168.1.155) at \u0026lt;incomplete\u0026gt; on br0 ? (XXX.XXX.178.1) at XX:XX:XX:XX:fc:81 [ether] on eth0 ? (192.168.1.254) at ff:ff:ff:ff:ff:ff [ether] PERM on br0 \u0026lt;---- ? (192.168.1.58) at XX:XX:XX:XX:4c:c4 [ether] on br0 ? (192.168.1.251) at XX:XX:XX:XX:5d:0a [ether] on br0 ? (192.168.1.170) at XX:XX:XX:XX:0e:f3 [ether] on br0 ? (192.168.1.40) at XX:XX:XX:XX:8a:58 [ether] on br0 Ahora simplemente es necesario configurar nuestra aplicación WOL para enviar el magic packet:\nDIRECCION MAC: La de nuestro dispositivo que deseamos levantar HOSTNAME/IP: myDDNS.asuscomm.com PUERTO: Según el ejemplo 4231 Esta configuración del router desaparecerá con el siguiente reinicio. Para dejarla permanente creamos un pequeño script que haga este trabajo en cada reinicio: Los router Asus tienen un almacenamiento permanente en /jffs Creamos un directorio dentro de /jffs llamado scrits y creamos el siguiente fichero:\ncat \u0026lt;\u0026lt;EOF \u0026gt; wan-wol.sh #!/bin/sh scriptName=\u0026#34;/jffs/scripts/\\$(basename $0)\u0026#34; myIp=\u0026#34;192.168.1.254\u0026#34; /usr/bin/logger -t \u0026#34;\\${scriptName}\u0026#34; \\$$ \u0026#34;arp -s \\${myIp} ff:ff:ff:ff:ff:ff\u0026#34; arp -s \\$myIp ff:ff:ff:ff:ff:ff /usr/bin/logger -t \u0026#34;\\${scriptName}\u0026#34; \\$$ \u0026#34;Check: \\$(arp | grep $myIp)\u0026#34; EOF Verificamos que esté bien:\ncat /jffs/scripts/wan-wol.sh Resultado correcto:\n#!/bin/sh scriptName=\u0026#34;/jffs/scripts/$(basename $0)\u0026#34; myIp=\u0026#34;192.168.1.254\u0026#34; /usr/bin/logger -t \u0026#34;${scriptName}\u0026#34; $$ \u0026#34;arp -s $myIp ff:ff:ff:ff:ff:ff\u0026#34; arp -s $myIp ff:ff:ff:ff:ff:ff /usr/bin/logger -t \u0026#34;${scriptName}\u0026#34; $$ \u0026#34;Check: $(arp | grep $myIp)\u0026#34; Los hacemos ejecutable:\nadmin@(none):/jffs/scripts# chmod a+x wan-wol.sh master@(none):/tmp/home/root# nvram show 2\u0026gt;\u0026amp;1 | grep script_usbmount script_usbmount= master@(none):/jffs/scripts# nvram set script_usbmount=\u0026#34;/jffs/scripts/wan-wol.sh\u0026#34; master@(none):/jffs/scripts# nvram commit master@(none):/jffs/scripts# nvram show 2\u0026gt;\u0026amp;1 | grep script_usbmount script_usbmount=/jffs/scripts/wan-wol.sh Después de reiniciar el router debería haberse ejecutado el script para crear la entrada en la tabla arp: Fuentes:\nhttps://andblu.blogspot.com/2016/08/configure-wol-from-internet-wan-asus.html\n","permalink":"https://blog.lasnotasdenoah.com/posts/wol-wan/","summary":"\u003ch2 id=\"configuración-wol-desde-internet-en-router-asus\"\u003eConfiguración WOL desde Internet en router Asus\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eInstalación y configuración del firewallD\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eEl primer paso es hacer una redirección de puertos en el router:\nElegimos un puerto aleatorio externo (que sea alto) y redireccionamos al puerto 9 a la IP 192.168.1.254:\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Foto 1 puertos\" loading=\"lazy\" src=\"/posts/wol-wan/redirect-puertos.png\"\u003e\u003c/p\u003e\n\u003cp\u003eAccedemos al router por ssh y creamos una nueva entrada en la tabla arp del router para reenviar el paquete WOL al broadcast de la red FF:FF:FF:FF:FF:FF (a todas las direcciones MAC):\u003c/p\u003e","title":"Wake On Lan WAN"},{"content":"Instalación y configuración de zsh con oh-my-zsh Instalación zsh Dependiendo nuestro sistema operativo, el comando será el siguiente:\n# Debian sudo apt install git zsh util-linux-user # Fedora sudo dnf install zsh git Clonamos el repositorio de oh-my-zsh\ngit clone https://github.com/ohmyzsh/ohmyzsh.git ~/.oh-my-zsh Usamos la primera plantilla para el fichero .zshrc\ncp ~/.oh-my-zsh/templates/zshrc.zsh-template ~/.zshrc Cambiamos la terminal por defecto de nuestro usuario\nsudo chsh -s /bin/zsh user_____ Instalación del tema Powerlevel10k\ngit clone --depth=1 https://github.com/romkatv/powerlevel10k.git ~/.oh-my-zsh/custom/themes/powerlevel10k echo \u0026#39;source ~/.oh-my-zsh/custom/themes/powerlevel10k/powerlevel10k.zsh-theme\u0026#39; \u0026gt;\u0026gt;~/.zshrc Modificamos el fichero .zshrc\nZSH_THEME=\u0026#34;robbyrussell\u0026#34; reemplazarlo por ZSH_THEME=\u0026#34;powerlevel10k/powerlevel10k\u0026#34; Fuentes recomendadas para el tema MesloLGS NF Enlace en mi github Copiamos las fuentes a su ubicación y configuramos Gnome terminal con la fuente recomendada\n/usr/share/fonts/truetype Reiniciar la termninal, si no arranca la configuración inicial, siguiente comando\np10k configure Instalación de los plugins\nplugins=( git sudo web-search history zsh-autosuggestions zsh-syntax-highlighting zsh-completions zsh-dircolors-solarized ) Los únicos plugin que requiere instalación manual es zsh-autosuggestions:\nzsh-autosuggestions\nzsh-completions\nsh-syntax-highlighting\nzsh-dircolors-solarized\nClonamos los repositorios y añadimos los nombres al apartado plugins del fichero .zshrc:\ngit clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting git clone https://github.com/zsh-users/zsh-completions ${ZSH_CUSTOM:=~/.oh-my-zsh/custom}/plugins/zsh-completions git clone --recursive https://github.com/joel-porquet/zsh-dircolors-solarized $ZSH_CUSTOM/plugins/zsh-dircolors-solarized Este último plugin el zsh-dircolors-solarized, despues de añadirlo a la sección plugins, es necesario ejecutar el siguiente comando para establecer los valores por defecto: setupsolarized.\nEl resto de plugins simplemente hay que añadirlo a la sección plugins de .zshrc: sudo web-search history\nFuentes:\nhttps://terminaldelinux.com/terminal/introduccion/instalacion-zsh/\nhttps://blog.linuxitos.com/post/instalar-zsh-y-tema-powerlevel10k-fedora-33\nhttps://travis.media/top-10-oh-my-zsh-plugins-for-productive-developers/#20210719-sudo\n","permalink":"https://blog.lasnotasdenoah.com/posts/zsh/","summary":"\u003ch2 id=\"instalación-y-configuración-de-zsh-con-oh-my-zsh\"\u003eInstalación y configuración de zsh con oh-my-zsh\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eInstalación zsh\u003c/strong\u003e\nDependiendo nuestro sistema operativo, el comando será el siguiente:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Debian\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo apt install git zsh util-linux-user\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Fedora\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo dnf install zsh git\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eClonamos el repositorio de oh-my-zsh\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit clone https://github.com/ohmyzsh/ohmyzsh.git ~/.oh-my-zsh\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eUsamos la primera plantilla para el fichero .zshrc\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecp ~/.oh-my-zsh/templates/zshrc.zsh-template ~/.zshrc\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eCambiamos la terminal por defecto de nuestro usuario\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo chsh -s /bin/zsh user_____\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eInstalación del tema\u003c/strong\u003e \u003ca href=\"https://github.com/romkatv/powerlevel10k\"\u003ePowerlevel10k\u003c/a\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit clone --depth\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e https://github.com/romkatv/powerlevel10k.git ~/.oh-my-zsh/custom/themes/powerlevel10k\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eecho \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;source ~/.oh-my-zsh/custom/themes/powerlevel10k/powerlevel10k.zsh-theme\u0026#39;\u003c/span\u003e \u0026gt;\u0026gt;~/.zshrc\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eModificamos el fichero .zshrc\u003c/p\u003e","title":"Zsh"}]