Linux Initial Setup Guide#


1. Initial System Setup#

Timezone & Updates#

timedatectl set-timezone America/Toronto
apt update && apt full-upgrade -y

Warpification (Terminal UI)#

echo -e '\n# Auto-Warpify\nprintf '\''\eP$f{"hook": "SourcedRcFileForWarp", "value": { "shell": "bash", "uname": "'$(uname)'" }}\x9c'\'' ' >> ~/.bashrc

Essential Package Installation#

For Virtual Machines (Full Suite):

apt install gdebi curl sudo gpg ethtool ngrep lshw lsscsi cifs-utils ncdu etherwake lshw sudo tasksel fail2ban openssh-server qemu-guest-agent unzip smbclient fio iperf3 nmap net-tools apt-transport-https software-properties-common wget duf tldr zip git eza snapd samba glances -y

For LXC Containers (Lightweight):

apt install curl gpg sudo fail2ban apt-transport-https software-properties-common wget etherwake zip git -y 

Security Scripts#

Run the AI protection script from the Mac Studio volume:

/Volumes/Software/Software/Scripts/MacOS/ai_deploy_safety_on_all_servers.sh

2. User & Access Management#

Root Password & Sudo Users#

# Change root password
sudo passwd root
# Create user 'marc' with NOPASSWD sudo
adduser --home /home/marc marc && usermod -aG sudo marc
echo "marc ALL=(ALL) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/marc
# Create user 'chr'
adduser --home /home/chr chr && usermod -aG sudo chr

Configure SSH Public Key#

Edit authorized keys:

nano ~/.ssh/authorized_keys

