# Hetzner VPS Setup

> From a blank server to a secured production-ready machine. Choose how you want to set up your server.

:::tabs
=== Automatically (AI)
### Automatic Setup via AI
Provide your AI assistant with access to this repository. It will automatically perform all checks, configure security, and generate a file with all access credentials (credentials guide) on your computer.

[Open GitHub Repository](https://github.com/orlovvugorivzai/vps-hetzner-setup-by-orlov)

=== Manually
### Variables Preparation
In the commands below, you will need to substitute your values instead of the curly braces:

- `{username}` — the name of your regular user (e.g., `dev`)
- `{nickname}` — a short name for the server for convenience (e.g., `hetzner-main`)
- `{SERVER_IP}` — the public IP address of your new server

:::

## 1. Creating an SSH Key (Local)
Executed on **your computer** (Mac or Linux) BEFORE you connect to the server.

```bash
ssh-keygen -t ed25519 -C "{username}@{nickname}" -f ~/.ssh/{nickname}_key -N ""
cat ~/.ssh/{nickname}_key.pub
```

Copy the output of the second command (it starts with ssh-ed25519 ...). This is your public key.

## 2. Login as Root
Connect to the server using the password Hetzner sent to your email.

> [!WARNING]
> Hetzner may ask you to change the password. Enter the current password, then the new temporary one twice. If the connection drops after this — just connect again using the new password.

```bash
ssh root@{SERVER_IP}
```

## 3. System Update
Updating all packages in non-interactive mode (without grub popups).

```bash
apt update && DEBIAN_FRONTEND=noninteractive NEEDRESTART_MODE=a apt upgrade -y
```

## 4. Creating a User with sudo
Working as root is dangerous. We create a regular user and give them administrator privileges.

```bash
useradd -m -s /bin/bash {username}
echo "{username}:YOUR_SECURE_PASSWORD" | chpasswd
usermod -aG sudo {username}
```

## 5. SSH Key Deployment
We will write your public key, which you copied in Step 1, to the server.

```bash
mkdir -p /home/{username}/.ssh
echo "{PUBLIC_KEY_CONTENT}" > /home/{username}/.ssh/authorized_keys
chmod 700 /home/{username}/.ssh
chmod 600 /home/{username}/.ssh/authorized_keys
chown -R {username}:{username} /home/{username}/.ssh
```

## 6. Login Check
> [!IMPORTANT]
> **MANDATORY CHECKPOINT**
> Do not close the root session! Open a new terminal window on your PC and try to log in using the key. You can only proceed after a successful login.

Check if `sudo` works (the system should ask for the password you set in Step 4 and output "root"):

```bash
ssh -i ~/.ssh/{nickname}_key {username}@{SERVER_IP}
sudo whoami
```

## 7. Firewall (UFW)
Execute all subsequent commands as your new user (with sudo). Setting up the "deny all incoming except SSH, HTTP, and HTTPS" policy.

```bash
sudo apt install -y ufw
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw --force enable
sudo ufw status
```

## 8. Kernel Protection (sysctl)
Applying parameters to protect against network attacks.

```bash
sudo tee /etc/sysctl.d/99-security.conf << 'EOF'
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
EOF
sudo sysctl -p /etc/sysctl.d/99-security.conf
```

## 9. Basic Packages and Time
Accurate time is critical for logs, SSL certificates, and fail2ban.

```bash
sudo apt install -y chrony curl wget git unzip net-tools
sudo systemctl enable chrony
```

## 10. Local SSH Config
Setting up a shortcut **on your local PC** to connect with a short command `ssh {nickname}` in the future.

```bash
mkdir -p ~/.ssh && touch ~/.ssh/config && chmod 600 ~/.ssh/config
cat >> ~/.ssh/config << 'EOF'

Host {nickname}
    HostName {SERVER_IP}
    User {username}
    IdentityFile ~/.ssh/{nickname}_key
    IdentitiesOnly yes
EOF
```

## 11. Security Check
Verify that the short command from the local PC works and that the basic protections are enabled.

```bash
ssh {nickname}
sudo ufw status
sysctl net.ipv4.tcp_syncookies
```

## 12. Final Lockdown
We install protection against brute force (fail2ban) and permanently disable password login and root login.

```bash
sudo apt install -y fail2ban
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
sudo tee /etc/ssh/sshd_config.d/99-hardening.conf << 'EOF'
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
AuthenticationMethods publickey
EOF
sudo sshd -t && sudo systemctl restart ssh
```

> [!TIP]
> Done! The server is fully configured and secured.