Skip to content

rkruk/gentoo-server-setup

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

84 Commits
 
 
 
 
 
 
 
 

Repository files navigation


GENTOO WEB SERVER
SETUP GUIDE

A comprehensive guide for setting up a secure Gentoo server with Nginx for WordPress hosting.

Table of Contents

Project Description

This project provides a comprehensive guide for setting up a secure Gentoo server with Nginx for WordPress hosting. It covers initial server setup, basic security measures, installation of necessary software, and configuration details to ensure optimal performance and security.

Follow the steps in each section of this guide to set up your server.

Usage Instructions

This guide is intended for setting up a secure Gentoo server for hosting WordPress websites.
Follow the detailed instructions provided in each section to complete the setup.

Contributing Guidelines

Contributions are welcome! Please submit a pull request or open an issue to discuss any changes or improvements.

License Information

This project is licensed under the MIT License. See the LICENSE file for more details.

Installation Instructions

  1. Clone the repository:
git clone https://github.com/rkruk/gentoo-server-setup.git
cd gentoo-server-setup

Initial Server Setup

System Update

# Update Gentoo system
emerge --sync
emerge -avuDN @world

Install essential tools

emerge --ask app-admin/sudo
emerge --ask app-admin/logrotate
emerge --ask app-admin/fail2ban
emerge --ask net-firewall/iptables
emerge --ask net-analyzer/ipset

Create Service User

useradd -m -G users,wheel -s /bin/bash adminuser
passwd adminuser

Basic Security

SSH Configuration

Edit /etc/ssh/sshd_config:

Example SSH configuration changes

Port 2222
PermitRootLogin no
PasswordAuthentication yes

Secure SSH Access

Generate SSH Keys On your local machine, generate an SSH key pair:

ssh-keygen -t rsa -b 4096 -C "[email protected]"

Press Enter to accept the default file location and enter a passphrase for added security.

Copy Public Key to Server

ssh-copy-id -p 2222 [email protected]

Replace 2222 with your SSH port if different, and [email protected] with your server's user and address.

Configure SSH Daemon Edit the SSH daemon configuration file:

nano /etc/ssh/sshd_config

Modify the following settings:

Port 2222
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
AuthorizedKeysFile  .ssh/authorized_keys

Explanation:

Port 2222: Change the SSH port to a custom port for security.
PermitRootLogin no: Disable root login over SSH.
PasswordAuthentication no: Disable password-based authentication, enforcing key-based authentication.
PubkeyAuthentication yes: Ensure key-based authentication is enabled.

Restart SSH Service

rc-service sshd restart

Firewall Configuration

Continue to manage IPTables and IPSet rules to block unwanted traffic.

Update IPTables to Block Additional Countries Create or update the update-country-blocks.sh script to block specific countries.

# /usr/local/sbin/update-country-blocks.sh
#!/bin/bash

# Countries to block
COUNTRIES=("CN" "RU" "BY" "KP" "IR" "IN" "PK" "DZ" "AO" "EG" "NG" "ZA" "KE" "UG" "GH" "TZ" "MA" "TN" "CM" "IQ" "SY")

TMPDIR="/tmp/country-blocks"

# Create temporary directory
mkdir -p $TMPDIR

# Download latest country IP lists
for country in "${COUNTRIES[@]}"; do
    wget -q "https://www.ipdeny.com/ipblocks/data/countries/${country}.zone" -O "$TMPDIR/${country}.zone"
done

# Create ipset for each country
for country in "${COUNTRIES[@]}"; do
    # Destroy existing set if exists
    ipset destroy ${country,,} 2>/dev/null
    # Create new set
    ipset create ${country,,} hash:net
    # Add IPs to set
    while IFS= read -r ip; do
        ipset add ${country,,} $ip
    done < "$TMPDIR/${country}.zone"
done

# Clean up
rm -rf $TMPDIR

echo "Country IP sets updated."

Make the script executable:

chmod +x /usr/local/sbin/update-country-blocks.sh

Enhanced IPTables Configuration Update /etc/iptables/firewall.rules to include the additional countries:

*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
:FAIL2BAN - [0:0]

# Allow loopback
-A INPUT -i lo -j ACCEPT

# Allow established connections
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# Allow SSH on custom port with rate limiting
-A INPUT -p tcp --dport 2222 -m state --state NEW -m recent --set
-A INPUT -p tcp --dport 2222 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 -j DROP
-A INPUT -p tcp --dport 2222 -j ACCEPT

# Allow HTTP and HTTPS
-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -p tcp --dport 443 -j ACCEPT

# Block traffic from specified countries
-A INPUT -m set --match-set cn src -j DROP
-A INPUT -m set --match-set ru src -j DROP
-A INPUT -m set --match-set by src -j DROP
-A INPUT -m set --match-set kp src -j DROP
-A INPUT -m set --match-set ir src -j DROP
-A INPUT -m set --match-set in src -j DROP
-A INPUT -m set --match-set pk src -j DROP
-A INPUT -m set --match-set dz src -j DROP
-A INPUT -m set --match-set ao src -j DROP
-A INPUT -m set --match-set eg src -j DROP
-A INPUT -m set --match-set ng src -j DROP
-A INPUT -m set --match-set za src -j DROP
-A INPUT -m set --match-set ke src -j DROP
-A INPUT -m set --match-set ug src -j DROP
-A INPUT -m set --match-set gh src -j DROP
-A INPUT -m set --match-set tz src -j DROP
-A INPUT -m set --match-set ma src -j DROP
-A INPUT -m set --match-set tn src -j DROP
-A INPUT -m set --match-set cm src -j DROP
-A INPUT -m set --match-set iq src -j DROP
-A INPUT -m set --match-set sy src -j DROP

# ICMP rate limiting
-A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT

# Rate limiting for HTTP(S)
-A INPUT -p tcp --dport 80 -m limit --limit 25/minute --limit-burst 100 -j ACCEPT
-A INPUT -p tcp --dport 443 -m limit --limit 25/minute --limit-burst 100 -j ACCEPT

# Custom chain for fail2ban
-A INPUT -j FAIL2BAN

