← Back to DevBytes

Securing Gentoo Servers: A Practical Checklist

Introduction to Securing Gentoo Servers

Gentoo Linux is a source-based distribution renowned for its flexibility and performance. Because every package is compiled from source with user-defined USE flags, Gentoo offers a uniquely small attack surface compared to binary distributions. However, this power comes with responsibility: a misconfigured Gentoo server can be just as vulnerable as any other system. This tutorial provides a practical, end-to-end checklist for hardening a Gentoo server from initial installation through ongoing maintenance.

Why Gentoo Security Matters

Security on Gentoo matters for several reasons. First, because you control the build process, you can strip out unnecessary features that introduce vulnerabilities. Second, Gentoo's rolling nature means updates arrive quickly, but only if you actively apply them — there is no automatic patching by default. Third, many Gentoo deployments run on edge cases, embedded systems, or custom infrastructure where a compromise can have outsized impact. A hardened Gentoo server leverages the distribution's strengths while mitigating its manual-update weaknesses.

Phase 1: Installation Hardening

Security begins at install time. The choices you make during the initial Gentoo setup reverberate throughout the server's lifetime.

Choosing the Right Profile and Stage

Select a hardened profile if your workload supports it. Hardened profiles enable PIE (Position Independent Executables), stack smashing protection, and other compiler-level mitigations by default.

# List available profiles
eselect profile list

# Select a hardened profile
eselect profile set 1

# Verify the selection
eselect profile show

Configuring USE Flags for Minimal Attack Surface

Review your make.conf and remove any USE flags you do not need. Fewer enabled features mean fewer potential vulnerabilities.

# /etc/portage/make.conf
USE="-doc -test -examples -X -alsa -opengl -wayland"
USE="${USE} ssl crypt pam systemd"
MAKEOPTS="-j4"
FEATURES="buildpkg collision-protect"

The collision-protect feature prevents packages from overwriting files owned by other packages, which can mask malicious or accidental file replacements.

Compiler Hardening Flags

Add explicit hardening flags to your make.conf to ensure consistent protection across all builds:

# /etc/portage/make.conf
CFLAGS="-O2 -pipe -fstack-protector-strong -D_FORTIFY_SOURCE=2"
CXXFLAGS="${CFLAGS}"
LDFLAGS="-Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack"

Phase 2: Kernel Hardening

The kernel is the foundation of system security. A poorly configured kernel undermines every other hardening measure.

Essential Kernel Options

When configuring your kernel with make menuconfig, enable the following options:

# Disable loading modules at runtime
CONFIG_MODULES=n

# Or, if modules are required, restrict them
CONFIG_MODULE_SIG=y
CONFIG_MODULE_SIG_FORCE=y

# Enable SELinux or AppArmor
CONFIG_SECURITY_SELINUX=y
# or
CONFIG_SECURITY_APPARMOR=y

# Restrict kernel pointer access
CONFIG_RANDOMIZE_BASE=y
CONFIG_RANDOMIZE_MEMORY=y

# Restrict dmesg access
CONFIG_SECURITY_DMESG_RESTRICT=y

# Disable legacy /dev/mem access
CONFIG_STRICT_DEVMEM=y
CONFIG_IO_STRICT_DEVMEM=y

# Enable BPF hardening
CONFIG_BPF_UNPRIV_DEFAULT_OFF=y

Applying sysctl Tunables

Create a sysctl configuration file to enforce runtime kernel protections:

# /etc/sysctl.d/99-hardening.conf

# Network hardening
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_source_route = 0

# Disable IP forwarding (unless this is a router)
net.ipv4.ip_forward = 0
net.ipv6.conf.all.forwarding = 0

# Memory protection
kernel.randomize_va_space = 2
kernel.kptr_restrict = 2
kernel.dmesg_restrict = 1
kernel.perf_event_paranoid = 3
kernel.yama.ptrace_scope = 2

