Linux Initial Setup Guide#
1. Initial System Setup#
Timezone & Updates#
timedatectl set-timezone America/Torontoapt update && apt full-upgrade -yWarpification (Terminal UI)#
echo -e '\n# Auto-Warpify\nprintf '\''\eP$f{"hook": "SourcedRcFileForWarp", "value": { "shell": "bash", "uname": "'$(uname)'" }}\x9c'\'' ' >> ~/.bashrcEssential 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 -yFor 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.sh2. 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 chrConfigure SSH Public Key#
Edit authorized keys:
nano ~/.ssh/authorized_keysPaste 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 sshdIn some cases, the file is located here:
nano /etc/pve/priv/authorized_keys
Disable Root SSH Login#
Edit SSH config:
nano /etc/ssh/sshd_configEnsure the following settings:
PermitRootLogin prohibit-password
#PermitRootLogin yes
PubkeyAuthentication yesApply changes:
systemctl restart sshdn8n 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_keys3. Storage Maintenance#
SSD Trimming#
# Manual trim
fstrim -v /# Enable weekly automation
systemctl enable --now fstrim.timer# Verify schedule
systemctl list-timers fstrim.timerLVM 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--lv4. Security: #Fail2ban & #UFW#
Fail2ban Hardened Strategy#
Strategy: 3 failed attempts in 24h = 1-year ban (8760h).
- 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- Restart:
systemctl restart fail2banUFW Firewall Setup#
Reset#
sudo ufw --force resetDeny 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 enableTerminal Aliases#
#alias
Specific Docker and 1Password Aliases
# Edit aliases
/root/.bashrc5. Network Shares (Samba - #SMB)#
Basic Share Setup#
apt install samba
smbpasswd -a marcConfig (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 smbdRestricted #SMB - Only User#
sudo adduser --system --shell /usr/sbin/nologin --no-create-home --group proxmox
sudo smbpasswd -a proxmox7. Maintenance Tools#
Malware Scanning#
sudo apt install rkhunter chkrootkit -y# Run check
sudo rkhunter --check --sk# Update baseline after clean scan
sudo rkhunter --propupdQEMU Guest Agent (Proxmox Integration)#
apt-get install qemu-guest-agent
systemctl start qemu-guest-agent
systemctl enable qemu-guest-agentRClone Installation#
curl [https://rclone.org/install.sh](https://rclone.org/install.sh) | sudo bash# Configure remotes
rclone config8. 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#
- Use a dedicated Gmail account for homelab notifications, for example
proxmox.app@gmail.com. - Enable two-step verification on that Google account.
- Create a Google App Password for Postfix.
- 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 -yIf 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.cfAdd 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.crtStore the Relay Credentials#
Create the credential map without placing the password in a command or shell history:
sudo nano /etc/postfix/sasl_passwdAdd one line, replacing the placeholder with the Google App Password:
[smtp.gmail.com]:587 proxmox.app@gmail.com:GOOGLE_APP_PASSWORDBuild 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.dbValidate and Restart#
sudo postfix check
sudo systemctl restart postfix
sudo systemctl status postfix --no-pagerSend 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.comMonitor delivery and the queue:
sudo tail -f /var/log/mail.log
postqueue -pThe 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.comNever embed the App Password in application scripts. The script should use the local Postfix service, which reads the protected credential map.
HP1GPU configured