# Log dropped packets
-A INPUT -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "IPTables Dropped: " --log-level 7

COMMIT

Explanation:

Added ipset rules to block traffic from:

  • India (IN)
  • Pakistan (PK)
  • Russia (RU)
  • Belarus (BY)
  • China (CN)

and selected African countries:

  • Algeria (DZ)
  • Angola (AO)
  • Egypt (EG)
  • Nigeria (NG)
  • South Africa (ZA)
  • Kenya (KE)
  • Uganda (UG)
  • Ghana (GH)
  • Tanzania (TZ)
  • Morocco (MA)
  • Tunisia (TN)
  • Cameroon (CM)
  • Iraq (IQ)
  • Syria (SY)

Schedule IPSet Updates
Automate the update-country-blocks.sh script to run periodically.

Schedule the script to run daily at 1 AM

echo "0 1 * * * root /usr/local/sbin/update-country-blocks.sh" >> /etc/crontab

Monitor Logs

Install Logwatch
Logwatch summarizes logs and sends reports via email.

# Install Logwatch
emerge --ask app-admin/logwatch

Configure Logwatch
Edit Logwatch configuration file:

nano /etc/logwatch/conf/logwatch.conf

Basic Configuration:

MailTo = [email protected]
Detail = High
Service = All
Range = yesterday

Schedule Logwatch Reports
Create a cron job to send daily log summaries.

# Schedule Logwatch to run daily at 6 AM
echo "0 6 * * * root /usr/sbin/logwatch --output mail --mailto [email protected] --detail high" >> /etc/crontab

Enable Two-Factor Authentication (2FA)

Install Google Authenticator PAM Module

# Install Google Authenticator
emerge --ask app-auth/libpam-google-authenticator

Configure PAM for SSH
Edit the SSH PAM configuration:

nano /etc/pam.d/sshd

Add the following line at the top:

auth required pam_google_authenticator.so

Configure SSH Daemon for 2FA
Edit the SSH daemon configuration file:

nano /etc/ssh/sshd_config

Add or modify the following settings:

ChallengeResponseAuthentication yes
AuthenticationMethods publickey,keyboard-interactive

Restart SSH Service

rc-service sshd restart

Configure 2FA for Each User
On the server, for each user, run:

google-authenticator

Follow the prompts to set up 2FA, scanning the QR code with an authenticator app.

Limit User Privileges

Ensure users have the minimum required permissions.

Use sudo for Administrative Tasks
Edit the sudoers file:

visudo

Add the following line to grant sudo privileges to adminuser:

adminuser ALL=(ALL) ALL

Explanation:

Users should perform administrative tasks using sudo rather than logging in as root, minimizing the risk of accidental system-wide changes.

Use Fail2Ban

Protect against brute-force attacks.

Configure Fail2Ban Edit Fail2Ban configuration for SSH:

nano /etc/fail2ban/jail.local

Add the following configuration:

[sshd]
enabled = true
port    = 2222
filter  = sshd
logpath = /var/log/auth.log
maxretry = 5
bantime  = 3600

Start and Enable Fail2Ban

# Start Fail2Ban service
rc-service fail2ban start

# Enable Fail2Ban to start on boot
rc-update add fail2ban default

Nginx Installation

Add USE flags

echo "www-servers/nginx http2 ssl" >> /etc/portage/package.use/nginx

Install Nginx

emerge --ask www-servers/nginx

Directory Structure

mkdir -p /etc/nginx/{sites-available,sites-enabled}
mkdir -p /var/www/example.com
chown -R nginx:nginx /var/www/example.com

Base Configuration Create /etc/nginx/nginx.conf:

user nginx nginx;
worker_processes auto;
worker_rlimit_nofile 65535;

events {
    multi_accept on;
    worker_connections 65535;
}

