Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Welcome

My docs

Tux

CODEBERG (Could work with github)

SSH AUTENTIFICACION

git config --global user.name "John Doe"
git config --global user.email "johnDoe123@email.com"
ssh-keygen -t ed25519 -a 100
 [Press enter to select default]
 set pwd

cat ~/.ssh/id_ed25519.pub

Copy ssh-ed... to the end without user@algo

Add this in codeberg -> config -> add ssh

Setup user to commit

Do as the msg says but the email should be the one that has the @noreply in user settings Profile at the bottom

POSTGRESQL

Install

sudo dnf install -y postgresql postgresql-server

sudo postgresql-setup --initdb --unit postgresql
sudo systemctl start postgresql

Running psql

sudo -i -u postgres
psql

Setup postgres and User

CREATE USER mi_usuario WITH PASSWORD 'Mi Contraseña';
psql -U tu_usuario -d tu_base_de_datos

ALTER USER nombre_usuario WITH PASSWORD 'nueva_contraseña'; # Cambiar contrsaeña de un user
ALTER USER postgres WITH PASSWORD 'nueva_contraseña'; # Poner contraseña a postgres de ser necesario
DROP USER nombre_usuario; # Eliminar usuario

To Connect to the database from outside

To connect to tools like pgadmin4 or pgmodeler.

sudo -i -u postgres
psql
ALTER USER postgres WITH PASSWORD 'nueva_contraseña';
\q

Go to /var/lib/pgsql/data/pg_hba.conf. In the end of the file change the line that says

local all all peer # Original
local all all md5 # Cambio

host all all 127.0.0.1/32 ident # Original (no exactamente el 127 no va asi pero se entiende)
host all all 127.0.0.1/32 md5 # Cambio


host all all ::1/128 ident # Original
host all all ::1/128 md5 # Cambio

Then in the same data dir open postgresql.conf and add at the end this:

listen_addresses = 'localhost' # If doesnt work try '*'

With this is all ready just restart the psql service, and put the correct pwd in the tool that your gonna use.

sudo systemctl restart postgresql # In normal user

DB

CREATE DATABASE mi_base_de_datos;
GRANT ALL PRIVILEGES ON DATABASE mi_base_de_datos TO mi_usuario;
DROP DATABASE nombre_base_de_datos; # Eliminar base de datos
ALTER DATABASE nombre_base_de_datos RENAME TO nuevo_nombre; # Renombrar base de datos

Commands

\l; # Muestra todas las bases de datos que existen en tu sistema PostgreSQL.
\dt; # Muestra todas las tablas en la base de datos en la que estás trabajando actualmente.
\c nombre_de_base_de_datos; # Conectarse base de datos
\dt nombre_de_tabla; # Muestra detalles sobre la tabla específica llamada nombre_de_tabla.
\d nombre_de_tabla;
\di nombre_de_tabla; # Indices de una tabla
\q; # Salir de psql
\du; # Ver permisos de usuario

Export and Import

Exportar

pg_dump -U mi_usuario -d mi_base_de_datos -f archivo_de_respaldo.sql

Exportar solo esquema (sin datos):

pg_dump -U usuario -s -d base_de_datos -f esquema.sql

Exportar solo datos (sin esquema):

pg_dump -U usuario -a -d base_de_datos -f datos.sql

Importar

psql -U mi_usuario -d mi_base_de_datos -f archivo_de_respaldo.sql

Tables

CREATE TABLE nombre_tabla (
    columna1 tipo_dato,
    columna2 tipo_dato,
    ...
);
DROP TABLE nombre_tabla; # Borrar tabla
ALTER TABLE nombre_tabla ADD COLUMN nombre_columna tipo_dato; # Agregar una columna a una tabla:
ALTER TABLE nombre_tabla DROP COLUMN nombre_columna; # Eliminar columna de una tabla
ALTER TABLE nombre_tabla RENAME TO nuevo_nombre; # Renombrar tabla

Conf

La configuración principal se guarda en:

/var/lib/pgsql/data/postgresql.conf

Data Type

  • INTEGER o INT (-/+ 2,147,483,648)

  • BIGINT (-/+ 9,223,372,036,854,775,808)

  • SMALLINT (-/+ 32,768)

  • DECIMAL o NUMERIC (precio DECIMAL(10,2) 10 digitos en total, 2 despues del punto decimal)

  • REAL (Almacena números con precisión simple en coma flotante (menos preciso que DOUBLE PRECISION))

  • DOUBLE PRECISION (Almacena números con mayor precisión en coma flotante)

  • VARCHAR(n) (Longitud variable maxima n)

  • TEXT (Longitud variable sin limite explicito)

  • CHAR(n) (Longitud fija de n)

  • DATE (año, mes, dia)

  • TIME

  • TIMESTAMP (Fecha y hora con precisión hasta fracciones de segundo)

  • TIMESTAMPTZ (Con zona horaria)

  • INTERVAL (Periodo de timepo (diferencia entre dos fechas u horas))

  • BOOLEAN (TRUE, FALSE, NULL)

  • SERIAL (Autoincremental. Usualmente usado en ejemplo: id SERIAL PRIMARY KEY)

  • BIGSERIAL (Lo mismo pero mas grande)

  • UUID (Almacena un identificador unico universal)

  • JSON

  • JSONB (Lo mismo que json pero en formato binario)

  • XML (Datos en formato xml)

  • BYTEA (Binarios como imagenes o archivos)

  • ARRAY (Lista de valores de tipo determinado ejemplo: numeros ARRAY[INTEGER])

  • RANGE (Rango de valores)

Restricciones comunes

Formato: nombre DATA_TYPE RESTRICCION EJ: nombre VARCHAR(100) NOT NULL

  • NOT NULL
  • DEFAULT 'Valor por defecto' (estado VARCHAR(10) DEFAULT 'activo')
  • UNIQUE (Asegura que los valores de una columna sean únicos (sin duplicados))
  • CHECK (edad INT CHECK (edad >= 18))
  • CONSTRAINT [fk_usuario FOREIGN KEY (usuario_id) REFERENCES usuarios(id)] ( Define una clave foránea para relacionar tablas.)
  • PRIMARY [id SERIAL PRIMARY KEY]

Primary KEY and FOREING KEY

  • id SERIAL PRIMARY KEY,
  • estudiante_id INT REFERENCES estudiante(id),

Sha

Sha256sum Pro tips

Hacer shasum a todos los archivos dentro de un directorio que tambien esten dentro de otros subdirectorios

find path/to/directory -type f -exec sha256sum {} + > hashes.sha256
  • -type f: Significa tipo file
  • {}: Significa en nombre del archivo actual de find
  • +: Indica el final del comando que se esta ejecutando con -exec. cuando se usa find agrupa los nombres de archivo y ejecuta el comando una sola vez con una lista de archivos, lo que es mas eficiente que usar ;

Setup doas

Example in fedora:

sudo su
dnf install -y doas # pacman also works and almost every package manager should work
echo "permit persist setenv {PATH=/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin} :wheel" > /etc/doas.conf
chown -c root:root /etc/doas.conf
chmod -c 0400 /etc/doas.conf

Ssh

Simple connection between linux

Do this in the destiny ssh

sudo dnf install -y sshd # openssh-server i think
sudo systemctl start sshd # enable for always running
ip addr show # Search for the local ip
ssh user@192.168.x.x # Local ip

Copy files

scp /path/to/my/file user@192.168.x.x:/path/in/destiny/desire # username@localip:path/to

GPG

CIFRAR

Empaquetar una carpeta (no comprimir, mas rapido)

tar -cvf carpeta.tar carpeta_a_encriptar

Cifrar carpeta

gpg -c carpeta.tar

LIMPIAR

rm -rf carpeta_a_encriptar

DESCIFRAR

Descifrar el gpg

gpg carpeta.tar.gpg

Desempaquetar

tar -xvf carpeta.tar

Podman

Podmans

Create Basic Container

podman run -it --name prueba-debian --hostname debi debian
  • '-it' Para terminal interactivo
  • '--name' Nombre de container
  • '--hostname' Hostname dentro de container

Copy File From Host to Container

podman cp /ruta/en/host/mi_archivo.txt name-container:/ruta/destino/

Create User Sudoer in Debian

apt update && apt install -y sudo
useradd -m -s /bin/bash devuser
usermod -aG sudo devuser
echo "devuser ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
su - devuser

Open a Created Container

# Usuario root (por defecto)
podman exec -it nombre_contenedor bash

# Usuario específico
podman exec -it --user usuario nombre_contenedor bash

# Ejemplo con usuario creado:
podman exec -it --user devuser prueba-debian bash

Gui

x11

 podman run -it --rm \
  -v /tmp/.X11-unix:/tmp/.X11-unix:ro \
  -e DISPLAY=$DISPLAY \
  --security-opt label=type:container_runtime_t \
  --name test \
  debian \
  /bin/bash

Wayland(No probado)

podman run -it --rm \
  -v "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY:/tmp/wayland-0" \
  -e XDG_RUNTIME_DIR=/tmp \
  -e WAYLAND_DISPLAY=wayland-0 \
  --security-opt label=type:container_runtime_t \
  docker.io/library/debian:latest \
  sh -c "apt update && apt install -y weston && weston --socket=wayland-0"

¿Qué hace cada parte?

-v "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY:/tmp/wayland-0"
Monta el socket de Wayland del host en el contenedor.

-e XDG_RUNTIME_DIR=/tmp
Configura el directorio runtime dentro del contenedor.

-e WAYLAND_DISPLAY=wayland-0
Define el nombre del socket Wayland.

--security-opt label=type:container_runtime_t
Política de SELinux segura (mejor que label=disable).

sh -c "..."
Instala solo lo necesario y ejecuta Weston (compositor minimalista).

Containers

podman run -it \
  --name bllsht \
  --hostname fedora \
  -v "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY:/tmp/wayland-0" \
  -e XDG_RUNTIME_DIR=/tmp \
  -e WAYLAND_DISPLAY=wayland-0 \
  --security-opt label=type:container_runtime_t \
  fedora

EN PODMAN DESKTOP

Volumes: /run/user/1000/wayland-1 : /tmp/wayland-0

ENV:

XDG_RUNTIME_DIR : /tmp WAYLAND_DISPLAY : wayland-0 QT_QPA_PLATFORM : wayland

PARA EL DE KEEPASS AGREGAR ESTE ENV

Ollama

podman run -d -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama

Ejemplo:

podman exec -it ollama ollama run llama3

Alias

alias gemma="podman start ollama && podman exec -it ollama ollama run gemma3:4b"
alias deepseekr1="podman start ollama && podman exec -it ollama ollama run deepseek-r1:8b"
alias qwen="podman start ollama && podman exec -it ollama ollama run qwen3:8b"

Java FX (openjfx)

Dependencias

Tener instalado openjdk

# java-21-openjdk-1:21.0.7.0.6-1.fc42.x86_64
# java-21-openjdk-devel-1:21.0.7.0.6-1.fc42.x86_64
doas dnf install -y java javac 

Instalar Java-fx y configurar

doas dnf install -y openjfx

Usar estos alias

