nigig-org/nimanyatta/deploy/README.md
andodeki fd8b0632ca
Some checks failed
repo hygiene / hygiene (push) Has been cancelled
Include nimanyatta as normal tree (not embedded git)
2026-09-26 09:29:36 +03:00

91 lines
3.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Deployment security workflow
A fresh VPS with a public IP is attacked within hours. This workflow hardens the
server **before** the app is deployed, and re-verifies the state on every deploy.
## The two phases
### 1. One-time hardening (on the fresh VPS)
```bash
# From your machine, immediately after first login as root:
ssh root@<vps-ip> 'bash -s' < deploy/hardening.sh
```
The script refuses to run twice, and performs, in order:
| Step | What it does |
|------|--------------|
| 1 | Updates system packages, installs `ufw`, `fail2ban`, `unattended-upgrades` |
| 2 | Creates a non-root `deploy` user with sudo privileges |
| 3 | Copies your root SSH key to the `deploy` user |
| 4 | Rewrites `sshd_config`: no root login, no password auth, `AllowUsers deploy`, MaxAuthTries 4, keeps your SSH port |
| 5 | Validates and reloads `sshd` (does not drop your session) |
| 6 | UFW: deny all incoming except SSH + app ports (default `8080`) |
| 7 | fail2ban: bans 5 failed attempts within 10 min for 1 hour |
| 8 | Enables unattended security upgrades |
> **Critical:** after the script prints its summary, open a **new terminal** and test
> `ssh -p 22 deploy@<vps-ip>` **before closing the root session**. Only after that
> login works should you deploy the app.
### 2. Verify on every deploy (CI + manual)
#### Automated (GitHub Actions)
`.github/workflows/predeploy-security.yml` runs on every push to `main` / PR and blocks
deploy if any job fails:
- **gitleaks** – scans for leaked secrets in the repo
- **shellcheck** – lints both deploy scripts
- **cargo audit** – checks dependencies for known vulnerabilities
- **release build** – confirms `broadcast_server` builds with `--features b_server`
- **hardening verify** – syntax-checks and smoke-runs the verification script
#### Manual (on the active VPS, any time)
```bash
# Audits the live server state; exit 0 = hardened, non-zero = something reverted.
sudo bash deploy/verify-hardening.sh
```
It prints `[PASS]`/`[FAIL]` per check, plus the last 10 unique brute-force usernames
from `/var/log/auth.log`.
## Configuration
Both scripts honour environment variables:
```bash
DEPLOY_USER=deploy # the sudo user to create / check
APP_PORTS="8080" # extra firewall ports (space-separated)
SSH_PORT=22 # your SSH port
```
Example with custom values:
```bash
SSH_PORT=2222 APP_PORTS="8080 9090" ssh root@<vps-ip> 'bash -s' < deploy/hardening.sh
```
## Monitoring (the step you already started)
```bash
# Tail for brute-force attempts
sudo tail -f /var/log/auth.log | grep -E 'Failed|Invalid user'
# Watch fail2ban bans
sudo fail2ban-client status sshd
# Blocklist grows here as attackers get banned
sudo cat /etc/fail2ban/jail.local
```
## Order of operations for a new deploy
1. Provision VPS → get public IP.
2. `ssh root@<ip> 'bash -s' < deploy/hardening.sh` (hardening first, **before** the app).
3. In a new terminal: `ssh deploy@<ip>` → confirm it works, then close root session.
4. Deploy the app binary.
5. `sudo bash deploy/verify-hardening.sh` → confirm all `[PASS]`.
6. Push code → CI re-runs pre-deploy checks automatically.