| name | vps-hetzner-setup-by-orlov |
| description | Official skill for Andriy Orlov's TG Community. Automates full security hardening of a fresh Linux VPS — from raw provider credentials to a locked-down, production-grade server. Covers Hetzner, DigitalOcean, Vultr, Linode, AWS, OVH, and other popular hosting providers. Core features - SSH key pair creation, UFW firewall configuration, fail2ban brute-force protection, sysctl kernel parameters tuning, non-root sudo user provisioning, SSH password and root access lockdown. Ukrainian triggers - "купив VPS/впску/сервер", "налаштувати сервер", "захардити", "підняти ufw/fail2ban", "захистити сервер", "свіжий дебіан/убунту в хмарі". English triggers - "got new server", "secure my VPS", "harden Ubuntu/Debian", "lock down SSH", "server hardening checklist", "audit server security". Safety-first approach - SSH password lockdown is deferred until the very last step, only after key-based access has been fully verified from the user's machine, making accidental self-lockout impossible. Not intended for - application deployment (Docker/Nginx config), DNS or domain management, or routine maintenance of already-secured servers. |
| allowed-tools | Bash,Read,Write,Edit |
VPS Hardening — Initial Server Setup
Transform a brand-new Linux server from raw hosting provider credentials
into a fully secured, production-grade machine. The core safety principle
of this skill: root access and password-based SSH login are locked down
exclusively at the final step, only after the user has successfully
connected using their SSH key. This eliminates the most common beginner
mistake — accidentally getting permanently locked out of your own server.
Procedure at a Glance
Hosting provider credentials (IP + root + password)
→ Identify working mode (Remote vs Local)
→ Create SSH key pair (Remote) / postpone (Local)
→ Log in as root
→ Handle mandatory password reset if required
→ Full system upgrade (noninteractive)
→ Provision non-root user with sudo privileges
→ Deploy SSH public key
→ ⚠ VERIFY new user can log in (MANDATORY CHECKPOINT)
→ Configure firewall (ufw)
→ Apply kernel security parameters (sysctl)
→ Set up time synchronisation + essential packages
→ Create local ~/.ssh/config alias
→ Pre-lockdown security check
→ Build credentials cheat-sheet (guide file)
→ ⚠ Confirm ssh {nickname} is working
→ Install fail2ban + disable root/password SSH access
→ Final confirmation that ssh {nickname} still connects
→ ✅ Server hardened and ready
Step 0: Identify Working Mode and Gather Credentials
Begin by establishing the working mode:
Where is Claude Code currently running?
- On the user's personal computer (Remote mode) — the remote
server will be configured over SSH.
- Directly on the server (Local mode) — commands run on the
same machine. The lockdown sequence requires extra care because
the user hasn't set up an SSH key on their laptop yet.
Remote Mode — Request from the user:
- Server IP address — from the hosting provider's welcome email
- Root password — from the hosting provider's welcome email
- Preferred username — for the new non-root account
- Server alias — for SSH config shortcut (e.g.,
myserver, prod1)
If the user shares the full provider email, parse the relevant values
and confirm them before proceeding.
Detect the user's local operating system (Remote mode)
The local OS determines how Steps 1, 12, and the guide file's
"SSH Key Setup" instructions are generated. Run detection first and
only ask the user if the result is unclear:
uname -s 2>/dev/null
Darwin → macOS (use macOS/Linux command variants)
Linux → Linux (use macOS/Linux command variants)
- Command not recognised / output contains
Microsoft / PowerShell
environment → Windows (use Windows/PowerShell variants)
If automatic detection is inconclusive (e.g. unusual terminal setup),
ask directly: "What OS are you on — macOS, Linux, or Windows?"
In Local mode, the server itself is Linux — detecting the user's
laptop OS is postponed until Step 14, when the user first interacts
with their local machine.
Local Mode — Request from the user:
- Preferred username — for the new non-root account
- Server alias — for future SSH config on the user's laptop
(e.g.,
myserver, prod1)
In Local mode, retrieve the server's public IP automatically:
curl -4 -s ifconfig.me
Working Modes — Step-by-Step Differences
All commands in references/workflow.md and references/lockdown.md
default to Remote mode (run via SSH from the user's laptop).
For Local mode, apply these adjustments:
| Step | Remote Mode (default) | Local Mode |
|---|
| Step 1 | Create SSH key pair on LOCAL machine | SKIP — user generates key on laptop later (Step 14) |
| Step 2 | ssh root@{SERVER_IP} | Already on server. If not root: sudo su - |
| Steps 3–4 | Execute on server over root SSH session | Execute directly (already on server) |
| Step 5 | Copy local public key to server | SKIP — user uploads .pub via SCP later (Step 14) |
| Step 6 | SSH login test from LOCAL: ssh -i ... user@IP | Switch user: su - {username}, then sudo whoami |
| Step 7 | SKIP — lockdown postponed to Step 14 | SKIP — lockdown postponed to Step 14 |
| Steps 8–11 | sudo commands over SSH | sudo commands directly (no SSH wrapper) |
| Step 12 | Write ~/.ssh/config on LOCAL machine | SKIP — user follows guide file instructions (Step 14) |
| Step 13 | Verify with ssh {nickname} | Run checks locally, skip SSH lockdown verification |
| Step 14 | Generate guide + fail2ban + lock SSH | Generate guide → SCP download → key setup on laptop → upload .pub → fail2ban + lock SSH |
In both modes, the final result is the same: key-based SSH
access from the user's laptop via ssh {nickname}, with password
and root login fully disabled.
Reference Files Structure
This SKILL.md contains Step 0 and the safety contract. Detailed
step-by-step instructions are split into two reference files — load
each one as you reach the corresponding phase:
- Steps 1–13 (key creation, root connection, user provisioning,
Step-6 verification, ufw, kernel hardening, time sync, local SSH
config, pre-lockdown audit) → read
references/workflow.md
- Step 14 (deferred lockdown: guide file creation, fail2ban
setup, PermitRootLogin/PasswordAuthentication off, post-lockdown
verification) → read
references/lockdown.md
This separation keeps the initial context lightweight while preserving
the complete procedure on demand. Always process both files
sequentially for a fresh setup — Step 14 must never be omitted,
as it is the cornerstone of the deferred-lockdown safety design.
Mandatory Safety Rules
- NEVER bypass Step 6 (login verification) — skipping this can
lead to permanent lockout.
- NEVER disable root or password access before Step 14 —
Step 14 is the only authorised point for lockdown, after end-to-end
key-based login confirmation.
- NEVER leave passwords in files on the server that aren't
cleaned up at the end. The server-side guide file is deleted in
Step 14L-8.
- If the connection drops after a password change, simply
reconnect — this is expected behaviour.
- If Step 6 fails, resolve the issue before moving forward.
In Remote mode, keep the root session open as a recovery path.
- Create the SSH key BEFORE connecting to the server in Remote
mode — this allows the entire setup to complete in a single pass.
- After Step 6, always use
sudo — never operate as root.
- Steps 7 and 9 are intentionally empty — SSH lockdown and
fail2ban are handled exclusively in Step 14.
Additional Software
Once the base hardening is complete, the user may need extra tools
(Docker, Nginx, Node.js, Certbot, PM2, swap configuration). Refer to
references/optional-software.md.
Security Audit Mode
To audit an existing server's security posture (or to revalidate
after initial setup), refer to references/security-audit.md.
High-Risk Commands
Always request explicit user confirmation before running:
| Command | Severity |
|---|
rm -rf | CRITICAL — irreversible data destruction |
docker system prune | CRITICAL — removes containers, images, volumes |
ufw disable | HIGH — exposes all ports |
systemctl restart sshd | HIGH — may cause lockout (safe only after Step 14 key verification) |
| Database migrations | HIGH — irreversible schema modifications |
--force flag on package managers | MEDIUM-HIGH — can break system dependencies |