{"id":26552,"date":"2025-06-23T11:44:56","date_gmt":"2025-06-23T09:44:56","guid":{"rendered":"https:\/\/tremhost.com\/blog\/?p=26552"},"modified":"2025-06-23T11:44:56","modified_gmt":"2025-06-23T09:44:56","slug":"securing-your-unmanaged-vps-a-step-by-step-guide-2","status":"publish","type":"post","link":"https:\/\/tremhost.com\/blog\/securing-your-unmanaged-vps-a-step-by-step-guide-2\/","title":{"rendered":"Securing your unmanaged VPS: A step-by-step guide.\u00a0"},"content":{"rendered":"<div id=\"bsf_rt_marker\"><\/div><div id=\"chat-history\" class=\"chat-history-scroll-container\">\n<div id=\"2df9bded4e979d61\" class=\"conversation-container message-actions-hover-boundary ng-star-inserted\">\n<div>\n<div class=\"response-container ng-tns-c3275733674-220 response-container-with-gpi ng-star-inserted response-container-has-multiple-responses\">\n<div class=\"presented-response-container ng-tns-c3275733674-220\">\n<div class=\"response-container-content ng-tns-c3275733674-220\">\n<div class=\"response-content ng-tns-c3275733674-220\">\n<div id=\"model-response-message-contentr_2df9bded4e979d61\" class=\"markdown markdown-main-panel stronger enable-updated-hr-color\" dir=\"ltr\">\n<p data-sourcepos=\"1:1-1:311\">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:167\"><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<h3 data-sourcepos=\"7:1-7:18\">Prerequisites:<\/h3>\n<ul data-sourcepos=\"9:3-13:0\">\n<li data-sourcepos=\"9:3-9:87\">An unmanaged Linux VPS (Ubuntu, Debian, CentOS, AlmaLinux, Rocky Linux are common).<\/li>\n<li data-sourcepos=\"10:3-10:71\">SSH client (PuTTY\/MobaXterm for Windows, Terminal for macOS\/Linux).<\/li>\n<li data-sourcepos=\"11:3-11:35\">Basic command-line familiarity.<\/li>\n<li data-sourcepos=\"12:3-13:0\"><strong>Crucially, a working internet connection.<\/strong><\/li>\n<\/ul>\n<h3 data-sourcepos=\"16:1-16:47\">Step 1: Initial Login and Immediate Actions<\/h3>\n<ol data-sourcepos=\"18:1-57:0\">\n<li data-sourcepos=\"18:1-26:0\">\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-259 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-259 ng-star-inserted\"><span class=\"ng-tns-c736498386-259\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-259 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-259\">\n<div class=\"animated-opacity ng-tns-c736498386-259\">\n<pre class=\"ng-tns-c736498386-259\"><code class=\"code-container formatted ng-tns-c736498386-259\" 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-35:0\">\n<p data-sourcepos=\"27:5-28:98\"><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-260 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-260 ng-star-inserted\"><span class=\"ng-tns-c736498386-260\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-260 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-260\">\n<div class=\"animated-opacity ng-tns-c736498386-260\">\n<pre class=\"ng-tns-c736498386-260\"><code class=\"code-container formatted ng-tns-c736498386-260\" 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:90\">Enter the new password twice. Use a mix of uppercase, lowercase, numbers, and symbols.<\/p>\n<\/li>\n<li data-sourcepos=\"36:1-57:0\">\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-49:0\">\n<li data-sourcepos=\"39:7-43:11\"><strong>Ubuntu\/Debian:<\/strong>\n<div class=\"code-block ng-tns-c736498386-261 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-261 ng-star-inserted\"><span class=\"ng-tns-c736498386-261\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-261 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-261\">\n<div class=\"animated-opacity ng-tns-c736498386-261\">\n<pre class=\"ng-tns-c736498386-261\"><code class=\"code-container formatted ng-tns-c736498386-261\" 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-49:0\"><strong>CentOS\/AlmaLinux\/Rocky Linux:<\/strong>\n<div class=\"code-block ng-tns-c736498386-262 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-262 ng-star-inserted\"><span class=\"ng-tns-c736498386-262\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-262 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-262\">\n<div class=\"animated-opacity ng-tns-c736498386-262\">\n<pre class=\"ng-tns-c736498386-262\"><code class=\"code-container formatted ng-tns-c736498386-262\" 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-263 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-263 ng-star-inserted\"><span class=\"ng-tns-c736498386-263\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-263 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-263\">\n<div class=\"animated-opacity ng-tns-c736498386-263\">\n<pre class=\"ng-tns-c736498386-263\"><code class=\"code-container formatted ng-tns-c736498386-263\" 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 data-sourcepos=\"58:1-58:5\" \/>\n<h3 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-172:0\">\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-264 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-264 ng-star-inserted\"><span class=\"ng-tns-c736498386-264\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-264 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-264\">\n<div class=\"animated-opacity ng-tns-c736498386-264\">\n<pre class=\"ng-tns-c736498386-264\"><code class=\"code-container formatted ng-tns-c736498386-264\" 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-265 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-265 ng-star-inserted\"><span class=\"ng-tns-c736498386-265\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-265 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-265\">\n<div class=\"animated-opacity ng-tns-c736498386-265\">\n<pre class=\"ng-tns-c736498386-265\"><code class=\"code-container formatted ng-tns-c736498386-265\" 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-90:0\">\n<p data-sourcepos=\"79:5-80:95\"><strong>Grant Sudo Privileges to the New User:<\/strong> This allows <code>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-266 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-266 ng-star-inserted\"><span class=\"ng-tns-c736498386-266\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-266 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-266\">\n<div class=\"animated-opacity ng-tns-c736498386-266\">\n<pre class=\"ng-tns-c736498386-266\"><code class=\"code-container formatted ng-tns-c736498386-266\" 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-267 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-267 ng-star-inserted\"><span class=\"ng-tns-c736498386-267\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-267 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-267\">\n<div class=\"animated-opacity ng-tns-c736498386-267\">\n<pre class=\"ng-tns-c736498386-267\"><code class=\"code-container formatted ng-tns-c736498386-267\" 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-268 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-268 ng-star-inserted\"><span class=\"ng-tns-c736498386-268\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-268 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-268\">\n<div class=\"animated-opacity ng-tns-c736498386-268\">\n<pre class=\"ng-tns-c736498386-268\"><code class=\"code-container formatted ng-tns-c736498386-268\" 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>sudo<\/code> access by trying a simple command:<\/p>\n<div class=\"code-block ng-tns-c736498386-269 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-269 ng-star-inserted\"><span class=\"ng-tns-c736498386-269\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-269 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-269\">\n<div class=\"animated-opacity ng-tns-c736498386-269\">\n<pre class=\"ng-tns-c736498386-269\"><code class=\"code-container formatted ng-tns-c736498386-269\" 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>your_username<\/code>&#8216;s password. If this works, you&#8217;re good.<\/p>\n<\/li>\n<li data-sourcepos=\"107:1-124:0\">\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-270 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-270 ng-star-inserted\"><span class=\"ng-tns-c736498386-270\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-270 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-270\">\n<div class=\"animated-opacity ng-tns-c736498386-270\">\n<pre class=\"ng-tns-c736498386-270\"><code class=\"code-container formatted ng-tns-c736498386-270\" 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>PermitRootLogin yes<\/code> and change it to:\n<div class=\"code-block ng-tns-c736498386-271 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-271\">\n<div class=\"animated-opacity ng-tns-c736498386-271\">\n<pre class=\"ng-tns-c736498386-271\"><code class=\"code-container formatted ng-tns-c736498386-271 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-272 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-272 ng-star-inserted\"><span class=\"ng-tns-c736498386-272\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-272 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-272\">\n<div class=\"animated-opacity ng-tns-c736498386-272\">\n<pre class=\"ng-tns-c736498386-272\"><code class=\"code-container formatted ng-tns-c736498386-272\" 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>your_username<\/code>.<\/li>\n<\/ul>\n<\/li>\n<li data-sourcepos=\"125:1-172:0\">\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-172:0\">\n<li data-sourcepos=\"128:7-134:180\"><strong>Generate an SSH Key Pair (on your local machine):<\/strong>\n<ul data-sourcepos=\"129:11-134:180\">\n<li data-sourcepos=\"129:11-133:110\"><strong>macOS\/Linux:<\/strong>\n<div class=\"code-block ng-tns-c736498386-273 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-273 ng-star-inserted\"><span class=\"ng-tns-c736498386-273\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-273 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-273\">\n<div class=\"animated-opacity ng-tns-c736498386-273\">\n<pre class=\"ng-tns-c736498386-273\"><code class=\"code-container formatted ng-tns-c736498386-273\" 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:180\"><strong>Windows (PuTTYgen for PuTTY users):<\/strong> Open PuTTYgen, click &#8220;Generate,&#8221; move your mouse randomly, then save both public (<code>id_rsa.pub<\/code>) and private (<code>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-274 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-274 ng-star-inserted\"><span class=\"ng-tns-c736498386-274\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-274 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-274\">\n<div class=\"animated-opacity ng-tns-c736498386-274\">\n<pre class=\"ng-tns-c736498386-274\"><code class=\"code-container formatted ng-tns-c736498386-274\" 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>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>your_username<\/code>.<\/li>\n<li data-sourcepos=\"143:13-149:19\">Create the <code>.ssh<\/code> directory and <code>authorized_keys<\/code> file if they don&#8217;t exist:\n<div class=\"code-block ng-tns-c736498386-275 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-275 ng-star-inserted\"><span class=\"ng-tns-c736498386-275\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-275 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-275\">\n<div class=\"animated-opacity ng-tns-c736498386-275\">\n<pre class=\"ng-tns-c736498386-275\"><code class=\"code-container formatted ng-tns-c736498386-275\" 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>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>authorized_keys<\/code> file:\n<div class=\"code-block ng-tns-c736498386-276 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-276 ng-star-inserted\"><span class=\"ng-tns-c736498386-276\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-276 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-276\">\n<div class=\"animated-opacity ng-tns-c736498386-276\">\n<pre class=\"ng-tns-c736498386-276\"><code class=\"code-container formatted ng-tns-c736498386-276\" 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-172:0\"><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>sshd_config<\/code> again:\n<div class=\"code-block ng-tns-c736498386-277 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-277 ng-star-inserted\"><span class=\"ng-tns-c736498386-277\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-277 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-277\">\n<div class=\"animated-opacity ng-tns-c736498386-277\">\n<pre class=\"ng-tns-c736498386-277\"><code class=\"code-container formatted ng-tns-c736498386-277\" 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>PasswordAuthentication yes<\/code> and change it to:\n<div class=\"code-block ng-tns-c736498386-278 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-278\">\n<div class=\"animated-opacity ng-tns-c736498386-278\">\n<pre class=\"ng-tns-c736498386-278\"><code class=\"code-container formatted ng-tns-c736498386-278 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-279 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-279 ng-star-inserted\"><span class=\"ng-tns-c736498386-279\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-279 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-279\">\n<div class=\"animated-opacity ng-tns-c736498386-279\">\n<pre class=\"ng-tns-c736498386-279\"><code class=\"code-container formatted ng-tns-c736498386-279\" 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>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>PasswordAuthentication yes<\/code> and troubleshoot.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<hr data-sourcepos=\"173:1-173:5\" \/>\n<h3 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-212:0\">\n<li data-sourcepos=\"179:3-195:0\">\n<p data-sourcepos=\"179:5-179:57\"><strong>For Ubuntu\/Debian (UFW &#8211; Uncomplicated Firewall):<\/strong><\/p>\n<div class=\"code-block ng-tns-c736498386-280 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-280 ng-star-inserted\"><span class=\"ng-tns-c736498386-280\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-280 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-280\">\n<div class=\"animated-opacity ng-tns-c736498386-280\">\n<pre class=\"ng-tns-c736498386-280\"><code class=\"code-container formatted ng-tns-c736498386-280\" 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=\"190:7-195:0\">\n<li data-sourcepos=\"190:7-195:0\"><strong>Open ports for services you run:<\/strong>\n<ul data-sourcepos=\"191:11-195:0\">\n<li data-sourcepos=\"191:11-191:75\">HTTP (web server): <code>sudo ufw allow http<\/code> or <code>sudo ufw allow 80<\/code><\/li>\n<li data-sourcepos=\"192:11-192:82\">HTTPS (SSL web server): <code>sudo ufw allow https<\/code> or <code>sudo ufw allow 443<\/code><\/li>\n<li data-sourcepos=\"193:11-193:118\">FTP (if used): <code>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>sudo ufw allow mysql<\/code> or <code>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-212:0\">\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-281 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-281 ng-star-inserted\"><span class=\"ng-tns-c736498386-281\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-281 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-281\">\n<div class=\"animated-opacity ng-tns-c736498386-281\">\n<pre class=\"ng-tns-c736498386-281\"><code class=\"code-container formatted ng-tns-c736498386-281\" 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-212:0\">\n<li data-sourcepos=\"207:7-212:0\"><strong>Open other ports as needed (e.g., MySQL if accessed remotely):<\/strong>\n<div class=\"code-block ng-tns-c736498386-282 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-282 ng-star-inserted\"><span class=\"ng-tns-c736498386-282\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-282 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-282\">\n<div class=\"animated-opacity ng-tns-c736498386-282\">\n<pre class=\"ng-tns-c736498386-282\"><code class=\"code-container formatted ng-tns-c736498386-282\" 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 data-sourcepos=\"213:1-213:5\" \/>\n<h3 data-sourcepos=\"215:1-215:42\">Step 4: Install and Configure Fail2Ban<\/h3>\n<p data-sourcepos=\"217:1-217:152\">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-255:0\">\n<li data-sourcepos=\"219:3-230:0\">\n<p data-sourcepos=\"219:5-219:25\"><strong>Install Fail2Ban:<\/strong><\/p>\n<ul data-sourcepos=\"221:7-230:0\">\n<li data-sourcepos=\"221:7-224:11\"><strong>Ubuntu\/Debian:<\/strong>\n<div class=\"code-block ng-tns-c736498386-283 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-283 ng-star-inserted\"><span class=\"ng-tns-c736498386-283\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-283 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-283\">\n<div class=\"animated-opacity ng-tns-c736498386-283\">\n<pre class=\"ng-tns-c736498386-283\"><code class=\"code-container formatted ng-tns-c736498386-283\" 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=\"225:7-230:0\"><strong>CentOS\/AlmaLinux\/Rocky Linux:<\/strong>\n<div class=\"code-block ng-tns-c736498386-284 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-284 ng-star-inserted\"><span class=\"ng-tns-c736498386-284\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-284 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-284\">\n<div class=\"animated-opacity ng-tns-c736498386-284\">\n<pre class=\"ng-tns-c736498386-284\"><code class=\"code-container formatted ng-tns-c736498386-284\" 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-245:0\">\n<p data-sourcepos=\"231:5-232:102\"><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-285 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-285 ng-star-inserted\"><span class=\"ng-tns-c736498386-285\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-285 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-285\">\n<div class=\"animated-opacity ng-tns-c736498386-285\">\n<pre class=\"ng-tns-c736498386-285\"><code class=\"code-container formatted ng-tns-c736498386-285\" 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-245:0\">\n<li data-sourcepos=\"239:7-242:84\"><strong>Find and modify the <code>[sshd]<\/code> section (or create it if missing for some reason):<\/strong>\n<ul data-sourcepos=\"240:11-242:84\">\n<li data-sourcepos=\"240:11-240:35\">Ensure <code>enabled = true<\/code><\/li>\n<li data-sourcepos=\"241:11-241:76\">Consider setting <code>bantime<\/code> (e.g., <code>bantime = 1h<\/code> for 1 hour ban)<\/li>\n<li data-sourcepos=\"242:11-242:84\">Consider setting <code>maxretry<\/code> (e.g., <code>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>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-255:0\">\n<p data-sourcepos=\"246:5-246:34\"><strong>Start and Enable Fail2Ban:<\/strong><\/p>\n<div class=\"code-block ng-tns-c736498386-286 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-286 ng-star-inserted\"><span class=\"ng-tns-c736498386-286\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-286 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-286\">\n<div class=\"animated-opacity ng-tns-c736498386-286\">\n<pre class=\"ng-tns-c736498386-286\"><code class=\"code-container formatted ng-tns-c736498386-286\" 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>sudo fail2ban-client status sshd<\/code>.<\/p>\n<\/li>\n<\/ul>\n<hr data-sourcepos=\"256:1-256:5\" \/>\n<h3 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-293:0\">\n<li data-sourcepos=\"262:3-271:0\">\n<p data-sourcepos=\"262:5-262:44\"><strong>Ubuntu\/Debian (Unattended Upgrades):<\/strong><\/p>\n<div class=\"code-block ng-tns-c736498386-287 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-287 ng-star-inserted\"><span class=\"ng-tns-c736498386-287\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-287 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-287\">\n<div class=\"animated-opacity ng-tns-c736498386-287\">\n<pre class=\"ng-tns-c736498386-287\"><code class=\"code-container formatted ng-tns-c736498386-287\" 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>\/etc\/apt\/apt.conf.d\/50unattended-upgrades<\/code> to customize.<\/p>\n<\/li>\n<li data-sourcepos=\"272:3-293:0\">\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-293:0\">\n<li data-sourcepos=\"274:7-282:11\"><strong>For dnf-automatic (newer CentOS\/AlmaLinux\/Rocky Linux):<\/strong>\n<div class=\"code-block ng-tns-c736498386-288 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-288 ng-star-inserted\"><span class=\"ng-tns-c736498386-288\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-288 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-288\">\n<div class=\"animated-opacity ng-tns-c736498386-288\">\n<pre class=\"ng-tns-c736498386-288\"><code class=\"code-container formatted ng-tns-c736498386-288\" 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>apply_updates = yes<\/code> and <code>emit_via = email<\/code> (or other methods).<\/p>\n<div class=\"code-block ng-tns-c736498386-289 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-289 ng-star-inserted\"><span class=\"ng-tns-c736498386-289\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-289 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-289\">\n<div class=\"animated-opacity ng-tns-c736498386-289\">\n<pre class=\"ng-tns-c736498386-289\"><code class=\"code-container formatted ng-tns-c736498386-289\" 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-293:0\"><strong>For yum-cron (older CentOS\/RHEL):<\/strong>\n<div class=\"code-block ng-tns-c736498386-290 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-290 ng-star-inserted\"><span class=\"ng-tns-c736498386-290\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-290 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-290\">\n<div class=\"animated-opacity ng-tns-c736498386-290\">\n<pre class=\"ng-tns-c736498386-290\"><code class=\"code-container formatted ng-tns-c736498386-290\" 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>apply_updates = yes<\/code> and <code>email_to<\/code> if you want email notifications.<\/p>\n<div class=\"code-block ng-tns-c736498386-291 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-291 ng-star-inserted\"><span class=\"ng-tns-c736498386-291\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-291 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-291\">\n<div class=\"animated-opacity ng-tns-c736498386-291\">\n<pre class=\"ng-tns-c736498386-291\"><code class=\"code-container formatted ng-tns-c736498386-291\" 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 data-sourcepos=\"294:1-294:5\" \/>\n<h3 data-sourcepos=\"296:1-296:27\">Step 6: Regular Backups<\/h3>\n<p data-sourcepos=\"298:1-298:162\">This is not a security measure <em>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-306:0\">\n<li data-sourcepos=\"300:3-300:128\"><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:104\"><strong>Manual Backups:<\/strong>\n<ul data-sourcepos=\"302:7-303:104\">\n<li data-sourcepos=\"302:7-302:95\"><code>tar<\/code> for archiving files: <code>sudo tar -czvf \/backup\/website_backup.tar.gz \/var\/www\/html<\/code><\/li>\n<li data-sourcepos=\"303:7-303:104\"><code>mysqldump<\/code> for databases: <code>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:113\"><strong>Automated Backup Scripts:<\/strong> Write a script to automate <code>tar<\/code> and <code>mysqldump<\/code>, then schedule it with <code>cron<\/code>.<\/li>\n<li data-sourcepos=\"305:3-306:0\"><strong>Offsite Storage:<\/strong> Always store backups off your VPS (e.g., Google Drive, Amazon S3, Dropbox, another server). Use <code>rsync<\/code> or <code>scp<\/code> to transfer.<\/li>\n<\/ul>\n<hr data-sourcepos=\"307:1-307:5\" \/>\n<h3 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-334:0\">\n<li data-sourcepos=\"313:3-319:7\"><strong>ClamAV (Antivirus):<\/strong>\n<div class=\"code-block ng-tns-c736498386-292 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-292 ng-star-inserted\"><span class=\"ng-tns-c736498386-292\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-292 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-292\">\n<div class=\"animated-opacity ng-tns-c736498386-292\">\n<pre class=\"ng-tns-c736498386-292\"><code class=\"code-container formatted ng-tns-c736498386-292\" 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-325:7\"><strong>Chkrootkit (Rootkit Scanner):<\/strong>\n<div class=\"code-block ng-tns-c736498386-293 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-293 ng-star-inserted\"><span class=\"ng-tns-c736498386-293\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-293 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-293\">\n<div class=\"animated-opacity ng-tns-c736498386-293\">\n<pre class=\"ng-tns-c736498386-293\"><code class=\"code-container formatted ng-tns-c736498386-293\" 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-334:0\"><strong>Rootkit Hunter (rkhunter):<\/strong>\n<div class=\"code-block ng-tns-c736498386-294 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\">\n<div class=\"code-block-decoration header-formatted gds-title-s ng-tns-c736498386-294 ng-star-inserted\"><span class=\"ng-tns-c736498386-294\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c736498386-294 ng-star-inserted\"><\/div>\n<\/div>\n<div class=\"formatted-code-block-internal-container ng-tns-c736498386-294\">\n<div class=\"animated-opacity ng-tns-c736498386-294\">\n<pre class=\"ng-tns-c736498386-294\"><code class=\"code-container formatted ng-tns-c736498386-294\" 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>These tools are for scanning, not real-time protection. Run them periodically.<\/em><\/li>\n<\/ul>\n<h3 data-sourcepos=\"337:1-337:57\">Step 8: Keep Services and Software Updated and Secure<\/h3>\n<ul data-sourcepos=\"339:3-354:0\">\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>mod_security<\/code> for Apache or equivalent for Nginx).<\/li>\n<\/ul>\n<\/li>\n<li data-sourcepos=\"342:3-346:170\"><strong>Database Server (MySQL\/MariaDB\/PostgreSQL):<\/strong>\n<ul data-sourcepos=\"343:7-346:170\">\n<li data-sourcepos=\"343:7-343:24\">Keep it updated.<\/li>\n<li data-sourcepos=\"344:7-344:63\">Run <code>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>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>php.ini<\/code> (e.g., <code>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>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<h3 data-sourcepos=\"357:1-357:26\">Step 9: Log Monitoring<\/h3>\n<ul data-sourcepos=\"359:3-365:0\">\n<li data-sourcepos=\"359:3-363:107\">Regularly check system logs for unusual activity.\n<ul data-sourcepos=\"360:7-363:107\">\n<li data-sourcepos=\"360:7-360:39\"><code>journalctl -u sshd<\/code> (SSH logs)<\/li>\n<li data-sourcepos=\"361:7-361:71\"><code>tail -f \/var\/log\/auth.log<\/code> (Ubuntu\/Debian authentication logs)<\/li>\n<li data-sourcepos=\"362:7-362:84\"><code>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<h3 data-sourcepos=\"368:1-368:35\">Step 10: General Best Practices<\/h3>\n<ul data-sourcepos=\"370:3-375:0\">\n<li data-sourcepos=\"370:3-370:68\"><strong>Use Strong, Unique Passwords:<\/strong> For all accounts and services.<\/li>\n<li data-sourcepos=\"371:3-371:114\"><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:85\"><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<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<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\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":26554,"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-26552","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\/26552","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=26552"}],"version-history":[{"count":1,"href":"https:\/\/tremhost.com\/blog\/wp-json\/wp\/v2\/posts\/26552\/revisions"}],"predecessor-version":[{"id":26555,"href":"https:\/\/tremhost.com\/blog\/wp-json\/wp\/v2\/posts\/26552\/revisions\/26555"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/tremhost.com\/blog\/wp-json\/wp\/v2\/media\/26554"}],"wp:attachment":[{"href":"https:\/\/tremhost.com\/blog\/wp-json\/wp\/v2\/media?parent=26552"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tremhost.com\/blog\/wp-json\/wp\/v2\/categories?post=26552"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tremhost.com\/blog\/wp-json\/wp\/v2\/tags?post=26552"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}