http {
    charset utf-8;
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    server_tokens off;
    log_not_found off;
    types_hash_max_size 2048;
    types_hash_bucket_size 64;
    client_max_body_size 16M;

    # MIME Types
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    # Logging
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log warn;

    # Gzip Compression
    gzip on;
    gzip_disable "msie6";
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml image/webp image/avif;

    # Brotli Compression
    brotli on;
    brotli_comp_level 6;
    brotli_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml image/webp image/avif;

    # Include Site Configurations
    include /etc/nginx/sites-enabled/*.conf;
}

Enhanced Configuration for Security and Performance
Enforce TLS 1.2 and Higher
Ensure only TLS 1.2 and TLS 1.3 protocols are used.

ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305';
ssl_dhparam /etc/nginx/ssl/dhparam.pem;

Generate Diffie-Hellman parameters

mkdir -p /etc/nginx/ssl
openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048

Redirect All HTTP Traffic to HTTPS

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;

    # Redirect all HTTP requests to HTTPS
    return 301 https://$host$request_uri;
}

Optimize Caching for WordPress

http {
    # FastCGI Cache Path
    fastcgi_cache_path /var/cache/nginx/fastcgi-cache levels=1:2 keys_zone=WORDPRESS:100m inactive=60m;

    # Define Cache Key
    fastcgi_cache_key "$scheme$request_method$host$request_uri";

    # ... existing settings ...

    server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;
        server_name example.com www.example.com;
        root /var/www/example.com;
        index index.php index.html;

        # SSL Configuration
        ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
        ssl_dhparam /etc/nginx/ssl/dhparam.pem;
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_prefer_server_ciphers off;
        ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305';

        # Security Headers
        add_header X-Frame-Options "SAMEORIGIN" always;
        add_header X-XSS-Protection "1; mode=block" always;
        add_header X-Content-Type-Options "nosniff" always;
        add_header Referrer-Policy "no-referrer-when-downgrade" always;
        add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
        add_header Permissions-Policy "camera=(), geolocation=(), microphone=()" always;
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

        # Logging
        access_log /var/log/nginx/sites/example.com/access.log main_ext;
        access_log /var/log/nginx/sites/example.com/security.log security;
        error_log /var/log/nginx/sites/example.com/error.log warn;
        access_log /var/log/nginx/sites/example.com/slow.log main_ext if=$slow_request;

        # Slow request tracking
        map $request_time $slow_request {
            default 0;
            "~^[3-9]|[0-9]{2,}" 1;
        }

        # Block disallowed countries
        if ($allowed_country = no) {
            return 444;
        }

        # PHP Handling with FastCGI Cache
        location ~ \.php$ {
            try_files $uri =404;
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_pass unix:/run/php-fpm/php-fpm.sock;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include fastcgi_params;

            # FastCGI Cache Configuration
            fastcgi_cache WORDPRESS;
            fastcgi_cache_valid 200 60m;
            fastcgi_cache_use_stale error timeout invalid_header updating http_500;
            fastcgi_cache_bypass $skip_cache;
            fastcgi_no_cache $skip_cache;
        }

        # Protect wp-config.php
        location ~ ^/wp-config.php$ {
            deny all;
        }

        # Protect .htaccess and other hidden files
        location ~ /\.(ht|git|env|config|composer\.json|composer\.lock|gitlab-ci\.yml)$ {
            deny all;
            return 404;
        }

        # Block PHP execution in uploads
        location /wp-content/uploads/ {
            location ~ \.php$ {
                deny all;
            }
        }

        # Handle WordPress Login with Rate Limiting
        location = /wp-login.php {
            limit_req zone=wp_login burst=2 nodelay;
            try_files $uri =404;
            include fastcgi_params;
            fastcgi_pass unix:/run/php-fpm/php-fpm.sock;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        }

        # Protect wp-admin with Rate Limiting
        location /wp-admin/ {
            limit_req zone=wp_admin burst=5 nodelay;
            try_files $uri $uri/ /index.php?$args;
        }

        # Static Files with Caching and Referrer Validation
        location ~* \.(gif|jpg|jpeg|png|webp|avif|ico|css|js|woff|woff2|ttf|otf|svg)$ {
            expires 1y;
            add_header Cache-Control "public, no-transform";

            valid_referers none blocked example.com www.example.com ~\.google\. ~\.bing\. ~\.facebook\. ~\.fbcdn\.;
            if ($invalid_referer) {
                return 403;
            }

            access_log off;
        }

        # Image Hotlinking Protection
        location ~* \.(gif|jpg|jpeg|png|webp|avif|ico)$ {
            valid_referers none blocked example.com www.example.com ~\.google\. ~\.bing\. ~\.facebook\. ~\.fbcdn\.;
            if ($invalid_referer) {
                return 403;
            }
            expires 1y;
            add_header Cache-Control "public, no-transform";
            access_log off;
        }

        # Gzip Compression
        gzip on;
        gzip_disable "msie6";
        gzip_vary on;
        gzip_proxied any;
        gzip_comp_level 6;
        gzip_buffers 16 8k;
        gzip_http_version 1.1;
        gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml image/webp image/avif;

        # Brotli Compression
        brotli on;
        brotli_comp_level 6;
        brotli_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml image/webp image/avif;
    }
}

Add Additional Security Enhancements

server {
    # Existing configurations...

    # HTTP Strict Transport Security (HSTS)
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

    # Content Security Policy (CSP)
    add_header Content-Security-Policy "default-src 'self'; script-src 'self' https://trusted.cdn.com; object-src 'none'; frame-ancestors 'none';" always;
    # the https://trusted.cdn.com is an CDN example :D - use whatever you need/want/know.
    # Disable Unnecessary HTTP Methods
    location / {
        if ($request_method !~ ^(GET|HEAD|POST)$ ) {
            return 405;
        }
        # Existing configurations...
    }

    # Limit Request Size
    client_max_body_size 16M;

    # Disable Server Signature
    server_tokens off;

    # Use limit_conn to Prevent Connection Flooding
    limit_conn_zone $binary_remote_addr zone=addr:10m;

    location / {
        limit_conn addr 10;
        # Existing configurations...
    }
}

Enable Nginx Site Configurations with Descriptions
Create symbolic links to enable site configurations and provide short descriptions.

Enable sites by creating symbolic links

ln -s /etc/nginx/sites-available/wordpress.conf /etc/nginx/sites-enabled/wordpress.conf  # Enables WordPress site
ln -s /etc/nginx/sites-available/static-html.conf /etc/nginx/sites-enabled/static-html.conf  # Enables Static HTML site
ln -s /etc/nginx/sites-available/nodejs-app.conf /etc/nginx/sites-enabled/nodejs-app.conf  # Enables Node.js application

Short Descriptions:

WordPress: Link to enable the WordPress website configuration.
Static HTML: Link to enable the Static HTML website configuration.
Node.js App: Link to enable the Node.js application configuration.

Test and Manage Nginx Service
! Ensure configurations are correct and manage the Nginx service using OpenRC !

Test Nginx configuration for syntax errors

nginx -t
# Start Nginx service
rc-service nginx start
# Stop Nginx service
rc-service nginx stop
# Restart Nginx service
rc-service nginx restart
# Reload Nginx configuration without downtime
rc-service nginx reload
# Enable Nginx to start on boot
rc-update add nginx default

Descriptions:

nginx -t: Tests the Nginx configuration for syntax errors and validity.
rc-service nginx start: Starts the Nginx service.
rc-service nginx stop: Stops the Nginx service.
rc-service nginx restart: Restarts the Nginx service.
rc-service nginx reload: Reloads the Nginx configuration without stopping the service.
rc-update add nginx default: Enables Nginx to start automatically on system boot.

Node.js Setup

Install Node.js and npm

# Sync the Portage tree
emerge --sync

# Update the system to ensure all packages are up to date
emerge -avuDN @world

# Install Node.js and npm
emerge --ask dev-lang/nodejs

Configure Node.js Environment

1.Set Up a Dedicated User for Node.js Applications:

useradd -m -G users,wheel -s /bin/bash nodeuser
passwd nodeuser

2.Switch to the Node.js User:

su - nodeuser

3.Initialize a New Node.js Project:

mkdir ~/myapp
cd ~/myapp
npm init -y

Install Essential Node.js Packages

npm install express helmet morgan rate-limiter-flexible
  • express: Web framework for Node.js.
  • helmet: Secures Express apps by setting various HTTP headers.
  • morgan: HTTP request logger middleware.
  • rate-limiter-flexible: Flexible rate limiter for Express.

Create a Secure Express Application
1.Create app.js:

const express = require('express');
const helmet = require('helmet');
const morgan = require('morgan');
const { RateLimiterMemory } = require('rate-limiter-flexible');

const app = express();

// Set security-related HTTP headers
app.use(helmet());

// Setup request logging
app.use(morgan('combined'));

// Rate limiting middleware
const rateLimiter = new RateLimiterMemory({
  points: 100, // Number of points
  duration: 60, // Per second
});

app.use((req, res, next) => {
  rateLimiter.consume(req.ip)
    .then(() => {
      next();
    })
    .catch(() => {
      res.status(429).send('Too Many Requests');
    });
});

app.get('/', (req, res) => {
  res.send('Hello, secure Node.js app!');
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});

2.Secure Application Configuration:

  • Environment Variables: Store sensitive information like API keys and database credentials in environment variables or a .env file using packages like dotenv.
npm install dotenv
require('dotenv').config();
const dbPassword = process.env.DB_PASSWORD;

Set Up Reverse Proxy with Nginx
Configure Nginx as a Reverse Proxy:

nano /etc/nginx/sites-available/nodejs-app.conf

Example Configuration:

server {
    listen 80;
    server_name node.example.com;

    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_cache_bypass $http_upgrade;
    }

    # Optional: Enable SSL
    listen 443 ssl http2;
    ssl_certificate /etc/letsencrypt/live/node.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/node.example.com/privkey.pem;

    include /etc/nginx/snippets/ssl-params.conf;
}

2.Enable the Node.js Site Configuration:

ln -s /etc/nginx/sites-available/nodejs-app.conf /etc/nginx/sites-enabled/nodejs-app.conf

3.Test and Reload Nginx:

nginx -t
rc-service nginx reload

Implement Proper Logging
1.Configure Log Rotation for Application Logs:

nano /etc/logrotate.d/nodejs-app

Example Configuration:

/var/www/myapp/logs/*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    create 0640 nodeuser www-data
    sharedscripts
    postrotate
        systemctl reload nginx > /dev/null 2>/dev/null || true
    endscript
}

2.Use a Process Manager (e.g., PM2) for Enhanced Logging and Management:

npm install pm2 -g
pm2 start app.js
pm2 startup
pm2 save

Note: PM2 can be configured to start on system boot and manage logs effectively.

Security Best Practices

Keep Dependencies Updated:

Regularly update Node.js and all npm packages to patch vulnerabilities.

npm update

Use HTTPS:

  • Always serve your application over HTTPS to encrypt data in transit.
  • Validate and Sanitize Inputs:
  • Ensure all user inputs are validated and sanitized to prevent injection attacks.
  • Implement CORS Policies:
  • Configure Cross-Origin Resource Sharing (CORS) appropriately.
npm install cors
const cors = require('cors');
app.use(cors({
  origin: 'https://yourdomain.com',
  optionsSuccessStatus: 200
}));

Limit Request Sizes:

Prevent denial-of-service (DoS) attacks by limiting the size of incoming requests.

app.use(express.json({ limit: '10kb' }));
app.use(express.urlencoded({ limit: '10kb', extended: true }));

Start and Enable Node.js Application
1.Using PM2:

pm2 start app.js
pm2 startup
pm2 save

2.Using OpenRC:
Create a service script for your Node.js application.

nano /etc/init.d/nodejs-app

Example Service Script:

#!/sbin/openrc-run
command="/usr/bin/node"
command_args="/var/www/myapp/app.js"
name="nodejs-app"
description="Node.js Application"

depend() {
    need net
    after nginx
}

Make the script executable and add it to the default runlevel.

chmod +x /etc/init.d/nodejs-app
rc-update add nodejs-app default
rc-service nodejs-app start



PHP Installation

Install PHP and Extensions

# Add USE flags for PHP
echo "dev-lang/php fpm mysql mysqli pdo_mysql" >> /etc/portage/package.use/php

Install PHP with necessary extensions

emerge --ask dev-lang/php dev-lang/php-extensions

Configure PHP-FPM 1.Copy Default Configuration:

cp /etc/php/fpm/php-fpm.conf.default /etc/php/fpm/php-fpm.conf
cp /etc/php/fpm/www.conf.default /etc/php/fpm/www.conf

2.Edit php-fpm.conf:

nano /etc/php/fpm/php-fpm.conf

Example Configuration:

[global]
pid = /var/run/php-fpm.pid
error_log = /var/log/php-fpm/error.log
include=/etc/php/fpm/pool.d/*.conf

3.Edit www.conf:

nano /etc/php/fpm/www.conf

Example Configuration:

[www]
user = nginx
group = nginx
listen = /run/php-fpm/php-fpm.sock
listen.owner = nginx
listen.group = nginx
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
php_admin_value[error_log] = /var/log/php-fpm/www-error.log
php_admin_flag[log_errors] = on

Start and Enable PHP-FPM

# Start PHP-FPM service
rc-service php-fpm start

# Enable PHP-FPM to start on boot
rc-update add php-fpm default

Verify PHP Installation
Create a phpinfo.php file to verify PHP is working correctly.

echo "<?php phpinfo(); ?>" > /var/www/example.com/phpinfo.php

Navigate to http://example.com/phpinfo.php in your browser. You should see the PHP information page. Remove this file after verification for security reasons.

rm /var/www/example.com/phpinfo.php

Database setup

Install MariaDB

# Install MariaDB
emerge --ask dev-db/mariadb

# Initialize MariaDB
mysql_install_db --user=mysql --basedir=/usr --datadir=/var/lib/mysql

# Start MariaDB service
rc-service mysql start

# Enable MariaDB to start on boot
rc-update add mysql default

Secure MariaDB Installation
Run the secure installation script to improve the security of your MariaDB setup.

mysql_secure_installation

Follow the prompts:

  • Set a strong root password.
  • Remove anonymous users.
  • Disallow root login remotely.
  • Remove test database.
  • Reload privilege tables.

Create a Database and User for WordPress
1.Log into MariaDB as Root:

mysql -u root -p

2.Create Database:

CREATE DATABASE wordpress_db;

3.Create User and Grant Permissions:

CREATE USER 'wp_user'@'localhost' IDENTIFIED BY 'strong_password';
GRANT ALL PRIVILEGES ON wordpress_db.* TO 'wp_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;

Test Database Connection Ensure that the newly created user can connect to the database.

mysql -u wp_user -p wordpress_db

SSL Certificates

Install Certbot

# Install Certbot for obtaining SSL certificates
emerge --ask dev-util/certbot

Obtain SSL Certificate Use Certbot to obtain and install SSL certificates for your domain.

certbot certonly --webroot -w /var/www/example.com -d example.com -d www.example.com

Follow the prompts to complete the certificate issuance.

Configure Nginx to Use SSL Edit your Nginx server block to include SSL settings.

nano /etc/nginx/sites-available/wordpress.conf

Example Configuration:

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name example.com www.example.com;
    root /var/www/example.com;
    index index.php index.html;

    # SSL Configuration
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_dhparam /etc/nginx/ssl/dhparam.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers off;
    ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305';

    # Security Headers
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "no-referrer-when-downgrade" always;
    add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
    add_header Permissions-Policy "camera=(), geolocation=(), microphone=()" always;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

    # Logging
    access_log /var/log/nginx/sites/example.com/access.log main_ext;
    error_log /var/log/nginx/sites/example.com/error.log warn;

    # PHP Handling with FastCGI Cache
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/run/php-fpm/php-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;

        # FastCGI Cache Configuration
        fastcgi_cache WORDPRESS;
        fastcgi_cache_valid 200 60m;
        fastcgi_cache_use_stale error timeout invalid_header updating http_500;
        fastcgi_cache_bypass $skip_cache;
        fastcgi_no_cache $skip_cache;
    }

    # Additional Configurations...
}

Redirect HTTP to HTTPS Ensure all HTTP traffic is redirected to HTTPS by updating your HTTP server block.

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;

    # Redirect all HTTP requests to HTTPS
    return 301 https://$host$request_uri;
}

Test and Reload Nginx

# Test Nginx configuration for syntax errors
nginx -t

# Reload Nginx to apply changes
rc-service nginx reload

Automate Certificate Renewal Certbot sets up a cron job for automatic renewal. Verify the cron job exists.

cat /etc/crontab | grep certbot

If not present, add the following to renew certificates automatically:

echo "0 3 * * * root certbot renew --quiet && rc-service nginx reload" >> /etc/crontab

WordPress Configuration

Download and Install WordPress

# Change to the web root directory
cd /var/www/example.com

# Download the latest WordPress package
wget https://wordpress.org/latest.tar.gz

# Extract the WordPress package
tar -xzvf latest.tar.gz

# Move WordPress files to the root of the web directory
mv wordpress/* .

# Remove unnecessary files
rm -rf wordpress latest.tar.gz

# Set the correct ownership
chown -R nginx:nginx /var/www/example.com

Create WordPress Configuration File 1.Copy the Sample Configuration:

cp wp-config-sample.php wp-config.php

2.Edit wp-config.php:

nano wp-config.php

Update the following settings:

<?php
// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define( 'DB_NAME', 'wordpress_db' );

/** MySQL database username */
define( 'DB_USER', 'wp_user' );

/** MySQL database password */
define( 'DB_PASSWORD', 'strong_password' );

/** MySQL hostname */
define( 'DB_HOST', 'localhost' );

3.Set Unique Keys and Salts:

Visit https://api.wordpress.org/secret-key/1.1/salt/ to generate unique keys, then replace the placeholders in wp-config.php with the generated values.

Configure Nginx for WordPress Permalinks 1.Edit Nginx Server Block:

nano /etc/nginx/sites-available/wordpress.conf

2.Add the Following Location Block Inside the Server Block:

location / {
    try_files $uri $uri/ /index.php?$args;
}

location ~ \.php$ {
    try_files $uri =404;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass unix:/run/php-fpm/php-fpm.sock;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
}

Secure WordPress 1.Set Proper File Permissions:

find /var/www/example.com/ -type d -exec chmod 755 {} \;
find /var/www/example.com/ -type f -exec chmod 644 {} \;

2.Protect wp-config.php:

location ~ ^/wp-config.php$ {
    deny all;
}

Complete WordPress Installation 1.Access WordPress in a Browser:

Navigate to https://example.com and follow the on-screen instructions to complete the installation.

2.Remove Installation Directory (if applicable).

Not necessary in WordPress, but ensure security.

Server Hardening

IPTables Configuration Update IPTables to Block Additional Countries Create or update the update-country-blocks.sh script to block specific countries.

# /usr/local/sbin/update-country-blocks.sh
#!/bin/bash

# Countries to block
COUNTRIES=("CN" "RU" "BY" "KP" "IR" "IN" "PK" "DZ" "AO" "EG" "NG" "ZA" "KE" "UG" "GH" "TZ" "MA" "TN" "CM" "IQ" "SY")

TMPDIR="/tmp/country-blocks"

# Create temporary directory
mkdir -p $TMPDIR

# Download latest country IP lists
for country in "${COUNTRIES[@]}"; do
    wget -q "https://www.ipdeny.com/ipblocks/data/countries/${country}.zone" -O "$TMPDIR/${country}.zone"
done

# Create ipset for each country
for country in "${COUNTRIES[@]}"; do
    # Destroy existing set if exists
    ipset destroy ${country,,} 2>/dev/null
    # Create new set
    ipset create ${country,,} hash:net
    # Add IPs to set
    while IFS= read -r ip; do
        ipset add ${country,,} $ip
    done < "$TMPDIR/${country}.zone"
done

# Clean up
rm -rf $TMPDIR

echo "Country IP sets updated."

Make the script executable:

chmod +x /usr/local/sbin/update-country-blocks.sh

Enhanced IPTables Configuration Update /etc/iptables/firewall.rules to include the additional countries:

*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
:FAIL2BAN - [0:0]

# Whitelist admin IP addresses
-A INPUT -p tcp -s <ADMIN_IP1> --dport 2222 -j ACCEPT
-A INPUT -p tcp -s <ADMIN_IP2> --dport 2222 -j ACCEPT

# Allow loopback
-A INPUT -i lo -j ACCEPT

# Allow established connections
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# Drop invalid packets
-A INPUT -m state --state INVALID -j DROP

# Allow SSH on custom port with rate limiting
-A INPUT -p tcp --dport 2222 -m state --state NEW -m recent --set
-A INPUT -p tcp --dport 2222 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 -j DROP
-A INPUT -p tcp --dport 2222 -j ACCEPT

# Allow HTTP and HTTPS
-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -p tcp --dport 443 -j ACCEPT

# Block traffic from specified countries
-A INPUT -m set --match-set cn src -j DROP
-A INPUT -m set --match-set ru src -j DROP
-A INPUT -m set --match-set by src -j DROP
-A INPUT -m set --match-set kp src -j DROP
-A INPUT -m set --match-set ir src -j DROP
-A INPUT -m set --match-set in src -j DROP
-A INPUT -m set --match-set pk src -j DROP
-A INPUT -m set --match-set dz src -j DROP
-A INPUT -m set --match-set ao src -j DROP
-A INPUT -m set --match-set eg src -j DROP
-A INPUT -m set --match-set ng src -j DROP
-A INPUT -m set --match-set za src -j DROP
-A INPUT -m set --match-set ke src -j DROP
-A INPUT -m set --match-set ug src -j DROP
-A INPUT -m set --match-set gh src -j DROP
-A INPUT -m set --match-set tz src -j DROP
-A INPUT -m set --match-set ma src -j DROP
-A INPUT -m set --match-set tn src -j DROP
-A INPUT -m set --match-set cm src -j DROP
-A INPUT -m set --match-set iq src -j DROP
-A INPUT -m set --match-set sy src -j DROP
-A INPUT -m set --match-set vn src -j DROP
-A INPUT -m set --match-set id src -j DROP
-A INPUT -m set --match-set tr src -j DROP
-A INPUT -m set --match-set bd src -j DROP

# ICMP rate limiting
-A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT

# Rate limiting for SSH
-A INPUT -p tcp --dport 2222 -m limit --limit 10/minute --limit-burst 20 -j ACCEPT

# Rate limiting for HTTP
-A INPUT -p tcp --dport 80 -m limit --limit 50/minute --limit-burst 200 -j ACCEPT

# Rate limiting for HTTPS
-A INPUT -p tcp --dport 443 -m limit --limit 50/minute --limit-burst 200 -j ACCEPT

# Protect against SYN flood
-A INPUT -p tcp ! --syn -m state --state NEW -j DROP
-A INPUT -p tcp --syn -m limit --limit 1/s --limit-burst 4 -j ACCEPT

# Drop invalid packets
-A INPUT -m state --state INVALID -j DROP

# Custom chain for fail2ban
-A INPUT -j FAIL2BAN

# Log dropped traffic
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "IPTables Dropped: " --log-level 4

COMMIT

Explanation:

Added ipset rules to block traffic from:

  • Russia (RU): Known for advanced cyber-attacks and state-sponsored malicious activities.
  • China (CN): High volume of unsolicited traffic, potential source of vulnerability scans.
  • Belarus (BY): Increasing instances of cyber threats with emerging malicious actors.
  • India (IN): Significant number of login attempts and potential for brute-force attacks.
  • Pakistan (PK): Frequent sources of malicious traffic and security threats.
  • Algeria (DZ): Notable for suspicious traffic patterns.
  • Angola (AO): Reports of cyber threats and malicious activities.
  • Egypt (EG): Associated with higher rates of attacks.
  • Nigeria (NG): Common source of spam and malicious traffic.
  • South Africa (ZA): Increasing cyber threats targeting web servers.
  • Kenya (KE): Frequent sources of unsolicited traffic.
  • Uganda (UG): Observed as a source of malicious activities.
  • Ghana (GH): Higher incidence of cyber threats.
  • Tanzania (TZ): Notable for suspicious traffic.
  • Morocco (MA): Increased malicious traffic attempts.
  • Tunisia (TN): Reports of cyber threats.
  • Cameroon (CM): Sources of malicious traffic.
  • Iraq (IQ): Associated with higher cyber-attack rates.
  • Syria (SY): Known for state-sponsored cyber activities.
  • Vietnam (VN): Increasing number of cyber-attacks targeting web servers.
  • Indonesia (ID): Notable for unsolicited traffic and potential threats.
  • Turkey (TR): Reports of cyber threats and attacks.
  • Bangladesh (BD): Sources of malicious traffic activities.

These countries have been identified based on security assessments and observed malicious traffic patterns. Blocking them helps in reducing the attack surface and protecting the server from potential threats.

Can be extended to additional countries.

1. Whitelist Admin IP Addresses

To prevent locking yourself out, whitelist trusted admin IP addresses by allowing SSH connections from these IPs before applying the general SSH rules.

# Whitelist admin IP addresses
-A INPUT -p tcp -s <ADMIN_IP1> --dport 2222 -j ACCEPT
-A INPUT -p tcp -s <ADMIN_IP2> --dport 2222 -j ACCEPT

2.Replace <ADMIN_IP1> and <ADMIN_IP2> with your actual admin IP addresses.

# Drop invalid packets
-A INPUT -m state --state INVALID -j DROP

3. Enable Reverse Path Filtering

Improve protection against IP spoofing by enabling reverse path filtering.

# Enable Reverse Path Filtering
echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter
echo 1 > /proc/sys/net/ipv4/conf/default/rp_filter

To make these changes persistent, add the following lines to /etc/sysctl.conf:

net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1

4. Limit ICMP Types

Allow only specific ICMP types to control network diagnostics traffic.

# Allow specific ICMP types
-A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT
-A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT
-A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT
-A INPUT -p icmp --icmp-type parameter-problem -j ACCEPT
-A INPUT -p icmp -j DROP

5. Enhance Logging for Dropped Traffic

Improve logging to capture more details about dropped packets for better monitoring and analysis.

# Log dropped traffic
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "IPTables Dropped: " --log-level 4

Backup Current iptables Configuration: Before making any changes, backup your existing `firewall.rules` to prevent accidental lockouts.
cp /etc/iptables/firewall.rules /etc/iptables/firewall.rules.backup

Apply and Test Changes Carefully: After updating the rules, apply them and verify connectivity, especially SSH access from whitelisted IPs.

iptables-restore < /etc/iptables/firewall.rules

Use SSH from Whitelisted IPs: Always manage your server from the whitelisted admin IP addresses to maintain uninterrupted access.
Regularly Review and Update Rules: Periodically assess and update your firewall rules to adapt to evolving security threats and administrative needs.
Implement Additional Security Layers: Consider using intrusion detection systems (IDS) like Fail2Ban, regular security audits with Lynis, and keeping all software up to date.

Intrusion Detection Systems

Introduction

Implementing an Intrusion Detection System (IDS) like Snort or Suricata adds an additional layer of security by monitoring network traffic for suspicious activities and potential threats.


Some of these recommendations require powerful hardware with lots of RAM
(Elasticsearch, Kibana, etc.. eat up RAM like cookies)



If you don't have hardware with 32Gb RAM,... just tinker around the monitoring, drop the elasticsearch, kibana, snort, suricata - and you can fit this configuration into the small VPS with the 2-4Gb RAM (for a few websites with moderate traffic).


Option 1: Setting Up Suricata

Install Suricata

emerge --ask net-analyzer/suricata

Configure Suricata
1.Copy Default Configuration:

cp /etc/suricata/suricata.yaml.example /etc/suricata/suricata.yaml

2.Edit suricata.yaml:

nano /etc/suricata/suricata.yaml
  • Interface Configuration: Specify the network interface to monitor.
af-packet:
  - interface: eth0
    threads: auto
    defrag: yes
  • Logging Configuration: Define logging preferences.
outputs:
  - eve-log:
      enabled: yes
      filetype: regular
      filename: /var/log/suricata/eve.json
      types:
        - alert:
            payload: yes
            payload-printable: yes
            packet: yes
            hostnames: yes
            http: yes

Enable and Start Suricata

rc-service suricata start
rc-update add suricata default

Update Ruleset
1.Install suricata-update:

emerge --ask net-analyzer/suricata-update

2.Update and Manage Rules:

suricata-update update-sources
suricata-update
rc-service suricata restart



Option 2: Setting Up Snort

Install Snort

emerge --ask net-analyzer/snort

Configure Snort

  1. Copy Default Configuration:
cp /etc/snort/snort.conf.example /etc/snort/snort.conf

2.Edit snort.conf:

nano /etc/snort/snort.conf

Variable Definitions:
Set network variables.

var HOME_NET 192.168.1.0/24
var EXTERNAL_NET !$HOME_NET

Include Rules:
Include necessary rule files.

include $RULE_PATH/local.rules
include $RULE_PATH/community.rules

Output Configuration:
Define output formats.

output alert_fast: stdout
output alert_syslog: LOG_AUTH LOG_ALERT

Enable and Start Snort

rc-service snort start
rc-update add snort default

Update Ruleset 1.Subscribe to Snort Rules:
Register and obtain a ruleset from Snort.org.

2.Download and Install Rules:

snort-update download-community-rules
snort-update install-community-rules
rc-service snort restart

Integrate IDS with Logging and Alerts

1.Install Elasticsearch, Logstash, and Kibana (ELK Stack) for Log Management:

emerge --ask dev-db/elasticsearch dev-app-analogue/logstash dev-app-analogue/kibana

2.Configure Logstash to Parse IDS Logs:

nano /etc/logstash/conf.d/suricata.conf

Example Configuration for Suricata:

input {
  file {
    path => "/var/log/suricata/eve.json"
    codec => json
  }
}

filter {
  if [event_type] == "alert" {
    mutate { rename => { "src_ip" => "source.ip" } }
    mutate { rename => { "dest_ip" => "destination.ip" } }
    mutate { rename => { "alert.signature" => "event.signature" } }
  }
}

output {
  elasticsearch {
    hosts => ["localhost:9200"]
    index => "suricata-%{+YYYY.MM.dd}"
  }
}

3.Configure Kibana Dashboards for IDS Alerts:

Access Kibana at http://your_server_ip:5601 and set up dashboards to visualize and monitor IDS alerts.

Best Practices for IDS
Regularly Update Rulesets: Keep your IDS rules updated to recognize the latest threats.

suricata-update
rc-service suricata restart
  • Monitor Logs Continuously: Use centralized logging solutions like the ELK Stack to analyze and visualize IDS alerts.
  • Implement Automated Responses: Configure scripts or tools to respond to certain IDS alerts automatically, such as blocking offending IPs.
  • Conduct Regular Audits: Periodically review IDS logs and alerts to assess the security posture and adjust rules as necessary.

Summary
Implementing a robust Intrusion Detection System like Suricata or Snort significantly enhances your server's security by providing real-time monitoring and alerting capabilities. Coupled with proper configuration, regular updates, and integration with logging tools, an IDS serves as a critical component in defending against unauthorized access and malicious activities.

Automated Security Audits and Email Reporting

Install Lynis

Lynis is used for Security Audits.

emerge --ask sys-apps/lynis

Configure Lynis to Perform Periodic Security Audits
Create a cron job to run Lynis weekly and email the results.

Create a script for running Lynis and emailing the report

cat > /usr/local/sbin/lynis_audit.sh <<'EOF'
#!/bin/bash

# Define email variables
EMAIL="[email protected]"
SUBJECT="Weekly Lynis Security Audit Report - $(date +%F)"
REPORT="/var/log/lynis_audit_report.txt"

# Run Lynis audit and save the report
lynis audit system > "$REPORT"

# Send the report via email
mail -s "$SUBJECT" "$EMAIL" < "$REPORT"
EOF

Make the script executable

chmod +x /usr/local/sbin/lynis_audit.sh

Schedule the cron job to run every Sunday at 2 AM

echo "0 2 * * 0 /usr/local/sbin/lynis_audit.sh" >> /etc/crontab

Monitoring Setup

Real-Time Monitoring and Alerts: Utilize Netdata

Install Netdata

emerge --ask net-analyzer/netdata

Start Netdata service

rc-service netdata start

Enable Netdata to start on boot

rc-update add netdata default

Configure Netdata Email Alerts
1.Configure Mail Transfer Agent (MTA):

Ensure an MTA like postfix is installed and configured (as shown in Email Configuration).

Install Postfix

emerge --ask mail-mta/postfix

Configure Postfix

nano /etc/postfix/postfix.conf

Basic Configuration Example:

smtpd_banner = $myhostname ESMTP $mail_name (Gentoo)
myhostname = mail.example.com
mydomain = example.com
myorigin = /etc/mailname
inet_interfaces = all
inet_protocols = ipv4
mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
relayhost =
mynetworks = 127.0.0.0/8
home_mailbox = Maildir/
smtpd_tls_security_level = may
smtpd_tls_cert_file = /etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file = /etc/ssl/private/ssl-cert-snakeoil.key
smtpd_use_tls = yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

2.Configure Netdata Alerts:

Edit Netdata's health configuration to define alert conditions.

nano /etc/netdata/health.d/netdata.conf

Add Alert Definitions:

alarm: high_cpu
on: system.cpu
lookup: average -1m > 80
units: %
every: 10s
warn: 80
crit: 90
info: "High CPU usage detected"
to: [email protected]

alarm: traffic_spike
on: net.in
lookup: average -5m > 1000
units: bps
every: 1m
warn: 1000
crit: 1500
info: "Traffic spike detected"
to: [email protected]

alarm: website_down
on: http.up
lookup: current != 1
units: status
every: 1m
warn: 0
crit: 0
info: "Website is down"
to: [email protected]

3.Restart Netdata to Apply Changes:

rc-service netdata restart

Email Configuration: Set Up a Reliable MTA

Install Postfix

emerge --ask mail-mta/postfix

Configure Postfix

nano /etc/postfix/postfix.conf

Basic Configuration Example:

smtpd_banner = $myhostname ESMTP $mail_name (Gentoo)
myhostname = mail.example.com
mydomain = example.com
myorigin = /etc/mailname
inet_interfaces = all
inet_protocols = ipv4
mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
relayhost =
mynetworks = 127.0.0.0/8
home_mailbox = Maildir/
smtpd_tls_security_level = may
smtpd_tls_cert_file = /etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file = /etc/ssl/private/ssl-cert-snakeoil.key
smtpd_use_tls = yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

Start and Enable Postfix

Start Postfix service

rc-service postfix start

Enable Postfix to start on boot

rc-update add postfix default

Virus Protection

Install ClamAV

emerge --ask app-antivirus/clamav

Update ClamAV database

freshclam

Start ClamAV daemon

rc-service clamav-daemon start

Enable ClamAV to start on boot

rc-update add clamav-daemon default

Configure Regular Virus Scans
Create a cron job to perform daily virus scans and email the results.

Create a script for running ClamAV scans

cat > /usr/local/sbin/clamav_scan.sh <<'EOF'
#!/bin/bash

# Define email variables
EMAIL="[email protected]"
SUBJECT="Daily ClamAV Virus Scan Report - $(date +%F)"
REPORT="/var/log/clamav_scan_report.txt"

# Run ClamAV scan and save the report
clamscan -r /var/www > "$REPORT"

# Send the report via email
mail -s "$SUBJECT" "$EMAIL" < "$REPORT"
EOF

Make the script executable

chmod +x /usr/local/sbin/clamav_scan.sh

Schedule the cron job to run daily at 3 AM

echo "0 3 * * * root /usr/local/sbin/clamav_scan.sh" >> /etc/crontab

Automate IPSet Updates

Ensure that the update-country-blocks.sh script runs periodically to keep IP sets updated.

Already scheduled in Firewall Configuration

Ensure the cron job exists

grep 'update-country-blocks.sh' /etc/crontab || echo "0 1 * * * root /usr/local/sbin/update-country-blocks.sh" >> /etc/crontab

Implement SELinux or AppArmor

For enhanced security policies (optional).

Install AppArmor

emerge --ask sys-apps/apparmor

Start AppArmor service

rc-service apparmor start

Enable AppArmor to start on boot

rc-update add apparmor default

Configure AppArmor
Generate profiles for critical applications or use predefined profiles.

Example: Generate profile for Nginx

aa-genprof nginx

Follow prompts to create and enforce the profile

Final Recommendations

  • Regular Updates: Continuously update your server and all installed software to ensure you have the latest security patches and features.

  • Backup Strategy: Implement a regular backup routine for your website files and databases. Store backups securely and test restoration processes periodically.

  • Monitor Server Performance: Use monitoring tools like Netdata to keep an eye on server performance, resource usage, and potential issues.

  • Enhance Security Practices:

    • Strong Passwords: Enforce the use of strong, unique passwords for all user accounts.
    • Two-Factor Authentication (2FA): Encourage or enforce the use of 2FA for all administrative accounts.
    • Least Privilege Principle: Grant users only the minimum permissions necessary to perform their tasks.
  • Log Management: Regularly review and analyze server logs to detect and respond to suspicious activities promptly.

  • Automate Routine Tasks: Use cron jobs to automate maintenance tasks such as updates, backups, and security scans.

  • Optimize Nginx and PHP-FPM Configuration: Regularly review and optimize your Nginx and PHP-FPM settings for performance and security.

  • Stay Informed: Keep abreast of the latest security threats and best practices related to server administration and WordPress management.

  • Documentation: Maintain comprehensive documentation of your server setup, configurations, and procedures to aid in maintenance and troubleshooting.

  • Disaster Recovery Plan: Develop and regularly update a disaster recovery plan to ensure business continuity in case of server failure or data loss.

  • Regular Security Audits: Use tools like Lynis to perform periodic security audits and address any identified vulnerabilities.

    THE END?

About

Gentoo Web Server Setup

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published