{"id":26536,"date":"2025-06-23T11:38:45","date_gmt":"2025-06-23T09:38:45","guid":{"rendered":"https:\/\/tremhost.com\/blog\/?p=26536"},"modified":"2025-06-23T11:38:45","modified_gmt":"2025-06-23T09:38:45","slug":"securing-your-unmanaged-vps-a-step-by-step-guide","status":"publish","type":"post","link":"https:\/\/tremhost.com\/blog\/securing-your-unmanaged-vps-a-step-by-step-guide\/","title":{"rendered":"Securing your unmanaged VPS: A step-by-step guide.\u00a0"},"content":{"rendered":"<div id=\"bsf_rt_marker\"><\/div><p class=\"first-token\" data-sourcepos=\"1:1-1:28\">Securing an unmanaged VPS is a critical task, as you are solely responsible for its protection. Neglecting security can lead to data breaches, website defacement, DDoS attacks, and your server being used for malicious activities. This guide provides a step-by-step approach to securing your unmanaged Linux VPS.<\/p>\n<p data-sourcepos=\"3:1-3:47\"><strong>Disclaimer:<\/strong> Security is an ongoing process, not a one-time setup. This guide covers essential steps, but continuous monitoring, updates, and vigilance are crucial.<\/p>\n<hr class=\"\" data-sourcepos=\"5:1-5:5\" \/>\n<h3 class=\"\" data-sourcepos=\"7:1-7:18\">Prerequisites:<\/h3>\n<ul data-sourcepos=\"9:1-10:55\">\n<li data-sourcepos=\"9:1-9:85\">An unmanaged Linux VPS (Ubuntu, Debian, CentOS, AlmaLinux, Rocky Linux are common).<\/li>\n<li data-sourcepos=\"10:1-10:55\">SSH client (PuTTY\/MobaXterm for Windows,<span class=\"animating\"> Terminal for macOS\/Linux).<\/span><\/li>\n<li data-sourcepos=\"11:1-11:33\">Basic command-line familiarity.<\/li>\n<li data-sourcepos=\"12:1-13:0\"><strong>Crucially, a working internet connection.<\/strong><\/li>\n<\/ul>\n<hr class=\"\" data-sourcepos=\"14:1-14:5\" \/>\n<h3 class=\"\" data-sourcepos=\"16:1-16:47\">Step 1: Initial Login and Immediate Actions<\/h3>\n<ol data-sourcepos=\"18:1-19:7\">\n<li data-sourcepos=\"18:1-19:7\">\n<p data-sourcepos=\"18:5-19:67\"><strong>Login as Root (Initially):<\/strong> Use the IP address and root password provided by your VPS host.<\/p>\n<div class=\"code-block ng-tns-c736498386-145 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-145 ng-star-inserted\"><span class=\"ng-tns-c736498386-145\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-145 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-145\">\n<div class=\"animated-opacity ng-tns-c736498386-145\">\n<pre class=\"ng-tns-c736498386-145\"><code class=\"code-container formatted ng-tns-c736498386-145\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"21:5-23:32\">ssh root@your_vps_ip_address\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<p data-sourcepos=\"25:5-25:64\">If you get a security warning about the host key, accept it.<\/p>\n<\/li>\n<li data-sourcepos=\"27:1-28:58\">\n<p data-sourcepos=\"27:5-28:58\"><strong>Change Root Password:<\/strong> If your provider gave you a temporary password, change it immediately to a strong, unique one.<\/p>\n<div class=\"code-block ng-tns-c736498386-146 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-146 ng-star-inserted\"><span class=\"ng-tns-c736498386-146\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-146 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-146\">\n<div class=\"animated-opacity ng-tns-c736498386-146\">\n<pre class=\"ng-tns-c736498386-146\"><code class=\"code-container formatted ng-tns-c736498386-146\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"30:5-32:10\">passwd\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<p data-sourcepos=\"34:5-34:76\">Enter the new password twice. Use a mix of uppercase, lowercase, numbers, and symbols.<\/p>\n<\/li>\n<li data-sourcepos=\"36:1-39:18\">\n<p data-sourcepos=\"36:5-37:86\"><strong>Update All System Packages:<\/strong> This patches known vulnerabilities in the operating system and installed software.<\/p>\n<ul data-sourcepos=\"39:7-39:18\">\n<li data-sourcepos=\"39:7-39:18\"><strong>Ubuntu\/Debian:<\/strong>\n<div class=\"code-block ng-tns-c736498386-147 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-147 ng-star-inserted\"><span class=\"ng-tns-c736498386-147\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-147 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-147\">\n<div class=\"animated-opacity ng-tns-c736498386-147\">\n<pre class=\"ng-tns-c736498386-147\"><code class=\"code-container formatted ng-tns-c736498386-147\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"40:9-43:27\">sudo apt update\r\nsudo apt upgrade -y\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/li>\n<li data-sourcepos=\"44:7-48:11\"><strong>CentOS\/AlmaLinux\/Rocky Linux:<\/strong>\n<div class=\"code-block ng-tns-c736498386-148 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-148 ng-star-inserted\"><span class=\"ng-tns-c736498386-148\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-148 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-148\">\n<div class=\"animated-opacity ng-tns-c736498386-148\">\n<pre class=\"ng-tns-c736498386-148\"><code class=\"code-container formatted ng-tns-c736498386-148\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"45:9-48:51\">sudo yum update -y\r\n<span class=\"hljs-comment\"># Or for newer versions: sudo dnf update -y<\/span>\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/li>\n<\/ul>\n<p data-sourcepos=\"50:5-50:37\">Reboot if the kernel was updated:<\/p>\n<div class=\"code-block ng-tns-c736498386-149 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-149 ng-star-inserted\"><span class=\"ng-tns-c736498386-149\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-149 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-149\">\n<div class=\"animated-opacity ng-tns-c736498386-149\">\n<pre class=\"ng-tns-c736498386-149\"><code class=\"code-container formatted ng-tns-c736498386-149\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"52:5-54:15\">sudo reboot\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<p data-sourcepos=\"56:5-56:68\">You&#8217;ll be disconnected; wait a minute or two and then reconnect.<\/p>\n<\/li>\n<\/ol>\n<hr class=\"\" data-sourcepos=\"58:1-58:5\" \/>\n<h3 class=\"\" data-sourcepos=\"60:1-60:49\">Step 2: Create a New Sudo User and Secure SSH<\/h3>\n<p data-sourcepos=\"62:1-62:103\">This is fundamental for daily operations and significantly reduces the risk of direct root compromises.<\/p>\n<ol data-sourcepos=\"64:1-80:32\">\n<li data-sourcepos=\"64:1-78:0\">\n<p data-sourcepos=\"64:5-65:29\"><strong>Create a New Standard User:<\/strong> Choose a strong username.<\/p>\n<ul data-sourcepos=\"67:7-78:0\">\n<li data-sourcepos=\"67:7-71:82\"><strong>Ubuntu\/Debian:<\/strong>\n<div class=\"code-block ng-tns-c736498386-150 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-150 ng-star-inserted\"><span class=\"ng-tns-c736498386-150\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-150 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-150\">\n<div class=\"animated-opacity ng-tns-c736498386-150\">\n<pre class=\"ng-tns-c736498386-150\"><code class=\"code-container formatted ng-tns-c736498386-150\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"68:9-70:29\">adduser your_username\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<p>Follow the prompts to set a strong password and optional user information.<\/li>\n<li data-sourcepos=\"72:7-78:0\"><strong>CentOS\/AlmaLinux\/Rocky Linux:<\/strong>\n<div class=\"code-block ng-tns-c736498386-151 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-151 ng-star-inserted\"><span class=\"ng-tns-c736498386-151\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-151 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-151\">\n<div class=\"animated-opacity ng-tns-c736498386-151\">\n<pre class=\"ng-tns-c736498386-151\"><code class=\"code-container formatted ng-tns-c736498386-151\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"73:9-76:64\">useradd your_username\r\npasswd your_username <span class=\"hljs-comment\"># Set the password for the new user<\/span>\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<p>Follow the prompts.<\/li>\n<\/ul>\n<\/li>\n<li data-sourcepos=\"79:1-80:32\">\n<p data-sourcepos=\"79:5-80:32\"><strong>Grant Sudo Privileges to the New User:<\/strong> This allows <code class=\"\">your_username<\/code> to execute commands with administrative privileges when needed.<\/p>\n<ul data-sourcepos=\"82:7-90:0\">\n<li data-sourcepos=\"82:7-85:11\"><strong>Ubuntu\/Debian:<\/strong>\n<div class=\"code-block ng-tns-c736498386-152 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-152 ng-star-inserted\"><span class=\"ng-tns-c736498386-152\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-152 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-152\">\n<div class=\"animated-opacity ng-tns-c736498386-152\">\n<pre class=\"ng-tns-c736498386-152\"><code class=\"code-container formatted ng-tns-c736498386-152\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"83:9-85:38\">usermod -aG sudo your_username\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/li>\n<li data-sourcepos=\"86:7-90:0\"><strong>CentOS\/AlmaLinux\/Rocky Linux:<\/strong>\n<div class=\"code-block ng-tns-c736498386-153 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-153 ng-star-inserted\"><span class=\"ng-tns-c736498386-153\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-153 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-153\">\n<div class=\"animated-opacity ng-tns-c736498386-153\">\n<pre class=\"ng-tns-c736498386-153\"><code class=\"code-container formatted ng-tns-c736498386-153\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"87:9-89:39\">usermod -aG wheel your_username\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/li>\n<\/ul>\n<\/li>\n<li data-sourcepos=\"91:1-106:0\">\n<p data-sourcepos=\"91:5-92:105\"><strong>Test the New User Login:<\/strong><strong>Crucially, open a NEW SSH session<\/strong> (do not close the root session yet). Log in with your new user:<\/p>\n<div class=\"code-block ng-tns-c736498386-154 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-154 ng-star-inserted\"><span class=\"ng-tns-c736498386-154\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-154 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-154\">\n<div class=\"animated-opacity ng-tns-c736498386-154\">\n<pre class=\"ng-tns-c736498386-154\"><code class=\"code-container formatted ng-tns-c736498386-154\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"94:5-96:41\">ssh your_username@your_vps_ip_address\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<p data-sourcepos=\"98:5-98:52\">Verify <code class=\"\">sudo<\/code> access by trying a simple command:<\/p>\n<div class=\"code-block ng-tns-c736498386-155 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-155 ng-star-inserted\"><span class=\"ng-tns-c736498386-155\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-155 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-155\">\n<div class=\"animated-opacity ng-tns-c736498386-155\">\n<pre class=\"ng-tns-c736498386-155\"><code class=\"code-container formatted ng-tns-c736498386-155\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"100:5-103:50\">sudo apt update <span class=\"hljs-comment\"># Ubuntu\/Debian<\/span>\r\nsudo yum update <span class=\"hljs-comment\"># CentOS\/AlmaLinux\/Rocky Linux<\/span>\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<p data-sourcepos=\"105:5-105:82\">It should ask for your <code class=\"\">your_username<\/code>&#8216;s password. If this works, you&#8217;re good.<\/p>\n<\/li>\n<li data-sourcepos=\"107:1-107:4\">\n<p data-sourcepos=\"107:5-108:67\"><strong>Disable Root SSH Login:<\/strong> This prevents brute-force attacks directly on the root account.<\/p>\n<ul data-sourcepos=\"110:7-124:0\">\n<li data-sourcepos=\"110:7-113:11\"><strong>From your new <code>sudo<\/code> user&#8217;s session:<\/strong>\n<div class=\"code-block ng-tns-c736498386-156 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-156 ng-star-inserted\"><span class=\"ng-tns-c736498386-156\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-156 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-156\">\n<div class=\"animated-opacity ng-tns-c736498386-156\">\n<pre class=\"ng-tns-c736498386-156\"><code class=\"code-container formatted ng-tns-c736498386-156\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"111:9-113:38\">sudo nano \/etc\/ssh\/sshd_config\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/li>\n<li data-sourcepos=\"114:7-117:11\">Find the line <code class=\"\">PermitRootLogin yes<\/code> and change it to:\n<div class=\"code-block ng-tns-c736498386-157 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-157\">\n<div class=\"animated-opacity ng-tns-c736498386-157\">\n<pre class=\"ng-tns-c736498386-157\"><code class=\"code-container formatted ng-tns-c736498386-157 no-decoration-radius\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"115:9-117:26\">PermitRootLogin no\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/li>\n<li data-sourcepos=\"118:7-118:50\">Save and exit (Ctrl+X, Y, Enter for nano).<\/li>\n<li data-sourcepos=\"119:7-122:11\">Restart the SSH service to apply changes:\n<div class=\"code-block ng-tns-c736498386-158 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-158 ng-star-inserted\"><span class=\"ng-tns-c736498386-158\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-158 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-158\">\n<div class=\"animated-opacity ng-tns-c736498386-158\">\n<pre class=\"ng-tns-c736498386-158\"><code class=\"code-container formatted ng-tns-c736498386-158\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"120:9-122:35\">sudo systemctl restart sshd\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/li>\n<li data-sourcepos=\"123:7-124:0\">Now you can close the root SSH session. From now on, you will always log in as <code class=\"\">your_username<\/code>.<\/li>\n<\/ul>\n<\/li>\n<li data-sourcepos=\"125:1-128:40\">\n<p data-sourcepos=\"125:5-126:75\"><strong>Set Up SSH Key Authentication (Highly Recommended):<\/strong> This is much more secure than passwords, as it uses cryptographic keys.<\/p>\n<ul data-sourcepos=\"128:7-128:40\">\n<li data-sourcepos=\"128:7-128:40\"><strong>Generate an SSH Key Pair (on your local machine):<\/strong>\n<ul data-sourcepos=\"129:11-134:165\">\n<li data-sourcepos=\"129:11-133:110\"><strong>macOS\/Linux:<\/strong>\n<div class=\"code-block ng-tns-c736498386-159 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-159 ng-star-inserted\"><span class=\"ng-tns-c736498386-159\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-159 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-159\">\n<div class=\"animated-opacity ng-tns-c736498386-159\">\n<pre class=\"ng-tns-c736498386-159\"><code class=\"code-container formatted ng-tns-c736498386-159\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"130:13-132:37\">ssh-keygen -t rsa -b 4096\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<p>Follow prompts (press Enter for default location, optionally set a passphrase for extra security).<\/li>\n<li data-sourcepos=\"134:11-134:165\"><strong>Windows (PuTTYgen for PuTTY users):<\/strong> Open PuTTYgen, click &#8220;Generate,&#8221; move your mouse randomly, then save both public (<code class=\"\">id_rsa.pub<\/code>) and private (<code class=\"\">id_rsa.ppk<\/code>) keys.<\/li>\n<\/ul>\n<\/li>\n<li data-sourcepos=\"135:7-155:68\"><strong>Copy Public Key to VPS:<\/strong>\n<ul data-sourcepos=\"136:11-155:68\">\n<li data-sourcepos=\"136:11-140:64\"><strong>macOS\/Linux:<\/strong>\n<div class=\"code-block ng-tns-c736498386-160 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-160 ng-star-inserted\"><span class=\"ng-tns-c736498386-160\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-160 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-160\">\n<div class=\"animated-opacity ng-tns-c736498386-160\">\n<pre class=\"ng-tns-c736498386-160\"><code class=\"code-container formatted ng-tns-c736498386-160\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"137:13-139:57\">ssh-copy-id your_username@your_vps_ip_address\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<p>Enter your <code class=\"\">your_username<\/code>&#8216;s password when prompted.<\/li>\n<li data-sourcepos=\"141:11-155:68\"><strong>Windows (PuTTY\/manual):<\/strong>\n<ol data-sourcepos=\"142:13-155:68\">\n<li data-sourcepos=\"142:13-142:74\">Connect to your VPS with your password as <code class=\"\">your_username<\/code>.<\/li>\n<li data-sourcepos=\"143:13-149:19\">Create the <code class=\"\">.ssh<\/code> directory and <code class=\"\">authorized_keys<\/code> file if they don&#8217;t exist:\n<div class=\"code-block ng-tns-c736498386-161 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-161 ng-star-inserted\"><span class=\"ng-tns-c736498386-161\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-161 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-161\">\n<div class=\"animated-opacity ng-tns-c736498386-161\">\n<pre class=\"ng-tns-c736498386-161\"><code class=\"code-container formatted ng-tns-c736498386-161\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"144:17-149:48\">mkdir -p ~\/.ssh\r\nchmod 700 ~\/.ssh\r\ntouch ~\/.ssh\/authorized_keys\r\nchmod 600 ~\/.ssh\/authorized_keys\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/li>\n<li data-sourcepos=\"150:13-150:119\">Open your locally saved <code class=\"\">id_rsa.pub<\/code> file (the public key) with a text editor. Copy its entire content.<\/li>\n<li data-sourcepos=\"151:13-154:19\">On your VPS, edit the <code class=\"\">authorized_keys<\/code> file:\n<div class=\"code-block ng-tns-c736498386-162 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-162 ng-star-inserted\"><span class=\"ng-tns-c736498386-162\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-162 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-162\">\n<div class=\"animated-opacity ng-tns-c736498386-162\">\n<pre class=\"ng-tns-c736498386-162\"><code class=\"code-container formatted ng-tns-c736498386-162\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"152:17-154:43\">nano ~\/.ssh\/authorized_keys\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/li>\n<li data-sourcepos=\"155:13-155:68\">Paste your public key into this file. Save and exit.<\/li>\n<\/ol>\n<\/li>\n<\/ul>\n<\/li>\n<li data-sourcepos=\"156:7-157:71\"><strong>Disable Password Authentication (Optional but Recommended):<\/strong> Once you can log in using your SSH key, disable password logins for even greater security.\n<ul data-sourcepos=\"158:11-172:0\">\n<li data-sourcepos=\"158:11-158:46\"><strong>Login to your VPS via SSH key.<\/strong><\/li>\n<li data-sourcepos=\"159:11-162:15\">Edit <code class=\"\">sshd_config<\/code> again:\n<div class=\"code-block ng-tns-c736498386-163 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-163 ng-star-inserted\"><span class=\"ng-tns-c736498386-163\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-163 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-163\">\n<div class=\"animated-opacity ng-tns-c736498386-163\">\n<pre class=\"ng-tns-c736498386-163\"><code class=\"code-container formatted ng-tns-c736498386-163\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"160:13-162:42\">sudo nano \/etc\/ssh\/sshd_config\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/li>\n<li data-sourcepos=\"163:11-166:15\">Find <code class=\"\">PasswordAuthentication yes<\/code> and change it to:\n<div class=\"code-block ng-tns-c736498386-164 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-164\">\n<div class=\"animated-opacity ng-tns-c736498386-164\">\n<pre class=\"ng-tns-c736498386-164\"><code class=\"code-container formatted ng-tns-c736498386-164 no-decoration-radius\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"164:13-166:37\">PasswordAuthentication no\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/li>\n<li data-sourcepos=\"167:11-170:15\">Save and exit. Restart SSH service:\n<div class=\"code-block ng-tns-c736498386-165 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-165 ng-star-inserted\"><span class=\"ng-tns-c736498386-165\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-165 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-165\">\n<div class=\"animated-opacity ng-tns-c736498386-165\">\n<pre class=\"ng-tns-c736498386-165\"><code class=\"code-container formatted ng-tns-c736498386-165\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"168:13-170:39\">sudo systemctl restart sshd\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/li>\n<li data-sourcepos=\"171:11-172:0\"><strong>Crucially, test this again!<\/strong> Open a <em class=\"\">new<\/em> SSH session and try to log in with your SSH key. If it works, try to log in with just your password (it should fail). If it doesn&#8217;t work with the key, re-enable <code class=\"\">PasswordAuthentication yes<\/code> and troubleshoot.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<hr class=\"\" data-sourcepos=\"173:1-173:5\" \/>\n<h3 class=\"\" data-sourcepos=\"175:1-175:32\">Step 3: Configure a Firewall<\/h3>\n<p data-sourcepos=\"177:1-177:77\">A firewall is your server&#8217;s first line of defense, blocking unwanted traffic.<\/p>\n<ul data-sourcepos=\"179:3-189:52\">\n<li data-sourcepos=\"179:3-189:52\">\n<p class=\"\" data-sourcepos=\"179:5-179:57\"><strong class=\"\">For Ubuntu\/Debian (UFW &#8211; Uncomplicated Firewall):<\/strong><\/p>\n<div class=\"code-block ng-tns-c736498386-166 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-166 ng-star-inserted\"><span class=\"ng-tns-c736498386-166\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-166 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-166\">\n<div class=\"animated-opacity ng-tns-c736498386-166\">\n<pre class=\"ng-tns-c736498386-166\"><code class=\"code-container formatted ng-tns-c736498386-166\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"181:5-188:42\">sudo apt install ufw -y <span class=\"hljs-comment\"># Install if not present<\/span>\r\nsudo ufw allow OpenSSH  <span class=\"hljs-comment\"># Allow SSH (port 22) - ESSENTIAL, so you don't lock yourself out<\/span>\r\nsudo ufw default deny incoming <span class=\"hljs-comment\"># Deny all other incoming by default<\/span>\r\nsudo ufw default allow outgoing <span class=\"hljs-comment\"># Allow all outgoing<\/span>\r\nsudo ufw <span class=\"hljs-built_in\">enable<\/span> <span class=\"hljs-comment\"># Enable the firewall<\/span>\r\nsudo ufw status verbose <span class=\"hljs-comment\"># Check status<\/span>\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<ul data-sourcepos=\"188:7-189:52\">\n<li data-sourcepos=\"188:7-189:52\"><strong>Open ports for services you run:<\/strong>\n<ul data-sourcepos=\"189:11-189:52\">\n<li data-sourcepos=\"189:11-189:52\">HTTP (web server): <code class=\"\">sudo ufw allow http<\/code> or <code class=\"\">sudo ufw allow 80<\/code><\/li>\n<li data-sourcepos=\"192:11-192:82\">HTTPS (SSL web server): <code class=\"\">sudo ufw allow https<\/code> or <code class=\"\">sudo ufw allow 443<\/code><\/li>\n<li data-sourcepos=\"193:11-193:118\">FTP (if used): <code class=\"\">sudo ufw allow 21\/tcp<\/code> (and possibly passive ports) &#8211; <strong>Avoid FTP if possible, use SFTP.<\/strong><\/li>\n<li data-sourcepos=\"194:11-195:0\">MySQL (if accessed remotely): <code class=\"\">sudo ufw allow mysql<\/code> or <code class=\"\">sudo ufw allow 3306<\/code> &#8211; <strong>Only if truly necessary, restrict by IP if possible.<\/strong><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<li data-sourcepos=\"196:3-202:7\">\n<p data-sourcepos=\"196:5-196:53\"><strong>For CentOS\/AlmaLinux\/Rocky Linux (firewalld):<\/strong><\/p>\n<div class=\"code-block ng-tns-c736498386-167 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-167 ng-star-inserted\"><span class=\"ng-tns-c736498386-167\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-167 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-167\">\n<div class=\"animated-opacity ng-tns-c736498386-167\">\n<pre class=\"ng-tns-c736498386-167\"><code class=\"code-container formatted ng-tns-c736498386-167\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"198:5-205:47\">sudo systemctl <span class=\"hljs-built_in\">enable<\/span> firewalld --now <span class=\"hljs-comment\"># Enable and start<\/span>\r\nsudo firewall-cmd --permanent --add-service=ssh <span class=\"hljs-comment\"># Allow SSH<\/span>\r\nsudo firewall-cmd --permanent --add-service=http <span class=\"hljs-comment\"># Allow HTTP<\/span>\r\nsudo firewall-cmd --permanent --add-service=https <span class=\"hljs-comment\"># Allow HTTPS<\/span>\r\nsudo firewall-cmd --reload <span class=\"hljs-comment\"># Apply changes<\/span>\r\nsudo firewall-cmd --list-all <span class=\"hljs-comment\"># Check status<\/span>\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<ul data-sourcepos=\"207:7-207:40\">\n<li data-sourcepos=\"207:7-207:40\"><strong>Open other ports as needed (e.g., MySQL if accessed remotely):<\/strong>\n<div class=\"code-block ng-tns-c736498386-168 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-168 ng-star-inserted\"><span class=\"ng-tns-c736498386-168\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-168 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-168\">\n<div class=\"animated-opacity ng-tns-c736498386-168\">\n<pre class=\"ng-tns-c736498386-168\"><code class=\"code-container formatted ng-tns-c736498386-168\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"208:9-211:34\">sudo firewall-cmd --permanent --add-port=3306\/tcp\r\nsudo firewall-cmd --reload\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<hr class=\"\" data-sourcepos=\"213:1-213:5\" \/>\n<h3 class=\"\" data-sourcepos=\"215:1-215:42\">Step 4: Install and Configure Fail2Ban<\/h3>\n<p data-sourcepos=\"217:1-217:22\">Fail2Ban monitors logs for suspicious activity (like repeated failed login attempts) and automatically bans the offending IP addresses for a set period.<\/p>\n<ul data-sourcepos=\"219:3-219:25\">\n<li data-sourcepos=\"219:3-219:25\">\n<p data-sourcepos=\"219:5-219:25\"><strong>Install Fail2Ban:<\/strong><\/p>\n<ul data-sourcepos=\"220:7-224:28\">\n<li data-sourcepos=\"220:7-223:11\"><strong>Ubuntu\/Debian:<\/strong>\n<div class=\"code-block ng-tns-c736498386-169 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-169 ng-star-inserted\"><span class=\"ng-tns-c736498386-169\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-169 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-169\">\n<div class=\"animated-opacity ng-tns-c736498386-169\">\n<pre class=\"ng-tns-c736498386-169\"><code class=\"code-container formatted ng-tns-c736498386-169\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"222:9-224:36\">sudo apt install fail2ban -y\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/li>\n<li data-sourcepos=\"224:7-224:28\"><strong>CentOS\/AlmaLinux\/Rocky Linux:<\/strong>\n<div class=\"code-block ng-tns-c736498386-170 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-170 ng-star-inserted\"><span class=\"ng-tns-c736498386-170\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-170 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-170\">\n<div class=\"animated-opacity ng-tns-c736498386-170\">\n<pre class=\"ng-tns-c736498386-170\"><code class=\"code-container formatted ng-tns-c736498386-170\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"226:9-229:69\">sudo yum install epel-release -y\r\nsudo yum install fail2ban fail2ban-systemd -y <span class=\"hljs-comment\"># For CentOS 7+<\/span>\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/li>\n<\/ul>\n<\/li>\n<li data-sourcepos=\"231:3-232:66\">\n<p data-sourcepos=\"231:5-232:66\"><strong>Configure Fail2Ban:<\/strong> Create a local configuration file to override defaults without directly modifying the main config.<\/p>\n<div class=\"code-block ng-tns-c736498386-171 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-171 ng-star-inserted\"><span class=\"ng-tns-c736498386-171\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-171 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-171\">\n<div class=\"animated-opacity ng-tns-c736498386-171\">\n<pre class=\"ng-tns-c736498386-171\"><code class=\"code-container formatted ng-tns-c736498386-171\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"234:5-237:38\">sudo cp \/etc\/fail2ban\/jail.conf \/etc\/fail2ban\/jail.local\r\nsudo nano \/etc\/fail2ban\/jail.local\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<ul data-sourcepos=\"239:7-239:59\">\n<li data-sourcepos=\"239:7-239:59\"><strong>Find and modify the <code>[sshd]<\/code> section (or create it if missing for some reason):<\/strong>\n<ul data-sourcepos=\"240:11-241:43\">\n<li data-sourcepos=\"240:11-240:35\">Ensure <code class=\"\">enabled = true<\/code><\/li>\n<li data-sourcepos=\"241:11-241:43\">Consider setting <code class=\"\">bantime<\/code> (e.g., <code class=\"\">bantime = 1h<\/code> for 1 hour ban)<\/li>\n<li data-sourcepos=\"242:11-242:61\">Consider setting <code class=\"\">maxretry<\/code> (e.g., <code class=\"\">maxretry = 3<\/code> for 3 failed attempts)<\/li>\n<\/ul>\n<\/li>\n<li data-sourcepos=\"243:7-243:141\"><strong>Add your IP address to <code>ignoreip<\/code><\/strong> to prevent yourself from being banned (e.g., <code class=\"\">ignoreip = 127.0.0.1 ::1 your_local_ip_address<\/code>).<\/li>\n<li data-sourcepos=\"244:7-245:0\"><strong>Save and exit.<\/strong><\/li>\n<\/ul>\n<\/li>\n<li data-sourcepos=\"246:3-246:4\">\n<p data-sourcepos=\"246:5-246:34\"><strong>Start and Enable Fail2Ban:<\/strong><\/p>\n<div class=\"code-block ng-tns-c736498386-172 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-172 ng-star-inserted\"><span class=\"ng-tns-c736498386-172\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-172 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-172\">\n<div class=\"animated-opacity ng-tns-c736498386-172\">\n<pre class=\"ng-tns-c736498386-172\"><code class=\"code-container formatted ng-tns-c736498386-172\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"248:5-252:49\">sudo systemctl start fail2ban\r\nsudo systemctl <span class=\"hljs-built_in\">enable<\/span> fail2ban\r\nsudo systemctl status fail2ban <span class=\"hljs-comment\"># Check status<\/span>\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<p data-sourcepos=\"254:5-254:69\">You can check banned IPs with <code class=\"\">sudo fail2ban-client status sshd<\/code>.<\/p>\n<\/li>\n<\/ul>\n<hr class=\"\" data-sourcepos=\"256:1-256:5\" \/>\n<h3 class=\"\" data-sourcepos=\"258:1-258:72\">Step 5: Install and Configure Automated Updates (Highly Recommended)<\/h3>\n<p data-sourcepos=\"260:1-260:80\">While you&#8217;ve manually updated, setting up automatic security updates is crucial.<\/p>\n<ul data-sourcepos=\"262:3-262:14\">\n<li data-sourcepos=\"262:3-262:14\">\n<p data-sourcepos=\"262:5-262:44\"><strong>Ubuntu\/Debian (Unattended Upgrades):<\/strong><\/p>\n<div class=\"code-block ng-tns-c736498386-173 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-173 ng-star-inserted\"><span class=\"ng-tns-c736498386-173\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-173 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-173\">\n<div class=\"animated-opacity ng-tns-c736498386-173\">\n<pre class=\"ng-tns-c736498386-173\"><code class=\"code-container formatted ng-tns-c736498386-173\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"264:5-267:60\">sudo apt install unattended-upgrades -y\r\nsudo dpkg-reconfigure --priority=low unattended-upgrades\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<p data-sourcepos=\"269:5-270:79\">Follow the prompts. It&#8217;s usually safe to enable automatic security updates. You can also edit <code class=\"\">\/etc\/apt\/apt.conf.d\/50unattended-upgrades<\/code> to customize.<\/p>\n<\/li>\n<li data-sourcepos=\"272:3-274:67\">\n<p data-sourcepos=\"272:5-272:65\"><strong>CentOS\/AlmaLinux\/Rocky Linux (dnf-automatic or yum-cron):<\/strong><\/p>\n<ul data-sourcepos=\"274:7-274:67\">\n<li data-sourcepos=\"274:7-274:67\"><strong>For dnf-automatic (newer CentOS\/AlmaLinux\/Rocky Linux):<\/strong>\n<div class=\"code-block ng-tns-c736498386-174 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-174 ng-star-inserted\"><span class=\"ng-tns-c736498386-174\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-174 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-174\">\n<div class=\"animated-opacity ng-tns-c736498386-174\">\n<pre class=\"ng-tns-c736498386-174\"><code class=\"code-container formatted ng-tns-c736498386-174\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"275:9-278:41\">sudo dnf install dnf-automatic -y\r\nsudo nano \/etc\/dnf\/automatic.conf\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<p>Edit <code class=\"\">apply_updates = yes<\/code> and <code class=\"\">emit_via = email<\/code> (or other methods).<\/p>\n<div class=\"code-block ng-tns-c736498386-175 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-175 ng-star-inserted\"><span class=\"ng-tns-c736498386-175\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-175 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-175\">\n<div class=\"animated-opacity ng-tns-c736498386-175\">\n<pre class=\"ng-tns-c736498386-175\"><code class=\"code-container formatted ng-tns-c736498386-175\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"280:9-282:55\">sudo systemctl <span class=\"hljs-built_in\">enable<\/span> dnf-automatic.timer --now\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/li>\n<li data-sourcepos=\"283:7-288:34\"><strong>For yum-cron (older CentOS\/RHEL):<\/strong>\n<div class=\"code-block ng-tns-c736498386-176 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-176 ng-star-inserted\"><span class=\"ng-tns-c736498386-176\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-176 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-176\">\n<div class=\"animated-opacity ng-tns-c736498386-176\">\n<pre class=\"ng-tns-c736498386-176\"><code class=\"code-container formatted ng-tns-c736498386-176\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"284:9-287:40\">sudo yum install yum-cron -y\r\nsudo nano \/etc\/yum\/yum-cron.conf\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<p>Set <code class=\"\">apply_updates = yes<\/code> and <code class=\"\">email_to<\/code> if you want email notifications.<\/p>\n<div class=\"code-block ng-tns-c736498386-177 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-177 ng-star-inserted\"><span class=\"ng-tns-c736498386-177\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-177 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-177\">\n<div class=\"animated-opacity ng-tns-c736498386-177\">\n<pre class=\"ng-tns-c736498386-177\"><code class=\"code-container formatted ng-tns-c736498386-177\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"289:9-292:38\">sudo systemctl start yum-cron\r\nsudo systemctl <span class=\"hljs-built_in\">enable<\/span> yum-cron\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<hr class=\"\" data-sourcepos=\"294:1-294:5\" \/>\n<h3 class=\"\" data-sourcepos=\"296:1-296:27\">Step 6: Regular Backups<\/h3>\n<p data-sourcepos=\"298:1-298:83\">This is not a security measure <em class=\"\">per se<\/em>, but it&#8217;s your last line of defense against data loss due to successful attacks, accidental deletion, or hardware failure.<\/p>\n<ul data-sourcepos=\"300:3-300:93\">\n<li data-sourcepos=\"300:3-300:93\"><strong>VPS Provider Backups:<\/strong> Many providers offer automated backup services for an extra fee. This is often the easiest option.<\/li>\n<li data-sourcepos=\"301:3-303:51\"><strong>Manual Backups:<\/strong>\n<ul data-sourcepos=\"302:7-303:51\">\n<li data-sourcepos=\"302:7-302:95\"><code class=\"\">tar<\/code> for archiving files: <code class=\"\">sudo tar -czvf \/backup\/website_backup.tar.gz \/var\/www\/html<\/code><\/li>\n<li data-sourcepos=\"303:7-303:51\"><code class=\"\">mysqldump<\/code> for databases: <code class=\"\">sudo mysqldump -u root -p database_name &gt; \/backup\/database_name.sql<\/code><\/li>\n<\/ul>\n<\/li>\n<li data-sourcepos=\"304:3-304:60\"><strong>Automated Backup Scripts:<\/strong> Write a script to automate <code class=\"\">tar<\/code> and <code class=\"\">mysqldump<\/code>, then schedule it with <code class=\"\">cron<\/code>.<\/li>\n<li data-sourcepos=\"305:3-305:72\"><strong>Offsite Storage:<\/strong> Always store backups off your VPS (e.g., Google Drive, Amazon S3, Dropbox, another server). Use <code class=\"\">rsync<\/code> or <code class=\"\">scp<\/code> to transfer.<\/li>\n<\/ul>\n<hr class=\"\" data-sourcepos=\"307:1-307:5\" \/>\n<h3 class=\"\" data-sourcepos=\"309:1-309:46\">Step 7: Basic Malware and Rootkit Scanning<\/h3>\n<p data-sourcepos=\"311:1-311:51\">Tools to periodically check for malicious software.<\/p>\n<ul data-sourcepos=\"313:3-316:7\">\n<li data-sourcepos=\"313:3-316:7\"><strong>ClamAV (Antivirus):<\/strong>\n<div class=\"code-block ng-tns-c736498386-178 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-178 ng-star-inserted\"><span class=\"ng-tns-c736498386-178\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-178 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-178\">\n<div class=\"animated-opacity ng-tns-c736498386-178\">\n<pre class=\"ng-tns-c736498386-178\"><code class=\"code-container formatted ng-tns-c736498386-178\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"314:5-319:69\">sudo apt install clamav clamav-daemon -y <span class=\"hljs-comment\"># Ubuntu\/Debian<\/span>\r\nsudo yum install epel-release -y &amp;&amp; sudo yum install clamav clamd -y <span class=\"hljs-comment\"># CentOS\/AlmaLinux\/Rocky Linux<\/span>\r\nsudo freshclam <span class=\"hljs-comment\"># Update virus definitions<\/span>\r\nsudo clamscan -r -i \/ <span class=\"hljs-comment\"># Scan entire system (can take a long time)<\/span>\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/li>\n<li data-sourcepos=\"320:3-323:7\"><strong>Chkrootkit (Rootkit Scanner):<\/strong>\n<div class=\"code-block ng-tns-c736498386-179 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-179 ng-star-inserted\"><span class=\"ng-tns-c736498386-179\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-179 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-179\">\n<div class=\"animated-opacity ng-tns-c736498386-179\">\n<pre class=\"ng-tns-c736498386-179\"><code class=\"code-container formatted ng-tns-c736498386-179\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"321:5-325:19\">sudo apt install chkrootkit -y <span class=\"hljs-comment\"># Ubuntu\/Debian<\/span>\r\nsudo yum install chkrootkit -y <span class=\"hljs-comment\"># CentOS\/AlmaLinux\/Rocky Linux (may need EPEL)<\/span>\r\nsudo chkrootkit\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/li>\n<li data-sourcepos=\"326:3-331:7\"><strong>Rootkit Hunter (rkhunter):<\/strong>\n<div class=\"code-block ng-tns-c736498386-180 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-180 ng-star-inserted\"><span class=\"ng-tns-c736498386-180\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-180 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-180\">\n<div class=\"animated-opacity ng-tns-c736498386-180\">\n<pre class=\"ng-tns-c736498386-180\"><code class=\"code-container formatted ng-tns-c736498386-180\" role=\"text\" data-test-id=\"code-content\" data-sourcepos=\"327:5-332:25\">sudo apt install rkhunter -y <span class=\"hljs-comment\"># Ubuntu\/Debian<\/span>\r\nsudo yum install rkhunter -y <span class=\"hljs-comment\"># CentOS\/AlmaLinux\/Rocky Linux (may need EPEL)<\/span>\r\nsudo rkhunter --update\r\nsudo rkhunter --check\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<p><em class=\"\">These tools are for scanning, not real-time protection. Run them periodically.<\/em><\/li>\n<\/ul>\n<hr class=\"\" data-sourcepos=\"335:1-335:5\" \/>\n<h3 class=\"\" data-sourcepos=\"337:1-337:57\">Step 8: Keep Services and Software Updated and Secure<\/h3>\n<ul data-sourcepos=\"339:3-344:11\">\n<li data-sourcepos=\"339:3-341:190\"><strong>Web Server (Apache\/Nginx):<\/strong>\n<ul data-sourcepos=\"340:7-341:190\">\n<li data-sourcepos=\"340:7-340:24\">Keep it updated.<\/li>\n<li data-sourcepos=\"341:7-341:190\">Configure it for security (e.g., disable unused modules, set appropriate permissions for web root, disable directory listings, use <code class=\"\">mod_security<\/code> for Apache or equivalent for Nginx).<\/li>\n<\/ul>\n<\/li>\n<li data-sourcepos=\"342:3-344:11\"><strong>Database Server (MySQL\/MariaDB\/PostgreSQL):<\/strong>\n<ul data-sourcepos=\"343:7-344:11\">\n<li data-sourcepos=\"343:7-343:24\">Keep it updated.<\/li>\n<li data-sourcepos=\"344:7-344:11\">Run <code class=\"\">mysql_secure_installation<\/code> if using MySQL\/MariaDB.<\/li>\n<li data-sourcepos=\"345:7-345:56\">Use strong, unique passwords for database users.<\/li>\n<li data-sourcepos=\"346:7-346:170\">Restrict database access to <code class=\"\">localhost<\/code> if possible (only allow your web server to connect). If remote access is needed, use firewall rules to limit by source IP.<\/li>\n<\/ul>\n<\/li>\n<li data-sourcepos=\"347:3-350:31\"><strong>PHP (if used):<\/strong>\n<ul data-sourcepos=\"348:7-350:31\">\n<li data-sourcepos=\"348:7-348:42\">Use the latest stable PHP version.<\/li>\n<li data-sourcepos=\"349:7-349:189\">Disable dangerous functions in <code class=\"\">php.ini<\/code> (e.g., <code class=\"\">disable_functions = exec, passthru, shell_exec, system, proc_open, popen, curl_exec, curl_multi_exec, parse_ini_file, show_source<\/code>).<\/li>\n<li data-sourcepos=\"350:7-350:31\">Set <code class=\"\">expose_php = Off<\/code>.<\/li>\n<\/ul>\n<\/li>\n<li data-sourcepos=\"351:3-354:0\"><strong>Application Security:<\/strong>\n<ul data-sourcepos=\"352:7-354:0\">\n<li data-sourcepos=\"352:7-352:119\">If running CMS like WordPress, keep core, themes, and plugins updated. Use strong passwords for admin accounts.<\/li>\n<li data-sourcepos=\"353:7-354:0\">Regularly audit code for custom applications.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<hr class=\"\" data-sourcepos=\"355:1-355:5\" \/>\n<h3 class=\"\" data-sourcepos=\"357:1-357:26\">Step 9: Log Monitoring<\/h3>\n<ul data-sourcepos=\"359:3-362:16\">\n<li data-sourcepos=\"359:3-362:16\">Regularly check system logs for unusual activity.\n<ul data-sourcepos=\"360:7-362:16\">\n<li data-sourcepos=\"360:7-360:39\"><code class=\"\">journalctl -u sshd<\/code> (SSH logs)<\/li>\n<li data-sourcepos=\"361:7-361:71\"><code class=\"\">tail -f \/var\/log\/auth.log<\/code> (Ubuntu\/Debian authentication logs)<\/li>\n<li data-sourcepos=\"362:7-362:16\"><code class=\"\">tail -f \/var\/log\/secure<\/code> (CentOS\/AlmaLinux\/Rocky Linux authentication logs)<\/li>\n<li data-sourcepos=\"363:7-363:107\">Web server access and error logs (e.g., <code>\/var\/log\/apache2\/access.log<\/code>, <code>\/var\/log\/nginx\/error.log<\/code>).<\/li>\n<\/ul>\n<\/li>\n<li data-sourcepos=\"364:3-365:0\">Consider using a log management tool (e.g., ELK Stack, Splunk, Graylog) for larger setups.<\/li>\n<\/ul>\n<hr data-sourcepos=\"366:1-366:5\" \/>\n<h3 data-sourcepos=\"368:1-368:35\">Step 10: General Best Practices<\/h3>\n<ul data-sourcepos=\"370:3-370:11\">\n<li data-sourcepos=\"370:3-370:11\"><strong>Use Strong, Unique Passwords:<\/strong> For all accounts and services.<\/li>\n<li data-sourcepos=\"371:3-371:113\"><strong>Principle of Least Privilege:<\/strong> Grant users and services only the minimum permissions they need to function.<\/li>\n<li data-sourcepos=\"372:3-372:68\"><strong>Remove Unused Services\/Software:<\/strong> Reduces the attack surface.<\/li>\n<li data-sourcepos=\"373:3-373:67\"><strong>Stay Informed:<\/strong> Follow security news, especially for your OS and applications.<\/li>\n<li data-sourcepos=\"374:3-375:0\"><strong>Perform Regular Audits:<\/strong> Periodically review your server&#8217;s security configurations.<\/li>\n<\/ul>\n<hr data-sourcepos=\"376:1-376:5\" \/>\n<p data-sourcepos=\"378:1-378:204\">Securing an unmanaged VPS is an ongoing commitment. By following these steps, you&#8217;ll establish a strong security foundation for your server, but remember to stay proactive and adapt as new threats emerge.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Securing an unmanaged VPS is a critical task, as you are solely responsible for its protection. Neglecting security can lead to data breaches, website defacement, DDoS attacks, and your server being used for malicious activities. This guide provides a step-by-step approach to securing your unmanaged Linux VPS. Disclaimer: Security is an ongoing process, not a [&hellip;]<\/p>\n","protected":false},"author":226,"featured_media":26548,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"tdm_status":"","tdm_grid_status":"","footnotes":""},"categories":[163],"tags":[],"class_list":{"0":"post-26536","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","7":"category-hosting"},"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/tremhost.com\/blog\/wp-json\/wp\/v2\/posts\/26536","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tremhost.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tremhost.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tremhost.com\/blog\/wp-json\/wp\/v2\/users\/226"}],"replies":[{"embeddable":true,"href":"https:\/\/tremhost.com\/blog\/wp-json\/wp\/v2\/comments?post=26536"}],"version-history":[{"count":2,"href":"https:\/\/tremhost.com\/blog\/wp-json\/wp\/v2\/posts\/26536\/revisions"}],"predecessor-version":[{"id":26551,"href":"https:\/\/tremhost.com\/blog\/wp-json\/wp\/v2\/posts\/26536\/revisions\/26551"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/tremhost.com\/blog\/wp-json\/wp\/v2\/media\/26548"}],"wp:attachment":[{"href":"https:\/\/tremhost.com\/blog\/wp-json\/wp\/v2\/media?parent=26536"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tremhost.com\/blog\/wp-json\/wp\/v2\/categories?post=26536"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tremhost.com\/blog\/wp-json\/wp\/v2\/tags?post=26536"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}