# Filesystem hardening
fs.protected_hardlinks = 1
fs.protected_symlinks = 1
fs.protected_fifos = 2
fs.protected_regular = 2
fs.suid_dumpable = 0

Apply the changes immediately:

sysctl --system

Phase 3: User and Access Management

Securing SSH Access

SSH is the primary entry point for most servers. Lock it down aggressively.

# /etc/ssh/sshd_config

# Disable root login
PermitRootLogin no

# Disable password authentication
PasswordAuthentication no
PubkeyAuthentication yes

# Limit to specific users
AllowUsers deploy admin

# Reduce login grace period
LoginGraceTime 30

# Limit authentication attempts
MaxAuthTries 3

# Disable X11 forwarding if not needed
X11Forwarding no

# Use strong ciphers and MACs
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group16-sha512

# Idle timeout
ClientAliveInterval 300
ClientAliveCountMax 0

Restart the SSH daemon after changes:

systemctl restart sshd

Configuring Sudo and Privilege Escalation

Avoid giving users full root access. Use sudo with granular rules:

# /etc/sudoers.d/deploy
deploy ALL=(root) /usr/bin/emerge --sync, /usr/bin/emerge --update *
deploy ALL=(root) /usr/bin/systemctl restart nginx
deploy ALL=(root) /usr/bin/journalctl -u nginx

Always edit sudoers files with visudo to validate syntax before saving:

visudo -f /etc/sudoers.d/deploy

Enforcing Password Policies

Configure PAM to enforce strong passwords and account lockout:

# /etc/security/passwdqc.conf
min=disabled,disabled,12,8,7
max=72
passphrase=4
match=4
similar=deny
enforce=everyone
# /etc/pam.d/system-auth - add to password section
password  required  pam_pwquality.so retry=3 minlen=12 dcredit=-1 ucredit=-1 ocredit=-1 lcredit=-1
password  required  pam_pwhistory.so use_authtok remember=12

Phase 4: Package and Update Management

Regular Security Updates

Gentoo does not auto-update. Establish a routine for syncing and applying security patches:

# Sync the portage tree
emaint sync -a

# Check for security vulnerabilities
glsa-check --list

# Apply all GLSA-flagged packages
glsa-check --fix all

# Full system update
emerge --ask --update --deep --newuse @world
emerge --ask --depclean
emerge --ask @preserved-rebuild

Automate GLSA checks with a cron job or systemd timer:

# /etc/cron.daily/glsa-check
#!/bin/bash
glsa-check --list 2>&1 | mail -s "Gentoo GLSA Report $(hostname)" admin@example.com
chmod +x /etc/cron.daily/glsa-check

Using glsa-check Effectively

The glsa-check tool is Gentoo's primary vulnerability scanner. It cross-references installed packages against published Gentoo Linux Security Advisories.

# List all applicable GLSAs
glsa-check --list

# Show details of a specific GLSA
glsa-check --dump 202312-01

# Test without applying
glsa-check --test 202312-01

# Apply a specific fix
glsa-check --fix 202312-01

Verifying Package Integrity

Ensure your repositories use signed manifests and verify them:

# /etc/portage/repos.conf/gentoo.conf
[gentoo]
location = /var/db/repos/gentoo
sync-type = rsync
sync-uri = rsync://rsync.gentoo.org/gentoo-portage
sync-openpgp-key-path = /usr/share/openpgp-keys/gentoo-release.asc
sync-openpgp-key-refresh = no
sync-openpgp-keyserver = hkps://keys.gentoo.org

Phase 5: Firewall and Network Security

Configuring nftables

Gentoo supports both iptables and nftables. For new deployments, nftables is recommended due to its cleaner syntax and better performance.

# /etc/nftables.conf

flush ruleset