alias javac-fx="javac --module-path /usr/lib/jvm/openjfx/ --add-modules javafx.controls"
alias java-fx="java --module-path /usr/lib/jvm/openjfx/ --add-modules javafx.controls"

Cuidado!!

Revisar el --module-path con

find / -name '*openjfx*' 2>/dev/null

Desde Gluon

Descargar la version deseada luego extraer y mover el directorio a /.local/share/ Luego en .bash_profile o .zprofile

export PATH_TO_FX="$HOME/.local/share/javafx-sdk-21.0.7/lib"
alias javac-fx="javac --module-path $PATH_TO_FX --add-modules javafx.controls,javafx.fxml,javafx.media"
alias java-fx="java --module-path $PATH_TO_FX --add-modules javafx.controls,javafx.media"

Brave Wayland

Ir a /usr/share/applications/brave-browser.desktop Y cambiar todas las lineas que tengan Exec con --enable-features=UseOzonePlatform --ozone-platform=wayland. Por ejemplo:

Exec=brave-browser --enable-features=UseOzonePlatform --ozone-platform=wayland %U

Mullvad VPN Wayland

Ir a /usr/share/applications/mullvad-vpn.desktop Y cambiar todas las lineas que tengan Exec con --enable-features=UseOzonePlatform,WaylandWindowDecorations --ozone-platform=wayland. Por ejemplo:

# Disable gpu opcional
Exec="/opt/Mullvad VPN/mullvad-vpn" --enable-features=UseOzonePlatform,WaylandWindowDecorations --ozone-platform=wayland %U

VSCodium Wayland

Ir a /usr/share/applications/codium.desktop Y cambiar todas las lineas que tengan Exec con --enable-features=UseOzonePlatform,WaylandWindowDecorations --ozone-platform=wayland. Por ejemplo:

Exec=/usr/share/codium/codium --enable-features=UseOzonePlatform,WaylandWindowDecorations --ozone-platform=wayland --new-window %F

Git

Basic

git clone <repositorio>
git status # Mostrara si hay cambios
git add <Archvios/Directorios>
git commit -m "Mensaje de commit"
git push . # Pushea el directorio actual
git reset --soft HEAD~1 # Eliminar ultimo commit

Branch

# 1. Crear y cambiar a una rama nueva  
git checkout -b [nombre-rama]  
# Ej: git checkout -b feature/login → Crea la rama "feature/login" y se mueve a ella.*

# 2. Cambiar a una rama existente  
git checkout [nombre-rama]  
# Ej: git checkout main → Te mueve a la rama main.*

# 3. Subir una rama nueva al repositorio remoto (GitHub) SOLO LA PRIMERA VEZ DESPUES git push normal
git push -u origin [nombre-rama]  
# El -u vincula la rama local con la remota para futuros push.*

# 4. Listar ramas locales y remotas  
git branch -a  
# Muestra todas las ramas (locales en verde, remotas en rojo).*

# 5. Sincronizar rama actual con cambios remotos  
git pull  
# Descarga cambios del repositorio remoto y los fusiona con tu rama local.*

# 6. Fusionar una rama con la rama actual  
git merge [nombre-rama]  
# Ej: Si estás en main → git merge feature/login une feature/login con main.*

# 7. Eliminar rama local  
git branch -d [nombre-rama]  
# -d solo borra si está fusionada; usa -D para forzar eliminación.*

# 8. Eliminar rama remota  
git push origin --delete [nombre-rama]  
# Ej: git push origin --delete feature/login → Borra la rama en GitHub.*

# 9. Ver estado actual (cambios, rama, conflictos)  
git status  

# 10. Ver historial de commits  
git log --oneline  
# Muestra commits resumidos en una línea.*

# 11. Tag
git tag name-tag
git push origin name-tag

Gnu Stow

sudo dnf in stow

Funciona Asi:

Normal Home:

~ | |-> .zshrc -> .config -> alacritty -> alacritty.toml -> *

Luego en Stow:

stow_dir | |-> zsh | -> .zshrc | -> alacritty -> .config -> alacritty -> alacritty.toml -> *

Luego para hacer los enlaces simbolicos

stow zsh alacritty

Rust Cheatsheet para Principiantes (desde C++/Java)

Este cheatsheet se centra en los conceptos fundamentales que necesitas para empezar a ser productivo en Rust, basándose en la tabla que proporcionaste.


1. Rust Básico

Variables y Mutabilidad

Rust prioriza la inmutabilidad por defecto. Usa let para declarar variables. Para hacerlas mutables, añade mut. Los tipos se infieren a menudo, pero puedes especificarlos.

  • Inmutable:
    #![allow(unused)]
    fn main() {
    let x: i32 = 5; // x es inmutable
    let y = 10;    // Tipo i32 inferido, y es inmutable
    // x = 6; // Error! No se puede reasignar una variable inmutable
    }
  • Mutable:
    #![allow(unused)]
    fn main() {
    let mut z = 15; // z es mutable
    z = 20;         // ¡Ok!
    println!("z es: {}", z);
    }
  • Constantes (siempre inmutables, tipo debe ser anotado, evaluadas en tiempo de compilación):
    #![allow(unused)]
    fn main() {
    const MAX_POINTS: u32 = 100_000;
    }
  • Shadowing (puedes declarar una nueva variable con el mismo nombre, incluso cambiando el tipo):
    #![allow(unused)]
    fn main() {
    let spaces = "   ";
    let spaces = spaces.len(); // Ahora 'spaces' es un número (3)
    }

Tipos de Datos Comunes

  • Enteros: i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize (tamaño de puntero).
  • Flotantes: f32, f64 (por defecto f64).
  • Booleanos: bool (true, false).
  • Caracteres: char (Unicode, 4 bytes).
  • Tuplas: Colección fija de diferentes tipos.
    #![allow(unused)]
    fn main() {
    let tup: (i32, f64, u8) = (500, 6.4, 1);
    let (x, y, z) = tup; // Destructuración
    println!("El valor de y es: {}", y); // 6.4
    println!("El primer valor es: {}", tup.0); // Acceso por índice
    }
  • Arrays: Colección fija del mismo tipo, en el stack.
    #![allow(unused)]
    fn main() {
    let a = [1, 2, 3, 4, 5];
    let first = a[0];
    // let b: [i32; 5] = [1, 2, 3, 4, 5]; // Con anotación de tipo y tamaño
    // a[0] = 10; // Error si 'a' no es mutable
    }
  • Strings:
    • &str (string slice): Inmutable, referencia a datos de string (usualmente en el binario o en el heap).
      #![allow(unused)]
      fn main() {
      let s_literal = "hola"; // &str
      }
    • String: Mutable, buffer de string en el heap. Similar a std::string en C++ o String en Java.
      #![allow(unused)]
      fn main() {
      let mut s_heap = String::from("hola");
      s_heap.push_str(", mundo!");
      println!("{}", s_heap); // hola, mundo!
      }

Funciones

Declaradas con fn. Los tipos de los parámetros y el tipo de retorno (si lo hay) deben ser especificados. La última expresión en una función es su valor de retorno implícito si no se usa return.

fn saludar(nombre: &str) {
    println!("Hola, {}!", nombre);
}

fn sumar(a: i32, b: i32) -> i32 {
    a + b // No se necesita ';' ni 'return' si es la última expresión
}

fn main() {
    saludar("Mundo");
    let resultado = sumar(5, 3);
    println!("5 + 3 = {}", resultado);
}

Control de Flujo

  • if/else if/else: Similar a C++/Java. Las condiciones deben ser bool. if es una expresión.
    #![allow(unused)]
    fn main() {
    let numero = 6;
    if numero % 4 == 0 {
        println!("El número es divisible por 4");
    } else if numero % 3 == 0 {
        println!("El número es divisible por 3");
    } else {
        println!("El número no es divisible ni por 4 ni por 3");
    }
    
    let condicion = true;
    let valor = if condicion { 5 } else { 6 }; // 'if' como expresión
    println!("El valor es: {}", valor);
    }
  • Bucles:
    • loop: Bucle infinito (usa break para salir).
      #![allow(unused)]
      fn main() {
      let mut contador = 0;
      let resultado_loop = loop {
          contador += 1;
          if contador == 10 {
              break contador * 2; // 'break' puede devolver un valor
          }
      };
      println!("El resultado del loop es {}", resultado_loop); // 20
      }
    • while: Bucle condicional.
      #![allow(unused)]
      fn main() {
      let mut numero = 3;
      while numero != 0 {
          println!("{}!", numero);
          numero -= 1;
      }
      println!("¡DESPEGUE!");
      }
    • for: Para iterar sobre colecciones (más común y seguro).
      #![allow(unused)]
      fn main() {
      let a = [10, 20, 30, 40, 50];
      for elemento in a.iter() { // .iter() crea un iterador sobre referencias
          println!("El valor es: {}", elemento);
      }
      
      for numero in (1..4).rev() { // Rango (1, 2, 3) en reversa
          println!("{}!", numero);
      }
      }

Módulos

Para organizar el código.

// En lib.rs o main.rs
mod mi_modulo {
    pub fn funcion_publica() {
        println!("Llamada a funcion_publica()");
        funcion_privada();
    }

    fn funcion_privada() {
        println!("Llamada a funcion_privada()");
    }

    pub mod sub_modulo {
        pub fn otra_funcion() {
            println!("Llamada a otra_funcion() en sub_modulo");
        }
    }
}

fn main() {
    // Ruta completa
    crate::mi_modulo::funcion_publica();
    // Usando 'use'
    use crate::mi_modulo::sub_modulo::otra_funcion;
    otra_funcion();

    // Si 'mi_modulo' está en otro archivo llamado 'mi_modulo.rs'
    // mod mi_modulo; // En main.rs o lib.rs para declarar el módulo
    // mi_modulo::funcion_publica();
}
  • crate: Raíz del crate (paquete).
  • pub: Hace un ítem público. Por defecto, todo es privado.
  • use: Importa ítems a un scope.

2. Gestión de Paquetes con Cargo

Cargo es el gestor de paquetes y sistema de construcción de Rust.

  • Crear un nuevo proyecto:
    cargo new mi_proyecto      # Crea una aplicación binaria
    cargo new --lib mi_libreria # Crea una librería
    
  • Estructura típica del proyecto:
    mi_proyecto/
    ├── Cargo.toml  # Manifiesto del paquete (metadatos, dependencias)
    ├── src/
    │   └── main.rs   # Código fuente principal para binarios
    │   # O lib.rs para librerías
    
  • Comandos comunes de Cargo:
    • cargo build: Compila el proyecto (en target/debug/).
    • cargo build --release: Compila con optimizaciones (en target/release/).
    • cargo run: Compila y ejecuta el binario.
    • cargo test: Ejecuta las pruebas.
    • cargo check: Comprueba el código sin generar un ejecutable (más rápido).
    • cargo doc --open: Genera y abre la documentación.
    • cargo add <crate_name>: Añade una dependencia a Cargo.toml.
  • Cargo.toml (ejemplo básico):
    [package]
    name = "mi_proyecto"
    version = "0.1.0"
    edition = "2021" # Edición de Rust
    
    [dependencies]
    # rand = "0.8.5" # Ejemplo de dependencia de crates.io
    # ratatui = { version = "0.26.0", features = ["crossterm"] }
    # crossterm = "0.27.0"
    

