Skip to content

Commit 60f7783

Browse files
committed
doc: Add Ubuntu 24.04 server hardening guide
Add interactive hardening script with 8 stages: - Stage 0: HTTPS APT sources (for networks blocking HTTP) - Stage 1-3: Base system, SSH hardening, auto-updates - Stage 4: CrowdSec + UFW firewall (optional for private networks) - Stage 5-6: Core tools, Docker, devops user setup - Stage 7: Caddy web server (optional, skip for STATBUS) Link from DEPLOYMENT.md with STATBUS-specific guidance on which stages to skip based on deployment environment.
1 parent 51de252 commit 60f7783

File tree

3 files changed

+1228
-0
lines changed

3 files changed

+1228
-0
lines changed

doc/DEPLOYMENT.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,31 @@ crystal --version
134134
shards --version
135135
```
136136

137+
### Server Hardening (Recommended)
138+
139+
Before installing StatBus on a production server, we recommend hardening the Ubuntu installation:
140+
141+
```bash
142+
curl -fsSL https://raw.githubusercontent.com/statisticsnorway/statbus/main/doc/harden-ubuntu-lts-24.sh -o harden.sh
143+
chmod +x harden.sh
144+
sudo ./harden.sh
145+
```
146+
147+
This interactive script configures:
148+
- HTTPS APT sources (optional, for networks that block HTTP)
149+
- SSH key-only authentication (no passwords)
150+
- Automatic security updates
151+
- CrowdSec intrusion detection and UFW firewall (optional for private networks)
152+
- Docker and essential tools
153+
- `devops` user with GitHub SSH keys
154+
155+
**For STATBUS deployments:**
156+
- **Run Stage 0** if your network blocks HTTP (switches APT to HTTPS mirror)
157+
- **Skip Stage 4** if your server is on a private network with existing firewall infrastructure
158+
- **Skip Stage 7** (Caddy) — StatBus runs Caddy inside Docker
159+
160+
See [Server Hardening Guide](harden-ubuntu-lts-24.md) for full details.
161+
137162
### Installation Steps
138163

139164
#### 1. Clone Repository

doc/harden-ubuntu-lts-24.md

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# harden-ubuntu-lts-24.sh
2+
3+
Ubuntu 24.04 LTS server hardening script with interactive stage-by-stage execution.
4+
5+
## Quick Start
6+
7+
```bash
8+
# Download
9+
curl -fsSL https://raw.githubusercontent.com/statisticsnorway/statbus/main/doc/harden-ubuntu-lts-24.sh -o harden.sh
10+
chmod +x harden.sh
11+
12+
# Run (will prompt for configuration, then each stage)
13+
sudo ./harden.sh
14+
```
15+
16+
## Features
17+
18+
- **Interactive**: Prompts Yes/No before each stage - safe to run from uncomfortable consoles
19+
- **Verification**: Automatic checks after each stage with pass/fail indicators
20+
- **Configurable**: Settings stored in `~/.harden-ubuntu.env`
21+
- **Non-interactive mode**: `--non-interactive` flag for automation
22+
23+
## Stages
24+
25+
| # | Stage | What it does |
26+
|---|-------|--------------|
27+
| 0 | HTTPS APT Sources *(optional)* | Switch to HTTPS mirror for networks that block HTTP |
28+
| 1 | Base System | etckeeper, eternal bash history, locale configuration |
29+
| 2 | SSH Hardening | Disable password auth, root password login, empty passwords |
30+
| 3 | Auto Updates | unattended-upgrades with nightly schedule, email notifications |
31+
| 4 | Security Tools *(optional)* | CrowdSec IDS + firewall bouncer, UFW firewall |
32+
| 5 | Core Tools | neovim, htop, ripgrep, Docker CE + compose |
33+
| 6 | User Setup | devops user, GitHub SSH keys, Homebrew, helix/bottom/zellij |
34+
| 7 | Caddy *(optional)* | Caddy web server with optional plugin support via xcaddy |
35+
36+
## Configuration
37+
38+
On first run, you'll be prompted for:
39+
40+
| Variable | Description |
41+
|----------|-------------|
42+
| `ADMIN_EMAIL` | Email for unattended-upgrades notifications |
43+
| `GITHUB_USERS` | Space-separated GitHub usernames for SSH key fetching |
44+
| `EXTRA_LOCALES` | Extra locales to enable (e.g., `nb_NO fr_FR`) |
45+
| `CADDY_PLUGINS` | Caddy plugins for custom build (empty = standard Caddy) |
46+
47+
Configuration is saved to `~/.harden-ubuntu.env` and reused on subsequent runs.
48+
49+
### Caddy Plugin Options
50+
51+
When prompted, select by number or enter custom plugin paths:
52+
53+
1. `github.com/mholt/caddy-l4` - Layer 4 (TCP/UDP) proxying
54+
2. `github.com/caddy-dns/cloudflare` - Cloudflare DNS for ACME
55+
3. `github.com/caddy-dns/namedotcom` - Name.com DNS for ACME
56+
4. `github.com/caddy-dns/route53` - AWS Route53 DNS for ACME
57+
5. `github.com/caddy-dns/digitalocean` - DigitalOcean DNS for ACME
58+
6. `github.com/greenpau/caddy-security` - Authentication/Authorization
59+
60+
## Non-Interactive Mode
61+
62+
For automation, create the `.env` file first:
63+
64+
```bash
65+
cat > ~/.harden-ubuntu.env << 'EOF'
66+
ADMIN_EMAIL="admin@example.com"
67+
GITHUB_USERS="githubuser1 githubuser2"
68+
EXTRA_LOCALES="nb_NO fr_FR"
69+
CADDY_PLUGINS=""
70+
EOF
71+
72+
sudo ./harden.sh --non-interactive
73+
```
74+
75+
## Post-Installation
76+
77+
After running:
78+
79+
1. **Test SSH access** as `devops` user before closing console session
80+
2. **Configure Caddy** at `/etc/caddy/Caddyfile`
81+
3. **Review CrowdSec**: `cscli metrics`, `cscli decisions list`
82+
4. **Check firewall**: `ufw status`
83+
84+
## What Gets Hardened
85+
86+
### APT Sources (Stage 0)
87+
- Switches from HTTP to HTTPS mirror (`mirrors.edge.kernel.org`)
88+
- Required for networks that block unencrypted HTTP traffic
89+
90+
> **Note**: Skip Stage 0 if your network allows HTTP or you prefer a different mirror.
91+
92+
### SSH (`/etc/ssh/sshd_config.d/hardening.conf`)
93+
- Root login: key-only (no password)
94+
- Password authentication: disabled
95+
- Empty passwords: disabled
96+
- Keyboard-interactive auth: disabled
97+
98+
### Firewall (UFW)
99+
- Default: deny incoming, allow outgoing
100+
- Allowed: SSH (22), HTTP (80), HTTPS (443), PostgreSQL (5432)
101+
102+
> **Note**: Skip Stage 4 if your server is on a private network with existing firewall infrastructure.
103+
104+
### Intrusion Detection (CrowdSec)
105+
- SSH brute-force protection
106+
- Caddy log analysis (prepared)
107+
- nftables firewall bouncer for automatic IP banning
108+
109+
### Memory Tuning (`/etc/sysctl.d/20-server-tuning.conf`)
110+
- `vm.swappiness=1` - Minimize swapping for server workloads
111+
- Dirty page limits tuned for predictable I/O
112+
113+
## Requirements
114+
115+
- Ubuntu 24.04 LTS
116+
- Root/sudo access
117+
- Internet connection (for package downloads)
118+
119+
## STATBUS Integration
120+
121+
When using this script to prepare a server for STATBUS deployment:
122+
123+
1. **Stage 0 (HTTPS Sources)** — Run if your network blocks HTTP traffic
124+
2. **Run Stages 1-3, 5-6** — Essential hardening and tools
125+
3. **Stage 4 (Security Tools)** — Skip if on a private network with existing firewall
126+
4. **Stage 7 (Caddy)** — Skip, as STATBUS runs Caddy inside Docker
127+
128+
After hardening, continue with the [STATBUS Deployment Guide](DEPLOYMENT.md).
129+
130+
## License
131+
132+
MIT

0 commit comments

Comments
 (0)