Introduction
As an indie hacker, I often need to quickly set up environments for new app ideas while keeping costs low. I developed a simple, budget-friendly approach that lets me deploy projects efficiently without sacrificing security or scalability. In this guide, I’ll walk you through the steps to set up a secure VPS, covering everything from basic SSH configuration to deploying essential services like Nginx, Docker, and SSL.
For sake of simplicity, I'll assume:
- you have a VPS (I use hetzner's
CX22
with 4GB of ram and 40GB of NVMe SSD, but you can use anything else) - your app's domain is
example.com
- your private and public keys file names are
example
andexample.pub
- your server ip address is
1.1.1.1
- your email is
your-email@email.com
- your server user name is
new_user_name
Don't worry, this will all make sense soon.
1. Connect to Your VPS
Once you have your server up and running, the first step is to connect to it using SSH.
2. Run System Updates
It’s important to make sure your server is running the latest updates for security and performance. Run the following commands to update and upgrade all packages.
This will fetch and install the latest updates for your system packages.
3. Create a New User with Sudo Privileges
This will allow the new user to perform administrative tasks when needed.
4. Set Up SSH for New User
Switch to the new user:
On your local machine, generate a new SSH key pair (if you don’t have one already):
Save it with a name you can remember as you'll need it soon. For example purposes, lets call it "example", as mentioned in the beginning.
On the VPS, create the .ssh directory and paste your public key:
Back at your local machine, assuming your public key is at ~/.ssh/example.pub
:
5. Disable Root Login and Password Authentication
For added security, you should disable root login and password-based authentication.
Provide the correct permissions to your server's .ssh folder:
Then, edit the SSH configuration:
Set the following configurations to disable root login and password authentication:
Edit your host SSH config
6. Enable Firewall (UFW)
Enable UFW to allow only specific traffic:
This ensures that SSH traffic is allowed while securing other ports.
7. Install Fail2Ban for Brute Force Protection
Fail2Ban helps protect your server from brute force attacks. Install it and configure:
Ensure SSHD jail is enabled:
8. Install and Configure Nginx
Install Nginx as your web server:
Then, configure it to act as a reverse proxy for your app. Open the configuration file:
Replace the contents with:
Replace example.com with your actual domain name.
The proxy_pass line should point to the port your application is running on (e.g., port 3000 for a Node.js app).
9. Enable Nginx
To ensure everything is configured properly, test the configuration and restart Nginx:
10. Setup SSL with Certbot
Certbot will automatically configure SSL for your domain and generate the certificates.
Install Certbot and the Nginx plugin:
Note: Before running this step, you need to set you domains and point them to your server's ip (using 1.1.1.1 as an example). If you just did it, wait a few minutes before moving to the next step so that DNS can broadcast.
Type | Host | Answer | TTL | Priority | Options |
---|---|---|---|---|---|
A | example.com |
1.1.1.1 | 600 | ||
A | www.example.com |
1.1.1.1 | 600 | ||
CNAME | *.example.com |
1.1.1.1 | 600 |
Run Certbot for Nginx
When prompted: Enter your email address (for renewal and security notices). Agree to the terms of service. Select the domain(s) you want to enable SSL for (e.g., example.com and www.example.com).
Verify the Nginx Configuration:
It should look similar to this:
(Optional) - Force Https
If Certbot didn’t already set up HTTP-to-HTTPS redirection, you can do this manually by modifying your server block for port 80 to redirect all traffic to HTTPS:
Test SSL and Reload Nginx:
Certbot should automatically reload Nginx after successful installation, but you can test your configuration and reload Nginx manually just to ensure everything is working.
bash
sudo nginx -t
sudo systemctl reload nginx
Test automatic renewal:
Let’s Encrypt certificates are valid for 90 days, but Certbot will automatically renew them for you. To make sure it’s working, you can test the renewal process:
11. Install Docker
Update and install prerequisites
Add Docker GPG key
Add Docker repository
Install Docker
Verify Docker installation
(Optional) Add current user to Docker group
Enable Docker at startup
12. Set Up Unattended Upgrades
Now your VPS is fully secured and configured with essential services like Nginx, SSL, and Docker. You’ve also set up SSH key-based authentication, a firewall, and brute-force protection with Fail2Ban.
In the next post, I'll teach you how to integrate this deployment strategy with a CI/CD pipeline so you can manage your code remotely.
Happy deploying!
Diogo