3. Propiedad y Préstamos (Ownership & Borrowing)

Este es el concepto más distintivo de Rust. Asegura la seguridad de memoria sin un recolector de basura.

Reglas de Propiedad (Ownership)

  1. Cada valor en Rust tiene una variable que es su dueña (owner).
  2. Solo puede haber un dueño a la vez.
  3. Cuando el dueño sale del ámbito (scope), el valor se libera (dropped).
#![allow(unused)]
fn main() {
{
    let s1 = String::from("hola"); // s1 es dueña de "hola"

    // let s2 = s1; // ¡MOVIMIENTO! s1 ya no es válida.
                  // Similar a std::unique_ptr en C++ (sin copia implícita)
                  // Para tipos simples como i32, se copian (implementan el trait 'Copy')

    let s2 = s1.clone(); // Copia profunda (heap data copiado)
    println!("s1 = {}, s2 = {}", s1, s2); // Ambas válidas
} // s1 (si no fue movida) y s2 salen del scope, la memoria se libera.
}

Préstamos y Referencias (Borrowing & References)

Permiten acceder a datos sin tomar posesión.

  • Referencias Inmutables (&T):
    • Puedes tener múltiples referencias inmutables a un dato.
    • No puedes modificar el dato a través de ellas.
    #![allow(unused)]
    fn main() {
    let s1 = String::from("hola");
    let len = calcular_longitud(&s1); // Se presta s1 inmutablemente
    println!("La longitud de '{}' es {}.", s1, len);
    
    fn calcular_longitud(s: &String) -> usize { // s es una referencia a un String
        s.len()
    } // s sale del scope, pero no libera nada porque no es dueña
    }
  • Referencias Mutables (&mut T):
    • Solo puedes tener una referencia mutable a un dato en un scope particular.
    • Esto previene data races en tiempo de compilación.
    • No puedes tener referencias inmutables si existe una mutable.
    #![allow(unused)]
    fn main() {
    let mut s = String::from("hola");
    cambiar(&mut s);
    println!("{}", s); // "hola, mundo"
    
    fn cambiar(algun_string: &mut String) {
        algun_string.push_str(", mundo");
    }
    }
    Restricción importante:
    #![allow(unused)]
    fn main() {
    let mut s = String::from("hello");
    let r1 = &s; // Referencia inmutable, OK
    let r2 = &s; // Otra referencia inmutable, OK
    // let r3 = &mut s; // ¡ERROR! No puedes tener una referencia mutable mientras existan inmutables
    // println!("{}, {}, and {}", r1, r2, r3);
    
    let mut s_mut = String::from("hello");
    let r_mut1 = &mut s_mut;
    // let r_mut2 = &mut s_mut; // ¡ERROR! Solo una referencia mutable a la vez
    // println!("{}, {}", r_mut1, r_mut2);
    }

Lifetimes (Tiempos de Vida) 'a

Aseguran que las referencias sean siempre válidas. A menudo son inferidos por el compilador. Los necesitas explícitamente cuando las relaciones de lifetimes entre referencias no son obvias para el compilador, especialmente en firmas de funciones y structs que contienen referencias.

  • Objetivo: Evitar dangling references (referencias que apuntan a memoria que ha sido liberada).
  • Ejemplo donde se necesitan:
    // Devuelve una referencia, el compilador necesita saber si vive tanto como 'x' o 'y'
    fn el_mas_largo<'a>(x: &'a str, y: &'a str) -> &'a str {
        if x.len() > y.len() {
            x
        } else {
            y
        }
    }
    
    fn main() {
        let string1 = String::from("cadena larga es larga");
        {
            let string2 = String::from("xyz");
            let resultado = el_mas_largo(string1.as_str(), string2.as_str());
            println!("La cadena más larga es {}", resultado);
        } // string2 se libera aquí. Si resultado apuntara a string2, sería un dangling reference.
          // Pero el lifetime 'a' del resultado está atado al más corto de string1 y string2.
    }
    La idea es que el dato referenciado por 'a debe vivir al menos tanto como la referencia anotada con 'a.

4. POO en Rust (Estilo Rust)

Rust no tiene "clases" como Java/C++, pero ofrece estructuras (structs), enumeraciones (enums), y comportamientos (traits) para lograr encapsulación y polimorfismo.

struct (Estructuras)

Agrupan datos relacionados. Similar a struct en C o los campos de una clase en Java/C++.

struct Usuario {
    activo: bool,
    nombre_usuario: String,
    email: String,
    contador_sesion: u64,
}

fn main() {
    let mut usuario1 = Usuario {
        email: String::from("alguien@ejemplo.com"),
        nombre_usuario: String::from("alguien123"),
        activo: true,
        contador_sesion: 1,
    };

    usuario1.email = String::from("otroemail@ejemplo.com");
    println!("Email: {}", usuario1.email);

    let usuario2 = construir_usuario(
        String::from("usuario2@ejemplo.com"),
        String::from("usuario2")
    );
}

fn construir_usuario(email: String, nombre_usuario: String) -> Usuario {
    Usuario {
        email, // Abreviatura si el nombre del parámetro y el campo son iguales
        nombre_usuario,
        activo: true,
        contador_sesion: 1,
    }
}

// Structs tupla (sin nombres de campo)
struct Color(i32, i32, i32);
struct Punto(i32, i32, i32);

let negro = Color(0, 0, 0);
let origen = Punto(0, 0, 0);
println!("Primer valor de negro: {}", negro.0);

impl (Implementación de Métodos)

Define métodos para structs y enums.

struct Rectangulo {
    ancho: u32,
    alto: u32,
}

// Bloque de implementación para Rectangulo
impl Rectangulo {
    // Método (toma &self, &mut self, o self)
    fn area(&self) -> u32 { // &self es una referencia inmutable a la instancia
        self.ancho * self.alto
    }

    fn puede_contener(&self, otro: &Rectangulo) -> bool {
        self.ancho > otro.ancho && self.alto > otro.alto
    }

    // Función asociada (no toma self), a menudo usada como constructor
    // Similar a un método estático en Java/C++
    fn cuadrado(tamano: u32) -> Self { // Self es un alias para Rectangulo
        Self { ancho: tamano, alto: tamano }
    }
}

fn main() {
    let rect1 = Rectangulo { ancho: 30, alto: 50 };
    let rect2 = Rectangulo { ancho: 10, alto: 40 };
    let rect_cuadrado = Rectangulo::cuadrado(25); // Llamada a función asociada

    println!("El área del rectángulo es {} pixeles cuadrados.", rect1.area());
    println!("¿Puede rect1 contener a rect2? {}", rect1.puede_contener(&rect2));
    println!("Área del cuadrado: {}", rect_cuadrado.area());
}

enum (Enumeraciones)

Tipos que pueden ser uno de varios valores posibles (variantes). Las variantes pueden tener datos asociados. Son mucho más potentes que los enums de C/C++ y Java (más cercanos a uniones discriminadas o tipos algebraicos de datos).

enum Mensaje {
    Salir,                       // Sin datos asociados
    Mover { x: i32, y: i32 },    // Con campos nombrados (como un struct)
    Escribir(String),            // Con un String
    CambiarColor(i32, i32, i32), // Con una tupla de datos
}

impl Mensaje {
    fn procesar(&self) {
        match self {
            Mensaje::Salir => println!("Saliendo..."),
            Mensaje::Mover { x, y } => {
                println!("Moviendo a x: {}, y: {}", x, y);
            }
            Mensaje::Escribir(texto) => {
                println!("Mensaje de texto: {}", texto);
            }
            Mensaje::CambiarColor(r, g, b) => {
                println!("Cambiando color a R:{}, G:{}, B:{}", r, g, b);
            }
        }
    }
}

fn main() {
    let msg1 = Mensaje::Mover { x: 10, y: 20 };
    let msg2 = Mensaje::Escribir(String::from("Hola enum"));
    msg1.procesar();
    msg2.procesar();
}

trait (Rasgos)

Definen un conjunto de métodos que un tipo puede implementar. Similar a interfaces en Java o clases base puramente virtuales en C++. Permiten el polimorfismo.

// Definición de un trait
pub trait Resumible {
    fn resumir_autor(&self) -> String; // Método que debe ser implementado

    fn resumir(&self) -> String { // Método con implementación por defecto
        format!("(Leer más de {}...)", self.resumir_autor())
    }
}

pub struct Noticia {
    pub titular: String,
    pub autor: String,
    pub contenido: String,
}

// Implementación del trait Resumible para Noticia
impl Resumible for Noticia {
    fn resumir_autor(&self) -> String {
        format!("@{}", self.autor)
    }
    // Podríamos sobreescribir resumir() aquí si quisiéramos
}

pub struct Tweet {
    pub nombre_usuario: String,
    pub contenido: String,
    pub respuesta: bool,
    pub retweet: bool,
}

impl Resumible for Tweet {
    fn resumir_autor(&self) -> String {
        format!("@{}", self.nombre_usuario)
    }

    fn resumir(&self) -> String {
        format!("{}: {}", self.nombre_usuario, self.contenido)
    }
}

// Polimorfismo usando traits (parámetros genéricos con trait bounds)
pub fn notificar<T: Resumible>(item: &T) {
    println!("¡Noticia de última hora! {}", item.resumir());
}

// Polimorfismo usando trait objects (dinámico)
pub fn notificar_dinamico(item: &dyn Resumible) {
    println!("¡Noticia dinámica! {}", item.resumir());
}

fn main() {
    let tweet = Tweet {
        nombre_usuario: String::from("caballo_ebooks"),
        contenido: String::from("por supuesto, como ustedes saben, la gente"),
        respuesta: false,
        retweet: false,
    };

    let articulo = Noticia {
        titular: String::from("¡Los pingüinos ganan la Stanley Cup!"),
        autor: String::from("Iceburgh"),
        contenido: String::from("El equipo de hockey de Pittsburgh, los Pingüinos..."),
    };

    println!("1 nuevo tweet: {}", tweet.resumir());
    println!("Nuevo artículo disponible: {}", articulo.resumir());

    notificar(&tweet);
    notificar_dinamico(&articulo);
}

5. Tratamiento de Errores

Rust no tiene excepciones como Java o C++. En su lugar, usa tipos para representar posibles errores.

Option<T>

Para valores que pueden ser opcionales (o estar ausentes). Similar a Optional<T> en Java 8+.

  • Variantes: Some(T) (el valor está presente) o None (el valor está ausente).
fn encontrar_caracter(texto: &str, caracter_buscado: char) -> Option<usize> {
    for (indice, caracter_actual) in texto.char_indices() {
        if caracter_actual == caracter_buscado {
            return Some(indice); // Valor encontrado
        }
    }
    None // Valor no encontrado
}

