You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
**One script. No dependencies. Dry-run first. Lockout protection built in.**
4
+
5
+
Idempotent Bash script to harden a Debian/Ubuntu VPS. Run it once on a fresh server or repeatedly to verify and fix drift. Every change is previewed before it's applied, and SSH lockout protection rolls back automatically if something goes wrong.
Idempotent VPS security hardening script for Debian/Ubuntu. Run it once on a fresh VPS or repeatedly to verify and fix drift.
34
+
Most VPS hardening guides are long checklists you follow manually. Most scripts are interactive, not idempotent, and will break if you run them twice. This tool is different:
8
35
9
-
> **New here?** Start with the [Getting Started guide](docs/getting-started.md) — it walks you through the full setup in about 10 minutes.
36
+
-**Idempotent** — checks current state before every action. Safe to re-run anytime.
37
+
-**Dry-run mode** — preview every change before applying. Nothing is modified until you're ready.
38
+
-**Modular** — run all 14 modules or pick only what you need with `--skip` and `--only`.
39
+
-**Lockout protection** — validates SSH config, keys, firewall rules, and AllowUsers before restarting. Auto-rolls back on failure.
40
+
-**Non-interactive** — fully CLI-driven. No prompts. Automate it in CI, cron, or cloud-init.
41
+
-**Single file, zero dependencies** — just Bash. No Python, no Ansible, no agents.
42
+
43
+
---
10
44
11
45
## Quick Start
12
46
@@ -16,7 +50,7 @@ Idempotent VPS security hardening script for Debian/Ubuntu. Run it once on a fre
> **New to VPS security?** The [Getting Started guide](docs/getting-started.md) walks you through everything step by step, including why each module matters.
37
71
38
-
| Flag | Required | Description |
39
-
|------|----------|-------------|
40
-
|`--username USER`| Yes | Non-root user to create/harden |
41
-
|`--ssh-key KEY`| Yes | SSH public key (file path or inline `ssh-*` string) |
42
-
|`--ssh-safety-ip IP`| No | IP to always allow SSH from (safety net before tightening) |
43
-
|`--netbird-key KEY`| No | Netbird setup key for mesh VPN (skips VPN module if omitted) |
44
-
|`--timezone TZ`| No | System timezone (e.g. `Europe/Amsterdam`, `UTC`) |
45
-
|`--hostname NAME`| No | Set system hostname |
46
-
|`--auto-reboot`| No | Enable automatic reboot after kernel updates |
47
-
|`--openclaw-skill`| No | Add `server-report` skill to an OpenClaw bot (requires OpenClaw installed) |
48
-
|`--skip MOD[,MOD]`| No | Comma-separated modules to skip |
49
-
|`--only MOD[,MOD]`| No | Run only specified modules |
50
-
|`--dry-run`| No | Preview changes without applying them |
51
-
|`--config FILE`| No | Load parameters from a `KEY=VALUE` file |
52
-
|`--no-color`| No | Disable colored output (useful for logging) |
53
-
|`--verbose`| No | Show command output instead of redirecting to log |
54
-
|`--version`| No | Print version and exit |
55
-
|`-h`, `--help`| No | Show usage help |
72
+
---
56
73
57
-
## Modules
58
-
59
-
Modules run in this order. Each is idempotent — safe to re-run.
sudo server-report full # Full logwatch report (today)
110
139
```
111
140
112
-
All output is plain text with no colors — safe for piping, logging, or chatbot consumption. Commands degrade gracefully if tools (auditd, logwatch, fail2ban) are not installed.
141
+
All output is plain text — no colors, no control codes. Safe for piping, logging, or chatbot consumption. Commands degrade gracefully if tools (auditd, logwatch, fail2ban) are not installed.
142
+
143
+
**OpenClaw bot integration:** Add `--openclaw-skill` to automatically configure server-report as a chatbot skill, so your bot can answer "how's the server?" on demand.
144
+
145
+
---
146
+
147
+
## Parameters
148
+
149
+
| Flag | Required | Description |
150
+
|------|----------|-------------|
151
+
|`--username USER`| Yes | Non-root user to create/harden |
152
+
|`--ssh-key KEY`| Yes | SSH public key (file path or inline `ssh-*` string) |
153
+
|`--ssh-safety-ip IP`| No | IP to always allow SSH from (safety net before tightening) |
154
+
|`--netbird-key KEY`| No | Netbird setup key for mesh VPN (skips VPN module if omitted) |
155
+
|`--timezone TZ`| No | System timezone (e.g. `Europe/Amsterdam`, `UTC`) |
156
+
|`--hostname NAME`| No | Set system hostname |
157
+
|`--auto-reboot`| No | Enable automatic reboot after kernel updates |
158
+
|`--openclaw-skill`| No | Add `server-report` skill to an OpenClaw bot |
159
+
|`--skip MOD[,MOD]`| No | Comma-separated modules to skip |
160
+
|`--only MOD[,MOD]`| No | Run only specified modules |
161
+
|`--dry-run`| No | Preview changes without applying them |
162
+
|`--config FILE`| No | Load parameters from a `KEY=VALUE` file |
163
+
|`--no-color`| No | Disable colored output |
164
+
|`--verbose`| No | Show command output instead of redirecting to log |
165
+
|`--version`| No | Print version and exit |
166
+
|`-h`, `--help`| No | Show usage help |
167
+
168
+
---
113
169
114
170
## Config File
115
171
116
-
Instead of passing flags, use a config file:
172
+
Instead of passing flags, use a config file for repeatable setups:
117
173
118
174
```bash
119
-
sudo vps-harden --config config.env
175
+
sudo vps-harden --config /root/harden.env
120
176
```
121
177
122
178
See [`examples/config.env`](examples/config.env) for the format.
123
179
124
-
## Requirements
125
-
126
-
-**OS:** Debian 11+ or Ubuntu 20.04+
127
-
-**Access:** Root (via `sudo`)
128
-
-**Network:** Outbound internet access (for package installs)
180
+
---
129
181
130
182
## Lockout Protection
131
183
132
-
The SSH module includes multiple safeguards:
184
+
The SSH module includes multiple safeguards to prevent you from losing access:
133
185
134
186
1. Validates `sshd` config syntax before restarting
135
187
2. Verifies SSH keys exist in `authorized_keys`
136
188
3. Checks `AllowUsers` includes the target user
137
189
4. Confirms UFW has an SSH allow rule
138
190
5. Rolls back config automatically if any check fails
139
191
192
+
If something goes wrong, your current SSH session stays alive and the config is reverted.
193
+
194
+
---
195
+
196
+
## Compatibility
197
+
198
+
| OS | Version | Status |
199
+
|----|---------|--------|
200
+
| Ubuntu | 24.04 LTS | Tested |
201
+
| Ubuntu | 22.04 LTS | Tested |
202
+
| Ubuntu | 20.04 LTS | Tested |
203
+
| Debian | 12 (Bookworm) | Supported |
204
+
| Debian | 11 (Bullseye) | Supported |
205
+
206
+
**Architecture:** amd64, arm64
207
+
208
+
**Requirements:** Root access (via `sudo`), outbound internet for package installs.
0 commit comments