How I setup my VPS servers



This guide walks you through the process of setting up a secure and optimized VPS using Apache, MySQL, PHP, and Cloudflare. It covers everything from system updates to security headers and performance enhancements. Of course, the information presented here is not something new, but it is collected in one place and well organized check list.




Create a Swap File

Swap helps when your system runs out of physical RAM (in case of excessive load or DDoS).

Here’s how to create a 2GB swap file:

sudo fallocate -l 2G /swapfile

sudo chmod 600 /swapfile

sudo mkswap /swapfile

sudo swapon /swapfile


Disable Core Dump Files (Crash Dumps)

Core dumps are generated when applications crash, and they can consume a lot of space. It can take a second to fill an entire drive with crash dumps and they are only useful for professional developers who will actually analyze and reverse them.

Here’s how to disable them system-wide:

Set limits in limits.conf:

sudo nano /etc/security/limits.conf

Add these lines at the end:

* hard core 0
* soft core 0

Disable Core Dumps in sysctl:

sudo nano /etc/sysctl.conf

Add:

fs.suid_dumpable = 0

Run:

sudo sysctl -p

Disable Core Dumps via systemd:

sudo systemctl edit — full systemd-coredump

Find this section:

[Service]

Set:

ExecStart=

ExecStart=/lib/systemd/systemd-coredump — backtrace=no — journal=none — storage=none

Restart service:

sudo systemctl daemon-reexec



Disable IPv6 (Recommended Unless Needed)

You need to disable unused interfaces. Disabling IPv6 will minimize attack vectors and make it easier to develop firewall rules.

Edit sysctl.conf:

sudo nano /etc/sysctl.conf

Add these lines at the end:

net.ipv6.conf.all.disable_ipv6 = 1

net.ipv6.conf.default.disable_ipv6 = 1

net.ipv6.conf.lo.disable_ipv6 = 1

Apply changes:

sudo sysctl -p


Change SSH Port (Optional)

I recommend changing the SSH port from the default one. If you don’t do this, many automated bots will try to bruteforce your server, creating unwanted load, logs and possible security risks. This also helps the attacker identify your server and its structure, what services are you using. Before changing the SSH port, make sure the port is open and your firewall is not blocking it.


To change the port edit SSH config:

sudo nano /etc/ssh/sshd_config

Find the line #Port 22 and change it to something like Port 2289

Optional security tweaks in the same file:

PermitRootLogin no

PasswordAuthentication no

Restart SSH Server:

sudo systemctl restart ssh


Update the Server & Install Essentials

Let’s start with installing the LAMP stack. I prefer Apache instead of Ngnix since it is more classic and has support for .htaccess CMS. Performance does not really play a role for small projects.


Start by updating the server:

sudo apt-get update

sudo apt-get upgrade -y

sudo apt-get dist-upgrade -y

sudo do-release-upgrade


Install the basic stack (Apache + MySQL + PHP):

sudo apt install apache2

sudo apt install mysql-server

sudo apt install php libapache2-mod-php php-mysql

sudo apt install php-gd php-curl php-mbstring php-zip unzip


To see all php extensions (use Q to exit):

apt search php- | less


Create a MySQL Database and User

Enter MySQL:

sudo mysql

Here is an example how to create basic database and a user:

CREATE DATABASE example_database;

CREATE USER ‘example_user’@’%’ IDENTIFIED BY ‘password’;

ALTER USER ‘root’@’localhost’ IDENTIFIED WITH mysql_native_password BY ‘password’;

GRANT ALL ON example_database.* TO ‘example_user’@’%’;

FLUSH PRIVILEGES;

EXIT;


Disable Directory Listing

By default Apache displays all the content inside the directory if no index.html file is present. This possesses great security risks and needs to be disabled by all times.

Edit the Apache config:

sudo nano /etc/apache2/apache2.conf

Find lines with Options Indexes and remove Indexes.

Restart Apache:

sudo service apache2 restart


Hide Apache & PHP Versions

Hiding Apache and PHP versions helps protect your web server. If attackers know exact versions, they can exploit known vulnerabilities. Hiding this info does not affect server performance but adds difficulty for hackers.


To hide Apache version edit apache2.conf:

sudo nano /etc/apache2/apache2.conf

Add the following lines:

ServerSignature Off

ServerTokens Prod

To hide PHP Version edit php.ini:

sudo nano /etc/php/*/apache2/php.ini

Set expose_php = Off

Don’t forget to restart Apache after every manipulation:

sudo service apache2 restart


Configure Apache log rotation (Optional)

Default log rotation for Apache is 14 days which sometimes may be not enough (especially if you process payments). In this case, it makes sense to increase the storage period for logs.


Edit the Apache logrotate config:

sudo nano /etc/logrotate.d/apache2

Replace rotate 14 with the number of days you want (for example rotate 30)


Add .htaccess Rules

A very important step is to set up the htaccess file. While most CMS generate its own htaccess, you still may need to add a few rules to make your server more secure.

Inside your site’s root directory (/var/www/html or similar), create/edit .htaccess, here is a few example rules (this is just an example, never leave important files in www directory):


  RewriteEngine on

  # Block access to configuration files
  
    Require all denied
  

  # Block access to .git directory explicitly (additional protection)
  RedirectMatch 403 /\.git

  # Silent IP ban. When accessing your website, the attacker will get a maintenance page. 
  # What is good about this method is that results are being cached and the hacker still will get a maintenance page after he changes ip.
  RewriteCond %{REMOTE_ADDR} ^111\.111\.111\.111$
  RewriteRule .* /maintenence.html [R=301,L]

  # Block access to backup files (don't rely on it, never leave important files in www dir)
  RewriteRule ^backup/.*\.(sql|rb|py)$ - [F,L,NC]

  # Redirect to construction page when accessing admin directory unless from a specific IP
  RewriteCond %{REMOTE_ADDR} != 111.111.111.111
  RewriteCond %{REQUEST_URI} admin
  RewriteRule .* /construction.php [L]

  # Block access with 404 code to logs directory
  RewriteRule ^logs.*$ - [F,L]




Install ModSecurity (Apache Web Application Firewall)

ModSecurity is a additional firewall that helps detect and block malicious HTTP traffic.

Install and activate:

sudo apt install libapache2-mod-security2 -y

sudo a2enmod security2

sudo systemctl restart apache2

Download default OWASP rules:

cd /etc/modsecurity

sudo git clone https://github.com/coreruleset/coreruleset.git

sudo mv coreruleset /etc/modsecurity/owasp-crs

cp modsecurity.conf-recommended modsecurity.conf

edit /etc/modsecurity/modsecurity.conf

and set SecRuleEngine On

Restart Apache:

sudo systemctl restart apache2

Test to see if it works with simple XSS injection:

http://yoursite.com/?id=1' OR ‘1’=’1

If it is not working check if the module is loaded:

apachectl -M | grep security2

Security HTTP Headers

Make sure to use security headers such as Content-Security-Policy, Referrer-Policy, X-Content-Type-Options, X-Frame-Options, Strict-Transport-Security in your application.

PHP example:

header("Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' telegram.org t.me cdn.jsdelivr.net code.jquery.com; style-src 'self' 'unsafe-inline' cdn.jsdelivr.net; img-src 'self' data: cdn.jsdelivr.net telegra.ph; frame-src 'self' https://www.youtube.com telegram.org t.me cdn.jsdelivr.net;");
header("Referrer-Policy: no-referrer");
header("X-Content-Type-Options: nosniff");
header("X-Frame-Options: SAMEORIGIN");
header("Strict-Transport-Security: max-age=31536000; includeSubDomains; preload");

Clean the Server

Some applications may create lots of useless files, especially if not used right. Even if the system is working properly it is still generating trash and it is very important to clean up trash from time to time. There is a cool little tool called BleachBit, that I like to use.

Install BleachBit to clean up junk:

sudo apt install bleachbit

To clean use:

bleachbit — list | grep -E “[a-z0–9_\-]+\.[a-z0–9_\-]+” | xargs bleachbit — clean

Setup Process Manager & Log Rotation (if needed)

Install Node + PM2:

npm install -g n

n stable

npm install pm2@latest -g

pm2 startup

Enable log rotation for PM2:

pm2 install pm2-logrotate

pm2 set pm2-logrotate:max_size 1G

pm2 set pm2-logrotate:compress true

pm2 set pm2-logrotate:rotateInterval ‘0 * * * *’

☁️ Setup Cloudflare

Cloudflare setup is very important. Not only it provides CDN and free SSL, but also may stop bots and DDoS. However, improper setup provides no protection against DDoS and bots.

Configure your DNS:

Type Name Content Proxy TTL

A domain.com 111.111.11.11 Proxied Auto

A www 111111.11.11 Proxied Auto

other records for mail, validation, etc

Cloudflare SSL/TLS:

  • Always Use HTTPS: ON
  • Minimum TLS Version: TLS 1.0
  • TLS 1.3: ON
  • Opportunistic Encryption: ON
  • Automatic HTTPS Rewrites: ON
  • Authenticated Origin Pulls: ON

Cloudflare Security:

Rate Limiting: Block >100 requests per 10 seconds. (depends on your website)

Custom Rules (WAF):

  • Block bad requests (IP, URL, User-Agent).
  • Block access to secure and unused directories.
  • JS Challenge or CAPTCHA for unknown clients.
  • JS Challenge or CAPTCHA for users from other countries. For example, if you provide service in USA you don't need to be accessible from India.
  • Block HTTP and IPv6. IPv6 is rarely used by average users. It’s often favored for activities like parsing due to its affordability.
  • JS Challenge for low HTTP versions (HTTP /1).
  • Create whitelist for known good bots/IPs.
  • Never use “I’m under attack” mode — use rules instead.

It is very important that you disable disable direct access to your website. Your website should not be accessible by IP. Many web server administrators assume that attacker will not attack their website just because they never publish their IP. However, server IP address can easily be found using resources like Censys, Shodan, Zoomeye, dnshistory. This will allow attacker to bypass Cloudflare filters and attack your website directly.

Cloudflare acts as a reverse proxy, so all legit traffic will come from their IPs. More experianced admins block everything else at the firewall level using Cloudflare’s current IP list like that:

ufw allow from 103.21.244.0/22 to any port 443
ufw allow from 103.21.244.0/22 to any port 80
... etc

The example above works and enough in most cases, however the attack still may attack your website by register another domain on Cloudflare, disabling protection and pointing it to your server’s IP.

Not only you need to block all direct access to your server via IP address, but also block access from any other domains that may point to your server’s IP. To do this:

Edit your default Apache host to deny all requests:


    ServerName _
    
        Require all denied
    

Verify domain in your host:


    Redirect 403 /

Some security advises

Never share your access credentials, instead create separate accounts with limited permissions and enforce strong passwords.

Generally it is a good idea to separate database and web servers. This will improve security and stability.

Test your server with free tools like pentest-tools.com. Stay away from CMS add-ons.

Encrypting may be worth it for protecting sensitive data. Recommended tools:

  • VeraCrypt for full-disk encryption
  • encryptfs for encrypted folders
  • gpg for encrypting files




Tags: web, http, html, server, vps, ddos
Owned by kleskby#1837
Telegram
Close

You have no new notifications.


You have no new messages.