fn main() {
    let texto = "hola mundo";
    match encontrar_caracter(texto, 'm') {
        Some(indice) => println!("'m' encontrada en el índice: {}", indice),
        None => println!("'m' no encontrada."),
    }

    match encontrar_caracter(texto, 'z') {
        Some(indice) => println!("'z' encontrada en el índice: {}", indice),
        None => println!("'z' no encontrada."),
    }

    // 'if let' es una forma concisa de manejar una variante de Option/Result
    if let Some(indice) = encontrar_caracter(texto, 'o') {
        println!("'o' encontrada con if let en: {}", indice);
    }

    // Métodos útiles de Option:
    // unwrap(): Devuelve el valor en Some(T) o hace panic! si es None (¡usar con cuidado!)
    // unwrap_or(default_value): Devuelve el valor o un valor por defecto.
    // unwrap_or_else(closure): Devuelve el valor o el resultado de una clausura.
    // map(closure): Aplica una función al valor dentro de Some.
    // and_then(closure): Encadena operaciones que devuelven Option.
    let quizas_numero: Option<i32> = Some(5);
    let _numero_mas_uno = quizas_numero.map(|n| n + 1); // Some(6)
    let _otro_numero = None::<i32>.unwrap_or(0); // 0
}

Result<T, E>

Para operaciones que pueden fallar (éxito o error). T es el tipo del valor en caso de éxito, E es el tipo del error.

  • Variantes: Ok(T) (operación exitosa) o Err(E) (operación fallida).
use std::fs::File;
use std::io::{self, Read};

// Función que devuelve un Result
fn leer_archivo(nombre_archivo: &str) -> Result<String, io::Error> {
    let mut f = match File::open(nombre_archivo) {
        Ok(archivo) => archivo,
        Err(e) => return Err(e), // Propaga el error temprano
    };

    let mut s = String::new();
    match f.read_to_string(&mut s) {
        Ok(_) => Ok(s),
        Err(e) => Err(e),
    }
}

// Usando el operador '?' para propagar errores (más idiomático)
// '?' solo puede usarse en funciones que devuelven Result o Option.
fn leer_archivo_con_interrogante(nombre_archivo: &str) -> Result<String, io::Error> {
    let mut f = File::open(nombre_archivo)?; // Si es Err, retorna Err(e) desde esta función
    let mut s = String::new();
    f.read_to_string(&mut s)?; // Si es Err, retorna Err(e)
    Ok(s) // Si todo va bien, retorna Ok(s)

    // Incluso más corto:
    // std::fs::read_to_string(nombre_archivo)
}

fn main() {
    match leer_archivo_con_interrogante("hola.txt") {
        Ok(contenido) => println!("Contenido del archivo: {}", contenido),
        Err(error) => println!("Error al leer el archivo: {:?}", error),
    }

    // expect(): Similar a unwrap(), pero con un mensaje de panic personalizado.
    // let _contenido = File::open("no_existe.txt").expect("Falló al abrir no_existe.txt");
}

El operador ? desenvuelve Ok(T) a T o retorna Err(E) de la función actual.


6. Asincronía (Básico) (Opcional, según tu proyecto TUI)

Si tu TUI necesita realizar operaciones de I/O (red, disco) sin bloquear el hilo principal, necesitarás asincronía.

  • async fn: Define una función asíncrona. Devuelve un Future.
  • .await: Espera a que un Future se complete sin bloquear el hilo. Solo se puede usar dentro de una async fn.
// Este es un ejemplo conceptual. Necesitarías un runtime como tokio o async-std.
// Añade a Cargo.toml:
// tokio = { version = "1", features = ["full"] }

/*
async fn obtener_datos_web(url: &str) -> Result<String, reqwest::Error> {
    // reqwest es una librería popular para HTTP, también asíncrona
    let respuesta = reqwest::get(url).await?;
    let cuerpo = respuesta.text().await?;
    Ok(cuerpo)
}

async fn tarea_larga() {
    println!("Iniciando tarea larga...");
    // Simula trabajo, como una llamada de red
    tokio::time::sleep(std::time::Duration::from_secs(2)).await;
    println!("Tarea larga completada.");
}

// En tu función main (o una función marcada con el macro del runtime)
#[tokio::main] // Si usas tokio
async fn main() {
    println!("Iniciando programa asíncrono.");

    let handle1 = tokio::spawn(async { // Ejecuta en una nueva "tarea" (green thread)
        tarea_larga().await;
    });

    let handle2 = tokio::spawn(async {
        match obtener_datos_web("https://www.rust-lang.org").await {
            Ok(pagina) => println!("Página obtenida (primeros 100 chars): {:.100}", pagina),
            Err(e) => eprintln!("Error al obtener la página: {}", e),
        }
    });

    println!("Tareas iniciadas, esperando...");
    // Espera a que todas las tareas spawneadas terminen
    let _ = tokio::try_join!(handle1, handle2);
    println!("Programa asíncrono finalizado.");
}
*/
  • Runtimes asíncronos (tokio, async-std): Proveen el ejecutor para los Futures, manejo de I/O, timers, etc.
    • tokio es muy popular, especialmente para networking.
    • async-std busca ser un análogo asíncrono de la librería estándar.

7. Ratatui + Crossterm (Específico para TUI)

Estas bibliotecas te ayudarán a construir tu Interfaz de Usuario en Terminal (TUI).

  • Crossterm: Proporciona funcionalidades de bajo nivel para interactuar con la terminal (manipulación del cursor, colores, entrada de teclado/ratón, modo raw). Ratatui lo usa como backend.
  • Ratatui: Es una biblioteca para construir TUIs, inspirada en React. Se basa en dibujar "widgets" en un "buffer" y luego mostrar ese buffer en la terminal.
    • Ciclo principal (conceptual):
      1. Inicializar la terminal (usando Crossterm).
      2. Entrar en un bucle: a. Leer eventos de entrada (teclado, ratón) de forma no bloqueante (Crossterm). b. Actualizar el estado de tu aplicación según la entrada. c. Dibujar la UI en un Frame de Ratatui: i. Definir Layouts para dividir el área de la terminal. ii. Renderizar Widgets en las áreas del layout. d. Si el usuario quiere salir, romper el bucle.
      3. Restaurar la terminal.

Conceptos Clave de Ratatui:

  • Terminal: El objeto principal para interactuar con la terminal.
  • Frame: Se pasa a tu función de dibujado en cada iteración, es donde dibujas.
  • Layout: Define cómo dividir un área rectangular en sub-áreas.
    • Direction: Horizontal o Vertical.
    • Constraint: Define el tamaño de cada celda del layout (Percentage, Length, Min, Max).
    #![allow(unused)]
    fn main() {
    // Ejemplo de Layout
    // use ratatui::layout::{Layout, Direction, Constraint, Rect};
    // fn ui(frame: &mut Frame) {
    //     let chunks = Layout::default()
    //         .direction(Direction::Vertical)
    //         .margin(1)
    //         .constraints(
    //             [
    //                 Constraint::Percentage(10), // 10% para el título
    //                 Constraint::Percentage(80), // 80% para el contenido
    //                 Constraint::Percentage(10), // 10% para el pie
    //             ]
    //             .as_ref(),
    //         )
    //         .split(frame.size()); // frame.size() es el Rect de toda la terminal
    //     // chunks[0] es el Rect para el título, chunks[1] para contenido, etc.
    // }
    }
  • Widget: Componentes visuales. Son structs que implementan el trait Widget.
    • Block: Un contenedor con bordes opcionales y título. A menudo envuelve a otros widgets.
    • Paragraph: Para mostrar texto, con opciones de alineación y autoajuste.
    • List: Para mostrar una lista de ítems.
    • Tabs: Para crear una interfaz con pestañas.
    • Muchos más: Table, Chart, Gauge, Sparkline, etc.
    #![allow(unused)]
    fn main() {
    // Ejemplo de Widget (dentro de la función ui)
    // use ratatui::widgets::{Block, Borders, Paragraph};
    // use ratatui::text::Text;
    //
    // // En chunks[0] (definido arriba)
    // let titulo = Paragraph::new(Text::styled("Mi TUI con Ratatui", Style::default().fg(Color::Yellow)))
    //     .block(Block::default().borders(Borders::ALL))
    //     .alignment(Alignment::Center);
    // frame.render_widget(titulo, chunks[0]);
    //
    // // En chunks[1]
    // let contenido_texto = "Este es el contenido principal...\nPresiona 'q' para salir.";
    // let parrafo_contenido = Paragraph::new(contenido_texto)
    //     .block(Block::default().title("Contenido").borders(Borders::ALL));
    // frame.render_widget(parrafo_contenido, chunks[1]);
    }
  • Style: Para definir colores (foreground, background) y modificadores (bold, italic).
  • Eventos (con Crossterm):
    #![allow(unused)]
    fn main() {
    // use crossterm::event::{self, Event as CrosstermEvent, KeyCode, KeyEvent};
    // loop {
    //     // Esperar un evento por un tiempo máximo (para no bloquear indefinidamente)
    //     if crossterm::event::poll(std::time::Duration::from_millis(50))? {
    //         if let CrosstermEvent::Key(key_event) = event::read()? {
    //             match key_event.code {
    //                 KeyCode::Char('q') => break, // Salir del bucle
    //                 KeyCode::Up => { /* mover selección hacia arriba */ },
    //                 KeyCode::Down => { /* mover selección hacia abajo */ },
    //                 // ... otros KeyCode
    //                 _ => {}
    //             }
    //         } else if let CrosstermEvent::Mouse(mouse_event) = event::read()? {
    //             // Procesar eventos de ratón (posición, clics)
    //             // mouse_event.kind, mouse_event.column, mouse_event.row
    //         }
    //     }
    //     // Lógica de la app y dibujar UI aquí
    //     // terminal.draw(|f| ui(f, &app_state))?;
    // }
    }

Configuración inicial para Ratatui + Crossterm:

  1. Añade a Cargo.toml:
    [dependencies]
    ratatui = { version = "0.27.0", features = ["crossterm"] } # O la versión más reciente
    crossterm = "0.27.0"                                  # O la versión más reciente
    
  2. Código básico de inicialización/restauración:
    // En tu main.rs
    /*
    use std::io;
    use ratatui::Terminal;
    use ratatui::backend::CrosstermBackend;
    use crossterm::{terminal::{enable_raw_mode, disable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, execute};
    
    fn main() -> Result<(), Box<dyn std::error::Error>> {
        // Setup terminal
        enable_raw_mode()?; // Entrar en modo raw para control total de entrada
        let mut stdout = io::stdout();
        execute!(stdout, EnterAlternateScreen)?; // Cambiar a una pantalla alternativa
        let backend = CrosstermBackend::new(stdout);
        let mut terminal = Terminal::new(backend)?;
    
        // Bucle principal de la aplicación aquí...
        // loop {
        //    terminal.draw(|f| {
        //        // ui(f, &app_state); // Tu función de dibujado
        //    })?;
        //    // Manejo de eventos aquí...
        //    // if quit { break; }
        // }
    
        // Restaurar terminal
        disable_raw_mode()?;
        execute!(terminal.backend_mut(), LeaveAlternateScreen)?;
        // terminal.show_cursor()?; // Si lo ocultaste
    
        Ok(())
    }
    */