table inet filter {
    chain input {
        type filter hook input priority 0; policy drop;

        # Allow loopback
        iif "lo" accept

        # Allow established connections
        ct state established,related accept

        # Allow SSH with rate limiting
        tcp dport 22 ct state new limit rate 3/minute burst 5 packets accept

        # Allow HTTP/HTTPS
        tcp dport { 80, 443 } accept

        # Drop invalid packets
        ct state invalid drop

        # Allow ICMP (rate limited)
        icmp type echo-request limit rate 1/second accept
        ip6 nexthdr icmpv6 icmpv6 type echo-request limit rate 1/second accept

        # Log and drop everything else
        limit rate 5/minute log prefix "nftables-drop: " drop
    }

    chain forward {
        type filter hook forward priority 0; policy drop;
    }

    chain output {
        type filter hook output priority 0; policy accept;
    }
}

Enable and start the service:

systemctl enable nftables
systemctl start nftables
nft list ruleset

Port Knocking for Sensitive Services

For administrative services that should not be publicly accessible, consider port knocking with knockd:

# /etc/knockd.conf
[openSSH]
sequence    = 7000,8000,9000
seq_timeout = 10
start_command = nft add rule inet filter input tcp dport 22 accept
stop_command  = nft delete rule inet filter input tcp dport 22 accept
cmd_timeout   = 600

Phase 6: Filesystem and Data Protection

Securing Temporary Directories

Mount /tmp, /var/tmp, and /dev/shm with noexec, nosuid, and nodev options:

# /etc/fstab
tmpfs   /tmp        tmpfs   defaults,noexec,nosuid,nodev,size=2G        0 0
tmpfs   /var/tmp    tmpfs   defaults,noexec,nosuid,nodev,size=2G        0 0
tmpfs   /dev/shm    tmpfs   defaults,noexec,nosuid,nodev,size=1G        0 0

File Integrity Monitoring with AIDE

Install and configure AIDE to detect unauthorized file changes:

emerge --ask app-forensics/aide
# Initialize the AIDE database
aide --init

# Move the database to the active location
mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db

# Run a check
aide --check

Schedule regular integrity checks:

# /etc/cron.daily/aide-check
#!/bin/bash
aide --check 2>&1 | mail -s "AIDE Report $(hostname)" admin@example.com

Securing Sensitive Files

Review and tighten permissions on critical system files:

# Restrict cron access
chmod 700 /etc/cron.d
chmod 600 /etc/crontab

# Restrict SSH host keys
chmod 600 /etc/ssh/ssh_host_*_key
chmod 644 /etc/ssh/ssh_host_*_key.pub

# Restrict bootloader config
chmod 600 /boot/grub/grub.cfg