Paste SSH keys for [1Password Private note](https://start.1password.com/open/i?a=G7ECSBBRRFHWPDIM7F7J6TWP7I&v=4bxn4d3worhhq7rc6m3usjciia&i=6hoe6ndejfr5evqpatwk2xsatq&h=my.1password.com)

Restart SSH:

systemctl restart sshd

In some cases, the file is located here:

nano /etc/pve/priv/authorized_keys

Disable Root SSH Login#

Edit SSH config:

nano /etc/ssh/sshd_config

Ensure the following settings:

PermitRootLogin prohibit-password
#PermitRootLogin yes
PubkeyAuthentication yes

Apply changes:

systemctl restart sshd

n8n Restricted SSH User#

Created for secure command execution from the n8n container.

# Create system user
adduser --system --home /home/n8n --shell /bin/bash --group n8n
# Setup SSH Directory
mkdir -p /home/n8n/.ssh
chown -R n8n:n8n /home/n8n
chmod 700 /home/n8n/.ssh
# Add public key from n8n host (HP1GPU)
nano /home/n8n/.ssh/authorized_keys
# Paste key: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG6oOUXHpXQDKMiFGmjWqZNAg6rw00a33HkooILzyeim root@HP1GPU
# Finalize Permissions
chmod 600 /home/n8n/.ssh/authorized_keys
chown n8n:n8n /home/n8n/.ssh/authorized_keys

3. Storage Maintenance#

SSD Trimming#

# Manual trim
fstrim -v /
# Enable weekly automation
systemctl enable --now fstrim.timer
# Verify schedule
systemctl list-timers fstrim.timer

LVM Partition Extension (Ubuntu)#

# Identify drive
df -h
# Extend Logical Volume
lvextend -l +100%FREE /dev/mapper/ubuntu--vg-ubuntu--lv
# Resize Filesystem
resize2fs /dev/mapper/ubuntu--vg-ubuntu--lv

4. Security: #Fail2ban & #UFW#

Fail2ban Hardened Strategy#

Strategy: 3 failed attempts in 24h = 1-year ban (8760h).

  1. Setup local config:
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
echo "[INCLUDES]
before = paths-debian.conf

[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 YOUR_HOME_IP_HERE
bantime  = 1h
findtime  = 1h
maxretry = 5
backend  = systemd
banaction = ufw

[sshd]
enabled  = true
port     = ssh
maxretry = 3
findtime = 24h
bantime  = 8760h
filter   = sshd[mode=aggressive]" > /etc/fail2ban/jail.local
  1. Restart:
systemctl restart fail2ban

UFW Firewall Setup#

Reset#

sudo ufw --force reset

Deny Incoming#

sudo ufw default deny incoming
sudo ufw default allow outgoing
# Allow Trusted SSH
sudo ufw allow from 72.11.191.80 to any port 22 proto tcp
sudo ufw allow from 24.114.107.66 to any port 22 proto tcp
# Allow Web & WireGuard
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 51820/udp
sudo ufw enable

Terminal Aliases#

#alias

Specific Docker and 1Password Aliases

# Edit aliases
/root/.bashrc

5. Network Shares (Samba - #SMB)#

Basic Share Setup#

apt install samba
smbpasswd -a marc

Config (nano /etc/samba/smb.conf):

nano /etc/samba/smb.conf
[paperless]
   path = /mnt/paperless/media/documents/originals/
   browseable = yes
   read only = no
   guest ok = no
   valid users = "marc"
   force user = "marc"
sudo systemctl restart smbd

Restricted #SMB - Only User#

sudo adduser --system --shell /usr/sbin/nologin --no-create-home --group proxmox
sudo smbpasswd -a proxmox


7. Maintenance Tools#

Malware Scanning#

sudo apt install rkhunter chkrootkit -y
# Run check
sudo rkhunter --check --sk
# Update baseline after clean scan
sudo rkhunter --propupd

QEMU Guest Agent (Proxmox Integration)#

apt-get install qemu-guest-agent
systemctl start qemu-guest-agent
systemctl enable qemu-guest-agent

RClone Installation#

curl [https://rclone.org/install.sh](https://rclone.org/install.sh) | sudo bash
# Configure remotes
rclone config

8. Postfix Authenticated SMTP Relay#

Purpose#

Direct-to-Gmail delivery from a homelab IP can be rejected because the server does not pass SPF or DKIM authentication. Configure Postfix to relay outbound mail through an authenticated Gmail account over encrypted SMTP instead.

This is intended for Linux hosts such as HP1GPU (10.1.2.231) that already run Postfix and need to send service notifications.

Prerequisites#

  1. Use a dedicated Gmail account for homelab notifications, for example proxmox.app@gmail.com.
  2. Enable two-step verification on that Google account.
  3. Create a Google App Password for Postfix.
  4. Store the App Password in 1Password. Do not store it in this note, shell history, Git, or a script.

Install Required Packages#

sudo apt update
sudo apt install postfix libsasl2-modules ca-certificates mailutils -y

If Postfix is already installed, retain the existing service configuration when prompted.

Configure the Gmail Relay#

Edit the active Postfix configuration:

sudo nano /etc/postfix/main.cf

Add or update these settings:

relayhost = [smtp.gmail.com]:587
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_sasl_tls_security_options = noanonymous
smtp_tls_security_level = encrypt
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt

Store the Relay Credentials#

Create the credential map without placing the password in a command or shell history:

sudo nano /etc/postfix/sasl_passwd

Add one line, replacing the placeholder with the Google App Password:

[smtp.gmail.com]:587 proxmox.app@gmail.com:GOOGLE_APP_PASSWORD

Build the lookup database and restrict both files:

sudo postmap hash:/etc/postfix/sasl_passwd
sudo chmod 600 /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db
sudo chown root:root /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db

Validate and Restart#

sudo postfix check
sudo systemctl restart postfix
sudo systemctl status postfix --no-pager

Send a Test Message#

Use the authenticated Gmail address as the sender:

printf '%s\n' "Postfix Gmail relay test from $(hostname)" | \
  mail -r proxmox.app@gmail.com \
       -s "Postfix authenticated relay test" \
       proxmox.app@gmail.com

Monitor delivery and the queue:

sudo tail -f /var/log/mail.log
postqueue -p

The log should show delivery through smtp.gmail.com with a successful status. A queue entry or bounce indicates that the relay credentials, App Password, TLS configuration, or Google account security settings need review.

Script Integration#

Scripts that send notifications through this host should use the configured sender address:

mail -r proxmox.app@gmail.com -s "Subject" proxmox.app@gmail.com

Never embed the App Password in application scripts. The script should use the local Postfix service, which reads the protected credential map.

HP1GPU configured