Eww

sudo dnf in gtk3-devel gtk-layer-shell-devel libdbusmenu-gtk3-devel pango-devel gdk-pixbuf2-devel cairo-devel glib2-devel
cargo install --locked --no-default-features --features=wayland --git https://github.com/elkowar/eww eww
sudo dnf rm gtk3-devel gtk-layer-shell-devel libdbusmenu-gtk3-devel pango-devel gdk-pixbuf2-devel cairo-devel glib2-devel

Ironbar

Me rendi antes de terminarla

Instalacion en fedora

dnf in gtk3-devel gtk-layer-shell-devel openssl-devel libdbusmenu-gtk3-devel pulseaudio-libs-devel libinput-devel luajit-devel lua-lgi libevdev-devel
cargo install --locked --git https://github.com/jakestanger/ironbar.git ironbar
dnf rm gtk3-devel gtk-layer-shell-devel openssl-devel libdbusmenu-gtk3-devel pulseaudio-libs-devel libinput-devel luajit-devel lua-lgi libevdev-devel

Mdbook


Crates.io

Install

cargo install mdbook

TLDR

  Create online books by writing Markdown files.
  More information: <https://rust-lang.github.io/mdBook/>.

  Create an mdbook project in the current directory:

      mdbook init

  Create an mdbook project in a specific directory:

      mdbook init path/to/directory

  Clean the directory with the generated book:

      mdbook clean

  Serve a book at <http://localhost:3000>, auto build when file changes:

      mdbook serve

  Watch a set of Markdown files and automatically build when a file is changed:

      mdbook watch

Pages


En codeberg con mdbook.

git checkout --orphan pages
git rm -rf .  # Borra todos los archivos del tracking
git commit --allow-empty -m "Initial commit for pages branch"
git push origin pages
git checkout main # Vuelve a tu rama principal

git worktree add ../repo-pages pages

Modificar scripts deploy.sh y clean.sh.

Dd


sudo dd if=tails.img of=device bs=16M oflag=direct status=progress
sudo dd if=~/Descargas/kali-linux.iso of=/dev/sdb bs=4M status=progress oflag=sync

Rust Tools


First of all, install rustup

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup update
rustup component add rust-analyzer

Security

cargo install cargo-audit
cargo install cargo-update
cargo install cargo-download

How to check with cargo audit

cargo download pkg | save pkg.gz # > in bash
tar -xvf pkg.gz
cd pkg*
cargo audit

How to use cargo-update

cargo install-update -l

Install Packages

# Find dependencies if necesary
cargo install paquete
cargo install --locked paquete

Luks

Creando una partición:

sudo fdisk /dev/sdb
n
# Enter a todo
w

Encriptando la partición creada:

sudo cryptsetup luksFormat /dev/sdb1
sudo cryptsetup open /dev/sdb1 a
sudo mkfs.ext4 /dev/mapper/a
sudo cryptsetup close a
sync 

Monero Node


Store Monero Node on an external drive.

  • First, do the same as in the LUKS guide for the drive.
  • Assuming that /dev/sdb is the drive

Tux

If you don't use sudo, just change it to sudo

Preparing the Drive

sudo fdisk /dev/sdb
n
# Enter
# Enter
# Enter
# Enter
w

Optional encryption

sudo cryptsetup luksFormat /dev/sdb1
sudo cryptsetup open /dev/sdb1 a
sudo mkfs.ext4 /dev/mapper/a
sudo cryptsetup close a
sync 

Downloading monerod

Install monerod in your distro of choice

# In Archlinux
sudo pacman -S monero
# In Debian 
sudo apt install monero
# With Homebrew
brew install monero

or

In other distros install wget and ->

wget https://downloads.getmonero.org/gui/linux64
# Or if you prefer only cli
wget https://downloads.getmonero.org/cli/linux64
tar -xvf linux64
# ...
sudo cp monerod /usr/local/bin/
sudo cp monero-wallet-cli /usr/local/bin/
# Or just
sudo mv monero* /usr/local/bin/

or

Recommended to create a user without sudo for only monero

Setting up Monero

sudo useradd --system --shell /usr/sbin/nologin --home-dir /var/lib/monero monero

sudo mkdir -p /mnt/monero-node/
sudo mount /dev/xxx /mnt/monero-node
sudo mkdir -p /mnt/monero-node/.bitmonero   # Your blockchain storage location
sudo mkdir -p /var/log/monero               # Log directory
sudo mkdir -p /etc/monero                   # Configuration directory
sudo mkdir -p /run/monero
sudo chown monero:monero /run/monero

# Set ownership for blockchain directory
sudo chown -R monero:monero /mnt/monero-node/.bitmonero
sudo chmod 750 /mnt/monero-node/.bitmonero

# Set ownership for log directory
sudo chown -R monero:monero /var/log/monero
sudo chmod 750 /var/log/monero

# Create the monerod configuration file
sudo vim /etc/monero/monerod.conf

sudo chown root:monero /etc/monero/monerod.conf
sudo chmod 640 /etc/monero/monerod.conf

Firewall

sudo firewall-cmd --permanent --add-port=18089/tcp --zone=drop
sudo firewall-cmd --reload

Run Monerod

There are 2 alternatives; Service or Terminal

Monerod Service

# Create the systemd service file
sudo vim /etc/systemd/system/monerod.service
sudo systemctl daemon-reload
sudo systemctl enable monerod
sudo systemctl start monerod
sudo systemctl status monerod

Monerod in Terminal

sudo -u monero /usr/local/bin/monerod --config-file=/etc/monero/monerod.conf

Homebrew (In Linux)

sudo -u monero /home/linuxbrew/.linuxbrew/bin/monerod --config-file=/etc/monero/monerod.conf

Cli Wallet

monero-wallet-cli --trusted-daemon --daemon-login username

Monero Ban List

Github repo

In monero

Yazi


Must

To use Yazi, you must have the following prerequisites installed:

file (for file type detection)

Optional

Yazi can be optionally extended with other command line tools to enable additional features.

nerd-fonts (recommended)
ffmpeg (for video thumbnails)
7-Zip (for archive extraction and preview)
jq (for JSON preview)
poppler (for PDF preview)
fd (for file searching)
rg (for file content searching)
fzf (for quick file subtree navigation, >= 0.53.0)
zoxide (for historical directories navigation, requires fzf)
resvg (for SVG preview)
ImageMagick (for Font, HEIC, and JPEG XL preview)
xclip / wl-clipboard / xsel (for Linux clipboard support)

Compile

sudo dnf in chafa fzf
cargo install --locked yazi-fm yazi-cli

Use

yazi

or in nushell with this use only y

def --env y [...args] {
	let tmp = (mktemp -t "yazi-cwd.XXXXXX")
	yazi ...$args --cwd-file $tmp
	let cwd = (open $tmp)
	if $cwd != "" and $cwd != $env.PWD {
		cd $cwd
	}
	rm -fp $tmp
}

Then run yazi

y

Yazi Keymap

F1 for keybindings

Official Resources

Yazi Github

Yazi Page


Crates.io

Usb Guard


sudo dnf in usbguard usbguard-selinux
sudo sytemctl enable --now usbguard
sudo bash -c "usbguard generate-policy > /etc/usbguard/rules.conf"

Manejar Dispositivos Temporalmentes

sudo usbguard list-devices
sudo usbguard allow-device #ID/Numero
sudo usbguard block-device #ID/Numero

Permitir Dispositivos Permanentemente

Primera vez

Esto es en Nushell, para hacerlo en POSIX cambiar | save por -> >

usbguard generate-policy | save rules.conf 
hx rules.conf
sudo install -m 0600 -o root -g root rules.conf /etc/usbguard/rules.conf
sudo systemctl restart usbguard

Cambio Normal

Agregar todo el path que aparece en usbguard list-devices. Sin el primer número y poniendo allow

sudo hx /etc/usbguard/rules.conf
sudo systemctl restart usbguard

Niri


Instalar mediante fedora everything de la forma mas minimalista

Index

Tty/Display Manager

No display manager solo tty.

En .zprofile:

if [ -z "$DISPLAY" ] && [ -z "$WAYLAND_DISPLAY" ] && [ "$(tty)" = "/dev/tty1" ]; then
    exec niri --session
fi

Polkit

sudo dnf in polkit-kde kf6-kirigami kf6-kirigami2

Agregar la siguiente linea al config de niri

spawn-at-startup "/usr/libexec/kf6/polkit-kde-authentication-agent-1"
systemctl --user daemon-reload
ln -s ~/.config/systemd/user/swayidle.service ~/.config/systemd/user/niri.service.wants/

Swaylock

mkdir -p ~/.config/swaylock
cp config ~/.config/swaylock/

Mako

mkdir -p ~/.config/mako
cp config ~/.config/mako/

Waybar

mkdir -p ~/.config/waybar
cp -r waybar/ ~/.config/waybar/

Color Scheme (TokyoNight)

Gtk