# Protect sudoers
chmod 440 /etc/sudoers
chmod 440 /etc/sudoers.d/*

Phase 7: Logging and Auditing

Centralized Logging

Configure journald to persist logs and forward critical events to a remote log server:

# /etc/systemd/journald.conf
[Journal]
Storage=persistent
Compress=yes
SystemMaxUse=2G
SystemMaxFileSize=100M
MaxRetentionSec=6month
ForwardToSyslog=yes
# /etc/rsyslog.d/remote.conf - forward to central log server
*.* action(type="omfwd" target="logserver.internal" port="6514" protocol="tcp"
      action.resumeRetryCount="-1"
      queue.type="LinkedList"
      queue.size="10000")

Enabling Process Auditing

Install and configure the Linux audit daemon for detailed process tracking:

emerge --ask sys-process/audit
systemctl enable auditd
systemctl start auditd
# /etc/audit/rules.d/audit.rules

# Monitor login events
-w /var/log/tallylog -p wa -k logins
-w /var/log/lastlog -p wa -k logins

# Monitor sudo usage
-w /etc/sudoers -p wa -k sudo
-w /etc/sudoers.d/ -p wa -k sudo

# Monitor SSH configuration changes
-w /etc/ssh/sshd_config -p wa -k ssh_config

# Monitor user/group modifications
-w /etc/passwd -p wa -k identity
-w /etc/group -p wa -k identity
-w /etc/shadow -p wa -k identity

# Monitor cron changes
-w /etc/crontab -p wa -k cron
-w /etc/cron.d/ -p wa -k cron

# Watch for system time changes
-a always,exit -F arch=b64 -S adjtimex,settimeofday,clock_settime -k time-change
# Reload audit rules
augenrules --load

# View audit logs
ausearch -k ssh_config
aureport --summary

Phase 8: Service Isolation and Sandboxing

Systemd Service Hardening

For every custom systemd service, apply sandboxing directives. Create drop-in overrides rather than editing the original unit file:

# /etc/systemd/system/myservice.service.d/hardening.conf

[Service]
# Filesystem isolation
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
PrivateDevices=true

# Network isolation (if service doesn't need network)
# RestrictAddressFamilies=AF_UNIX

# User namespace isolation
PrivateUsers=true

# Kernel protection
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectKernelLogs=true
ProtectControlGroups=true
ProtectClock=true
ProtectHostname=true
ProtectProc=invisible

# Capability restrictions
CapabilityBoundingSet=
AmbientCapabilities=

# Resource limits
LimitNOFILE=1024
LimitNPROC=256

# Memory protection
MemoryDenyWriteExecute=true
LockPersonality=true
RestrictRealtime=true
RestrictSUIDSGID=true
RemoveIPC=true

# System call filtering
SystemCallFilter=@system-service
SystemCallFilter=~@privileged @resources
SystemCallArchitectures=native

# No new privileges
NoNewPrivileges=true
systemctl daemon-reload
systemctl restart myservice

AppArmor or SELinux MAC

Mandatory Access Control adds a layer of policy enforcement beyond traditional file permissions. AppArmor is generally easier to configure on Gentoo:

# Enable AppArmor in kernel and bootloader
# Add to kernel command line: apparmor=1 security=apparmor

# Install AppArmor userspace
emerge --ask sys-libs/libapparmor sys-apps/apparmor-utils

# Enable and start the service
systemctl enable apparmor
systemctl start apparmor

# Check status
aa-status

Create profiles for custom services:

# Generate a profile template
aa-genprof /usr/local/bin/myservice

# Put a profile into complain mode (logging only)
aa-complain /usr/local/bin/myservice

# Switch to enforce mode
aa-enforce /usr/local/bin/myservice

Phase 9: Monitoring and Intrusion Detection

Installing Fail2ban

Fail2ban monitors log files and automatically bans IPs showing malicious behavior:

emerge --ask net-analyzer/fail2ban
# /etc/fail2ban/jail.local

[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 3
banaction = nftables-multiport
backend = systemd

[sshd]
enabled = true
port = ssh
maxretry = 3
bantime = 86400

[nginx-http-auth]
enabled = true
port = http,https
maxretry = 5
bantime = 3600
systemctl enable fail2ban
systemctl start fail2ban
fail2ban-client status
fail2ban-client status sshd

Rootkit Detection

Install rkhunter for periodic rootkit scans:

emerge --ask app-forensics/rkhunter

# Update the database
rkhunter --update
rkhunter --propupd

# Run a scan
rkhunter --check --sk
# /etc/cron.weekly/rkhunter
#!/bin/bash
rkhunter --check --sk --report-warnings-only 2>&1 | \
  mail -s "rkhunter Report $(hostname)" admin@example.com

Best Practices Summary

Conclusion

Securing a Gentoo server is an ongoing process that takes advantage of the distribution's unique source-based architecture. By carefully selecting USE flags, applying compiler hardening, configuring a minimal kernel, enforcing strict access controls, maintaining regular update routines, and layering monitoring tools, you can build a server that is significantly more resistant to attack than a default installation. The checklist above is not exhaustive — every environment has its own threat model — but it provides a strong baseline that addresses the most common attack vectors. Remember that security is a spectrum, not a binary state: the goal is to raise the cost of compromise high enough that attackers move on to easier targets, while ensuring you can detect and respond quickly when something does go wrong. Revisit and refine these measures regularly as your infrastructure evolves and new threats emerge.

— Ad —

Google AdSense will appear here after approval

← Back to all articles