Versión
Fecha
Comentario
Autor
1.0
10/01/2025
Primera edición. Marco Teórico y Cheat Sheet.
Jes
This guide is a step by step meant to reproduce my workstation environment after a hard wipe of the disk.
This includes: Debian 13 official free repos, Librewolf repo, Mullvad browser repo, full Proton desktop suite, Neovim, tmux and a set of my favorite packages from apt; some for work/productivity, some for customization and some for fun.
My Proton referral code
Do not use any network.
Use entire disk + guided partition + encrypted Logical Volume.
Use a separated /home partition.
Select Debian desktop environment and Gnome.
Grant sudo rights to everyday user.
su -
usermod -aG sudo jes
Reboot now.
Load a pre‑downloaded Wireguard profile for Proton VPN.
If wg-quick is available:
sudo mkdir -p /etc/wireguard
sudo cp /mnt/$USER /external_drive_mount_point/Wireward/CH-MX.conf /etc/wireguard/
sudo wg-quick up CH-MX
sudo systemctl enable wg-quick@CH-MX
Reload if you edit the profile:
sudo wg-quick down CH-MX && sudo wg-quick up CH-MX
But it's not If we don't connect to the internet during installation (for example because we only have access to an unsecured network), so we use the GNOME GUI NetworkManager .
First make the file be only accessible by our everyday user:
sudo mkdir -p /etc/wireguard
sudo cp /mnt/$USER /external_drive_mount_point/Wireward/CH-MX.conf /etc/wireguard/
sudo chmod 600 /etc/wireguard/CH-MX.conf
sudo chown $USER :$USER CH-MX.conf
Then proceed with the GUI
Turn on Wi-Fi or connect Ethernet cable and Check public IP .
I run this snippet as root, could also open touch and open file as sudo with gedit/nano and paste it.
cat << EOF > /etc/apt/sources.list.d/debian.sources
Types: deb deb-src
URIs: https://deb.debian.org/debian
Suites: trixie trixie-updates
Components: main non-free-firmware
Enabled: yes
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
Types: deb deb-src
URIs: https://security.debian.org/debian-security
Suites: trixie-security
Components: main non-free-firmware
Enabled: yes
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
EOF
Curl and other utilities are installed here instead of the next section because we use it right away.
sudo apt update && \
sudo apt install extrepo curl wget apt-transport-https -y && \
sudo extrepo enable librewolf && \
sudo wget -O /usr/share/keyrings/element-io-archive-keyring.gpg https://packages.element.io/debian/element-io-archive-keyring.gpg && \
echo "deb [signed-by=/usr/share/keyrings/element-io-archive-keyring.gpg] https://packages.element.io/debian/ default main" | sudo tee /etc/apt/sources.list.d/element-io.list && \
sudo curl -fsSLo /usr/share/keyrings/mullvad-keyring.asc https://repository.mullvad.net/deb/mullvad-keyring.asc && \
echo "deb [signed-by=/usr/share/keyrings/mullvad-keyring.asc arch= $( dpkg --print-architecture ) ] https://repository.mullvad.net/deb/stable stable main" | sudo tee /etc/apt/sources.list.d/mullvad.list
Before continuing we upgrade the packages that were included offline from the installation media:
sudo apt update && \
sudo apt upgrade -y
sudo apt update && \
sudo apt full-upgrade -y && \
sudo apt install -y unattended-upgrades && \
sudo dpkg-reconfigure unattended-upgrades
sudo apt install -y git exiftool vim tar btop ufw apparmor apparmor-utils gnupg gnupg2 gnupg1 gnupg-agent libayatana-appindicator3-1 gir1.2-ayatanaappindicator3-0.1 gnome-shell-extensions gnome-shell-extension-manager gnome-shell-extension-prefs gnome-shell-extension-appindicator gnome-shell-extension-blur-my-shell gnome-shell-extension-impatience gnome-shell-extension-system-monitor gnome-shell-extension-hard-disk-led gnome-shell-extension-user-theme flatpak gnome-software-plugin-flatpak xfce4-terminal clamav clamav-daemon clamtk clamtk-gnome rkhunter fail2ban mullvad-browser librewolf debsig-verify debian-keyring nicotine keepassxc-full webext-keepassxc-browser keepassxc nextcloud-desktop tmux rhythmbox easyeffects perl jq element-desktop
sudo apt update && \
sudo apt autoremove --purge && \
sudo apt clean
sudo ufw default deny incoming && \
sudo ufw default allow outgoing && \
sudo ufw enable
sudo curl -fsSL https://raw.githubusercontent.com/ThatOneCalculator/NerdFetch/main/nerdfetch -o /usr/local/bin/nerdfetch && \
sudo chmod +x /usr/local/bin/nerdfetch && \
echo 'nerdfetch' >> /home/$USER /.bashrc
Links on this website point to old versions: Proton Apps
Individual product websites do point to latest versions... mostly.
But I figured the best way to get the newest links is to check the .json files that contains all version numbers, checksums and download URLs.
For some reason ProtonVPN has the file URL and the checksum published on this support article: How to install the Proton VPN GUI app on Debian .
I failed to find a .json file similar to the other products. I did foud a Release gpg key on the protonvpn repository but the checksum on the support article works fine so we use that.
For mail bridge they use a different integrity verification method: Proton Mail Bridge Signature
export PROTON_VPN_CHECKSUM = "0b14e71586b22e498eb20926c48c7b434b751149b1f2af9902ef1cfe6b03e180" && \
export PROTON_VPN_VERSION = "1.0.8_all" && \
export PROTON_PASS_CHECKSUM = "c742f302f73d59484a11055d58229240c7a0f648b2b9778968b6aac9e814e33c316f2a658cac58b55c518d228b59d92e1215e3eda07a5957fd5c4dddc086c8d0" && \
export PROTON_PASS_VERSION = "1.33.5_amd64" && \
export PROTON_MAIL_CHECKSUM = "eb24eeee66adc282ad7127a3e90cfd075353188f1a259c54d63ceb1883a6bfd4c5de4931a614836c20fedb18f3be1d972cf69486965e973f7f66d87e0120e28e" && \
export PROTON_MAIL_VERSION = "1.12.0" && \
export PROTON_BRIDGE_VERSION = "3.21.2-1_amd64" && \
export PROTON_AUTH_CHECKSUM = "f442dbf6c798586316f0e49cdfec999787cee3a0e1b42d43a868405e4f1f33496eb9e20a15209ad31595b26ac795eb7808bc10c341658c89732727bef5ca55de" && \
export PROTON_AUTH_VERSION = "1.1.4_amd64"
wget https://repo.protonvpn.com/debian/dists/stable/main/binary-all/protonvpn-stable-release_${ PROTON_VPN_VERSION } .deb && \
wget https://proton.me/download/pass/linux/proton-pass_${ PROTON_PASS_VERSION } .deb && \
wget https://proton.me/download/authenticator/linux/ProtonAuthenticator_${ PROTON_AUTH_VERSION } .deb && \
wget https://proton.me/download/mail/linux/${ PROTON_MAIL_VERSION } /ProtonMail-desktop-beta.deb && \
wget https://proton.me/download/bridge/protonmail-bridge_${ PROTON_BRIDGE_VERSION } .deb
echo " $PROTON_VPN_CHECKSUM protonvpn-stable-release_ ${ PROTON_VPN_VERSION } .deb" | sha256sum --check - && \
echo " $PROTON_PASS_CHECKSUM proton-pass_ ${ PROTON_PASS_VERSION } .deb" | sha512sum --check - && \
echo " $PROTON_AUTH_CHECKSUM ProtonAuthenticator_ ${ PROTON_AUTH_VERSION } .deb" | sha512sum --check - && \
echo " $PROTON_MAIL_CHECKSUM ProtonMail-desktop-beta.deb" | sha512sum --check -
We expect to see all OK to this point.
Now proceed with the verification mechanism for the bridge:
wget https://proton.me/download/bridge/bridge_pubkey.gpg && \
gpg --dearmor --output debsig.gpg bridge_pubkey.gpg && \
sudo mkdir -p /usr/share/debsig/keyrings/E2C75D68E6234B07 && \
sudo mv debsig.gpg /usr/share/debsig/keyrings/E2C75D68E6234B07 && \
wget https://proton.me/download/bridge/bridge.pol && \
sudo mkdir -p /etc/debsig/policies/E2C75D68E6234B07 && \
sudo cp bridge.pol /etc/debsig/policies/E2C75D68E6234B07 && \
debsig-verify protonmail-bridge_${ PROTON_BRIDGE_VERSION } .deb
Should yield:
debsig: Verified package from 'Proton AG (Proton Mail Bridge developers) <bridge@protonmail.ch>' (Proton AG)
sudo dpkg -i ./protonvpn-stable-release_${ PROTON_VPN_VERSION } .deb && \
sudo apt update && \
sudo apt install -y proton-vpn-gnome-desktop
sudo apt update && \
sudo dpkg -i ./proton-pass_${ PROTON_PASS_VERSION } .deb && \
sudo dpkg -i ./ProtonAuthenticator_${ PROTON_AUTH_VERSION } .deb && \
sudo dpkg -i ./ProtonMail-desktop-beta.deb && \
sudo dpkg -i ./protonmail-bridge_${ PROTON_BRIDGE_VERSION } .deb
I wouldn't use unofficial RClone plugin for Proton Drive because I'm paying ProtonAG for an enterprise level office-suite and that's what I expect...
For the time being I'm using the Proton Drive Webapp for my personal files, and a Nextcloud instance on my own vps for work-related files.
Deny everything by default and only enable known traffic.
Add fallback "kill-switch" just in case.
export WG_IFACE = "CH-MX"
export PROTON_IFACE = "proton0"
export ETH_IFACE = "en0"
export WIFI_IFACE = "wl0"
sudo ufw reset
sudo ufw default deny incoming
sudo ufw default deny outgoing
sudo ufw default deny routed
sudo ufw allow in on lo
sudo ufw allow in on " $ETH_IFACE " to any port 67 proto udp comment 'DHCP server (eth)'
sudo ufw allow in on " $ETH_IFACE " to any port 68 proto udp comment 'DHCP client (eth)'
sudo ufw allow in on " $WIFI_IFACE " to any port 67 proto udp comment 'DHCP server (wifi)'
sudo ufw allow in on " $WIFI_IFACE " to any port 68 proto udp comment 'DHCP client (wifi)'
# DNS
sudo ufw allow out on " $ETH_IFACE " to 127 .0.0.53 port 53 proto udp comment 'DNS (eth)'
sudo ufw allow out on " $WIFI_IFACE " to 127 .0.0.53 port 53 proto udp comment 'DNS (wifi)'
sudo ufw allow out on " $ETH_IFACE " to " $PROTON_DNS " port 53 proto { udp,tcp} comment 'Proton DNS (eth)'
sudo ufw allow out on " $WIFI_IFACE " to " $PROTON_DNS " port 53 proto { udp,tcp} comment 'Proton DNS (wifi)'
# API de Proton VPN
sudo ufw allow out on " $ETH_IFACE " to any port 443 proto tcp comment 'Proton VPN API (eth)'
sudo ufw allow out on " $WIFI_IFACE " to any port 443 proto tcp comment 'Proton VPN API (wifi)'
# Túneles VPN
sudo ufw allow out on " $WG_IFACE " comment "WireGuard tunnel ( $WG_IFACE ) – outbound"
sudo ufw allow out on " $PROTON_IFACE " comment "Proton VPN tunnel ( $PROTON_IFACE ) – outbound"
sudo ufw allow in on " $PROTON_IFACE " comment "Allow inbound from Proton tunnel (established)"
sudo ufw allow in on " $WG_IFACE " comment "Allow inbound from WireGuard tunnel (established)"
sudo ufw enable
sudo systemctl enable --now apparmor
net.ipv4.tcp_syncookies = 1 – enables SYN-cookies to mitigate SYN-flood attacks that could exhaust the TCP connection table.
net.ipv4.conf.all.rp_filter = 1 – activates reverse-path filtering, discarding packets with source addresses that do not match the expected output path, avoiding spoofing and reflections.
net.ipv4.conf.all.accept_redirects = 0 – ignores ICMP redirects, preventing an attacker from modifying the host's route table.
net.ipv4.icmp_echo_ignore_broadcasts = 1 – blocks responses to broadcast pings, preventing the machine from participating in DDoS amplification attacks.
kernel.randomize_va_space = 2 – enables full ASLR, increasing the randomness of memory layout and making it more difficult to exploit vulnerabilities.
kernel.kptr_restrict = 2 – Hides kernel symbols in /proc/kallsyms from unprivileged users, reducing the information available to local attackers.
fs.suid_dumpable = 0 – prevents processes with SUID/SGID from generating core dumps, avoiding the exposure of sensitive data in case of failures.
As root or sudo with gedit instead:
cat << EOF > /etc/sysctl.d/99-hardening.conf
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.icmp_echo_ignore_broadcasts = 1
kernel.randomize_va_space = 2
kernel.kptr_restrict = 2
fs.suid_dumpable = 0
EOF
sudo sysctl --system
Enable automatic signature updates
sudo freshclam
sudo systemctl enable --now clamav-freshclam
sudo systemctl status clamav-freshclam
sudo systemctl enable --now fail2ban
sudo systemctl status fail2ban
KeepassXC Browser Extension
Allow exntesion on KeepassXC Gui.
flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
mkdir -p ~/.local/share/xfce4/terminal/colorschemes
git clone https://github.com/rose-pine/xfce-terminal.git ~/Repositories/rose-pine/
cp ~/Repositories/rose-pine/dist/*.theme /home/$USER /.local/share/xfce4/terminal/colorschemes/
chown -R $USER :$USER ~/.local/share/xfce4
git clone https://github.com/neovim/neovim.git
git clone ssh://git@codeberg.org/jesmx/tmux.conf.git
git clone ssh://git@codeberg.org/jesmx/tmux.powerline.conf.git
git clone ssh://git@codeberg.org/jesmx/nvim.conf.git
Use Neovim nightly (main) branch for build from source. Follow up with Personal Tmux and Neovim configurations.
git clone ssh://git@codeberg.org/jesmx/Knowledge.git
Easy Effects wiki Community Presets
mkdir -p ~/Music/eq_presets/
cd ~/Music/eq_presets/
git clone https://github.com/Bundy01/EasyEffects-Presets
git clone https://github.com/JackHack96/EasyEffects-Presets.git
git clone https://github.com/qbarbosa/PulseEffects-Presets.git
Converting PulseEffects presets to EasyEffects presets:
In EasyEffects 6.0.0 preset structure changed a little. There is a bash shell script that can convert all presets in directory the entire directory.
The script is provided in this issue comment by AbsurdlySuspicious
cat << EOF > ~/Music/eq_presets/fix_ef_pe.sh
#!/usr/bin/env bash
# Replace with 'input' if you want to convert input preset
section='output'
# Convert boolean and numeric strings + replace invalid empty blocklist
perl -i -pe 's/"(true|false|[\d\.-]+)"/$1/g; s/(?<="blocklist": )""/[]/g' "$@"
# Fix plugins order using v5 state field (your set up plugin order is preserved)
for f in "$@"; do
# Extract active plugins in right order
po_src=$(jq ".$section"' | . as $out | .plugins_order | .[] | . as $pn | select($out | to_entries | .[] | .key as $key | select(["blocklist", "plugins_order"] | any(. == $key) | not) | select(.value.state != false) | .key == $pn)' "$f" -r)
# Replace order array in config with new one
jq --arg po "$po_src" '($po | split("\n")) as $poa | '".$section.plugins_order"' = $poa' "$f" >tmp
mv tmp "$f"
done
EOF
chmod +x ~/Music/eq_presets/fix_ef_pe.sh
cd ~/Music/eq_presets/fix_ef_pe.sh
./fix_ef_pe.sh *.json
sudo aa-status | grep "enforced"
sudo systemctl is-active clamav-freshclam
sudo systemctl is-active fail2ban
id $USER
sudo -lU $USER
sudo ufw status verbose
nmcli connection show --active
git config --global user.email " $USER @jes.mx"
git config --global user.user " $USER "
git config --global user.name " $USER "
sudo apt update
sudo apt upgrade -y
sudo apt clean
sudo apt autoremove --purge
Reboot now.
Setup anime girl background and transparent xfce terminal. Make terminal maximize on start, remove scrollbar, remove all terminal key-binds but full-screen. Set rose-pine color theme in settings.
Make VPN GUI launch at startup, setup kill-switch, netshield, ipv6 support, automatic connection to México.
Enable and customize gnome shell extensions.
Install Top Bar Customizer from gnome user extensions and sort the top bar.
Login into NextCloud accounts via Desktop app. Login into Nextcloud accounts via Gnome Accounts.
Setup proton mail bridge.
Login into IMAP & SMPT Accounts via Gnome accounts.
Blast some music and get ready to work ;)