(https://github.com/Fausto-Korpsvart/Tokyonight-GTK-Theme):

sudo dnf in xdg-desktop-portal-gtk xdg-desktop-portal-gnome gtk-murrine-engine sassc
  • Mover Tokyonight-Dark a ~/.themes/
  • Mover gtk-4.0 a ~/.config/
dconf write /org/gnome/desktop/interface/gtk-theme "'Tokyonight-Dark'"

Qt

sudo dnf in qt5ct qt6ct
  • en .profile: export QT_QPA_PLATFORMTHEME=qt5ct
sudo cp .dotfile/qt/tokyonight.conf /usr/share/qt5ct/colors
sudo cp .dotfile/qt/tokyonight.conf /usr/share/qt6ct/colors
  • qt5ct -> tokyonight
  • qt6ct -> tokyonight

File Picker

For browsers add in /usr/share/xdg-desktop-portal/niri-portals.conf:

org.freedesktop.impl.portal.FileChooser=gtk;

Nushell

sudo dnf install libxcb openssl-devel libX11-devel
cargo install nu --locked
sudo sh -c 'echo "/home/user/.cargo/bin/nu" >> /etc/shells'

Sin cambiar de terminal, correr desde .bashrc

Macchina

sudo dnf in wmctrl
cargo install macchina

Tectonic

sudo dnf in openssl-devel graphite2-devel ghc-gi-freetype2-devel fontconfig-devel harfbuzz-devel libpng-devel ghc-zlib-devel
cargo install tectonic
sudo dnf rm graphite2-devel ghc-gi-freetype2-devel fontconfig-devel harfbuzz-devel libpng-devel ghc-zlib-devel

Bottom

cargo install --locked bottom

Mdbook

cargo install mdbook

Yazi

sudo dnf in chafa fzf
cargo install --locked yazi-fm yazi-cli

Plymouth

plymouth-set-default-theme tribar -R

Labwc

sudo dnf in labwc

Grub Password

Follow this guide Grub Password

Loupe

An image viewer made in RUST made by gnome

sudo dnf in loupe bubblewrap

To make it default

ls /usr/share/applications | grep -i loupe
ls ~/.local/share/applications | grep -i loupe
xdg-mime default org.gnome.Loupe.desktop image/jpeg
xdg-mime default org.gnome.Loupe.desktop image/png
xdg-mime default org.gnome.Loupe.desktop image/gif
xdg-mime default org.gnome.Loupe.desktop image/bmp
xdg-mime default org.gnome.Loupe.desktop image/webp
xdg-mime default org.gnome.Loupe.desktop image/svg+xml

xdg-mime query default image/png
# → should print: org.gnome.Loupe.desktop

Yofi

Yofi Github Repo

sudo dnf in libxkbcommon-devel
cargo install yofi

Papers

Semi rust pdf reader

ls /usr/share/applications | grep -i papers
ls ~/.local/share/applications | grep -i papers
xdg-mime default org.gnome.Papers.desktop application/pdf
xdg-mime query default application/pdf

Homebrew

curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh | bash

Then add in env.nu

$env.PATH = ($env.PATH | split row (char esep) | prepend '/home/linuxbrew/.linuxbrew/bin')

Virtualización


systemctl enable --now libvirtd
usermod -aG libvirt user
firewall-cmd --add-service=libvirt --permanent

sed -i 's/#unix_sock_group = "libvirt"/unix_sock_group = "libvirt"/' /etc/libvirt/libvirtd.conf
sed -i 's/#auth_unix_ro = "none"/auth_unix_ro = "none"/' /etc/libvirt/libvirtd.conf

sed -i '
  /^#.*unix_sock_group = "libvirt"/s/^#//
  s/unix_sock_ro_perms = "0777"/unix_sock_ro_perms = "0770"/
  s/^#auth_unix_ro = "none"/auth_unix_ro = "polkit"/
  s/^#auth_unix_rw = "none"/auth_unix_rw = "polkit"/
' /etc/libvirt/libvirtd.conf

En kvm activar edicion de xml, y en la distro a eleccion ir a la network poner xml y em vez de network poner user arriba Para que rinda perfecto poner spice server y video con qxl

Whonix Kvm


Tux

Kvm/Libvirt

Here -> Kvm

Download

License Agreement

tar -xvf Whonix*.libvirt.xz
touch WHONIX_BINARY_LICENSE_AGREEMENT_accepted 

Importing Whonix VM Templates

  • Add the virtual networks:
sudo virsh -c qemu:///system net-define Whonix_external*.xml ;
sudo virsh -c qemu:///system net-define Whonix_internal*.xml
  • Activate the virual networks
sudo virsh -c qemu:///system net-autostart Whonix-External ;
sudo virsh -c qemu:///system net-start Whonix-External ;
sudo virsh -c qemu:///system net-autostart Whonix-Internal ;
sudo virsh -c qemu:///system net-start Whonix-Internal 
  • Import the Whonix Gateway and Workstation images
sudo virsh -c qemu:///system define Whonix-Gateway*.xml ;
sudo virsh -c qemu:///system define Whonix-Workstation*.xml 

Image File Installation

  • Option 1: Slow
sudo mv Whonix-Gateway*.qcow2 /var/lib/libvirt/images/Whonix-Gateway.qcow2 ;
sudo mv Whonix-Workstation*.qcow2 /var/lib/libvirt/images/Whonix-Workstation.qcow2 
  • Option 2: Recommended Con root:
sudo su
cp Whonix*.qcow2.libvirt.xz /var/lib/libvirt/images/
cd /var/lib/libvirt/images/
tar -xvf Whonix*.qcow2.libvirt.xz 
rm WH* Wh*.xml Wh*.xz
mv Whonix-Workstation*.qcow2 Whonix-Workstation.qcow2
mv Whonix-Gateway*.qcow2 Whonix-Gateway.qcow2

Extra

Solo modificar cosas como ram o cpu.

Pasar Archivos

Existen 2 formas:

  • virtio-9p: Mas antigua y mas lenta
  • virtio-fs: Mas nuevo y rapido. A costo de tener que activar Shared memory. que puede afectar a la seguridad asi que ir con precaucion.

Settings -> Add hardware -> Filsesystem -> virtio-9p/virtio-fs

Ln


  • ln (hard link)

    • Crea un segundo nombre (alias) para el mismo archivo en el sistema de ficheros.

    • Ambos nombres comparten el mismo inode y, por tanto, los mismos datos; borrar uno no afecta al otro hasta que ambos se eliminen.

    • Sintaxis básica:

      ln <ruta_origen> <ruta_destino>
      
    • Limitaciones:

      • Debe residir en la misma partición.
      • Git lo trata como un archivo normal (bueno), pero no detecta que hay “vínculo” (todo bi-n).
  • ln -s (symbolic link / symlink)

    • Crea un pequeño archivo que apunta a otro por su ruta. No comparten inode.

    • Borrar el objetivo deja un “enlace roto”.

    • Sintaxis básica:

      ln -s <ruta_origen> <ruta_destino>
      
    • Ventajas:

      • Funciona entre distintas particiones o sistemas de ficheros.
      • Con rutas relativas, es portátil si se conserva la estructura de carpetas.
    • Consideraciones con Git:

      • Git almacena la ruta del symlink, no el contenido.
      • Quienes clonen el repo obtendrán el enlace, que puede fallar si no existe la misma ruta en sus máquinas.

–––

Resumen de usos

  • Usa hard link (ln) cuando quieras un segundo nombre indistinguible para el mismo fichero y estés en la misma partición.
  • Usa symlink (ln -s) cuando necesites apuntar a archivos en otra ubicación o mantener portabilidad con rutas relativas.

Nushell


Crates.io

Follow this guide first: Install rust.

If your distro has it just install it as nu or nushell. In Fedora:

sudo dnf in nu

Compile it from source

Dependencies

# Debian
sudo apt install pkg-config libssl-dev build-essential

# RedHat/Fedora based
sudo yum install libxcb openssl-devel libX11-devel
cargo install nu --locked

Usage

Removing files older than 3 weeks

ls | where modified <= (date now) - 3wk | each {|file| rm $file.name}

Rust Coreutils


In Fedora:

sudo dnf in uutils-coreutils
# Recommended
sudo dnf in bat ripgrep zoxide nu skim

Modify path for example in .bash_profile

export PATH="/usr/libexec/uutils-coreutils:$HOME:$PATH"

Ansible

sudo dnf in ansible

Set up your Inventory

Create a inventory.ini

[myhosts]
192.0.2.50
192.0.2.51
192.0.2.52

CONTINUAR

RustScan


Crates.io

Installation

First install Nmap. In Fedora:

sudo dnf in nmap

Setup Rustup/Cargo Then:

cargo install rustscan

Tips

Para revisar puertos abiertos

rustscan -a <ip-local> --ulimit 5000
rustscan -a 192.168.x.y --ulimit 5000

TLDR

 Modern Port Scanner written in Rust.
  Note: `nmap` must be installed for some of the examples below to work.
  More information: <https://github.com/bee-san/RustScan/wiki>.

  Scan all ports of one or more comma-delimited addresses using the default values:

      rustscan [-a|--addresses] ip_or_hostname

  Scan the top 1000 ports with service and version detection:

      rustscan --top [-a|--addresses] address_or_addresses

  Scan a specific list of ports:

      rustscan [-p|--ports] port1,port2,... [-a|--addresses] address_or_addresses

  Scan a specific range of ports:

      rustscan [-r|--range] start-end [-a|--addresses] address_or_addresses

  Invoke `nmap` functionalities (Nmap's OS detection and default scripts):

      rustscan [-a|--addresses] address_or_addresses -- -O [-sC|--script=default]

  Scan with custom batch size (default: 4500) and timeout (default: 1500ms):

      rustscan [-b|--batch-size] batch_size [-t|--timeout] timeout [-a|--addresses] address_or_addresses

  Scan with specific port order:

      rustscan --scan-order serial|random [-a|--addresses] address_or_addresses

  Scan in greppable mode (only output of the ports, no `nmap`):

      rustscan [-g|--greppable] [-a|--addresses] address_or_addresses

Firewalld


Entendiendo Firewalld: Tu Guardián en Linux

Firewalld es el demonio de firewall por defecto en distribuciones como Fedora, AlmaLinux, CentOS y RHEL. A diferencia de su predecesor, iptables (que también está por debajo, pero firewalld es una capa de abstracción superior), firewalld utiliza un concepto de zonas para gestionar las reglas de firewall, lo que lo hace más fácil de usar y más dinámico.


El Concepto de Zonas en Firewalld

Imagina tu red dividida en diferentes áreas de "confianza". Cada una de estas áreas es una zona, y a cada zona se le asigna un nivel de confianza y un conjunto de reglas que definen qué tipo de tráfico se permite o se bloquea. Las interfaces de red (Ethernet, Wi-Fi) o las direcciones IP de origen se asignan a estas zonas.

Cuando un paquete de red llega a tu sistema, firewalld intenta asignarlo a una zona. Una vez que el paquete está en una zona, se aplican las reglas de esa zona para decidir si se permite, se rechaza o se descarta.

Zonas Predefinidas Comunes:

Firewalld viene con varias zonas predefinidas, cada una con un nivel de confianza y reglas por defecto:

  • public: La zona por defecto para redes públicas. No confías en otros ordenadores en la red. Solo se aceptan las conexiones entrantes explícitamente permitidas. Es un buen punto de partida para servidores.
  • home: Para redes domésticas. Confías la mayoría de los otros ordenadores en la red.
  • work: Para redes de trabajo. Confías la mayoría de los otros ordenadores.
  • internal: Para redes internas. Mayor nivel de confianza que home o work.
  • trusted: La zona de mayor confianza. Todas las conexiones de red son aceptadas. ¡Úsala con precaución!
  • dmz (Demilitarized Zone): Para servidores que son públicos pero con acceso limitado a tu red interna.
  • drop: Cualquier paquete entrante es descartado sin ninguna respuesta. Solo son posibles las conexiones salientes. Es la más restrictiva.
  • block: Rechaza cualquier paquete entrante con un mensaje de "host prohibido".
  • external: Usada para redes externas, a menudo con enmascaramiento (NAT) habilitado, típico de routers.

Las interfaces de red se asignan a una zona. Por defecto, tu interfaz de red principal a menudo se asigna a la zona public.


Funcionamiento Básico de firewalld

  • firewall-cmd: Esta es la herramienta de línea de comandos principal para interactuar con firewalld.
  • --permanent: Las reglas que añades se pueden aplicar de forma temporal (solo hasta el siguiente reinicio o recarga del firewall) o de forma permanente. Para que una regla persista después de un reinicio, debes usar la opción --permanent.
  • --reload: Después de añadir o quitar reglas con --permanent, necesitas recargar el firewall para que los cambios permanentes se apliquen al firewall en ejecución. Si no usas --permanent, las reglas se aplican inmediatamente pero se pierden.

Comandos Clave de firewalld

1. Ver Reglas Actuales

Para ver las reglas activas en una zona específica (o en la zona por defecto si no especificas una):

sudo firewall-cmd --list-all --zone=public
  • Esto mostrará el estado de la zona public: servicios permitidos, puertos abiertos, reglas ricas, etc.
  • Si no especificas --zone=public, mostrará las reglas de la zona por defecto (que a menudo es public).

Para ver todas las zonas y sus configuraciones:

sudo firewall-cmd --list-all-zones

Para ver qué interfaces están asignadas a qué zonas:

sudo firewall-cmd --get-active-zones

2. Añadir Reglas (Permitir Tráfico)

Para permitir tráfico entrante a un puerto específico en una zona:

sudo firewall-cmd --permanent --add-port=PUERTO/protocolo --zone=zona_deseada
sudo firewall-cmd --reload
  • PUERTO: El número del puerto (ej., 18089).
  • protocolo: tcp o udp.
  • zona_deseada: La zona donde quieres aplicar la regla (ej., public).
  • Ejemplo para Monero RPC: sudo firewall-cmd --permanent --add-port=18089/tcp --zone=public

Para permitir tráfico entrante para un servicio conocido (SSH, HTTP, HTTPS, etc.) en una zona:

sudo firewall-cmd --permanent --add-service=nombre_servicio --zone=zona_deseada
sudo firewall-cmd --reload
  • nombre_servicio: El nombre del servicio (ej., ssh, http). Firewalld tiene definiciones preestablecidas para los puertos y protocolos de muchos servicios comunes.

Para permitir tráfico de una fuente específica (dirección IP o rango) a una zona (esto es más restrictivo y seguro):

sudo firewall-cmd --permanent --add-source=IP_o_rango_CIDR --zone=zona_deseada
sudo firewall-cmd --reload
  • IP_o_rango_CIDR: Por ejemplo, 192.168.1.0/24 para toda tu subred local.
  • Ejemplo para Monero con fuente específica:
    sudo firewall-cmd --permanent --add-source=192.168.1.0/24 --add-port=18089/tcp --zone=public
    sudo firewall-cmd --reload
    
    (Reemplaza 192.168.1.0/24 con el rango de tu red local si es diferente).

3. Eliminar Reglas

Para quitar una regla de puerto:

sudo firewall-cmd --permanent --remove-port=PUERTO/protocolo --zone=zona_deseada
sudo firewall-cmd --reload

Para quitar una regla de servicio:

sudo firewall-cmd --permanent --remove-service=nombre_servicio --zone=zona_deseada
sudo firewall-cmd --reload

Para quitar una regla de fuente:

sudo firewall-cmd --permanent --remove-source=IP_o_rango_CIDR --zone=zona_deseada
sudo firewall-cmd --reload

4. Recargar el Firewall

Siempre que hagas cambios permanentes, ¡no olvides recargar!

sudo firewall-cmd --reload

Esto aplica los cambios permanentes al firewall en ejecución sin interrumpir las conexiones existentes.


¿Qué significa --zone=public?

Cuando usas --zone=public, estás indicando que la regla que estás añadiendo o modificando debe aplicarse a la zona public.

En el contexto de tu VM de AlmaLinux:

  • Si la interfaz de red de tu VM está asignada a la zona public (que es lo más común por defecto, especialmente si la VM está en modo puente y no hay otras zonas configuradas explícitamente), entonces al añadir una regla a la zona public, estás permitiendo que el tráfico del puerto 18089/tcp llegue a esa VM desde tu red local (o cualquier red asociada a la zona public).
  • La zona public se considera "no confiable" por defecto, lo que significa que a menos que una conexión esté explícitamente permitida, será bloqueada. Al añadir el puerto 18089 a esta zona, estás haciendo esa excepción específica.

Qrrs


Qrrs

Usage

Quickly generate qr code

qrrs "Your input here"
qrrs "Your input here" --invert_colors

Generate code, than read it

qrrs "Something" /tmp/qr.png
$ qrrs --read /tmp/qr.png
Something
qrrs -t "Something" /tmp/qr.png

█████████████████████████████
█████████████████████████████
████ ▄▄▄▄▄ █▄ █▄▄█ ▄▄▄▄▄ ████
████ █   █ █▀▄████ █   █ ████
████ █▄▄▄█ █ ▄█▀▄█ █▄▄▄█ ████
████▄▄▄▄▄▄▄█ ▀ ▀ █▄▄▄▄▄▄▄████
████▄███ █▄▄ ▄▀ ▀▄▄▄  █▀▄████
████▄ ▀█▀▄▄▀▄▀▀▄█▀▄█ █▄ ▀████
████▄█▄██▄▄▄▀▀▀█ ▄▀█ ▀█▄ ████
████ ▄▄▄▄▄ █▄▀▄▀ ▄▄▀ ██ █████
████ █   █ █▄█▀ ▀▄▄█ ▀▀ ▀████
████ █▄▄▄█ ██▀ ▄█▀ ▀ ████████
████▄▄▄▄▄▄▄█▄▄▄█▄▄▄▄█▄██▄████
█████████████████████████████
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀

Show code as text in terminal

qrrs --read --terminal /tmp/qr.png

█████████████████████████████
█████████████████████████████
████ ▄▄▄▄▄ █▄ █▄▄█ ▄▄▄▄▄ ████
████ █   █ █▀▄████ █   █ ████
████ █▄▄▄█ █ ▄█▀▄█ █▄▄▄█ ████
████▄▄▄▄▄▄▄█ ▀ ▀ █▄▄▄▄▄▄▄████
████▄███ █▄▄ ▄▀ ▀▄▄▄  █▀▄████
████▄ ▀█▀▄▄▀▄▀▀▄█▀▄█ █▄ ▀████
████▄█▄██▄▄▄▀▀▀█ ▄▀█ ▀█▄ ████
████ ▄▄▄▄▄ █▄▀▄▀ ▄▄▀ ██ █████
████ █   █ █▄█▀ ▀▄▄█ ▀▀ ▀████
████ █▄▄▄█ ██▀ ▄█▀ ▀ ████████
████▄▄▄▄▄▄▄█▄▄▄█▄▄▄▄█▄██▄████
█████████████████████████████
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀

Save it into another file

qrrs --read --terminal /tmp/qr.png /tmp/qr1.png

Almost the same result will be without terminal flag, but now instead of QrCode printed in terminal we will see text from it.

qrrs --read /tmp/qr.png /tmp/qr1.png

Ssss

ssss-split -t 3 -n 5
Generating shares using a (3,5) scheme with dynamic security level.
Enter the secret, at most 128 ASCII characters: my secret root password
Using a 184 bit security level.
1-1c41ef496eccfbeba439714085df8437236298da8dd824
2-fbc74a03a50e14ab406c225afb5f45c40ae11976d2b665
3-fa1c3a9c6df8af0779c36de6c33f6e36e989d0e0b91309
4-468de7d6eb36674c9cf008c8e8fc8c566537ad6301eb9e
5-4756974923c0dce0a55f4774d09ca7a4865f64f56a4ee0
ssss-combine -t 3
Enter 3 shares separated by newlines:
Share [1/3]: 3-fa1c3a9c6df8af0779c36de6c33f6e36e989d0e0b91309
Share [2/3]: 5-4756974923c0dce0a55f4774d09ca7a4865f64f56a4ee0
Share [3/3]: 2-fbc74a03a50e14ab406c225afb5f45c40ae11976d2b665
Resulting secret: my secret root password

Labwc

sudo dnf in labwc

In this path ~/.config/labwc copy the rc.xml

Grub2 Password


In Libreboot

    1. Generate the HASH of the password
grub2-mkpasswd-pbkdf2

The output should be something like

grub.pbkdf2.sha512.10000.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    1. Open with sudo /etc/grub.d/40_custom. At the end add:
#──────────────────────────────────────
set superusers="admin"
password_pbkdf2 admin grub.pbkdf2.sha512.10000.XXXXXXXXXXXXXXXXXXXXXXXX
#──────────────────────────────────────
    1. Update grub
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
sudo reboot
    1. Test Test with "e", it should ask for an user and a password.

Cake Wallet


sha256sum Cake_Wallet_v5.1.2_Linux.tar.xz # Check in the realease page 
tar -xvf Cake_Wallet_v5.1.2_Linux.tar.xz
sudo mv Cake_Wallet*Linux /opt/cakewallet

Desktop Entry

sudo hx ~/.local/share/applications/cakewallet.desktop

Copy this:

[Desktop Entry]
Version=1.0
Type=Application
Name=CakeWallet
Comment=Wallet (CakeWallet Desktop)
Exec=/opt/cakewallet/cake_wallet %U
Icon=/opt/cakewallet/data/flutter_assets/assets/images/cake_logo_dark.svg
Terminal=false
Categories=Finance;Wallet;Cryptocurrency;
StartupNotify=true

Carapace



Download the rpm, this is for nushell

sha256sum carapace-bin*linux*.rpm
sudo dnf in carapace-bin*linux*.rpm
# ~/.config/nushell/env.nu
mkdir ~/.cache/carapace
carapace _carapace nushell | save --force ~/.cache/carapace/init.nu
# ~/.config/nushell/config.nu
source ~/.cache/carapace/init.nu

Force Dark Mode In Browser

    1. Open your browser’s Bookmarks Manager (e.g. Ctrl+Shift+O or Ctrl+Shift+B).
    1. Click Add New Bookmark.
    1. Set Name to “Dark Mode” (or your choice).
    1. Set URL to:
javascript:(function(){var s=document.getElementById('darkmode-toggle');s?s.remove():(s=document.createElement('style'),s.id='darkmode-toggle',s.textContent="html{filter:invert(1)hue-rotate(180deg)!important;}img,video,iframe{filter:invert(1)hue-rotate(180deg)!important;}",document.head.appendChild(s));})();
    1. Save the bookmark.
    1. (Optional) Enable your Bookmarks Bar for easy access.
    1. Click the “Dark Mode” bookmarklet on any page to invert colors.

Alacritty


Crates.io

Here

sudo dnf in cmake freetype-devel fontconfig-devel libxcb-devel libxkbcommon-devel g++
cargo install alacritty

Extra

The .desktop

git clone https://github.com/alacritty/alacritty/
cd alacritty
sudo desktop-file-install extra/linux/Alacritty.desktop

Mullvad VPN CLI Commands


Most Used

CommandDescription
mullvad account loginLog in to your Mullvad account.
mullvad account getShow your account information, including account number, device name, and expiration date.
mullvad relay listList available server locations.
mullvad relay set location <country_code> <city_code>Select a server location. Replace <country_code> and <city_code> with your desired values.
mullvad relay set location <server_name>Select a specific server by name.
mullvad connectConnect to the selected server location.
mullvad disconnectDisconnect from the VPN.
mullvad status -vCheck your connection status with detailed information.
mullvad auto-connect set onEnable auto-connect on startup.
mullvad lockdown-mode set onEnable Lockdown mode to block all Internet traffic until connected to Mullvad.
mullvad dns set default --block-ads --block-trackers --block-malware --block-adult-contentTo enable all DNS filters except social media, use the following command.
mullvad relay set tunnel-protocol wireguardUse Wireguard as the tunnel protocol (Is default).
mullvad tunnel set wireguard --quantum-resistant onEnable Quantum Resistant.

Basic Commands

CommandDescription
mullvad account login <account_number>Log in to your Mullvad account. Replace <account_number> with your actual account number.
mullvad account getShow your account information, including account number, device name, and expiration date.
mullvad account list-devicesList all device names associated with your account.
mullvad relay listList available server locations.
mullvad relay set location <country_code> <city_code>Select a server location. Replace <country_code> and <city_code> with your desired values.
mullvad relay set location <server_name>Select a specific server by name.
mullvad connectConnect to the selected server location.
mullvad disconnectDisconnect from the VPN.
mullvad relay updateForce an update of the server location list.
mullvad status -vCheck your connection status with detailed information.

Advanced Commands

CommandDescription
mullvad relay set tunnel-protocol openvpnUse OpenVPN as the tunnel protocol.
mullvad relay set tunnel openvpn --transport-protocol tcpUse OpenVPN over TCP.
mullvad relay set tunnel-protocol wireguardUse Wireguard as the tunnel protocol (Is default).
mullvad auto-connect set onEnable auto-connect on startup.
mullvad auto-connect set offDisable auto-connect on startup.
mullvad lan set allowEnable LAN access.
mullvad lockdown-mode set onEnable Lockdown mode to block all Internet traffic until connected to Mullvad.
mullvad tunnel set ipv6 onEnable in-tunnel IPv6.

Split Tunneling (Linux)

CommandDescription
mullvad-exclude <program>Start a new process excluded from Mullvad.
mullvad split-tunnel add <pid>Exclude a running process from Mullvad using its PID.
mullvad split-tunnel listList all currently excluded processes.
mullvad split-tunnel delete <pid>To restore a previously excluded process use this command.
mullvad split-tunnel clearTo restore all previously excluded processes use this command.

Shadowsocks Commands

CommandDescription
mullvad bridge set location <location>Set the location for Shadowsocks. Replace <location> with a specific country or city.
mullvad bridge set state onEnable bridge mode for Shadowsocks.
mullvad bridge set state offDisable bridge mode.
mullvad bridge set custom set shadowsocks --cipher <CIPHER> <REMOTE_IP> <REMOTE_PORT> <PASSWORD>Configure advanced Shadowsocks settings.

DNS Commands

CommandDescription
mullvad dns set default --helpTo view the help, use this command.
mullvad dns set default --block-ads --block-trackers --block-malware --block-gambling --block-adult-contentTo enable all DNS filters except social media, use the following command.
mullvad dns set defaultTo turn off all the content blockers use this command.

Make custom server lists

CommandDescription
mullvad custom-list new FavoritesTo create a new custom list named "Favorites" use this command.
mullvad custom-list edit add Favorites se-mma-wg-001To add a specific server, city or country to the list use one of these commands.
mullvad custom-list edit add Favorites se gotTo add a specific server, city or country to the list use one of these commands.
mullvad custom-list edit add Favorites seTo add a specific server, city or country to the list use one of these commands.
mullvad relay set custom-list FavoritesTo select your custom list so you can connect to it, use this command.
mullvad custom-list edit remove Favorites se-mma-wg-001To remove a specific server,city or country from the list use one of these commands. (The same as add)
mullvad custom-list edit rename Favorites FavouritesTo rename a custom list use this command.
mullvad custom-list listTo list all your custom lists and their content use this command.

Reset Settings

CommandDescription
mullvad factory-resetThis command performs a factory reset on all settings, deletes app logs and cache files, disconnects the app, and logs you out.

Official Page

Mullvad Cli

Homebrew


GitHub release

Not in Nushell

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
eval "$(<Homebrew prefix path>/bin/brew shellenv)"

In Nushell

curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh | bash

Then add in env.nu

$env.PATH = ($env.PATH | split row (char esep) | prepend '/home/linuxbrew/.linuxbrew/bin')

WebRTC

Mullvad Site


Firefox

Note: Firefox is the only browser that can properly disable WebRTC completely.

    1. Type about:config into the address bar and hit Enter.
    1. Click the button I accept the risk!.
    1. Type media.peerconnection.enabled in the search bar. Only one entry should appear.
    1. Double-click on the entry to change it to false.

To enable WebRTC again, change it back to "true".

Brave (desktop and Android)

Desktop

Open the Settings and click on the Magnifying glass icon in the top right corner and search for webrtc . Under WebRTC IP Handling Policy select Disable Non-Proxied UDP.

Android

Open the Settings and tap on Brave Shields & privacy. Then scroll down and tap on WebRTC IP Handling Policy. Select Disable Non-Proxied UDP and then tap on the X in the top right corner.

Test

Mullvad SOCK5

Brave

Add this line --proxy-server=socks5://10.64.0.1 at the .desktop (in /home/user/.local/share/applications so it dont overwrite)

Exec=/usr/bin/brave-browser-stable --proxy-server=socks5://10.64.0.1 --enable-features=UseOzonePlatform --ozone-platform=wayland %U

Localsend

tar -xvf LocalSend-X.XX.X-linux-XXX.tar.gz
sudo mkdir -p /opt/localsend
sudo cp data/ lib/ localsend_app /opt/localsend
cp localsend.desktop .local/share/applications/localsend.desktop

Extra

sudo firewall-cmd --add-port=53317/tcp --zone=drop

Ghostscript

To reduce pdf size

sudo dnf in ghostscript
gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dNOPAUSE -dQUIET -dBATCH -dDetectDuplicateImages=true -dCompressFonts=true -dSubsetFonts=true -dAutoRotatePages=/None -dPDFSETTINGS=/ebook -dColorImageDownsampleType=/Bicubic -dColorImageResolution=150 -dGrayImageDownsampleType=/Bicubic -dGrayImageResolution=150 -dMonoImageDownsampleType=/Subsample -dMonoImageResolution=300 -sOutputFile=output.pdf input.pdf

Autologin TTY1

sudo EDITOR=hx systemctl edit getty@tty1
[Service]
ExecStart=
ExecStart=-/usr/bin/agetty --autologin <user> --noclear %I $TERM
sudo systemctl daemon-reload
sudo systemctl restart getty@tty1.service

Tuigreet In Fedora

sudo dnf in greetd tuigreet

In /etc/greetd/config.toml

[terminal]
vt = 1

[default_session]
command = "tuigreet --cmd 'niri --session' --time --remember --asterisks"
user = "greetd"

Then:

sudo systemctl set-default graphical.target
sudo systemctl enable greetd
sudo systemctl start greetd

Fedora + Nix

Índice

  1. Preparando Todo
  2. Usuarios (mínimo privilegio)
  3. Login: greetd + tuigreet + niri
  4. Sudo-rs
  5. Instalar Nix (multiusuario)
  6. Configurar Nix en /etc/nix/nix.conf
  7. Sistema base con DNF
  8. Flake Home Manager
  9. Notas útiles y rollbacks

Preparación

sudo dnf up -y
sudo dnf in -y helix tar git NetworkManager-wifi NetworkManager-tui iwlwifi-mvm-firmware

Usuarios (mínimo privilegio)

  • admin → con sudo
  • main / focus / safe → sin sudo.

Crear usuarios:

sudo groupadd -f nhm
sudo useradd -m -s /bin/bash -G nhm main  && sudo passwd main
sudo useradd -m -s /bin/bash -G nhm focus && sudo passwd focus
sudo useradd -m -s /bin/bash -G nhm safe  && sudo passwd safe

Login: greetd + tuigreet + niri

sudo dnf in -y niri greetd tuigreet xdg-desktop-portal xdg-desktop-portal-wlr
sudo dnf rm -y fuzzel nano bluez

Configurar /etc/greetd/config.toml:

[terminal]
vt = 1
[default_session]
command = "tuigreet --cmd 'niri --session' --time --remember --asterisks"
user = "greetd"

Habilitar:

sudo systemctl set-default graphical.target
sudo systemctl enable greetd

Sudo-rs

su
dnf -y in sudo-rs
install -d /usr/local/bin
cat >/usr/local/bin/sudo <<'EOF'
#!/bin/sh
exec /usr/bin/sudo-rs "$@"
EOF
chmod 0755 /usr/local/bin/sudo
restorecon -v /usr/local/bin/sudo || true
type -a sudo    # debe listar /usr/local/bin/sudo primero

Su-rs

su
cat >/usr/local/bin/su <<'EOF'
#!/bin/sh
exec /usr/bin/su-rs "$@"
EOF
chmod 0755 /usr/local/bin/su
restorecon -v /usr/local/bin/su || true
type -a su    # debe listar /usr/local/bin/su primero

Instalar Nix (multiusuario)

curl --proto '=https' --tlsv1.2 -sSf -L https://artifacts.nixos.org/experimental-installer | sh -s -- install
. /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh

Configurar Nix en /etc/nix/nix.conf

Preparar directorio:

sudo mkdir /nhm
sudo chown admin:nhm /nhm
sudo chmod 750 /nhm
cd /nhm
git clone https://codeberg.org/Kyronix/dotfiles.git
cd dotfiles
git checkout nix-fedora
sudo git config --system --add safe.directory /nhm/dotfiles

Editar como root:

experimental-features = nix-command flakes
sandbox = true
sandbox-fallback = false
trusted-users = root @wheel
keep-outputs = true
keep-derivations = true

Aplicar:

sudo systemctl restart nix-daemon

Sistema base con DNF

sudo dnf config-manager addrepo --from-repofile=https://repository.mullvad.net/rpm/stable/mullvad.repo
sudo dnf config-manager addrepo --from-repofile=https://brave-browser-rpm-release.s3.brave.com/brave-browser.repo
sudo dnf in -y setroubleshoot nmap dnf-plugins-core power-profiles-daemon wlogout \
  libguestfs-tools usbguard-selinux @virtualization brave-browser mullvad-vpn mullvad-browser \
  lxqt-policykit clamav swayidle pulseaudio-utils foot mako

Flake Home Manager

# Genera/Actualiza flake.lock
cd /nhm/dotfiles
nix flake update

Desde el usuario correr este comando:

nix run /nhm/dotfiles#home-manager -- switch --flake /nhm/dotfiles#<usuario>
# Logeado como admin
nix run /nhm/dotfiles#home-manager -- switch --flake /nhm/dotfiles#admin
# Logeado como main 
nix run /nhm/dotfiles#home-manager -- switch --flake /nhm/dotfiles#main
# Logeado como focus
nix run /nhm/dotfiles#home-manager -- switch --flake /nhm/dotfiles#focus
# Logeado como safe
nix run /nhm/dotfiles#home-manager -- switch --flake /nhm/dotfiles#safe

Extra

Si estas en /nhm/dotfiles se puede usar:

nix run .#home-manager -- switch --flake .#admin

Notas útiles

  • Update:
cd /nhm/dotfiles
nix flake update                     # refresca nixpkgs/home-manager en flake.lock
# aplica por usuario:
nix run .#home-manager -- switch --flake .#admin
nix run .#home-manager -- switch --flake .#main
nix run .#home-manager -- switch --flake .#focus
nix run .#home-manager -- switch --flake .#safe
  • HM:
home-manager generations
home-manager switch --rollback
  • Limpieza:
sudo nix store gc
# Por usuario
home-manager expire-generations "-30 days"